refactor(ui): 重构BaseController及相关组件,优化代码结构和性能

重构BaseController,移除冗余属性,引入bean缓存机制
新增LocalDateTimeConfig类处理日期时间配置
优化AbstEntityManagerSkin的分页和表格数据处理逻辑
调整ContractTabSkinBase的依赖注入方式,使用缓存bean
统一日期、数字和货币的格式化处理,使用CurrentEmployee的配置
This commit is contained in:
2025-08-27 19:36:30 +08:00
parent f810532824
commit c69d3f1af2
16 changed files with 484 additions and 208 deletions

View File

@@ -1,5 +1,6 @@
package com.ecep.contract.manager; package com.ecep.contract.manager;
import java.time.format.DateTimeFormatter;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
@@ -8,22 +9,28 @@ import java.util.concurrent.TimeUnit;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import com.ecep.contract.manager.ds.other.model.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.model.EmployeeRole;
import com.ecep.contract.manager.ds.other.service.EmployeeService; import com.ecep.contract.manager.ds.other.service.EmployeeService;
import com.ecep.contract.manager.ds.other.vo.EmployeeViewModel; import com.ecep.contract.manager.ds.other.vo.EmployeeViewModel;
import com.ecep.contract.manager.util.MyDateTimeUtils;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.beans.property.SimpleListProperty; import javafx.beans.property.SimpleListProperty;
import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections; import javafx.collections.FXCollections;
import javafx.util.converter.CurrencyStringConverter;
import javafx.util.converter.LocalDateStringConverter;
import javafx.util.converter.LocalDateTimeStringConverter;
import javafx.util.converter.NumberStringConverter;
import lombok.ToString; import lombok.ToString;
/** /**
* 当前登录用户 * 当前登录用户
*/ */
@ToString(of = {"id", "name", "email", "phone", "roles"}) @ToString(callSuper = false, exclude = "roles")
public class CurrentEmployee extends EmployeeViewModel { public class CurrentEmployee extends EmployeeViewModel {
private static final Logger logger = LoggerFactory.getLogger(CurrentEmployee.class); private static final Logger logger = LoggerFactory.getLogger(CurrentEmployee.class);
/** /**
@@ -34,24 +41,89 @@ public class CurrentEmployee extends EmployeeViewModel {
* 角色 * 角色
*/ */
private SimpleListProperty<EmployeeRole> roles = new SimpleListProperty<>(FXCollections.observableArrayList()); private SimpleListProperty<EmployeeRole> roles = new SimpleListProperty<>(FXCollections.observableArrayList());
private DateTimeFormatter dateFormatter = DateTimeFormatter
.ofPattern(MyDateTimeUtils.DEFAULT_DATE_FORMAT_PATTERN);
private DateTimeFormatter dateTimeFormatter = DateTimeFormatter
.ofPattern(MyDateTimeUtils.DEFAULT_DATETIME_FORMAT_PATTERN);
private DateTimeFormatter timeFormatter = DateTimeFormatter
.ofPattern(MyDateTimeUtils.DEFAULT_TIME_FORMAT_PATTERN);
private LocalDateStringConverter localDateStringConverter = new LocalDateStringConverter(
dateFormatter, null);
private LocalDateTimeStringConverter localDateTimeStringConverter = new LocalDateTimeStringConverter(
dateTimeFormatter, null);
private NumberStringConverter numberStringConverter = new NumberStringConverter("#,##0.00");
private CurrencyStringConverter currencyStringConverter = new CurrencyStringConverter("#,##0.00");
/** /**
* 是否系统管理员 * 是否系统管理员
*/ */
public boolean isSystemAdministrator() { public boolean isSystemAdministrator() {
return roles.stream().anyMatch(EmployeeRole::isSystemAdministrator); return roles.stream().anyMatch(EmployeeRole::isSystemAdministrator);
} }
/** /**
* 语言环境属性 * 语言环境属性
*/ */
public SimpleObjectProperty<Locale> localeProperty() { public SimpleObjectProperty<Locale> localeProperty() {
return locale; return locale;
} }
/** /**
* 角色属性 * 角色属性
*/ */
public SimpleListProperty<EmployeeRole> rolesProperty() { public SimpleListProperty<EmployeeRole> rolesProperty() {
return roles; return roles;
} }
@Override
protected void updateFrom(Employee v) {
super.updateFrom(v);
// 根据用户的个人配置修改
if (StringUtils.hasText(v.getLocale())) {
try {
localeProperty().set(Locale.forLanguageTag(v.getLocale()));
} catch (Exception e) {
handleException("解析设置用户区域设置失败," + v.getLocale(), e);
}
}
if (StringUtils.hasText(v.getDateFormatter())) {
try {
dateFormatter = DateTimeFormatter.ofPattern(v.getDateFormatter());
localDateStringConverter = new LocalDateStringConverter(dateFormatter, null);
} catch (Exception e) {
handleException("解析设置用户日期格式失败," + v.getDateFormatter(), e);
}
}
if (StringUtils.hasText(v.getDateTimeFormatter())) {
try {
dateTimeFormatter = DateTimeFormatter.ofPattern(v.getDateTimeFormatter());
localDateTimeStringConverter = new LocalDateTimeStringConverter(dateTimeFormatter, null);
} catch (Exception e) {
handleException("解析设置用户日期时间格式失败," + v.getDateTimeFormatter(), e);
}
}
if (StringUtils.hasText(v.getNumberFormatter())) {
try {
numberStringConverter = new NumberStringConverter(localeProperty().get(), v.getNumberFormatter());
} catch (Exception e) {
handleException("解析设置用户数字格式失败," + v.getNumberFormatter(), e);
}
}
if (StringUtils.hasText(v.getCurrencyFormatter())) {
try {
currencyStringConverter = new CurrencyStringConverter(localeProperty().get(), v.getCurrencyFormatter());
} catch (Exception e) {
handleException("解析设置用户货币格式失败," + v.getCurrencyFormatter(), e);
}
}
}
/** /**
* 初始化 * 初始化
*/ */
@@ -92,4 +164,24 @@ public class CurrentEmployee extends EmployeeViewModel {
}, 10, 10, TimeUnit.SECONDS); }, 10, 10, TimeUnit.SECONDS);
return future; return future;
} }
private void handleException(String msg, Exception e) {
logger.warn(msg, e);
}
public LocalDateStringConverter getLocalDateStringConverter() {
return localDateStringConverter;
}
public LocalDateTimeStringConverter getLocalDateTimeStringConverter() {
return localDateTimeStringConverter;
}
public NumberStringConverter getNumberStringConverter() {
return numberStringConverter;
}
public CurrencyStringConverter getCurrencyStringConverter() {
return currencyStringConverter;
}
} }

View File

