Files
contract-manager/docs/task/table_cell_implementation_guide.md
songqq 09b0da498b feat(service): 实现国际化支持并优化Service层
重构文件类型相关Service以支持国际化查询
添加findOneByLang辅助方法统一查询逻辑
实现StringConverter支持UI控件显示
优化缓存配置和查询性能
新增UnitStringConverter和CustomerCatalogStringConverter
完善文档和测试用例
2025-09-24 16:20:49 +08:00

220 lines
6.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# TableCell 实现规则与模式指南
## 1. 目的与作用
TableCell 是 JavaFX TableView 组件中的关键元素,负责表格中单个单元格的渲染和交互。在 Contract-Manager 项目中TableCell 主要用于:
- 显示各种类型的数据(数字、日期、实体引用等)
- 提供自定义的显示格式和样式
- 支持异步加载关联数据
- 实现单元格内编辑功能
## 2. 文件结构与命名规范
- **文件位置**`client/src/main/java/com/ecep/contract/controller/table/cell/`
- **命名规范**:使用 PascalCase驼峰命名法首字母大写`TableCell` 结尾
- 示例:`CompanyTableCell.java``LocalDateFieldTableCell.java`
## 3. TableCell 分类与实现模式
### 3.1 基础 TableCell
直接继承 JavaFX 的 `TableCell` 类,适用于简单的数据显示。
**实现规则**
- 继承 `TableCell<S, T>`,其中 S 是表格行数据类型T 是单元格数据类型
- 实现 `updateItem(T item, boolean empty)` 方法
- 提供静态的 `forTableColumn()` 工厂方法
**示例**
```java
public class NumberTableCell<S> extends TableCell<S, Number> {
private final NumberStringConverter numberStringConverter;
public NumberTableCell(NumberStringConverter numberStringConverter) {
this.numberStringConverter = numberStringConverter;
}
@Override
protected void updateItem(Number item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null) {
setText(null);
} else {
setText(numberStringConverter.toString(item));
}
}
public static <S> Callback<TableColumn<S, Number>, TableCell<S, Number>> forTableColumn(NumberStringConverter numberStringConverter) {
return param -> new NumberTableCell<>(numberStringConverter);
}
}
```
### 3.2 异步更新 TableCell
继承 `AsyncUpdateTableCell`,用于异步加载并显示关联的实体数据。
**实现规则**
- 继承 `AsyncUpdateTableCell<V, K, T>`,其中 V 是表格行数据类型K 是 ID 类型T 是实体类型
- 提供构造函数接收服务对象,或实现 `getServiceBean()` 方法从 Spring 容器获取服务
- 可选:重写 `initialize()` 方法自定义实体加载逻辑
- 可选:重写 `format()` 方法自定义实体显示格式
**示例**
```java
@NoArgsConstructor
public class CompanyTableCell<V> extends AsyncUpdateTableCell<V, Integer, CompanyVo> {
public CompanyTableCell(CompanyService companyService) {
setService(companyService);
}
@Override
protected CompanyService getServiceBean() {
return SpringApp.getBean(CompanyService.class);
}
}
```
### 3.3 可编辑 TableCell
实现单元格内编辑功能,如日期选择、文本编辑等。
**实现规则**
- 继承 `TableCell` 或其子类
- 实现 `startEdit()``cancelEdit()` 方法
-`updateItem()` 方法中处理编辑状态的显示
- 提供编辑控件和事件处理
**示例**
```java
public class LocalDateFieldTableCell<S> extends TableCell<S, LocalDate> {
private final DatePicker datePicker;
// 构造函数、converter 属性等
@Override
public void startEdit() {
if (isEmpty()) {
return;
}
super.startEdit();
setGraphic(datePicker);
datePicker.setConverter(getConverter());
datePicker.setValue(getItem());
datePicker.requestFocus();
}
@Override
public void cancelEdit() {
super.cancelEdit();
LocalDate item = getItem();
if (item == null) {
setText(null);
} else {
setText(getConverter().toString(item));
}
setGraphic(null);
}
@Override
protected void updateItem(LocalDate item, boolean empty) {
// 实现更新逻辑
}
}
```
## 4. AsyncUpdateTableCell 核心功能
`AsyncUpdateTableCell` 是项目中最常用的基类,提供以下核心功能:
### 4.1 异步加载机制
- 显示占位符(`#id`)直到数据加载完成
- 使用线程池执行异步任务
- 自动取消不再需要的异步任务
- 确保在 JavaFX 应用线程更新 UI
### 4.2 实体显示格式化
- 默认使用 `toString()` 方法格式化实体
-`NamedEntity``BasedEntity` 有特殊处理
- 允许子类重写 `format()` 方法自定义格式
### 4.3 服务获取方式
- 通过构造函数注入服务
- 或通过 `getServiceBean()` 方法从 Spring 容器获取
## 5. 特殊情况处理
### 5.1 非 Integer 类型 ID
当实体 ID 不是 Integer 类型时,需要重写 `initialize()` 方法:
```java
@Override
protected ContractFileTypeLocalVo initialize() {
ContractFileType item = getItem();
ContractFileTypeLocalVo localVo = getServiceBean().findByType(
Desktop.instance.getActiveEmployee().localeProperty().get(), item);
return localVo;
}
```
### 5.2 自定义显示格式
当需要自定义实体的显示格式时,重写 `format()` 方法:
```java
@Override
public String format(ContractFileTypeLocalVo entity) {
if (entity == null) {
return null;
}
return entity.getValue();
}
```
## 6. 工厂方法模式
所有 TableCell 类都应提供静态的 `forTableColumn()` 工厂方法,用于创建单元格工厂回调:
- 无参数版本:`public static <S> Callback<TableColumn<S, T>, TableCell<S, T>> forTableColumn()`
- 带服务参数版本:`public static <S> Callback<TableColumn<S, T>, TableCell<S, T>> forTableColumn(ServiceType service)`
## 7. 代码规范
- 使用 Lombok 注解(如 `@NoArgsConstructor`)简化代码
- 添加适当的 JavaDoc 注释
- 遵循 JavaFX 最佳实践
- 处理空值和异常情况
- 确保线程安全UI 更新在 JavaFX 应用线程执行
## 8. 实现检查清单
创建新的 TableCell 时,请检查以下项目:
- [ ] 类名符合 `*TableCell` 命名规范
- [ ] 放置在正确的包路径下
- [ ] 选择合适的基类TableCell、AsyncUpdateTableCell
- [ ] 实现必要的构造函数
- [ ] 实现或重写 `updateItem()` 方法
- [ ] 提供静态的 `forTableColumn()` 工厂方法
- [ ] 对于异步更新类型,实现 `getServiceBean()` 或提供服务注入
- [ ] 添加适当的注释
- [ ] 处理空值和异常情况
## 9. 示例实现
### 9.1 简单数据类型 TableCell
参考 `NumberTableCell.java``LocalDateFieldTableCell.java`
### 9.2 实体引用 TableCell
参考 `CompanyTableCell.java``ContractTableCell.java`
### 9.3 特殊处理 TableCell
参考 `ContractFileTypeTableCell.java`