# 金蝶云星空旗舰版插件生命周期

## 表单插件生命周期 (AbstractBillPlugIn)

### 生命周期顺序

```
表单打开
  ↓
afterLoadData() - 加载数据后
  ↓
afterCreateNewDataEntity() - 新建数据实体后
  ↓
用户操作
  ↓
afterPropertyChanged() - 字段值变更后
  ↓
beforeSave() - 保存前
  ↓
afterSave() - 保存后
  ↓
beforeSubmit() - 提交前
  ↓
afterSubmit() - 提交后
  ↓
beforeAudit() - 审核前
  ↓
afterAudit() - 审核后
  ↓
表单关闭
```

### 关键事件详解

#### afterLoadData - 数据加载后

**触发时机：** 表单数据从数据库加载完成后

**用途：**
- 初始化界面控件
- 计算派生字段
- 设置字段可见性

**示例：**
```java
@Override
public void afterLoadData(EventObject e) {
    super.afterLoadData(e);
    
    // 获取数据实体
    DynamicObject dataEntity = this.getModel().getDataEntity();
    
    // 初始化界面
    this.getView().setVisible(true, "field1");
    this.getView().setEnable(false, "field2");
}
```

#### afterPropertyChanged - 字段值变更后

**触发时机：** 用户修改字段值后

**用途：**
- 联动计算
- 数据验证
- 界面刷新

**示例：**
```java
@Override
public void afterPropertyChanged(PropertyChangedArgs e) {
    String fieldKey = e.getProperty().getName();
    
    if ("qty".equals(fieldKey)) {
        // 数量变更后计算金额
        BigDecimal qty = (BigDecimal) e.getNewValue();
        BigDecimal price = this.getModel().getValue("price");
        BigDecimal amount = qty.multiply(price);
        this.getModel().setValue("amount", amount);
    }
}
```

#### beforeSave - 保存前

**触发时机：** 用户点击保存按钮后，数据保存到数据库前

**用途：**
- 数据校验
- 自动生成编号
- 设置默认值

**示例：**
```java
@Override
public void beforeSave(BeforeSaveEventArgs e) {
    // 校验必填字段
    DynamicObject dataEntity = this.getModel().getDataEntity();
    String billNo = dataEntity.getString("billno");
    
    if (StringUtils.isEmpty(billNo)) {
        e.setCancel(true);
        this.getView().showErrorNotification("单据编号不能为空");
        return;
    }
    
    // 自动生成编号
    if ("AUTO".equals(billNo)) {
        String newBillNo = generateBillNo();
        dataEntity.set("billno", newBillNo);
    }
}
```

---

## 操作插件生命周期 (AbstractOperatePlugin)

### 生命周期顺序

```
操作触发
  ↓
onGetValidateRules() - 获取校验规则
  ↓
beforeExecuteOperationTransaction() - 操作执行前
  ↓
executeOperationTransaction() - 执行操作（事务内）
  ↓
afterExecuteOperationTransaction() - 操作执行后
  ↓
操作完成
```

### 关键事件详解

#### beforeExecuteOperationTransaction - 操作执行前

**触发时机：** 操作事务开始前

**用途：**
- 业务规则校验
- 数据预处理
- 权限检查

**示例：**
```java
@Override
public void beforeExecuteOperationTransaction(BeforeExecuteOperationTransactionArgs e) {
    String operateKey = e.getOperateKey();
    
    if ("submit".equals(operateKey)) {
        // 提交前校验
        DynamicObject[] dataEntities = e.getDataEntities();
        for (DynamicObject entity : dataEntities) {
            BigDecimal amount = entity.getBigDecimal("amount");
            if (amount.compareTo(BigDecimal.ZERO) <= 0) {
                e.setCancel(true);
                throw new KDException("", "金额必须大于零");
            }
        }
    }
}
```

#### afterExecuteOperationTransaction - 操作执行后

**触发时机：** 操作事务提交后

**用途：**
- 触发下游业务
- 发送通知
- 记录日志

**示例：**
```java
@Override
public void afterExecuteOperationTransaction(AfterExecuteOperationTransactionArgs e) {
    String operateKey = e.getOperateKey();
    
    if ("audit".equals(operateKey)) {
        // 审核后触发下游业务
        DynamicObject[] dataEntities = e.getDataEntities();
        for (DynamicObject entity : dataEntities) {
            triggerDownstreamBusiness(entity);
        }
    }
}
```

---

## 校验插件生命周期 (AbstractValidatePlugin)

### 生命周期顺序

```
数据提交
  ↓
onGetValidateRules() - 获取校验规则
  ↓
validate() - 执行校验
  ↓
校验结果
```

### 示例

```java
public class AmountValidatePlugin extends AbstractValidatePlugin {
    
    @Override
    public void onGetValidateRules(GetValidateRulesEventArgs e) {
        // 添加校验规则
        e.addValidateRule("amount", "金额必须大于零");
    }
    
    @Override
    public void validate(ValidateEventArgs e) {
        DynamicObject dataEntity = e.getDataEntity();
        BigDecimal amount = dataEntity.getBigDecimal("amount");
        
        if (amount.compareTo(BigDecimal.ZERO) <= 0) {
            e.addError("amount", "金额必须大于零");
        }
    }
}
```

---

## 列表插件生命周期 (AbstractListPlugin)

### 常用事件

```java
// 列表加载后
public void afterLoadData(EventObject e)

// 行选中后
public void afterRowClick(AfterRowClickEventArgs e)

// 列表操作前
public void beforeDoOperation(BeforeDoOperationEventArgs e)

// 列表操作后
public void afterDoOperation(AfterDoOperationEventArgs e)
```