@@ -7,6 +7,7 @@ import org.springframework.stereotype.Component;
import com.ecep.contract.manager.cloud.u8.ctx.CompanyCtx; import com.ecep.contract.manager.cloud.u8.ctx.CompanyCtx;
import com.ecep.contract.manager.cloud.u8.ctx.ContractCtx; import com.ecep.contract.manager.cloud.u8.ctx.ContractCtx;
import com.ecep.contract.manager.ds.other.LocalDateConfig; import com.ecep.contract.manager.ds.other.LocalDateConfig;
import com.ecep.contract.manager.ds.other.LocalDateTimeConfig;
import com.ecep.contract.manager.ds.other.StringConfig; import com.ecep.contract.manager.ds.other.StringConfig;
import com.ecep.contract.manager.ui.BaseController; import com.ecep.contract.manager.ui.BaseController;
import com.ecep.contract.manager.ui.FxmlPath; import com.ecep.contract.manager.ui.FxmlPath;
@@ -25,7 +26,7 @@ public class YongYouU8ConfigWindowController extends BaseController {
private DatePicker auto_create_company_after; private DatePicker auto_create_company_after;
@FXML @FXML
private DatePicker contract_latest_date; private TextField contract_latest_date;
@FXML @FXML
private TextField contract_latest_id; private TextField contract_latest_id;
@@ -42,15 +43,16 @@ public class YongYouU8ConfigWindowController extends BaseController {
config1.setPicker(auto_create_company_after); config1.setPicker(auto_create_company_after);
config1.initialize(); config1.initialize();
LocalDateConfig config2 = new LocalDateConfig(ContractCtx.KEY_SYNC_BY_LATEST_DATE); LocalDateTimeConfig config2 = new LocalDateTimeConfig(ContractCtx.KEY_SYNC_BY_LATEST_DATE);
config2.setPicker(contract_latest_date); config2.setTextField(contract_latest_date);
config2.setConverter(getCurrentEmployee().getLocalDateTimeStringConverter());
config2.initialize(); config2.initialize();
StringConfig config3 = new StringConfig(ContractCtx.KEY_SYNC_BY_LATEST_ID); StringConfig config3 = new StringConfig(ContractCtx.KEY_SYNC_BY_LATEST_ID);
config3.setTextField(contract_latest_id); config3.setTextField(contract_latest_id);
config3.initialize(); config3.initialize();
StringConfig config4 = new StringConfig("cloud.u8.sync.elapse"); StringConfig config4 = new StringConfig(ContractCtx.KEY_SYNC_ELAPSE);
config4.setTextField(sync_elapse); config4.setTextField(sync_elapse);
config4.initialize(); config4.initialize();

View File

@@ -1,11 +1,42 @@
package com.ecep.contract.manager.cloud.u8.ctx; package com.ecep.contract.manager.cloud.u8.ctx;
import static com.ecep.contract.manager.SpringApp.getBean;
import java.io.File;
import java.text.NumberFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.hibernate.Hibernate;
import org.springframework.util.StringUtils;
import com.ecep.contract.manager.cloud.u8.YongYouU8Service; import com.ecep.contract.manager.cloud.u8.YongYouU8Service;
import com.ecep.contract.manager.ds.company.CompanyFileUtils; import com.ecep.contract.manager.ds.company.CompanyFileUtils;
import com.ecep.contract.manager.ds.company.model.Company; import com.ecep.contract.manager.ds.company.model.Company;
import com.ecep.contract.manager.ds.contract.ContractFileType; import com.ecep.contract.manager.ds.contract.ContractFileType;
import com.ecep.contract.manager.ds.contract.ContractPayWay; import com.ecep.contract.manager.ds.contract.ContractPayWay;
import com.ecep.contract.manager.ds.contract.model.*; import com.ecep.contract.manager.ds.contract.model.Contract;
import com.ecep.contract.manager.ds.contract.model.ContractCatalog;
import com.ecep.contract.manager.ds.contract.model.ContractFile;
import com.ecep.contract.manager.ds.contract.model.ContractFileTypeLocal;
import com.ecep.contract.manager.ds.contract.model.ContractGroup;
import com.ecep.contract.manager.ds.contract.model.ContractItem;
import com.ecep.contract.manager.ds.contract.model.ContractKind;
import com.ecep.contract.manager.ds.contract.model.ContractPayPlan;
import com.ecep.contract.manager.ds.contract.model.ContractType;
import com.ecep.contract.manager.ds.contract.service.ContractFileService; import com.ecep.contract.manager.ds.contract.service.ContractFileService;
import com.ecep.contract.manager.ds.contract.service.ContractItemService; import com.ecep.contract.manager.ds.contract.service.ContractItemService;
import com.ecep.contract.manager.ds.contract.service.ContractPayPlanService; import com.ecep.contract.manager.ds.contract.service.ContractPayPlanService;
@@ -27,22 +58,9 @@ import com.ecep.contract.manager.ui.MessageHolder;
import com.ecep.contract.manager.util.MyDateTimeUtils; import com.ecep.contract.manager.util.MyDateTimeUtils;
import com.ecep.contract.manager.util.NumberUtils; import com.ecep.contract.manager.util.NumberUtils;
import com.ecep.contract.manager.util.TaxRateUtils; import com.ecep.contract.manager.util.TaxRateUtils;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import org.hibernate.Hibernate;
import org.springframework.util.StringUtils;
import java.io.File;
import java.text.NumberFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeParseException;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static com.ecep.contract.manager.SpringApp.getBean;
/** /**
* 合同上下文 * 合同上下文
@@ -61,6 +79,10 @@ public class ContractCtx extends AbstractYongYouU8Ctx {
* 合同同步时是否使用最后更新的Id来判断更新范围否则使用最后更新的合同日期来判断更新范围 * 合同同步时是否使用最后更新的Id来判断更新范围否则使用最后更新的合同日期来判断更新范围
*/ */
public static final String KEY_SYNC_USE_LATEST_ID = KEY_PREFIX + "sync.use-latest-id"; public static final String KEY_SYNC_USE_LATEST_ID = KEY_PREFIX + "sync.use-latest-id";
/**
* 合同同步时的时间间隔,单位:秒
*/
public static final String KEY_SYNC_ELAPSE = KEY_PREFIX + "sync.elapse";
@Setter @Setter
private ContractService contractService; private ContractService contractService;

View File

@@ -1,5 +1,18 @@
package com.ecep.contract.manager.ds.contract.controller; package com.ecep.contract.manager.ds.contract.controller;
import java.io.File;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Optional;
import org.controlsfx.control.textfield.TextFields;
import org.controlsfx.glyphfont.Glyph;
import org.hibernate.Hibernate;
import org.springframework.util.StringUtils;
import com.ecep.contract.manager.SpringApp; import com.ecep.contract.manager.SpringApp;
import com.ecep.contract.manager.ds.company.CompanyFileUtils; import com.ecep.contract.manager.ds.company.CompanyFileUtils;
import com.ecep.contract.manager.ds.company.CompanyStringConverter; import com.ecep.contract.manager.ds.company.CompanyStringConverter;
@@ -26,8 +39,8 @@ import com.ecep.contract.manager.ds.vendor.model.CompanyVendor;
import com.ecep.contract.manager.ds.vendor.service.CompanyVendorService; import com.ecep.contract.manager.ds.vendor.service.CompanyVendorService;
import com.ecep.contract.manager.ds.vendor.service.VendorGroupService; import com.ecep.contract.manager.ds.vendor.service.VendorGroupService;
import com.ecep.contract.manager.ui.tab.TabSkin; import com.ecep.contract.manager.ui.tab.TabSkin;
import com.ecep.contract.manager.util.MyDateTimeUtils;
import com.ecep.contract.manager.util.UITools; import com.ecep.contract.manager.util.UITools;
import javafx.beans.binding.Bindings; import javafx.beans.binding.Bindings;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
import javafx.scene.control.Tab; import javafx.scene.control.Tab;
@@ -36,34 +49,13 @@ import javafx.scene.control.TextInputDialog;
import javafx.stage.DirectoryChooser; import javafx.stage.DirectoryChooser;
import javafx.util.StringConverter; import javafx.util.StringConverter;
import javafx.util.converter.LocalDateStringConverter; import javafx.util.converter.LocalDateStringConverter;
import javafx.util.converter.LocalDateTimeStringConverter;
import javafx.util.converter.NumberStringConverter; import javafx.util.converter.NumberStringConverter;
import lombok.Setter; import lombok.Setter;
import org.controlsfx.control.textfield.TextFields;
import org.controlsfx.glyphfont.Glyph;
import org.hibernate.Hibernate;
import org.springframework.util.StringUtils;
import java.io.File;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
/** /**
* * 合同基础信息标签页
*/ */
public class ContractTabSkinBase public class ContractTabSkinBase extends AbstContractBasedTabSkin {
extends AbstContractBasedTabSkin
implements TabSkin {
@Setter
private CompanyCustomerService companyCustomerService;
@Setter
private SaleTypeService saleTypeService;
@Setter
private ExtendVendorInfoService extendVendorInfoService;
@Setter
private VendorGroupService vendorGroupService;
public ContractTabSkinBase(ContractWindowController controller) { public ContractTabSkinBase(ContractWindowController controller) {
super(controller); super(controller);
@@ -88,7 +80,8 @@ public class ContractTabSkinBase
return v == null ? "关联" : "打开"; return v == null ? "关联" : "打开";
})); }));
Glyph linkContractProjectBtnIcon = new Glyph("FontAwesome", viewModel.getProject().get() == null ? "UNLINK" : "LINK"); Glyph linkContractProjectBtnIcon = new Glyph("FontAwesome",
viewModel.getProject().get() == null ? "UNLINK" : "LINK");
controller.linkContractProjectBtn.graphicProperty().set(linkContractProjectBtnIcon); controller.linkContractProjectBtn.graphicProperty().set(linkContractProjectBtnIcon);
linkContractProjectBtnIcon.iconProperty().bind(viewModel.getProject().map(v -> { linkContractProjectBtnIcon.iconProperty().bind(viewModel.getProject().map(v -> {
return v == null ? "UNLINK" : "LINK"; return v == null ? "UNLINK" : "LINK";
@@ -124,7 +117,8 @@ public class ContractTabSkinBase
if (!Hibernate.isInitialized(type)) { if (!Hibernate.isInitialized(type)) {
type = getContractService().findTypeById(type.getId()); type = getContractService().findTypeById(type.getId());
} }
return type.getCode() + " " + type.getCatalog() + " " + type.getName() + " " + type.getTitle() + "(" + type.getDirection() + ")"; return type.getCode() + " " + type.getCatalog() + " " + type.getName() + " " + type.getTitle() + "("
+ type.getDirection() + ")";
})); }));
controller.kindField.textProperty().bind(viewModel.getKind().map(kind -> { controller.kindField.textProperty().bind(viewModel.getKind().map(kind -> {
@@ -150,8 +144,10 @@ public class ContractTabSkinBase
} }
return !Objects.equals(type.getDirection(), ""); return !Objects.equals(type.getDirection(), "");
}, viewModel.getType())); }, viewModel.getType()));
controller.openRelativeCompanyCustomerBtn.managedProperty().bind(controller.openRelativeCompanyCustomerBtn.disabledProperty().not()); controller.openRelativeCompanyCustomerBtn.managedProperty()
controller.openRelativeCompanyCustomerBtn.visibleProperty().bind(controller.openRelativeCompanyCustomerBtn.managedProperty()); .bind(controller.openRelativeCompanyCustomerBtn.disabledProperty().not());
controller.openRelativeCompanyCustomerBtn.visibleProperty()
.bind(controller.openRelativeCompanyCustomerBtn.managedProperty());
// as vendor // as vendor
controller.openRelativeCompanyVendorBtn.setOnAction(this::onContractOpenRelativeCompanyVendorAction); controller.openRelativeCompanyVendorBtn.setOnAction(this::onContractOpenRelativeCompanyVendorAction);
@@ -169,10 +165,13 @@ public class ContractTabSkinBase
} }
return !Objects.equals(type.getDirection(), ""); return !Objects.equals(type.getDirection(), "");
}, viewModel.getType())); }, viewModel.getType()));
controller.openRelativeCompanyVendorBtn.managedProperty().bind(controller.openRelativeCompanyVendorBtn.disabledProperty().not()); controller.openRelativeCompanyVendorBtn.managedProperty()
controller.openRelativeCompanyVendorBtn.visibleProperty().bind(controller.openRelativeCompanyVendorBtn.managedProperty()); .bind(controller.openRelativeCompanyVendorBtn.disabledProperty().not());
controller.openRelativeCompanyVendorBtn.visibleProperty()
.bind(controller.openRelativeCompanyVendorBtn.managedProperty());
LocalDateStringConverter localDateStringConverter = controller.localDateStringConverter; LocalDateStringConverter localDateStringConverter = controller.getCurrentEmployee()
.getLocalDateStringConverter();
controller.setupDateField.setConverter(localDateStringConverter); controller.setupDateField.setConverter(localDateStringConverter);
controller.setupDateField.valueProperty().bindBidirectional(viewModel.getSetupDate()); controller.setupDateField.valueProperty().bindBidirectional(viewModel.getSetupDate());
@@ -202,21 +201,23 @@ public class ContractTabSkinBase
initializeBaseTabProjectFieldAutoCompletion(controller.projectField); initializeBaseTabProjectFieldAutoCompletion(controller.projectField);
controller.pathField.textProperty().bind(viewModel.getPath()); controller.pathField.textProperty().bind(viewModel.getPath());
// controller.createdField.textProperty().bind(viewModel.getCreated().map(MyDateTimeUtils::format)); controller.createdField.textProperty().bindBidirectional(viewModel.getCreated(),
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(MyDateTimeUtils.DEFAULT_DATETIME_FORMAT_PATTERN); controller.getCurrentEmployee().getLocalDateTimeStringConverter());
controller.createdField.textProperty().bindBidirectional(viewModel.getCreated(), new LocalDateTimeStringConverter(dateTimeFormatter, null));
controller.guidField.textProperty().bind(viewModel.getGuid()); controller.guidField.textProperty().bind(viewModel.getGuid());
controller.descriptionField.textProperty().bindBidirectional(viewModel.getDescription()); controller.descriptionField.textProperty().bindBidirectional(viewModel.getDescription());
NumberStringConverter numberStringConverter = controller.getCurrentEmployee().getNumberStringConverter();
NumberStringConverter numberStringConverter = new NumberStringConverter(controller.getLocale(), "#,##0.00");
controller.amountField.textProperty().bindBidirectional(viewModel.getAmount(), numberStringConverter); controller.amountField.textProperty().bindBidirectional(viewModel.getAmount(), numberStringConverter);
controller.totalQuantityField.textProperty().bindBidirectional(viewModel.getTotalQuantity(), numberStringConverter); controller.totalQuantityField.textProperty().bindBidirectional(viewModel.getTotalQuantity(),
numberStringConverter);
controller.totalAmountField.textProperty().bindBidirectional(viewModel.getTotalAmount(), numberStringConverter); controller.totalAmountField.textProperty().bindBidirectional(viewModel.getTotalAmount(), numberStringConverter);
controller.totalUnTaxAmountField.textProperty().bindBidirectional(viewModel.getTotalUnTaxAmount(), numberStringConverter); controller.totalUnTaxAmountField.textProperty().bindBidirectional(viewModel.getTotalUnTaxAmount(),
controller.execQuantityField.textProperty().bindBidirectional(viewModel.getExecQuantity(), numberStringConverter); numberStringConverter);
controller.execQuantityField.textProperty().bindBidirectional(viewModel.getExecQuantity(),
numberStringConverter);
controller.execAmountField.textProperty().bindBidirectional(viewModel.getExecAmount(), numberStringConverter); controller.execAmountField.textProperty().bindBidirectional(viewModel.getExecAmount(), numberStringConverter);
controller.execUnTaxAmountField.textProperty().bindBidirectional(viewModel.getExecUnTaxAmount(), numberStringConverter); controller.execUnTaxAmountField.textProperty().bindBidirectional(viewModel.getExecUnTaxAmount(),
numberStringConverter);
controller.versionLabel.textProperty().bind(viewModel.getVersion().asString()); controller.versionLabel.textProperty().bind(viewModel.getVersion().asString());
} }
@@ -264,7 +265,6 @@ public class ContractTabSkinBase
return; return;
} }
project = new Project(); project = new Project();
String name = viewModel.getName().get(); String name = viewModel.getName().get();
@@ -327,7 +327,6 @@ public class ContractTabSkinBase
ContractWindowController.show(parent, controller.root.getScene().getWindow()); ContractWindowController.show(parent, controller.root.getScene().getWindow());
} }
/** /**
* 创建合同存储目录 * 创建合同存储目录
*/ */
@@ -470,7 +469,6 @@ public class ContractTabSkinBase
CompanyVendorWindowController.show(companyVendor, null); CompanyVendorWindowController.show(companyVendor, null);
} }
private void initializeBaseTabCompanyFieldAutoCompletion(TextField textField) { private void initializeBaseTabCompanyFieldAutoCompletion(TextField textField) {
CompanyStringConverter converter = SpringApp.getBean(CompanyStringConverter.class); CompanyStringConverter converter = SpringApp.getBean(CompanyStringConverter.class);
UITools.autoCompletion(textField, viewModel.getCompany(), converter); UITools.autoCompletion(textField, viewModel.getCompany(), converter);
@@ -498,12 +496,8 @@ public class ContractTabSkinBase
UITools.autoCompletion(textField, viewModel.getProject(), converter::suggest, stringConverter); UITools.autoCompletion(textField, viewModel.getProject(), converter::suggest, stringConverter);
} }
public CompanyCustomerService getCompanyCustomerService() { public CompanyCustomerService getCompanyCustomerService() {
if (companyCustomerService == null) { return controller.getCachedBean(CompanyCustomerService.class);
companyCustomerService = SpringApp.getBean(CompanyCustomerService.class);
}
return companyCustomerService;
} }
public ProjectService getProjectService() { public ProjectService getProjectService() {
@@ -511,23 +505,14 @@ public class ContractTabSkinBase
} }
public SaleTypeService getSaleTypeService() { public SaleTypeService getSaleTypeService() {
if (saleTypeService == null) { return controller.getCachedBean(SaleTypeService.class);
saleTypeService = SpringApp.getBean(SaleTypeService.class);
}
return saleTypeService;
} }
public ExtendVendorInfoService getExtendVendorInfoService() { public ExtendVendorInfoService getExtendVendorInfoService() {
if (extendVendorInfoService == null) { return controller.getCachedBean(ExtendVendorInfoService.class);
extendVendorInfoService = SpringApp.getBean(ExtendVendorInfoService.class);
}
return extendVendorInfoService;
} }
public VendorGroupService getVendorGroupService() { public VendorGroupService getVendorGroupService() {
if (vendorGroupService == null) { return controller.getCachedBean(VendorGroupService.class);
vendorGroupService = SpringApp.getBean(VendorGroupService.class);
}
return vendorGroupService;
} }
} }

