Compare commits

..

41 Commits

Author SHA1 Message Date
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
1184 changed files with 32430 additions and 16493 deletions

View File

@@ -1,12 +1,22 @@
# server 模块
Java 21
Spring Boot 3.3.7
Spring Data JPA 3.3.7
JavaFX 21
ControlsFX 11.1.2
MySQL 8.0.33
Lombok 1.18.32
POI 5.2.5
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:
- .idea

View File

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

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;
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;
package com.ecep.contract;
import java.io.File;
import java.io.FileInputStream;
@@ -29,8 +6,42 @@ import java.io.IOException;
import java.net.URL;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.*;
import java.util.logging.Level;
import java.util.concurrent.CompletableFuture;
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 应用程序
@@ -58,9 +69,11 @@ public class Desktop extends Application {
private ScheduledExecutorService scheduledExecutorService = null;
private final TaskMonitorCenter taskMonitorCenter = new TaskMonitorCenter();
private final SimpleIntegerProperty sessionId = new SimpleIntegerProperty(0);
private final SimpleStringProperty sessionId = new SimpleStringProperty("");
@Getter
private final CurrentEmployee activeEmployee = new CurrentEmployee();
@Getter
private OkHttpClient httpClient;
public void setActiveEmployeeId(int activeEmployeeId) {
activeEmployee.getId().set(activeEmployeeId);
@@ -70,11 +83,11 @@ public class Desktop extends Application {
return activeEmployee.getId().get();
}
public int getSessionId() {
public String getSessionId() {
return sessionId.get();
}
public void setSessionId(int sessionId) {
public void setSessionId(String 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) {
System.out.println("Desktop.startSpringApp");
logger.debug("startSpringApp");
// 更新窗口标题
Node titleNode = root.lookup("#title");
if (titleNode != null) {
@@ -138,34 +155,26 @@ public class Desktop extends Application {
ScrollPane logPane = (ScrollPane) root.lookup("#logPane");
logBox.getChildren().clear();
MessageHolder holder = (level, message) -> {
Text text = new Text(message);
if (Level.WARNING == level) { // warning
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);
TextMessageHolder holder = new TextMessageHolder() {
@Override
public void addTextMessage(Text text) {
Platform.runLater(() -> {
logBox.getChildren().add(text);
logPane.layout();
logPane.setVvalue(1.0);
});
}
Platform.runLater(() -> {
logBox.getChildren().add(text);
logPane.layout();
logPane.setVvalue(1.0);
});
};
holder.info("启动中,请稍后...");
CompletableFuture.runAsync(() -> {
runAsync(() -> {
try {
//
holder.info("读取配置文件...");
Properties properties = new Properties();
File configFile = new File("config.properties");
if (configFile.exists()) {
holder.debug("读取配置文件 " + configFile.getName() + "...");
holder.info("读取配置文件 " + configFile.getAbsolutePath() + "...");
try (FileInputStream input = new FileInputStream(configFile)) {
properties.load(input);
holder.info("配置文件读取成功.");
@@ -174,9 +183,12 @@ public class Desktop extends Application {
logger.error(e.getMessage(), e);
return;
}
} else {
logger.warn("配置文件{}不存在", configFile.getAbsolutePath());
}
HibernateProxyUtils.useProxy(false);
CompletableFuture.runAsync(() -> {
runAsync(() -> {
SpringApp.launch(properties, holder);
ConfigurableListableBeanFactory beanFactory = SpringApp.context.getBeanFactory();
@@ -185,16 +197,35 @@ public class Desktop extends Application {
});
try {
LoginWidowController controller = new LoginWidowController();
initHttpClient();
OkHttpLoginController controller = new OkHttpLoginController();
controller.setHttpClient(this.httpClient);
controller.setHolder(holder);
controller.setPrimaryStage(primaryStage);
controller.setProperties(properties);
while (true) {
controller.tryLogin();
break;
}
if (logger.isDebugEnabled()) {
logger.debug("login in");
try {
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);
}
}
} catch (Exception e) {
holder.error("登录失败:" + e.getMessage());
@@ -206,6 +237,27 @@ public class Desktop extends Application {
}
});
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
@@ -253,5 +305,4 @@ public class Desktop extends Application {
}
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.IOException;
@@ -6,8 +6,6 @@ import java.util.function.Consumer;
import org.springframework.util.StringUtils;
import com.ecep.contract.manager.Desktop;
public class DesktopUtils {
/**

View File

@@ -1,4 +1,4 @@
package com.ecep.contract.manager;
package com.ecep.contract;
import lombok.Getter;
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.Instant;
@@ -25,7 +25,6 @@ import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.event.ContextClosedEvent;
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.EnableScheduling;
import com.ecep.contract.manager.cloud.CloudRepositoriesConfig;
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.ecep.contract.util.UITools;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
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.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
@EnableAsync
@EnableCaching
public class SpringApp {
private static final Logger logger = LoggerFactory.getLogger(SpringApp.class);
static SpringApplication application;
static ConfigurableApplicationContext context;
public static SpringApplication application;
public static ConfigurableApplicationContext context;
public static <T> T getBean(Class<T> requiredType) throws BeansException {
return context.getBean(requiredType);
@@ -92,11 +92,6 @@ public class SpringApp {
environment.getPropertySources().addLast(new PropertiesPropertySource("dynamicProperties", properties));
// app.getBeanFactory().registerSingleton("dataSource", dataSource());
logger.debug("app = {}", app);
if (app instanceof AnnotationConfigApplicationContext ctx) {
ctx.register(DsRepositoriesConfig.class);
ctx.register(CloudRepositoriesConfig.class);
}
});
startup.start("");
@@ -108,7 +103,7 @@ public class SpringApp {
CompletableFuture.runAsync(() -> {
// 在这里调用 startup 性能分析
analyzeStartupPerformance(startup);
});
}, Desktop.instance.getExecutorService());
}
/**
@@ -242,14 +237,18 @@ public class SpringApp {
public ObjectMapper objectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
JavaTimeModule javaTimeModule = new JavaTimeModule();
// LocalDate
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(LocalDateTime.class, new LocalDateTimeDeserializer(
DateTimeFormatter.ofPattern(MyDateTimeUtils.DEFAULT_DATETIME_FORMAT_PATTERN)));
// LocalTime
javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(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);
return objectMapper;
}

View File

@@ -0,0 +1,342 @@
package com.ecep.contract;
import com.ecep.contract.constant.WebSocketConstant;
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.*;
import okio.ByteString;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
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;
/**
* 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);
}
} else 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());
}
}
} else 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();
// TODO 需要重新登录
logger.error("收到错误消息: 错误码={}, 错误信息={}", errorCode, errorMsg);
}
} 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 com.ecep.contract.manager.ds.other.vo.IdentityViewModel;
import org.apache.poi.ss.formula.functions.T;
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.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.beans.binding.Bindings;
import javafx.beans.binding.BooleanBinding;
@@ -18,12 +28,6 @@ import javafx.stage.WindowEvent;
import lombok.Getter;
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>>
extends BaseController {
@@ -43,24 +47,38 @@ public abstract class AbstEntityController<T extends IdentityEntity, TV extends
@Override
public void onShown(WindowEvent windowEvent) {
Class<?> aClass = getClass();
super.onShown(windowEvent);
loadedFuture = CompletableFuture.supplyAsync(() -> {
T entity = loadEntity();
if (entity == null) {
ViewModelService<T, TV> service = getViewModelService();
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
if (viewModel != null) {
viewModel.bindListener();
}
return null;
}
Platform.runLater(() -> {
setStatus();
viewModel.update(entity);
// BaseViewModel.updateInFxApplicationThread(entity, viewModel);
});
viewModel.bindListener();
return entity;
});
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;
}
Platform.runLater(() -> {
setStatus();
viewModel.update(entity);
});
viewModel.bindListener();
return entity;
});
}
registerTabSkins();
if (saveBtn != null) {
@@ -71,10 +89,6 @@ public abstract class AbstEntityController<T extends IdentityEntity, TV extends
installTabSkins();
}
protected T loadEntity() {
return getViewModelService().findById(viewModel.getId().get());
}
public T getEntity() {
return getLoadedFuture().join();
}
@@ -190,35 +204,42 @@ public abstract class AbstEntityController<T extends IdentityEntity, TV extends
public CompletableFuture<Void> refresh() {
CompletableFuture<Void> future = new CompletableFuture<>();
T entity = loadEntity();
Platform.runLater(() -> {
ViewModelService<T, TV> service = getViewModelService();
if (service instanceof QueryService<T, TV> queryService) {
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);
}
List<RefreshableSkin> list = tabSkins.stream()
.filter(v -> v instanceof RefreshableSkin)
.map(v -> ((RefreshableSkin) v)).toList();
List<RefreshableSkin> list = tabSkins.stream()
.filter(v -> v instanceof RefreshableSkin)
.map(v -> ((RefreshableSkin) v)).toList();
if (list.isEmpty()) {
future.complete(null);
return;
}
if (list.isEmpty()) {
future.complete(null);
return future;
}
CompletableFuture.allOf(list
.stream()
.map(RefreshableSkin::refresh)
.filter(Objects::nonNull)
.toArray(CompletableFuture<?>[]::new))
.whenComplete((v, ex) -> {
if (ex != null) {
future.completeExceptionally(ex);
} else {
future.complete(null);
}
});
});
return future;
return CompletableFuture.allOf(list
.stream()
.map(RefreshableSkin::refresh)
.filter(Objects::nonNull)
.toArray(CompletableFuture<?>[]::new))
.whenComplete((v, ex) -> {
if (ex != null) {
future.completeExceptionally(ex);
} else {
future.complete(null);
}
});
}
public abstract ViewModelService<T, TV> getViewModelService();

View File

@@ -1,27 +1,30 @@
package com.ecep.contract.manager.ui;
package com.ecep.contract.controller;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import com.ecep.contract.manager.ui.table.EditableEntityTableTabSkin;
import com.ecep.contract.manager.ui.table.TableTabSkin;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
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.manager.ds.other.vo.IdentityViewModel;
import com.ecep.contract.manager.util.TableViewUtils;
import com.ecep.contract.manager.util.UITools;
import com.ecep.contract.controller.table.EditableEntityTableTabSkin;
import com.ecep.contract.controller.table.TableTabSkin;
import com.ecep.contract.model.IdentityEntity;
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.beans.property.Property;
@@ -43,12 +46,15 @@ import javafx.scene.input.KeyEvent;
import javafx.util.converter.NumberStringConverter;
/**
* 实体管理器皮肤
* 提供了实体管理器的基本功能如查询新增删除修改分页等
*
* @param <T> Entity 的类型
* @param <TV> Entity 对应的ViewModel
* @param <Skin> Skin 的类型
* @param <SKIN> Skin 的类型
* @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> {
private static final Logger logger = LoggerFactory.getLogger(AbstEntityManagerSkin.class);
/**
@@ -61,11 +67,20 @@ public abstract class AbstEntityManagerSkin<T extends IdentityEntity, TV extends
protected PageRequest currentPageable = PageRequest.ofSize(25);
protected final SimpleIntegerProperty currentPageNumber = new SimpleIntegerProperty();
// 是否允许调整表格高度
private boolean allowResize = true;
// 记录延时任务信息
private ScheduledFuture<?> loadTableDataSetFuture;
public AbstEntityManagerSkin(C controller) {
this.controller = controller;
}
@Override
public <TT> TT getBean(Class<TT> requiredType) throws BeansException {
return controller.getCachedBean(requiredType);
}
@Override
public TableView<TV> getTableView() {
return controller.table;
@@ -199,6 +214,9 @@ public abstract class AbstEntityManagerSkin<T extends IdentityEntity, TV extends
* 根据表格高度重新计算分页的页大小
*/
private void resizeTable(Object observable, Bounds old, Bounds newBounds) {
if (!allowResize) {
return;
}
double tableHeight = newBounds.getHeight();
if (tableHeight <= 0) {
return;
@@ -208,8 +226,13 @@ public abstract class AbstEntityManagerSkin<T extends IdentityEntity, TV extends
if (lookup != null) {
double rowHeight = lookup.prefHeight(-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) {
return;
}
@@ -259,9 +282,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();
Property<K> property = function.apply(row);
Property<K> property = propGetter.apply(row);
property.setValue(event.getNewValue());
try {
saveRowData(row);
@@ -317,21 +348,47 @@ public abstract class AbstEntityManagerSkin<T extends IdentityEntity, TV extends
row.saveInFxApplicationThread(service);
}
/**
* 加载行数据
*
* @param row
* @return
*/
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) {
if (entity == null) {
return;
}
ViewModelService<T, TV> service = getViewModelService();
getViewModelService().delete(entity);
}
/**
* 保存行数据
*
* @param entity
* @return
*/
public T saveRowData(T entity) {
if (entity == null) {
return null;
}
ViewModelService<T, TV> service = getViewModelService();
return getViewModelService().save(entity);
}
// 记录延时任务信息
private ScheduledFuture<?> loadTableDataSetFuture;
@Override
public void loadTableDataSet() {
loadTableDataSet(false);
@@ -359,18 +416,18 @@ public abstract class AbstEntityManagerSkin<T extends IdentityEntity, TV extends
private CompletableFuture<Void> _reloadTableData() {
CompletableFuture<Void> future = new CompletableFuture<>();
Platform.runLater(() -> {
allowResize = false; // 禁用调整
dataSet.clear();
runAsync(() -> {
controller.setStatus("载入中...");
// 异步加载数据
if (getViewModelService() instanceof QueryService<T, TV> queryService) {
asyncLoadTableData(queryService, future);
return;
}
// 同步加载方法
List<TV> models = loadTableData();
Platform.runLater(() -> {
try {
updateTableDataSet(models);
future.complete(null);
} catch (Exception e) {
future.completeExceptionally(e);
}
});
_updateModels(models, future);
}).exceptionally(ex -> {
future.completeExceptionally(ex);
return null;
@@ -379,20 +436,60 @@ public abstract class AbstEntityManagerSkin<T extends IdentityEntity, TV extends
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) {
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;
if (logger.isDebugEnabled()) {
logger.debug("update table dataSet cost: {} ms", timeCost);
}
}
/**
* 加载表格数据
*
* @return
*/
protected List<TV> loadTableData() {
Specification<T> spec = getSpecification();
Map<String, Object> params = getSpecification();
ViewModelService<T, TV> service = getViewModelService();
long timeMillis = System.currentTimeMillis();
Page<T> page = service.findAll(spec, getPageable());
Page<T> page = service.findAll(params, getPageable());
long timeCost = System.currentTimeMillis() - timeMillis;
if (logger.isDebugEnabled()) {
logger.debug("load table data cost: {} ms", timeCost);
@@ -404,17 +501,44 @@ public abstract class AbstEntityManagerSkin<T extends IdentityEntity, TV extends
return page.map(service::from).toList();
}
/**
* 异步加载表格数据
*
* @param queryService
* @param future
*/
private void asyncLoadTableData(QueryService<T, TV> queryService, CompletableFuture<Void> future) {
queryService.asyncFindAll(getSpecification(), 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() {
ViewModelService<T, TV> service = controller.getViewModelService();
if (service == null) {
if (logger.isWarnEnabled()) {
logger.warn("ViewModelService is null");
}
throw new IllegalArgumentException("ViewModelService is null");
}
return service;
}
public Specification<T> getSpecification() {
/**
* 获取查询条件
*
* @return
*/
public Map<String, Object> getSpecification() {
TextField field = controller.searchKeyField;
if (field != null) {
return getViewModelService().getSpecification(field.getText());
@@ -422,8 +546,14 @@ public abstract class AbstEntityManagerSkin<T extends IdentityEntity, TV extends
return null;
}
protected Specification<T> getSpecification(String searchText) {
return controller.getViewModelService().getSpecification(searchText);
/**
* 获取查询条件
*
* @param searchText
* @return
*/
protected Map<String, Object> getSpecification(String searchText) {
return getViewModelService().getSpecification(searchText);
}
/**
@@ -434,6 +564,11 @@ public abstract class AbstEntityManagerSkin<T extends IdentityEntity, TV extends
protected void onTableRowDoubleClickedAction(TV item) {
}
/**
* 更新页脚
*
* @param page
*/
protected void updateFooter(Page<T> page) {
Platform.runLater(() -> {
controller.previousPageBtn.setDisable(!page.hasPrevious());
@@ -444,19 +579,44 @@ public abstract class AbstEntityManagerSkin<T extends IdentityEntity, TV extends
});
}
/**
* 获取表格排序
*
* @return
*/
public List<Sort.Order> getTableOrders() {
return TableViewUtils.getOrders(getTableView());
}
/**
* 获取表格排序
*
* @return
*/
public Sort getSortByTable() {
if (getTableView() == null) {
return Sort.unsorted();
}
return Sort.by(getTableOrders());
}
/**
* 获取分页参数
*
* @return
*/
public Pageable getPageable() {
Sort sort = getSortByTable();
return currentPageable.withSort(sort);
}
/**
* 显示在当前窗口为父窗口的新窗口
*
* @param <Controller> 控制器类型
* @param clz 控制器类
* @param model 数据
*/
protected <Controller extends AbstEntityController<T, TV>> void showInOwner(Class<Controller> clz, TV model) {
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.manager.ds.other.vo.IdentityViewModel;
import com.ecep.contract.model.IdentityEntity;
import com.ecep.contract.vm.IdentityViewModel;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
@@ -41,6 +41,4 @@ public abstract class AbstManagerWindowController<T extends IdentityEntity, TV e
}
}

View File

@@ -1,14 +1,32 @@
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 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.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
@@ -21,21 +39,6 @@ import javafx.stage.Stage;
import javafx.stage.Window;
import javafx.stage.WindowEvent;
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 {
private static final Logger logger = LoggerFactory.getLogger(BaseController.class);
@@ -45,7 +48,8 @@ public class BaseController {
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();
if (toFront(key)) {
return null;
@@ -63,10 +67,10 @@ public class BaseController {
controller.show(loader, owner, Modality.NONE, key);
});
}
@SuppressWarnings("unchecked")
public static <K extends IdentityEntity, M extends IdentityViewModel<K>, T extends BaseController>
void show(Class<T> clz, M viewModel, Window owner) {
public static <K extends IdentityEntity, M extends IdentityViewModel<K>, T extends BaseController> void show(
Class<T> clz, M viewModel, Window owner) {
String key = getKey(clz, viewModel);
if (toFront(key)) {
return;
@@ -76,7 +80,6 @@ public class BaseController {
throw new RuntimeException("@FxmlPath is required");
}
FxmlUtils.newLoaderAsyncWithRunLater(annotation.value(), null, loader -> {
T controller = loader.getController();
if (controller instanceof AbstEntityController<?, ?>) {
@@ -114,7 +117,6 @@ public class BaseController {
});
}
public static boolean toFront(String key) {
Stage stage = stages.get(key);
if (stage != null) {
@@ -161,6 +163,11 @@ public class BaseController {
return future;
}
public CompletableFuture<Void> runAsync(Runnable runnable) {
return CompletableFuture.runAsync(runnable, Desktop.instance.getExecutorService())
.exceptionally(this::handleException);
}
/**
* 窗口标题
*/
@@ -177,33 +184,30 @@ public class BaseController {
private String stageKey;
public Label leftStatusLabel;
public Label rightStatusLabel;
@Getter
@Setter
private Locale locale = Locale.getDefault();
@Setter
private SysConfService confService;
@Setter
private EmployeeService employeeService;
private Employee currentUser;
protected <T> T getBean(Class<T> requiredType) throws BeansException {
private HashMap<Class<?>, Object> cachedBeans = new HashMap<>();
public <T> T getBean(Class<T> requiredType) throws BeansException {
return SpringApp.getBean(requiredType);
}
public SysConfService getConfService() {
if (confService == null) {
confService = getBean(SysConfService.class);
@SuppressWarnings("unchecked")
public <T> T getCachedBean(Class<T> requiredType) throws BeansException {
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() {
if (employeeService == null) {
employeeService = getBean(EmployeeService.class);
}
return employeeService;
return getCachedBean(EmployeeService.class);
}
public Employee getCurrentUser() {
@@ -213,6 +217,18 @@ public class BaseController {
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) {
return SpringApp.getMessage(code, args, getLocale());
}

View File

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

View File

@@ -0,0 +1,98 @@
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.model.CloudRk;
import com.ecep.contract.model.Company;
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 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<CloudRk, 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;
public TableColumn<CloudRkViewModel, Company> 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,23 @@
package com.ecep.contract.manager.cloud.tyc;
package com.ecep.contract.controller;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.hibernate.Hibernate;
import com.ecep.contract.util.ProxyUtils;
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 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.model.CloudTyc;
import com.ecep.contract.model.Company;
import com.ecep.contract.service.CloudTycService;
import com.ecep.contract.service.CompanyService;
import com.ecep.contract.vm.CloudTycInfoViewModel;
import jakarta.persistence.criteria.Path;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.scene.control.ContextMenu;
@@ -49,31 +51,6 @@ public class CloudTycManagerSkin
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
public void initializeTable() {
controller.idColumn.setCellValueFactory(param -> param.getValue().getId());
@@ -126,7 +103,7 @@ public class CloudTycManagerSkin
@Override
protected void onTableRowDoubleClickedAction(CloudTycInfoViewModel item) {
Company company = item.getCompany().get();
if (!Hibernate.isInitialized(item)) {
if (!ProxyUtils.isInitialized(company)) {
company = getCompanyService().findById(company.getId());
}
CompanyWindowController.show(company, getTableView().getScene().getWindow());

View File

@@ -0,0 +1,73 @@
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.model.CloudTyc;
import com.ecep.contract.model.Company;
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 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<CloudTyc, 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;
@FXML
public TableColumn<CloudTycInfoViewModel, Company> 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,19 @@
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.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.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ListCell;
import org.springframework.util.StringUtils;
import java.util.List;
public class ComboBoxUtils {
@@ -19,7 +21,7 @@ public class ComboBoxUtils {
if (t == null) {
return "全部";
}
if (t instanceof Entity e) {
if (t instanceof BasedEntity e) {
return e.toPrettyString();
}
if (t instanceof BaseEnumEntity<?> e) {
@@ -44,7 +46,7 @@ public class ComboBoxUtils {
if (t == null) {
continue;
}
if (t instanceof Entity e) {
if (t instanceof BasedEntity e) {
if (e.toPrettyString().equals(string)) {
return t;
}

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

View File

@@ -1,39 +1,51 @@
package com.ecep.contract.manager.ds.other.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;
package com.ecep.contract.controller;
import java.io.FileOutputStream;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
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.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.ExecutionException;
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 {
private static final Logger logger = LoggerFactory.getLogger(LoginWidowController.class);
@@ -60,27 +72,11 @@ public class LoginWidowController implements MessageHolder {
}
String getHost() {
return properties.getProperty("db.server.host", DEFAULT_DB_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);
return properties.getProperty("server.host");
}
public void tryLogin() {
// CompletableFuture<ButtonType> future = new CompletableFuture<>();
// CompletableFuture<ButtonType> future = new CompletableFuture<>();
// 检查配置文件中是否保存用户名和密码
String userName = getUserName();
if (StringUtils.hasText(userName)) {
@@ -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() {
return CompletableFuture.supplyAsync(() -> {
@@ -123,7 +128,8 @@ public class LoginWidowController implements MessageHolder {
// -分割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 ? "-" : ""));
sb.append(
String.format("%02X%s", hardwareAddress[i], i < hardwareAddress.length - 1 ? "-" : ""));
}
while (inetAddresses.hasMoreElements()) {
@@ -146,40 +152,20 @@ public class LoginWidowController implements MessageHolder {
String database = getDatabase();
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()
.type(HikariDataSource.class)
.url("jdbc:mysql://" + host + ":" + port + "/" + database)
.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 getDatabase() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'getDatabase'");
}
private String getPort() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'getPort'");
}
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<>();
macAndIP.thenAccept(macIPS -> {
if (macIPS.isEmpty()) {
@@ -409,8 +396,7 @@ public class LoginWidowController implements MessageHolder {
} catch (SQLException e) {
throw new RuntimeException(
String.format("查询本机绑定信息异常请联系管理员或重启应用MAC: %s, IP: %s", macIP.mac, macIP.ip),
e
);
e);
}
return list;
}
@@ -429,7 +415,7 @@ public class LoginWidowController implements MessageHolder {
grid.setHgap(10);
grid.setVgap(10);
// 为整个 GridPane 设置外边距
//GridPane.setMargin(grid, new Insets(10));
// GridPane.setMargin(grid, new Insets(10));
// 账户输入框
Label userLabel = new Label("账户:");
@@ -479,14 +465,12 @@ public class LoginWidowController implements MessageHolder {
borderPane.setCenter(grid);
// 登录按钮
Button loginButton = new Button("登录");
loginButton.setDefaultButton(true);
borderPane.setBottom(loginButton);
BorderPane.setAlignment(loginButton, javafx.geometry.Pos.CENTER);
// 登录按钮点击事件
loginButton.setOnAction(event -> {
String username = userField.getText();
@@ -526,23 +510,21 @@ public class LoginWidowController implements MessageHolder {
stage.close();
});
// 创建场景并设置到窗口
Scene scene = new Scene(borderPane, 400, 260);
stage.setScene(scene);
// stage.setAlwaysOnTop(true);
// stage.setAlwaysOnTop(true);
stage.setResizable(false);
stage.showAndWait();
}
private void logined(EmployeeInfo employeeInfo) {
info("欢迎 " + employeeInfo.name.get());
if (!SpringApp.isRunning()) {
info("请稍后...");
}
Desktop.instance.setActiveEmployeeId(employeeInfo.employeeId);
Desktop.instance.setSessionId(employeeInfo.sessionId);
// Desktop.instance.setSessionId(employeeInfo.sessionId);
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 {

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 com.ecep.contract.util.FxmlPath;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import com.ecep.contract.manager.Desktop;
import com.ecep.contract.manager.ui.BaseController;
import com.ecep.contract.manager.ui.FxmlPath;
import com.ecep.contract.manager.ui.Message;
import com.ecep.contract.manager.util.MyDateTimeUtils;
import com.ecep.contract.Desktop;
import com.ecep.contract.Message;
import com.ecep.contract.MyDateTimeUtils;
import com.ecep.contract.task.MonitoredTask;
import com.ecep.contract.task.TaskHistory;
import com.ecep.contract.task.TaskMonitorCenter;
import javafx.beans.property.SimpleStringProperty;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
@@ -69,10 +76,47 @@ public class TaskMonitorViewController extends BaseController {
private Button cancelTaskButton;
@FXML
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() {
}
/**
* 用于存储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
public void onShown(WindowEvent windowEvent) {
super.onShown(windowEvent);
@@ -144,6 +188,94 @@ public class TaskMonitorViewController extends BaseController {
});
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信息时发生错误"));
}
}
/**
@@ -205,7 +337,7 @@ public class TaskMonitorViewController extends BaseController {
text.setFill(Color.ORANGE);
} else if (msg.getLevel() == Level.SEVERE) {
text.setFill(Color.RED);
}else if (msg.getLevel()== Level.CONFIG) {
} else if (msg.getLevel() == Level.CONFIG) {
text.setFill(Color.GRAY);
}
vBox.getChildren().add(text);
@@ -218,4 +350,11 @@ public class TaskMonitorViewController extends BaseController {
alert.getDialogPane().setContent(scrollPane);
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

@@ -1,79 +1,44 @@
package com.ecep.contract.manager.cloud.u8;
package com.ecep.contract.controller;
import java.util.List;
import java.util.Map;
import org.springframework.data.domain.Page;
import org.springframework.util.StringUtils;
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.model.CloudYu;
import com.ecep.contract.model.Company;
import com.ecep.contract.service.CompanyService;
import com.ecep.contract.service.YongYouU8Service;
import com.ecep.contract.util.ParamUtils;
import com.ecep.contract.util.ProxyUtils;
import com.ecep.contract.vm.CloudYuInfoViewModel;
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.ManagerSkin;
import com.ecep.contract.manager.ui.table.cell.LocalDateTimeTableCell;
import jakarta.persistence.criteria.Path;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import lombok.Setter;
import org.hibernate.Hibernate;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.util.StringUtils;
import java.util.List;
public class YongYouU8ManagerSkin
extends AbstEntityManagerSkin<CloudYu, CloudYuInfoViewModel, YongYouU8ManagerSkin, YongYouU8ManagerWindowController>
extends
AbstEntityManagerSkin<CloudYu, CloudYuInfoViewModel, YongYouU8ManagerSkin, YongYouU8ManagerWindowController>
implements ManagerSkin {
@Setter
private YongYouU8Service u8Service;
@Setter
private CompanyService companyService;
public YongYouU8ManagerSkin(YongYouU8ManagerWindowController controller) {
super(controller);
}
YongYouU8Service getU8Service() {
if (u8Service == null) {
u8Service = SpringApp.getBean(YongYouU8Service.class);
}
return u8Service;
return getBean(YongYouU8Service.class);
}
CompanyService getCompanyService() {
if (companyService == null) {
companyService = SpringApp.getBean(CompanyService.class);
}
return companyService;
}
@Override
protected List<CloudYuInfoViewModel> loadTableData() {
String searchText = controller.searchKeyField.getText();
Specification<CloudYu> spec = null;
if (StringUtils.hasText(searchText)) {
Specification<CloudYu> 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<CloudYu> cloudIdSpec = (root, query, builder) -> {
return builder.like(root.get("cloudId"), "%" + searchText + "%");
};
Specification<CloudYu> exceptionSpec = (root, query, builder) -> {
return builder.like(root.get("exceptionMessage"), "%" + searchText + "%");
};
spec = Specification.anyOf(companySpec, cloudIdSpec, exceptionSpec);
}
Page<CloudYu> page = getU8Service().findAll(spec, getPageable());
updateFooter(page);
return page.map(CloudYuInfoViewModel::from).toList();
return getBean(CompanyService.class);
}
@Override
@@ -116,7 +81,7 @@ public class YongYouU8ManagerSkin
}
for (CloudYuInfoViewModel selectedItem : selectedItems) {
CloudYu cloudYu = getU8Service().findById(selectedItem.getId().get());
selectedItem.getCustomerCode().set("");
selectedItem.getCustomerCode().set("");
if (selectedItem.copyTo(cloudYu)) {
CloudYu saved = getU8Service().save(cloudYu);
selectedItem.update(saved);
@@ -127,7 +92,7 @@ public class YongYouU8ManagerSkin
@Override
protected void onTableRowDoubleClickedAction(CloudYuInfoViewModel item) {
Company company = item.getCompany().get();
if (!Hibernate.isInitialized(item)) {
if (!ProxyUtils.isInitialized(item)) {
company = getCompanyService().findById(company.getId());
}
CompanyWindowController.show(company, getTableView().getScene().getWindow());

View File

@@ -0,0 +1,119 @@
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.model.CloudYu;
import com.ecep.contract.model.Company;
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 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<CloudYu, 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, Company> 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.cell.TextFieldTableCell;
public class BankManagerSkin
extends AbstEntityManagerSkin<Bank, BankViewModel, BankManagerSkin, BankManagerWindowController>
implements ManagerSkin, EditableEntityTableTabSkin<Bank, BankViewModel> {
extends AbstEntityManagerSkin<BankVo, BankViewModel, BankManagerSkin, BankManagerWindowController>
implements ManagerSkin, EditableEntityTableTabSkin<BankVo, BankViewModel> {
public BankManagerSkin(BankManagerWindowController 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.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
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
@Scope("prototype")
@Component
@FxmlPath("/ui/bank-manager.fxml")
public class BankManagerWindowController
extends AbstManagerWindowController<Bank, BankViewModel, BankManagerSkin> {
extends AbstManagerWindowController<BankVo, BankViewModel, BankManagerSkin> {
@Autowired
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.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
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
@Scope("prototype")
@Component
@FxmlPath("/ui/company/bank-account.fxml")
public class BankAccountWindowController extends AbstEntityController<CompanyBankAccount, CompanyBankAccountViewModel> {
public class BankAccountWindowController extends AbstEntityController<CompanyBankAccountVo, CompanyBankAccountViewModel> {
public BorderPane root;
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.model.Company;
import com.ecep.contract.service.CompanyService;
import com.ecep.contract.vm.CompanyViewModel;
import javafx.concurrent.Task;
public abstract class AbstCompanyBasedTabSkin
extends AbstEntityBasedTabSkin<CompanyWindowController, Company, 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,47 @@
package com.ecep.contract.controller.company;
import java.util.Map;
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 Map<String, Object> getSpecification(CompanyVo parent) {
return ParamUtils.equal("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.Optional;
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.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.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.stage.Modality;
import javafx.stage.Stage;
@@ -16,22 +35,13 @@ import javafx.stage.WindowEvent;
import javafx.util.converter.LocalDateStringConverter;
import lombok.Getter;
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
@Scope("prototype")
@Component
public class CompanyContactWindowController extends BaseController {
private static final Logger logger = LoggerFactory.getLogger(CompanyContactWindowController.class);
/**
* 显示界面
*/
@@ -59,8 +69,9 @@ public class CompanyContactWindowController extends BaseController {
@Getter
@Setter
private CompanyContactViewModel viewModel;
@Autowired
private CompanyContactRepository companyContactRepository;
private CompanyContactService companyContactService;
public TextField nameField;
public TextField positionField;
@@ -78,7 +89,8 @@ public class CompanyContactWindowController extends BaseController {
@Override
public void show(Stage 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
@@ -91,24 +103,19 @@ public class CompanyContactWindowController extends BaseController {
initializeBaseTab();
companyContactLoadedFuture = CompletableFuture.supplyAsync(() -> {
Optional<CompanyContact> optional = companyContactRepository.findById(viewModel.getId().get());
if (optional.isPresent()) {
CompanyContact oldName = optional.get();
Platform.runLater(() -> {
viewModel.update(oldName);
viewModel.bindListener();
if (logger.isDebugEnabled()) {
logger.debug("bind ViewModel({}) Listener", viewModel.getName().get());
}
tabPane.getSelectionModel().getSelectedItem().getOnSelectionChanged().handle(null);
});
return oldName;
}
return null;
CompanyContact oldName = companyContactService.findById(viewModel.getId().get());
Platform.runLater(() -> {
viewModel.update(oldName);
viewModel.bindListener();
if (logger.isDebugEnabled()) {
logger.debug("bind ViewModel({}) Listener", viewModel.getName().get());
}
tabPane.getSelectionModel().getSelectedItem().getOnSelectionChanged().handle(null);
});
return oldName;
});
}
private void initializeBaseTab() {
baseInfoTab.setOnSelectionChanged(event -> {
if (logger.isDebugEnabled()) {
@@ -123,7 +130,7 @@ public class CompanyContactWindowController extends BaseController {
try {
CompanyContact contact = companyContactLoadedFuture.join();
viewModel.copyTo(contact);
CompanyContact saved = companyContactRepository.save(contact);
CompanyContact saved = companyContactService.save(contact);
viewModel.update(saved);
companyContactLoadedFuture = CompletableFuture.completedFuture(saved);
} catch (Exception e) {
@@ -155,7 +162,7 @@ public class CompanyContactWindowController extends BaseController {
if (logger.isDebugEnabled()) {
logger.debug("onBaseTabShown company contact {}", contact.getName());
}
// viewModel.update(contact);
// viewModel.update(contact);
}).exceptionally(ex -> {
UITools.showExceptionAndWait(ex.getMessage(), ex);
return null;
@@ -176,4 +183,3 @@ public class CompanyContactWindowController extends BaseController {
super.onHidden(windowEvent);
}
}

View File

@@ -1,20 +1,20 @@
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.model.Company;
import com.ecep.contract.service.CompanyOldNameService;
import com.ecep.contract.service.CompanyService;
import com.ecep.contract.vm.CompanyViewModel;
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.event.ActionEvent;
import javafx.scene.control.Alert;
import javafx.scene.control.TextInputDialog;
import lombok.Setter;
import java.util.List;
import java.util.Optional;
public class CompanyManagerSkin
extends AbstEntityManagerSkin<Company, CompanyViewModel, CompanyManagerSkin, CompanyManagerWindowController> {

View File

@@ -1,4 +1,4 @@
package com.ecep.contract.manager.ds.company.controller;
package com.ecep.contract.controller.company;
import java.time.LocalDate;
@@ -7,13 +7,13 @@ import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import com.ecep.contract.manager.ds.company.model.Company;
import com.ecep.contract.manager.ds.company.service.CompanyService;
import com.ecep.contract.manager.ds.company.tasker.CompanyFilesRebuildTasker;
import com.ecep.contract.manager.ds.company.vo.CompanyViewModel;
import com.ecep.contract.manager.ui.AbstManagerWindowController;
import com.ecep.contract.manager.ui.FxmlPath;
import com.ecep.contract.manager.util.UITools;
import com.ecep.contract.controller.AbstManagerWindowController;
import com.ecep.contract.model.Company;
import com.ecep.contract.service.CompanyService;
import com.ecep.contract.task.CompanyFilesRebuildTasker;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vm.CompanyViewModel;
import javafx.event.ActionEvent;
import javafx.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.Scope;
import org.springframework.stereotype.Component;
import com.ecep.contract.controller.BaseController;
import com.ecep.contract.util.FxmlPath;
@Lazy
@Scope("prototype")
@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.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -35,25 +11,62 @@ import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
import com.ecep.contract.DesktopUtils;
import com.ecep.contract.SpringApp;
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.model.Company;
import com.ecep.contract.model.CompanyCustomer;
import com.ecep.contract.model.CompanyVendor;
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.ProxyUtils;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vm.CompanyViewModel;
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
@Scope("prototype")
@Component
@FxmlPath("/ui/company/company.fxml")
public class CompanyWindowController
extends AbstEntityController<Company, CompanyViewModel> {
extends AbstEntityController<CompanyVo, CompanyViewModel> {
private static final Logger logger = LoggerFactory.getLogger(CompanyWindowController.class);
public static void show(Company company, Window window) {
CompanyViewModel viewModel = new CompanyViewModel();
if (!Hibernate.isInitialized(company)) {
company = SpringApp.getBean(CompanyService.class).findById(company.getId());
}
viewModel.update(company);
show(viewModel, window);
public static void show(CompanyVo company, Window window) {
show(CompanyViewModel.from(company), window);
}
/**
@@ -66,10 +79,6 @@ public class CompanyWindowController
@Autowired
private CompanyService companyService;
@Autowired
private CompanyFileService companyFileService;
@Autowired
private ContractService contractService;
@Autowired
private CompanyCustomerService companyCustomerService;
@Autowired
private CompanyVendorService companyVendorService;
@@ -89,7 +98,7 @@ public class CompanyWindowController
public Tab purchaseBillVoucherTab;
public Tab otherTab;
/*
*/
public TextField nameField;
public TextField shortNameField;
@@ -117,9 +126,10 @@ public class CompanyWindowController
public Button companyPathChangeBtn;
public Button companyPathSameAsNameBtn;
// private final CompanyCustomerViewModel companyCustomerViewModel = new CompanyCustomerViewModel();
// private final CompanyVendorViewModel companyVendorViewModel = new CompanyVendorViewModel();
// private final CompanyCustomerViewModel companyCustomerViewModel = new
// CompanyCustomerViewModel();
// private final CompanyVendorViewModel companyVendorViewModel = new
// CompanyVendorViewModel();
private final SimpleObjectProperty<CompanyCustomer> companyCustomerProperty = new SimpleObjectProperty<>();
private final SimpleObjectProperty<CompanyVendor> companyVendorProperty = new SimpleObjectProperty<>();
@@ -134,7 +144,6 @@ public class CompanyWindowController
public Pane vendorTab_pane2;
public Button vendorTab_createBtn;
@Override
public void show(Stage stage) {
super.show(stage);
@@ -143,17 +152,6 @@ public class CompanyWindowController
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
protected void registerTabSkins() {
registerTabSkin(baseInfoTab, tab1 -> new CompanyTabSkinBase(this));
@@ -161,18 +159,16 @@ public class CompanyWindowController
registerTabSkin(contactTab, tab1 -> new CompanyTabSkinContact(this));
registerTabSkin(blackReasonTab, tab1 -> new CompanyTabSkinBlackReason(this));
registerTabSkin(bankAccountTab, tab1 -> new CompanyTabSkinBankAccount(this));
registerTabSkin(contractTab, this::createContractTabSkin);
registerTabSkin(fileTab, this::createFileTabSkin);
registerTabSkin(contractTab, tab -> new CompanyTabSkinContract(this));
registerTabSkin(fileTab, tab -> new CompanyTabSkinFile(this));
registerTabSkin(invoiceTab, tab -> new CompanyTabSkinInvoice(this));
registerTabSkin(purchaseBillVoucherTab, tab -> new CompanyTabSkinPurchaseBillVoucher(this));
registerTabSkin(otherTab, tab -> new CompanyTabSkinOther(this));
initializeVendorTab();
initializeCustomerTab();
}
@Override
protected <K extends AbstEntityBasedTabSkin<?, ?, ?>> K registerTabSkin(Tab tab, Function<Tab, K> func) {
K skin = super.registerTabSkin(tab, func);
@@ -187,19 +183,6 @@ public class CompanyWindowController
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() {
customerTab.setOnSelectionChanged(event -> {
if (logger.isDebugEnabled()) {
@@ -210,7 +193,6 @@ public class CompanyWindowController
}
});
customerTab_pane1.visibleProperty().bind(customerTab_pane2.visibleProperty().not());
customerTab_pane2.visibleProperty().bind(companyCustomerProperty.isNull());
customerTab_createBtn.setOnAction(event -> {
@@ -283,8 +265,7 @@ public class CompanyWindowController
* 企业合规检查
*/
public void onCompanyVerifyAction(ActionEvent event) {
Company company = getEntity();
CompanyVo company = getEntity();
CompanyVerifyTasker task = new CompanyVerifyTasker();
task.setCompanyService(companyService);
task.setCompany(company);
@@ -292,7 +273,7 @@ public class CompanyWindowController
}
public void onCompanyOpenInExplorerAction(ActionEvent event) {
Company company = getEntity();
CompanyVo company = getEntity();
String path = company.getPath();
CompletableFuture.runAsync(() -> {

View File

@@ -1,17 +1,18 @@
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.model.CompanyOldName;
import com.ecep.contract.service.CompanyOldNameService;
import com.ecep.contract.service.CompanyService;
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.util.converter.LocalDateStringConverter;
import lombok.Setter;
import java.time.format.DateTimeFormatter;
public class CompanyOldNameTabSkinBase
extends AbstEntityBasedTabSkin<CompanyOldNameWindowController, CompanyOldName, CompanyOldNameViewModel>

View File

@@ -0,0 +1,368 @@
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.CompanyFile;
import com.ecep.contract.model.CompanyOldName;
import com.ecep.contract.service.CompanyFileService;
import com.ecep.contract.service.CompanyOldNameService;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vm.CompanyFileViewModel;
import com.ecep.contract.vm.CompanyOldNameViewModel;
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, CompanyOldName, CompanyOldNameViewModel, CompanyFile, 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 Map<String, Object> getSpecification(CompanyOldName parent) {
Map<String, Object> params = new HashMap<>();
params.put("company", parent.getCompanyId());
return params;
}
@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) {
CompanyOldName 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,30 +1,38 @@
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.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 org.springframework.util.StringUtils;
import java.io.File;
import java.util.concurrent.CompletableFuture;
import com.ecep.contract.DesktopUtils;
import com.ecep.contract.controller.AbstEntityController;
import com.ecep.contract.model.CompanyOldName;
import com.ecep.contract.service.CompanyOldNameService;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.util.UITools;
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
@Scope("prototype")
@@ -45,12 +53,6 @@ public class CompanyOldNameWindowController extends AbstEntityController<Company
public TabPane tabPane;
public Tab fileTab;
@Autowired
private CompanyOldNameService companyOldNameService;
@Autowired
private CompanyService companyService;
public TextField nameField;
public CheckBox ambiguityField;
public DatePicker startDateField;
@@ -62,26 +64,14 @@ public class CompanyOldNameWindowController extends AbstEntityController<Company
public Button saveBtn;
public Button saveBtn2;
public TableView<CompanyFileViewModel> fileTable;
@Override
public void onShown(WindowEvent windowEvent) {
super.onShown(windowEvent);
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
protected void registerTabSkins() {
registerTabSkin(baseInfoTab, this::createBaseTabSkin);
@@ -90,23 +80,22 @@ public class CompanyOldNameWindowController extends AbstEntityController<Company
@Override
public CompanyOldNameService getViewModelService() {
return companyOldNameService;
return getCachedBean(CompanyOldNameService.class);
}
private CompanyOldNameTabSkinBase createBaseTabSkin(Tab tab) {
CompanyOldNameTabSkinBase skin = new CompanyOldNameTabSkinBase(this);
skin.setCompanyOldNameService(companyOldNameService);
skin.setCompanyOldNameService(getViewModelService());
return skin;
}
private CompanyOldNameTabSkinFile createFileTabSkin(Tab tab) {
CompanyOldNameTabSkinFile skin = new CompanyOldNameTabSkinFile(this);
skin.setCompanyOldNameService(companyOldNameService);
// skin.setCompanyFileService(companyFileService);
skin.setCompanyOldNameService(getViewModelService());
// skin.setCompanyFileService(companyFileService);
return skin;
}
public void onOldCompanyOpenInExplorerAction(ActionEvent event) {
CompanyOldName companyOldName = getEntity();
String path = companyOldName.getPath();
@@ -115,7 +104,7 @@ public class CompanyOldNameWindowController extends AbstEntityController<Company
if (!StringUtils.hasText(path)) {
ButtonType buttonType = UITools.showConfirmation("目录未设置", "是否创建目录").join();
if (buttonType == ButtonType.OK) {
if (companyOldNameService.makePathAbsent(companyOldName)) {
if (getViewModelService().makePathAbsent(companyOldName)) {
save(companyOldName);
}
} else {
@@ -128,4 +117,3 @@ public class CompanyOldNameWindowController extends AbstEntityController<Company
});
}
}

View File

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

View File

@@ -0,0 +1,33 @@
package com.ecep.contract.controller.contract;
import java.util.HashMap;
import java.util.Map;
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.Contract;
import com.ecep.contract.model.IdentityEntity;
import com.ecep.contract.service.ContractService;
import com.ecep.contract.vm.ContractViewModel;
import com.ecep.contract.vm.IdentityViewModel;
public abstract class AbstContractTableTabSkin<T extends IdentityEntity, TV extends IdentityViewModel<T>>
extends AbstEntityTableTabSkin<ContractWindowController, Contract, ContractViewModel, T, TV>
implements TabSkin, TableOfTabSkin<Contract, T, TV> {
public AbstContractTableTabSkin(ContractWindowController controller) {
super(controller);
}
public ContractService getContractService() {
return controller.getViewModelService();
}
@Override
public Map<String, Object> getSpecification(Contract parent) {
Map<String, Object> params = new HashMap<>();
params.put("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.LocalDateTime;
@@ -8,19 +8,20 @@ import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import com.ecep.contract.manager.ds.company.model.Company;
import com.ecep.contract.manager.ds.contract.model.Contract;
import com.ecep.contract.manager.ds.contract.model.ContractGroup;
import com.ecep.contract.manager.ds.contract.model.ContractKind;
import com.ecep.contract.manager.ds.contract.model.ContractType;
import com.ecep.contract.manager.ds.contract.service.ContractService;
import com.ecep.contract.manager.ds.contract.tasker.ContractFilesRebuildAllTasker;
import com.ecep.contract.manager.ds.contract.tasker.ContractRepairAllTasker;
import com.ecep.contract.manager.ds.contract.vo.ContractViewModel;
import com.ecep.contract.manager.ds.other.model.Employee;
import com.ecep.contract.manager.ui.AbstManagerWindowController;
import com.ecep.contract.manager.ui.FxmlPath;
import com.ecep.contract.manager.util.UITools;
import com.ecep.contract.controller.AbstManagerWindowController;
import com.ecep.contract.controller.tab.ContractManagerSkin;
import com.ecep.contract.model.Company;
import com.ecep.contract.model.Contract;
import com.ecep.contract.model.ContractGroup;
import com.ecep.contract.model.ContractKind;
import com.ecep.contract.model.ContractType;
import com.ecep.contract.model.Employee;
import com.ecep.contract.service.ContractService;
import com.ecep.contract.task.ContractFilesRebuildAllTasker;
import com.ecep.contract.task.ContractRepairAllTasker;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vm.ContractViewModel;
import javafx.event.ActionEvent;
import javafx.scene.control.CheckBox;

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.concurrent.CompletableFuture;
import org.hibernate.Hibernate;
import com.ecep.contract.manager.SpringApp;
import com.ecep.contract.manager.ds.contract.model.Contract;
import com.ecep.contract.manager.ds.contract.model.ExtendVendorInfo;
import com.ecep.contract.manager.ds.contract.service.ExtendVendorInfoService;
import com.ecep.contract.manager.ds.contract.vo.ExtendVendorInfoViewModel;
import com.ecep.contract.manager.ds.vendor.model.VendorGroup;
import com.ecep.contract.manager.ds.vendor.service.VendorGroupService;
import com.ecep.contract.manager.ui.ComboBoxUtils;
import com.ecep.contract.manager.ui.FxmlPath;
import com.ecep.contract.manager.util.UITools;
import com.ecep.contract.SpringApp;
import com.ecep.contract.controller.ComboBoxUtils;
import com.ecep.contract.model.Contract;
import com.ecep.contract.model.ExtendVendorInfo;
import com.ecep.contract.model.VendorGroup;
import com.ecep.contract.service.ExtendVendorInfoService;
import com.ecep.contract.service.VendorGroupService;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.util.ProxyUtils;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vm.ExtendVendorInfoViewModel;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
@@ -116,7 +115,7 @@ public class ContractTabSkinExtendVendorInfo
if (v == null) {
return "-";
}
if (!Hibernate.isInitialized(v)) {
if (!ProxyUtils.isInitialized(v)) {
v = getVendorGroupService().findById(v.getId());
viewModel.getGroup().set(v);
}

View File

@@ -1,37 +1,19 @@
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.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
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.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -40,21 +22,51 @@ import org.springframework.context.annotation.Scope;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.io.File;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import com.ecep.contract.Message;
import com.ecep.contract.MessageHolder;
import com.ecep.contract.controller.BaseController;
import com.ecep.contract.controller.table.cell.EmployeeTableCell;
import com.ecep.contract.model.Contract;
import com.ecep.contract.model.Employee;
import com.ecep.contract.service.ContractService;
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 static com.ecep.contract.manager.util.TableViewUtils.bindDoubleClicked;
import static com.ecep.contract.manager.util.TableViewUtils.bindEnterPressed;
import static java.util.concurrent.CompletableFuture.runAsync;
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.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
@Scope("prototype")
@@ -78,7 +90,6 @@ public class ContractVerifyWindowController extends BaseController {
}
}
@Data
public static class Model implements MessageHolder {
private SimpleStringProperty code = new SimpleStringProperty();
@@ -104,9 +115,6 @@ public class ContractVerifyWindowController extends BaseController {
}
}
static class StateTableCell extends TableCell<Model, ObservableList<MessageExt>> {
Label message2Label(MessageExt message) {
Label label = new Label(message.getMessage());
@@ -154,7 +162,7 @@ public class ContractVerifyWindowController extends BaseController {
ContractVerifyComm comm = new ContractVerifyComm();
@Autowired
private SaleTypeService saleTypeService;
private ProjectSaleTypeService saleTypeService;
@Autowired
private VendorGroupService vendorGroupService;
@Autowired
@@ -189,7 +197,6 @@ public class ContractVerifyWindowController extends BaseController {
@FXML
public CheckMenuItem onlyShowVerifiedChecker;
@FXML
public TableView<Model> viewTable;
private final ObservableList<Model> viewTableDataSet = FXCollections.observableArrayList();
@@ -224,9 +231,11 @@ public class ContractVerifyWindowController extends BaseController {
viewTable_employeeColumn.setCellValueFactory(param -> param.getValue().getEmployee());
viewTable_employeeColumn.setCellFactory(param -> new EmployeeTableCell<>(getEmployeeService()));
viewTable_setupDateColumn.setCellValueFactory(param -> param.getValue().getSetupDate());
// viewTable_stateColumn.setCellValueFactory(param -> param.getValue().getMessages().map(messages -> {
// return messages.stream().map(Message::getMessage).collect(Collectors.joining(", "));
// }));
// viewTable_stateColumn.setCellValueFactory(param ->
// param.getValue().getMessages().map(messages -> {
// return
// messages.stream().map(Message::getMessage).collect(Collectors.joining(", "));
// }));
viewTable_stateColumn.setCellValueFactory(param -> param.getValue().getMessages());
viewTable_stateColumn.setCellFactory(param -> new StateTableCell());
@@ -241,11 +250,9 @@ public class ContractVerifyWindowController extends BaseController {
comm.getVerifyCustomerFiles().bind(verifyCustomerFileChecker.selectedProperty());
comm.getVerifyCustomerSubContractDate().bind(verifyCustomerSubContractDateChecker.selectedProperty());
bindDoubleClicked(viewTable, this::showContract);
bindEnterPressed(viewTable, this::reVerifyContract);
}
/**
@@ -257,22 +264,13 @@ public class ContractVerifyWindowController extends BaseController {
viewTableDataSet.clear();
Pageable pageRequest = PageRequest.ofSize(200);
AtomicInteger counter = new AtomicInteger(0);
Specification<Contract> spec = (root, query, builder) -> {
return builder.and(
builder.or(
builder.equal(root.get("payWay"), ContractPayWay.RECEIVE),
builder.and(
builder.equal(root.get("payWay"), ContractPayWay.PAY),
builder.or(
builder.isNull(root.get("parentCode")),
builder.equal(root.get("parentCode"), "")
)
)
),
builder.between(root.get("setupDate"), setupDateBeginSelector.getValue(), setupDateEndSelector.getValue())
);
};
long total = contractService.count(spec);
Map<String, Object> params = ParamUtils.builder().
between("setupDate", setupDateBeginSelector.getValue(), setupDateEndSelector.getValue())
.build();
long total = contractService.count(params);
setStatus("合同:" + total + "");
while (true) {
@@ -280,7 +278,7 @@ public class ContractVerifyWindowController extends BaseController {
break;
}
Page<Contract> page = contractService.findAll(spec, pageRequest);
Page<Contract> page = contractService.findAll(params, pageRequest);
for (Contract contract : page) {
if (isCloseRequested()) {
break;
@@ -298,6 +296,7 @@ public class ContractVerifyWindowController extends BaseController {
model.getCode().set(contract.getCode());
model.getName().set(contract.getName());
model.getSetupDate().set(contract.getSetupDate());
comm.verify(contract, model);
setStatus("合同验证进度:" + counter.get() + " / " + total);
// 移除中间消息
@@ -323,7 +322,6 @@ public class ContractVerifyWindowController extends BaseController {
});
}
public void onContractReVerifyAction(ActionEvent event) {
Model selectedItem = viewTable.getSelectionModel().getSelectedItem();
if (selectedItem == null) {
@@ -338,7 +336,13 @@ public class ContractVerifyWindowController extends BaseController {
return;
}
runAsync(() -> {
Contract contract = contractService.findByCode(contractCode);
Contract contract = null;
try {
contract = contractService.findByCode(contractCode);
} catch (Exception e) {
handleException("查找合同 " + contractCode + " 时发生错误", e);
return;
}
if (contract == null) {
return;
}
@@ -362,7 +366,6 @@ public class ContractVerifyWindowController extends BaseController {
});
}
public void onShowContractDetailAction(ActionEvent event) {
Model selectedItem = viewTable.getSelectionModel().getSelectedItem();
if (selectedItem == null) {
@@ -376,7 +379,13 @@ public class ContractVerifyWindowController extends BaseController {
if (!StringUtils.hasText(contractCode)) {
return;
}
Contract contract = contractService.findByCode(contractCode);
Contract contract = null;
try {
contract = contractService.findByCode(contractCode);
} catch (Exception e) {
handleException("查找合同 " + contractCode + " 时发生错误", e);
return;
}
if (contract == null) {
return;
}
@@ -389,7 +398,7 @@ public class ContractVerifyWindowController extends BaseController {
chooser.setInitialFileName("核验结果.xlsx");
File selected = chooser.showSaveDialog(viewTable.getScene().getWindow());
if (selected != null) {
ContractVerifyResultExportAsExcelFile task = new ContractVerifyResultExportAsExcelFile();
ContractVerifyResultExportAsExcelFileTasker task = new ContractVerifyResultExportAsExcelFileTasker();
task.setDestFile(selected);
task.setModels(new ArrayList<>(viewTableDataSet));
UITools.showTaskDialogAndWait("导出中...", task, null);

View File

@@ -1,33 +1,31 @@
package com.ecep.contract.manager.ds.contract.controller;
package com.ecep.contract.controller.contract;
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 com.ecep.contract.ContractPayWay;
import com.ecep.contract.DesktopUtils;
import com.ecep.contract.controller.AbstEntityController;
import com.ecep.contract.controller.company.CompanyWindowController;
import com.ecep.contract.controller.tab.*;
import com.ecep.contract.model.Company;
import com.ecep.contract.model.Contract;
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 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.Scope;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.io.File;
import java.time.format.DateTimeFormatter;
@Lazy
@Scope("prototype")
@@ -36,7 +34,6 @@ import java.time.format.DateTimeFormatter;
public class ContractWindowController
extends AbstEntityController<Contract, ContractViewModel> {
public static void show(Contract contract, Window owner) {
ContractViewModel model = new ContractViewModel();
model.update(contract);
@@ -63,16 +60,6 @@ public class ContractWindowController
public Button openRelativeCompanyCustomerBtn;
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 guidField;
public TextField codeField;
@@ -124,12 +111,17 @@ public class ContractWindowController
@Override
public ContractService getViewModelService() {
return contractService;
return getCachedBean(ContractService.class);
}
public CompanyService getCompanyService() {
return getCachedBean(CompanyService.class);
}
public void onShown(WindowEvent 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");
}
@@ -139,31 +131,27 @@ public class ContractWindowController
ObservableList<Tab> tabs = tabPane.getTabs();
registerTabSkin(baseInfoTab, tab -> new ContractTabSkinBase(this));
switch (viewModel.getPayWay().get()) {
case RECEIVE -> {
tabs.remove(extendVendorInfo);
registerTabSkin(contractTab, t -> new ContractTabSkinSubContract(this));
tabs.remove(bidVendorTab);
Tab saleOrderTab = new Tab("销售订单");
tabs.add(saleOrderTab);
registerTabSkin(saleOrderTab, tab -> new ContractTabSkinSaleOrders(this, tab));
tabs.add(new Tab("票据"));
break;
}
case PAY -> {
registerTabSkin(extendVendorInfo, t -> new ContractTabSkinExtendVendorInfo(this));
tabs.remove(contractTab);
registerTabSkin(bidVendorTab, t -> new ContractTabSkinVendorBid(this));
ContractPayWay payWay = viewModel.getPayWay().get();
if (payWay == ContractPayWay.RECEIVE) {
tabs.remove(extendVendorInfo);
registerTabSkin(contractTab, t -> new ContractTabSkinSubContract(this));
tabs.remove(bidVendorTab);
Tab saleOrderTab = new Tab("销售订单");
tabs.add(saleOrderTab);
registerTabSkin(saleOrderTab, tab -> new ContractTabSkinSaleOrders(this, tab));
tabs.add(new Tab("票据"));
} else if (payWay == ContractPayWay.PAY) {
registerTabSkin(extendVendorInfo, t -> new ContractTabSkinExtendVendorInfo(this));
tabs.remove(contractTab);
registerTabSkin(bidVendorTab, t -> new ContractTabSkinVendorBid(this));
Tab purchaseOrderTab = new Tab("采购订单");
tabs.add(purchaseOrderTab);
registerTabSkin(purchaseOrderTab, tab -> new ContractTabSkinPurchaseOrders(this, tab));
Tab purchaseOrderTab = new Tab("采购订单");
tabs.add(purchaseOrderTab);
registerTabSkin(purchaseOrderTab, tab -> new ContractTabSkinPurchaseOrders(this, tab));
tabs.add(new Tab("发货单"));
tabs.add(new Tab("签收单"));
tabs.add(new Tab("付款单"));
break;
}
tabs.add(new Tab("发货单"));
tabs.add(new Tab("签收单"));
tabs.add(new Tab("付款单"));
}
registerTabSkin(itemTab, tab -> new ContractTabSkinItemsV2(this));
@@ -171,7 +159,6 @@ public class ContractWindowController
registerTabSkin(fileTab, tab -> new ContractTabSkinFiles(this));
}
public void onContractOpenInExplorerAction(ActionEvent event) {
Contract contract = getEntity();
String path = contract.getPath();
@@ -194,7 +181,7 @@ public class ContractWindowController
return;
}
Integer companyId = contract.getCompany().getId();
Company company = companyService.findById(companyId);
Company company = getCompanyService().findById(companyId);
if (company != null) {
CompanyWindowController.show(company, root.getScene().getWindow());
}
@@ -202,7 +189,6 @@ public class ContractWindowController
public void onSyncContractAction(ActionEvent event) {
ContractRepairTask task = new ContractRepairTask();
task.setContractService(contractService);
task.setContract(getEntity());
UITools.showTaskDialogAndWait("同步合同", task, null);
if (task.isRepaired()) {
@@ -221,7 +207,7 @@ public class ContractWindowController
}
}
if (task.isItemsUpdated()) {
ContractTabSkinItems tabSkin = getTabSkin(ContractTabSkinItems.class);
ContractTabSkinItemsV2 tabSkin = getTabSkin(ContractTabSkinItemsV2.class);
if (tabSkin != null) {
tabSkin.loadTableDataSet();
}
@@ -234,14 +220,12 @@ public class ContractWindowController
}
}
/**
* 验证合同合规性
*/
public void onContractVerifyAction(ActionEvent event) {
Contract contract = getEntity();
ContractVerifyTasker task = new ContractVerifyTasker();
task.setContractService(contractService);
task.setContract(contract);
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.CompanyCustomer;
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;
public abstract class AbstCompanyCustomerTableTabSkin<T extends IdentityEntity, TV extends IdentityViewModel<T>>
extends
AbstEntityTableTabSkin<CompanyCustomerWindowController, CompanyCustomer, 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.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;
@@ -33,11 +17,37 @@ import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
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.controller.BaseController;
import com.ecep.contract.model.CompanyCustomerEvaluationFormFile;
import com.ecep.contract.model.CompanyCustomerFile;
import com.ecep.contract.service.CompanyCustomerFileService;
import com.ecep.contract.util.FileUtils;
import com.ecep.contract.util.FxmlUtils;
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
@Scope("prototype")
@Component
@@ -96,10 +106,6 @@ public class CompanyCustomerEvaluationFormFileWindowController extends BaseContr
private SimpleObjectProperty<Image> imageProperty = new SimpleObjectProperty<>();
private CompletableFuture<CompanyCustomerEvaluationFormFile> loadedFuture;
@Autowired
private CompanyCustomerFileRepository companyCustomerFileRepository;
@Autowired
private CompanyCustomerEvaluationFormFileRepository companyCustomerEvaluationFormFileRepository;
@Lazy
@Autowired
private CompanyCustomerFileService companyCustomerFileService;
@@ -291,7 +297,7 @@ public class CompanyCustomerEvaluationFormFileWindowController extends BaseContr
imageView.imageProperty().bind(viewModel.getFilePath().map(path -> {
if (CompanyFileUtils.withExtensions(path, CompanyFileUtils.PDF)) {
if (FileUtils.withExtensions(path, FileUtils.PDF)) {
File pdfFile = new File(path);
try (PDDocument pdDocument = Loader.loadPDF(pdfFile)) {
PDFRenderer pdfRenderer = new PDFRenderer(pdDocument);

View File

@@ -1,35 +1,39 @@
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.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 static com.ecep.contract.util.ExcelUtils.setCellValue;
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.util.Comparator;
import java.util.List;
import static com.ecep.contract.manager.util.ExcelUtils.setCellValue;
import com.ecep.contract.service.*;
import com.ecep.contract.util.CompanyUtils;
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 com.ecep.contract.util.ProxyUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import com.ecep.contract.CompanyCustomerFileType;
import com.ecep.contract.SpringApp;
import com.ecep.contract.model.CloudTyc;
import com.ecep.contract.model.Company;
import com.ecep.contract.model.CompanyCustomer;
import com.ecep.contract.model.CompanyCustomerEvaluationFormFile;
import com.ecep.contract.model.CompanyCustomerFile;
import javafx.concurrent.Task;
import lombok.Setter;
public class CompanyCustomerEvaluationFormUpdateTask extends Task<Object> {
private static final Logger logger = LoggerFactory.getLogger(CompanyCustomerEvaluationFormUpdateTask.class);
@@ -109,8 +113,7 @@ public class CompanyCustomerEvaluationFormUpdateTask extends Task<Object> {
updateMessage("表单文件已经存在," + destFile.getName());
try (
InputStream inp = new FileInputStream(destFile);
Workbook wb = WorkbookFactory.create(inp)
) {
Workbook wb = WorkbookFactory.create(inp)) {
updateEvaluationForm(wb, destFile);
updateMessage("评价表已更新");
} catch (Exception e) {
@@ -121,8 +124,7 @@ public class CompanyCustomerEvaluationFormUpdateTask extends Task<Object> {
updateMessage("根据模板 " + template_file_name + " 创建表单 " + destFile.getName());
try (
InputStream inp = new FileInputStream(template);
Workbook wb = WorkbookFactory.create(inp)
) {
Workbook wb = WorkbookFactory.create(inp)) {
updateEvaluationForm(wb, destFile);
updateMessage("评价表已创建");
CompanyCustomerFile customerFile = new CompanyCustomerFile();
@@ -142,7 +144,6 @@ public class CompanyCustomerEvaluationFormUpdateTask extends Task<Object> {
getCompanyCustomerFileService().save(customerFile);
}
/**
* 更新客户评估表依据模板创建如果已经存在生成的文件则更新评估表
*
@@ -150,10 +151,9 @@ public class CompanyCustomerEvaluationFormUpdateTask extends Task<Object> {
* @param destFile 目标文件
*/
public void updateEvaluationForm(
Workbook wb, File destFile
) throws IOException {
Workbook wb, File destFile) throws IOException {
Company company = customer.getCompany();
if (!Hibernate.isInitialized(company)) {
if (!ProxyUtils.isInitialized(company)) {
company = getCompanyService().findById(company.getId());
customer.setCompany(company);
}
@@ -172,10 +172,10 @@ public class CompanyCustomerEvaluationFormUpdateTask extends Task<Object> {
}
private void updateSheet(Company company, Sheet sheet) {
setCellValue(sheet, "B3", "客户编号:" + CompanyBasicService.formatCompanyVendorId(customer.getId()));
setCellValue(sheet, "B3", "客户编号:" + CompanyUtils.formatCompanyVendorId(customer.getId()));
setCellValue(sheet, "B4", "客户名称:" + company.getName());
LocalDate suggestDate = getCompanyCustomerFileService().getNextSignDate(customer, msg -> {
LocalDate suggestDate = getCompanyCustomerFileService().getNextSignDate(customer, (level, msg) -> {
updateMessage(" - " + msg);
});
if (suggestDate == null) {
@@ -192,7 +192,8 @@ public class CompanyCustomerEvaluationFormUpdateTask extends Task<Object> {
setCellValue(sheet, "H6", "成立日期:" + company.getSetupDate());
// 所属行业
setCellValue(sheet, "D7", "所属行业:" + company.getIndustry());
setCellValue(sheet, "D8", "注册资金:" + company.getRegisteredCapital() + " " + company.getRegisteredCapitalCurrency());
setCellValue(sheet, "D8",
"注册资金:" + company.getRegisteredCapital() + " " + company.getRegisteredCapitalCurrency());
// 企业类型
setCellValue(sheet, "H10", "企业类型:" + company.getEntType());
// 天眼评分
@@ -200,10 +201,9 @@ public class CompanyCustomerEvaluationFormUpdateTask extends Task<Object> {
CloudTyc cloudTyc = cloudTycService.getOrCreateCloudTyc(company);
setCellValue(sheet, "D10", "天眼评分:" + (cloudTyc.getScore() > 0 ? cloudTyc.getScore() : ""));
// 检索评估表
List<CompanyCustomerEvaluationFormFile> evaluationFormFiles =
getCompanyCustomerFileService().findAllCustomerEvaluationFormFiles(customer);
List<CompanyCustomerEvaluationFormFile> evaluationFormFiles = getCompanyCustomerFileService()
.findAllCustomerEvaluationFormFiles(customer);
List<CompanyCustomerEvaluationFormFile> filteredList = evaluationFormFiles.stream()
.filter(v -> {
CompanyCustomerFile file = v.getCustomerFile();
@@ -227,7 +227,7 @@ public class CompanyCustomerEvaluationFormUpdateTask extends Task<Object> {
setCellValue(sheet, "E40", "经济指标");
setCellValue(sheet, "F40", "综合指标");
setCellValue(sheet, "G40", "资信等级");
String[] CreditLevelTitles = new String[]{"-", "差★", " 一般★★", " 较好★★★", " 好★★★★", " "};
String[] CreditLevelTitles = new String[] { "-", "差★", " 一般★★", " 较好★★★", " 好★★★★", " " };
int baseRow = 40;
for (CompanyCustomerEvaluationFormFile form : filteredList) {
CompanyCustomerFile customerFile = form.getCustomerFile();

View File

@@ -1,17 +1,13 @@
package com.ecep.contract.manager.ds.customer.controller;
package com.ecep.contract.controller.customer;
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.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 com.ecep.contract.MessageHolder;
import com.ecep.contract.MyDateTimeUtils;
import com.ecep.contract.model.*;
import com.ecep.contract.service.CompanyCustomerEntityService;
import com.ecep.contract.service.CompanyCustomerFileService;
import com.ecep.contract.service.CompanyCustomerService;
import com.ecep.contract.task.Tasker;
import com.ecep.contract.util.UITools;
import lombok.Setter;
import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.usermodel.*;
@@ -19,7 +15,7 @@ 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 com.ecep.contract.util.ProxyUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Pageable;
@@ -31,12 +27,11 @@ import java.time.LocalDateTime;
import java.util.Comparator;
import java.util.List;
import static com.ecep.contract.manager.util.ExcelUtils.*;
import static com.ecep.contract.util.ExcelUtils.*;
public class CompanyCustomerExportExcelTasker extends Tasker<Object> {
private static final Logger logger = LoggerFactory.getLogger(CompanyCustomerExportExcelTasker.class);
@Setter
File destFile;
@@ -55,6 +50,7 @@ public class CompanyCustomerExportExcelTasker extends Tasker<Object> {
customerFileService = getBean(CompanyCustomerFileService.class);
return customerFileService;
}
CompanyCustomerEntityService getCustomerEntityService() {
if (customerEntityService == null)
customerEntityService = getBean(CompanyCustomerEntityService.class);
@@ -78,8 +74,7 @@ public class CompanyCustomerExportExcelTasker extends Tasker<Object> {
}
try (
InputStream inp = new FileInputStream(template);
Workbook wb = WorkbookFactory.create(inp);
) {
Workbook wb = WorkbookFactory.create(inp);) {
String sheetName = "客户资信台账";
Sheet sheet = null;
for (int i = 0; i < wb.getNumberOfSheets(); i++) {
@@ -105,26 +100,26 @@ public class CompanyCustomerExportExcelTasker extends Tasker<Object> {
holder.warn("客户 #" + customer.getId() + " 不存在对应公司");
continue;
}
if (!Hibernate.isInitialized(company)) {
if (!ProxyUtils.isInitialized(company)) {
company = getCompanyService().findById(company.getId());
}
LocalDate devDate = null;
List<CompanyCustomerEntity> entities = getCustomerEntityService() .findAllByCustomer(customer);
List<CompanyCustomerEntity> entities = getCustomerEntityService().findAllByCustomer(customer);
for (CompanyCustomerEntity entity : entities) {
if (devDate == null || devDate.isAfter(entity.getDevelopDate())) {
devDate = entity.getDevelopDate();
}
}
CompanyCustomerEvaluationFormFile evaluationFormFile = getCustomerFileService().findAllCustomerEvaluationFormFiles(customer).stream().filter(v -> {
CompanyCustomerFile customerFile = v.getCustomerFile();
if (customerFile == null) {
return false;
}
return customerFile.isValid();
}).max(Comparator.comparing(v -> v.getCustomerFile().getSignDate())).orElse(null);
CompanyCustomerEvaluationFormFile evaluationFormFile = getCustomerFileService()
.findAllCustomerEvaluationFormFiles(customer).stream().filter(v -> {
CompanyCustomerFile customerFile = v.getCustomerFile();
if (customerFile == null) {
return false;
}
return customerFile.isValid();
}).max(Comparator.comparing(v -> v.getCustomerFile().getSignDate())).orElse(null);
if (evaluationFormFile == null) {
holder.warn(company.getName() + " 未匹配的客户评估");
@@ -133,10 +128,10 @@ public class CompanyCustomerExportExcelTasker extends Tasker<Object> {
CompanyCustomerFile customerFile = evaluationFormFile.getCustomerFile();
if (devDate != null && devDate.isAfter(customerFile.getSignDate())) {
holder.debug(company.getName() + " 最新评估日期早于客户开发日期,评估日期:" + customerFile.getSignDate() + ", 开发日期:" + devDate);
holder.debug(company.getName() + " 最新评估日期早于客户开发日期,评估日期:" + customerFile.getSignDate() + ", 开发日期:"
+ devDate);
}
rowIndex++;
if (rowIndex > 11) {
@@ -155,7 +150,6 @@ public class CompanyCustomerExportExcelTasker extends Tasker<Object> {
}
}
Row row = getRow(sheet, rowIndex + 3, true);
setCellValue(row, 0, rowIndex);
@@ -173,10 +167,11 @@ public class CompanyCustomerExportExcelTasker extends Tasker<Object> {
for (XSSFTable table : ((XSSFSheet) sheet).getTables()) {
if ("表2".equals(table.getName())) {
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.getCTTable().setRef("$A$4:$H$" + (rowIndex + 4));
// table.setDataRowCount(rowIndex);
// table.getCTTable().setRef("$A$4:$H$" + (rowIndex + 4));
}
}
@@ -200,7 +195,6 @@ public class CompanyCustomerExportExcelTasker extends Tasker<Object> {
UITools.showExceptionAndWait("保存失败", e);
}
return null;
}
}

View File

@@ -1,32 +1,25 @@
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.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.AbstEntityManagerSkin;
import com.ecep.contract.manager.util.MyDateTimeUtils;
import com.ecep.contract.MyDateTimeUtils;
import com.ecep.contract.controller.AbstEntityManagerSkin;
import com.ecep.contract.controller.table.cell.CompanyTableCell;
import com.ecep.contract.model.CompanyCustomer;
import com.ecep.contract.service.CompanyCustomerService;
import com.ecep.contract.service.CompanyService;
import com.ecep.contract.vm.CompanyCustomerViewModel;
import javafx.application.Platform;
import lombok.Setter;
public class CompanyCustomerManagerSkin
extends
AbstEntityManagerSkin<CompanyCustomer, CompanyCustomerViewModel, CompanyCustomerManagerSkin, CompanyCustomerManagerWindowController> {
@Setter
private CompanyService companyService;
public CompanyCustomerManagerSkin(CompanyCustomerManagerWindowController controller) {
super(controller);
}
public CompanyService getCompanyService() {
if (companyService == null) {
companyService = getBean(CompanyService.class);
}
return companyService;
return getBean(CompanyService.class);
}
public CompanyCustomerService getCompanyCustomerService() {
@@ -37,7 +30,7 @@ public class CompanyCustomerManagerSkin
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.companyColumn.setCellFactory(param -> new CompanyTableCell<>(getCompanyService()));
controller.developDateColumn.setCellValueFactory(param -> param.getValue().getDevelopDate());
controller.pathColumn.setCellValueFactory(param -> param.getValue().getPath());

View File

@@ -1,11 +1,10 @@
package com.ecep.contract.manager.ds.customer.controller;
package com.ecep.contract.controller.customer;
import java.io.File;
import java.time.LocalDate;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicBoolean;
import org.hibernate.Hibernate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
@@ -14,15 +13,16 @@ import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Component;
import com.ecep.contract.manager.ds.company.model.Company;
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.AbstManagerWindowController;
import com.ecep.contract.manager.ui.FxmlPath;
import com.ecep.contract.manager.util.MyDateTimeUtils;
import com.ecep.contract.manager.util.UITools;
import com.ecep.contract.MyDateTimeUtils;
import com.ecep.contract.controller.AbstManagerWindowController;
import com.ecep.contract.model.Company;
import com.ecep.contract.model.CompanyCustomer;
import com.ecep.contract.service.CompanyCustomerService;
import com.ecep.contract.service.CompanyService;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.util.ProxyUtils;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vm.CompanyCustomerViewModel;
import javafx.application.Platform;
import javafx.collections.FXCollections;
@@ -55,14 +55,15 @@ public class CompanyCustomerManagerWindowController
public TableColumn<CompanyCustomerViewModel, String> pathColumn;
public TableColumn<CompanyCustomerViewModel, String> createdColumn;
@Autowired
private CompanyService companyService;
@Autowired
private CompanyCustomerService companyCustomerService;
@Override
public CompanyCustomerService getViewModelService() {
return companyCustomerService;
return getCachedBean(CompanyCustomerService.class);
}
@Autowired
private CompanyService getCompanyService() {
return getCachedBean(CompanyService.class);
}
@Override
@@ -74,7 +75,6 @@ public class CompanyCustomerManagerWindowController
@Override
protected CompanyCustomerManagerSkin createDefaultSkin() {
CompanyCustomerManagerSkin skin = new CompanyCustomerManagerSkin(this);
skin.setCompanyService(companyService);
return skin;
}
@@ -116,7 +116,7 @@ public class CompanyCustomerManagerWindowController
CompletableFuture.runAsync(() -> {
Pageable pageRequest = PageRequest.ofSize(50);
while (!canceled.get()) {
Page<CompanyCustomer> page = companyCustomerService.findAll(null, pageRequest);
Page<CompanyCustomer> page = getViewModelService().findAll(null, pageRequest);
int index = page.getNumber() * page.getSize();
int i = 1;
@@ -125,12 +125,12 @@ public class CompanyCustomerManagerWindowController
return;
}
Company company = companyCustomer.getCompany();
if (!Hibernate.isInitialized(company)) {
company = companyService.findById(company.getId());
if (!ProxyUtils.isInitialized(company)) {
company = getCompanyService().findById(company.getId());
}
String prefix = (index + i) + "/" + page.getTotalElements() + ", " + company.getName() + "> ";
companyCustomerService.reBuildingFiles(companyCustomer, msg -> {
getViewModelService().reBuildingFiles(companyCustomer, (level, msg) -> {
Platform.runLater(() -> {
listViewDataSet.add(prefix + msg);
listView.scrollTo(listViewDataSet.size() - 1);
@@ -164,7 +164,7 @@ public class CompanyCustomerManagerWindowController
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("导出");
fileChooser.setInitialFileName("客户资信台账-" + MyDateTimeUtils.format(LocalDate.now()) + ".xlsx");
fileChooser.setInitialDirectory(companyCustomerService.getBasePath());
fileChooser.setInitialDirectory(getViewModelService().getBasePath());
File destFile = fileChooser.showSaveDialog(table.getScene().getWindow());
tasker.setDestFile(destFile);
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.model.Company;
import com.ecep.contract.model.CompanyContact;
import com.ecep.contract.model.CompanyCustomer;
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.property.SimpleObjectProperty;
import javafx.event.ActionEvent;
@@ -22,9 +26,6 @@ import javafx.scene.control.Tab;
import javafx.scene.control.TextField;
import javafx.util.converter.LocalDateStringConverter;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class CompanyCustomerTabSkinBase
extends AbstEntityBasedTabSkin<CompanyCustomerWindowController, CompanyCustomer, CompanyCustomerViewModel>
implements TabSkin {
@@ -53,8 +54,7 @@ public class CompanyCustomerTabSkinBase
controller.createdField.textProperty().bind(
Bindings.createStringBinding(
() -> localDateTimeFormatter(viewModel.getCreated()),
viewModel.getCreated())
);
viewModel.getCreated()));
controller.versionLabel.textProperty().bind(viewModel.getVersion().asString());
controller.relativeCompanyBtn.disableProperty().bind(viewModel.getCompany().isNull());
@@ -65,7 +65,6 @@ public class CompanyCustomerTabSkinBase
}
});
controller.createPathBtn.setOnAction(this::onCompanyCustomerCreatePathAction);
controller.changePathBtn.setOnAction(this::onCompanyCustomerChangePathAction);
controller.pathAsNameBtn.setOnAction(this::onCompanyCustomerPathSameAsNameAction);
@@ -82,7 +81,9 @@ public class CompanyCustomerTabSkinBase
private void initializeContactFieldAutoCompletion(TextField textField) {
EntityStringConverter<CompanyContact> stringConverter = new EntityStringConverter<>();
stringConverter.setInitialized(cc -> getCompanyContactService().findById(cc.getId()));
UITools.autoCompletion(textField, viewModel.getContact(), p -> getCompanyContactService().searchByCompany(viewModel.getCompany().get(), p.getUserText()), stringConverter);
UITools.autoCompletion(textField, viewModel.getContact(),
p -> getCompanyContactService().searchByCompany(viewModel.getCompany().get(), p.getUserText()),
stringConverter);
}
private void initializeCompanyFieldAutoCompletion(TextField textField) {
@@ -100,7 +101,6 @@ public class CompanyCustomerTabSkinBase
}
}
public void onCompanyCustomerChangePathAction(ActionEvent event) {
setStatus("未实现");
}
@@ -110,14 +110,14 @@ public class CompanyCustomerTabSkinBase
}
public CompanyCustomerService getCompanyCustomerService() {
return controller.companyCustomerService;
return controller.getCachedBean(CompanyCustomerService.class);
}
public CompanyContactService getCompanyContactService() {
return controller.companyContactService;
return controller.getCachedBean(CompanyContactService.class);
}
public CompanyService getCompanyService() {
return controller.companyService;
return controller.getCachedBean(CompanyService.class);
}
}

View File

@@ -1,31 +1,36 @@
package com.ecep.contract.manager.ds.customer.controller;
package com.ecep.contract.controller.customer;
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.ui.AbstEntityController;
import com.ecep.contract.manager.ui.FxmlPath;
import com.ecep.contract.manager.ui.ViewModelService;
import com.ecep.contract.manager.util.DesktopUtils;
import java.io.File;
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.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 org.springframework.util.StringUtils;
import java.io.File;
import com.ecep.contract.DesktopUtils;
import com.ecep.contract.controller.AbstEntityController;
import com.ecep.contract.model.CompanyCustomer;
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.util.ProxyUtils;
import com.ecep.contract.vm.CompanyCustomerViewModel;
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
@Scope("prototype")
@@ -33,6 +38,7 @@ import java.io.File;
@FxmlPath("/ui/company/customer/customer.fxml")
public class CompanyCustomerWindowController extends AbstEntityController<CompanyCustomer, CompanyCustomerViewModel> {
private static final Logger logger = LoggerFactory.getLogger(CompanyCustomerWindowController.class);
/**
* 显示界面
*/
@@ -48,14 +54,6 @@ public class CompanyCustomerWindowController extends AbstEntityController<Compan
public Tab fileTab;
public Tab entityTab;
public Tab satisfactionTab;
@Autowired
CompanyService companyService;
@Autowired
CompanyCustomerService companyCustomerService;
@Autowired
CompanyContactService companyContactService;
public TextField companyField;
public TextField contactField;
public TextField pathField;
@@ -70,7 +68,6 @@ public class CompanyCustomerWindowController extends AbstEntityController<Compan
public Button pathAsNameBtn;
public Button OpenCustomerPathInExplorerBtn;
@Override
public void show(Stage stage) {
super.show(stage);
@@ -78,8 +75,8 @@ public class CompanyCustomerWindowController extends AbstEntityController<Compan
if (company == null) {
return "-";
}
if (!Hibernate.isInitialized(company)) {
company = companyService.findById(company.getId());
if (!ProxyUtils.isInitialized(company)) {
company = getCompanyService().findById(company.getId());
viewModel.getCompany().set(company);
}
return getMessage("ui.customer.title", String.valueOf(viewModel.getId().get()), company.getName());
@@ -96,7 +93,15 @@ public class CompanyCustomerWindowController extends AbstEntityController<Compan
@Override
public CompanyCustomerService getViewModelService() {
return companyCustomerService;
return getCachedBean(CompanyCustomerService.class);
}
public CompanyService getCompanyService() {
return getCachedBean(CompanyService.class);
}
public CompanyContactService getCompanyContactService() {
return getCachedBean(CompanyContactService.class);
}
@Override
@@ -119,6 +124,4 @@ public class CompanyCustomerWindowController extends AbstEntityController<Compan
DesktopUtils.showInExplorer(file);
}
}

View File

@@ -1,24 +1,24 @@
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 com.ecep.contract.SpringApp;
import com.ecep.contract.controller.table.cell.LocalDateTimeTableCell;
import com.ecep.contract.converter.EmployeeStringConverter;
import com.ecep.contract.converter.EntityStringConverter;
import com.ecep.contract.model.CompanyCustomer;
import com.ecep.contract.model.CompanyCustomerEntity;
import com.ecep.contract.model.CustomerCatalog;
import com.ecep.contract.service.CompanyCustomerEntityService;
import com.ecep.contract.service.CustomerCatalogService;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.vm.CustomerEntityViewModel;
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.LocalDateTime;
import java.util.Map;
@FxmlPath("/ui/company/customer/customer-tab-entity.fxml")
public class CustomerTabSkinEntity
@@ -52,7 +52,6 @@ public class CustomerTabSkinEntity
return controller.entityTab;
}
@Override
public void initializeTab() {
super.initializeTab();
@@ -66,8 +65,10 @@ public class CustomerTabSkinEntity
EmployeeStringConverter stringConverter = SpringApp.getBean(EmployeeStringConverter.class);
entityTable_developDateColumn.setCellValueFactory(param -> param.getValue().getDevelopDate());
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_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());
fetchedTimeColumn.setCellValueFactory(param -> param.getValue().getFetchedTime());
@@ -77,10 +78,9 @@ public class CustomerTabSkinEntity
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()));
converter.setInitialized(v -> getCachedBean(CustomerCatalogService.class).findById(v.getId()));
column.setCellValueFactory(param -> param.getValue().getCatalog().map(converter::toString));
}
@@ -97,10 +97,10 @@ public class CustomerTabSkinEntity
}
@Override
public Specification<CompanyCustomerEntity> getSpecification(CompanyCustomer parent) {
return SpecificationUtils.and(getSpecification(), (root, query, builder) -> {
return builder.equal(root.get("customer"), parent);
});
public Map<String, Object> getSpecification(CompanyCustomer parent) {
Map<String, Object> params = getSpecification();
params.put("customer", parent.getId());
return params;
}
}

View File

@@ -1,46 +1,55 @@
package com.ecep.contract.manager.ds.customer.controller;
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;
package com.ecep.contract.controller.customer;
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.ScheduledExecutorService;
import java.util.function.Consumer;
import com.ecep.contract.service.CompanyCustomerFileTypeService;
import org.springframework.util.StringUtils;
import com.ecep.contract.CompanyCustomerFileType;
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.model.Company;
import com.ecep.contract.model.CompanyCustomer;
import com.ecep.contract.model.CompanyCustomerFile;
import com.ecep.contract.model.CompanyCustomerFileTypeLocal;
import com.ecep.contract.service.CompanyCustomerFileService;
import com.ecep.contract.service.CompanyCustomerService;
import com.ecep.contract.util.FileUtils;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.util.ProxyUtils;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vm.CompanyCustomerFileViewModel;
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")
public class CustomerTabSkinFile
extends AbstCompanyCustomerTableTabSkin<CompanyCustomerFile, CompanyCustomerFileViewModel>
@@ -49,7 +58,6 @@ public class CustomerTabSkinFile
@Setter
private CompanyCustomerFileService companyCustomerFileService;
public TableColumn<CompanyCustomerFileViewModel, Number> fileTable_idColumn;
public TableColumn<CompanyCustomerFileViewModel, String> fileTable_typeColumn;
public TableColumn<CompanyCustomerFileViewModel, String> fileTable_filePathColumn;
@@ -83,10 +91,10 @@ public class CustomerTabSkinFile
}
@Override
public Specification<CompanyCustomerFile> getSpecification(CompanyCustomer parent) {
return SpecificationUtils.and(getSpecification(), (root, query, builder) -> {
return builder.equal(root.get("customer"), parent);
});
public Map<String, Object> getSpecification(CompanyCustomer parent) {
Map<String, Object> params = getSpecification();
params.put("customer", parent.getId());
return params;
}
@Override
@@ -97,8 +105,9 @@ public class CustomerTabSkinFile
table.disableProperty().bind(viewModel.getPath().isEmpty());
fileTable_idColumn.setCellValueFactory(param -> param.getValue().getId());
ObservableMap<CompanyCustomerFileType, CompanyCustomerFileTypeLocal> observableMapByLocal = SpringApp.getBean(CompanyCustomerFileTypeLocalRepository.class).getObservableMapByLocal();
CompanyCustomerFileTypeService fileTypeService = getCachedBean(CompanyCustomerFileTypeService.class);
ObservableMap<CompanyCustomerFileType, CompanyCustomerFileTypeLocal> observableMapByLocal = FXCollections
.observableMap(fileTypeService.findAll(getLocale()));
fileTable_typeColumn.setCellValueFactory(param -> Bindings.valueAt(observableMapByLocal,
param.getValue().getType()).map(BaseEnumEntity::getValue));
@@ -150,7 +159,8 @@ public class CustomerTabSkinFile
CompanyCustomerFileType fileType = item.getType().get();
if (fileType == CompanyCustomerFileType.EvaluationForm) {
// 文件不是 Excel 文件时打开编辑UI
if (!CompanyFileUtils.withExtensions(item.getFilePath().get(), CompanyFileUtils.XLS, CompanyFileUtils.XLSX)) {
if (!FileUtils.withExtensions(item.getFilePath().get(), FileUtils.XLS,
FileUtils.XLSX)) {
CompanyCustomerEvaluationFormFileWindowController.show(item, controller.root.getScene().getWindow());
return;
}
@@ -175,12 +185,14 @@ public class CustomerTabSkinFile
return;
}
CompanyCustomer companyCustomer = getParent();
LocalDate nextSignDate = getCompanyCustomerFileService().getNextSignDate(companyCustomer, this::setStatus);
LocalDate nextSignDate = getCompanyCustomerFileService().getNextSignDate(companyCustomer,
((level, message) -> setStatus(message)));
if (nextSignDate != null && files.size() == 1) {
File file = files.getFirst();
String fileName = file.getName();
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);
File dest = new File(dir, destFileName);
if (file.renameTo(dest)) {
@@ -195,7 +207,8 @@ public class CustomerTabSkinFile
CompanyCustomerFileViewModel model = new CompanyCustomerFileViewModel();
model.update(saved);
dataSet.add(model);
CompanyCustomerEvaluationFormFileWindowController.show(model, getTableView().getScene().getWindow());
CompanyCustomerEvaluationFormFileWindowController.show(model,
getTableView().getScene().getWindow());
});
return;
}
@@ -203,7 +216,6 @@ public class CustomerTabSkinFile
}
List<CompanyCustomerFile> companyCustomerFiles = new ArrayList<>();
for (File file : files) {
File dest = new File(dir, file.getName());
if (file.renameTo(dest)) {
@@ -212,12 +224,9 @@ public class CustomerTabSkinFile
ccf.setType(CompanyCustomerFileType.General);
ccf.setFilePath(dest.getAbsolutePath());
ccf.setValid(false);
companyCustomerFiles.add(ccf);
getCompanyCustomerFileService().save(ccf);
}
}
getCompanyCustomerFileService().saveAll(companyCustomerFiles);
loadTableDataSet();
}
@@ -226,7 +235,7 @@ public class CustomerTabSkinFile
CompanyCustomerService customerService = getCompanyCustomerService();
try {
CompanyCustomer companyCustomer = customerService.findById(viewModel.getId().get());
if (customerService.reBuildingFiles(companyCustomer, this::setStatus)) {
if (customerService.reBuildingFiles(companyCustomer, (level, message) -> setStatus(message))) {
loadTableDataSet();
}
} catch (Exception e) {
@@ -270,13 +279,12 @@ public class CustomerTabSkinFile
return false;
}
public void onFileTableMoveToCompanyPathAction(ActionEvent event) {
Company company = viewModel.getCompany().get();
if (!Hibernate.isInitialized(company)) {
if (!ProxyUtils.isInitialized(company)) {
company = getCompanyService().findById(company.getId());
viewModel.getCompany().set(company);
}
viewModel.getCompany().set(company);
if (!StringUtils.hasText(company.getPath())) {
setStatus("公司目录未设置");
@@ -318,11 +326,10 @@ public class CustomerTabSkinFile
deleteRow(selectedItem);
// getCompanyCustomerService().deleteFileById(selectedItem.getId().get());
// dataSet.remove(selectedItem);
// getCompanyCustomerService().deleteFileById(selectedItem.getId().get());
// dataSet.remove(selectedItem);
}
private void initializeTask(Task<Object> task, String prefix, Consumer<String> consumer) {
task.setOnScheduled(e -> {
consumer.accept("正在" + prefix + ",请稍后...");
@@ -351,11 +358,10 @@ public class CustomerTabSkinFile
loadTableDataSet();
}
public void onCalcNextSignDateAction(ActionEvent event) {
UITools.showDialogAndWait("计算客户下一个评价日期", "依据已有的客户评估表和登记采购的合同计算下一个评估日期", ds -> {
CompanyCustomer companyCustomer = getCompanyCustomerService().findById(viewModel.getId().get());
LocalDate nextSignDate = getCompanyCustomerFileService().getNextSignDate(companyCustomer, msg -> {
LocalDate nextSignDate = getCompanyCustomerFileService().getNextSignDate(companyCustomer, (level, msg) -> {
Platform.runLater(() -> {
ds.add(msg);
});
@@ -368,7 +374,6 @@ public class CustomerTabSkinFile
});
}
class FileTableFilePathTableCell extends TableCell<CompanyCustomerFileViewModel, String> {
@Override
protected void updateItem(String item, boolean empty) {
@@ -388,7 +393,6 @@ public class CustomerTabSkinFile
}
}
private CompanyCustomerFileService getCompanyCustomerFileService() {
if (companyCustomerFileService == null) {
companyCustomerFileService = SpringApp.getBean(CompanyCustomerFileService.class);

View File

@@ -1,29 +1,29 @@
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.model.CompanyCustomer;
import com.ecep.contract.model.CustomerCatalog;
import com.ecep.contract.model.CustomerSatisfactionSurvey;
import com.ecep.contract.model.Employee;
import com.ecep.contract.model.Project;
import com.ecep.contract.service.CustomerSatisfactionSurveyService;
import com.ecep.contract.service.ProjectService;
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.Tab;
import javafx.scene.control.TableColumn;
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")
public class CustomerTabSkinSatisfactionSurvey
@@ -41,8 +41,8 @@ public class CustomerTabSkinSatisfactionSurvey
public MenuItem entityTable_menu_refresh;
public MenuItem entityTable_menu_del;
@Setter
private ProjectService projectService;
@Setter
private ProjectService projectService;
@Setter
private CustomerSatisfactionSurveyService satisfactionSurveyService;
@@ -55,7 +55,6 @@ private ProjectService projectService;
return controller.satisfactionTab;
}
@Override
public void initializeTab() {
super.initializeTab();
@@ -75,10 +74,9 @@ private ProjectService projectService;
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()));
converter.setInitialized(v -> getCachedBean(CustomerCatalogService.class).findById(v.getId()));
column.setCellValueFactory(param -> param.getValue().getCatalog().map(converter::toString));
}
@@ -102,14 +100,10 @@ private ProjectService projectService;
}
@Override
public Specification<CustomerSatisfactionSurvey> getSpecification(CompanyCustomer parent) {
return SpecificationUtils.and(getSpecification(), (root, query, builder) -> {
Company company = parent.getCompany();
if (company == null) {
return null;
}
return builder.equal(root.get("project").get("customer"), company);
});
public Map<String, Object> getSpecification(CompanyCustomer parent) {
Map<String, Object> params = getSpecification();
params.put("project.customer", parent.getId());
return params;
}
@Override

View File

@@ -1,20 +1,28 @@
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.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.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.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.model.SalesOrder;
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
@Scope("prototype")
@Component
@@ -41,19 +49,6 @@ public class SalesOrderWindowController extends AbstEntityController<SalesOrder,
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
public void show(Stage stage) {
super.show(stage);
@@ -69,6 +64,6 @@ public class SalesOrderWindowController extends AbstEntityController<SalesOrder,
@Override
public SaleOrdersService getViewModelService() {
return service;
return getCachedBean(SaleOrdersService.class);
}
}

View File

@@ -1,22 +1,24 @@
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.converter.EmployeeStringConverter;
import com.ecep.contract.model.Department;
import com.ecep.contract.model.Employee;
import com.ecep.contract.util.ParamUtils;
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.event.ActionEvent;
import javafx.scene.control.TableColumn;
import javafx.scene.control.cell.CheckBoxTableCell;
import javafx.scene.control.cell.ComboBoxTableCell;
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
extends AbstEntityManagerSkin<Department, DepartmentViewModel, DepartmentManagerSkin, DepartmentManagerWindowController>
@@ -31,10 +33,7 @@ public class DepartmentManagerSkin
public void initializeTable() {
getTableView().setEditable(true);
Specification<Employee> spec = (root, query, cb) -> {
return cb.equal(root.get("isActive"), true);
};
List<Employee> employees = controller.getEmployeeService().findAll(spec, Pageable.ofSize(30)).getContent();
List<Employee> employees = controller.getEmployeeService().findAll(ParamUtils.equal("isActive", true), Pageable.ofSize(30)).getContent();
controller.idColumn.setCellValueFactory(param -> param.getValue().getId());

View File

@@ -1,20 +1,22 @@
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.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import com.ecep.contract.controller.AbstManagerWindowController;
import com.ecep.contract.model.Department;
import com.ecep.contract.model.Employee;
import com.ecep.contract.service.DepartmentService;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.vm.DepartmentViewModel;
import javafx.event.ActionEvent;
import javafx.scene.control.TableColumn;
import javafx.stage.Stage;
@Lazy
@Scope("prototype")
@Component

View File

@@ -1,12 +1,13 @@
package com.ecep.contract.manager.ds.other.controller.employee;
package com.ecep.contract.controller.employee;
import com.ecep.contract.controller.tab.AbstEntityBasedTabSkin;
import com.ecep.contract.controller.tab.TabSkin;
import com.ecep.contract.model.Employee;
import com.ecep.contract.service.EmployeeRoleService;
import com.ecep.contract.service.EmployeeService;
import com.ecep.contract.service.PermissionService;
import com.ecep.contract.vm.EmployeeViewModel;
import com.ecep.contract.manager.ds.other.model.Employee;
import com.ecep.contract.manager.ds.other.service.EmployeeRoleService;
import com.ecep.contract.manager.ds.other.service.EmployeeService;
import com.ecep.contract.manager.ds.other.service.PermissionService;
import com.ecep.contract.manager.ds.other.vo.EmployeeViewModel;
import com.ecep.contract.manager.ui.tab.AbstEntityBasedTabSkin;
import com.ecep.contract.manager.ui.tab.TabSkin;
import lombok.Setter;
public abstract class AbstEmployeeBasedTabSkin

View File

@@ -0,0 +1,42 @@
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.vm.EmployeeBasedViewModel;
import com.ecep.contract.vm.EmployeeViewModel;
import com.ecep.contract.vm.IdentityViewModel;
public abstract class AbstEmployeeTableTabSkin<T extends IdentityEntity, TV extends IdentityViewModel<T>>
extends AbstEntityTableTabSkin<EmployeeWindowController, Employee, 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());
}
return model;
}
@Override
public Map<String, Object> getSpecification(Employee parent) {
Map<String, Object> params = getSpecification();
params.put("employee", parent.getId());
return params;
}
}

View File

@@ -1,17 +1,16 @@
package com.ecep.contract.manager.ds.other.controller.employee;
package com.ecep.contract.controller.employee;
import java.util.Map;
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.vm.EmployeeViewModel;
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.scene.control.cell.CheckBoxTableCell;
import org.springframework.data.jpa.domain.Specification;
public class EmployeeManagerSkin
extends AbstEntityManagerSkin<Employee, EmployeeViewModel, EmployeeManagerSkin, EmployeeManagerWindowController>
@@ -30,14 +29,12 @@ public class EmployeeManagerSkin
}
@Override
public Specification<Employee> getSpecification() {
Specification<Employee> spec = super.getSpecification();
public Map<String, Object> getSpecification() {
Map<String, Object> params = super.getSpecification();
if (controller.activeCheckBox.isSelected()) {
spec = SpecificationUtils.and(spec, (root, query, builder) -> {
return builder.isTrue(root.get("isActive"));
});
params.put("isActive", true);
}
return spec;
return params;
}
@Override
@@ -51,7 +48,6 @@ public class EmployeeManagerSkin
controller.departmentColumn.setCellValueFactory(param -> param.getValue().getDepartment());
controller.departmentColumn.setCellFactory(param -> new DepartmentTableCell<>(getDepartmentService()));
controller.emailColumn.setCellValueFactory(param -> param.getValue().getEmail());
controller.createdColumn.setCellValueFactory(param -> param.getValue().getCreated());
controller.entryDateColumn.setCellValueFactory(param -> param.getValue().getEntryDate());

View File

@@ -1,25 +1,26 @@
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.model.Employee;
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.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.fxml.FXML;
import javafx.scene.control.CheckBox;
import javafx.scene.control.TableColumn;
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
@Scope("prototype")
@@ -68,8 +69,8 @@ public class EmployeeManagerWindowController
* U8系统 同步员工数据
*/
public void onSyncFromU8Action(ActionEvent event) {
Task<Object> task = new EmployeesSyncTask();
UITools.showTaskDialogAndWait("" + YongYouU8Service.NAME + " 同步员工数据", task, null);
EmployeesSyncTask task = new EmployeesSyncTask();
UITools.showTaskDialogAndWait("" + CloudServiceConstant.U8_NAME + " 同步员工数据", task, null);
}

View File

@@ -1,21 +1,23 @@
package com.ecep.contract.manager.ds.other.controller.employee;
package com.ecep.contract.controller.employee;
import java.time.LocalDateTime;
import java.util.List;
import org.springframework.data.domain.Sort;
import com.ecep.contract.controller.table.cell.EmployeeTableCell;
import com.ecep.contract.model.Employee;
import com.ecep.contract.model.EmployeeAuthBind;
import com.ecep.contract.service.EmployeeAuthBindService;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.vm.EmployeeAuthBindViewModel;
import com.ecep.contract.manager.ds.other.model.Employee;
import com.ecep.contract.manager.ds.other.model.EmployeeAuthBind;
import com.ecep.contract.manager.ds.other.service.EmployeeAuthBindService;
import com.ecep.contract.manager.ds.other.vo.EmployeeAuthBindViewModel;
import com.ecep.contract.manager.ui.FxmlPath;
import com.ecep.contract.manager.ui.table.cell.EmployeeTableCell;
import javafx.application.Platform;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.Tab;
import javafx.scene.control.TableColumn;
import lombok.Setter;
import org.springframework.data.domain.Sort;
import java.time.LocalDateTime;
import java.util.List;
@FxmlPath("/ui/employee/employee-auth-bind.fxml")
public class EmployeeTabSkinAuthBind
@@ -81,7 +83,7 @@ public class EmployeeTabSkinAuthBind
MenuItem menuItem = new MenuItem("导入未关联");
menuItem.setOnAction(event -> {
EmployeeAuthBindService service = getEmployeeAuthBindService();
List<EmployeeAuthBind> authBinds = service.findAllByEmployee(null, Sort.unsorted());
List<EmployeeAuthBind> authBinds = service.findAllByEmployee(null);
for (EmployeeAuthBind authBind : authBinds) {
authBind.setEmployee(getEntity());
authBind.setUpdateTime(LocalDateTime.now());

View File

@@ -1,15 +1,16 @@
package com.ecep.contract.manager.ds.other.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;
package com.ecep.contract.controller.employee;
import java.time.format.DateTimeFormatter;
import com.ecep.contract.controller.tab.TabSkin;
import com.ecep.contract.converter.EntityStringConverter;
import com.ecep.contract.model.Department;
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
extends AbstEmployeeBasedTabSkin
implements TabSkin {

View File

@@ -1,17 +1,18 @@
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.model.EmployeeLoginHistory;
import com.ecep.contract.service.EmployeeLoginHistoryService;
import com.ecep.contract.util.FxmlPath;
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.scene.control.Tab;
import javafx.scene.control.TableColumn;
import java.time.LocalDateTime;
@FxmlPath("/ui/employee/employee-login-history.fxml")
public class EmployeeTabSkinLoginHistory
extends AbstEmployeeTableTabSkin<EmployeeLoginHistory, EmployeeLoginHistoryViewModel>

View File

@@ -1,17 +1,17 @@
package com.ecep.contract.manager.ds.other.controller.employee;
package com.ecep.contract.controller.employee;
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 com.ecep.contract.controller.tab.TabSkin;
import com.ecep.contract.model.Employee;
import com.ecep.contract.model.EmployeeRole;
import com.ecep.contract.service.EmployeeRoleService;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.collections.ListChangeListener;
import javafx.scene.control.ListCell;
import javafx.scene.control.Tab;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import java.util.HashMap;
import java.util.List;
public class EmployeeTabSkinRole
@@ -48,11 +48,8 @@ public class EmployeeTabSkinRole
private void initializeListView() {
// 非系统内置账户
Specification<EmployeeRole> spec = null;
if (!Desktop.instance.getActiveEmployee().isSystemAdministrator()) {
spec = (root, query, cb) -> cb.equal(root.get("systemAdministrator"), false);
}
List<EmployeeRole> roles = getEmployeeRoleService().findAll(spec, Pageable.ofSize(500)).getContent();
HashMap<String, Object> params = new HashMap<>();
List<EmployeeRole> roles = getEmployeeRoleService().findAll(params, Pageable.ofSize(500)).getContent();
controller.rolesField.getSourceItems().setAll(roles);
controller.rolesField.setCellFactory(param -> {

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.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -21,6 +8,24 @@ import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import com.ecep.contract.controller.AbstEntityController;
import com.ecep.contract.model.Employee;
import com.ecep.contract.model.EmployeeRole;
import com.ecep.contract.service.EmployeeService;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.vm.EmployeeViewModel;
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
@Scope("prototype")
@Component

View File

@@ -1,16 +1,17 @@
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.LocalDateFieldTableCell;
import com.ecep.contract.controller.table.cell.LocalDateTimeTableCell;
import com.ecep.contract.converter.EntityStringConverter;
import com.ecep.contract.model.Inventory;
import com.ecep.contract.model.InventoryCatalog;
import com.ecep.contract.service.InventoryCatalogService;
import com.ecep.contract.service.InventoryService;
import com.ecep.contract.vm.InventoryViewModel;
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.event.ActionEvent;
import javafx.scene.control.TableColumn;
@@ -19,11 +20,8 @@ import javafx.util.converter.CurrencyStringConverter;
import javafx.util.converter.NumberStringConverter;
import lombok.Setter;
import java.util.function.Function;
public class InventoryManagerSkin
extends AbstEntityManagerSkin<Inventory, InventoryViewModel, InventoryManagerSkin, InventoryManagerWindowController>
implements ManagerSkin, EditableEntityTableTabSkin<Inventory, InventoryViewModel> {
public class InventoryManagerSkin extends
AbstEntityManagerSkin<Inventory, InventoryViewModel, InventoryManagerSkin, InventoryManagerWindowController> {
@Setter
private InventoryCatalogService catalogService;
@@ -69,7 +67,8 @@ public class InventoryManagerSkin
controller.specificationColumn.setCellValueFactory(param -> param.getValue().getSpecification());
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.setCellFactory(TextFieldTableCell.forTableColumn());
@@ -77,44 +76,48 @@ public class InventoryManagerSkin
controller.purchaseTaxRateColumn.setCellValueFactory(param -> param.getValue().getPurchaseTaxRate());
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.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.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.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.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.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.setCellFactory(TextFieldTableCell.forTableColumn());
controller.descriptionColumn.setOnEditCommit(event -> onColumnEditCommit(event, InventoryViewModel::getDescription));
controller.descriptionColumn
.setOnEditCommit(event -> onColumnEditCommit(event, InventoryViewModel::getDescription));
}
private <T> void onColumnEditCommit(
TableColumn.CellEditEvent<InventoryViewModel, T> event,
Function<InventoryViewModel, Property<T>> supplier
) {
Function<InventoryViewModel, Property<T>> supplier) {
InventoryViewModel row = event.getRowValue();
supplier.apply(row).setValue(event.getNewValue());
saveRowData(row);
}
@Override
protected void onTableRowDoubleClickedAction(InventoryViewModel item) {
showInOwner(InventoryWindowController.class, item);

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.LocalDateTime;
@@ -8,13 +8,14 @@ import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
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.InventoryService;
import com.ecep.contract.manager.ds.other.vo.InventoryViewModel;
import com.ecep.contract.manager.ui.AbstManagerWindowController;
import com.ecep.contract.manager.ui.FxmlPath;
import com.ecep.contract.manager.util.UITools;
import com.ecep.contract.controller.AbstManagerWindowController;
import com.ecep.contract.model.Inventory;
import com.ecep.contract.model.InventoryCatalog;
import com.ecep.contract.service.InventoryService;
import com.ecep.contract.task.InventorySyncTask;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vm.InventoryViewModel;
import javafx.event.ActionEvent;
import javafx.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.model.Inventory;
import com.ecep.contract.model.InventoryCatalog;
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.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.property.SimpleDoubleProperty;
import javafx.event.ActionEvent;
@@ -23,37 +29,21 @@ import javafx.util.converter.CurrencyStringConverter;
import javafx.util.converter.LocalDateStringConverter;
import javafx.util.converter.LocalDateTimeStringConverter;
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
extends AbstEntityBasedTabSkin<InventoryWindowController, Inventory, InventoryViewModel>
implements TabSkin, EditableEntityTableTabSkin<Inventory, InventoryViewModel> {
@Setter
private InventoryService service;
@Setter
private InventoryCatalogService catalogService;
public InventoryTabSkinBase(InventoryWindowController controller) {
super(controller);
}
InventoryService getService() {
if (service == null) {
service = getBean(InventoryService.class);
}
return service;
return getCachedBean(InventoryService.class);
}
InventoryCatalogService getCatalogService() {
if (catalogService == null) {
catalogService = getBean(InventoryCatalogService.class);
}
return catalogService;
return getCachedBean(InventoryCatalogService.class);
}
@Override
@@ -84,65 +74,83 @@ public class InventoryTabSkinBase
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.purchaseTaxPriceField, viewModel.getPurchaseTaxPrice(), currencyStringConverter, viewModel::updatePurchaseTaxPrice);
bindPriceField(controller.purchasePriceField, viewModel.getPurchasePrice(), currencyStringConverter,
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.saleTaxPriceField, viewModel.getSaleTaxPrice(), currencyStringConverter, viewModel::updateSaleTaxPrice);
bindPriceField(controller.salePriceField, viewModel.getSalePrice(), currencyStringConverter,
viewModel::updateSalePrice);
bindPriceField(controller.saleTaxPriceField, viewModel.getSaleTaxPrice(), currencyStringConverter,
viewModel::updateSaleTaxPrice);
// 采购价不能大于销售价
Bindings.greaterThan(viewModel.getPurchasePrice(), viewModel.getSalePrice()).addListener((observable, oldValue, newValue) -> {
if (newValue) {
controller.purchasePriceField.getStyleClass().add("error");
controller.salePriceField.getStyleClass().add("error");
} else {
controller.purchasePriceField.getStyleClass().remove("error");
controller.salePriceField.getStyleClass().remove("error");
}
});
Bindings.greaterThan(viewModel.getPurchaseTaxPrice(), viewModel.getSaleTaxPrice()).addListener((observable, oldValue, newValue) -> {
if (newValue) {
controller.purchaseTaxPriceField.getStyleClass().add("error");
controller.saleTaxPriceField.getStyleClass().add("error");
} else {
controller.purchaseTaxPriceField.getStyleClass().remove("error");
controller.saleTaxPriceField.getStyleClass().remove("error");
}
});
Bindings.greaterThan(viewModel.getPurchasePrice(), viewModel.getSalePrice())
.addListener((observable, oldValue, newValue) -> {
if (newValue) {
controller.purchasePriceField.getStyleClass().add("error");
controller.salePriceField.getStyleClass().add("error");
} else {
controller.purchasePriceField.getStyleClass().remove("error");
controller.salePriceField.getStyleClass().remove("error");
}
});
Bindings.greaterThan(viewModel.getPurchaseTaxPrice(), viewModel.getSaleTaxPrice())
.addListener((observable, oldValue, newValue) -> {
if (newValue) {
controller.purchaseTaxPriceField.getStyleClass().add("error");
controller.saleTaxPriceField.getStyleClass().add("error");
} else {
controller.purchaseTaxPriceField.getStyleClass().remove("error");
controller.saleTaxPriceField.getStyleClass().remove("error");
}
});
EmployeeStringConverter employeeStringConverter = getBean(EmployeeStringConverter.class);
UITools.autoCompletion(controller.creatorField, viewModel.getCreator(), employeeStringConverter);
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));
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.sizeUnitField.textProperty().bindBidirectional(viewModel.getSizeUnit());
controller.volumeUnitField.textProperty().bindBidirectional(viewModel.getVolumeUnit());
controller.weightField.textProperty().bindBidirectional(viewModel.getWeight(), new NumberStringConverter());
controller.packagedWeightField.textProperty().bindBidirectional(viewModel.getPackagedWeight(), new NumberStringConverter());
controller.sizeLengthField.textProperty().bindBidirectional(viewModel.getSizeLength(), new NumberStringConverter());
controller.sizeWidthField.textProperty().bindBidirectional(viewModel.getSizeWidth(), new NumberStringConverter());
controller.sizeHeightField.textProperty().bindBidirectional(viewModel.getSizeHeight(), new NumberStringConverter());
controller.packagedWeightField.textProperty().bindBidirectional(viewModel.getPackagedWeight(),
new NumberStringConverter());
controller.sizeLengthField.textProperty().bindBidirectional(viewModel.getSizeLength(),
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.packagedSizeLengthField.textProperty().bindBidirectional(viewModel.getPackagedSizeLength(), new NumberStringConverter());
controller.packagedSizeWidthField.textProperty().bindBidirectional(viewModel.getPackagedSizeWidth(), new NumberStringConverter());
controller.packagedSizeHeightField.textProperty().bindBidirectional(viewModel.getPackagedSizeHeight(), new NumberStringConverter());
controller.packagedVolumeField.textProperty().bindBidirectional(viewModel.getPackagedVolume(), new NumberStringConverter());
controller.packagedSizeLengthField.textProperty().bindBidirectional(viewModel.getPackagedSizeLength(),
new NumberStringConverter());
controller.packagedSizeWidthField.textProperty().bindBidirectional(viewModel.getPackagedSizeWidth(),
new NumberStringConverter());
controller.packagedSizeHeightField.textProperty().bindBidirectional(viewModel.getPackagedSizeHeight(),
new NumberStringConverter());
controller.packagedVolumeField.textProperty().bindBidirectional(viewModel.getPackagedVolume(),
new NumberStringConverter());
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()));
property.addListener((observable, oldValue, newValue) -> {
textField.setText(stringConverter.toString(newValue));
@@ -165,15 +173,8 @@ public class InventoryTabSkinBase
return;
}
setStatus("正在同步数据...");
InventoryCtx ctx = new InventoryCtx();
MessageHolder holder = (lv, msg) -> setStatus(msg);
ctx.initializeRepository(holder);
if (ctx.syncInventoryDetailByCode(inventory, inventory.getCode(), holder)) {
save(inventory);
setStatus("同步数据完成.");
} else {
setStatus("没有数据更新.");
}
getService().syncInventory(inventory, holder);
}

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 java.util.Map;
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.model.Contract;
import com.ecep.contract.model.Inventory;
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.vm.ContractViewModel;
import com.ecep.contract.vm.InventoryViewModel;
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.MenuItem;
import javafx.scene.control.Tab;
import javafx.scene.control.TableColumn;
import javafx.util.converter.CurrencyStringConverter;
import lombok.Setter;
import org.springframework.data.jpa.domain.Specification;
import java.text.NumberFormat;
import java.time.LocalDate;
@FxmlPath("/ui/inventory/inventory-contract.fxml")
public class InventoryTabSkinContracts
extends AbstEntityTableTabSkin<InventoryWindowController, Inventory, InventoryViewModel, Contract, ContractViewModel>
extends
AbstEntityTableTabSkin<InventoryWindowController, Inventory, InventoryViewModel, Contract, ContractViewModel>
implements TabSkin {
public TableColumn<ContractViewModel, Number> idColumn;
public TableColumn<ContractViewModel, String> nameColumn;
@@ -77,7 +75,6 @@ public class InventoryTabSkinContracts
return controller.contractsTab;
}
@Override
public void initializeTable() {
super.initializeTable();
@@ -93,18 +90,22 @@ public class InventoryTabSkinContracts
}
@Override
public Specification<Contract> getSpecification(Inventory parent) {
return SpecificationUtils.and(getSpecification(), (root, query, builder) -> {
// 创建ContractItem的子查询
Subquery<Integer> subquery = query.subquery(Integer.class);
Root<ContractItem> from = subquery.from(ContractItem.class);
// 子查询选择与指定库存相关的合同ID
subquery.select(from.get("contract").get("id"))
.where(builder.equal(from.get("inventory"), parent));
public Map<String, Object> getSpecification(Inventory parent) {
Map<String, Object> params = getSpecification();
params.put("inventory", parent);
// 主查询筛选ID在子查询结果中的合同
return builder.in(root.get("id")).value(subquery);
});
// return SpecificationUtils.and(getSpecification(), (root, query, builder) -> {
// // 创建ContractItem的子查询
// Subquery<Integer> subquery = query.subquery(Integer.class);
// 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);
// });
return params;
}
@Override

View File

@@ -1,28 +1,4 @@
package com.ecep.contract.manager.ds.other.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;
package com.ecep.contract.controller.inventory;
import java.text.NumberFormat;
import java.time.MonthDay;
@@ -30,11 +6,41 @@ import java.time.Year;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import com.ecep.contract.util.ProxyUtils;
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.vm.InventoryHistoryPriceViewModel;
import com.ecep.contract.vm.InventoryViewModel;
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;
import lombok.Setter;
@FxmlPath("/ui/inventory/inventory-history-price.fxml")
public class InventoryTabSkinHistoryPrice
extends AbstEntityTableTabSkin<InventoryWindowController, Inventory, InventoryViewModel, InventoryHistoryPrice, InventoryHistoryPriceViewModel>
extends
AbstEntityTableTabSkin<InventoryWindowController, Inventory, InventoryViewModel, InventoryHistoryPrice, InventoryHistoryPriceViewModel>
implements TabSkin {
public Button refreshBtn;
public TableColumn<InventoryHistoryPriceViewModel, Number> idColumn;
@@ -66,42 +72,25 @@ public class InventoryTabSkinHistoryPrice
public TableColumn<InventoryHistoryPriceViewModel, Number> miniPurchaseTaxPriceColumn;
public TableColumn<InventoryHistoryPriceViewModel, MonthDay> miniPurchasePriceDateColumn;
@Setter
InventoryHistoryPriceService service;
@Setter
ContractService contractService;
@Setter
ContractItemService contractItemService;
public InventoryTabSkinHistoryPrice(InventoryWindowController controller) {
super(controller);
}
@Override
protected InventoryHistoryPriceService getViewModelService() {
return getService();
return getHistoryPriceService();
}
InventoryHistoryPriceService getService() {
if (service == null) {
service = getBean(InventoryHistoryPriceService.class);
}
return service;
InventoryHistoryPriceService getHistoryPriceService() {
return getCachedBean(InventoryHistoryPriceService.class);
}
ContractItemService getContractItemService() {
if (contractItemService == null) {
contractItemService = getBean(ContractItemService.class);
}
return contractItemService;
return getCachedBean(ContractItemService.class);
}
ContractService getContractService() {
if (contractService == null) {
contractService = getBean(ContractService.class);
}
return contractService;
return getCachedBean(ContractService.class);
}
@Override
@@ -109,7 +98,6 @@ public class InventoryTabSkinHistoryPrice
return controller.historyPriceTab;
}
@Override
public void initializeTable() {
super.initializeTable();
@@ -178,18 +166,17 @@ public class InventoryTabSkinHistoryPrice
HashMap<Integer, InventoryHistoryPrice> historyPriceMap = new HashMap<>();
for (InventoryHistoryPrice historyPrice : getService().findAllByInventory(getParent())) {
for (InventoryHistoryPrice historyPrice : getHistoryPriceService().findAllByInventory(getParent())) {
InventoryHistoryPrice oldValue = historyPriceMap.put(historyPrice.getYear().getValue(), historyPrice);
if (oldValue != null) {
getService().delete(oldValue);
getHistoryPriceService().delete(oldValue);
}
}
List<ContractItem> items = getContractItemService().findAllByInventory(getParent());
items.stream().collect(Collectors.groupingBy(v -> {
Contract contract = v.getContract();
if (!Hibernate.isInitialized(contract)) {
if (!ProxyUtils.isInitialized(contract)) {
contract = getContractService().findById(contract.getId());
v.setContract(contract);
}
@@ -213,8 +200,10 @@ public class InventoryTabSkinHistoryPrice
return contract.getSetupDate();
})).ifPresent(v -> update(historyPrice.getLatestSalePrice(), v));
list.stream().max(Comparator.comparing(ContractItem::getTaxPrice)).ifPresent(v -> update(historyPrice.getMaxSalePrice(), v));
list.stream().min(Comparator.comparing(ContractItem::getTaxPrice)).ifPresent(v -> update(historyPrice.getMiniSalePrice(), v));
list.stream().max(Comparator.comparing(ContractItem::getTaxPrice))
.ifPresent(v -> update(historyPrice.getMaxSalePrice(), v));
list.stream().min(Comparator.comparing(ContractItem::getTaxPrice))
.ifPresent(v -> update(historyPrice.getMiniSalePrice(), v));
} else if (ContractPayWay.PAY.equals(payWay)) {
// 采购
@@ -223,13 +212,15 @@ public class InventoryTabSkinHistoryPrice
return contract.getSetupDate();
})).ifPresent(v -> update(historyPrice.getLatestPurchasePrice(), v));
list.stream().max(Comparator.comparing(ContractItem::getTaxPrice)).ifPresent(v -> update(historyPrice.getMaxPurchasePrice(), v));
list.stream().min(Comparator.comparing(ContractItem::getTaxPrice)).ifPresent(v -> update(historyPrice.getMiniPurchasePrice(), v));
list.stream().max(Comparator.comparing(ContractItem::getTaxPrice))
.ifPresent(v -> update(historyPrice.getMaxPurchasePrice(), v));
list.stream().min(Comparator.comparing(ContractItem::getTaxPrice))
.ifPresent(v -> update(historyPrice.getMiniPurchasePrice(), v));
} else {
}
});
getService().save(historyPrice);
getHistoryPriceService().save(historyPrice);
});
loadTableDataSet();
@@ -246,7 +237,7 @@ public class InventoryTabSkinHistoryPrice
}
getContractService();
Contract contract = item.getContract();
if (!Hibernate.isInitialized(contract)) {
if (!ProxyUtils.isInitialized(contract)) {
contract = getContractService().findById(contract.getId());
item.setContract(contract);
}
@@ -257,10 +248,10 @@ public class InventoryTabSkinHistoryPrice
}
@Override
public Specification<InventoryHistoryPrice> getSpecification(Inventory parent) {
return SpecificationUtils.and(getSpecification(), (root, query, builder) -> {
return builder.equal(root.get("inventory"), parent);
});
public Map<String, Object> getSpecification(Inventory parent) {
Map<String, Object> params = getSpecification();
params.put("inventory", parent.getId());
return params;
}
@Override

View File

@@ -1,20 +1,27 @@
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.Scope;
import org.springframework.stereotype.Component;
import com.ecep.contract.controller.AbstEntityController;
import com.ecep.contract.model.Inventory;
import com.ecep.contract.service.InventoryService;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.vm.InventoryViewModel;
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
@Scope("prototype")
@Component
@@ -31,7 +38,6 @@ public class InventoryWindowController extends AbstEntityController<Inventory, I
@FXML
public Tab contractsTab;
@FXML
public TextField nameField;
@FXML
@@ -97,27 +103,16 @@ public class InventoryWindowController extends AbstEntityController<Inventory, I
@FXML
public TextField packagedVolumeField;
@Autowired
private InventoryService service;
@Override
public void onShown(WindowEvent 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");
}
@Override
protected Inventory loadEntity() {
return service.findById(viewModel.getId().get());
}
@Override
protected Inventory saveEntity(Inventory entity) {
return service.save(entity);
}
@Override
protected void registerTabSkins() {
registerTabSkin(baseInfoTab, tab -> new InventoryTabSkinBase(this));
@@ -127,6 +122,6 @@ public class InventoryWindowController extends AbstEntityController<Inventory, I
@Override
public InventoryService getViewModelService() {
return service;
return getCachedBean(InventoryService.class);
}
}

View File

@@ -0,0 +1,30 @@
package com.ecep.contract.controller.permission;
import com.ecep.contract.controller.tab.AbstEntityBasedTabSkin;
import com.ecep.contract.model.EmployeeRole;
import com.ecep.contract.service.EmployeeRoleService;
import com.ecep.contract.service.FunctionService;
import com.ecep.contract.service.PermissionService;
import com.ecep.contract.vm.EmployeeRoleViewModel;
public abstract class AbstEmployeeRoleBasedTabSkin
extends AbstEntityBasedTabSkin<EmployeeRoleWindowController, EmployeeRole, 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.context.annotation.Description;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import com.ecep.contract.controller.AbstManagerWindowController;
import com.ecep.contract.model.Function;
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 javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.TableColumn;
import javafx.stage.Stage;
@Lazy
@Scope("prototype")

View File

@@ -1,16 +1,18 @@
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.model.EmployeeRole;
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 lombok.Setter;
public class EmployeeRoleManagerSkin
extends AbstEntityManagerSkin<EmployeeRole, EmployeeRoleViewModel, EmployeeRoleManagerSkin, EmployeeRoleManagerWindowController>
extends
AbstEntityManagerSkin<EmployeeRole, EmployeeRoleViewModel, EmployeeRoleManagerSkin, EmployeeRoleManagerWindowController>
implements ManagerSkin, EditableEntityTableTabSkin<EmployeeRole, EmployeeRoleViewModel> {
@Setter

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.LoggerFactory;
@@ -7,15 +7,14 @@ import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
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.AbstManagerWindowController;
import com.ecep.contract.manager.ui.FxmlPath;
import com.ecep.contract.controller.AbstManagerWindowController;
import com.ecep.contract.model.EmployeeRole;
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 javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.TableColumn;
import javafx.stage.Stage;

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;
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 org.controlsfx.control.ListSelectionView;
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.manager.ds.other.model.Function;
import com.ecep.contract.model.EmployeeRole;
import com.ecep.contract.model.Function;
import com.ecep.contract.util.ParamUtils;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.collections.ListChangeListener;
@@ -59,8 +59,8 @@ public class EmployeeRoleTabSkinFunctions extends AbstEmployeeRoleBasedTabSkin {
private void initializeListView() {
// 非系统内置账户
Specification<Function> spec = (root, query, cb) -> cb.equal(root.get("active"), true);
List<Function> roles = getFunctionService().findAll(spec, Pageable.ofSize(500)).getContent();
List<Function> roles = getFunctionService()
.findAll(ParamUtils.builder().equals("active", true).build(), Pageable.ofSize(500)).getContent();
functionsField.getSourceItems().setAll(roles);
functionsField.setCellFactory(param -> {

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.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -21,6 +8,24 @@ import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import com.ecep.contract.controller.AbstEntityController;
import com.ecep.contract.model.EmployeeRole;
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 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
@Scope("prototype")
@@ -53,7 +58,7 @@ public class EmployeeRoleWindowController extends AbstEntityController<EmployeeR
*/
public Tab functionsTab;
public ListSelectionView<com.ecep.contract.manager.ds.other.model.Function> functionsField;
public ListSelectionView<com.ecep.contract.model.Function> functionsField;
/*
@@ -66,17 +71,6 @@ public class EmployeeRoleWindowController extends AbstEntityController<EmployeeR
@Autowired
EmployeeRoleService employeeRoleService;
@Override
protected EmployeeRole loadEntity() {
return employeeRoleService.findById(viewModel.getId().get());
}
@Override
protected EmployeeRole saveEntity(EmployeeRole role) {
return employeeRoleService.save(role);
}
@Override
public void onShown(WindowEvent 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.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.ui.AbstEntityManagerSkin;
import com.ecep.contract.controller.AbstEntityManagerSkin;
import com.ecep.contract.model.Function;
import com.ecep.contract.service.FunctionService;
import com.ecep.contract.service.PermissionService;
import com.ecep.contract.vm.FunctionViewModel;
import javafx.scene.control.TableColumn;
import javafx.scene.control.cell.CheckBoxTableCell;

View File

@@ -1,8 +1,8 @@
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.vo.FunctionViewModel;
import com.ecep.contract.manager.ui.tab.AbstEntityBasedTabSkin;
import com.ecep.contract.controller.tab.AbstEntityBasedTabSkin;
import com.ecep.contract.model.Function;
import com.ecep.contract.vm.FunctionViewModel;
import javafx.scene.control.Tab;

View File

@@ -1,16 +1,16 @@
package com.ecep.contract.manager.ds.other.controller.permission;
package com.ecep.contract.controller.permission;
import java.util.Map;
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.manager.ds.other.model.Permission;
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.table.AbstEntityTableTabSkin;
import com.ecep.contract.manager.ui.FxmlPath;
import com.ecep.contract.manager.util.SpecificationUtils;
import com.ecep.contract.controller.table.AbstEntityTableTabSkin;
import com.ecep.contract.model.Function;
import com.ecep.contract.model.Permission;
import com.ecep.contract.service.PermissionService;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.vm.FunctionViewModel;
import com.ecep.contract.vm.PermissionViewModel;
import javafx.fxml.FXML;
import javafx.scene.control.Tab;
@@ -61,10 +61,10 @@ public class FunctionTabSkinPermission
}
@Override
public Specification<Permission> getSpecification(Function parent) {
return SpecificationUtils.and(getSpecification(), (root, query, criteriaBuilder) -> {
return criteriaBuilder.equal(root.get("function"), parent);
});
public Map<String, Object> getSpecification(Function parent) {
Map<String, Object> params = getSpecification();
params.put("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.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -18,6 +7,23 @@ import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import com.ecep.contract.controller.AbstEntityController;
import com.ecep.contract.model.Function;
import com.ecep.contract.service.FunctionService;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.vm.FunctionViewModel;
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
@Scope("prototype")
@Component

View File

@@ -1,11 +1,22 @@
package com.ecep.contract.manager.ds.other.controller.permission;
package com.ecep.contract.controller.permission;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
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.model.Permission;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vm.FunctionViewModel;
import com.ecep.contract.vm.PermissionViewModel;
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.beans.property.Property;
import javafx.collections.FXCollections;
@@ -16,14 +27,6 @@ import javafx.scene.control.MenuItem;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import lombok.Setter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.jpa.domain.Specification;
import java.util.ArrayList;
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);
@@ -56,7 +59,6 @@ public class PermissionManagerSkin implements ManagerSkin, TableTabSkin<Permissi
return table;
}
@Override
public void install() {
initializeTable();
@@ -64,14 +66,14 @@ public class PermissionManagerSkin implements ManagerSkin, TableTabSkin<Permissi
loadTableDataSet();
}
@Override
public void initializeTable() {
table.setEditable(true);
// controller.permissionTable_descriptionColumn.setCellValueFactory(param -> param.getValue().getDescription());
// controller.permissionTable_descriptionColumn.setCellFactory(TextFieldTableCell.forTableColumn());
// controller.permissionTable_descriptionColumn.setOnEditCommit(this::onSignMethodTableDescriptionColumnEditCommitAction);
// controller.permissionTable_descriptionColumn.setCellValueFactory(param ->
// param.getValue().getDescription());
// controller.permissionTable_descriptionColumn.setCellFactory(TextFieldTableCell.forTableColumn());
// controller.permissionTable_descriptionColumn.setOnEditCommit(this::onSignMethodTableDescriptionColumnEditCommitAction);
table.setItems(dataSet);
@@ -98,7 +100,7 @@ public class PermissionManagerSkin implements ManagerSkin, TableTabSkin<Permissi
protected void onTableCreateNewAction(ActionEvent event) {
Permission newRow = new Permission();
com.ecep.contract.manager.ds.other.model.Function function = controller.functionService.findById(viewModel.getId().get());
com.ecep.contract.model.Function function = controller.functionService.findById(viewModel.getId().get());
newRow.setFunction(function);
Permission saved = controller.permissionService.save(newRow);
@@ -141,7 +143,8 @@ public class PermissionManagerSkin implements ManagerSkin, TableTabSkin<Permissi
if (viewModel == null) {
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() {
@@ -161,12 +164,14 @@ public class PermissionManagerSkin implements ManagerSkin, TableTabSkin<Permissi
}
@Override
public Specification<Permission> getSpecification() {
return controller.permissionService.getSpecification(null);
public Map<String, Object> getSpecification() {
Map<String, Object> params = new HashMap<>();
// 使用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();
Property<K> property = function.apply(row);
property.setValue(event.getNewValue());
@@ -186,5 +191,4 @@ public class PermissionManagerSkin implements ManagerSkin, TableTabSkin<Permissi
}
}
}

View File

@@ -1,10 +1,10 @@
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.manager.ds.project.service.ProjectService;
import com.ecep.contract.manager.ds.project.vo.ProjectViewModel;
import com.ecep.contract.manager.ui.tab.AbstEntityBasedTabSkin;
import com.ecep.contract.manager.ui.tab.TabSkin;
import com.ecep.contract.controller.tab.AbstEntityBasedTabSkin;
import com.ecep.contract.controller.tab.TabSkin;
import com.ecep.contract.model.Project;
import com.ecep.contract.service.ProjectService;
import com.ecep.contract.vm.ProjectViewModel;
public abstract class AbstProjectBasedTabSkin
extends AbstEntityBasedTabSkin<ProjectWindowController, Project, ProjectViewModel>

View File

@@ -0,0 +1,41 @@
package com.ecep.contract.controller.project;
import java.util.Map;
import com.ecep.contract.controller.tab.TabSkin;
import com.ecep.contract.controller.table.AbstEntityTableTabSkin;
import com.ecep.contract.model.IdentityEntity;
import com.ecep.contract.model.Project;
import com.ecep.contract.service.ProjectService;
import com.ecep.contract.vm.IdentityViewModel;
import com.ecep.contract.vm.ProjectBasedViewModel;
import com.ecep.contract.vm.ProjectViewModel;
public abstract class AbstProjectTableTabSkin<T extends IdentityEntity, TV extends IdentityViewModel<T>>
extends AbstEntityTableTabSkin<ProjectWindowController, Project, ProjectViewModel, T, TV>
implements TabSkin {
public AbstProjectTableTabSkin(ProjectWindowController controller) {
super(controller);
}
public ProjectService getProjectService() {
return controller.projectService;
}
@Override
protected TV createNewViewModel() {
TV model = super.createNewViewModel();
if (model instanceof ProjectBasedViewModel m) {
m.getProject().set(getEntity());
}
return model;
}
@Override
public Map<String, Object> getSpecification(Project parent) {
Map<String, Object> params = getSpecification();
params.put("project", parent.getId());
return params;
}
}

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