feat: 实现VoableService接口并重构相关服务

refactor: 优化WebSocket通信和任务处理逻辑

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

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

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

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

test: 添加CustomerFileMoveTasker测试类

chore: 更新tasker_mapper.json注册信息
This commit is contained in:
2025-09-25 18:57:17 +08:00
parent bf90117116
commit 45f7b611c5
61 changed files with 1638 additions and 286 deletions

View File

@@ -6,12 +6,12 @@
<parent>
<groupId>com.ecep.contract</groupId>
<artifactId>Contract-Manager</artifactId>
<version>0.0.84-SNAPSHOT</version>
<version>0.0.86-SNAPSHOT</version>
</parent>
<groupId>com.ecep.contract</groupId>
<artifactId>client</artifactId>
<version>0.0.84-SNAPSHOT</version>
<version>0.0.86-SNAPSHOT</version>
<properties>
<maven.compiler.source>${java.version}</maven.compiler.source>
@@ -22,7 +22,7 @@
<dependency>
<groupId>com.ecep.contract</groupId>
<artifactId>common</artifactId>
<version>0.0.84-SNAPSHOT</version>
<version>0.0.86-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>

View File

@@ -96,17 +96,14 @@ public class WebSocketClientSession {
Object value = args.get(1);
try {
PropertyDescriptor descriptor = BeanUtils.getPropertyDescriptor(tasker.getClass(), name);
System.out.println("descriptor = " + descriptor);
System.out.println("descriptor.getPropertyType() = " + descriptor.getPropertyType());
if (descriptor == null) {
tasker.updateMessage(java.util.logging.Level.SEVERE, "属性 " + name + " 不存在");
return;
}
Object object = webSocketService.getObjectMapper().convertValue(value, descriptor.getPropertyType());
System.out.println("object = " + object);
System.out.println("descriptor.getWriteMethod() = " + descriptor.getWriteMethod());
if (descriptor.getWriteMethod() == null) {
tasker.updateMessage(java.util.logging.Level.SEVERE, "属性 " + name + " 不可写");
} else {
System.out.println("descriptor.getWriteMethod().getParameterTypes() = "
+ descriptor.getWriteMethod().getParameterTypes());
descriptor.getWriteMethod().invoke(tasker, object);
}
} catch (Exception e) {
@@ -123,7 +120,7 @@ public class WebSocketClientSession {
private void handleAsMessage(JsonNode args) {
String level = args.get(0).asText();
String message = args.get(1).asText();
updateMessage(java.util.logging.Level.parse(level), message);
updateMessage(java.util.logging.Level.parse(level), "[R] "+message);
}
public void updateMessage(Level level, String message) {

View File

@@ -1,8 +1,6 @@
package com.ecep.contract;
import com.fasterxml.jackson.core.JsonProcessingException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Locale;
import java.util.UUID;

View File

@@ -115,6 +115,9 @@ public class ContractTabSkinExtendVendorInfo extends AbstContractBasedTabSkin {
assignedProviderField.selectedProperty().bindBidirectional(viewModel.getAssignedProvider());
assignedProviderField.disableProperty().bind(Bindings.createBooleanBinding(() -> {
Integer groupId = viewModel.getGroup().get();
if (groupId == null) {
return false;
}
VendorGroupVo group = getVendorGroupService().findById(groupId);
if (group == null) {
return false;

View File

@@ -1,29 +1,29 @@
package com.ecep.contract.controller.customer;
import java.io.File;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import org.springframework.util.StringUtils;
import com.ecep.contract.MyDateTimeUtils;
import com.ecep.contract.SpringApp;
import com.ecep.contract.controller.company.CompanyWindowController;
import com.ecep.contract.controller.tab.AbstEntityBasedTabSkin;
import com.ecep.contract.controller.tab.TabSkin;
import com.ecep.contract.converter.CompanyStringConverter;
import com.ecep.contract.converter.EntityStringConverter;
import com.ecep.contract.vo.CompanyVo;
import com.ecep.contract.vo.CompanyContactVo;
import com.ecep.contract.vo.CompanyCustomerVo;
import com.ecep.contract.service.CompanyContactService;
import com.ecep.contract.service.CompanyCustomerService;
import com.ecep.contract.service.CompanyService;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vm.CompanyCustomerViewModel;
import com.ecep.contract.vo.CompanyCustomerVo;
import com.ecep.contract.vo.CompanyVo;
import javafx.beans.binding.Bindings;
import javafx.beans.property.SimpleObjectProperty;
import javafx.event.ActionEvent;
import javafx.scene.control.Tab;
import javafx.scene.control.TextField;
import javafx.stage.DirectoryChooser;
import javafx.util.converter.LocalDateStringConverter;
public class CompanyCustomerTabSkinBase
@@ -102,7 +102,33 @@ public class CompanyCustomerTabSkinBase
}
public void onCompanyCustomerChangePathAction(ActionEvent event) {
setStatus("未实现");
DirectoryChooser chooser = new DirectoryChooser();
CompanyCustomerVo entity = getEntity();
String path = entity.getPath();
File initialDirectory = null;
// 如果当前已经设置了目录并且路径有效,则设置初始目录为该目录
if (StringUtils.hasText(path)) {
File dir = new File(path);
if (dir.exists()) {
initialDirectory = dir;
}
}
// 如果没有有效的初始目录,则使用基础路径
if (initialDirectory == null) {
initialDirectory = getCompanyCustomerService().getBasePath();
}
if (initialDirectory != null) {
chooser.setInitialDirectory(initialDirectory);
}
File newDirectory = chooser.showDialog(getTab().getContent().getScene().getWindow());
if (newDirectory != null) {
entity.setPath(newDirectory.getAbsolutePath());
save(entity);
}
}
public void onCompanyCustomerPathSameAsNameAction(ActionEvent event) {

View File

@@ -23,6 +23,8 @@ import com.ecep.contract.service.CompanyCustomerEvaluationFormFileService;
import com.ecep.contract.service.CompanyCustomerFileService;
import com.ecep.contract.service.CompanyCustomerFileTypeService;
import com.ecep.contract.service.CompanyCustomerService;
import com.ecep.contract.service.CompanyService;
import com.ecep.contract.task.CustomerFileMoveTasker;
import com.ecep.contract.util.FileUtils;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.util.ParamUtils;
@@ -246,7 +248,6 @@ public class CustomerTabSkinFile
public void onFileReBuildingAction(ActionEvent event) {
CompanyCustomerService customerService = getCompanyCustomerService();
try {
CompanyCustomerVo companyCustomer = customerService.findById(viewModel.getId().get());
@@ -279,6 +280,12 @@ public class CustomerTabSkinFile
}
public void onFileTableMoveToCompanyPathAction(ActionEvent event) {
CompanyCustomerFileViewModel selectedItem = getSelectedItem();
if (selectedItem == null) {
return;
}
// 检查公司目录设置
Integer companyId = viewModel.getCompany().get();
CompanyVo company = getCompanyService().findById(companyId);
@@ -289,41 +296,17 @@ public class CustomerTabSkinFile
File companyPath = new File(company.getPath());
if (!companyPath.exists()) {
setStatus("公司目录设置设置异常,无法访问");
setStatus("公司目录设置异常,无法访问");
return;
}
CompanyCustomerFileViewModel selectedItem = getSelectedItem();
if (selectedItem == null) {
return;
}
String filePath = selectedItem.getFilePath().get();
String editFilePath = selectedItem.getEditFilePath().get();
// 创建并启动任务
CustomerFileMoveTasker task = new CustomerFileMoveTasker();
task.setFileId(selectedItem.getId().get());
UITools.showTaskDialogAndWait("移动文件到公司目录", task, null);
if (StringUtils.hasText(filePath)) {
File file = new File(filePath);
if (file.exists()) {
File dest = new File(companyPath, file.getName());
if (file.renameTo(dest)) {
setStatus(file.getAbsolutePath() + " -> " + dest.getAbsolutePath());
}
}
}
if (StringUtils.hasText(editFilePath)) {
File file = new File(editFilePath);
if (file.exists()) {
File dest = new File(companyPath, file.getName());
if (file.renameTo(dest)) {
setStatus(file.getAbsolutePath() + " -> " + dest.getAbsolutePath());
}
}
}
deleteRow(selectedItem);
// getCompanyCustomerService().deleteFileById(selectedItem.getId().get());
// dataSet.remove(selectedItem);
// 刷新表格数据
loadTableDataSet();
}
private void initializeTask(Task<Object> task, String prefix, Consumer<String> consumer) {
@@ -368,7 +351,6 @@ public class CustomerTabSkinFile
});
}
private CompanyCustomerFileService getCompanyCustomerFileService() {
if (companyCustomerFileService == null) {
companyCustomerFileService = SpringApp.getBean(CompanyCustomerFileService.class);

View File

@@ -97,6 +97,7 @@ public class CompanyTabSkinBase
}
private void onCompanyPathChangePathAction(ActionEvent event) {
}
private void onCompanyPathSameAsNameAction(ActionEvent event) {

View File

@@ -1,7 +1,10 @@
package com.ecep.contract.controller.vendor;
import java.io.File;
import java.time.format.DateTimeFormatter;
import org.springframework.util.StringUtils;
import com.ecep.contract.MyDateTimeUtils;
import com.ecep.contract.SpringApp;
import com.ecep.contract.VendorType;
@@ -23,6 +26,7 @@ import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Tab;
import javafx.stage.DirectoryChooser;
import javafx.util.converter.LocalDateStringConverter;
import javafx.util.converter.LocalDateTimeStringConverter;
@@ -107,7 +111,33 @@ public class VendorTabSkinBase
}
public void onChangePathAction(ActionEvent event) {
setStatus("未实现");
DirectoryChooser chooser = new DirectoryChooser();
VendorVo entity = getEntity();
String path = entity.getPath();
File initialDirectory = null;
// 如果当前已经设置了目录并且路径有效,则设置初始目录为该目录
if (StringUtils.hasText(path)) {
File dir = new File(path);
if (dir.exists()) {
initialDirectory = dir;
}
}
// 如果没有有效的初始目录,则使用基础路径
if (initialDirectory == null) {
initialDirectory = getCompanyVendorService().getBasePath();
}
if (initialDirectory != null) {
chooser.setInitialDirectory(initialDirectory);
}
File newDirectory = chooser.showDialog(getTab().getContent().getScene().getWindow());
if (newDirectory != null) {
entity.setPath(newDirectory.getAbsolutePath());
save(entity);
}
}
public void onPathSameAsNameAction(ActionEvent event) {

View File

@@ -48,7 +48,7 @@ public class CompanyCustomerService extends QueryService<CompanyCustomerVo, Comp
public boolean reBuildingFiles(CompanyCustomerVo companyCustomer, MessageHolder holder) {
// 首先确保客户有有效的路径
if (!makePathAbsent(companyCustomer)) {
holder.addMessage(java.util.logging.Level.WARNING, "无法创建或确认客户路径,文件重建可能失败");
holder.warn("无法创建或确认客户路径,文件重建可能失败");
}
// 创建并配置文件重建任务
@@ -119,8 +119,16 @@ public class CompanyCustomerService extends QueryService<CompanyCustomerVo, Comp
* @return 格式化后的ID字符串
*/
private String formatCompanyCustomerId(Integer id) {
// 简单实现实际应与server端的CompanyUtils.formatCompanyVendorId保持一致
return String.format("%06d", id);
if (id != null) {
if (id > 99) {
return String.valueOf(id);
} else if (id > 9) {
return "0" + id;
} else if (id > 0) {
return "00" + id;
}
}
throw new IllegalArgumentException("客户ID必须为正数");
}
/**

View File

@@ -10,7 +10,7 @@ import lombok.Getter;
import lombok.Setter;
/**
*
* 合同修复任务
*/
public class ContractRepairTask extends Tasker<Object> implements WebSocketClientTasker {
@Getter
@@ -18,14 +18,19 @@ public class ContractRepairTask extends Tasker<Object> implements WebSocketClien
private ContractVo contract;
@Getter
boolean repaired = false;
@Setter
private boolean repaired = false;
@Getter
@Setter
protected boolean filesUpdated = false;
@Getter
@Setter
protected boolean itemsUpdated = false;
@Getter
@Setter
protected boolean playPlanUpdated = false;
@Getter
@Setter
protected boolean saleOrderUpdated = false;
public ContractRepairTask() {

View File

@@ -0,0 +1,52 @@
package com.ecep.contract.task;
import com.ecep.contract.MessageHolder;
import com.ecep.contract.WebSocketClientTasker;
import lombok.Getter;
import lombok.Setter;
import java.util.logging.Level;
/**
* 客户文件移动到公司目录任务器
* 用于将客户相关文件从客户目录移动到公司目录
*/
public class CustomerFileMoveTasker extends Tasker<Object> implements WebSocketClientTasker {
private static final String TASK_NAME = "CustomerFileMoveTasker";
@Setter
@Getter
private boolean filesUpdated;
private Integer fileId;
public void setFileId(Integer fileId) {
this.fileId = fileId;
}
@Override
public String getTaskName() {
return TASK_NAME;
}
@Override
public void updateProgress(long current, long total) {
super.updateProgress(current, total);
}
@Override
protected Object execute(MessageHolder holder) throws Exception {
try {
updateTitle("移动文件到公司目录");
updateMessage("开始执行文件移动任务...");
// 调用远程WebSocket任务传递客户ID和文件ID
callRemoteTask(holder, getLocale(), fileId);
updateMessage("文件移动任务已提交到服务器,等待执行完成...");
return true;
} catch (Exception e) {
updateMessage(Level.SEVERE, "文件移动失败: " + e.getMessage());
throw e;
}
}
}