View File

@@ -1,5 +1,13 @@
package com.ecep.contract.manager.ds.contract.controller; package com.ecep.contract.manager.ds.contract.controller;
import java.io.File;
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 com.ecep.contract.manager.ds.company.controller.CompanyWindowController; 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.Company;
import com.ecep.contract.manager.ds.company.service.CompanyService; import com.ecep.contract.manager.ds.company.service.CompanyService;
@@ -13,21 +21,19 @@ import com.ecep.contract.manager.ui.AbstEntityController;
import com.ecep.contract.manager.ui.FxmlPath; import com.ecep.contract.manager.ui.FxmlPath;
import com.ecep.contract.manager.util.DesktopUtils; import com.ecep.contract.manager.util.DesktopUtils;
import com.ecep.contract.manager.util.UITools; import com.ecep.contract.manager.util.UITools;
import javafx.collections.ObservableList; import javafx.collections.ObservableList;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
import javafx.scene.control.*; import javafx.scene.control.Button;
import javafx.scene.control.DatePicker;
import javafx.scene.control.Label;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane; import javafx.scene.layout.BorderPane;
import javafx.stage.Window; import javafx.stage.Window;
import javafx.stage.WindowEvent; import javafx.stage.WindowEvent;
import javafx.util.converter.LocalDateStringConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.io.File;
import java.time.format.DateTimeFormatter;
@Lazy @Lazy
@Scope("prototype") @Scope("prototype")
@@ -70,9 +76,6 @@ public class ContractWindowController
@Autowired @Autowired
ProjectService projectService; ProjectService projectService;
LocalDateStringConverter localDateStringConverter = new LocalDateStringConverter(DateTimeFormatter.ISO_LOCAL_DATE, null);
public TextField nameField; public TextField nameField;
public TextField guidField; public TextField guidField;
public TextField codeField; public TextField codeField;

