diff --git a/README.md b/README.md index da00d2b..28c66e5 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ 服务端模块,包含服务端的代码,依赖common模块 - client: 客户端模块,包含客户端的代码,依赖common模块 +UI 的fxml文件在 /client/src/main/resources/ui/ diff --git a/client/pom.xml b/client/pom.xml index 9e14534..0f67b65 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -88,7 +88,7 @@ javafx-maven-plugin 0.0.8 - com.ecep.contract.AppV2 + com.ecep.contract.ClientV2 app app-jlink app-jlink-image diff --git a/client/src/main/java/com/ecep/contract/ClientV2.java b/client/src/main/java/com/ecep/contract/ClientV2.java index df06e2d..33b397e 100644 --- a/client/src/main/java/com/ecep/contract/ClientV2.java +++ b/client/src/main/java/com/ecep/contract/ClientV2.java @@ -5,7 +5,7 @@ import javafx.application.Application; /** * Created by Administrator on 2017/4/16. */ -public class AppV2 { +public class ClientV2 { public static void main(String[] args) { Application.launch(Desktop.class, args); } diff --git a/client/src/main/java/com/ecep/contract/WebSocketService.java b/client/src/main/java/com/ecep/contract/WebSocketService.java index 77a71fe..f12cb45 100644 --- a/client/src/main/java/com/ecep/contract/WebSocketService.java +++ b/client/src/main/java/com/ecep/contract/WebSocketService.java @@ -1,5 +1,22 @@ package com.ecep.contract; +import com.ecep.contract.msg.SimpleMessage; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import javafx.application.Platform; +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.SimpleBooleanProperty; +import javafx.beans.property.SimpleStringProperty; +import javafx.beans.property.StringProperty; +import lombok.Getter; +import lombok.Setter; +import okhttp3.*; +import okio.ByteString; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -8,29 +25,6 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import com.ecep.contract.msg.SimpleMessage; -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消息的功能 @@ -45,6 +39,9 @@ public class WebSocketService { 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; // 心跳任务 @@ -280,4 +277,5 @@ public class WebSocketService { public BooleanProperty getOnlineProperty() { return online; } + } diff --git a/client/src/main/java/com/ecep/contract/controller/company/AbstCompanyTableTabSkin.java b/client/src/main/java/com/ecep/contract/controller/company/AbstCompanyTableTabSkin.java index 3931b8d..6898b18 100644 --- a/client/src/main/java/com/ecep/contract/controller/company/AbstCompanyTableTabSkin.java +++ b/client/src/main/java/com/ecep/contract/controller/company/AbstCompanyTableTabSkin.java @@ -1,5 +1,6 @@ package com.ecep.contract.controller.company; +import java.util.HashMap; import java.util.Map; import com.ecep.contract.controller.tab.TabSkin; @@ -16,7 +17,6 @@ public abstract class AbstCompanyTableTabSkin implements TabSkin, TableOfTabSkin { - public AbstCompanyTableTabSkin(CompanyWindowController controller) { super(controller); viewModel = controller.getViewModel(); @@ -42,6 +42,9 @@ public abstract class AbstCompanyTableTabSkin getSpecification(Company parent) { Map params = getSpecification(); + if (params == null) { + params = new HashMap<>(); + } params.put("company", parent.getId()); return params; } diff --git a/client/src/main/java/com/ecep/contract/controller/customer/CustomerTabSkinEntity.java b/client/src/main/java/com/ecep/contract/controller/customer/CustomerTabSkinEntity.java index 99bfd9e..6d1cc51 100644 --- a/client/src/main/java/com/ecep/contract/controller/customer/CustomerTabSkinEntity.java +++ b/client/src/main/java/com/ecep/contract/controller/customer/CustomerTabSkinEntity.java @@ -1,9 +1,5 @@ package com.ecep.contract.controller.customer; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.util.Map; - import com.ecep.contract.SpringApp; import com.ecep.contract.controller.table.cell.LocalDateTimeTableCell; import com.ecep.contract.converter.EmployeeStringConverter; @@ -12,14 +8,18 @@ import com.ecep.contract.model.CompanyCustomer; import com.ecep.contract.model.CompanyCustomerEntity; import com.ecep.contract.model.CustomerCatalog; import com.ecep.contract.service.CompanyCustomerEntityService; +import com.ecep.contract.service.CustomerCatalogService; import com.ecep.contract.util.FxmlPath; import com.ecep.contract.vm.CustomerEntityViewModel; - import javafx.scene.control.MenuItem; import javafx.scene.control.Tab; import javafx.scene.control.TableColumn; import lombok.Setter; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.Map; + @FxmlPath("/ui/company/customer/customer-tab-entity.fxml") public class CustomerTabSkinEntity extends AbstCompanyCustomerTableTabSkin { @@ -80,7 +80,7 @@ public class CustomerTabSkinEntity private void initializeEntityTabCatalogColumn(TableColumn column) { EntityStringConverter converter = new EntityStringConverter<>(); - converter.setInitialized(v -> getCompanyCustomerService().findCatalogById(v.getId())); + converter.setInitialized(v -> getCachedBean(CustomerCatalogService.class).findById(v.getId())); column.setCellValueFactory(param -> param.getValue().getCatalog().map(converter::toString)); } diff --git a/client/src/main/java/com/ecep/contract/controller/customer/CustomerTabSkinSatisfactionSurvey.java b/client/src/main/java/com/ecep/contract/controller/customer/CustomerTabSkinSatisfactionSurvey.java index 6d10d93..150aa42 100644 --- a/client/src/main/java/com/ecep/contract/controller/customer/CustomerTabSkinSatisfactionSurvey.java +++ b/client/src/main/java/com/ecep/contract/controller/customer/CustomerTabSkinSatisfactionSurvey.java @@ -4,6 +4,7 @@ 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; @@ -75,7 +76,7 @@ public class CustomerTabSkinSatisfactionSurvey private void initializeEntityTabCatalogColumn(TableColumn column) { EntityStringConverter converter = new EntityStringConverter<>(); - converter.setInitialized(v -> getCompanyCustomerService().findCatalogById(v.getId())); + converter.setInitialized(v -> getCachedBean(CustomerCatalogService.class).findById(v.getId())); column.setCellValueFactory(param -> param.getValue().getCatalog().map(converter::toString)); } diff --git a/client/src/main/java/com/ecep/contract/controller/tab/CompanyTabSkinFile.java b/client/src/main/java/com/ecep/contract/controller/tab/CompanyTabSkinFile.java index 7b83414..b78a8f3 100644 --- a/client/src/main/java/com/ecep/contract/controller/tab/CompanyTabSkinFile.java +++ b/client/src/main/java/com/ecep/contract/controller/tab/CompanyTabSkinFile.java @@ -6,6 +6,8 @@ import java.time.LocalDate; import java.util.List; import java.util.function.Consumer; +import com.ecep.contract.service.CompanyFileTypeService; +import com.ecep.contract.service.ContractFileTypeService; import org.springframework.util.FileSystemUtils; import org.springframework.util.StringUtils; @@ -103,7 +105,7 @@ public class CompanyTabSkinFile fileTable_menu_copy_as_matched_by_contract.setOnAction(this::onTableCopyAsMatchedByContractAction); fileTable_menu_copy_as_matched_by_contract.setOnMenuValidation(this::onTableCopyAsMatchedMenuValidation); - fileTypeLocalMap.putAll(getCompanyFileService().findAllFileTypes(getLocale().toLanguageTag())); + fileTypeLocalMap.putAll(getCachedBean(CompanyFileTypeService.class).findAll(getLocale())); } private void onTableResetAction(ActionEvent event) { diff --git a/client/src/main/java/com/ecep/contract/controller/tab/CompanyTabSkinOldName.java b/client/src/main/java/com/ecep/contract/controller/tab/CompanyTabSkinOldName.java index 88fdb3b..fc2ba88 100644 --- a/client/src/main/java/com/ecep/contract/controller/tab/CompanyTabSkinOldName.java +++ b/client/src/main/java/com/ecep/contract/controller/tab/CompanyTabSkinOldName.java @@ -2,6 +2,7 @@ package com.ecep.contract.controller.tab; import java.time.LocalDate; import java.util.ArrayList; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -10,13 +11,13 @@ import java.util.Optional; import org.springframework.util.StringUtils; -import com.ecep.contract.util.FxmlPath; import com.ecep.contract.controller.company.AbstCompanyTableTabSkin; import com.ecep.contract.controller.company.CompanyWindowController; import com.ecep.contract.controller.company_old_name.CompanyOldNameWindowController; import com.ecep.contract.model.Company; import com.ecep.contract.model.CompanyOldName; import com.ecep.contract.service.CompanyOldNameService; +import com.ecep.contract.util.FxmlPath; import com.ecep.contract.vm.CompanyOldNameViewModel; import javafx.application.Platform; @@ -73,6 +74,9 @@ public class CompanyTabSkinOldName @Override public Map getSpecification(Company parent) { Map params = getSpecification(); + if (params == null) { + params = new HashMap<>(); + } params.put("company", parent.getId()); return params; } diff --git a/client/src/main/java/com/ecep/contract/controller/table/AbstEntityTableTabSkin.java b/client/src/main/java/com/ecep/contract/controller/table/AbstEntityTableTabSkin.java index 5553424..136771b 100644 --- a/client/src/main/java/com/ecep/contract/controller/table/AbstEntityTableTabSkin.java +++ b/client/src/main/java/com/ecep/contract/controller/table/AbstEntityTableTabSkin.java @@ -243,7 +243,8 @@ public abstract class AbstEntityTableTabSkin { dataSet.clear(); - CompletableFuture.runAsync(() -> { + runAsync(() -> { + List models = loadTableData(parent); Platform.runLater(() -> { try { @@ -252,7 +253,7 @@ public abstract class AbstEntityTableTabSkin * @param */ @@ -41,7 +42,7 @@ public class AsyncUpdateTableCell extends javafx.sc /** * 通过 #setService 设置服务类,或者子类实现, 提供服务类 - * + * * @return */ protected IEntityService getServiceBean() { @@ -87,7 +88,7 @@ public class AsyncUpdateTableCell extends javafx.sc /** * 检查实体是否已初始化 - * + * * @param proxy * @return */ @@ -97,7 +98,7 @@ public class AsyncUpdateTableCell extends javafx.sc /** * 初始化实体 - * + * * @return */ protected T initialize() { @@ -106,7 +107,7 @@ public class AsyncUpdateTableCell extends javafx.sc /** * 提交异步任务 - * + * * @param var1 异步任务 * @return */ @@ -119,7 +120,16 @@ public class AsyncUpdateTableCell extends javafx.sc return; } + if (getService() instanceof QueryService queryService) { + queryService.asyncFindById(getItem().getId()).thenAccept(this::_updateEntity); + return; + } T entity = initialize(); + _updateEntity(entity); + + } + + private void _updateEntity(T entity) { String formated; try { formated = format(entity); diff --git a/client/src/main/java/com/ecep/contract/service/CompanyCustomerService.java b/client/src/main/java/com/ecep/contract/service/CompanyCustomerService.java index 4ce5ad8..5d255b5 100644 --- a/client/src/main/java/com/ecep/contract/service/CompanyCustomerService.java +++ b/client/src/main/java/com/ecep/contract/service/CompanyCustomerService.java @@ -1,26 +1,28 @@ package com.ecep.contract.service; -import java.io.File; - -import org.springframework.stereotype.Service; - import com.ecep.contract.MessageHolder; import com.ecep.contract.model.Company; import com.ecep.contract.model.CompanyCustomer; -import com.ecep.contract.model.CustomerCatalog; import com.ecep.contract.vm.CompanyCustomerViewModel; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; @Service public class CompanyCustomerService extends QueryService { public CompanyCustomer findByCompany(Company company) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'findByCompany'"); - } - - public CustomerCatalog findCatalogById(Integer id) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'findCatalogById'"); + Map params = new HashMap<>(); + params.put("company", company.getId()); + Page page = findAll(params, Pageable.ofSize(1)); + if (page.isEmpty()) { + return null; + } + return page.getContent().getFirst(); } public boolean reBuildingFiles(CompanyCustomer companyCustomer, MessageHolder holder) { diff --git a/client/src/main/java/com/ecep/contract/service/CompanyFileService.java b/client/src/main/java/com/ecep/contract/service/CompanyFileService.java index dff789c..3167995 100644 --- a/client/src/main/java/com/ecep/contract/service/CompanyFileService.java +++ b/client/src/main/java/com/ecep/contract/service/CompanyFileService.java @@ -1,27 +1,237 @@ package com.ecep.contract.service; -import java.time.LocalDate; -import java.util.List; -import java.util.Map; -import java.util.function.Consumer; - -import org.springframework.stereotype.Service; - import com.ecep.contract.CompanyFileType; import com.ecep.contract.MessageHolder; +import com.ecep.contract.MyDateTimeUtils; +import com.ecep.contract.SpringApp; +import com.ecep.contract.constant.CloudServiceConstant; +import com.ecep.contract.constant.CompanyConstant; import com.ecep.contract.model.Company; import com.ecep.contract.model.CompanyFile; -import com.ecep.contract.model.CompanyFileTypeLocal; +import com.ecep.contract.model.CompanyOldName; +import com.ecep.contract.util.FileUtils; import com.ecep.contract.vm.CompanyFileViewModel; - import javafx.collections.ObservableList; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; + +import java.io.File; +import java.time.LocalDate; +import java.util.*; +import java.util.function.Consumer; +import java.util.regex.Matcher; +import java.util.regex.Pattern; @Service public class CompanyFileService extends QueryService { + public List findByCompany(Company company) { + Map params = new HashMap<>(); + params.put("company", company.getId()); + return findAll(params, Pageable.unpaged()).getContent(); + } + + public List findByCompanyAndPath(Company company, String absolutePath) { + Map params = new HashMap<>(); + params.put("company", company.getId()); + params.put("filePath", absolutePath); + return findAll(params, Pageable.unpaged()).getContent(); + } + public boolean reBuildingFiles(Company company, MessageHolder holder) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'reBuildingFiles'"); + List dbFiles = findByCompany(company); + List retrieveFiles = new ArrayList<>(); + boolean modfied = false; + + Map map = new HashMap<>(); + // 排除掉数据库中重复的 + for (CompanyFile dbFile : dbFiles) { + String filePath = dbFile.getFilePath(); + // 没有文件信息,无效记录,删除 + if (!StringUtils.hasText(filePath)) { + delete(dbFile); + modfied = true; + continue; + } + + // 目录不存在,删除 + File dir = new File(filePath); + if (!dir.exists()) { + delete(dbFile); + modfied = true; + continue; + } + + CompanyFile old = map.put(filePath, dbFile); + // 目录有重复删除 + if (old != null) { + delete(old); + modfied = true; + } + } + + Map directoryMap = new HashMap<>(); + + // 公司目录 + if (StringUtils.hasText(company.getPath())) { + File dir = new File(company.getPath()); + directoryMap.put(company.getName(), dir); + } + + // 获取所有曾用名 + List oldNames = SpringApp.getBean(CompanyOldNameService.class).findAllByCompany(company); + for (CompanyOldName companyOldName : oldNames) { + String path = companyOldName.getPath(); + if (StringUtils.hasText(path)) { + File dir = new File(path); + directoryMap.put(companyOldName.getName(), dir); + } + } + + for (Map.Entry entry : directoryMap.entrySet()) { + String companyName = entry.getKey(); + File dir = entry.getValue(); + if (!StringUtils.hasText(companyName)) { + continue; + } + if (dir == null || !dir.exists()) { + continue; + } + + File[] files = dir.listFiles(); + if (files == null) { + // 文件系统出错或者没有相关文件 + continue; + } + for (File file : files) { + // 只处理文件 + if (!file.isFile() || FileUtils.isHiddenFile(file)) { + continue; + } + String filePath = file.getAbsolutePath(); + if (!map.containsKey(filePath)) { + // 未记录 + CompanyFile filled = fillFileType(file, holder); + retrieveFiles.add(filled); + } + } + } + + holder.info("导入 " + retrieveFiles.size() + " 个文件"); + if (retrieveFiles.isEmpty()) { + return modfied; + } + + // update db + retrieveFiles.forEach(v -> { + v.setCompany(company); + save(v); + }); + return true; + } + + + /** + * 从文件名生成公司文件对象,文件已经存在公司对应的存储目录下 + * + * @param file 文件 + * @param holder 状态输出 + * @return 公司文件对象 + */ + private CompanyFile fillFileType(File file, MessageHolder holder) { + String fileName = file.getName(); + CompanyFile companyFile = new CompanyFile(); + companyFile.setType(CompanyFileType.General); + companyFile.setFilePath(file.getAbsolutePath()); + fillApplyDateAndExpiringDateAbsent(file, companyFile); + + // 天眼查 基础版企业信用报告 + if (fileName.contains(CloudServiceConstant.TYC_ENTERPRISE_BASIC_REPORT) + || fileName.contains(CloudServiceConstant.TYC_ENTERPRISE_MAJOR_REPORT) + || fileName.contains(CloudServiceConstant.TYC_ENTERPRISE_ANALYSIS_REPORT)) { + companyFile.setType(CompanyFileType.CreditReport); + fillExpiringDateAbsent(companyFile); + return companyFile; + } + + // 天眼查 企业信用信息公示报告 + if (fileName.contains(CloudServiceConstant.TYC_ENTERPRISE_CREDIT_REPORT)) { + companyFile.setType(CompanyFileType.CreditInfoPublicityReport); + return companyFile; + } + + // 集团相关方平台 元素征信 企业征信报告 + if (fileName.contains(CloudServiceConstant.RK_VENDOR_NAME) + && fileName.contains(CloudServiceConstant.RK_ENTERPRISE_CREDIT_REPORT)) { + companyFile.setType(CompanyFileType.CreditReport); + fillExpiringDateAbsent(companyFile); + return companyFile; + } + + // 营业执照 + if (fileName.contains(CompanyConstant.BUSINESS_LICENSE)) { + companyFile.setType(CompanyFileType.BusinessLicense); + return companyFile; + } + + // 其他企业信用报告 + if (fileName.contains(CompanyConstant.ENTERPRISE_REPORT)) { + companyFile.setType(CompanyFileType.CreditReport); + fillExpiringDateAbsent(companyFile); + return companyFile; + } + return companyFile; + } + + /** + * 补齐有效期 + */ + private void fillExpiringDateAbsent(CompanyFile file) { + LocalDate expiringDate = file.getExpiringDate(); + if (expiringDate == null) { + LocalDate applyDate = file.getApplyDate(); + if (applyDate != null) { + expiringDate = applyDate.plusYears(1); + file.setExpiringDate(expiringDate); + } + } + } + + private static void fillApplyDateAndExpiringDateAbsent(File file, CompanyFile companyFile) { + LocalDate applyDate = companyFile.getApplyDate(); + if (applyDate != null) { + return; + } + + String fileName = file.getName(); + Pattern pattern = Pattern.compile(MyDateTimeUtils.REGEX_DATE); + Matcher matcher = pattern.matcher(fileName); + while (matcher.find()) { + // 找到第一个日期,记作起始日期 + String date = matcher.group(); + try { + LocalDate n = LocalDate.parse(date); + companyFile.setApplyDate(n); + + // 如果 截至日期未设置,则第二个日期记作截至日期(如有) + LocalDate expiringDate = companyFile.getExpiringDate(); + if (expiringDate == null) { + while (matcher.find()) { + date = matcher.group(); + try { + n = LocalDate.parse(date); + companyFile.setExpiringDate(n); + break; + } catch (Exception ignored) { + } + } + } + break; + } catch (Exception ignored) { + } + } + } public void verify(Company company, LocalDate setupDate, MessageHolder holder) { @@ -39,19 +249,205 @@ public class CompanyFileService extends QueryService findAllFileTypes(String languageTag) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'findAllFileTypes'"); - } - - public List findByCompany(Company company) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'findByCompany'"); - } - public void copyAsMatchedByContract(Company parent, ObservableList list) { // TODO Auto-generated method stub throw new UnsupportedOperationException("Unimplemented method 'copyAsMatchedByContract'"); } + + /** + * 移动文件到企业目录下 + * + * @param company 企业对象 + * @param files 要被移动的文件集合,需要从中选择需要的 + * @param holder 状态输出 + */ + public boolean retrieveFromDownloadFiles(Company company, File[] files, MessageHolder holder) { + Map map = new HashMap<>(); + File home = new File(company.getPath()); + map.put(company.getName(), home); + List retrieveFiles = new ArrayList<>(); + + List oldNames = SpringApp.getBean(CompanyOldNameService.class).findAllByCompany(company); + + // 获取所有曾用名 + for (CompanyOldName companyOldName : oldNames) { + String name = companyOldName.getName(); + if (!StringUtils.hasText(name)) { + continue; + } + File dir = null; + String path = companyOldName.getPath(); + if (StringUtils.hasText(path)) { + dir = new File(path); + } + map.put(name, dir); + } + + // 对所有文件进行遍历 + for (int i = 0; i < files.length; i++) { + File file = files[i]; + // 只处理文件 + if (!file.isFile()) { + continue; + } + + MessageHolder sub = holder.sub("[" + (i + 1) + "/" + files.length + "]"); + + String fileName = file.getName(); + sub.info(fileName); + for (Map.Entry entry : map.entrySet()) { + String companyName = entry.getKey(); + // 必须要包含公司名称否则无法区分 + if (!fileName.contains(companyName)) { + continue; + } + + // 文件存储的目的地目录 + File dir = entry.getValue(); + if (dir == null) { + dir = home; + } + + CompanyFile filled = fillDownloadFileType(company, file, companyName, dir, sub); + if (filled != null) { + retrieveFiles.add(filled); + } + + } + } + + holder.info("导入 " + retrieveFiles.size() + " 个文件"); + if (retrieveFiles.isEmpty()) { + return false; + } + + // update db + retrieveFiles.forEach(v -> { + v.setCompany(company); + save(v); + }); + return true; + } + + + /** + * 从文件名生成公司文件对象 + * 文件从下载目录中导入 + * + * @param company 公司对象 + * @param file 导入的文件对象 + * @param companyName 公司名称 + * @param destDir 目标目录 + * @param holder 状态输出 + * @return 生成的公司文件对象,如果无法转换则返回null + */ + private CompanyFile fillDownloadFileType(Company company, File file, String companyName, File destDir, + MessageHolder holder) { + String fileName = file.getName(); + // 天眼查的报告 + // 目前只有 基础版企业信用报告, 企业信用信息公示报告下载保存时的文件名中没有天眼查 + if (CloudTycService.isTycReport(fileName)) { + CompanyFile companyFile = new CompanyFile(); + companyFile.setType(CompanyFileType.CreditReport); + fillApplyDateAbsent(file, companyFile); + + String destFileName = fileName; + // 重命名 基础版企业信用报告 + for (String report : Arrays.asList( + CloudServiceConstant.TYC_ENTERPRISE_ANALYSIS_REPORT, + CloudServiceConstant.TYC_ENTERPRISE_BASIC_REPORT, + CloudServiceConstant.TYC_ENTERPRISE_MAJOR_REPORT)) { + + if (fileName.contains(report)) { + LocalDate applyDate = companyFile.getApplyDate(); + if (applyDate == null) { + applyDate = LocalDate.now(); + companyFile.setApplyDate(applyDate); + } + String formatted = MyDateTimeUtils.format(applyDate); + String extension = StringUtils.getFilenameExtension(fileName); + destFileName = String.format("%s_%s_%s_%s.%s", + companyName, CloudServiceConstant.TYC_NAME, report, formatted, extension); + } + } + + // 重新设置 企业分析报告 未普通文件 + // if (fileName.contains(CloudTycService.TYC_ENTERPRISE_ANALYSIS_REPORT)) { + // companyFile.setType(General); + // } + + File dest = new File(destDir, destFileName); + // 移动文件 + if (!file.renameTo(dest)) { + // 移动失败时 + holder.warn(fileName + " 无法移动到 " + dest.getAbsolutePath()); + return null; + } + + holder.info(fileName + " 移动到 " + dest.getAbsolutePath()); + companyFile.setFilePath(dest.getAbsolutePath()); + + // + if (companyFile.getExpiringDate() == null) { + if (companyFile.getApplyDate() != null) { + companyFile.setExpiringDate(companyFile.getApplyDate().plusYears(1)); + } + } + return companyFile; + } + + // 企业信用信息公示报告 + if (fileName.contains(CloudServiceConstant.TYC_ENTERPRISE_CREDIT_REPORT)) { + CompanyFile companyFile = new CompanyFile(); + companyFile.setType(CompanyFileType.CreditInfoPublicityReport); + fillApplyDateAbsent(file, companyFile); + File dest = new File(destDir, fileName); + + // 移动文件 + if (!file.renameTo(dest)) { + if (dest.exists()) { + // 尝试删除已经存在的文件 + if (!dest.delete()) { + holder.warn("覆盖时,无法删除已存在的文件 " + dest.getAbsolutePath()); + return null; + } + if (file.renameTo(dest)) { + List files = findByCompanyAndPath(company, dest.getAbsolutePath()); + if (!files.isEmpty()) { + companyFile = files.getFirst(); + } + } else { + holder.error(fileName + " 无法覆盖到 " + dest.getAbsolutePath()); + return null; + } + } else { + holder.error(fileName + " 无法移动到 " + dest.getAbsolutePath()); + return null; + } + } + + holder.info(fileName + " 移动到 " + dest.getAbsolutePath()); + companyFile.setFilePath(dest.getAbsolutePath()); + return companyFile; + } + return null; + } + + + /** + * 当 ApplyDate 未设置时,尝试使用文件名中包含的日期 + */ + private static void fillApplyDateAbsent(File file, CompanyFile companyFile) { + LocalDate applyDate = companyFile.getApplyDate(); + if (applyDate != null) { + return; + } + String fileName = file.getName(); + // 从文件名中提取日期 + LocalDate picked = MyDateTimeUtils.pickLocalDate(fileName); + if (picked != null) { + companyFile.setApplyDate(picked); + } + } } diff --git a/client/src/main/java/com/ecep/contract/service/CompanyFileTypeService.java b/client/src/main/java/com/ecep/contract/service/CompanyFileTypeService.java index fbd7856..41507a2 100644 --- a/client/src/main/java/com/ecep/contract/service/CompanyFileTypeService.java +++ b/client/src/main/java/com/ecep/contract/service/CompanyFileTypeService.java @@ -1,4 +1,29 @@ package com.ecep.contract.service; -public class CompanyFileTypeService { +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +import org.springframework.cache.annotation.CacheConfig; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; + +import com.ecep.contract.CompanyFileType; +import com.ecep.contract.model.CompanyFileTypeLocal; +import com.ecep.contract.vm.CompanyFileTypeLocalViewModel; + +@Service +@CacheConfig(cacheNames = "company-file-type") +public class CompanyFileTypeService extends QueryService { + + @Cacheable + public Map findAll(Locale locale) { + Map params = new HashMap<>(); + params.put("lang", locale.toLanguageTag()); + return findAll(params, Pageable.unpaged()).stream() + .collect(Collectors.toMap(CompanyFileTypeLocal::getType, Function.identity())); + } } diff --git a/client/src/main/java/com/ecep/contract/service/CompanyOldNameService.java b/client/src/main/java/com/ecep/contract/service/CompanyOldNameService.java index 03d8008..ee6c3e3 100644 --- a/client/src/main/java/com/ecep/contract/service/CompanyOldNameService.java +++ b/client/src/main/java/com/ecep/contract/service/CompanyOldNameService.java @@ -1,13 +1,14 @@ package com.ecep.contract.service; -import java.time.LocalDate; -import java.util.List; - -import org.springframework.stereotype.Service; - import com.ecep.contract.model.Company; import com.ecep.contract.model.CompanyOldName; import com.ecep.contract.vm.CompanyOldNameViewModel; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; + +import java.time.LocalDate; +import java.util.HashMap; +import java.util.List; @Service public class CompanyOldNameService extends QueryService { @@ -26,4 +27,10 @@ public class CompanyOldNameService extends QueryService findAllByCompany(Company company) { + HashMap params = new HashMap<>(); + params.put("company", company.getId()); + return findAll(params, Pageable.unpaged()).getContent(); + } } diff --git a/client/src/main/java/com/ecep/contract/service/CompanyService.java b/client/src/main/java/com/ecep/contract/service/CompanyService.java index ff672f7..7a98909 100644 --- a/client/src/main/java/com/ecep/contract/service/CompanyService.java +++ b/client/src/main/java/com/ecep/contract/service/CompanyService.java @@ -1,31 +1,54 @@ package com.ecep.contract.service; +import com.ecep.contract.MessageHolder; +import com.ecep.contract.SpringApp; +import com.ecep.contract.constant.CompanyConstant; +import com.ecep.contract.model.Company; +import com.ecep.contract.util.FileUtils; +import com.ecep.contract.vm.CompanyViewModel; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; + import java.io.File; import java.time.LocalDate; +import java.util.HashMap; import java.util.List; - -import org.springframework.stereotype.Service; - -import com.ecep.contract.MessageHolder; -import com.ecep.contract.model.Company; -import com.ecep.contract.vm.CompanyViewModel; +import java.util.Map; @Service public class CompanyService extends QueryService { + @Autowired + private SysConfService confService; + + private File basePath; + @Override public String getBeanName() { return "companyService"; } + public File getBasePath() { + if (basePath == null) { + basePath = new File(confService.getString(CompanyConstant.COMPANY_BASE_PATH)); + } + return basePath; + } + public Company findByName(String name) { - // return companyRepository.findByName(name); - throw new UnsupportedOperationException("Unimplemented method 'findByName'"); + List list = findAllByName(name); + if (list.isEmpty()) { + return null; + } + return list.getFirst(); } public List findAllByName(String name) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'findAllByName'"); + Map params = new HashMap<>(); + params.put("name", name); + return findAll(params, Pageable.unpaged()).getContent(); } public void merge(Company company, Company updater) { @@ -34,8 +57,10 @@ public class CompanyService extends QueryService { } public Company createNewCompany(String newCompanyName) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'createNewCompany'"); + Company company = new Company(); + company.setName(newCompanyName); + company.setCreated(LocalDate.now()); + return company; } public boolean existsCompanyPath(Company company) { @@ -54,13 +79,97 @@ public class CompanyService extends QueryService { } public boolean makePathAbsent(Company company) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'makePathAbsent'"); + String path = company.getPath(); + if (StringUtils.hasText(path)) { + File file = new File(path); + if (file.exists()) { + return false; + } + } + + File dir = makePath(company); + if (dir == null) { + return false; + } + if (!dir.exists()) { + return false; + } + company.setPath(dir.getAbsolutePath()); + company.setPathExist(true); + return true; } + /** + * 创建企业目录 + * + * @param company 要创建的企业对象 + * @return 目录 + */ + public File makePath(Company company) { + File basePath = getBasePath(); + if (!basePath.exists()) { + return null; + } + String companyName = company.getName(); + String district = company.getDistrict(); + if (StringUtils.hasText(district)) { + String parentPrefix = FileUtils.getParentPrefixByDistrict(district); + if (parentPrefix != null) { + File parent = new File(basePath, parentPrefix); + if (!parent.exists()) { + if (!parent.mkdir()) { + return null; + } + } + String fileName = FileUtils.escapeFileName(companyName); + File dir = new File(parent, fileName); + if (!dir.exists()) { + if (!dir.mkdir()) { + return null; + } + } + return dir; + } + } + return null; + } + + + /** + * 移动文件到企业目录下 + * + * @param company 企业对象 + * @param files 要被移动的文件集合,需要从中选择需要的 + * @param holder 状态输出 + */ public boolean retrieveFromDownloadFiles(Company company, File[] files, MessageHolder holder) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'retrieveFromDownloadFiles'"); + // + boolean companyChanged = makePathAbsent(company); + + if (!StringUtils.hasText(company.getPath())) { + // fixed 要退出,需要保存 + if (companyChanged) { + save(company); + } + holder.error("存储目录未设置,请检查"); + return false; + } + + File home = new File(company.getPath()); + if (!home.exists()) { + // fixed 要退出,需要保存 + if (companyChanged) { + company = save(company); + } + holder.error(company.getPath() + " 不存在,无法访问,请检查或者修改"); + return false; + } + CompanyFileService fileService = SpringApp.getBean(CompanyFileService.class); + boolean retrieved = fileService.retrieveFromDownloadFiles(company, files, holder); + if (companyChanged) { + save(company); + } + return retrieved; } } diff --git a/client/src/main/java/com/ecep/contract/service/CompanyVendorService.java b/client/src/main/java/com/ecep/contract/service/CompanyVendorService.java index ee45704..e6ca130 100644 --- a/client/src/main/java/com/ecep/contract/service/CompanyVendorService.java +++ b/client/src/main/java/com/ecep/contract/service/CompanyVendorService.java @@ -1,18 +1,14 @@ package com.ecep.contract.service; import java.io.File; -import java.util.Collection; -import java.util.List; -import java.util.Locale; +import java.util.*; +import com.ecep.contract.model.*; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import com.ecep.contract.MessageHolder; -import com.ecep.contract.model.Company; -import com.ecep.contract.model.CompanyVendor; -import com.ecep.contract.model.Contract; -import com.ecep.contract.model.VendorCatalog; -import com.ecep.contract.model.VendorTypeLocal; import com.ecep.contract.vm.CompanyVendorViewModel; @Service @@ -24,8 +20,13 @@ public class CompanyVendorService extends QueryService params = new HashMap<>(); + params.put("company", company.getId()); + Page page = findAll(params, Pageable.ofSize(1)); + if (page.isEmpty()) { + return null; + } + return page.getContent().getFirst(); } public boolean reBuildingFiles(CompanyVendor companyVendor, MessageHolder messageHolder) { diff --git a/client/src/main/java/com/ecep/contract/service/CustomerCatalogService.java b/client/src/main/java/com/ecep/contract/service/CustomerCatalogService.java index 9666432..7d89bf6 100644 --- a/client/src/main/java/com/ecep/contract/service/CustomerCatalogService.java +++ b/client/src/main/java/com/ecep/contract/service/CustomerCatalogService.java @@ -1,4 +1,10 @@ package com.ecep.contract.service; -public class CustomerCatalogService { +import com.ecep.contract.model.CustomerCatalog; +import com.ecep.contract.vm.CustomerCatalogViewModel; +import org.springframework.stereotype.Service; + +@Service +public class CustomerCatalogService extends QueryService{ + } diff --git a/client/src/main/java/com/ecep/contract/service/QueryService.java b/client/src/main/java/com/ecep/contract/service/QueryService.java index 1563aec..6d97d73 100644 --- a/client/src/main/java/com/ecep/contract/service/QueryService.java +++ b/client/src/main/java/com/ecep/contract/service/QueryService.java @@ -1,25 +1,26 @@ package com.ecep.contract.service; -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.TimeUnit; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; - import com.ecep.contract.PageArgument; import com.ecep.contract.PageContent; import com.ecep.contract.WebSocketService; import com.ecep.contract.model.IdentityEntity; import com.ecep.contract.msg.SimpleMessage; import com.ecep.contract.vm.IdentityViewModel; +import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; +import java.util.function.Supplier; public class QueryService> implements ViewModelService { @@ -27,7 +28,6 @@ public class QueryService { + return webSocketService.send(msg).orTimeout(webSocketService.getReadTimeout(), TimeUnit.MILLISECONDS).handle((response, ex) -> { if (ex != null) { return null; } @@ -133,7 +133,7 @@ public class QueryService { + return webSocketService.send(msg).orTimeout(webSocketService.getReadTimeout(), TimeUnit.MILLISECONDS).handle((response, ex) -> { if (ex != null) { return null; } @@ -141,37 +141,12 @@ public class QueryService pageContent = new PageContent<>(); try { - List content = new ArrayList<>(); - if (response.has("content")) { - JsonNode contentNode = response.get("content"); - if (contentNode != null && contentNode.isArray()) { - for (JsonNode node : contentNode) { - T newEntity = createNewEntity(); - objectMapper.updateValue(newEntity, node); - content.add(newEntity); - } - } - } - pageContent.setContent(content); - if (response.has("page")) { - JsonNode pageNode = response.get("page"); - PageArgument pageArgument = objectMapper.treeToValue(pageNode, PageArgument.class); - pageContent.setPage(pageArgument); - } - if (response.has("totalElements")) { - int totalElements = response.get("totalElements").asInt(); - pageContent.setTotalElements(totalElements); - } - if (response.has("totalPages")) { - int totalPages = response.get("totalPages").asInt(); - pageContent.setTotalPages(totalPages); - } + PageContent pageContent = of(response, objectMapper, this::createNewEntity); + return pageContent.toPage(); } catch (Exception e) { throw new RuntimeException(response.toString(), e); } - return pageContent.toPage(); }); } @@ -190,4 +165,38 @@ public class QueryService list = findAll(params, Pageable.ofSize(10)).getContent(); return list; } + + + public static PageContent of(JsonNode response, ObjectMapper objectMapper, Supplier createNewEntity) + throws JsonProcessingException { + + PageContent pageContent = new PageContent<>(); + List content = new ArrayList<>(); + if (response.has("content")) { + JsonNode contentNode = response.get("content"); + if (contentNode != null && contentNode.isArray()) { + for (JsonNode node : contentNode) { + T newEntity = createNewEntity.get(); + objectMapper.updateValue(newEntity, node); + content.add(newEntity); + } + } + } + pageContent.setContent(content); + if (response.has("page")) { + JsonNode pageNode = response.get("page"); + PageArgument pageArgument = objectMapper.treeToValue(pageNode, PageArgument.class); + pageContent.setPage(pageArgument); + } + if (response.has("totalElements")) { + int totalElements = response.get("totalElements").asInt(); + pageContent.setTotalElements(totalElements); + } + if (response.has("totalPages")) { + int totalPages = response.get("totalPages").asInt(); + pageContent.setTotalPages(totalPages); + } + return pageContent; + } + } diff --git a/client/src/main/java/com/ecep/contract/service/SysConfService.java b/client/src/main/java/com/ecep/contract/service/SysConfService.java index 47fbb03..0b8a3ab 100644 --- a/client/src/main/java/com/ecep/contract/service/SysConfService.java +++ b/client/src/main/java/com/ecep/contract/service/SysConfService.java @@ -1,60 +1,186 @@ package com.ecep.contract.service; -import java.util.List; -import java.util.Map; - +import com.ecep.contract.PageArgument; +import com.ecep.contract.PageContent; +import com.ecep.contract.WebSocketService; +import com.ecep.contract.model.SysConf; +import com.ecep.contract.msg.SimpleMessage; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheConfig; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; -import com.ecep.contract.model.SysConf; +import java.time.LocalDateTime; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; @Service -public class SysConfService { +@CacheConfig(cacheNames = "sys_conf") +public class SysConfService { + @Autowired + protected WebSocketService webSocketService; + @Autowired + protected ObjectMapper objectMapper; - public SysConf findById(String id) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'findById'"); + public CompletableFuture asyncFindById(String id) { + SimpleMessage msg = new SimpleMessage(); + msg.setService(getBeanName()); + msg.setMethod("findById"); + msg.setArguments(id); + return webSocketService.send(msg).orTimeout(webSocketService.getReadTimeout(), TimeUnit.MILLISECONDS).handle((response, ex) -> { + if (ex != null) { + return null; + } + if (response == null) { + return null; + } + SysConf newEntity = new SysConf(); + try { + objectMapper.updateValue(newEntity, response); + } catch (JsonMappingException e) { + throw new RuntimeException(response.toString(), e); + } + return newEntity; + }); } - public SysConf save(SysConf entity) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'save'"); + public SysConf findById(String key) { + try { + return asyncFindById(key).get(); + } catch (Exception e) { + e.printStackTrace(); + } + return null; } - public void delete(SysConf entity) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'delete'"); - } - - public List findAll() { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'findAll'"); + public CompletableFuture> asyncFindAll(Map params, Pageable pageable) { + SimpleMessage msg = new SimpleMessage(); + msg.setService(getBeanName()); + msg.setMethod("findAll"); + msg.setArguments(params, PageArgument.of(pageable)); + return webSocketService.send(msg).orTimeout(webSocketService.getReadTimeout(), TimeUnit.MILLISECONDS).handle((response, ex) -> { + if (ex != null) { + return null; + } + if (response == null) { + return null; + } + try { + PageContent pageContent = QueryService.of(response, objectMapper, SysConf::new); + return pageContent.toPage(); + } catch (Exception e) { + throw new RuntimeException(response.toString(), e); + } + }); } public Page findAll(Map params, Pageable pageable) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'findAll'"); + try { + return asyncFindAll(params, pageable).get(); + } catch (Exception e) { + e.printStackTrace(); + } + return null; } + @Cacheable(key = "#p0") public boolean getBoolean(String key) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'getBoolean'"); + return get(key, false); } - public void set(String key, String string) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'set'"); + public boolean get(String key, boolean defaultValue) { + SysConf conf = findById(key); + if (conf == null) { + return defaultValue; + } else { + if (Boolean.parseBoolean(conf.getValue())) { + return true; + } + return "1".equalsIgnoreCase(conf.getValue()); + } } - public String getString(String string) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'getString'"); + @CacheEvict(key = "#p0") + public SysConf set(String key, String value) { + SysConf conf = findById(key); + if (conf == null) { + conf = new SysConf(); + conf.setId(key); + conf.setCreated(LocalDateTime.now()); + } + conf.setValue(value); + conf.setModified(LocalDateTime.now()); + return save(conf); } + @Cacheable(key = "#p0") + public String getString(String key) { + return get(key, null); + } + + public String get(String key, String defaultValue) { + SysConf conf = findById(key); + if (conf == null) { + return defaultValue; + } else { + return conf.getValue(); + } + } + + @Cacheable(key = "#p0") + public long getLong(String key) { + return get(key, 0); + } + + public long get(String key, long defaultValue) { + SysConf conf = findById(key); + if (conf == null) { + return defaultValue; + } else { + return Long.parseLong(conf.getValue()); + } + } + + @Cacheable(key = "#p0") public int getInt(String key) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'getInt'"); + return get(key, 0); + } + + public int get(String key, int defaultValue) { + SysConf conf = findById(key); + if (conf == null) { + return defaultValue; + } else { + return Integer.parseInt(conf.getValue()); + } + } + + @CacheEvict(key = "#p0.id") + public SysConf save(SysConf entity) { + SimpleMessage msg = new SimpleMessage(); + msg.setService(getBeanName()); + msg.setMethod("save"); + msg.setArguments(entity); + try { + Object response = webSocketService.send(msg).get(webSocketService.getReadTimeout(), TimeUnit.MILLISECONDS); + if (response != null) { + objectMapper.updateValue(entity, response); + } + } catch (Exception e) { + e.printStackTrace(); + } + return entity; + + } + + public String getBeanName() { + return "sysConfService"; } } diff --git a/client/src/main/java/com/ecep/contract/util/FxmlUtils.java b/client/src/main/java/com/ecep/contract/util/FxmlUtils.java index 510a120..d5156b6 100644 --- a/client/src/main/java/com/ecep/contract/util/FxmlUtils.java +++ b/client/src/main/java/com/ecep/contract/util/FxmlUtils.java @@ -4,7 +4,7 @@ import java.io.IOException; import java.net.URL; import java.util.concurrent.CompletableFuture; -import com.ecep.contract.AppV2; +import com.ecep.contract.ClientV2; import com.ecep.contract.Desktop; import com.ecep.contract.SpringApp; @@ -15,7 +15,7 @@ public class FxmlUtils { public static FXMLLoader newLoader(String path) { FXMLLoader loader = new FXMLLoader(); - URL location = AppV2.class.getResource(path); + URL location = ClientV2.class.getResource(path); if (location == null) { throw new RuntimeException("无法找到窗口资源文件 " + path); } diff --git a/client/src/main/java/com/ecep/contract/util/ProxyUtils.java b/client/src/main/java/com/ecep/contract/util/ProxyUtils.java index 531729b..56c09c5 100644 --- a/client/src/main/java/com/ecep/contract/util/ProxyUtils.java +++ b/client/src/main/java/com/ecep/contract/util/ProxyUtils.java @@ -8,10 +8,13 @@ import com.fasterxml.jackson.annotation.JsonIgnore; public class ProxyUtils { /** - * 判断对象是否已初始化 - * 在客户端环境中,从服务器端返回的数据中,代理对象序列化时只包含Id属性, - * 其他属性为null,因此需要判断对象是否已初始化 - * 初始化条件:对象不为null,且不是代理对象或已被标记为初始化 + * 判断传入的对象是否已完成初始化。 + * 在客户端接收服务器返回数据的场景下,代理对象序列化后通常仅包含 id 属性,其余属性均为 null。 + * 本方法通过检查对象除 id 外的其他非 @JsonIgnore 字段是否为 null 来判断对象是否已初始化。 + * 若执行过程中出现异常,则默认对象已初始化。 + * + * @param proxy 待检查的对象 + * @return 若对象已初始化返回 true,否则返回 false */ public static boolean isInitialized(Object proxy) { if (proxy == null) { diff --git a/client/src/main/java/com/ecep/contract/vm/CompanyFileTypeLocalViewModel.java b/client/src/main/java/com/ecep/contract/vm/CompanyFileTypeLocalViewModel.java new file mode 100644 index 0000000..9e5c2b4 --- /dev/null +++ b/client/src/main/java/com/ecep/contract/vm/CompanyFileTypeLocalViewModel.java @@ -0,0 +1,45 @@ +package com.ecep.contract.vm; + +import java.util.Objects; + +import com.ecep.contract.CompanyFileType; +import com.ecep.contract.model.CompanyFileTypeLocal; + +import javafx.beans.property.SimpleObjectProperty; +import javafx.beans.property.SimpleStringProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper = false) +public class CompanyFileTypeLocalViewModel extends IdentityViewModel { + private SimpleObjectProperty type = new SimpleObjectProperty<>(); + private SimpleStringProperty lang = new SimpleStringProperty(); + private SimpleStringProperty value = new SimpleStringProperty(); + + @Override + protected void updateFrom(CompanyFileTypeLocal v) { + super.updateFrom(v); + type.set(v.getType()); + lang.set(v.getLang()); + value.set(v.getValue()); + } + + @Override + public boolean copyTo(CompanyFileTypeLocal v) { + boolean ret = super.copyTo(v); + if (!Objects.equals(type.get(), v.getType())) { + v.setType(type.get()); + ret = true; + } + if (!Objects.equals(lang.get(), v.getLang())) { + v.setLang(lang.get()); + ret = true; + } + if (!Objects.equals(value.get(), v.getValue())) { + v.setValue(value.get()); + ret = true; + } + return ret; + } +} \ No newline at end of file diff --git a/client/src/main/java/com/ecep/contract/vm/CustomerCatalogViewModel.java b/client/src/main/java/com/ecep/contract/vm/CustomerCatalogViewModel.java index 5c25df0..87f8946 100644 --- a/client/src/main/java/com/ecep/contract/vm/CustomerCatalogViewModel.java +++ b/client/src/main/java/com/ecep/contract/vm/CustomerCatalogViewModel.java @@ -1,4 +1,42 @@ package com.ecep.contract.vm; -public class CustomerCatalogViewModel { +import com.ecep.contract.model.CustomerCatalog; +import javafx.beans.property.SimpleStringProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Objects; + +@Data +@EqualsAndHashCode(callSuper = false) +public class CustomerCatalogViewModel extends IdentityViewModel { + private SimpleStringProperty code = new SimpleStringProperty(); + private SimpleStringProperty name = new SimpleStringProperty(); + private SimpleStringProperty description = new SimpleStringProperty(); + + @Override + protected void updateFrom(CustomerCatalog v) { + super.updateFrom(v); + code.set(v.getCode()); + name.set(v.getName()); + description.set(v.getDescription()); + } + + @Override + public boolean copyTo(CustomerCatalog v) { + boolean ret = super.copyTo(v); + if (!Objects.equals(code.get(), v.getCode())) { + v.setCode(code.get()); + ret = true; + } + if (!Objects.equals(name.get(), v.getName())) { + v.setName(name.get()); + ret = true; + } + if (!Objects.equals(description.get(), v.getDescription())) { + v.setDescription(description.get()); + ret = true; + } + return ret; + } } diff --git a/client/src/main/java/com/ecep/contract/vm/SysConfViewModel.java b/client/src/main/java/com/ecep/contract/vm/SysConfViewModel.java index 71fa491..75594c7 100644 --- a/client/src/main/java/com/ecep/contract/vm/SysConfViewModel.java +++ b/client/src/main/java/com/ecep/contract/vm/SysConfViewModel.java @@ -1,4 +1,46 @@ package com.ecep.contract.vm; -public class SysConfViewModel { +import com.ecep.contract.model.SysConf; +import javafx.beans.property.SimpleObjectProperty; +import javafx.beans.property.SimpleStringProperty; + +import java.time.LocalDateTime; +import java.util.Objects; + +public class SysConfViewModel extends BaseViewModel { + private SimpleStringProperty id = new SimpleStringProperty(); + private SimpleStringProperty value = new SimpleStringProperty(); + private SimpleObjectProperty modified = new SimpleObjectProperty<>(); + private SimpleObjectProperty created = new SimpleObjectProperty<>(); + + @Override + protected void updateFrom(SysConf v) { + super.updateFrom(v); + id.set(v.getId()); + value.set(v.getValue()); + modified.set(v.getModified()); + created.set(v.getCreated()); + } + + @Override + public boolean copyTo(SysConf v) { + boolean ret = super.copyTo(v); + if (!Objects.equals(id.get(), v.getId())) { + v.setId(id.get()); + ret = true; + } + if (!Objects.equals(value.get(), v.getValue())) { + v.setValue(value.get()); + ret = true; + } + if (!Objects.equals(modified.get(), v.getModified())) { + v.setModified(modified.get()); + ret = true; + } + if (!Objects.equals(created.get(), v.getCreated())) { + v.setCreated(created.get()); + ret = true; + } + return ret; + } } diff --git a/client/src/main/resources/ui/company/company-tab-bank-account.fxml b/client/src/main/resources/ui/company/company-tab-bank-account.fxml index 78e1250..9a8e890 100644 --- a/client/src/main/resources/ui/company/company-tab-bank-account.fxml +++ b/client/src/main/resources/ui/company/company-tab-bank-account.fxml @@ -3,7 +3,7 @@ + fx:controller="com.ecep.contract.controller.tab.CompanyTabSkinBankAccount"> diff --git a/client/src/main/resources/ui/company/company-tab-contact.fxml b/client/src/main/resources/ui/company/company-tab-contact.fxml index a37610a..b78601e 100644 --- a/client/src/main/resources/ui/company/company-tab-contact.fxml +++ b/client/src/main/resources/ui/company/company-tab-contact.fxml @@ -3,7 +3,7 @@ + fx:controller="com.ecep.contract.controller.tab.CompanyTabSkinContact"> diff --git a/client/src/main/resources/ui/company/company-tab-purchase-bill-voucher.fxml b/client/src/main/resources/ui/company/company-tab-purchase-bill-voucher.fxml index 2e51275..3158e7a 100644 --- a/client/src/main/resources/ui/company/company-tab-purchase-bill-voucher.fxml +++ b/client/src/main/resources/ui/company/company-tab-purchase-bill-voucher.fxml @@ -3,7 +3,7 @@ + fx:controller="com.ecep.contract.controller.tab.CompanyTabSkinPurchaseBillVoucher"> diff --git a/client/src/main/resources/ui/company/company_old_name.fxml b/client/src/main/resources/ui/company/company_old_name.fxml index 5ccbe75..57ddb85 100644 --- a/client/src/main/resources/ui/company/company_old_name.fxml +++ b/client/src/main/resources/ui/company/company_old_name.fxml @@ -22,117 +22,121 @@ - - -
- - - - - - - - - - - - - - - - - - - - - - - - -