Compare commits

..

71 Commits

Author SHA1 Message Date
97a2586c21 更新策略 2025-09-25 19:31:55 +08:00
45f7b611c5 feat: 实现VoableService接口并重构相关服务
refactor: 优化WebSocket通信和任务处理逻辑

fix: 修复客户和供应商路径选择功能

docs: 更新任务通信规则文档

build: 更新项目版本至0.0.86-SNAPSHOT

style: 清理无用导入和日志输出

test: 添加CustomerFileMoveTasker测试类

chore: 更新tasker_mapper.json注册信息
2025-09-25 18:57:17 +08:00
bf90117116 docs: 添加客户端模块Service层规则文档
添加客户端模块Service层的架构设计、缓存管理、数据操作模式等详细规则文档,总结项目中的最佳实践和规范要求
2025-09-25 17:56:36 +08:00
928d10c681 Merge branch 'main' of http://10.84.210.110/songqq/contract-manager 2025-09-25 11:02:48 +08:00
fa6920806d refactor(客户文件): 重构客户文件相关任务处理逻辑
- 移除CompanyCustomerFileService中未实现的searchEvaluationFile方法
- 删除已不再使用的tasker_mapper.json配置文件
- 重构CompanyCustomerEvaluationFormUpdateTask,移除无用日志记录
- 更新客户端与服务端Tasker通信文档中的文件路径格式
- 重构CustomerTabSkinFile中的文件重建和日期计算逻辑,改为直接调用服务方法
2025-09-25 11:02:45 +08:00
c21269975d 更新 README.md 2025-09-25 10:08:17 +08:00
ad42a49858 docs(task): 更新任务通信规则文档并添加任务注册描述
添加任务注册信息的描述字段到tasker_mapper.json
完善WebSocket通信机制文档,补充核心组件说明
修正属性同步机制中的空指针问题
优化代码格式和注释
2025-09-25 09:56:27 +08:00
2057c3ca67 feat: 实现客户端与服务器端Tasker通信机制及文件管理功能
refactor: 重构Tasker基类与服务获取逻辑
fix: 修复文件路径显示问题及任务注册加载机制
docs: 添加客户端与服务器端Tasker通信规则文档
style: 优化代码格式与日志输出
build: 添加tasker_mapper.json配置文件
chore: 清理无用代码与文件
2025-09-25 00:14:34 +08:00
dc764e6ed8 feat(表格单元格): 添加文件路径表格单元格基础类 2025-09-25 00:14:13 +08:00
09b0da498b feat(service): 实现国际化支持并优化Service层
重构文件类型相关Service以支持国际化查询
添加findOneByLang辅助方法统一查询逻辑
实现StringConverter支持UI控件显示
优化缓存配置和查询性能
新增UnitStringConverter和CustomerCatalogStringConverter
完善文档和测试用例
2025-09-24 16:20:49 +08:00
45eed8281f docs 2025-09-24 00:11:21 +08:00
7b023fd07b docs: 添加数据库结构文档和任务说明文档
添加多个数据库表结构SQL文件,包括供应商评分、企业报告等JSON数据模板
添加任务说明文档,包括枚举类型本地化实现方案、VO创建指南和异步任务监控方案
删除无用的CustomerFileTypeLocalRepository.java文件
2025-09-24 00:11:05 +08:00
9561ad99e6 refactor(vendor): 重构供应商相关类命名和包结构
将CompanyVendor前缀的类重命名为Vendor前缀,优化包结构
调整供应商相关控制器、服务、仓库类的命名和位置
修复TableViewUtils中的类型安全警告
更新FXML文件中的控制器引用路径
2025-09-23 23:37:44 +08:00
9c3306eea3 feat: 添加供应商管理相关功能及数据库表结构
新增供应商名录管理功能,包括合格供应商名录、供应商文件、供应商关联实体等模块。主要变更包括:

1. 添加COMPANY_VENDOR_ENTITY表的CREATOR_ID、MODIFIER_ID和MODIFY_DATE字段
2. 实现供应商同步任务类(VendorClassSyncTask等)
3. 新增供应商相关VO类(VendorApprovedVo、VendorFileVo等)
4. 添加供应商相关Repository接口(VendorRepository、VendorFileRepository等)
5. 实现供应商相关服务类(VendorApprovedService、VendorFileService等)
6. 添加供应商管理界面控制器及皮肤类
7. 新增供应商文件类型枚举和本地化配置
2025-09-23 23:37:04 +08:00
71d3ecab52 CompanyVendor 改为 Vendor 2025-09-23 22:50:30 +08:00
5919636c04 feat(供应商管理): 新增供应商实体类及VO转换方法
添加CompanyVendor实体类,包含供应商基本信息、关联关系和VO转换功能
2025-09-23 22:50:16 +08:00
57fbae90c5 feat: 实现文件类型枚举的本地化支持
新增文件类型枚举的本地化功能,包括供应商、项目、公司、合同和客户文件类型。添加了相关的SQL表结构、Repository、Service、ViewModel和StringConverter实现。同时更新了文档说明如何创建和使用枚举类型的本地化功能。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

style: 清理无用导入和代码

chore: 更新.gitignore文件

build: 调整项目依赖配置

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

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

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

docs: 更新代码注释和文档

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

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

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

docs: 更新部分代码注释

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

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

fix: 修复WebSocketService消息发送逻辑

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

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

test: 添加CompanyFilePathTableCell测试类

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

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

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

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

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

refactor: 重命名CompanyTableCell为EmployeeRoleTableCell

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

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

View File

@@ -1,13 +1,233 @@
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
# Contract-Manager 项目规则
## 技术栈规范
### server 模块
- Java 21
- Spring Boot 3.3.7
- Spring Data JPA 3.3.7
- 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 模块通信
- StringConverter 创建规则与实现逻辑 `docs/task/string_converter_implementation_guide.md`
- TableCell 规则与逻辑 `docs/task/table_cell_implementation_guide.md`
- Service 规则与逻辑 `docs/task/serservice_layer_rules.md`
- 客户端 Tasker 至 服务器端 Tasker 通信规则与逻辑 `docs/task/client_server_tasker_communication_rules.md`
### common 模块
- Java 21
- Lombok 1.18.32
## 文件命名规范
- Java类名使用驼峰命名法首字母大写`ContractService.java`
- 接口名使用驼峰命名法首字母大写以I开头`IContractService.java`
- 控制器类名以Controller结尾`ContractController.java`
- 服务类名以Service结尾`ContractService.java`
- 实体类名:使用驼峰命名法,首字母大写,如 `Contract.java`
- FXML文件使用小写字母和下划线`contract_view.fxml`
- SQL文件表名使用大写和下划线`CONTRACT_TYPE_LOCAL.sql`
## 目录结构规范
- 源代码位于 `src/main/java` 目录
- 资源文件位于 `src/main/resources` 目录
- 测试代码位于 `src/test` 目录
- 数据库脚本位于 `docs/db` 目录
## 数据库规范
- 表名使用大写字母和下划线,如 `COMPANY_VENDOR_FILE_TYPE_LOCAL`
- 字段名使用大写字母和下划线,如 `CREATE_DATE`
- 主键命名为 `ID`
- 外键命名格式为 `[关联表名]_ID`
- 唯一约束命名格式为 `UK_[表名缩写]_[字段名]`
## 代码规范
- 使用Lombok注解简化代码`@Data``@Slf4j`
- 类和方法应有适当的JavaDoc注释
- 变量命名应清晰表达其含义
- 避免魔法数字,使用常量替代
- 异常处理使用统一的异常处理机制
## 忽略文件
ignore:
- .idea
- target
- *.iml
- .gitignore
- .gitattributes
- out/
- *.log
- build/
- .DS_Store
- *.class
# 6A工作流执行规则
## 阶段1: Align (对齐阶段)
### 目标: 模糊需求 → 精确规范
### 执行步骤
1. **项目上下文分析**
- 分析现有项目结构、技术栈、架构模式、依赖关系
- 分析现有代码模式、现有文档和约定
- 理解业务域和数据模型
2. **需求理解确认**
- 创建 `docs/任务名/ALIGNMENT_[任务名].md`
- 包含项目和任务特性规范
- 包含原始需求、边界确认(明确任务范围)、需求理解(对现有项目的理解)、疑问澄清(存在歧义的地方)
3. **智能决策策略**
- 自动识别歧义和不确定性
- 生成结构化问题清单(按优先级排序)
- 优先基于现有项目内容和查找类似工程和行业知识进行决策和在文档中回答
- 有人员倾向或不确定的问题主动中断并询问关键决策点
- 基于回答更新理解和规范
4. **中断并询问关键决策点**
- 主动中断询问,迭代执行智能决策策略
5. **最终共识**
- 生成 `docs/任务名/CONSENSUS_[任务名].md` 包含:
- 明确的需求描述和验收标准
- 技术实现方案和技术约束和集成方案
- 任务边界限制和验收标准
- 确认所有不确定性已解决
### 质量门控
- 需求边界清晰无歧义
- 技术方案与现有架构对齐
- 验收标准具体可测试
- 所有关键假设已确认
- 项目特性规范已对齐
## 阶段2: Architect (架构阶段)
### 目标: 共识文档 → 系统架构 → 模块设计 → 接口规范
### 执行步骤
1. **系统分层设计**
- 基于CONSENSUS、ALIGNMENT文档设计架构
- 生成 `docs/任务名/DESIGN_[任务名].md` 包含:
- 整体架构图(mermaid绘制)
- 分层设计和核心组件
- 模块依赖关系图
- 接口契约定义
- 数据流向图
- 异常处理策略
2. **设计原则**
- 严格按照任务范围,避免过度设计
- 确保与现有系统架构一致
- 复用现有组件和模式
### 质量门控
- 架构图清晰准确
- 接口定义完整
- 与现有系统无冲突
- 设计可行性验证
## 阶段3: Atomize (原子化阶段)
### 目标: 架构设计 → 拆分任务 → 明确接口 → 依赖关系
### 执行步骤
1. **子任务拆分**
- 基于DESIGN文档生成 `docs/任务名/TASK_[任务名].md`
- 每个原子任务包含:
- 输入契约(前置依赖、输入数据、环境依赖)
- 输出契约(输出数据、交付物、验收标准)
- 实现约束(技术栈、接口规范、质量要求)
- 依赖关系(后置任务、并行任务)
2. **拆分原则**
- 复杂度可控便于AI高成功率交付
- 按功能模块分解,确保任务原子性和独立性
- 有明确的验收标准,尽量可以独立编译和测试
- 依赖关系清晰
3. **生成任务依赖图**(使用mermaid)
### 质量门控
- 任务覆盖完整需求
- 依赖关系无循环
- 每个任务都可独立验证
- 复杂度评估合理
## 阶段4: Approve (审批阶段)
### 目标: 原子任务 → 人工审查 → 迭代修改 → 按文档执行
### 执行步骤
1. **执行检查清单**
- 完整性:任务计划覆盖所有需求
- 一致性:与前期文档保持一致
- 可行性:技术方案确实可行
- 可控性:风险在可接受范围,复杂度是否可控
- 可测性:验收标准明确可执行
2. **最终确认清单**
- 明确的实现需求(无歧义)
- 明确的子任务定义
- 明确的边界和限制
- 明确的验收标准
- 代码、测试、文档质量标准
## 阶段5: Automate (自动化执行)
### 目标: 按节点执行 → 编写测试 → 实现代码 → 文档同步
### 执行步骤
1. **逐步实施子任务**
- 创建 `docs/任务名/ACCEPTANCE_[任务名].md` 记录完成情况
2. **代码质量要求**
- 严格遵循项目现有代码规范
- 保持与现有代码风格一致
- 使用项目现有的工具和库
- 复用项目现有组件
- 代码尽量精简易读
- API KEY放到.env文件中并且不要提交git
3. **异常处理**
- 遇到不确定问题立刻中断执行
- 在TASK文档中记录问题详细信息和位置
- 寻求人工澄清后继续
4. **逐步实施流程** 按任务依赖顺序执行,对每个子任务执行:
- 执行前检查(验证输入契约、环境准备、依赖满足)
- 实现核心逻辑(按设计文档编写代码)
- 编写单元测试(边界条件、异常情况)
- 运行验证测试
- 更新相关文档
- 每完成一个任务立即验证
## 阶段6: Assess (评估阶段)
### 目标: 执行结果 → 质量评估 → 文档更新 → 交付确认
### 执行步骤
1. **验证执行结果**
- 更新 `docs/任务名/ACCEPTANCE_[任务名].md`
- 整体验收检查:
- 所有需求已实现
- 验收标准全部满足
- 项目编译通过
- 所有测试通过
- 功能完整性验证
- 实现与设计文档一致
2. **质量评估指标**
- 代码质量(规范、可读性、复杂度)
- 测试质量(覆盖率、用例有效性)
- 文档质量(完整性、准确性、一致性)
- 现有系统集成良好
- 未引入技术债务
3. **最终交付物**
- 生成 `docs/任务名/FINAL_[任务名].md`(项目总结报告)
- 生成 `docs/任务名/TODO_[任务名].md`(精简明确哪些待办的事宜和哪些缺少的配置等,我方便直接寻找支持)
4. **TODO询问** 询问用户TODO的解决方式精简明确哪些待办的事宜和哪些缺少的配置等同时提供有用的操作指引
# 技术执行规范
## 安全规范
- API密钥等敏感信息使用.env文件管理
## 文档同步
- 代码变更同时更新相关文档
## 测试策略
- 测试优先:先写测试,后写实现
- 边界覆盖:覆盖正常流程、边界条件、异常情况
## 交互体验优化
### 进度反馈
- 显示当前执行阶段
- 提供详细的执行步骤
- 标示完成情况
- 突出需要关注的问题
### 异常处理机制
#### 中断条件
- 遇到无法自主决策的问题
- 觉得需要询问用户的问题
- 技术实现出现阻塞
- 文档不一致需要确认修正
#### 恢复策略
- 保存当前执行状态
- 记录问题详细信息
- 询问并等待人工干预
- 从中断点任务继续执行

231
README.md
View File

@@ -1,33 +1,198 @@
## 项目改进与优化分析报告
### 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. 配置管理优化
- 配置集中管理 :将分散在代码中的配置项(如同步间隔、批处理大小)集中到配置文件
- 动态配置支持 :添加动态配置更新机制,避免重启应用
以上优化点已按优先级和影响范围排序,建议逐步实施。实施过程中应注意性能测试和兼容性验证,确保优化不会引入新问题。
# Contract-Manager 项目报告
## 项目概述
Contract-Manager是一个企业级合同管理系统提供完整的合同生命周期管理包括合同的创建、审批、执行、归档等功能同时集成了供应商管理、客户管理、项目管理等相关业务模块。
## 项目架构
### 模块划分
项目采用模块化设计,分为三个主要模块:
- **common**:公共模块,包含实体类、枚举、异常、工具类等共享组件
- **server**服务端模块基于Spring Boot开发提供HTTP服务和WebSocket通信
- **client**客户端模块基于JavaFX开发提供图形用户界面
### 技术栈
#### 服务端技术栈
- Java 21
- Spring Boot 3.3.7
- Spring Data JPA 3.3.7
- MySQL 8.0.33
- Lombok 1.18.32
- POI 5.2.5 (Office文档处理)
- PDFBox 3.0.1 (PDF文档处理)
- Redis (缓存)
- WebSocket (实时通信)
#### 客户端技术栈
- Java 21
- JavaFX 21
- ControlsFX 11.1.2 (UI控件增强)
- Lombok 1.18.32
- Caffeine 3.1.8 (本地缓存)
- WebSocket (与服务端通信)
## 目录结构
```
Contract-Manager/
├── common/ # 公共模块
│ ├── src/main/java/com/ecep/contract/
│ │ ├── model/ # 实体类
│ │ ├── vo/ # 值对象
│ │ ├── util/ # 工具类
│ │ ├── constant/ # 常量定义
│ │ └── msg/ # 消息相关
├── server/ # 服务端模块
│ ├── src/main/java/com/ecep/contract/
│ │ ├── api/ # API接口
│ │ ├── controller/ # 控制器
│ │ ├── service/ # 服务层
│ │ ├── ds/ # 数据访问层
│ │ ├── config/ # 配置类
│ │ ├── util/ # 工具类
│ │ ├── handler/ # WebSocket处理器
│ │ ├── cloud/ # 云端服务集成
│ │ └── ui/ # 服务端UI组件
├── client/ # 客户端模块
│ ├── src/main/java/com/ecep/contract/
│ │ ├── controller/ # 控制器
│ │ ├── service/ # 服务层
│ │ ├── vm/ # 视图模型
│ │ ├── util/ # 工具类
│ │ ├── task/ # 任务处理
│ │ ├── converter/ # 类型转换器
│ │ └── serializer/ # 序列化器
│ └── src/main/resources/ui/ # FXML界面文件
└── docs/ # 文档目录
└── db/ # 数据库相关文件
└── task/ # 任务
```
## 核心功能模块
### 1. 公司管理
- 公司基本信息管理
- 公司联系方式管理
- 公司银行账户管理
- 公司文件管理
- 公司黑名单管理
### 2. 供应商管理
- 供应商信息管理
- 供应商资质审核
- 供应商分类管理
- 供应商文件管理
- 供应商评估
### 3. 客户管理
- 客户信息管理
- 客户分类管理
- 客户满意度调查
- 客户文件管理
### 4. 合同管理
- 合同创建与编辑
- 合同审批流程
- 合同执行跟踪
- 合同付款计划
- 合同文件管理
- 合同分类与归档
### 5. 项目管理
- 项目信息管理
- 项目成本管理
- 项目报价管理
- 项目文件管理
- 项目资金计划
### 6. 库存管理
- 库存物品管理
- 库存价格历史
- 库存分类管理
### 7. 员工与权限管理
- 员工信息管理
- 角色权限管理
- 登录历史记录
### 8. 云端服务集成
- 天眼查企业信息集成
- 用友U8系统集成
- 其他云端服务集成
## 数据模型设计
系统采用JPA注解式实体类设计主要实体类包括
- **基础实体类**BasedEntity, IdentityEntity, NamedEntity等
- **公司相关**Company, CompanyContact, CompanyBankAccount等
- **供应商相关**Vendor, VendorApproved, VendorFile等
- **客户相关**CompanyCustomer, CustomerSatisfactionSurvey等
- **合同相关**Contract, ContractItem, ContractPayPlan等
- **项目相关**Project, ProjectCost, ProjectFundPlan等
- **枚举实体类**各种类型的本地枚举实体如VendorTypeLocal, ContractFileTypeLocal等
## 通信机制
系统采用WebSocket进行客户端与服务端的实时通信主要组件包括
- **服务端**WebSocketController, WebSocketServerHandler
- **客户端**WebSocketClientService, WebSocketClientSession
## 任务处理机制
系统实现了异步任务处理机制,支持长时间运行的任务监控和管理:
- **TaskMonitorCenter**:任务监控中心
- **MonitoredTask**:可监控的任务基类
- **TaskHistory**:任务历史记录
## 扩展性设计
系统采用良好的分层架构和接口设计,具有较强的扩展性:
1. **服务接口标准化**通过IEntityService等接口统一服务访问方式
2. **模块化设计**:各功能模块相对独立,便于扩展和维护
3. **配置管理**:支持动态配置和属性绑定
4. **国际化支持**通过messages.properties实现多语言支持
## 安全机制
系统实现了基本的安全机制:
- **用户认证与授权**:基于角色的权限控制
- **登录历史记录**:记录用户登录信息
- **异常处理**:全局异常处理机制
## 部署说明
### 服务端部署
1. 配置application.properties中的数据库连接和Redis连接信息
2. 打包为jar文件`mvn clean package`
3. 运行jar文件`java -jar server.jar`
### 客户端部署
1. 确保安装Java 21运行环境
2. 配置连接到服务端的WebSocket地址
3. 打包为可执行jar或使用jpackage创建安装包
## 开发环境要求
- JDK 21
- Maven 3.6+
- MySQL 8.0+
- Redis 6.0+
- IntelliJ IDEA或Eclipse推荐使用IDEA
## 后续优化方向
1. 完善单元测试和集成测试
2. 优化数据库查询性能
3. 增强系统安全机制
4. 改进用户界面体验
5. 扩展更多云端服务集成

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

View File

