# Spec: Excel Import/Export with EasyExcel

## ADDED Requirements

### Requirement: 流式导出大量数据

The system **MUST** support streaming export using EasyExcel to handle datasets exceeding 100,000 rows while maintaining low memory footprint.

系统**必须**支持使用 EasyExcel 进行流式导出，以处理超过 10 万行的数据集，同时保持低内存占用。

#### Scenario: 导出 10 万行用户数据

**Given** 系统中有 10 万条用户记录

**When** 管理员调用用户导出接口

**Then** 系统应：
- 成功生成包含 10 万行数据的 Excel 文件
- 内存占用不超过 500MB
- 导出时间在合理范围内（< 30 秒）
- 生成的文件包含所有必要的表头和样式

#### Scenario: 导出超过 65536 行数据

**Given** 数据集包含 10 万行记录（超过传统 Excel 限制）

**When** 调用导出功能

**Then** 系统应：
- 自动使用 .xlsx 格式
- 不进行 Sheet 分割（EasyExcel 自动处理）
- 所有数据完整导出到单个文件

---

### Requirement: 流式导入大文件

The system **MUST** support streaming import using EasyExcel to process Excel files larger than 100MB.

系统**必须**支持使用 EasyExcel 进行流式读取，以处理超过 100MB 的 Excel 文件。

#### Scenario: 导入包含 10 万行数据的 Excel 文件

**Given** 一个包含 10 万行数据的 Excel 文件（约 50MB）

**When** 管理员上传该文件进行导入

**Then** 系统应：
- 逐行解析文件，不一次性加载到内存
- 内存占用不超过 200MB
- 正确解析所有数据行
- 返回完整的解析结果列表

#### Scenario: 导入包含超长文本的单元格

**Given** Excel 文件中某些单元格包含超过 32,767 个字符（超过 POI 限制）

**When** 执行导入操作

**Then** 系统应：
- 完整读取单元格内容
- 不截断或丢失数据
- 正确映射到实体类字段

---

### Requirement: 保持注解驱动配置兼容性

The system **MUST** maintain compatibility with existing `@Excel` and `@Excels` annotations, allowing existing entity classes to work without modification.

系统**必须**保持与现有 `@Excel` 和 `@Excels` 注解的兼容性，使现有实体类无需修改即可使用新实现。

#### Scenario: 使用现有注解导出数据

**Given** 实体类上已定义 `@Excel` 注解

```java
@Excel(name = "用户名", sort = 1)
private String userName;

@Excel(name = "性别", dictType = "sys_user_sex", sort = 2)
private String sex;

@Excel(name = "创建时间", dateFormat = "yyyy-MM-dd HH:mm:ss", sort = 3)
private Date createTime;
```

**When** 调用导出功能

**Then** 系统应：
- 正确解析 `@Excel` 注解配置
- 按指定的 `sort` 顺序排列列
- 应用字典转换（`dictType`）
- 应用日期格式化（`dateFormat`）
- 生成包含正确表头的 Excel 文件

#### Scenario: 使用复合注解导出嵌套属性

**Given** 实体类使用 `@Excels` 注解配置多个导出规则

```java
@Excels({
    @Excel(name = "部门名称", targetAttr = "deptName", sort = 10),
    @Excel(name = "部门编码", targetAttr = "deptCode", sort = 11)
})
private SysDept dept;
```

**When** 调用导出功能

**Then** 系统应：
- 正确解析嵌套对象属性
- 生成多个对应的列
- 正确填充数据

---

### Requirement: 样式与格式支持

The system **SHALL** support basic cell styling configuration through annotations, including alignment, background color, etc.

系统**应当**支持通过注解配置基本的单元格样式，包括对齐方式、背景色等。

#### Scenario: 应用自定义样式

**Given** 实体类定义了样式配置

```java
@Excel(
    name = "金额",
    align = HorizontalAlignmentEnum.RIGHT,
    backgroundColor = "yellow",
    color = "red",
    sort = 5
)
private BigDecimal amount;
```

**When** 导出数据

**Then** 系统应：
- 单元格内容右对齐
- 背景色为黄色
- 字体颜色为红色

#### Scenario: 数字格式化

**Given** 字段配置了精度和舍入模式

```java
@Excel(name = "单价", scale = 2, roundingMode = BigDecimal.ROUND_HALF_UP)
private BigDecimal price;
```