View File

@@ -2,12 +2,8 @@ package com.ecep.contract.manager.ds.other;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.concurrent.CompletableFuture;
import com.ecep.contract.manager.Desktop;
import com.ecep.contract.manager.SpringApp;
import com.ecep.contract.manager.ds.other.model.SysConf; import com.ecep.contract.manager.ds.other.model.SysConf;
import com.ecep.contract.manager.ds.other.service.SysConfService;
import javafx.beans.property.Property; import javafx.beans.property.Property;
import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleObjectProperty;

View File

@@ -0,0 +1,51 @@
package com.ecep.contract.manager.ds.other;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import com.ecep.contract.manager.ds.other.model.SysConf;
import javafx.beans.property.Property;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ObservableValue;
import javafx.scene.control.TextField;
import javafx.util.converter.LocalDateTimeStringConverter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@NoArgsConstructor
public class LocalDateTimeConfig extends AbstractConfigBounder {
Property<LocalDateTime> property;
@Setter
javafx.util.StringConverter<LocalDateTime> converter;
@Setter
TextField textField;
public LocalDateTimeConfig(String string) {
key = string;
}
@Override
public void initialize() {
textField.setDisable(true);
if (converter == null) {
converter = new LocalDateTimeStringConverter(DateTimeFormatter.ISO_LOCAL_DATE_TIME, null);
}
runAsync(() -> {
conf = getConfService().findById(key);
LocalDateTime dateTime = LocalDateTime.parse(conf.getValue());
property = new SimpleObjectProperty<>(dateTime);
property.addListener(this::propertyChanged);
textField.textProperty().bindBidirectional(property, converter);
textField.setDisable(false);
});
}
void propertyChanged(ObservableValue<? extends LocalDateTime> observable, LocalDateTime oldValue,
LocalDateTime newValue) {
conf.setValue(newValue.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
SysConf saved = getConfService().save(conf);
saved.getValue();
}
}

View File

@@ -1,5 +1,7 @@
package com.ecep.contract.manager.ds.other.controller.inventory; package com.ecep.contract.manager.ds.other.controller.inventory;
import java.util.function.Function;
import com.ecep.contract.manager.ds.other.EntityStringConverter; 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.Inventory;
import com.ecep.contract.manager.ds.other.model.InventoryCatalog; import com.ecep.contract.manager.ds.other.model.InventoryCatalog;
@@ -7,10 +9,9 @@ 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.service.InventoryService;
import com.ecep.contract.manager.ds.other.vo.InventoryViewModel; import com.ecep.contract.manager.ds.other.vo.InventoryViewModel;
import com.ecep.contract.manager.ui.AbstEntityManagerSkin; 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 com.ecep.contract.manager.ui.table.cell.LocalDateTimeTableCell;
import com.ecep.contract.manager.ui.util.LocalDateFieldTableCell;
import javafx.beans.property.Property; import javafx.beans.property.Property;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
import javafx.scene.control.TableColumn; import javafx.scene.control.TableColumn;
@@ -19,11 +20,8 @@ import javafx.util.converter.CurrencyStringConverter;
import javafx.util.converter.NumberStringConverter; import javafx.util.converter.NumberStringConverter;
import lombok.Setter; import lombok.Setter;
import java.util.function.Function; public class InventoryManagerSkin extends
AbstEntityManagerSkin<Inventory, InventoryViewModel, InventoryManagerSkin, InventoryManagerWindowController> {
public class InventoryManagerSkin
extends AbstEntityManagerSkin<Inventory, InventoryViewModel, InventoryManagerSkin, InventoryManagerWindowController>
implements ManagerSkin, EditableEntityTableTabSkin<Inventory, InventoryViewModel> {
@Setter @Setter
private InventoryCatalogService catalogService; private InventoryCatalogService catalogService;
@@ -69,7 +67,8 @@ public class InventoryManagerSkin
controller.specificationColumn.setCellValueFactory(param -> param.getValue().getSpecification()); controller.specificationColumn.setCellValueFactory(param -> param.getValue().getSpecification());
controller.specificationColumn.setCellFactory(TextFieldTableCell.forTableColumn()); controller.specificationColumn.setCellFactory(TextFieldTableCell.forTableColumn());
controller.specificationColumn.setOnEditCommit(event -> onColumnEditCommit(event, InventoryViewModel::getSpecification)); controller.specificationColumn
.setOnEditCommit(event -> onColumnEditCommit(event, InventoryViewModel::getSpecification));
controller.unitColumn.setCellValueFactory(param -> param.getValue().getUnit()); controller.unitColumn.setCellValueFactory(param -> param.getValue().getUnit());
controller.unitColumn.setCellFactory(TextFieldTableCell.forTableColumn()); controller.unitColumn.setCellFactory(TextFieldTableCell.forTableColumn());
@@ -77,44 +76,48 @@ public class InventoryManagerSkin
controller.purchaseTaxRateColumn.setCellValueFactory(param -> param.getValue().getPurchaseTaxRate()); controller.purchaseTaxRateColumn.setCellValueFactory(param -> param.getValue().getPurchaseTaxRate());
controller.purchaseTaxRateColumn.setCellFactory(TextFieldTableCell.forTableColumn(new NumberStringConverter())); controller.purchaseTaxRateColumn.setCellFactory(TextFieldTableCell.forTableColumn(new NumberStringConverter()));
controller.purchaseTaxRateColumn.setOnEditCommit(event -> onColumnEditCommit(event, InventoryViewModel::getPurchaseTaxRate)); controller.purchaseTaxRateColumn
.setOnEditCommit(event -> onColumnEditCommit(event, InventoryViewModel::getPurchaseTaxRate));
controller.purchasePriceColumn.setCellValueFactory(param -> param.getValue().getPurchasePrice()); controller.purchasePriceColumn.setCellValueFactory(param -> param.getValue().getPurchasePrice());
controller.purchasePriceColumn.setCellFactory(TextFieldTableCell.forTableColumn(new CurrencyStringConverter())); controller.purchasePriceColumn.setCellFactory(TextFieldTableCell.forTableColumn(new CurrencyStringConverter()));
// controller.purchasePriceColumn.setOnEditCommit(event -> onColumnEditCommit(event, InventoryViewModel::getPurchasePrice)); // controller.purchasePriceColumn.setOnEditCommit(event ->
// onColumnEditCommit(event, InventoryViewModel::getPurchasePrice));
controller.saleTaxRateColumn.setCellValueFactory(param -> param.getValue().getSaleTaxRate()); controller.saleTaxRateColumn.setCellValueFactory(param -> param.getValue().getSaleTaxRate());
controller.saleTaxRateColumn.setCellFactory(TextFieldTableCell.forTableColumn(new NumberStringConverter())); controller.saleTaxRateColumn.setCellFactory(TextFieldTableCell.forTableColumn(new NumberStringConverter()));
controller.saleTaxRateColumn.setOnEditCommit(event -> onColumnEditCommit(event, InventoryViewModel::getSaleTaxRate)); controller.saleTaxRateColumn
.setOnEditCommit(event -> onColumnEditCommit(event, InventoryViewModel::getSaleTaxRate));
controller.salePriceColumn.setCellValueFactory(param -> param.getValue().getSalePrice()); controller.salePriceColumn.setCellValueFactory(param -> param.getValue().getSalePrice());
controller.salePriceColumn.setCellFactory(TextFieldTableCell.forTableColumn(new CurrencyStringConverter())); controller.salePriceColumn.setCellFactory(TextFieldTableCell.forTableColumn(new CurrencyStringConverter()));
// controller.salePriceColumn.setOnEditCommit(event -> onColumnEditCommit(event, InventoryViewModel::getSalePrice)); // controller.salePriceColumn.setOnEditCommit(event -> onColumnEditCommit(event,
// InventoryViewModel::getSalePrice));
controller.createTimeColumn.setCellValueFactory(param -> param.getValue().getCreateTime()); controller.createTimeColumn.setCellValueFactory(param -> param.getValue().getCreateTime());
controller.createTimeColumn.setCellFactory(LocalDateFieldTableCell.forTableColumn()); controller.createTimeColumn.setCellFactory(LocalDateFieldTableCell.forTableColumn());
controller.createTimeColumn.setOnEditCommit(event -> onColumnEditCommit(event, InventoryViewModel::getCreateTime)); controller.createTimeColumn
.setOnEditCommit(event -> onColumnEditCommit(event, InventoryViewModel::getCreateTime));
controller.updateDateColumn.setCellValueFactory(param -> param.getValue().getUpdateDate()); controller.updateDateColumn.setCellValueFactory(param -> param.getValue().getUpdateDate());
controller.updateDateColumn.setCellFactory(param -> new LocalDateTimeTableCell<>()); controller.updateDateColumn.setCellFactory(param -> new LocalDateTimeTableCell<>());
controller.updateDateColumn.setOnEditCommit(event -> onColumnEditCommit(event, InventoryViewModel::getUpdateDate)); controller.updateDateColumn
.setOnEditCommit(event -> onColumnEditCommit(event, InventoryViewModel::getUpdateDate));
controller.descriptionColumn.setCellValueFactory(param -> param.getValue().getDescription()); controller.descriptionColumn.setCellValueFactory(param -> param.getValue().getDescription());
controller.descriptionColumn.setCellFactory(TextFieldTableCell.forTableColumn()); controller.descriptionColumn.setCellFactory(TextFieldTableCell.forTableColumn());
controller.descriptionColumn.setOnEditCommit(event -> onColumnEditCommit(event, InventoryViewModel::getDescription)); controller.descriptionColumn
.setOnEditCommit(event -> onColumnEditCommit(event, InventoryViewModel::getDescription));
} }
private <T> void onColumnEditCommit( private <T> void onColumnEditCommit(
TableColumn.CellEditEvent<InventoryViewModel, T> event, TableColumn.CellEditEvent<InventoryViewModel, T> event,
Function<InventoryViewModel, Property<T>> supplier Function<InventoryViewModel, Property<T>> supplier) {
) {
InventoryViewModel row = event.getRowValue(); InventoryViewModel row = event.getRowValue();
supplier.apply(row).setValue(event.getNewValue()); supplier.apply(row).setValue(event.getNewValue());
saveRowData(row); saveRowData(row);
} }
@Override @Override
protected void onTableRowDoubleClickedAction(InventoryViewModel item) { protected void onTableRowDoubleClickedAction(InventoryViewModel item) {
showInOwner(InventoryWindowController.class, item); showInOwner(InventoryWindowController.class, item);

View File

@@ -56,6 +56,27 @@ public class Employee implements Entity, IdentityEntity, NamedEntity {
@Column(name = "LEAVE_DATE") @Column(name = "LEAVE_DATE")
private LocalDate leaveDate; private LocalDate leaveDate;
@Column(name = "LOCALE")
private String locale;
@Column(name = "DATE_FORMATTER")
private String dateFormatter;
@Column(name = "DATETIME_FORMATTER")
private String dateTimeFormatter;
@Column(name = "TIME_FORMATTER")
private String timeFormatter;
@Column(name = "TIME_ZONE")
private String timeZone;
@Column(name = "NUMBER_FORMATTER")
private String numberFormatter;
@Column(name = "CURRENCY_FORMATTER")
private String currencyFormatter;
/** /**
* 员工是否活跃的状态 * 员工是否活跃的状态
*/ */
@@ -63,11 +84,7 @@ public class Employee implements Entity, IdentityEntity, NamedEntity {
private boolean isActive; private boolean isActive;
@ManyToMany(fetch = FetchType.LAZY, cascade = { CascadeType.PERSIST, CascadeType.MERGE }) @ManyToMany(fetch = FetchType.LAZY, cascade = { CascadeType.PERSIST, CascadeType.MERGE })
@JoinTable( @JoinTable(name = "EMPLOYEE_ROLES", joinColumns = @JoinColumn(name = "EMPLOYEE_ID"), inverseJoinColumns = @JoinColumn(name = "ROLE_ID"))
name = "EMPLOYEE_ROLES",
joinColumns = @JoinColumn(name = "EMPLOYEE_ID"),
inverseJoinColumns = @JoinColumn(name = "ROLE_ID")
)
private java.util.List<EmployeeRole> roles = new java.util.ArrayList<>(); private java.util.List<EmployeeRole> roles = new java.util.ArrayList<>();
@Override @Override
@@ -80,17 +97,26 @@ public class Employee implements Entity, IdentityEntity, NamedEntity {
@Override @Override
public final boolean equals(Object object) { public final boolean equals(Object object) {
if (this == object) return true; if (this == object)
if (object == null) return false; return true;
Class<?> oEffectiveClass = object instanceof HibernateProxy ? ((HibernateProxy) object).getHibernateLazyInitializer().getPersistentClass() : object.getClass(); if (object == null)
Class<?> thisEffectiveClass = this instanceof HibernateProxy ? ((HibernateProxy) this).getHibernateLazyInitializer().getPersistentClass() : this.getClass(); return false;
if (thisEffectiveClass != oEffectiveClass) return false; Class<?> oEffectiveClass = object instanceof HibernateProxy
? ((HibernateProxy) object).getHibernateLazyInitializer().getPersistentClass()
: object.getClass();
Class<?> thisEffectiveClass = this instanceof HibernateProxy
? ((HibernateProxy) this).getHibernateLazyInitializer().getPersistentClass()
: this.getClass();
if (thisEffectiveClass != oEffectiveClass)
return false;
Employee employee = (Employee) object; Employee employee = (Employee) object;
return getId() != null && Objects.equals(getId(), employee.getId()); return getId() != null && Objects.equals(getId(), employee.getId());
} }
@Override @Override
public final int hashCode() { public final int hashCode() {
return this instanceof HibernateProxy ? ((HibernateProxy) this).getHibernateLazyInitializer().getPersistentClass().hashCode() : getClass().hashCode(); return this instanceof HibernateProxy
? ((HibernateProxy) this).getHibernateLazyInitializer().getPersistentClass().hashCode()
: getClass().hashCode();
} }
} }

View File

@@ -16,6 +16,7 @@ import com.ecep.contract.manager.ds.other.repository.SysConfRepository;
@Service @Service
@CacheConfig(cacheNames = "sys_conf") @CacheConfig(cacheNames = "sys_conf")
public class SysConfService { public class SysConfService {
@Lazy
@Autowired @Autowired
private SysConfRepository repository; private SysConfRepository repository;
@@ -100,6 +101,4 @@ public class SysConfService {
return "1".equalsIgnoreCase(conf.getValue()); return "1".equalsIgnoreCase(conf.getValue());
} }
} }
} }

View File

@@ -14,11 +14,13 @@ import com.ecep.contract.manager.ds.vendor.service.CompanyVendorService;
import com.ecep.contract.manager.ds.vendor.vo.CompanyVendorViewModel; import com.ecep.contract.manager.ds.vendor.vo.CompanyVendorViewModel;
import com.ecep.contract.manager.ui.tab.AbstEntityBasedTabSkin; import com.ecep.contract.manager.ui.tab.AbstEntityBasedTabSkin;
import com.ecep.contract.manager.ui.ComboBoxUtils; import com.ecep.contract.manager.ui.ComboBoxUtils;
import com.ecep.contract.manager.util.MyDateTimeUtils;
import com.ecep.contract.manager.util.UITools; import com.ecep.contract.manager.util.UITools;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
import javafx.scene.control.Tab; import javafx.scene.control.Tab;
import javafx.scene.control.TextField; import javafx.scene.control.TextField;
import javafx.util.converter.LocalDateStringConverter; import javafx.util.converter.LocalDateStringConverter;
import javafx.util.converter.LocalDateTimeStringConverter;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.List; import java.util.List;
@@ -52,7 +54,8 @@ public class CompanyVendorTabSkinBase
controller.developDateField.setConverter(converter); controller.developDateField.setConverter(converter);
controller.developDateField.valueProperty().bindBidirectional(viewModel.getDevelopDate()); controller.developDateField.valueProperty().bindBidirectional(viewModel.getDevelopDate());
List<VendorTypeLocal> vendorTypeLocals = getCompanyVendorService().findAllTypes(controller.getLocale().toLanguageTag()); List<VendorTypeLocal> vendorTypeLocals = getCompanyVendorService()
.findAllTypes(controller.getLocale().toLanguageTag());
ComboBoxUtils.initialComboBox(controller.catalogField, vendorTypeLocals, true); ComboBoxUtils.initialComboBox(controller.catalogField, vendorTypeLocals, true);
ComboBoxUtils.bindComboBox(controller.catalogField, viewModel.getType(), vendorTypeLocals); ComboBoxUtils.bindComboBox(controller.catalogField, viewModel.getType(), vendorTypeLocals);
@@ -62,7 +65,10 @@ public class CompanyVendorTabSkinBase
controller.pathField.textProperty().bind(viewModel.getPath()); controller.pathField.textProperty().bind(viewModel.getPath());
controller.descriptionField.textProperty().bindBidirectional(viewModel.getDescription()); controller.descriptionField.textProperty().bindBidirectional(viewModel.getDescription());
controller.createdField.textProperty().bind(createStringBinding(viewModel.getCreated())); DateTimeFormatter dateTimeFormatter = DateTimeFormatter
.ofPattern(MyDateTimeUtils.DEFAULT_DATETIME_FORMAT_PATTERN);
controller.createdField.textProperty().bindBidirectional(viewModel.getCreated(),
new LocalDateTimeStringConverter(dateTimeFormatter, null));
controller.versionLabel.textProperty().bind(viewModel.getVersion().asString()); controller.versionLabel.textProperty().bind(viewModel.getVersion().asString());
controller.relativeCompanyBtn.disableProperty().bind(viewModel.getCompany().isNull()); controller.relativeCompanyBtn.disableProperty().bind(viewModel.getCompany().isNull());

View File

@@ -8,8 +8,6 @@ import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.function.Function; import java.util.function.Function;
import com.ecep.contract.manager.ui.table.EditableEntityTableTabSkin;
import com.ecep.contract.manager.ui.table.TableTabSkin;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
@@ -20,6 +18,8 @@ import org.springframework.data.jpa.domain.Specification;
import com.ecep.contract.manager.ds.other.model.IdentityEntity; import com.ecep.contract.manager.ds.other.model.IdentityEntity;
import com.ecep.contract.manager.ds.other.vo.IdentityViewModel; import com.ecep.contract.manager.ds.other.vo.IdentityViewModel;
import com.ecep.contract.manager.ui.table.EditableEntityTableTabSkin;
import com.ecep.contract.manager.ui.table.TableTabSkin;
import com.ecep.contract.manager.util.TableViewUtils; import com.ecep.contract.manager.util.TableViewUtils;
import com.ecep.contract.manager.util.UITools; import com.ecep.contract.manager.util.UITools;
@@ -43,12 +43,15 @@ import javafx.scene.input.KeyEvent;
import javafx.util.converter.NumberStringConverter; import javafx.util.converter.NumberStringConverter;
/** /**
* 实体管理器皮肤
* 提供了实体管理器的基本功能,如查询、新增、删除、修改、分页等
*
* @param <T> Entity 的类型 * @param <T> Entity 的类型
* @param <TV> Entity 对应的ViewModel * @param <TV> Entity 对应的ViewModel
* @param <Skin> Skin 的类型 * @param <SKIN> Skin 的类型
* @param <C> * @param <C>
*/ */
public abstract class AbstEntityManagerSkin<T extends IdentityEntity, TV extends IdentityViewModel<T>, Skin extends ManagerSkin, C extends AbstManagerWindowController<T, TV, Skin>> public abstract class AbstEntityManagerSkin<T extends IdentityEntity, TV extends IdentityViewModel<T>, SKIN extends ManagerSkin, C extends AbstManagerWindowController<T, TV, SKIN>>
implements ManagerSkin, TableTabSkin<T, TV>, EditableEntityTableTabSkin<T, TV> { implements ManagerSkin, TableTabSkin<T, TV>, EditableEntityTableTabSkin<T, TV> {
private static final Logger logger = LoggerFactory.getLogger(AbstEntityManagerSkin.class); private static final Logger logger = LoggerFactory.getLogger(AbstEntityManagerSkin.class);
/** /**
@@ -61,6 +64,10 @@ public abstract class AbstEntityManagerSkin<T extends IdentityEntity, TV extends
protected PageRequest currentPageable = PageRequest.ofSize(25); protected PageRequest currentPageable = PageRequest.ofSize(25);
protected final SimpleIntegerProperty currentPageNumber = new SimpleIntegerProperty(); protected final SimpleIntegerProperty currentPageNumber = new SimpleIntegerProperty();
// 是否允许调整表格高度
private boolean allowResize = true;
// 记录延时任务信息
private ScheduledFuture<?> loadTableDataSetFuture;
public AbstEntityManagerSkin(C controller) { public AbstEntityManagerSkin(C controller) {
this.controller = controller; this.controller = controller;
@@ -195,8 +202,6 @@ public abstract class AbstEntityManagerSkin<T extends IdentityEntity, TV extends
loadTableDataSet(true); loadTableDataSet(true);
} }
private boolean allowResize = true;
/** /**
* 根据表格高度重新计算分页的页大小 * 根据表格高度重新计算分页的页大小
*/ */
@@ -269,9 +274,17 @@ public abstract class AbstEntityManagerSkin<T extends IdentityEntity, TV extends
} }
} }
protected <K> void acceptCellEditEvent(TableColumn.CellEditEvent<TV, K> event, Function<TV, Property<K>> function) { /**
* 处理单元格编辑事件
*
* @param <K>
* @param event
* @param propGetter
*/
protected <K> void acceptCellEditEvent(TableColumn.CellEditEvent<TV, K> event,
Function<TV, Property<K>> propGetter) {
TV row = event.getRowValue(); TV row = event.getRowValue();
Property<K> property = function.apply(row); Property<K> property = propGetter.apply(row);
property.setValue(event.getNewValue()); property.setValue(event.getNewValue());
try { try {
saveRowData(row); saveRowData(row);
@@ -327,21 +340,47 @@ public abstract class AbstEntityManagerSkin<T extends IdentityEntity, TV extends
row.saveInFxApplicationThread(service); row.saveInFxApplicationThread(service);
} }
/**
* 加载行数据
*
* @param row
* @return
*/
public T loadRowData(TV row) { public T loadRowData(TV row) {
return getViewModelService().findById(row.getId().get()); if (row.getId() == null) {
return null;
}
T entity = getViewModelService().findById(row.getId().get());
return entity;
} }
/**
* 删除行数据
*
* @param entity
*/
public void deleteRowData(T entity) { public void deleteRowData(T entity) {
if (entity == null) {
return;
}
ViewModelService<T, TV> service = getViewModelService();
getViewModelService().delete(entity); getViewModelService().delete(entity);
} }
/**
* 保存行数据
*
* @param entity
* @return
*/
public T saveRowData(T entity) { public T saveRowData(T entity) {
if (entity == null) {
return null;
}
ViewModelService<T, TV> service = getViewModelService();
return getViewModelService().save(entity); return getViewModelService().save(entity);
} }
// 记录延时任务信息
private ScheduledFuture<?> loadTableDataSetFuture;
@Override @Override
public void loadTableDataSet() { public void loadTableDataSet() {
loadTableDataSet(false); loadTableDataSet(false);
@@ -392,6 +431,11 @@ public abstract class AbstEntityManagerSkin<T extends IdentityEntity, TV extends
return future; return future;
} }
/**
* 更新表格数据
*
* @param models
*/
protected void updateTableDataSet(List<TV> models) { protected void updateTableDataSet(List<TV> models) {
long timeMillis = System.currentTimeMillis(); long timeMillis = System.currentTimeMillis();
// 清除所有选择状态,避免选择状态混乱 // 清除所有选择状态,避免选择状态混乱
@@ -417,6 +461,11 @@ public abstract class AbstEntityManagerSkin<T extends IdentityEntity, TV extends
} }
} }
/**
* 加载表格数据
*
* @return
*/
protected List<TV> loadTableData() { protected List<TV> loadTableData() {
Specification<T> spec = getSpecification(); Specification<T> spec = getSpecification();
ViewModelService<T, TV> service = getViewModelService(); ViewModelService<T, TV> service = getViewModelService();
@@ -433,16 +482,24 @@ public abstract class AbstEntityManagerSkin<T extends IdentityEntity, TV extends
return page.map(service::from).toList(); return page.map(service::from).toList();
} }
/**
* 获取ViewModelService
*
* @return
*/
protected ViewModelService<T, TV> getViewModelService() { protected ViewModelService<T, TV> getViewModelService() {
ViewModelService<T, TV> service = controller.getViewModelService(); ViewModelService<T, TV> service = controller.getViewModelService();
if (service == null) { if (service == null) {
if (logger.isWarnEnabled()) { throw new IllegalArgumentException("ViewModelService is null");
logger.warn("ViewModelService is null");
}
} }
return service; return service;
} }
/**
* 获取查询条件
*
* @return
*/
public Specification<T> getSpecification() { public Specification<T> getSpecification() {
TextField field = controller.searchKeyField; TextField field = controller.searchKeyField;
if (field != null) { if (field != null) {
@@ -451,8 +508,14 @@ public abstract class AbstEntityManagerSkin<T extends IdentityEntity, TV extends
return null; return null;
} }
/**
* 获取查询条件
*
* @param searchText
* @return
*/
protected Specification<T> getSpecification(String searchText) { protected Specification<T> getSpecification(String searchText) {
return controller.getViewModelService().getSpecification(searchText); return getViewModelService().getSpecification(searchText);
} }
/** /**
@@ -463,6 +526,11 @@ public abstract class AbstEntityManagerSkin<T extends IdentityEntity, TV extends
protected void onTableRowDoubleClickedAction(TV item) { protected void onTableRowDoubleClickedAction(TV item) {
} }
/**
* 更新页脚
*
* @param page
*/
protected void updateFooter(Page<T> page) { protected void updateFooter(Page<T> page) {
Platform.runLater(() -> { Platform.runLater(() -> {
controller.previousPageBtn.setDisable(!page.hasPrevious()); controller.previousPageBtn.setDisable(!page.hasPrevious());
@@ -473,19 +541,44 @@ public abstract class AbstEntityManagerSkin<T extends IdentityEntity, TV extends
}); });
} }
/**
* 获取表格排序
*
* @return
*/
public List<Sort.Order> getTableOrders() { public List<Sort.Order> getTableOrders() {
return TableViewUtils.getOrders(getTableView()); return TableViewUtils.getOrders(getTableView());
} }
/**
* 获取表格排序
*
* @return
*/
public Sort getSortByTable() { public Sort getSortByTable() {
if (getTableView() == null) {
return Sort.unsorted();
}
return Sort.by(getTableOrders()); return Sort.by(getTableOrders());
} }
/**
* 获取分页参数
*
* @return
*/
public Pageable getPageable() { public Pageable getPageable() {
Sort sort = getSortByTable(); Sort sort = getSortByTable();
return currentPageable.withSort(sort); return currentPageable.withSort(sort);
} }
/**
* 显示在当前窗口为父窗口的新窗口
*
* @param <Controller> 控制器类型
* @param clz 控制器类
* @param model 数据
*/
protected <Controller extends AbstEntityController<T, TV>> void showInOwner(Class<Controller> clz, TV model) { protected <Controller extends AbstEntityController<T, TV>> void showInOwner(Class<Controller> clz, TV model) {
BaseController.show(clz, model, getTableView().getScene().getWindow()); BaseController.show(clz, model, getTableView().getScene().getWindow());
} }

View File

@@ -1,11 +1,13 @@
package com.ecep.contract.manager.ui; package com.ecep.contract.manager.ui;
import java.util.Locale;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import com.ecep.contract.manager.ui.tab.TabSkin; import com.ecep.contract.manager.ui.tab.TabSkin;
import com.ecep.contract.manager.util.UITools; import com.ecep.contract.manager.util.UITools;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Locale;
public abstract class AbstGenericTabSkin<C extends BaseController> implements TabSkin { public abstract class AbstGenericTabSkin<C extends BaseController> implements TabSkin {
private static final Logger logger = LoggerFactory.getLogger(AbstGenericTabSkin.class); private static final Logger logger = LoggerFactory.getLogger(AbstGenericTabSkin.class);
@@ -18,6 +20,10 @@ public abstract class AbstGenericTabSkin<C extends BaseController> implements Ta
this.controller = controller; this.controller = controller;
} }
public <T> T getCachedBean(Class<T> requiredType) throws BeansException {
return controller.getCachedBean(requiredType);
}
protected void setStatus(String status) { protected void setStatus(String status) {
controller.setStatus(status); controller.setStatus(status);
} }
@@ -38,4 +44,5 @@ public abstract class AbstGenericTabSkin<C extends BaseController> implements Ta
} }
UITools.showExceptionAndWait(message, ex); UITools.showExceptionAndWait(message, ex);
} }
} }