@@ -0,0 +1,115 @@
package com.ecep.contract;
import com.fasterxml.jackson.core.JsonProcessingException;
import java.util.Locale;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.logging.Level;
/**
* WebSocket客户端任务接口
* 定义了所有通过WebSocket与服务器通信的任务的通用方法
* 包括任务名称、更新消息、更新标题、更新进度等操作
*/
public interface WebSocketClientTasker {
/**
* 获取任务名称
*
* @return 任务名称
*/
String getTaskName();
/**
* 更新任务执行过程中的消息
*
* @param level 消息级别
* @param message 消息内容
*/
void updateMessage(Level level, String message);
/**
* 更新任务标题
*
* @param title 任务标题
*/
void updateTitle(String title);
/**
* 更新任务进度
*
* @param current 当前进度
* @param total 总进度
*/
void updateProgress(long current, long total);
/**
* 取消任务执行
* 默认实现为空,可由具体任务重写以提供取消逻辑
*/
default void cancelTask() {
// 默认实现为空,由具体任务重写
}
/**
* 调用远程WebSocket任务
*
* @param holder 消息持有者,用于记录任务执行过程中的消息
* @param locale 语言环境
* @param args 任务参数
* @return 任务执行结果
*/
default Object callRemoteTask(MessageHolder holder, Locale locale, Object... args) {
WebSocketClientService webSocketService = SpringApp.getBean(WebSocketClientService.class);
// 检查WebSocket连接是否可用
if (!webSocketService.getOnlineProperty().get()) {
String errorMsg = "WebSocket连接不可用请检查网络连接或服务器状态";
holder.addMessage(Level.SEVERE, errorMsg);
return null;
}
webSocketService.withSession(session -> {
try {
session.submitTask(this, locale, args);
holder.addMessage(Level.INFO, "已提交任务到服务器: " + getTaskName());
} catch (JsonProcessingException e) {
String errorMsg = "任务提交失败: " + e.getMessage();
holder.addMessage(Level.SEVERE, errorMsg);
throw new RuntimeException("任务提交失败: " + e.getMessage(), e);
}
});
return null;
}
/**
* 异步调用远程WebSocket任务
*
* @param holder 消息持有者,用于记录任务执行过程中的消息
* @param locale 语言环境
* @param args 任务参数
* @return 包含任务执行结果的CompletableFuture
*/
default CompletableFuture<Object> callRemoteTaskAsync(MessageHolder holder, Locale locale, Object... args) {
CompletableFuture<Object> future = new CompletableFuture<>();
try {
// 立即执行callRemoteTask并返回结果
Object result = callRemoteTask(holder, locale, args);
future.complete(result);
} catch (Exception e) {
future.completeExceptionally(e);
}
return future;
}
/**
* 生成唯一的任务ID
*
* @return 唯一的任务ID
*/
default String generateTaskId() {
return UUID.randomUUID().toString();
}
}

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,31 @@
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 com.ecep.contract.util.ParamUtils;
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 +47,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 +68,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 +215,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 +227,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 +283,17 @@ public abstract class AbstEntityManagerSkin<T extends IdentityEntity, TV extends
}
}
protected <K> void acceptCellEditEvent(TableColumn.CellEditEvent<TV, K> event, Function<TV, Property<K>> function) {
/**
* 处理单元格编辑事件
*
* @param <K>
* @param event
* @param propGetter
*/
protected <K> void acceptCellEditEvent(TableColumn.CellEditEvent<TV, K> event,
Function<TV, Property<K>> propGetter) {
TV row = event.getRowValue();
Property<K> property = function.apply(row);
Property<K> property = propGetter.apply(row);
property.setValue(event.getNewValue());
try {
saveRowData(row);
@@ -317,21 +349,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 +417,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 +437,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();
ParamUtils.Builder params = getSpecification();
ViewModelService<T, TV> service = getViewModelService();
long timeMillis = System.currentTimeMillis();
Page<T> page = service.findAll(spec, getPageable());
Page<T> page = service.findAll(params == null ? null : params.build(), getPageable());
long timeCost = System.currentTimeMillis() - timeMillis;
if (logger.isDebugEnabled()) {
logger.debug("load table data cost: {} ms", timeCost);
@@ -404,17 +502,45 @@ public abstract class AbstEntityManagerSkin<T extends IdentityEntity, TV extends
return page.map(service::from).toList();
}
/**
* 异步加载表格数据
*
* @param queryService
* @param future
*/
private void asyncLoadTableData(QueryService<T, TV> queryService, CompletableFuture<Void> future) {
ParamUtils.Builder params = getSpecification();
queryService.asyncFindAll(params == null ? null : params.build(), getPageable()).whenComplete((result, ex) -> {
if (ex != null) {
future.completeExceptionally(ex);
return;
}
updateFooter(result);
List<TV> models = result.map(getViewModelService()::from).toList();
_updateModels(models, future);
});
}
/**
* 获取ViewModelService
*
* @return
*/
protected ViewModelService<T, TV> getViewModelService() {
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 ParamUtils.Builder getSpecification() {
TextField field = controller.searchKeyField;
if (field != null) {
return getViewModelService().getSpecification(field.getText());
@@ -422,8 +548,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 ParamUtils.Builder getSpecification(String searchText) {
return getViewModelService().getSpecification(searchText);
}
/**
@@ -434,6 +566,11 @@ public abstract class AbstEntityManagerSkin<T extends IdentityEntity, TV extends
protected void onTableRowDoubleClickedAction(TV item) {
}
/**
* 更新页脚
*
* @param page
*/
protected void updateFooter(Page<T> page) {
Platform.runLater(() -> {
controller.previousPageBtn.setDisable(!page.hasPrevious());
@@ -444,19 +581,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,33 @@
package com.ecep.contract.manager.ui;
package com.ecep.contract.controller;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Locale;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.util.FxmlUtils;
import com.ecep.contract.vo.EmployeeVo;
import org.apache.logging.log4j.util.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import com.ecep.contract.Desktop;
import com.ecep.contract.SpringApp;
import com.ecep.contract.model.Employee;
import com.ecep.contract.model.IdentityEntity;
import com.ecep.contract.service.EmployeeService;
import com.ecep.contract.service.SysConfService;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vm.CurrentEmployee;
import com.ecep.contract.vm.IdentityViewModel;
import com.ecep.contract.manager.Desktop;
import com.ecep.contract.manager.SpringApp;
import com.ecep.contract.manager.ds.other.model.Employee;
import com.ecep.contract.manager.ds.other.model.IdentityEntity;
import com.ecep.contract.manager.ds.other.service.EmployeeService;
import com.ecep.contract.manager.ds.other.service.SysConfService;
import com.ecep.contract.manager.ds.other.vo.IdentityViewModel;
import com.ecep.contract.manager.util.FxmlUtils;
import com.ecep.contract.manager.util.UITools;
import javafx.application.Platform;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
@@ -21,21 +40,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 +49,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 +68,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 +81,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 +118,6 @@ public class BaseController {
});
}
public static boolean toFront(String key) {
Stage stage = stages.get(key);
if (stage != null) {
@@ -161,6 +164,11 @@ public class BaseController {
return future;
}
public CompletableFuture<Void> runAsync(Runnable runnable) {
return CompletableFuture.runAsync(runnable, Desktop.instance.getExecutorService())
.exceptionally(this::handleException);
}
/**
* 窗口标题
*/
@@ -177,42 +185,51 @@ public class BaseController {
private String stageKey;
public Label leftStatusLabel;
public Label rightStatusLabel;
private EmployeeVo currentUser;
@Getter
@Setter
private Locale locale = Locale.getDefault();
private HashMap<Class<?>, Object> cachedBeans = new HashMap<>();
@Setter
private SysConfService confService;
@Setter
private EmployeeService employeeService;
private Employee currentUser;
protected <T> T getBean(Class<T> requiredType) throws BeansException {
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() {
public EmployeeVo getCurrentUser() {
if (currentUser == null) {
currentUser = getEmployeeService().findById(Desktop.instance.getActiveEmployeeId());
}
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,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

@@ -1,11 +1,16 @@
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 com.ecep.contract.controller.cloud.rk.CloudRkManagerWindowController;
import com.ecep.contract.controller.cloud.tyc.CloudTycManagerWindowController;
import com.ecep.contract.controller.cloud.u8.YongYouU8ManagerWindowController;
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 +19,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.VendorManagerWindowController;
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,13 +74,15 @@ 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() {
openCompanyManagerWindow.setOnAction(event -> showInOwner(CompanyManagerWindowController.class));
openProjectManagerWindow.setOnAction(event -> showInOwner(ProjectManagerWindowController.class));
openContractManagerWindow.setOnAction(event -> showInOwner(ContractManagerWindowController.class));
openVendorManagerWindow.setOnAction(event -> showInOwner(CompanyVendorManagerWindowController.class));
openVendorManagerWindow.setOnAction(event -> showInOwner(VendorManagerWindowController.class));
openCustomManagerWindow.setOnAction(event -> showInOwner(CompanyCustomerManagerWindowController.class));
}
@@ -102,6 +103,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 +122,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 +146,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 +219,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

@@ -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

@@ -1,14 +1,15 @@
package com.ecep.contract.manager.cloud.rk;
package com.ecep.contract.controller.cloud.rk;
import org.hibernate.Hibernate;
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.AbstEntityManagerSkin;
import com.ecep.contract.controller.company.CompanyWindowController;
import com.ecep.contract.controller.table.cell.CompanyTableCell;
import com.ecep.contract.controller.table.cell.LocalDateTimeTableCell;
import com.ecep.contract.service.CloudRkService;
import com.ecep.contract.service.CompanyService;
import com.ecep.contract.vm.CloudRkViewModel;
import com.ecep.contract.vo.CloudRkVo;
import com.ecep.contract.vo.CompanyVo;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
@@ -19,7 +20,7 @@ import javafx.scene.control.cell.CheckBoxTableCell;
import lombok.Setter;
public class CloudRkManagerSkin
extends AbstEntityManagerSkin<CloudRk, CloudRkInfoViewModel, CloudRkManagerSkin, CloudRkManagerWindowController> {
extends AbstEntityManagerSkin<CloudRkVo, CloudRkViewModel, CloudRkManagerSkin, CloudRkManagerWindowController> {
@Setter
private CompanyService companyService;
@@ -47,13 +48,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 +67,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,23 +90,21 @@ 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) {
Company company = item.getCompany().get();
if (!Hibernate.isInitialized(item)) {
company = getCompanyService().findById(company.getId());
}
protected void onTableRowDoubleClickedAction(CloudRkViewModel item) {
Integer companyId = item.getCompany().get();
CompanyVo company = getCompanyService().findById(companyId);
CompanyWindowController.show(company, getTableView().getScene().getWindow());
}
}

View File

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

View File

@@ -1,21 +1,16 @@
package com.ecep.contract.manager.cloud.tyc;
package com.ecep.contract.controller.cloud.tyc;
import java.util.List;
import com.ecep.contract.SpringApp;
import com.ecep.contract.controller.AbstEntityManagerSkin;
import com.ecep.contract.controller.company.CompanyWindowController;
import com.ecep.contract.controller.table.cell.CompanyTableCell;
import com.ecep.contract.controller.table.cell.LocalDateTimeTableCell;
import com.ecep.contract.service.CloudTycService;
import com.ecep.contract.service.CompanyService;
import com.ecep.contract.vm.CloudTycInfoViewModel;
import com.ecep.contract.vo.CloudTycVo;
import com.ecep.contract.vo.CompanyVo;
import org.hibernate.Hibernate;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.util.StringUtils;
import com.ecep.contract.manager.SpringApp;
import com.ecep.contract.manager.ui.table.cell.CompanyTableCell;
import com.ecep.contract.manager.ds.company.controller.CompanyWindowController;
import com.ecep.contract.manager.ds.company.model.Company;
import com.ecep.contract.manager.ds.company.service.CompanyService;
import com.ecep.contract.manager.ui.AbstEntityManagerSkin;
import com.ecep.contract.manager.ui.table.cell.LocalDateTimeTableCell;
import jakarta.persistence.criteria.Path;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.scene.control.ContextMenu;
@@ -24,7 +19,7 @@ import lombok.Setter;
public class CloudTycManagerSkin
extends
AbstEntityManagerSkin<CloudTyc, CloudTycInfoViewModel, CloudTycManagerSkin, CloudTycManagerWindowController> {
AbstEntityManagerSkin<CloudTycVo, CloudTycInfoViewModel, CloudTycManagerSkin, CloudTycManagerWindowController> {
@Setter
private CloudTycService cloudTycService;
@@ -49,31 +44,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());
@@ -114,21 +84,20 @@ public class CloudTycManagerSkin
return;
}
for (CloudTycInfoViewModel selectedItem : selectedItems) {
CloudTyc cloudTyc = getCloudTycService().findById(selectedItem.getId().get());
CloudTycVo cloudTyc = getCloudTycService().findById(selectedItem.getId().get());
// selectedItem.getDescription().set("");
if (selectedItem.copyTo(cloudTyc)) {
CloudTyc saved = getCloudTycService().save(cloudTyc);
CloudTycVo saved = getCloudTycService().save(cloudTyc);
selectedItem.update(saved);
}
}
}
//
@Override
protected void onTableRowDoubleClickedAction(CloudTycInfoViewModel item) {
Company company = item.getCompany().get();
if (!Hibernate.isInitialized(item)) {
company = getCompanyService().findById(company.getId());
}
Integer companyId = item.getCompany().get();
CompanyVo company = getCompanyService().findById(companyId);
CompanyWindowController.show(company, getTableView().getScene().getWindow());
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,13 +1,32 @@
package com.ecep.contract.manager.ds.company.controller.contact;
package com.ecep.contract.controller.company;
import java.lang.reflect.InvocationTargetException;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.CompletableFuture;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import com.ecep.contract.controller.BaseController;
import com.ecep.contract.model.CompanyContact;
import com.ecep.contract.service.CompanyContactService;
import com.ecep.contract.util.FxmlUtils;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vm.CompanyContactViewModel;
import com.ecep.contract.vo.CompanyContactVo;
import com.ecep.contract.manager.ds.company.model.CompanyContact;
import com.ecep.contract.manager.ds.company.repository.CompanyContactRepository;
import com.ecep.contract.manager.ui.BaseController;
import com.ecep.contract.manager.ds.company.vo.CompanyContactViewModel;
import com.ecep.contract.manager.util.FxmlUtils;
import com.ecep.contract.manager.util.UITools;
import javafx.application.Platform;
import javafx.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;
@@ -73,12 +84,13 @@ public class CompanyContactWindowController extends BaseController {
public Label versionLabel;
public Button saveBtn;
private CompletableFuture<CompanyContact> companyContactLoadedFuture;
private CompletableFuture<CompanyContactVo> companyContactLoadedFuture;
@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;
CompanyContactVo 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()) {
@@ -121,9 +128,9 @@ public class CompanyContactWindowController extends BaseController {
saveBtn.disableProperty().bind(viewModel.getChanged().not());
saveBtn.setOnAction(event -> {
try {
CompanyContact contact = companyContactLoadedFuture.join();
CompanyContactVo contact = companyContactLoadedFuture.join();
viewModel.copyTo(contact);
CompanyContact saved = companyContactRepository.save(contact);
CompanyContactVo 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,22 +1,22 @@
package com.ecep.contract.manager.ds.company.controller;
package com.ecep.contract.controller.company;
import java.util.List;
import java.util.Optional;
import com.ecep.contract.controller.AbstEntityManagerSkin;
import com.ecep.contract.service.CompanyOldNameService;
import com.ecep.contract.service.CompanyService;
import com.ecep.contract.vm.CompanyViewModel;
import com.ecep.contract.vo.CompanyVo;
import com.ecep.contract.manager.ds.company.model.Company;
import com.ecep.contract.manager.ds.company.service.CompanyOldNameService;
import com.ecep.contract.manager.ds.company.service.CompanyService;
import com.ecep.contract.manager.ds.company.vo.CompanyViewModel;
import com.ecep.contract.manager.ui.AbstEntityManagerSkin;
import com.ecep.contract.manager.ui.ManagerSkin;
import javafx.application.Platform;
import javafx.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> {
extends AbstEntityManagerSkin<CompanyVo, CompanyViewModel, CompanyManagerSkin, CompanyManagerWindowController> {
@Setter
private CompanyOldNameService companyOldNameService;
@@ -65,11 +65,11 @@ public class CompanyManagerSkin
if (optional.isPresent()) {
CompanyService companyService = getCompanyService();
String newCompanyName = optional.get();
List<Company> list = companyService.findAllByName(newCompanyName);
List<CompanyVo> list = companyService.findAllByName(newCompanyName);
if (list == null || list.isEmpty()) {
// 未登记过
Company company = companyService.createNewCompany(newCompanyName);
Company saved = companyService.save(company);
CompanyVo company = companyService.createNewCompany(newCompanyName);
CompanyVo saved = companyService.save(company);
CompanyWindowController.show(saved, getTableView().getScene().getWindow());
} else {
Alert alert = new Alert(Alert.AlertType.INFORMATION);

View File

@@ -1,4 +1,4 @@
package com.ecep.contract.manager.ds.company.controller;
package com.ecep.contract.controller.company;
import java.time.LocalDate;
@@ -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.service.CompanyService;
import com.ecep.contract.task.CompanyFilesRebuildTasker;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vo.CompanyVo;
import com.ecep.contract.vm.CompanyViewModel;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
@@ -25,7 +25,7 @@ import javafx.stage.Stage;
@Component
@FxmlPath("/ui/company/company-manager.fxml")
public class CompanyManagerWindowController
extends AbstManagerWindowController<Company, CompanyViewModel, CompanyManagerSkin> {
extends AbstManagerWindowController<CompanyVo, CompanyViewModel, CompanyManagerSkin> {
// columns
@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,59 @@ 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.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.VendorWindowController;
import com.ecep.contract.service.CompanyCustomerService;
import com.ecep.contract.service.CompanyService;
import com.ecep.contract.service.VendorService;
import com.ecep.contract.task.CompanyCompositeUpdateTasker;
import com.ecep.contract.task.CompanyVerifyTasker;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vm.CompanyViewModel;
import com.ecep.contract.vo.CompanyCustomerVo;
import com.ecep.contract.vo.VendorVo;
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,13 +76,9 @@ public class CompanyWindowController
@Autowired
private CompanyService companyService;
@Autowired
private CompanyFileService companyFileService;
@Autowired
private ContractService contractService;
@Autowired
private CompanyCustomerService companyCustomerService;
@Autowired
private CompanyVendorService companyVendorService;
private VendorService vendorService;
public BorderPane root;
public TabPane tabPane;
@@ -89,7 +95,7 @@ public class CompanyWindowController
public Tab purchaseBillVoucherTab;
public Tab otherTab;
/*
*/
public TextField nameField;
public TextField shortNameField;
@@ -117,12 +123,13 @@ 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<>();
private final SimpleObjectProperty<CompanyCustomerVo> companyCustomerProperty = new SimpleObjectProperty<>();
private final SimpleObjectProperty<VendorVo> companyVendorProperty = new SimpleObjectProperty<>();
public Pane customerTab_pane1;
public Button customerTab_openBtn;
@@ -134,7 +141,6 @@ public class CompanyWindowController
public Pane vendorTab_pane2;
public Button vendorTab_createBtn;
@Override
public void show(Stage stage) {
super.show(stage);
@@ -143,17 +149,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 +156,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 +180,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 +190,6 @@ public class CompanyWindowController
}
});
customerTab_pane1.visibleProperty().bind(customerTab_pane2.visibleProperty().not());
customerTab_pane2.visibleProperty().bind(companyCustomerProperty.isNull());
customerTab_createBtn.setOnAction(event -> {
@@ -251,7 +230,7 @@ public class CompanyWindowController
});
vendorTab_openBtn.setOnAction(event -> {
CompanyVendorWindowController.show(companyVendorProperty.get(), root.getScene().getWindow());
VendorWindowController.show(companyVendorProperty.get(), root.getScene().getWindow());
});
}
@@ -263,7 +242,7 @@ public class CompanyWindowController
if (logger.isDebugEnabled()) {
logger.debug("onVendorTabShown company {}", company.getName());
}
companyVendorProperty.set(companyVendorService.findByCompany(company));
companyVendorProperty.set(vendorService.findByCompany(company));
}).exceptionally(ex -> {
UITools.showExceptionAndWait(ex.getMessage(), ex);
return null;
@@ -283,16 +262,14 @@ public class CompanyWindowController
* 企业合规检查
*/
public void onCompanyVerifyAction(ActionEvent event) {
Company company = getEntity();
CompanyVo company = getEntity();
CompanyVerifyTasker task = new CompanyVerifyTasker();
task.setCompanyService(companyService);
task.setCompany(company);
UITools.showTaskDialogAndWait("企业合规性验证", task, null);
}
public void onCompanyOpenInExplorerAction(ActionEvent event) {
Company company = getEntity();
CompanyVo company = getEntity();
String path = company.getPath();
CompletableFuture.runAsync(() -> {

View File

@@ -0,0 +1,59 @@
package com.ecep.contract.controller.company.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,31 @@
package com.ecep.contract.manager.ds.company.controller.bank_account;
package com.ecep.contract.controller.company.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.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

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

View File

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

View File

@@ -1,36 +1,44 @@
package com.ecep.contract.manager.ds.company.controller.old_name;
package com.ecep.contract.controller.company.old_name;
import java.io.File;
import java.util.concurrent.CompletableFuture;
import com.ecep.contract.manager.ds.company.model.CompanyOldName;
import com.ecep.contract.manager.ds.company.service.CompanyOldNameService;
import com.ecep.contract.manager.ds.company.service.CompanyService;
import com.ecep.contract.manager.ds.company.vo.CompanyFileViewModel;
import com.ecep.contract.manager.ds.company.vo.CompanyOldNameViewModel;
import com.ecep.contract.manager.ui.AbstEntityController;
import com.ecep.contract.manager.ui.FxmlPath;
import com.ecep.contract.manager.ui.ViewModelService;
import com.ecep.contract.manager.util.DesktopUtils;
import com.ecep.contract.manager.util.UITools;
import javafx.event.ActionEvent;
import javafx.scene.control.*;
import javafx.scene.layout.BorderPane;
import javafx.stage.Window;
import javafx.stage.WindowEvent;
import org.slf4j.Logger;
import org.slf4j.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.service.CompanyOldNameService;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vo.CompanyOldNameVo;
import com.ecep.contract.vm.CompanyFileViewModel;
import com.ecep.contract.vm.CompanyOldNameViewModel;
import javafx.event.ActionEvent;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.CheckBox;
import javafx.scene.control.DatePicker;
import javafx.scene.control.Label;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TableView;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.stage.Window;
import javafx.stage.WindowEvent;
@Lazy
@Scope("prototype")
@Component
@FxmlPath("/ui/company/company_old_name.fxml")
public class CompanyOldNameWindowController extends AbstEntityController<CompanyOldName, CompanyOldNameViewModel> {
public class CompanyOldNameWindowController extends AbstEntityController<CompanyOldNameVo, CompanyOldNameViewModel> {
private static final Logger logger = LoggerFactory.getLogger(CompanyOldNameWindowController.class);
/**
@@ -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,32 +80,31 @@ 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();
CompanyOldNameVo companyOldName = getEntity();
String path = companyOldName.getPath();
CompletableFuture.runAsync(() -> {
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,22 @@
package com.ecep.contract.controller.contract;
import com.ecep.contract.controller.tab.AbstEntityBasedTabSkin;
import com.ecep.contract.controller.tab.TabSkin;
import com.ecep.contract.service.ContractService;
import com.ecep.contract.vm.ContractViewModel;
import com.ecep.contract.vo.ContractVo;
public abstract class AbstContractBasedTabSkin
extends AbstEntityBasedTabSkin<ContractWindowController, ContractVo, ContractViewModel>
implements TabSkin {
public AbstContractBasedTabSkin(ContractWindowController controller) {
super(controller);
viewModel = controller.getViewModel();
}
public ContractService getContractService() {
return controller.getViewModelService();
}
}

View File

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

View File

@@ -1,4 +1,4 @@
package com.ecep.contract.manager.ds.contract.controller;
package com.ecep.contract.controller.contract;
import java.time.LocalDate;
import java.time.LocalDateTime;
@@ -8,19 +8,16 @@ 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.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 com.ecep.contract.vo.ContractGroupVo;
import com.ecep.contract.vo.ContractVo;
import javafx.event.ActionEvent;
import javafx.scene.control.CheckBox;
@@ -33,27 +30,27 @@ import javafx.stage.Stage;
@Component
@FxmlPath("/ui/contract/contract-manager.fxml")
public class ContractManagerWindowController
extends AbstManagerWindowController<Contract, ContractViewModel, ContractManagerSkin> {
extends AbstManagerWindowController<ContractVo, ContractViewModel, ContractManagerSkin> {
public ComboBox<ContractGroup> groupSelector;
public ComboBox<ContractGroupVo> groupSelector;
public CheckBox composeViewBtn;
// columns
public TableColumn<ContractViewModel, Number> idColumn;
public TableColumn<ContractViewModel, String> nameColumn;
public TableColumn<ContractViewModel, String> codeColumn;
public TableColumn<ContractViewModel, ContractGroup> groupColumn;
public TableColumn<ContractViewModel, ContractType> typeColumn;
public TableColumn<ContractViewModel, ContractKind> kindColumn;
public TableColumn<ContractViewModel, Integer> groupColumn;
public TableColumn<ContractViewModel, Integer> typeColumn;
public TableColumn<ContractViewModel, Integer> kindColumn;
public TableColumn<ContractViewModel, String> parentCodeColumn;
public TableColumn<ContractViewModel, LocalDate> setupDateColumn;
public TableColumn<ContractViewModel, LocalDate> orderDateColumn;
public TableColumn<ContractViewModel, LocalDate> startDateColumn;
public TableColumn<ContractViewModel, Employee> employeeColumn;
public TableColumn<ContractViewModel, Integer> employeeColumn;
public TableColumn<ContractViewModel, LocalDateTime> createdColumn;
public TableColumn<ContractViewModel, Number> amountColumn;
public TableColumn<ContractViewModel, Company> companyColumn;
public TableColumn<ContractViewModel, Integer> companyColumn;
@Autowired
private ContractService contractService;

View File

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

View File

@@ -1,37 +1,17 @@
package com.ecep.contract.manager.ds.contract.controller;
package com.ecep.contract.controller.contract;
import static com.ecep.contract.util.TableViewUtils.bindDoubleClicked;
import static com.ecep.contract.util.TableViewUtils.bindEnterPressed;
import java.io.File;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import com.ecep.contract.manager.ds.contract.ContractPayWay;
import com.ecep.contract.manager.ds.contract.model.Contract;
import com.ecep.contract.manager.ds.contract.service.ContractService;
import com.ecep.contract.manager.ds.contract.tasker.ContractVerifyComm;
import com.ecep.contract.manager.ds.contract.tasker.ContractVerifyResultExportAsExcelFile;
import com.ecep.contract.manager.ui.BaseController;
import com.ecep.contract.manager.ds.other.model.Employee;
import com.ecep.contract.manager.ds.other.service.EmployeeService;
import com.ecep.contract.manager.ds.project.service.SaleTypeService;
import com.ecep.contract.manager.ds.vendor.service.VendorGroupService;
import com.ecep.contract.manager.ui.FxmlPath;
import com.ecep.contract.manager.ui.Message;
import com.ecep.contract.manager.ui.MessageHolder;
import com.ecep.contract.manager.ui.table.cell.EmployeeTableCell;
import com.ecep.contract.manager.util.UITools;
import javafx.application.Platform;
import javafx.beans.property.SimpleListProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXMLLoader;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.scene.layout.HBox;
import javafx.stage.*;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.Hibernate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -40,21 +20,52 @@ import org.springframework.context.annotation.Scope;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.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.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 com.ecep.contract.vo.ContractVo;
import com.ecep.contract.vo.EmployeeVo;
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,12 +89,11 @@ public class ContractVerifyWindowController extends BaseController {
}
}
@Data
public static class Model implements MessageHolder {
private SimpleStringProperty code = new SimpleStringProperty();
private SimpleStringProperty name = new SimpleStringProperty();
private SimpleObjectProperty<Employee> employee = new SimpleObjectProperty<>();
private SimpleObjectProperty<Integer> employee = new SimpleObjectProperty<>();
private SimpleObjectProperty<LocalDate> setupDate = new SimpleObjectProperty<>();
private SimpleListProperty<MessageExt> messages = new SimpleListProperty<>(FXCollections.observableArrayList());
@@ -104,9 +114,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 +161,7 @@ public class ContractVerifyWindowController extends BaseController {
ContractVerifyComm comm = new ContractVerifyComm();
@Autowired
private SaleTypeService saleTypeService;
private ProjectSaleTypeService saleTypeService;
@Autowired
private VendorGroupService vendorGroupService;
@Autowired
@@ -189,7 +196,6 @@ public class ContractVerifyWindowController extends BaseController {
@FXML
public CheckMenuItem onlyShowVerifiedChecker;
@FXML
public TableView<Model> viewTable;
private final ObservableList<Model> viewTableDataSet = FXCollections.observableArrayList();
@@ -198,7 +204,7 @@ public class ContractVerifyWindowController extends BaseController {
@FXML
public TableColumn<Model, String> viewTable_nameColumn;
@FXML
public TableColumn<Model, Employee> viewTable_employeeColumn;
public TableColumn<Model, Integer> viewTable_employeeColumn;
@FXML
public TableColumn<Model, LocalDate> viewTable_setupDateColumn;
@FXML
@@ -224,9 +230,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 +249,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 +263,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,17 +277,17 @@ public class ContractVerifyWindowController extends BaseController {
break;
}
Page<Contract> page = contractService.findAll(spec, pageRequest);
for (Contract contract : page) {
Page<ContractVo> page = contractService.findAll(params, pageRequest);
for (ContractVo contract : page) {
if (isCloseRequested()) {
break;
}
counter.incrementAndGet();
Model model = new Model();
viewTableDataSet.add(model);
Employee handler = contract.getHandler();
Integer handler = contract.getHandlerId();
if (handler == null) {
model.getEmployee().set(contract.getEmployee());
model.getEmployee().set(contract.getEmployeeId());
} else {
model.getEmployee().set(handler);
}
@@ -298,6 +295,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 +321,6 @@ public class ContractVerifyWindowController extends BaseController {
});
}
public void onContractReVerifyAction(ActionEvent event) {
Model selectedItem = viewTable.getSelectionModel().getSelectedItem();
if (selectedItem == null) {
@@ -338,7 +335,13 @@ public class ContractVerifyWindowController extends BaseController {
return;
}
runAsync(() -> {
Contract contract = contractService.findByCode(contractCode);
ContractVo contract = null;
try {
contract = contractService.findByCode(contractCode);
} catch (Exception e) {
handleException("查找合同 " + contractCode + " 时发生错误", e);
return;
}
if (contract == null) {
return;
}
@@ -362,7 +365,6 @@ public class ContractVerifyWindowController extends BaseController {
});
}
public void onShowContractDetailAction(ActionEvent event) {
Model selectedItem = viewTable.getSelectionModel().getSelectedItem();
if (selectedItem == null) {
@@ -376,7 +378,13 @@ public class ContractVerifyWindowController extends BaseController {
if (!StringUtils.hasText(contractCode)) {
return;
}
Contract contract = contractService.findByCode(contractCode);
ContractVo contract = null;
try {
contract = contractService.findByCode(contractCode);
} catch (Exception e) {
handleException("查找合同 " + contractCode + " 时发生错误", e);
return;
}
if (contract == null) {
return;
}
@@ -389,7 +397,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,46 +1,57 @@
package com.ecep.contract.manager.ds.contract.controller;
package com.ecep.contract.controller.contract;
import java.io.File;
import com.ecep.contract.manager.ds.company.controller.CompanyWindowController;
import com.ecep.contract.manager.ds.company.model.Company;
import com.ecep.contract.manager.ds.company.service.CompanyService;
import com.ecep.contract.manager.ds.contract.model.Contract;
import com.ecep.contract.manager.ds.contract.service.ContractService;
import com.ecep.contract.manager.ds.contract.tasker.ContractRepairTask;
import com.ecep.contract.manager.ds.contract.tasker.ContractVerifyTasker;
import com.ecep.contract.manager.ds.contract.vo.ContractViewModel;
import com.ecep.contract.manager.ds.project.service.ProjectService;
import com.ecep.contract.manager.ui.AbstEntityController;
import com.ecep.contract.manager.ui.FxmlPath;
import com.ecep.contract.manager.util.DesktopUtils;
import com.ecep.contract.manager.util.UITools;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.scene.control.*;
import javafx.scene.layout.BorderPane;
import javafx.stage.Window;
import javafx.stage.WindowEvent;
import javafx.util.converter.LocalDateStringConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.io.File;
import java.time.format.DateTimeFormatter;
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.ContractTabSkinBase;
import com.ecep.contract.controller.tab.ContractTabSkinFiles;
import com.ecep.contract.controller.tab.ContractTabSkinItemsV2;
import com.ecep.contract.controller.tab.ContractTabSkinPayPlan;
import com.ecep.contract.controller.tab.ContractTabSkinPurchaseOrders;
import com.ecep.contract.controller.tab.ContractTabSkinSaleOrders;
import com.ecep.contract.controller.tab.ContractTabSkinSubContract;
import com.ecep.contract.controller.tab.ContractTabSkinVendorBid;
import com.ecep.contract.service.CompanyService;
import com.ecep.contract.service.ContractService;
import com.ecep.contract.task.ContractRepairTask;
import com.ecep.contract.task.ContractVerifyTasker;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vm.ContractViewModel;
import com.ecep.contract.vo.CompanyVo;
import com.ecep.contract.vo.ContractVo;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.scene.control.Button;
import javafx.scene.control.DatePicker;
import javafx.scene.control.Label;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.stage.Window;
import javafx.stage.WindowEvent;
@Lazy
@Scope("prototype")
@Component
@FxmlPath("/ui/contract/contract.fxml")
public class ContractWindowController
extends AbstEntityController<Contract, ContractViewModel> {
extends AbstEntityController<ContractVo, ContractViewModel> {
public static void show(Contract contract, Window owner) {
ContractViewModel model = new ContractViewModel();
model.update(contract);
show(model, owner);
public static void show(ContractVo contract, Window owner) {
show(ContractViewModel.from(contract), owner);
}
/**
@@ -63,16 +74,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 +125,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 +145,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,9 +173,8 @@ public class ContractWindowController
registerTabSkin(fileTab, tab -> new ContractTabSkinFiles(this));
}
public void onContractOpenInExplorerAction(ActionEvent event) {
Contract contract = getEntity();
ContractVo contract = getEntity();
String path = contract.getPath();
if (!StringUtils.hasText(path)) {
setStatus("未设置目录");
@@ -188,13 +189,13 @@ public class ContractWindowController
}
public void onContractOpenRelativeCompanyAction(ActionEvent event) {
Contract contract = getEntity();
if (contract.getCompany() == null) {
ContractVo contract = getEntity();
if (contract.getCompanyId() == null) {
UITools.showAlertAndWait("没有关联的公司,你可以尝试同步修复异常。");
return;
}
Integer companyId = contract.getCompany().getId();
Company company = companyService.findById(companyId);
Integer companyId = contract.getCompanyId();
CompanyVo company = getCompanyService().findById(companyId);
if (company != null) {
CompanyWindowController.show(company, root.getScene().getWindow());
}
@@ -202,7 +203,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 +221,7 @@ public class ContractWindowController
}
}
if (task.isItemsUpdated()) {
ContractTabSkinItems tabSkin = getTabSkin(ContractTabSkinItems.class);
ContractTabSkinItemsV2 tabSkin = getTabSkin(ContractTabSkinItemsV2.class);
if (tabSkin != null) {
tabSkin.loadTableDataSet();
}
@@ -234,14 +234,12 @@ public class ContractWindowController
}
}
/**
* 验证合同合规性
*/
public void onContractVerifyAction(ActionEvent event) {
Contract contract = getEntity();
ContractVo contract = getEntity();
ContractVerifyTasker task = new ContractVerifyTasker();
task.setContractService(contractService);
task.setContract(contract);
UITools.showTaskDialogAndWait("同步合规性验证", task, null);
}

View File

@@ -1,25 +1,33 @@
package com.ecep.contract.manager.ds.contract.controller.sale_order;
package com.ecep.contract.controller.contract.sale_order;
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 com.ecep.contract.vo.SalesOrderVo;
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.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
@FxmlPath("/ui/contract/sale-orders.fxml")
public class SalesOrderWindowController extends AbstEntityController<SalesOrder, SalesOrderViewModel> {
public class SalesOrderWindowController extends AbstEntityController<SalesOrderVo, SalesOrderViewModel> {
private static final Logger logger = LoggerFactory.getLogger(SalesOrderWindowController.class);
public TabPane tabPane;
public Button saveBtn;
@@ -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

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

View File

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

View File

@@ -0,0 +1,33 @@
package com.ecep.contract.controller.customer;
import com.ecep.contract.MessageHolder;
import com.ecep.contract.WebSocketClientTasker;
import com.ecep.contract.task.Tasker;
import com.ecep.contract.vo.CompanyCustomerVo;
import lombok.Setter;
/**
* 客户评估表更新任务
*/
public class CompanyCustomerEvaluationFormUpdateTask extends Tasker<Object> implements WebSocketClientTasker {
@Setter
private CompanyCustomerVo customer;
@Override
public String getTaskName() {
return getClass().getSimpleName();
}
@Override
public void updateProgress(long current, long total) {
super.updateProgress(current, total);
}
@Override
protected Object execute(MessageHolder holder) throws Exception {
updateTitle("客户评估表更新任务");
return callRemoteTask(holder, getLocale(), customer.getId());
}
}

View File

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

View File

@@ -1,32 +1,28 @@
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.controller.table.cell.CustomerCatalogTableCell;
import com.ecep.contract.service.CompanyCustomerService;
import com.ecep.contract.service.CompanyService;
import com.ecep.contract.service.CustomerCatalogService;
import com.ecep.contract.vm.CompanyCustomerViewModel;
import com.ecep.contract.vo.CompanyCustomerVo;
import com.ecep.contract.vo.CompanyVo;
import javafx.application.Platform;
import lombok.Setter;
public class CompanyCustomerManagerSkin
extends
AbstEntityManagerSkin<CompanyCustomer, CompanyCustomerViewModel, CompanyCustomerManagerSkin, CompanyCustomerManagerWindowController> {
@Setter
private CompanyService companyService;
AbstEntityManagerSkin<CompanyCustomerVo, CompanyCustomerViewModel, CompanyCustomerManagerSkin, CompanyCustomerManagerWindowController> {
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 +33,10 @@ 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(CompanyTableCell.forTableColumn(getCompanyService()));
controller.catalogColumn.setCellValueFactory(param -> param.getValue().getCatalog());
controller.catalogColumn.setCellFactory(CustomerCatalogTableCell.forTableColumn(getBean(CustomerCatalogService.class)));
controller.developDateColumn.setCellValueFactory(param -> param.getValue().getDevelopDate());
controller.pathColumn.setCellValueFactory(param -> param.getValue().getPath());

View File

@@ -1,11 +1,12 @@
package com.ecep.contract.manager.ds.customer.controller;
package com.ecep.contract.controller.customer;
import java.io.File;
import java.time.LocalDate;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicBoolean;
import org.hibernate.Hibernate;
import com.ecep.contract.vo.CompanyCustomerVo;
import com.ecep.contract.vo.CompanyVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
@@ -14,15 +15,13 @@ import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.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.service.CompanyCustomerService;
import com.ecep.contract.service.CompanyService;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vm.CompanyCustomerViewModel;
import javafx.application.Platform;
import javafx.collections.FXCollections;
@@ -45,24 +44,27 @@ import javafx.stage.Stage;
@Component
@FxmlPath("/ui/company/customer/customer_manager.fxml")
public class CompanyCustomerManagerWindowController
extends AbstManagerWindowController<CompanyCustomer, CompanyCustomerViewModel, CompanyCustomerManagerSkin> {
extends AbstManagerWindowController<CompanyCustomerVo, CompanyCustomerViewModel, CompanyCustomerManagerSkin> {
// columns
public TableColumn<CompanyCustomerViewModel, Number> idColumn;
public TableColumn<CompanyCustomerViewModel, Company> companyColumn;
public TableColumn<CompanyCustomerViewModel, String> catalogColumn;
/**
* 客户所属公司,Company
*/
public TableColumn<CompanyCustomerViewModel, Integer> companyColumn;
public TableColumn<CompanyCustomerViewModel, Integer> catalogColumn;
public TableColumn<CompanyCustomerViewModel, LocalDate> developDateColumn;
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);
}
private CompanyService getCompanyService() {
return getCachedBean(CompanyService.class);
}
@Override
@@ -74,7 +76,6 @@ public class CompanyCustomerManagerWindowController
@Override
protected CompanyCustomerManagerSkin createDefaultSkin() {
CompanyCustomerManagerSkin skin = new CompanyCustomerManagerSkin(this);
skin.setCompanyService(companyService);
return skin;
}
@@ -116,21 +117,18 @@ public class CompanyCustomerManagerWindowController
CompletableFuture.runAsync(() -> {
Pageable pageRequest = PageRequest.ofSize(50);
while (!canceled.get()) {
Page<CompanyCustomer> page = companyCustomerService.findAll(null, pageRequest);
Page<CompanyCustomerVo> page = getViewModelService().findAll(null, pageRequest);
int index = page.getNumber() * page.getSize();
int i = 1;
for (CompanyCustomer companyCustomer : page) {
for (CompanyCustomerVo companyCustomer : page) {
if (canceled.get()) {
return;
}
Company company = companyCustomer.getCompany();
if (!Hibernate.isInitialized(company)) {
company = companyService.findById(company.getId());
}
CompanyVo company = getCompanyService().findById(companyCustomer.getCompanyId());
String prefix = (index + i) + "/" + page.getTotalElements() + ", " + company.getName() + "> ";
companyCustomerService.reBuildingFiles(companyCustomer, msg -> {
getViewModelService().reBuildingFiles(companyCustomer, (level, msg) -> {
Platform.runLater(() -> {
listViewDataSet.add(prefix + msg);
listView.scrollTo(listViewDataSet.size() - 1);
@@ -164,7 +162,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

@@ -0,0 +1,34 @@
package com.ecep.contract.controller.customer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.ecep.contract.MessageHolder;
import com.ecep.contract.WebSocketClientTasker;
import com.ecep.contract.task.Tasker;
import com.ecep.contract.vo.CompanyCustomerVo;
import lombok.Setter;
public class CompanyCustomerNextSignDateTask extends Tasker<Object> implements WebSocketClientTasker {
private static final Logger logger = LoggerFactory.getLogger(CompanyCustomerNextSignDateTask.class);
@Setter
private CompanyCustomerVo customer;
@Override
public String getTaskName() {
return getClass().getSimpleName();
}
@Override
public void updateProgress(long current, long total) {
super.updateProgress(current, total);
}
@Override
protected Object execute(MessageHolder holder) throws Exception {
updateTitle("计算客户下一个评价日期");
return callRemoteTask(holder, getLocale(), customer.getId());
}
}

View File

@@ -1,32 +1,33 @@
package com.ecep.contract.manager.ds.customer.controller;
package com.ecep.contract.controller.customer;
import java.io.File;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import org.springframework.util.StringUtils;
import com.ecep.contract.MyDateTimeUtils;
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.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.vo.CompanyCustomerVo;
import com.ecep.contract.vo.CompanyVo;
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;
import javafx.scene.control.Tab;
import javafx.scene.control.TextField;
import javafx.stage.DirectoryChooser;
import javafx.util.converter.LocalDateStringConverter;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class CompanyCustomerTabSkinBase
extends AbstEntityBasedTabSkin<CompanyCustomerWindowController, CompanyCustomer, CompanyCustomerViewModel>
extends AbstEntityBasedTabSkin<CompanyCustomerWindowController, CompanyCustomerVo, CompanyCustomerViewModel>
implements TabSkin {
public CompanyCustomerTabSkinBase(CompanyCustomerWindowController controller) {
@@ -43,6 +44,8 @@ public class CompanyCustomerTabSkinBase
initializeCompanyFieldAutoCompletion(controller.companyField);
initializeContactFieldAutoCompletion(controller.contactField);
UITools.autoCompletion(controller.contactField, viewModel.getContact(), getCompanyContactService());
LocalDateStringConverter converter = new LocalDateStringConverter(DateTimeFormatter.ISO_LOCAL_DATE, null);
controller.developDateField.setConverter(converter);
@@ -53,19 +56,20 @@ 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());
controller.relativeCompanyBtn.setOnAction(event -> {
Company company = viewModel.getCompany().get();
if (company != null) {
CompanyWindowController.show(company, controller.root.getScene().getWindow());
Integer companyId = viewModel.getCompany().get();
if (companyId != null) {
CompanyVo company = getCompanyService().findById(companyId);
if (company != null) {
CompanyWindowController.show(company, controller.root.getScene().getWindow());
}
}
});
controller.createPathBtn.setOnAction(this::onCompanyCustomerCreatePathAction);
controller.changePathBtn.setOnAction(this::onCompanyCustomerChangePathAction);
controller.pathAsNameBtn.setOnAction(this::onCompanyCustomerPathSameAsNameAction);
@@ -80,18 +84,15 @@ 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(), getCompanyContactService());
}
private void initializeCompanyFieldAutoCompletion(TextField textField) {
CompanyStringConverter converter = SpringApp.getBean(CompanyStringConverter.class);
UITools.autoCompletion(textField, viewModel.getCompany(), converter::suggest, converter);
UITools.autoCompletion(textField, viewModel.getCompany(), getCompanyService());
}
public void onCompanyCustomerCreatePathAction(ActionEvent event) {
CompanyCustomer companyCustomer = getCompanyCustomerService().findById(viewModel.getId().get());
CompanyCustomerVo companyCustomer = getCompanyCustomerService().findById(viewModel.getId().get());
if (getCompanyCustomerService().makePathAbsent(companyCustomer)) {
companyCustomer = getCompanyCustomerService().save(companyCustomer);
viewModel.update(companyCustomer);
@@ -100,9 +101,34 @@ public class CompanyCustomerTabSkinBase
}
}
public void onCompanyCustomerChangePathAction(ActionEvent event) {
setStatus("未实现");
DirectoryChooser chooser = new DirectoryChooser();
CompanyCustomerVo entity = getEntity();
String path = entity.getPath();
File initialDirectory = null;
// 如果当前已经设置了目录并且路径有效则设置初始目录为该目录
if (StringUtils.hasText(path)) {
File dir = new File(path);
if (dir.exists()) {
initialDirectory = dir;
}
}
// 如果没有有效的初始目录则使用基础路径
if (initialDirectory == null) {
initialDirectory = getCompanyCustomerService().getBasePath();
}
if (initialDirectory != null) {
chooser.setInitialDirectory(initialDirectory);
}
File newDirectory = chooser.showDialog(getTab().getContent().getScene().getWindow());
if (newDirectory != null) {
entity.setPath(newDirectory.getAbsolutePath());
save(entity);
}
}
public void onCompanyCustomerPathSameAsNameAction(ActionEvent event) {
@@ -110,14 +136,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,45 +1,49 @@
package com.ecep.contract.manager.ds.customer.controller;
package com.ecep.contract.controller.customer;
import com.ecep.contract.manager.ds.company.service.CompanyContactService;
import 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.service.CompanyContactService;
import com.ecep.contract.service.CompanyCustomerService;
import com.ecep.contract.service.CompanyService;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.vm.CompanyCustomerViewModel;
import com.ecep.contract.vo.CompanyCustomerVo;
import com.ecep.contract.vo.CompanyVo;
import javafx.event.ActionEvent;
import javafx.scene.control.Button;
import javafx.scene.control.DatePicker;
import javafx.scene.control.Label;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import javafx.stage.Window;
import javafx.stage.WindowEvent;
@Lazy
@Scope("prototype")
@Component
@FxmlPath("/ui/company/customer/customer.fxml")
public class CompanyCustomerWindowController extends AbstEntityController<CompanyCustomer, CompanyCustomerViewModel> {
public class CompanyCustomerWindowController extends AbstEntityController<CompanyCustomerVo, CompanyCustomerViewModel> {
private static final Logger logger = LoggerFactory.getLogger(CompanyCustomerWindowController.class);
/**
* 显示界面
*/
public static void show(CompanyCustomer customer, Window window) {
CompanyCustomerViewModel viewModel = new CompanyCustomerViewModel();
viewModel.update(customer);
show(CompanyCustomerWindowController.class, viewModel, window);
public static void show(CompanyCustomerVo customer, Window window) {
show(CompanyCustomerWindowController.class, CompanyCustomerViewModel.from(customer), window);
}
public Tab baseInfoTab;
@@ -48,14 +52,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,18 +66,14 @@ public class CompanyCustomerWindowController extends AbstEntityController<Compan
public Button pathAsNameBtn;
public Button OpenCustomerPathInExplorerBtn;
@Override
public void show(Stage stage) {
super.show(stage);
getTitle().bind(viewModel.getCompany().map(company -> {
if (company == null) {
getTitle().bind(viewModel.getCompany().map(companyId -> {
if (companyId == null) {
return "-";
}
if (!Hibernate.isInitialized(company)) {
company = companyService.findById(company.getId());
viewModel.getCompany().set(company);
}
CompanyVo company = getCompanyService().findById(companyId);
return getMessage("ui.customer.title", String.valueOf(viewModel.getId().get()), company.getName());
}));
}
@@ -96,7 +88,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 +119,4 @@ public class CompanyCustomerWindowController extends AbstEntityController<Compan
DesktopUtils.showInExplorer(file);
}
}

View File

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

View File

@@ -1,57 +1,69 @@
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.concurrent.CompletableFuture;
import java.util.concurrent.ScheduledExecutorService;
import java.util.function.Consumer;
import com.ecep.contract.controller.table.cell.CompanyCustomerFileTableTypeTableCell;
import com.ecep.contract.controller.table.cell.FilePathTableCell;
import org.springframework.util.StringUtils;
import com.ecep.contract.CustomerFileType;
import com.ecep.contract.DesktopUtils;
import com.ecep.contract.Message;
import com.ecep.contract.MyDateTimeUtils;
import com.ecep.contract.SpringApp;
import com.ecep.contract.constant.CompanyCustomerConstant;
import com.ecep.contract.controller.table.EditableEntityTableTabSkin;
import com.ecep.contract.model.BaseEnumEntity;
import com.ecep.contract.service.CompanyCustomerEvaluationFormFileService;
import com.ecep.contract.service.CompanyCustomerFileService;
import com.ecep.contract.service.CompanyCustomerFileTypeService;
import com.ecep.contract.service.CompanyCustomerService;
import com.ecep.contract.service.CompanyService;
import com.ecep.contract.task.CustomerFileMoveTasker;
import com.ecep.contract.util.FileUtils;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.util.ParamUtils;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vm.CompanyCustomerFileViewModel;
import com.ecep.contract.vo.CompanyCustomerEvaluationFormFileVo;
import com.ecep.contract.vo.CompanyCustomerFileVo;
import com.ecep.contract.vo.CompanyCustomerVo;
import com.ecep.contract.vo.CompanyVo;
import com.ecep.contract.vo.CustomerFileTypeLocalVo;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.collections.FXCollections;
import javafx.collections.ObservableMap;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.MenuItem;
import javafx.scene.control.Tab;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.CheckBoxTableCell;
import javafx.scene.input.Dragboard;
import javafx.scene.input.TransferMode;
import lombok.Setter;
@FxmlPath("/ui/company/customer/customer-tab-file.fxml")
public class CustomerTabSkinFile
extends AbstCompanyCustomerTableTabSkin<CompanyCustomerFile, CompanyCustomerFileViewModel>
implements EditableEntityTableTabSkin<CompanyCustomerFile, CompanyCustomerFileViewModel> {
extends AbstCompanyCustomerTableTabSkin<CompanyCustomerFileVo, CompanyCustomerFileViewModel>
implements EditableEntityTableTabSkin<CompanyCustomerFileVo, CompanyCustomerFileViewModel> {
@Setter
private CompanyCustomerFileService companyCustomerFileService;
public TableColumn<CompanyCustomerFileViewModel, Number> fileTable_idColumn;
public TableColumn<CompanyCustomerFileViewModel, String> fileTable_typeColumn;
public TableColumn<CompanyCustomerFileViewModel, CustomerFileType> fileTable_typeColumn;
public TableColumn<CompanyCustomerFileViewModel, String> fileTable_filePathColumn;
public TableColumn<CompanyCustomerFileViewModel, String> fileTable_editFilePathColumn;
public TableColumn<CompanyCustomerFileViewModel, LocalDate> fileTable_signDateColumn;
@@ -82,11 +94,15 @@ public class CustomerTabSkinFile
return getCompanyCustomerFileService();
}
public CompanyCustomerEvaluationFormFileService getEvaluationFormFileService() {
return getCachedBean(CompanyCustomerEvaluationFormFileService.class);
}
@Override
public Specification<CompanyCustomerFile> getSpecification(CompanyCustomer parent) {
return SpecificationUtils.and(getSpecification(), (root, query, builder) -> {
return builder.equal(root.get("customer"), parent);
});
public ParamUtils.Builder getSpecification(CompanyCustomerVo parent) {
ParamUtils.Builder params = getSpecification();
params.equals("customer", parent.getId());
return params;
}
@Override
@@ -97,15 +113,16 @@ 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();
fileTable_typeColumn.setCellValueFactory(param -> Bindings.valueAt(observableMapByLocal,
param.getValue().getType()).map(BaseEnumEntity::getValue));
CompanyCustomerFileTypeService fileTypeService = getCachedBean(CompanyCustomerFileTypeService.class);
fileTable_typeColumn.setCellValueFactory(param -> param.getValue().getType());
fileTable_typeColumn.setCellFactory(CompanyCustomerFileTableTypeTableCell.forTableColumn(fileTypeService));
fileTable_filePathColumn.setCellValueFactory(param -> param.getValue().getFilePath());
fileTable_filePathColumn.setCellFactory(param -> new FileTableFilePathTableCell());
fileTable_filePathColumn.setCellFactory(FilePathTableCell.forTableColumn(viewModel.getPath()));
fileTable_editFilePathColumn.setCellValueFactory(param -> param.getValue().getEditFilePath());
fileTable_editFilePathColumn.setCellFactory(param -> new FileTableFilePathTableCell());
fileTable_editFilePathColumn.setCellFactory(FilePathTableCell.forTableColumn(viewModel.getPath()));
fileTable_signDateColumn.setCellValueFactory(param -> param.getValue().getSignDate());
fileTable_validColumn.setEditable(true);
fileTable_validColumn.setCellValueFactory(param -> param.getValue().getValid());
@@ -147,11 +164,16 @@ public class CustomerTabSkinFile
@Override
protected void onTableRowDoubleClickedAction(CompanyCustomerFileViewModel item) {
CompanyCustomerFileType fileType = item.getType().get();
if (fileType == CompanyCustomerFileType.EvaluationForm) {
CustomerFileType fileType = item.getType().get();
if (fileType == CustomerFileType.EvaluationForm) {
// 文件不是 Excel 文件时打开编辑UI
if (!CompanyFileUtils.withExtensions(item.getFilePath().get(), CompanyFileUtils.XLS, CompanyFileUtils.XLSX)) {
CompanyCustomerEvaluationFormFileWindowController.show(item, controller.root.getScene().getWindow());
if (!FileUtils.withExtensions(item.getFilePath().get(), FileUtils.XLS,
FileUtils.XLSX)) {
CompanyCustomerEvaluationFormFileVo evaluationFormFile = getEvaluationFormFileService()
.findByCustomerFile(item.getId().get());
CompanyCustomerEvaluationFormFileWindowController.show(evaluationFormFile,
controller.root.getScene().getWindow());
return;
}
}
@@ -174,28 +196,35 @@ public class CustomerTabSkinFile
setStatus("目录错误,不存在");
return;
}
CompanyCustomer companyCustomer = getParent();
LocalDate nextSignDate = getCompanyCustomerFileService().getNextSignDate(companyCustomer, this::setStatus);
CompanyCustomerVo companyCustomer = getParent();
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)) {
CompanyCustomerFile ccf = new CompanyCustomerFile();
ccf.setCustomer(companyCustomer);
ccf.setType(CompanyCustomerFileType.EvaluationForm);
CompanyCustomerFileVo ccf = new CompanyCustomerFileVo();
ccf.setCustomer(companyCustomer.getId());
ccf.setType(CustomerFileType.EvaluationForm);
ccf.setFilePath(dest.getAbsolutePath());
ccf.setSignDate(nextSignDate);
ccf.setValid(false);
CompanyCustomerFile saved = getCompanyCustomerFileService().save(ccf);
CompanyCustomerFileVo saved = getCompanyCustomerFileService().save(ccf);
Platform.runLater(() -> {
CompanyCustomerFileViewModel model = new CompanyCustomerFileViewModel();
model.update(saved);
dataSet.add(model);
CompanyCustomerEvaluationFormFileWindowController.show(model, getTableView().getScene().getWindow());
CompanyCustomerEvaluationFormFileVo evaluationFormFile = getCachedBean(
CompanyCustomerEvaluationFormFileService.class).findByCustomerFile(saved);
CompanyCustomerEvaluationFormFileWindowController.show(evaluationFormFile,
getTableView().getScene().getWindow());
});
return;
}
@@ -203,51 +232,31 @@ public class CustomerTabSkinFile
}
List<CompanyCustomerFile> companyCustomerFiles = new ArrayList<>();
for (File file : files) {
File dest = new File(dir, file.getName());
if (file.renameTo(dest)) {
CompanyCustomerFile ccf = new CompanyCustomerFile();
ccf.setCustomer(companyCustomer);
ccf.setType(CompanyCustomerFileType.General);
CompanyCustomerFileVo ccf = new CompanyCustomerFileVo();
ccf.setCustomer(companyCustomer.getId());
ccf.setType(CustomerFileType.General);
ccf.setFilePath(dest.getAbsolutePath());
ccf.setValid(false);
companyCustomerFiles.add(ccf);
getCompanyCustomerFileService().save(ccf);
}
}
getCompanyCustomerFileService().saveAll(companyCustomerFiles);
loadTableDataSet();
}
public void onFileReBuildingAction(ActionEvent event) {
CompletableFuture.runAsync(() -> {
CompanyCustomerService customerService = getCompanyCustomerService();
try {
CompanyCustomer companyCustomer = customerService.findById(viewModel.getId().get());
if (customerService.reBuildingFiles(companyCustomer, this::setStatus)) {
loadTableDataSet();
}
} catch (Exception e) {
e.printStackTrace();
CompanyCustomerService customerService = getCompanyCustomerService();
try {
CompanyCustomerVo companyCustomer = customerService.findById(viewModel.getId().get());
if (customerService.reBuildingFiles(companyCustomer, (level, message) -> setStatus(message))) {
loadTableDataSet();
}
});
}
@Override
public CompanyCustomerFile loadRowData(CompanyCustomerFileViewModel row) {
return getCompanyCustomerFileService().findById(row.getId().get());
}
@Override
public CompanyCustomerFile saveRowData(CompanyCustomerFile entity) {
return getCompanyCustomerFileService().save(entity);
}
@Override
public void deleteRowData(CompanyCustomerFile entity) {
getCompanyCustomerFileService().delete(entity);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
@@ -270,14 +279,16 @@ public class CustomerTabSkinFile
return false;
}
public void onFileTableMoveToCompanyPathAction(ActionEvent event) {
Company company = viewModel.getCompany().get();
if (!Hibernate.isInitialized(company)) {
company = getCompanyService().findById(company.getId());
viewModel.getCompany().set(company);
CompanyCustomerFileViewModel selectedItem = getSelectedItem();
if (selectedItem == null) {
return;
}
// 检查公司目录设置
Integer companyId = viewModel.getCompany().get();
CompanyVo company = getCompanyService().findById(companyId);
if (!StringUtils.hasText(company.getPath())) {
setStatus("公司目录未设置");
return;
@@ -285,44 +296,19 @@ public class CustomerTabSkinFile
File companyPath = new File(company.getPath());
if (!companyPath.exists()) {
setStatus("公司目录设置设置异常,无法访问");
setStatus("公司目录设置异常,无法访问");
return;
}
CompanyCustomerFileViewModel selectedItem = getSelectedItem();
if (selectedItem == null) {
return;
}
String filePath = selectedItem.getFilePath().get();
String editFilePath = selectedItem.getEditFilePath().get();
// 创建并启动任务
CustomerFileMoveTasker task = new CustomerFileMoveTasker();
task.setFileId(selectedItem.getId().get());
UITools.showTaskDialogAndWait("移动文件到公司目录", task, null);
if (StringUtils.hasText(filePath)) {
File file = new File(filePath);
if (file.exists()) {
File dest = new File(companyPath, file.getName());
if (file.renameTo(dest)) {
setStatus(file.getAbsolutePath() + " -> " + dest.getAbsolutePath());
}
}
}
if (StringUtils.hasText(editFilePath)) {
File file = new File(editFilePath);
if (file.exists()) {
File dest = new File(companyPath, file.getName());
if (file.renameTo(dest)) {
setStatus(file.getAbsolutePath() + " -> " + dest.getAbsolutePath());
}
}
}
deleteRow(selectedItem);
// getCompanyCustomerService().deleteFileById(selectedItem.getId().get());
// dataSet.remove(selectedItem);
// 刷新表格数据
loadTableDataSet();
}
private void initializeTask(Task<Object> task, String prefix, Consumer<String> consumer) {
task.setOnScheduled(e -> {
consumer.accept("正在" + prefix + ",请稍后...");
@@ -342,8 +328,6 @@ public class CustomerTabSkinFile
public void onUpdateEvaluationFormAction(ActionEvent event) {
CompanyCustomerEvaluationFormUpdateTask task = new CompanyCustomerEvaluationFormUpdateTask();
task.setCompanyService(getCompanyService());
task.setCompanyCustomerFileService(getCompanyCustomerFileService());
task.setCustomer(getCompanyCustomerService().findById(viewModel.getId().get()));
UITools.showTaskDialogAndWait("更新评价表", task, consumer -> {
initializeTask(task, "更新评价表", msg -> consumer.accept(Message.info(msg)));
@@ -351,11 +335,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 -> {
CompanyCustomerVo companyCustomer = getCompanyCustomerService().findById(viewModel.getId().get());
LocalDate nextSignDate = getCompanyCustomerFileService().getNextSignDate(companyCustomer, (level, msg) -> {
Platform.runLater(() -> {
ds.add(msg);
});
@@ -368,27 +351,6 @@ public class CustomerTabSkinFile
});
}
class FileTableFilePathTableCell extends TableCell<CompanyCustomerFileViewModel, String> {
@Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (empty || !StringUtils.hasText(item)) {
setText("");
return;
}
String path = viewModel.getPath().get();
if (StringUtils.hasText(path)) {
if (item.startsWith(path)) {
item = "~" + item.substring(path.length());
}
}
setText(item);
}
}
private CompanyCustomerFileService getCompanyCustomerFileService() {
if (companyCustomerFileService == null) {
companyCustomerFileService = SpringApp.getBean(CompanyCustomerFileService.class);

View File

@@ -1,48 +1,49 @@
package com.ecep.contract.manager.ds.customer.controller;
package com.ecep.contract.controller.customer;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Map;
import com.ecep.contract.service.CustomerCatalogService;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.controller.project.satisfaction_survey.CustomerSatisfactionSurveyWindowController;
import com.ecep.contract.controller.table.cell.EmployeeTableCell;
import com.ecep.contract.controller.table.cell.ProjectTableCell;
import com.ecep.contract.converter.EntityStringConverter;
import com.ecep.contract.vo.CompanyCustomerVo;
import com.ecep.contract.vo.CustomerCatalogVo;
import com.ecep.contract.vo.CustomerSatisfactionSurveyVo;
import com.ecep.contract.vo.EmployeeVo;
import com.ecep.contract.vo.ProjectVo;
import com.ecep.contract.service.CustomerSatisfactionSurveyService;
import com.ecep.contract.service.ProjectService;
import com.ecep.contract.util.ParamUtils;
import com.ecep.contract.vm.CustomerEntityViewModel;
import com.ecep.contract.vm.CustomerSatisfactionSurveyViewModel;
import com.ecep.contract.manager.ds.company.model.Company;
import com.ecep.contract.manager.ds.customer.model.CompanyCustomer;
import com.ecep.contract.manager.ds.customer.model.CustomerCatalog;
import com.ecep.contract.manager.ds.customer.vo.CustomerEntityViewModel;
import com.ecep.contract.manager.ds.other.EntityStringConverter;
import com.ecep.contract.manager.ds.project.service.ProjectService;
import com.ecep.contract.manager.ui.table.cell.EmployeeTableCell;
import com.ecep.contract.manager.ds.other.model.Employee;
import com.ecep.contract.manager.ds.project.controller.satisfaction_survey.CustomerSatisfactionSurveyWindowController;
import com.ecep.contract.manager.ds.project.model.CustomerSatisfactionSurvey;
import com.ecep.contract.manager.ds.project.model.Project;
import com.ecep.contract.manager.ds.project.service.CustomerSatisfactionSurveyService;
import com.ecep.contract.manager.ds.project.vo.CustomerSatisfactionSurveyViewModel;
import com.ecep.contract.manager.ui.FxmlPath;
import com.ecep.contract.manager.ui.table.cell.ProjectTableCell;
import com.ecep.contract.manager.util.SpecificationUtils;
import javafx.scene.control.MenuItem;
import javafx.scene.control.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
extends AbstCompanyCustomerTableTabSkin<CustomerSatisfactionSurvey, CustomerSatisfactionSurveyViewModel> {
extends AbstCompanyCustomerTableTabSkin<CustomerSatisfactionSurveyVo, CustomerSatisfactionSurveyViewModel> {
// 关联项 tab
public TableColumn<CustomerSatisfactionSurveyViewModel, Number> idColumn;
public TableColumn<CustomerSatisfactionSurveyViewModel, Project> projectColumn;
public TableColumn<CustomerSatisfactionSurveyViewModel, Integer> projectColumn;
public TableColumn<CustomerSatisfactionSurveyViewModel, String> codeColumn;
public TableColumn<CustomerSatisfactionSurveyViewModel, Number> totalScoreColumn;
public TableColumn<CustomerSatisfactionSurveyViewModel, Employee> applicantColumn;
public TableColumn<CustomerSatisfactionSurveyViewModel, Integer> applicantColumn;
public TableColumn<CustomerSatisfactionSurveyViewModel, LocalDateTime> applyTimeColumn;
public TableColumn<CustomerSatisfactionSurveyViewModel, String> descriptionColumn;
public TableColumn<CustomerSatisfactionSurveyViewModel, LocalDate> dateColumn;
public MenuItem entityTable_menu_refresh;
public MenuItem entityTable_menu_del;
@Setter
private ProjectService projectService;
@Setter
private ProjectService projectService;
@Setter
private CustomerSatisfactionSurveyService satisfactionSurveyService;
@@ -55,19 +56,19 @@ private ProjectService projectService;
return controller.satisfactionTab;
}
@Override
public void initializeTab() {
super.initializeTab();
bindNumberColumn(idColumn, CustomerSatisfactionSurveyViewModel::getId);
bindColumn(codeColumn, CustomerSatisfactionSurveyViewModel::getCode);
projectColumn.setCellValueFactory(param -> param.getValue().getProject());
projectColumn.setCellFactory(cell -> new ProjectTableCell<>(getProjectService()));
projectColumn.setCellFactory(ProjectTableCell.forTableColumn(getProjectService()));
bindLocalDateColumn(dateColumn, CustomerSatisfactionSurveyViewModel::getDate);
bindNumberColumn(totalScoreColumn, CustomerSatisfactionSurveyViewModel::getTotalScore);
applicantColumn.setCellValueFactory(param -> param.getValue().getApplicant());
applicantColumn.setCellFactory(cell -> new EmployeeTableCell<>(getEmployeeService()));
applicantColumn.setCellFactory(EmployeeTableCell.forTableColumn(getEmployeeService()));
bindLocalDateTimeColumn(applyTimeColumn, CustomerSatisfactionSurveyViewModel::getApplyTime);
bindColumn(descriptionColumn, CustomerSatisfactionSurveyViewModel::getDescription);
@@ -75,13 +76,6 @@ 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()));
column.setCellValueFactory(param -> param.getValue().getCatalog().map(converter::toString));
}
private CustomerSatisfactionSurveyService getCustomerSatisfactionSurveyService() {
if (satisfactionSurveyService == null) {
satisfactionSurveyService = getBean(CustomerSatisfactionSurveyService.class);
@@ -102,14 +96,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 ParamUtils.Builder getSpecification(CompanyCustomerVo parent) {
ParamUtils.Builder params = getSpecification();
params.equals("project.customer", parent.getId());
return params;
}
@Override

View File

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

View File

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

View File

@@ -1,16 +1,18 @@
package com.ecep.contract.manager.ds.other.controller.employee;
package com.ecep.contract.controller.employee;
import com.ecep.contract.manager.ds.other.model.Employee;
import com.ecep.contract.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 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.vo.EmployeeVo;
import lombok.Setter;
public abstract class AbstEmployeeBasedTabSkin
extends AbstEntityBasedTabSkin<EmployeeWindowController, Employee, EmployeeViewModel>
extends AbstEntityBasedTabSkin<EmployeeWindowController, EmployeeVo, EmployeeViewModel>
implements TabSkin {
@Setter
private PermissionService permissionService;

View File

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

View File

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

View File

@@ -1,39 +1,40 @@
package com.ecep.contract.manager.ds.other.controller.employee;
package com.ecep.contract.controller.employee;
import java.time.LocalDate;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import com.ecep.contract.constant.CloudServiceConstant;
import com.ecep.contract.controller.AbstManagerWindowController;
import com.ecep.contract.model.Department;
import com.ecep.contract.service.EmployeeService;
import com.ecep.contract.task.EmployeesSyncTask;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vm.EmployeeViewModel;
import com.ecep.contract.vo.EmployeeVo;
import com.ecep.contract.manager.cloud.u8.EmployeesSyncTask;
import com.ecep.contract.manager.cloud.u8.YongYouU8Service;
import com.ecep.contract.manager.ds.other.model.Department;
import com.ecep.contract.manager.ds.other.model.Employee;
import com.ecep.contract.manager.ds.other.service.EmployeeService;
import com.ecep.contract.manager.ds.other.vo.EmployeeViewModel;
import com.ecep.contract.manager.ui.AbstManagerWindowController;
import com.ecep.contract.manager.ui.FxmlPath;
import com.ecep.contract.manager.util.UITools;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.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")
@Component
@FxmlPath("/ui/employee/employee-manager.fxml")
public class EmployeeManagerWindowController
extends AbstManagerWindowController<Employee, EmployeeViewModel, EmployeeManagerSkin> {
extends AbstManagerWindowController<EmployeeVo, EmployeeViewModel, EmployeeManagerSkin> {
@FXML
public TableColumn<EmployeeViewModel, Number> idColumn;
@FXML
public TableColumn<EmployeeViewModel, String> accountColumn;
@FXML
public TableColumn<EmployeeViewModel, Department> departmentColumn;
public TableColumn<EmployeeViewModel, Integer> departmentColumn;
@FXML
public TableColumn<EmployeeViewModel, String> nameColumn;
@FXML
@@ -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,31 +1,32 @@
package com.ecep.contract.manager.ds.other.controller.employee;
package com.ecep.contract.controller.employee;
import com.ecep.contract.manager.ds.other.model.Employee;
import com.ecep.contract.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 com.ecep.contract.Desktop;
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.vo.EmployeeAuthBindVo;
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
extends AbstEmployeeTableTabSkin<EmployeeAuthBind, EmployeeAuthBindViewModel> {
extends AbstEmployeeTableTabSkin<EmployeeAuthBindVo, EmployeeAuthBindViewModel> {
public TableColumn<EmployeeAuthBindViewModel, Number> idColumn;
public TableColumn<EmployeeAuthBindViewModel, String> ipColumn;
public TableColumn<EmployeeAuthBindViewModel, String> macColumn;
public TableColumn<EmployeeAuthBindViewModel, LocalDateTime> createTime;
public TableColumn<EmployeeAuthBindViewModel, LocalDateTime> updateTimeColumn;
public TableColumn<EmployeeAuthBindViewModel, Employee> updaterColumn;
public TableColumn<EmployeeAuthBindViewModel, Integer> updaterColumn;
public TableColumn<EmployeeAuthBindViewModel, String> descriptionColumn;
@Setter
@@ -79,13 +80,18 @@ public class EmployeeTabSkinAuthBind
protected void createContextMenu(ContextMenu contextMenu) {
super.createContextMenu(contextMenu);
MenuItem menuItem = new MenuItem("导入未关联");
int activeEmployeeId = Desktop.instance.getActiveEmployeeId();
if (activeEmployeeId <= 0) {
logger.warn("未登录员工{}", activeEmployeeId);
return;
}
menuItem.setOnAction(event -> {
EmployeeAuthBindService service = getEmployeeAuthBindService();
List<EmployeeAuthBind> authBinds = service.findAllByEmployee(null, Sort.unsorted());
for (EmployeeAuthBind authBind : authBinds) {
authBind.setEmployee(getEntity());
List<EmployeeAuthBindVo> authBinds = service.findAllByEmployee(null);
for (EmployeeAuthBindVo authBind : authBinds) {
authBind.setEmployeeId(getEntity().getId());
authBind.setUpdateTime(LocalDateTime.now());
authBind.setUpdater(controller.getCurrentUser());
authBind.setUpdaterId(activeEmployeeId);
service.save(authBind);
}
});

View File

@@ -1,15 +1,14 @@
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.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 {
@@ -24,11 +23,8 @@ public class EmployeeTabSkinBase
@Override
public void initializeTab() {
EntityStringConverter<Department> departmentEntityStringConverter = new EntityStringConverter<>();
DepartmentService departmentService = getBean(DepartmentService.class);
departmentEntityStringConverter.setInitialized(department -> departmentService.findById(department.getId()));
UITools.autoCompletion(controller.departmentField, viewModel.getDepartment(),
p -> departmentService.search(p.getUserText()), departmentEntityStringConverter);
getCachedBean(DepartmentService.class));
controller.nameField.textProperty().bindBidirectional(viewModel.getName());
controller.aliasField.textProperty().bindBidirectional(viewModel.getAlias());
@@ -48,23 +44,25 @@ public class EmployeeTabSkinBase
controller.isActiveField.selectedProperty().bindBidirectional(viewModel.getIsActive());
// Callback<ListView<EmployeeRole>, ListCell<EmployeeRole>> cellFactory =
// controller.rolesField.getCellFactory();
// StringConverter<EmployeeRole> employeeRoleStringConverter = new
// EntityStringConverter<>();
// controller.rolesField.setCellFactory(param -> {
// ListCell<EmployeeRole> cell = cellFactory.call(param);
// if (cell instanceof CheckBoxListCell<EmployeeRole> list) {
// list.setConverter(employeeRoleStringConverter);
// }
// return cell;
// });
// Callback<ListView<EmployeeRole>, ListCell<EmployeeRole>> cellFactory = controller.rolesField.getCellFactory();
// StringConverter<EmployeeRole> employeeRoleStringConverter = new EntityStringConverter<>();
// controller.rolesField.setCellFactory(param -> {
// ListCell<EmployeeRole> cell = cellFactory.call(param);
// if (cell instanceof CheckBoxListCell<EmployeeRole> list) {
// list.setConverter(employeeRoleStringConverter);
// }
// return cell;
// });
// controller.rolesField.getCheckModel().getCheckedItems().setAll();
// Property<IndexedCheckModel<EmployeeRole>> selectedRoles = new SimpleObjectProperty<>();
// controller.rolesField.getCheckModel().getCheckedItems().addListener((ListChangeListener<? super EmployeeRole>) changed -> {
// System.out.println("newValue = " + changed);
// });
// controller.rolesField.getCheckModel().getCheckedItems().setAll();
// Property<IndexedCheckModel<EmployeeRole>> selectedRoles = new
// SimpleObjectProperty<>();
// controller.rolesField.getCheckModel().getCheckedItems().addListener((ListChangeListener<?
// super EmployeeRole>) changed -> {
// System.out.println("newValue = " + changed);
// });
}
}

View File

@@ -1,20 +1,21 @@
package com.ecep.contract.manager.ds.other.controller.employee;
package com.ecep.contract.controller.employee;
import java.time.LocalDateTime;
import com.ecep.contract.controller.tab.TabSkin;
import com.ecep.contract.controller.table.cell.LocalDateTimeTableCell;
import com.ecep.contract.service.EmployeeLoginHistoryService;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.vo.EmployeeLoginHistoryVo;
import com.ecep.contract.vm.EmployeeLoginHistoryViewModel;
import com.ecep.contract.manager.ds.other.model.EmployeeLoginHistory;
import com.ecep.contract.manager.ds.other.service.EmployeeLoginHistoryService;
import com.ecep.contract.manager.ds.other.vo.EmployeeLoginHistoryViewModel;
import com.ecep.contract.manager.ui.FxmlPath;
import com.ecep.contract.manager.ui.tab.TabSkin;
import com.ecep.contract.manager.ui.table.cell.LocalDateTimeTableCell;
import javafx.application.Platform;
import javafx.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>
extends AbstEmployeeTableTabSkin<EmployeeLoginHistoryVo, EmployeeLoginHistoryViewModel>
implements TabSkin {
public TableColumn<EmployeeLoginHistoryViewModel, Number> idColumn;
public TableColumn<EmployeeLoginHistoryViewModel, String> ipColumn;

View File

@@ -1,18 +1,18 @@
package com.ecep.contract.manager.ds.other.controller.employee;
package com.ecep.contract.controller.employee;
import java.util.HashMap;
import java.util.List;
import org.springframework.data.domain.Pageable;
import com.ecep.contract.controller.tab.TabSkin;
import com.ecep.contract.vo.EmployeeRoleVo;
import com.ecep.contract.manager.Desktop;
import com.ecep.contract.manager.ds.other.model.Employee;
import com.ecep.contract.manager.ds.other.model.EmployeeRole;
import com.ecep.contract.manager.ui.tab.TabSkin;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.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.List;
public class EmployeeTabSkinRole
extends AbstEmployeeBasedTabSkin
@@ -41,24 +41,21 @@ public class EmployeeTabSkinRole
}
private void loadSelectedRoles() {
List<EmployeeRole> selectedRoles = getEmployeeService().getRolesByEmployeeId(viewModel.getId().get());
List<EmployeeRoleVo> selectedRoles = getEmployeeService().getRolesByEmployeeId(viewModel.getId().get());
controller.rolesField.getTargetItems().setAll(selectedRoles);
changed.set(false);
}
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<EmployeeRoleVo> roles = getEmployeeRoleService().findAll(params, Pageable.ofSize(500)).getContent();
controller.rolesField.getSourceItems().setAll(roles);
controller.rolesField.setCellFactory(param -> {
return new ListCell<>() {
return new ListCell<EmployeeRoleVo>() {
@Override
protected void updateItem(EmployeeRole item, boolean empty) {
protected void updateItem(EmployeeRoleVo item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setText(null);
@@ -69,10 +66,10 @@ public class EmployeeTabSkinRole
};
});
controller.rolesField.getTargetItems().addListener((ListChangeListener<EmployeeRole>) change -> {
controller.rolesField.getTargetItems().addListener((ListChangeListener<EmployeeRoleVo>) change -> {
while (change.next()) {
List<? extends EmployeeRole> added = change.getAddedSubList();
List<? extends EmployeeRole> removed = change.getRemoved();
List<? extends EmployeeRoleVo> added = change.getAddedSubList();
List<? extends EmployeeRoleVo> removed = change.getRemoved();
if (!added.isEmpty() || !removed.isEmpty()) {
changed.set(true);
}
@@ -82,9 +79,7 @@ public class EmployeeTabSkinRole
@Override
public void save() {
Employee entity = getEntity();
entity.setRoles(controller.rolesField.getTargetItems());
save(entity);
getEmployeeService().getUpdateEmployeeRoles(viewModel.getId().get(), controller.rolesField.getTargetItems());
loadSelectedRoles();
}
}

View File

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

View File

@@ -1,16 +1,18 @@
package com.ecep.contract.manager.ds.other.controller.inventory;
package com.ecep.contract.controller.inventory;
import java.util.function.Function;
import com.ecep.contract.controller.AbstEntityManagerSkin;
import com.ecep.contract.controller.table.cell.InventoryCatalogTableCell;
import com.ecep.contract.controller.table.cell.LocalDateFieldTableCell;
import com.ecep.contract.controller.table.cell.LocalDateTimeTableCell;
import com.ecep.contract.converter.EntityStringConverter;
import com.ecep.contract.service.InventoryCatalogService;
import com.ecep.contract.service.InventoryService;
import com.ecep.contract.vm.InventoryViewModel;
import com.ecep.contract.vo.InventoryCatalogVo;
import com.ecep.contract.vo.InventoryVo;
import com.ecep.contract.manager.ds.other.EntityStringConverter;
import com.ecep.contract.manager.ds.other.model.Inventory;
import com.ecep.contract.manager.ds.other.model.InventoryCatalog;
import com.ecep.contract.manager.ds.other.service.InventoryCatalogService;
import com.ecep.contract.manager.ds.other.service.InventoryService;
import com.ecep.contract.manager.ds.other.vo.InventoryViewModel;
import com.ecep.contract.manager.ui.AbstEntityManagerSkin;
import com.ecep.contract.manager.ui.table.EditableEntityTableTabSkin;
import com.ecep.contract.manager.ui.ManagerSkin;
import com.ecep.contract.manager.ui.util.LocalDateFieldTableCell;
import com.ecep.contract.manager.ui.table.cell.LocalDateTimeTableCell;
import javafx.beans.property.Property;
import javafx.event.ActionEvent;
import javafx.scene.control.TableColumn;
@@ -19,11 +21,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<InventoryVo, InventoryViewModel, InventoryManagerSkin, InventoryManagerWindowController> {
@Setter
private InventoryCatalogService catalogService;
@@ -58,18 +57,13 @@ public class InventoryManagerSkin
controller.codeColumn.setOnEditCommit(event -> onColumnEditCommit(event, InventoryViewModel::getCode));
controller.catalogColumn.setCellValueFactory(param -> param.getValue().getCatalog());
EntityStringConverter<InventoryCatalog> catalogStringConverter = new EntityStringConverter<>();
catalogStringConverter.setInitialized(v -> getInventoryCatalogService().findById(v.getId()));
catalogStringConverter.setFormater(InventoryCatalog::getName);
catalogStringConverter.setFromString(v -> getInventoryCatalogService().findByName(v));
catalogStringConverter.setSuggestion(getInventoryCatalogService()::search);
controller.catalogColumn.setCellFactory(TextFieldTableCell.forTableColumn(catalogStringConverter));
controller.catalogColumn.setCellFactory(param-> new InventoryCatalogTableCell<>(getInventoryCatalogService()));
controller.catalogColumn.setOnEditCommit(event -> onColumnEditCommit(event, InventoryViewModel::getCatalog));
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 +71,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);
@@ -122,7 +120,7 @@ public class InventoryManagerSkin
@Override
protected void onTableCreateNewAction(ActionEvent event) {
Inventory inventory = getService().save(getService().createNewInstance());
InventoryVo inventory = getService().save(getService().createNewEntity());
InventoryViewModel viewModel = InventoryViewModel.from(inventory);
dataSet.add(viewModel);
}

View File

@@ -1,4 +1,4 @@
package com.ecep.contract.manager.ds.other.controller.inventory;
package com.ecep.contract.controller.inventory;
import java.time.LocalDate;
import java.time.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.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 com.ecep.contract.vo.InventoryCatalogVo;
import com.ecep.contract.vo.InventoryVo;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
@@ -26,7 +27,7 @@ import javafx.stage.Stage;
@Component
@FxmlPath(value = "/ui/inventory/inventory-manager.fxml")
public class InventoryManagerWindowController
extends AbstManagerWindowController<Inventory, InventoryViewModel, InventoryManagerSkin> {
extends AbstManagerWindowController<InventoryVo, InventoryViewModel, InventoryManagerSkin> {
@FXML
public TableColumn<InventoryViewModel, Number> idColumn;
@@ -34,8 +35,11 @@ public class InventoryManagerWindowController
public TableColumn<InventoryViewModel, String> nameColumn;
@FXML
public TableColumn<InventoryViewModel, String> codeColumn;
/**
* InventoryCatalogVo
*/
@FXML
public TableColumn<InventoryViewModel, InventoryCatalog> catalogColumn;
public TableColumn<InventoryViewModel, Integer> catalogColumn;
@FXML
public TableColumn<InventoryViewModel, String> specificationColumn;
@FXML

View File

@@ -1,19 +1,25 @@
package com.ecep.contract.manager.ds.other.controller.inventory;
package com.ecep.contract.controller.inventory;
import java.text.NumberFormat;
import java.time.format.DateTimeFormatter;
import java.util.function.Consumer;
import org.springframework.util.StringUtils;
import com.ecep.contract.MessageHolder;
import com.ecep.contract.MyDateTimeUtils;
import com.ecep.contract.controller.tab.AbstEntityBasedTabSkin;
import com.ecep.contract.controller.tab.TabSkin;
import com.ecep.contract.controller.table.EditableEntityTableTabSkin;
import com.ecep.contract.converter.EmployeeStringConverter;
import com.ecep.contract.converter.EntityStringConverter;
import com.ecep.contract.service.InventoryCatalogService;
import com.ecep.contract.service.InventoryService;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vm.InventoryViewModel;
import com.ecep.contract.vo.InventoryCatalogVo;
import com.ecep.contract.vo.InventoryVo;
import com.ecep.contract.manager.cloud.u8.ctx.InventoryCtx;
import com.ecep.contract.manager.ds.other.EmployeeStringConverter;
import com.ecep.contract.manager.ds.other.EntityStringConverter;
import com.ecep.contract.manager.ds.other.model.Inventory;
import com.ecep.contract.manager.ds.other.model.InventoryCatalog;
import com.ecep.contract.manager.ds.other.service.InventoryCatalogService;
import com.ecep.contract.manager.ds.other.service.InventoryService;
import com.ecep.contract.manager.ds.other.vo.InventoryViewModel;
import com.ecep.contract.manager.ui.tab.AbstEntityBasedTabSkin;
import com.ecep.contract.manager.ui.table.EditableEntityTableTabSkin;
import com.ecep.contract.manager.ui.MessageHolder;
import com.ecep.contract.manager.ui.tab.TabSkin;
import com.ecep.contract.manager.util.MyDateTimeUtils;
import com.ecep.contract.manager.util.UITools;
import javafx.beans.binding.Bindings;
import javafx.beans.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;
extends AbstEntityBasedTabSkin<InventoryWindowController, InventoryVo, InventoryViewModel>
implements TabSkin, EditableEntityTableTabSkin<InventoryVo, InventoryViewModel> {
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
@@ -77,72 +67,84 @@ public class InventoryTabSkinBase
controller.specificationField.textProperty().bindBidirectional(viewModel.getSpecification());
controller.specificationLockField.selectedProperty().bindBidirectional(viewModel.getSpecificationLock());
EntityStringConverter<InventoryCatalog> catalogConverter = new EntityStringConverter<>();
catalogConverter.setInitialized(v -> getCatalogService().findById(v.getId()));
catalogConverter.setFormater(InventoryCatalog::getName);
catalogConverter.setSuggestion(getCatalogService()::search);
catalogConverter.setFromString(getCatalogService()::findByName);
UITools.autoCompletion(controller.catalogField, viewModel.getCatalog(), catalogConverter);
UITools.autoCompletion(controller.catalogField, viewModel.getCatalog(), getCatalogService());
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);
UITools.autoCompletion(controller.creatorField, viewModel.getCreator(), controller.getEmployeeService());
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern(MyDateTimeUtils.DEFAULT_DATE_FORMAT_PATTERN);
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));
controller.createTimeField.textProperty().bindBidirectional(viewModel.getCreateTime(),
new LocalDateStringConverter(dateFormatter, null));
UITools.autoCompletion(controller.updaterField, viewModel.getUpdater(), controller.getEmployeeService());
DateTimeFormatter dateTimeFormatter = DateTimeFormatter
.ofPattern(MyDateTimeUtils.DEFAULT_DATETIME_FORMAT_PATTERN);
controller.updateDateField.textProperty().bindBidirectional(viewModel.getUpdateDate(),
new LocalDateTimeStringConverter(dateTimeFormatter, null));
controller.weightUnitField.textProperty().bindBidirectional(viewModel.getWeightUnit());
controller.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));
@@ -154,7 +156,7 @@ public class InventoryTabSkinBase
}
private void onSyncAction(ActionEvent event) {
Inventory inventory = getEntity();
InventoryVo inventory = getEntity();
setStatus("开始同步数据...");
if (inventory == null) {
setStatus("请选择要同步的数据.");
@@ -165,30 +167,23 @@ 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);
}
@Override
public void deleteRowData(Inventory entity) {
public void deleteRowData(InventoryVo entity) {
getService().delete(entity);
}
@Override
public Inventory loadRowData(InventoryViewModel row) {
public InventoryVo loadRowData(InventoryViewModel row) {
return getService().findById(row.getId().get());
}
@Override
public Inventory saveRowData(Inventory entity) {
public InventoryVo saveRowData(InventoryVo entity) {
return getService().save(entity);
}
}

View File

@@ -1,34 +1,32 @@
package com.ecep.contract.manager.ds.other.controller.inventory;
package com.ecep.contract.controller.inventory;
import java.text.NumberFormat;
import java.time.LocalDate;
import com.ecep.contract.controller.contract.ContractWindowController;
import com.ecep.contract.controller.tab.TabSkin;
import com.ecep.contract.controller.table.AbstEntityTableTabSkin;
import com.ecep.contract.service.ContractItemService;
import com.ecep.contract.service.ContractService;
import com.ecep.contract.service.InventoryHistoryPriceService;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.util.ParamUtils;
import com.ecep.contract.vm.ContractViewModel;
import com.ecep.contract.vm.InventoryViewModel;
import com.ecep.contract.vo.ContractVo;
import com.ecep.contract.vo.InventoryVo;
import com.ecep.contract.manager.ds.contract.controller.ContractWindowController;
import com.ecep.contract.manager.ds.contract.model.Contract;
import com.ecep.contract.manager.ds.contract.model.ContractItem;
import com.ecep.contract.manager.ds.contract.service.ContractItemService;
import com.ecep.contract.manager.ds.contract.service.ContractService;
import com.ecep.contract.manager.ds.contract.vo.ContractViewModel;
import com.ecep.contract.manager.ds.other.model.Inventory;
import com.ecep.contract.manager.ds.other.service.InventoryHistoryPriceService;
import com.ecep.contract.manager.ds.other.vo.InventoryViewModel;
import com.ecep.contract.manager.ui.table.AbstEntityTableTabSkin;
import com.ecep.contract.manager.ui.FxmlPath;
import com.ecep.contract.manager.ui.tab.TabSkin;
import com.ecep.contract.manager.util.SpecificationUtils;
import jakarta.persistence.criteria.Root;
import jakarta.persistence.criteria.Subquery;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.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, InventoryVo, InventoryViewModel, ContractVo, 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,10 @@ 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));
// 主查询筛选ID在子查询结果中的合同
return builder.in(root.get("id")).value(subquery);
});
public ParamUtils.Builder getSpecification(InventoryVo parent) {
ParamUtils.Builder params = getSpecification();
params.equals("inventory", parent);
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;
@@ -32,9 +8,41 @@ import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;
import com.ecep.contract.ContractPayWay;
import com.ecep.contract.controller.tab.TabSkin;
import com.ecep.contract.controller.table.AbstEntityTableTabSkin;
import com.ecep.contract.model.Contract;
import com.ecep.contract.model.ContractItem;
import com.ecep.contract.model.HistoryPrice;
import com.ecep.contract.model.Inventory;
import com.ecep.contract.model.InventoryHistoryPrice;
import com.ecep.contract.service.ContractItemService;
import com.ecep.contract.service.ContractService;
import com.ecep.contract.service.InventoryHistoryPriceService;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.util.ParamUtils;
import com.ecep.contract.util.ProxyUtils;
import com.ecep.contract.vm.InventoryHistoryPriceViewModel;
import com.ecep.contract.vm.InventoryViewModel;
import com.ecep.contract.vo.ContractItemVo;
import com.ecep.contract.vo.ContractVo;
import com.ecep.contract.vo.InventoryHistoryPriceVo;
import com.ecep.contract.vo.InventoryVo;
import javafx.event.ActionEvent;
import javafx.scene.control.Button;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.Tab;
import javafx.scene.control.TableColumn;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.util.converter.CurrencyStringConverter;
import javafx.util.converter.NumberStringConverter;
@FxmlPath("/ui/inventory/inventory-history-price.fxml")
public class InventoryTabSkinHistoryPrice
extends AbstEntityTableTabSkin<InventoryWindowController, Inventory, InventoryViewModel, InventoryHistoryPrice, InventoryHistoryPriceViewModel>
extends
AbstEntityTableTabSkin<InventoryWindowController, InventoryVo, InventoryViewModel, InventoryHistoryPriceVo, InventoryHistoryPriceViewModel>
implements TabSkin {
public Button refreshBtn;
public TableColumn<InventoryHistoryPriceViewModel, Number> idColumn;
@@ -66,42 +74,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 +100,6 @@ public class InventoryTabSkinHistoryPrice
return controller.historyPriceTab;
}
@Override
public void initializeTable() {
super.initializeTable();
@@ -176,67 +166,70 @@ public class InventoryTabSkinHistoryPrice
private void onRefreshAction(ActionEvent event) {
runAsync(() -> {
HashMap<Integer, InventoryHistoryPrice> historyPriceMap = new HashMap<>();
HashMap<Integer, InventoryHistoryPriceVo> historyPriceMap = new HashMap<>();
for (InventoryHistoryPrice historyPrice : getService().findAllByInventory(getParent())) {
InventoryHistoryPrice oldValue = historyPriceMap.put(historyPrice.getYear().getValue(), historyPrice);
for (InventoryHistoryPriceVo historyPrice : getHistoryPriceService().findAllByInventory(getParent())) {
InventoryHistoryPriceVo oldValue = historyPriceMap.put(historyPrice.getYear().getValue(), historyPrice);
if (oldValue != null) {
getService().delete(oldValue);
getHistoryPriceService().delete(oldValue);
}
}
List<ContractItem> items = getContractItemService().findAllByInventory(getParent());
List<ContractItemVo> items = getContractItemService().findAllByInventory(getParent());
items.stream().collect(Collectors.groupingBy(v -> {
Contract contract = v.getContract();
if (!Hibernate.isInitialized(contract)) {
contract = getContractService().findById(contract.getId());
v.setContract(contract);
}
Integer contractId = v.getContractId();
ContractVo contract = getContractService().findById(contractId);
return contract.getSetupDate().getYear();
})).forEach((year, list) -> {
InventoryHistoryPrice historyPrice = historyPriceMap.computeIfAbsent(year, k -> {
InventoryHistoryPrice price = new InventoryHistoryPrice();
price.setInventory(getParent());
price.setYear(year);
InventoryHistoryPriceVo historyPrice = historyPriceMap.computeIfAbsent(year, k -> {
InventoryHistoryPriceVo price = new InventoryHistoryPriceVo();
price.setInventoryId(getParent().getId());
price.setYear(Year.of(year));
return price;
});
list.stream().collect(Collectors.groupingBy(v -> {
Contract contract = v.getContract();
Integer contractId = v.getContractId();
ContractVo contract = getContractService().findById(contractId);
return contract.getPayWay();
})).forEach((payWay, contractItems) -> {
if (ContractPayWay.RECEIVE.equals(payWay)) {
// 销售
list.stream().max(Comparator.comparing(v -> {
Contract contract = v.getContract();
Integer contractId = v.getContractId();
ContractVo contract = getContractService().findById(contractId);
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(ContractItemVo::getTaxPrice))
.ifPresent(v -> update(historyPrice.getMaxSalePrice(), v));
list.stream().min(Comparator.comparing(ContractItemVo::getTaxPrice))
.ifPresent(v -> update(historyPrice.getMiniSalePrice(), v));
} else if (ContractPayWay.PAY.equals(payWay)) {
// 采购
list.stream().max(Comparator.comparing(v -> {
Contract contract = v.getContract();
Integer contractId = v.getContractId();
ContractVo contract = getContractService().findById(contractId);
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(ContractItemVo::getTaxPrice))
.ifPresent(v -> update(historyPrice.getMaxPurchasePrice(), v));
list.stream().min(Comparator.comparing(ContractItemVo::getTaxPrice))
.ifPresent(v -> update(historyPrice.getMiniPurchasePrice(), v));
} else {
}
});
getService().save(historyPrice);
getHistoryPriceService().save(historyPrice);
});
loadTableDataSet();
});
}
void update(HistoryPrice historyPrice, ContractItem item) {
void update(HistoryPrice historyPrice, ContractItemVo item) {
if (item == null) {
historyPrice.setTaxRate(0);
historyPrice.setPreTaxPrice(0);
@@ -245,22 +238,19 @@ public class InventoryTabSkinHistoryPrice
return;
}
getContractService();
Contract contract = item.getContract();
if (!Hibernate.isInitialized(contract)) {
contract = getContractService().findById(contract.getId());
item.setContract(contract);
}
historyPrice.setTaxRate((float) item.getTaxRate());
Integer contractId = item.getContractId();
ContractVo contract = getContractService().findById(contractId);
historyPrice.setTaxRate(item.getTaxRate().floatValue());
historyPrice.setPreTaxPrice(item.getExclusiveTaxPrice());
historyPrice.setPostTaxPrice(item.getTaxPrice());
historyPrice.setMonthDay(MonthDay.from(contract.getSetupDate()));
}
@Override
public Specification<InventoryHistoryPrice> getSpecification(Inventory parent) {
return SpecificationUtils.and(getSpecification(), (root, query, builder) -> {
return builder.equal(root.get("inventory"), parent);
});
public ParamUtils.Builder getSpecification(InventoryVo parent) {
ParamUtils.Builder params = getSpecification();
params.equals("inventory", parent.getId());
return params;
}
@Override

View File

@@ -1,25 +1,31 @@
package com.ecep.contract.manager.ds.other.controller.inventory;
package com.ecep.contract.controller.inventory;
import com.ecep.contract.manager.ds.other.model.Inventory;
import com.ecep.contract.manager.ds.other.service.InventoryService;
import com.ecep.contract.manager.ds.other.vo.InventoryViewModel;
import com.ecep.contract.manager.ui.AbstEntityController;
import com.ecep.contract.manager.ui.FxmlPath;
import javafx.beans.binding.Bindings;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.scene.layout.BorderPane;
import javafx.stage.WindowEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import com.ecep.contract.controller.AbstEntityController;
import com.ecep.contract.service.InventoryService;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.vm.InventoryViewModel;
import com.ecep.contract.vo.InventoryVo;
import javafx.beans.binding.Bindings;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.stage.WindowEvent;
@Lazy
@Scope("prototype")
@Component
@FxmlPath("/ui/inventory/inventory.fxml")
public class InventoryWindowController extends AbstEntityController<Inventory, InventoryViewModel> {
public class InventoryWindowController extends AbstEntityController<InventoryVo, InventoryViewModel> {
@FXML
public BorderPane root;
@FXML
@@ -31,7 +37,6 @@ public class InventoryWindowController extends AbstEntityController<Inventory, I
@FXML
public Tab contractsTab;
@FXML
public TextField nameField;
@FXML
@@ -97,27 +102,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 +121,6 @@ public class InventoryWindowController extends AbstEntityController<Inventory, I
@Override
public InventoryService getViewModelService() {
return service;
return getCachedBean(InventoryService.class);
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,7 +1,8 @@
package com.ecep.contract.manager.ds.other.controller.permission;
package com.ecep.contract.controller.permission;
import com.ecep.contract.Desktop;
import com.ecep.contract.controller.tab.TabSkin;
import com.ecep.contract.manager.Desktop;
import com.ecep.contract.manager.ui.tab.TabSkin;
import javafx.scene.control.Tab;
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.util.ParamUtils;
import com.ecep.contract.vo.EmployeeRoleVo;
import com.ecep.contract.vo.FunctionVo;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.collections.ListChangeListener;
@@ -20,7 +20,7 @@ import javafx.scene.control.Tab;
public class EmployeeRoleTabSkinFunctions extends AbstEmployeeRoleBasedTabSkin {
private final SimpleBooleanProperty changed = new SimpleBooleanProperty(false);
private ListSelectionView<Function> functionsField;
private ListSelectionView<FunctionVo> functionsField;
public EmployeeRoleTabSkinFunctions(EmployeeRoleWindowController controller) {
super(controller);
@@ -50,7 +50,7 @@ public class EmployeeRoleTabSkinFunctions extends AbstEmployeeRoleBasedTabSkin {
}
private void loadSelectedRoles() {
List<Function> selectedRoles = getRoleService().getFunctionsByRoleId(viewModel.getId().get());
List<FunctionVo> selectedRoles = getRoleService().getFunctionsByRoleId(viewModel.getId().get());
if (selectedRoles != null) {
functionsField.getTargetItems().setAll(selectedRoles);
}
@@ -59,14 +59,14 @@ 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<FunctionVo> roles = getFunctionService()
.findAll(ParamUtils.builder().equals("active", true).build(), Pageable.ofSize(500)).getContent();
functionsField.getSourceItems().setAll(roles);
functionsField.setCellFactory(param -> {
return new ListCell<>() {
return new ListCell<FunctionVo>() {
@Override
protected void updateItem(Function item, boolean empty) {
protected void updateItem(FunctionVo item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setText(null);
@@ -77,10 +77,10 @@ public class EmployeeRoleTabSkinFunctions extends AbstEmployeeRoleBasedTabSkin {
};
});
functionsField.getTargetItems().addListener((ListChangeListener<Function>) change -> {
functionsField.getTargetItems().addListener((ListChangeListener<FunctionVo>) change -> {
while (change.next()) {
List<? extends Function> added = change.getAddedSubList();
List<? extends Function> removed = change.getRemoved();
List<? extends FunctionVo> added = change.getAddedSubList();
List<? extends FunctionVo> removed = change.getRemoved();
if (!added.isEmpty() || !removed.isEmpty()) {
changed.set(true);
}
@@ -99,7 +99,7 @@ public class EmployeeRoleTabSkinFunctions extends AbstEmployeeRoleBasedTabSkin {
}
private void saveRoles(ActionEvent event) {
EmployeeRole entity = getEntity();
EmployeeRoleVo entity = getEntity();
entity.setFunctions(functionsField.getTargetItems());
save(entity);
loadSelectedRoles();

View File

@@ -1,18 +1,5 @@
package com.ecep.contract.manager.ds.other.controller.permission;
package com.ecep.contract.controller.permission;
import com.ecep.contract.manager.ds.other.model.EmployeeRole;
import com.ecep.contract.manager.ds.other.service.EmployeeRoleService;
import com.ecep.contract.manager.ds.other.service.PermissionService;
import com.ecep.contract.manager.ds.other.vo.EmployeeRoleViewModel;
import com.ecep.contract.manager.ui.AbstEntityController;
import com.ecep.contract.manager.ui.FxmlPath;
import com.ecep.contract.manager.ui.ViewModelService;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.scene.layout.BorderPane;
import javafx.stage.Window;
import javafx.stage.WindowEvent;
import org.controlsfx.control.ListSelectionView;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -21,12 +8,30 @@ 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.service.EmployeeRoleService;
import com.ecep.contract.service.PermissionService;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.vm.EmployeeRoleViewModel;
import com.ecep.contract.vo.EmployeeRoleVo;
import javafx.fxml.FXML;
import javafx.scene.control.CheckBox;
import javafx.scene.control.DatePicker;
import javafx.scene.control.Label;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.stage.Window;
import javafx.stage.WindowEvent;
@Lazy
@Scope("prototype")
@Component
@FxmlPath("/ui/employee/role.fxml")
public class EmployeeRoleWindowController extends AbstEntityController<EmployeeRole, EmployeeRoleViewModel> {
public class EmployeeRoleWindowController extends AbstEntityController<EmployeeRoleVo, EmployeeRoleViewModel> {
private static final Logger logger = LoggerFactory.getLogger(EmployeeRoleWindowController.class);
@@ -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.vo.FunctionVo> 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.service.FunctionService;
import com.ecep.contract.service.PermissionService;
import com.ecep.contract.vm.FunctionViewModel;
import com.ecep.contract.vo.FunctionVo;
import javafx.scene.control.TableColumn;
import javafx.scene.control.cell.CheckBoxTableCell;
@@ -12,7 +12,7 @@ import javafx.scene.control.cell.TextFieldTableCell;
public class FunctionManagerSkin
extends
AbstEntityManagerSkin<Function, FunctionViewModel, FunctionManagerSkin, EmployeeFunctionsManagerWindowController> {
AbstEntityManagerSkin<FunctionVo, FunctionViewModel, FunctionManagerSkin, EmployeeFunctionsManagerWindowController> {
public FunctionManagerSkin(EmployeeFunctionsManagerWindowController controller) {
super(controller);

View File

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

View File

@@ -1,16 +1,17 @@
package com.ecep.contract.manager.ds.other.controller.permission;
package com.ecep.contract.controller.permission;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.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.util.ParamUtils;
import com.ecep.contract.vm.FunctionViewModel;
import com.ecep.contract.vm.PermissionViewModel;
import com.ecep.contract.vo.FunctionVo;
import com.ecep.contract.vo.PermissionVo;
import javafx.fxml.FXML;
import javafx.scene.control.Tab;
@@ -19,7 +20,7 @@ import javafx.scene.control.TableColumn;
@FxmlPath("/ui/employee/function-tab-permission.fxml")
public class FunctionTabSkinPermission
extends
AbstEntityTableTabSkin<FunctionWindowController, Function, FunctionViewModel, Permission, PermissionViewModel> {
AbstEntityTableTabSkin<FunctionWindowController, FunctionVo, FunctionViewModel, PermissionVo, PermissionViewModel> {
@FXML
public TableColumn<PermissionViewModel, Number> idColumn;
@@ -61,10 +62,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 ParamUtils.Builder getSpecification(FunctionVo parent) {
ParamUtils.Builder params = getSpecification();
params.equals("function", parent.getId());
return params;
}
}

View File

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

View File

@@ -1,11 +1,21 @@
package com.ecep.contract.manager.ds.other.controller.permission;
package com.ecep.contract.controller.permission;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.ecep.contract.controller.ManagerSkin;
import com.ecep.contract.controller.table.TableTabSkin;
import com.ecep.contract.util.ParamUtils;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vm.FunctionViewModel;
import com.ecep.contract.vm.PermissionViewModel;
import com.ecep.contract.vo.PermissionVo;
import com.ecep.contract.manager.ds.other.model.Permission;
import com.ecep.contract.manager.ds.other.vo.FunctionViewModel;
import com.ecep.contract.manager.ds.other.vo.PermissionViewModel;
import com.ecep.contract.manager.ui.ManagerSkin;
import com.ecep.contract.manager.ui.table.TableTabSkin;
import com.ecep.contract.manager.util.UITools;
import javafx.application.Platform;
import javafx.beans.property.Property;
import javafx.collections.FXCollections;
@@ -16,16 +26,8 @@ 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> {
public class PermissionManagerSkin implements ManagerSkin, TableTabSkin<PermissionVo, PermissionViewModel> {
private static final Logger logger = LoggerFactory.getLogger(PermissionManagerSkin.class);
EmployeeFunctionsManagerWindowController controller;
@@ -56,7 +58,6 @@ public class PermissionManagerSkin implements ManagerSkin, TableTabSkin<Permissi
return table;
}
@Override
public void install() {
initializeTable();
@@ -64,14 +65,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);
@@ -97,11 +98,9 @@ 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());
newRow.setFunction(function);
Permission saved = controller.permissionService.save(newRow);
PermissionVo newRow = new PermissionVo();
newRow.setFunctionId(viewModel.getId().get());
PermissionVo saved = controller.getPermissionService().save(newRow);
PermissionViewModel row = PermissionViewModel.from(saved);
dataSet.add(row);
}
@@ -126,7 +125,17 @@ public class PermissionManagerSkin implements ManagerSkin, TableTabSkin<Permissi
}
protected boolean deleteRow(PermissionViewModel row) {
throw new UnsupportedOperationException("未实现");
try {
int id = row.getId().get();
PermissionVo permissionVo = controller.permissionService.findById(id);
if (permissionVo != null) {
controller.permissionService.delete(permissionVo);
return true;
}
} catch (Exception e) {
handleException("删除权限失败", e);
}
return false;
}
private void onNameColumnEditCommitAction(TableColumn.CellEditEvent<PermissionViewModel, String> event) {
@@ -141,7 +150,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 +171,14 @@ public class PermissionManagerSkin implements ManagerSkin, TableTabSkin<Permissi
}
@Override
public Specification<Permission> getSpecification() {
return controller.permissionService.getSpecification(null);
public ParamUtils.Builder getSpecification() {
ParamUtils.Builder params = ParamUtils.builder();
// 使用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());
@@ -179,12 +191,11 @@ public class PermissionManagerSkin implements ManagerSkin, TableTabSkin<Permissi
protected void save(PermissionViewModel row) {
int id = row.getId().get();
Permission type = controller.permissionService.findById(id);
if (row.copyTo(type)) {
Permission saved = controller.permissionService.save(type);
PermissionVo permissionVo = controller.permissionService.findById(id);
if (permissionVo != null && row.copyTo(permissionVo)) {
PermissionVo saved = controller.permissionService.save(permissionVo);
row.update(saved);
}
}
}

View File

@@ -1,13 +1,14 @@
package com.ecep.contract.manager.ds.project.controller;
package com.ecep.contract.controller.project;
import com.ecep.contract.manager.ds.project.model.Project;
import com.ecep.contract.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;
import com.ecep.contract.vo.ProjectVo;
public abstract class AbstProjectBasedTabSkin
extends AbstEntityBasedTabSkin<ProjectWindowController, Project, ProjectViewModel>
extends AbstEntityBasedTabSkin<ProjectWindowController, ProjectVo, ProjectViewModel>
implements TabSkin {
public AbstProjectBasedTabSkin(ProjectWindowController controller) {

View File

@@ -0,0 +1,42 @@
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.service.ProjectService;
import com.ecep.contract.util.ParamUtils;
import com.ecep.contract.vm.IdentityViewModel;
import com.ecep.contract.vm.ProjectBasedViewModel;
import com.ecep.contract.vm.ProjectViewModel;
import com.ecep.contract.vo.ProjectVo;
public abstract class AbstProjectTableTabSkin<T extends IdentityEntity, TV extends IdentityViewModel<T>>
extends AbstEntityTableTabSkin<ProjectWindowController, ProjectVo, 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().getId());
}
return model;
}
@Override
public ParamUtils.Builder getSpecification(ProjectVo parent) {
ParamUtils.Builder params = getSpecification();
params.equals("project", parent.getId());
return params;
}
}

View File

@@ -1,16 +1,27 @@
package com.ecep.contract.manager.ds.project.controller;
package com.ecep.contract.controller.project;
import java.time.LocalDate;
import java.util.Objects;
import java.util.function.Consumer;
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.Desktop;
import com.ecep.contract.controller.BaseController;
import com.ecep.contract.converter.EntityStringConverter;
import com.ecep.contract.model.ProjectSaleType;
import com.ecep.contract.service.EmployeeService;
import com.ecep.contract.service.ProjectSaleTypeService;
import com.ecep.contract.service.ProjectService;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.vm.ProjectViewModel;
import com.ecep.contract.vo.EmployeeVo;
import com.ecep.contract.vo.ProjectSaleTypeVo;
import com.ecep.contract.vo.ProjectVo;
import com.ecep.contract.manager.Desktop;
import com.ecep.contract.manager.ds.other.EntityStringConverter;
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.model.Project;
import com.ecep.contract.manager.ds.project.model.ProjectSaleType;
import com.ecep.contract.manager.ds.project.service.ProjectService;
import com.ecep.contract.manager.ds.project.service.SaleTypeService;
import com.ecep.contract.manager.ds.project.vo.ProjectViewModel;
import com.ecep.contract.manager.ui.FxmlPath;
import javafx.beans.binding.Bindings;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
@@ -26,14 +37,6 @@ import javafx.stage.Stage;
import javafx.stage.Window;
import javafx.stage.WindowEvent;
import javafx.util.converter.NumberStringConverter;
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.time.LocalDate;
import java.util.Objects;
import java.util.function.Consumer;
@Lazy
@Scope("prototype")
@@ -43,12 +46,11 @@ public class ApplyNewProjectWindowController extends BaseController {
@Autowired
private ProjectService projectService;
@Autowired
private SaleTypeService saleTypeService;
private ProjectSaleTypeService saleTypeService;
@Autowired
private EmployeeService employeeService;
public ComboBox<ProjectSaleType> saleTypeComboBox;
public ComboBox<ProjectSaleTypeVo> saleTypeComboBox;
public TextField codeYearField;
public Label codeYearLabel;
@@ -63,11 +65,10 @@ public class ApplyNewProjectWindowController extends BaseController {
public Button cancelBtn;
public Button applyBtn;
private ProjectViewModel viewModel = new ProjectViewModel();
private ObjectProperty<Consumer<Project>> onApplied = new SimpleObjectProperty<>();
private ObjectProperty<Consumer<ProjectVo>> onApplied = new SimpleObjectProperty<>();
public void setOnApplied(Consumer<Project> onApplied) {
public void setOnApplied(Consumer<ProjectVo> onApplied) {
this.onApplied.set(onApplied);
}
@@ -85,11 +86,11 @@ public class ApplyNewProjectWindowController extends BaseController {
initializeSaleTypeField(saleTypeComboBox);
NumberStringConverter stringConverter = new NumberStringConverter();
Bindings.bindBidirectional(codeYearField.textProperty(), viewModel.getCodeYear(), stringConverter);
Bindings.bindBidirectional(codeSequenceNumberField.textProperty(), viewModel.getCodeSequenceNumber(), stringConverter);
Bindings.bindBidirectional(codeSequenceNumberField.textProperty(), viewModel.getCodeSequenceNumber(),
stringConverter);
initializeApplicantLabel(applicantLabel);
initializeCodePreviewLabel(codePreviewLabel);
@@ -97,10 +98,9 @@ public class ApplyNewProjectWindowController extends BaseController {
cancelBtn.getScene().getWindow().hide();
});
applyBtn.disableProperty().bind(viewModel.getSaleType().isNull());
applyBtn.setOnAction(event -> {
Project newProject = new Project();
ProjectVo newProject = new ProjectVo();
newProject.setCodeYear(viewModel.getCodeYear().get());
int codeSequenceNumber = viewModel.getCodeSequenceNumber().get();
if (codeSequenceNumber == 0) {
@@ -112,11 +112,11 @@ public class ApplyNewProjectWindowController extends BaseController {
codeSequenceNumberLabel.setStyle("");
}
newProject.setCodeSequenceNumber(codeSequenceNumber);
newProject.setSaleType(viewModel.getSaleType().get());
newProject.setSaleTypeId(viewModel.getSaleType().get());
Project exist = projectService.findBySaleTypeAndCodeYearAndCodeSequenceNumber(newProject.getSaleType(), newProject.getCodeYear(), newProject.getCodeSequenceNumber());
ProjectVo exist = projectService.findBySaleTypeAndCodeYearAndCodeSequenceNumber(newProject.getSaleTypeId(),
newProject.getCodeYear(), newProject.getCodeSequenceNumber());
if (exist != null) {
codeLabel.setText("项目编号已存在");
codeLabel.setStyle("-fx-text-fill: #ffa2a2");
@@ -129,10 +129,10 @@ public class ApplyNewProjectWindowController extends BaseController {
// 暂时的项目编号
newProject.setCode(codePreviewLabel.getText());
newProject.setApplicant(viewModel.getApplicant().get());
newProject.setApplicantId(viewModel.getApplicant().get());
newProject.setCreated(LocalDate.now());
Project saved = projectService.save(newProject);
Consumer<Project> consumer = onApplied.get();
ProjectVo saved = projectService.save(newProject);
Consumer<ProjectVo> consumer = onApplied.get();
if (consumer != null) {
consumer.accept(saved);
}
@@ -142,11 +142,9 @@ public class ApplyNewProjectWindowController extends BaseController {
}
private void initializeApplicantLabel(Label applicantLabel) {
Employee operator = employeeService.findById(Desktop.instance.getActiveEmployeeId());
viewModel.getApplicant().set(operator);
viewModel.getApplicant().set(Desktop.instance.getActiveEmployeeId());
applicantLabel.textProperty().bind(Bindings.createObjectBinding(() -> {
Employee employee = viewModel.getApplicant().get();
EmployeeVo employee = employeeService.findById(viewModel.getApplicant().get());
if (employee == null) {
return "- 异常,未取得当前操作员信息 -";
}
@@ -158,13 +156,13 @@ public class ApplyNewProjectWindowController extends BaseController {
private void initializeCodePreviewLabel(Label codePreviewLabel) {
codePreviewLabel.textProperty().bind(Bindings.createObjectBinding(() -> {
StringBuilder sb = new StringBuilder();
ProjectSaleType saleType = viewModel.getSaleType().get();
ProjectSaleTypeVo saleType = getCachedBean(ProjectSaleTypeService.class)
.findById(viewModel.getSaleType().get());
if (saleType == null) {
return "";
}
sb.append(saleType.getCode());
int year = viewModel.getCodeYear().get();
if (year < 10) {
sb.append("0");
@@ -182,27 +180,33 @@ public class ApplyNewProjectWindowController extends BaseController {
}, viewModel.getSaleType(), viewModel.getCodeYear(), viewModel.getCodeSequenceNumber()));
}
private void initializeSaleTypeField(ComboBox<ProjectSaleType> field) {
ObservableList<ProjectSaleType> list = FXCollections.observableArrayList();
saleTypeService.findAll().stream().filter(ProjectSaleType::isActive).forEach(list::add);
private void initializeSaleTypeField(ComboBox<ProjectSaleTypeVo> field) {
ObservableList<ProjectSaleTypeVo> list = FXCollections.observableArrayList();
saleTypeService.findAll().stream().filter(ProjectSaleTypeVo::isActive).forEach(list::add);
field.setItems(list);
field.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
viewModel.getSaleType().set(newValue);
viewModel.getSaleType().set(newValue.getId());
// SequenceNumber 0 自动检索最新的 SequenceNumber
if (viewModel.getCodeYear().get() != 0) {
int nextCodeSequenceNumber = projectService.getNextCodeSequenceNumber(newValue, viewModel.getCodeYear().get());
int nextCodeSequenceNumber = projectService.getNextCodeSequenceNumber(newValue,
viewModel.getCodeYear().get());
viewModel.getCodeSequenceNumber().set(nextCodeSequenceNumber);
}
});
EntityStringConverter<ProjectSaleType> converter = new EntityStringConverter<>();
EntityStringConverter<ProjectSaleTypeVo> converter = new EntityStringConverter<>();
converter.setInitialized(saleType -> {
return list.stream().filter(v -> v != null && Objects.equals(v.getId(), saleType.getId())).findFirst().orElse(null);
return list.stream().filter(v -> v != null && Objects.equals(v.getId(), saleType.getId())).findFirst()
.orElse(null);
});
converter.setFromString(name -> {
return list.stream().filter(v -> v != null && Objects.equals(v.getName(), name)).findFirst().orElse(null);
});
field.setConverter(converter);
field.valueProperty().bindBidirectional(viewModel.getSaleType());
viewModel.getSaleType().addListener((observable, oldValue, newValue) -> {
if (newValue != null) {
field.getSelectionModel().select(newValue);
}
});
}
}

View File

@@ -1,25 +1,21 @@
package com.ecep.contract.manager.ds.project.controller;
package com.ecep.contract.controller.project;
import org.springframework.data.jpa.domain.Specification;
import com.ecep.contract.manager.ui.table.cell.CompanyTableCell;
import com.ecep.contract.manager.ds.company.model.Company;
import com.ecep.contract.manager.ds.company.service.CompanyService;
import com.ecep.contract.manager.ds.other.EntityStringConverter;
import com.ecep.contract.manager.ds.project.model.ProductType;
import com.ecep.contract.manager.ds.project.model.Project;
import com.ecep.contract.manager.ds.project.model.ProjectSaleType;
import com.ecep.contract.manager.ds.project.model.ProjectType;
import com.ecep.contract.manager.ds.project.service.ProductTypeService;
import com.ecep.contract.manager.ds.project.service.ProjectService;
import com.ecep.contract.manager.ds.project.service.ProjectTypeService;
import com.ecep.contract.manager.ds.project.service.SaleTypeService;
import com.ecep.contract.manager.ds.project.vo.ProjectViewModel;
import com.ecep.contract.manager.ui.AbstEntityManagerSkin;
import com.ecep.contract.manager.ui.BaseController;
import com.ecep.contract.manager.ui.ComboBoxUtils;
import com.ecep.contract.manager.ui.ManagerSkin;
import com.ecep.contract.manager.util.SpecificationUtils;
import com.ecep.contract.controller.AbstEntityManagerSkin;
import com.ecep.contract.controller.BaseController;
import com.ecep.contract.util.ComboBoxUtils;
import com.ecep.contract.controller.ManagerSkin;
import com.ecep.contract.controller.table.cell.CompanyTableCell;
import com.ecep.contract.controller.table.cell.ProductTypeTableCell;
import com.ecep.contract.controller.table.cell.ProjectSaleTypeTableCell;
import com.ecep.contract.controller.table.cell.ProjectTypeTableCell;
import com.ecep.contract.service.CompanyService;
import com.ecep.contract.service.ProductTypeService;
import com.ecep.contract.service.ProjectSaleTypeService;
import com.ecep.contract.service.ProjectService;
import com.ecep.contract.service.ProjectTypeService;
import com.ecep.contract.util.ParamUtils;
import com.ecep.contract.vm.ProjectViewModel;
import com.ecep.contract.vo.ProjectVo;
import javafx.application.Platform;
import javafx.event.ActionEvent;
@@ -30,18 +26,17 @@ import javafx.util.converter.CurrencyStringConverter;
import lombok.Setter;
public class ProjectManagerSkin
extends AbstEntityManagerSkin<Project, ProjectViewModel, ProjectManagerSkin, ProjectManagerWindowController>
extends AbstEntityManagerSkin<ProjectVo, ProjectViewModel, ProjectManagerSkin, ProjectManagerWindowController>
implements ManagerSkin {
@Setter
private CompanyService companyService;
@Setter
private ProjectTypeService projectTypeService;
@Setter
private SaleTypeService saleTypeService;
private ProjectSaleTypeService saleTypeService;
@Setter
private ProductTypeService productTypeService;
public ProjectManagerSkin(ProjectManagerWindowController controller) {
super(controller);
}
@@ -50,16 +45,16 @@ public class ProjectManagerSkin
return controller.getViewModelService();
}
public CompanyService getCompanyService(){
public CompanyService getCompanyService() {
if (companyService == null) {
companyService = getBean(CompanyService.class);
}
return companyService;
}
public SaleTypeService getSaleTypeService() {
public ProjectSaleTypeService getSaleTypeService() {
if (saleTypeService == null) {
saleTypeService = getBean(SaleTypeService.class);
saleTypeService = getBean(ProjectSaleTypeService.class);
}
return saleTypeService;
}
@@ -78,16 +73,13 @@ public class ProjectManagerSkin
return productTypeService;
}
@Override
public Specification<Project> getSpecification() {
Specification<Project> spec = super.getSpecification();
public ParamUtils.Builder getSpecification() {
ParamUtils.Builder params = super.getSpecification();
if (controller.saleTypeSelector.getValue() != null) {
spec = SpecificationUtils.and(spec, (root, query, builder) -> {
return builder.equal(root.get("saleType"), controller.saleTypeSelector.getValue());
});
params.equals("saleType", controller.saleTypeSelector.getValue());
}
return spec;
return params;
}
@Override
@@ -102,7 +94,9 @@ public class ProjectManagerSkin
controller.nameColumn.setCellValueFactory(param -> param.getValue().getName());
controller.amountColumn.setCellValueFactory(param -> param.getValue().getAmount());
controller.amountColumn.setCellFactory(TextFieldTableCell.forTableColumn(new CurrencyStringConverter(getLocale())));//, "#,##0"
controller.amountColumn
.setCellFactory(TextFieldTableCell.forTableColumn(new CurrencyStringConverter(getLocale())));// ,
// "#,##0"
initializeSaleTypeColumn(controller.saleTypeColumn);
initializeCustomerColumn(controller.customerColumn);
@@ -114,7 +108,6 @@ public class ProjectManagerSkin
controller.useOfferColumn.setCellValueFactory(param -> param.getValue().getUseOffer());
controller.useOfferColumn.setCellFactory(CheckBoxTableCell.forTableColumn(controller.useOfferColumn));
controller.createdColumn.setCellValueFactory(param -> param.getValue().getCreated());
Platform.runLater(() -> {
@@ -122,31 +115,24 @@ public class ProjectManagerSkin
});
}
private void initializeCustomerColumn(TableColumn<ProjectViewModel, Company> column) {
private void initializeCustomerColumn(TableColumn<ProjectViewModel, Integer> column) {
column.setCellValueFactory(param -> param.getValue().getCustomer());
column.setCellFactory(param-> new CompanyTableCell<>(getCompanyService()));
column.setCellFactory(param -> new CompanyTableCell<>(getCompanyService()));
}
private void initializeProductTypeColumn(TableColumn<ProjectViewModel, String> column) {
EntityStringConverter<ProductType> converter = new EntityStringConverter<>();
converter.setInitialized(productType -> getProductTypeService().findById(productType.getId()));
converter.setFromString(name -> getProductTypeService().findByName(name));
column.setCellValueFactory(param -> param.getValue().getProductType().map(converter::toString));
private void initializeProductTypeColumn(TableColumn<ProjectViewModel, Integer> column) {
column.setCellValueFactory(param -> param.getValue().getProductType());
column.setCellFactory(param -> new ProductTypeTableCell<>(getProductTypeService()));
}
private void initializeProjectTypeColumn(TableColumn<ProjectViewModel, String> column) {
EntityStringConverter<ProjectType> converter = new EntityStringConverter<>();
converter.setInitialized(projectType -> getProjectTypeService().findById(projectType.getId()));
converter.setFromString(name -> getProjectTypeService().findByName(name));
column.setCellValueFactory(param -> param.getValue().getProjectType().map(converter::toString));
private void initializeProjectTypeColumn(TableColumn<ProjectViewModel, Integer> column) {
column.setCellValueFactory(param -> param.getValue().getProjectType());
column.setCellFactory(param -> new ProjectTypeTableCell<>(getProjectTypeService()));
}
private void initializeSaleTypeColumn(TableColumn<ProjectViewModel, String> column) {
EntityStringConverter<ProjectSaleType> converter = new EntityStringConverter<>();
converter.setInitialized(saleType -> getSaleTypeService().findById(saleType.getId()));
converter.setFromString(name -> getSaleTypeService().findByName(name));
column.setCellValueFactory(param -> param.getValue().getSaleType().map(converter::toString));
private void initializeSaleTypeColumn(TableColumn<ProjectViewModel, Integer> column) {
column.setCellValueFactory(param -> param.getValue().getSaleType());
column.setCellFactory(param -> new ProjectSaleTypeTableCell<>(getSaleTypeService()));
}
@Override
@@ -156,13 +142,14 @@ public class ProjectManagerSkin
@Override
protected void onTableCreateNewAction(ActionEvent event) {
BaseController.show(ApplyNewProjectWindowController.class, getTableView().getScene().getWindow(), controller -> {
controller.setOnApplied(project -> {
ProjectViewModel viewModel = ProjectViewModel.from(project);
dataSet.addFirst(viewModel);
showInOwner(viewModel);
});
});
BaseController.show(ApplyNewProjectWindowController.class, getTableView().getScene().getWindow(),
controller -> {
controller.setOnApplied(project -> {
ProjectViewModel viewModel = ProjectViewModel.from(project);
dataSet.addFirst(viewModel);
showInOwner(viewModel);
});
});
}
private void showInOwner(ProjectViewModel model) {

View File

@@ -1,4 +1,4 @@
package com.ecep.contract.manager.ds.project.controller;
package com.ecep.contract.controller.project;
import java.time.LocalDate;
@@ -9,19 +9,18 @@ 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.project.controller.industry.ProjectIndustryManagerWindowController;
import com.ecep.contract.manager.ds.project.controller.product_type.ProductTypeManagerWindowController;
import com.ecep.contract.manager.ds.project.controller.project_type.ProjectTypeManagerWindowController;
import com.ecep.contract.manager.ds.project.controller.sale_type.ProjectSaleTypeManagerWindowController;
import com.ecep.contract.manager.ds.project.controller.usage.ProductUsageManagerWindowController;
import com.ecep.contract.manager.ds.project.model.Project;
import com.ecep.contract.manager.ds.project.model.ProjectSaleType;
import com.ecep.contract.manager.ds.project.service.ProjectService;
import com.ecep.contract.manager.ds.project.vo.ProjectViewModel;
import com.ecep.contract.manager.ui.AbstManagerWindowController;
import com.ecep.contract.manager.ui.BaseController;
import com.ecep.contract.manager.ui.FxmlPath;
import com.ecep.contract.controller.AbstManagerWindowController;
import com.ecep.contract.controller.BaseController;
import com.ecep.contract.controller.project.industry.ProjectIndustryManagerWindowController;
import com.ecep.contract.controller.project.product_type.ProductTypeManagerWindowController;
import com.ecep.contract.controller.project.project_type.ProjectTypeManagerWindowController;
import com.ecep.contract.controller.project.sale_type.ProjectSaleTypeManagerWindowController;
import com.ecep.contract.controller.project.usage.ProductUsageManagerWindowController;
import com.ecep.contract.service.ProjectService;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.vm.ProjectViewModel;
import com.ecep.contract.vo.ProjectSaleTypeVo;
import com.ecep.contract.vo.ProjectVo;
import javafx.event.ActionEvent;
import javafx.scene.control.ComboBox;
@@ -33,19 +32,19 @@ import javafx.stage.WindowEvent;
@Component
@FxmlPath("/ui/project/project-manager.fxml")
public class ProjectManagerWindowController
extends AbstManagerWindowController<Project, ProjectViewModel, ProjectManagerSkin> {
extends AbstManagerWindowController<ProjectVo, ProjectViewModel, ProjectManagerSkin> {
private static final Logger logger = LoggerFactory.getLogger(ProjectManagerWindowController.class);
public ComboBox<ProjectSaleType> saleTypeSelector;
public ComboBox<ProjectSaleTypeVo> saleTypeSelector;
public TableColumn<ProjectViewModel, Number> idColumn;
public TableColumn<ProjectViewModel, String> codeColumn;
public TableColumn<ProjectViewModel, String> nameColumn;
public TableColumn<ProjectViewModel, String> saleTypeColumn;
public TableColumn<ProjectViewModel, String> projectTypeColumn;
public TableColumn<ProjectViewModel, String> productTypeColumn;
public TableColumn<ProjectViewModel, Integer> saleTypeColumn;
public TableColumn<ProjectViewModel, Integer> projectTypeColumn;
public TableColumn<ProjectViewModel, Integer> productTypeColumn;
public TableColumn<ProjectViewModel, LocalDate> createdColumn;
public TableColumn<ProjectViewModel, Company> customerColumn;
public TableColumn<ProjectViewModel, Integer> customerColumn;
public TableColumn<ProjectViewModel, Boolean> useBidColumn;
public TableColumn<ProjectViewModel, Boolean> useOfferColumn;
public TableColumn<ProjectViewModel, Number> amountColumn;

View File

@@ -0,0 +1,265 @@
package com.ecep.contract.controller.project;
import java.util.Objects;
import java.util.function.Predicate;
import java.util.stream.Stream;
import org.springframework.util.StringUtils;
import com.ecep.contract.util.ComboBoxUtils;
import com.ecep.contract.controller.tab.TabSkin;
import com.ecep.contract.converter.EmployeeStringConverter;
import com.ecep.contract.service.DeliverySignMethodService;
import com.ecep.contract.service.EmployeeService;
import com.ecep.contract.service.ProductTypeService;
import com.ecep.contract.service.ProductUsageService;
import com.ecep.contract.service.ProjectCostService;
import com.ecep.contract.service.ProjectIndustryService;
import com.ecep.contract.service.ProjectSaleTypeService;
import com.ecep.contract.service.ProjectTypeService;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vo.DeliverySignMethodVo;
import com.ecep.contract.vo.ProductTypeVo;
import com.ecep.contract.vo.ProductUsageVo;
import com.ecep.contract.vo.ProjectCostVo;
import com.ecep.contract.vo.ProjectIndustryVo;
import com.ecep.contract.vo.ProjectSaleTypeVo;
import com.ecep.contract.vo.ProjectTypeVo;
import com.ecep.contract.vo.ProjectVo;
import javafx.beans.binding.Bindings;
import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList;
import javafx.event.ActionEvent;
import javafx.scene.control.Tab;
import javafx.util.converter.LocalDateStringConverter;
import javafx.util.converter.NumberStringConverter;
import lombok.Setter;
/**
* 基础信息
*/
public class ProjectTabSkinBase extends AbstProjectBasedTabSkin implements TabSkin {
@Setter
EmployeeStringConverter employeeStringConverter;
@Setter
LocalDateStringConverter localDateStringConverter;
@Setter
EmployeeService employeeService;
@Setter
private DeliverySignMethodService deliverySignMethodService;
public ProjectTabSkinBase(ProjectWindowController controller) {
super(controller);
}
@Override
public Tab getTab() {
return controller.baseInfoTab;
}
private EmployeeService getEmployeeService() {
return getBean(EmployeeService.class);
}
private ProjectTypeService getProjectTypeService() {
return getBean(ProjectTypeService.class);
}
private ProductTypeService getProductTypeService() {
return getBean(ProductTypeService.class);
}
private ProjectSaleTypeService getSaleTypeService() {
return getBean(ProjectSaleTypeService.class);
}
private ProductUsageService getProductUsageService() {
return getBean(ProductUsageService.class);
}
private ProjectIndustryService getProjectIndustryService() {
return getBean(ProjectIndustryService.class);
}
private DeliverySignMethodService getDeliverySignMethodService() {
return getBean(DeliverySignMethodService.class);
}
@Override
public void initializeTab() {
controller.deleteBtn.setOnAction(this::onDeleteAction);
controller.nameField.textProperty().bindBidirectional(viewModel.getName());
controller.codeField.textProperty().bind(viewModel.getCode());
NumberStringConverter stringConverter = new NumberStringConverter();
Bindings.bindBidirectional(controller.codeYearField.textProperty(), viewModel.getCodeYear(), stringConverter);
Bindings.bindBidirectional(controller.codeSequenceNumberField.textProperty(), viewModel.getCodeSequenceNumber(),
stringConverter);
controller.addressField.textProperty().bindBidirectional(viewModel.getAddress());
controller.useBidField.selectedProperty().bindBidirectional(viewModel.getUseBid());
controller.useOfferField.selectedProperty().bindBidirectional(viewModel.getUseOffer());
controller.standardPayWayField.selectedProperty().bindBidirectional(viewModel.getStandardPayWay());
Bindings.bindBidirectional(controller.amountField.textProperty(), viewModel.getAmount(),
new NumberStringConverter());
ComboBoxUtils.initialComboBox(controller.saleTypeField, viewModel.getSaleType(), getSaleTypeService(), true);
ComboBoxUtils.initialComboBox(controller.projectTypeField, viewModel.getProjectType(), getProjectTypeService(),
true);
ComboBoxUtils.initialComboBox(controller.saleTypeField, viewModel.getSaleType(), getSaleTypeService(), true);
ComboBoxUtils.initialComboBox(controller.industryField, viewModel.getIndustry(), getProjectIndustryService(),
true);
ComboBoxUtils.initialComboBox(controller.productTypeField, viewModel.getProductType(), getProductTypeService(),
true);
ComboBoxUtils.initialComboBox(controller.productUsageField, viewModel.getProductUsage(),
getProductUsageService(), true);
ComboBoxUtils.initialComboBox(controller.deliverySignMethodField, viewModel.getDeliverySignMethod(),
getDeliverySignMethodService(), true);
controller.saleTypeField.valueProperty().addListener((observable, oldValue, newValue) -> {
Predicate<DeliverySignMethodVo> predicate = p -> {
return p == null || Objects.equals(p.getSaleTypeId(), newValue.getId());
};
ObservableList<DeliverySignMethodVo> items = controller.deliverySignMethodField.getItems();
if (items instanceof FilteredList<DeliverySignMethodVo> filteredList) {
filteredList.setPredicate(predicate);
} else {
items = items.filtered(predicate);
controller.deliverySignMethodField.setItems(items);
}
});
// initializeDeliverySignMethodField(controller.saleTypeField,
// controller.deliverySignMethodField); // Changed from
// initializeDeliverySignMethodField(ComboBox<ProjectSaleType>
// saleTypeField,
// ComboBox<DeliverySignMethod>
// field)
controller.descriptionField.textProperty().bindBidirectional(viewModel.getDescription());
UITools.autoCompletion(controller.applicantField, viewModel.getApplicant(), getEmployeeService());
UITools.autoCompletion(controller.authorizerField, viewModel.getAuthorizer(), getEmployeeService());
controller.createdField.setConverter(localDateStringConverter);
controller.createdField.valueProperty().bindBidirectional(viewModel.getCreated());
controller.plannedStartTimeField.setConverter(localDateStringConverter);
controller.plannedStartTimeField.valueProperty().bindBidirectional(viewModel.getPlannedStartTime());
controller.plannedCompletionTimeField.setConverter(localDateStringConverter);
controller.plannedCompletionTimeField.valueProperty().bindBidirectional(viewModel.getPlannedCompletionTime());
controller.versionLabel.textProperty().bind(viewModel.getVersion().asString());
}
private void onDeleteAction(ActionEvent event) {
ProjectCostService projectCostService = getBean(ProjectCostService.class);
ProjectVo project = getEntity();
for (ProjectCostVo cost : projectCostService.findAllByProject(project)) {
projectCostService.delete(cost);
}
getProjectService().delete(project);
controller.root.getScene().getWindow().hide();
}
public void save() {
makeProjectCode();
super.save();
}
private void makeProjectCode() {
StringBuilder sb = new StringBuilder();
ProjectSaleTypeVo saleType = controller.saleTypeField.getValue();
if (saleType == null) {
sb.append("_");
} else {
controller.saleTypeField.getItems().stream()
.filter(item -> item != null && item.getId().equals(saleType.getId()))
.findFirst()
.ifPresent(item -> sb.append(item.getCode()));
}
int year = 0;
{
String text = controller.codeYearField.getText();
if (StringUtils.hasText(text)) {
year = Integer.parseInt(text);
}
}
if (year < 10) {
sb.append("0");
}
sb.append(year);
int sn = 0;
{
String text = controller.codeSequenceNumberField.getText();
if (StringUtils.hasText(text)) {
sn = Integer.parseInt(text);
}
}
if (sn < 10) {
sb.append("00");
} else if (sn < 100) {
sb.append("0");
}
sb.append(sn);
DeliverySignMethodVo signMethod = controller.deliverySignMethodField.getValue();
ProductTypeVo productType = controller.productTypeField.getValue();
ProjectTypeVo projectType = controller.projectTypeField.getValue();
ProjectIndustryVo industry = controller.industryField.getValue();
ProductUsageVo productUsage = controller.productUsageField.getValue();
if (!Stream.of(signMethod, productType, projectType, industry, productUsage)
.allMatch(Objects::isNull)) {
if (signMethod == null) {
sb.append("_");
} else {
controller.deliverySignMethodField.getItems().stream()
.filter(item -> item != null && item.getId().equals(signMethod.getId()))
.findFirst()
.ifPresent(item -> sb.append(item.getCode()));
}
if (productType == null) {
sb.append("_");
} else {
controller.productTypeField.getItems().stream()
.filter(item -> item != null && item.getId().equals(productType.getId()))
.findFirst()
.ifPresent(item -> sb.append(item.getCode()));
}
if (projectType == null) {
sb.append("_");
} else {
controller.projectTypeField.getItems().stream()
.filter(item -> item != null && item.getId().equals(projectType.getId()))
.findFirst()
.ifPresent(item -> sb.append(item.getCode()));
}
if (industry != null) {
controller.industryField.getItems().stream()
.filter(item -> item != null && item.getId().equals(industry.getId()))
.findFirst()
.ifPresent(item -> sb.append(item.getCode()));
} else {
sb.append("_");
}
if (productUsage != null) {
controller.productUsageField.getItems().stream()
.filter(item -> item != null && item.getId().equals(productUsage.getId()))
.findFirst()
.ifPresent(item -> sb.append(item.getCode()));
}
}
viewModel.getCode().set(sb.toString());
}
}

View File

@@ -1,49 +1,47 @@
package com.ecep.contract.manager.ds.project.controller;
package com.ecep.contract.controller.project;
import com.ecep.contract.manager.SpringApp;
import com.ecep.contract.manager.ds.company.CompanyStringConverter;
import com.ecep.contract.manager.ds.company.service.CompanyService;
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 com.ecep.contract.manager.ds.other.EmployeeStringConverter;
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.bid.ProjectBidWindowController;
import com.ecep.contract.manager.ds.project.model.Project;
import com.ecep.contract.manager.ds.project.model.ProjectBid;
import com.ecep.contract.manager.ds.project.service.ProjectBidService;
import com.ecep.contract.manager.ds.project.vo.ProjectBidViewModel;
import com.ecep.contract.manager.ui.*;
import com.ecep.contract.manager.ui.tab.TabSkin;
import com.ecep.contract.manager.ui.table.EditableEntityTableTabSkin;
import javafx.scene.control.*;
import javafx.util.converter.LocalDateStringConverter;
import lombok.Setter;
import org.hibernate.Hibernate;
import org.springframework.util.StringUtils;
import java.io.File;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.CompletableFuture;
import com.ecep.contract.controller.project.bid.ProjectBidWindowController;
import com.ecep.contract.controller.tab.RefreshableSkin;
import com.ecep.contract.controller.tab.TabSkin;
import com.ecep.contract.controller.table.EditableEntityTableTabSkin;
import com.ecep.contract.controller.table.cell.EmployeeTableCell;
import com.ecep.contract.converter.CompanyStringConverter;
import com.ecep.contract.converter.EmployeeStringConverter;
import com.ecep.contract.model.CompanyCustomerEvaluationFormFile;
import com.ecep.contract.model.Employee;
import com.ecep.contract.service.CompanyCustomerFileService;
import com.ecep.contract.service.CompanyCustomerService;
import com.ecep.contract.service.CompanyService;
import com.ecep.contract.service.ProjectBidService;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.vm.ProjectBidViewModel;
import com.ecep.contract.vo.ProjectBidVo;
import com.ecep.contract.vo.ProjectVo;
import javafx.scene.control.Tab;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.util.converter.LocalDateStringConverter;
import lombok.Setter;
@FxmlPath("/ui/project/project-tab-bid.fxml")
public class ProjectTabSkinBid
extends AbstProjectTableTabSkin<ProjectBid, ProjectBidViewModel>
implements TabSkin, EditableEntityTableTabSkin<ProjectBid, ProjectBidViewModel>, RefreshableSkin {
extends AbstProjectTableTabSkin<ProjectBidVo, ProjectBidViewModel>
implements TabSkin, EditableEntityTableTabSkin<ProjectBidVo, ProjectBidViewModel>, RefreshableSkin {
public TableColumn<ProjectBidViewModel, Number> idColumn;
public TableColumn<ProjectBidViewModel, Number> versionColumn;
public TableColumn<ProjectBidViewModel, CompanyCustomerEvaluationFormFile> evaluationFileColumn;
public TableColumn<ProjectBidViewModel, String> descriptionColumn;
public TableColumn<ProjectBidViewModel, Employee> applicantColumn;
public TableColumn<ProjectBidViewModel, Integer> applicantColumn;
public TableColumn<ProjectBidViewModel, LocalDateTime> applyTimeColumn;
public TableColumn<ProjectBidViewModel, Employee> authorizerColumn;
public TableColumn<ProjectBidViewModel, Integer> authorizerColumn;
public TableColumn<ProjectBidViewModel, LocalDateTime> authorizationTimeColumn;
public TableColumn<ProjectBidViewModel, Number> levelColumn;
public TableColumn<ProjectBidViewModel, String> standardPayWayColumn;
@@ -64,7 +62,6 @@ public class ProjectTabSkinBid
@Setter
private CompanyCustomerFileService customerFileService;
public ProjectTabSkinBid(ProjectWindowController controller) {
super(controller);
}
@@ -84,15 +81,18 @@ public class ProjectTabSkinBid
super.initializeTable();
bindNumberColumn(idColumn, ProjectBidViewModel::getId);
// levelColumn.setCellValueFactory(param -> param.getValue().getLevel());
// levelColumn.setCellFactory(param -> new LevelTableCell());
// standardPayWayColumn.setCellValueFactory(param -> param.getValue().getStandardPayWay().map(value -> value == null ? "" : (value ? "标准" : "非标准")));
// evaluationFileColumn.setCellValueFactory(param -> param.getValue().getEvaluationFile());
// evaluationFileColumn.setCellFactory(param -> new EvaluationFileTableCell());
// levelColumn.setCellValueFactory(param -> param.getValue().getLevel());
// levelColumn.setCellFactory(param -> new LevelTableCell());
// standardPayWayColumn.setCellValueFactory(param ->
// param.getValue().getStandardPayWay().map(value -> value == null ? "" : (value
// ? "标准" : "非标准")));
// evaluationFileColumn.setCellValueFactory(param ->
// param.getValue().getEvaluationFile());
// evaluationFileColumn.setCellFactory(param -> new EvaluationFileTableCell());
// amountColumn.setCellValueFactory(param -> param.getValue().getAmount());
// amountColumn.setCellFactory(TextFieldTableCell.forTableColumn(new CurrencyStringConverter(getLocale())));
// amountColumn.setCellValueFactory(param -> param.getValue().getAmount());
// amountColumn.setCellFactory(TextFieldTableCell.forTableColumn(new
// CurrencyStringConverter(getLocale())));
applicantColumn.setCellValueFactory(param -> param.getValue().getApplicant());
applicantColumn.setCellFactory(cell -> new EmployeeTableCell<>(getEmployeeService()));
@@ -107,9 +107,11 @@ public class ProjectTabSkinBid
@Override
protected ProjectBidViewModel createNewViewModel() {
ProjectBidViewModel model = new ProjectBidViewModel();
Project project = getParent();
model.getProject().set(project);
model.getApplicant().set(project.getApplicant());
ProjectVo project = getParent();
model.getProject().set(project.getId());
if (project.getApplicantId() != null) {
model.getApplicant().set(project.getApplicantId());
}
if (project.getAmount() != null) {
model.getAmount().set(project.getAmount());
}
@@ -178,21 +180,20 @@ public class ProjectTabSkinBid
}
@Override
public void deleteRowData(ProjectBid entity) {
public void deleteRowData(ProjectBidVo entity) {
getProjectBidService().delete(entity);
}
@Override
public ProjectBid loadRowData(ProjectBidViewModel row) {
public ProjectBidVo loadRowData(ProjectBidViewModel row) {
return getProjectBidService().findById(row.getId().get());
}
@Override
public ProjectBid saveRowData(ProjectBid entity) {
public ProjectBidVo saveRowData(ProjectBidVo entity) {
return getProjectBidService().save(entity);
}
private static class LevelTableCell extends TableCell<ProjectBidViewModel, Number> {
@Override
protected void updateItem(Number item, boolean empty) {

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