**When** 导出包含该字段的数据

**Then** 系统应：
- 数值保留 2 位小数
- 使用四舍五入规则

---

### Requirement: 导入模板生成

The system **MUST** support generating empty import templates for users to fill and upload.

系统**必须**支持生成空的导入模板，供用户填写后上传。

#### Scenario: 生成导入模板

**Given** 实体类配置了 `@Excel` 注解，其中部分字段标记为仅导入

```java
@Excel(name = "用户名", type = Type.ALL)
private String userName;

@Excel(name = "密码", type = Type.IMPORT)  // 仅导入
private String password;
```

**When** 调用 `importTemplateExcel()` 方法

**Then** 系统应：
- 生成包含所有 `type=IMPORT` 或 `type=ALL` 字段的表头
- 仅导入字段（`type=IMPORT`）不出现在模板中
- 应用数据验证配置（如果有）
- 设置合适的列宽

---

### Requirement: 字段筛选功能

The system **MUST** support runtime control of exported fields.

系统**必须**支持运行时动态控制导出包含的字段。

#### Scenario: 显示指定字段

**Given** 实体类有 20 个字段，但只想导出其中 5 个

**When** 调用 `util.showColumn("id", "name", "email", "phone", "status")`

**Then** 导出的 Excel 应：
- 仅包含指定的 5 个字段
- 其他字段不出现在导出结果中

#### Scenario: 排除指定字段

**Given** 实体类有 20 个字段，想导出其中 18 个

**When** 调用 `util.hideColumn("password", "salt")`

**Then** 导出的 Excel 应：
- 包含除 `password` 和 `salt` 外的所有字段
- 敏感字段不出现在导出结果中

---

### Requirement: 自定义数据处理器

The system **MUST** support custom data handlers for special cell data processing.

系统**必须**支持通过自定义处理器对单元格数据进行特殊处理。

#### Scenario: 使用自定义处理器格式化数据

**Given** 定义了自定义处理器

```java
public class CustomAmountHandler implements ExcelHandlerAdapter {
    @Override
    public Object format(Object value, String[] args, Cell cell, Workbook wb) {
        // 将金额转换为中文大写
        return convertToChinese((BigDecimal) value);
    }
}
```

**And** 实体字段配置使用该处理器

```java
@Excel(name = "金额(大写)", handler = CustomAmountHandler.class)
private BigDecimal amount;
```

**When** 导出数据

**Then** 金额列应显示为中文大写形式（如：壹万贰仟叁佰肆拾伍元陆角柒分）

---

### Requirement: 数据验证支持

The system **SHALL** support configuring dropdown options and prompt information for import templates.

系统**应当**支持为导入模板配置下拉选项和提示信息。

#### Scenario: 配置下拉选项

**Given** 字段配置了固定的下拉选项

```java
@Excel(name = "状态", combo = {"启用", "禁用"})
private String status;
```

**When** 生成导入模板

**Then** 该单元格应：
- 显示下拉箭头
- 仅能选择"启用"或"禁用"
- 无法输入其他值

#### Scenario: 从字典读取下拉选项

**Given** 字段配置从字典读取选项

```java
@Excel(name = "性别", dictType = "sys_user_sex", comboReadDict = true)
private String sex;
```

**When** 生成导入模板

**Then** 该单元格的下拉列表应：
- 包含字典中定义的所有选项
- 动态从系统缓存读取

---

## MODIFIED Requirements

### Requirement: ExcelUtil API 兼容性

The modified `ExcelUtil` **MUST** maintain API compatibility with existing code.

修改后的 `ExcelUtil` **必须**保持与现有代码的 API 兼容性。

#### Scenario: 使用现有导出方法

**Given** 现有 Controller 代码

```java
List<SysUser> list = userService.selectUserList(user);
ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
util.exportExcel(response, list, "用户数据");
```

**When** 替换为 EasyExcel 实现

**Then** 代码应无需修改即可正常工作

#### Scenario: 使用现有导入方法

**Given** 现有导入代码

```java
ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
List<SysUser> userList = util.importExcel(file.getInputStream());
```

**When** 替换为 EasyExcel 实现

**Then** 代码应无需修改即可正常工作

---

## REMOVED Requirements

### 无

此变更不删除任何现有功能需求，仅替换底层实现。