View File

@@ -15,6 +15,7 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException; import org.springframework.beans.BeansException;
import com.ecep.contract.manager.CurrentEmployee;
import com.ecep.contract.manager.Desktop; import com.ecep.contract.manager.Desktop;
import com.ecep.contract.manager.SpringApp; import com.ecep.contract.manager.SpringApp;
import com.ecep.contract.manager.ds.other.model.Employee; import com.ecep.contract.manager.ds.other.model.Employee;
@@ -37,7 +38,6 @@ import javafx.stage.Stage;
import javafx.stage.Window; import javafx.stage.Window;
import javafx.stage.WindowEvent; import javafx.stage.WindowEvent;
import lombok.Getter; import lombok.Getter;
import lombok.Setter;
public class BaseController { public class BaseController {
private static final Logger logger = LoggerFactory.getLogger(BaseController.class); private static final Logger logger = LoggerFactory.getLogger(BaseController.class);
@@ -163,7 +163,8 @@ public class BaseController {
} }
public CompletableFuture<Void> runAsync(Runnable runnable) { public CompletableFuture<Void> runAsync(Runnable runnable) {
return CompletableFuture.runAsync(runnable, Desktop.instance.getExecutorService()).exceptionally(this::handleException); return CompletableFuture.runAsync(runnable, Desktop.instance.getExecutorService())
.exceptionally(this::handleException);
} }
/** /**
@@ -182,33 +183,30 @@ public class BaseController {
private String stageKey; private String stageKey;
public Label leftStatusLabel; public Label leftStatusLabel;
public Label rightStatusLabel; public Label rightStatusLabel;
@Getter
@Setter
private Locale locale = Locale.getDefault();
@Setter
private SysConfService confService;
@Setter
private EmployeeService employeeService;
private Employee currentUser; private Employee currentUser;
private HashMap<Class<?>, Object> cachedBeans = new HashMap<>();
protected <T> T getBean(Class<T> requiredType) throws BeansException { protected <T> T getBean(Class<T> requiredType) throws BeansException {
return SpringApp.getBean(requiredType); return SpringApp.getBean(requiredType);
} }
public SysConfService getConfService() { @SuppressWarnings("unchecked")
if (confService == null) { public <T> T getCachedBean(Class<T> requiredType) throws BeansException {
confService = getBean(SysConfService.class); Object object = cachedBeans.get(requiredType);
if (object == null) {
object = getBean(requiredType);
cachedBeans.put(requiredType, object);
} }
return confService; return (T) object;
}
public SysConfService getConfService() {
return getCachedBean(SysConfService.class);
} }
public EmployeeService getEmployeeService() { public EmployeeService getEmployeeService() {
if (employeeService == null) { return getCachedBean(EmployeeService.class);
employeeService = getBean(EmployeeService.class);
}
return employeeService;
} }
public Employee getCurrentUser() { public Employee getCurrentUser() {
@@ -218,6 +216,18 @@ public class BaseController {
return currentUser; return currentUser;
} }
public CurrentEmployee getCurrentEmployee() {
return Desktop.instance.getActiveEmployee();
}
public Locale getLocale() {
CurrentEmployee currentEmployee = getCurrentEmployee();
if (currentEmployee == null) {
return Locale.getDefault();
}
return currentEmployee.localeProperty().get();
}
public String getMessage(String code, Object... args) { public String getMessage(String code, Object... args) {
return SpringApp.getMessage(code, args, getLocale()); return SpringApp.getMessage(code, args, getLocale());
} }

View File

@@ -1,5 +1,13 @@
package com.ecep.contract.manager.ui.tab; package com.ecep.contract.manager.ui.tab;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.concurrent.CompletableFuture;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import com.ecep.contract.manager.ds.other.model.IdentityEntity; import com.ecep.contract.manager.ds.other.model.IdentityEntity;
import com.ecep.contract.manager.ds.other.vo.IdentityViewModel; import com.ecep.contract.manager.ds.other.vo.IdentityViewModel;
import com.ecep.contract.manager.ui.AbstEntityController; import com.ecep.contract.manager.ui.AbstEntityController;
@@ -7,26 +15,15 @@ import com.ecep.contract.manager.ui.AbstGenericTabSkin;
import com.ecep.contract.manager.ui.BaseController; import com.ecep.contract.manager.ui.BaseController;
import com.ecep.contract.manager.ui.FxmlPath; import com.ecep.contract.manager.ui.FxmlPath;
import com.ecep.contract.manager.util.FxmlUtils; import com.ecep.contract.manager.util.FxmlUtils;
import com.ecep.contract.manager.util.MyDateTimeUtils;
import com.ecep.contract.manager.util.UITools; import com.ecep.contract.manager.util.UITools;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.StringBinding;
import javafx.beans.property.BooleanProperty; import javafx.beans.property.BooleanProperty;
import javafx.beans.property.Property;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
import javafx.scene.Node; import javafx.scene.Node;
import javafx.scene.control.Tab; import javafx.scene.control.Tab;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.concurrent.CompletableFuture;
public abstract class AbstEntityBasedTabSkin<C extends AbstEntityController<T, V>, T extends IdentityEntity, V extends IdentityViewModel<T>> public abstract class AbstEntityBasedTabSkin<C extends AbstEntityController<T, V>, T extends IdentityEntity, V extends IdentityViewModel<T>>
extends AbstGenericTabSkin<C> { extends AbstGenericTabSkin<C> {
@@ -184,20 +181,4 @@ public abstract class AbstEntityBasedTabSkin<C extends AbstEntityController<T, V
} }
} }
} }
protected String localDateTimeFormatter(Property<LocalDateTime> property) {
LocalDateTime dateTime = property.getValue();
if (dateTime == null) {
return "";
}
return MyDateTimeUtils.format(dateTime);
}
protected StringBinding createStringBinding(Property<LocalDateTime> property) {
return Bindings.createStringBinding(
() -> localDateTimeFormatter(property),
property);
}
} }

View File

@@ -29,7 +29,7 @@
<Label text="同步时未创建的公司时开发日期在此之后的自动创建" /> <Label text="同步时未创建的公司时开发日期在此之后的自动创建" />
<DatePicker fx:id="auto_create_company_after" GridPane.columnIndex="2" /> <DatePicker fx:id="auto_create_company_after" GridPane.columnIndex="2" />
<Label text="cloud.u8.contract.latestDate" GridPane.rowIndex="1" /> <Label text="cloud.u8.contract.latestDate" GridPane.rowIndex="1" />
<DatePicker fx:id="contract_latest_date" GridPane.columnIndex="2" GridPane.rowIndex="1" /> <TextField fx:id="contract_latest_date" GridPane.columnIndex="2" GridPane.rowIndex="1" />
<Label text="cloud.u8.contract.latestId" GridPane.rowIndex="2" /> <Label text="cloud.u8.contract.latestId" GridPane.rowIndex="2" />
<TextField fx:id="contract_latest_id" GridPane.columnIndex="2" GridPane.rowIndex="2" /> <TextField fx:id="contract_latest_id" GridPane.columnIndex="2" GridPane.rowIndex="2" />
<Label text="cloud.u8.sync.elapse" GridPane.rowIndex="3" /> <Label text="cloud.u8.sync.elapse" GridPane.rowIndex="3" />