# 金蝶云星空企业版插件生命周期

## 操作服务插件生命周期 (AbstractOperationServicePlugIn)

### 生命周期顺序

```
操作触发
  ↓
OnPreparePropertys() - 准备属性
  ↓
OnAddValidateRules() - 添加校验规则
  ↓
BeforeExecuteOperationTransaction() - 操作执行前
  ↓
ExecuteOperationTransaction() - 执行操作（事务内）
  ↓
AfterExecuteOperationTransaction() - 操作执行后
  ↓
操作完成
```

### 关键事件详解

#### OnPreparePropertys - 准备属性

**触发时机：** 操作开始前，用于指定需要加载的字段

**用途：**
- 指定需要访问的字段
- 优化数据加载性能

**示例：**
```csharp
public override void OnPreparePropertys(PreparePropertysEventArgs e)
{
    // 添加需要访问的字段
    e.FieldKeys.Add("FQty");
    e.FieldKeys.Add("FPrice");
    e.FieldKeys.Add("FAmount");
}
```

#### BeforeExecuteOperationTransaction - 操作执行前

**触发时机：** 操作事务开始前

**用途：**
- 业务规则校验
- 数据预处理
- 权限检查

**示例：**
```csharp
public override void BeforeExecuteOperationTransaction(BeforeExecuteOperationTransaction e)
{
    string operateKey = e.OperateKey;
    
    if (operateKey == "Submit")
    {
        // 提交前校验
        foreach (var entity in e.DataEntitys)
        {
            decimal amount = Convert.ToDecimal(entity["FAmount"] ?? 0);
            if (amount <= 0)
            {
                throw new KDException("", "金额必须大于零");
            }
        }
    }
}
```

#### AfterExecuteOperationTransaction - 操作执行后

**触发时机：** 操作事务提交后

**用途：**
- 触发下游业务
- 发送通知
- 记录日志

**示例：**
```csharp
public override void AfterExecuteOperationTransaction(AfterExecuteOperationTransaction e)
{
    string operateKey = e.OperateKey;
    
    if (operateKey == "Audit")
    {
        // 审核后触发下游业务
        foreach (var entity in e.DataEntitys)
        {
            TriggerDownstreamBusiness(entity);
        }
    }
}
```

---

## 表单插件生命周期 (AbstractBillPlugIn)

### 生命周期顺序

```
表单打开
  ↓
AfterBindData() - 绑定数据后
  ↓
用户操作
  ↓
AfterPropertyChanged() - 字段值变更后
  ↓
BeforeSave() - 保存前
  ↓
AfterSave() - 保存后
  ↓
表单关闭
```

### 示例

```csharp
public class OrderPlugin : AbstractBillPlugIn
{
    public override void AfterBindData(EventArgs e)
    {
        // 初始化界面
        this.View.Visible = true;
        this.View.SetControlValue("FStatus", "A");
    }
    
    public override void AfterPropertyChanged(PropertyChangedEventArgs e)
    {
        if (e.Property.Name == "FQty")
        {
            // 数量变更后计算金额
            decimal qty = Convert.ToDecimal(e.NewValue);
            decimal price = Convert.ToDecimal(this.Model.GetValue("FPrice"));
            decimal amount = qty * price;
            this.Model.SetValue("FAmount", amount);
        }
    }
    
    public override void BeforeSave(BeforeSaveEventArgs e)
    {
        // 校验必填字段
        var dataEntity = this.Model.DataEntity;
        string billNo = dataEntity["FBillNo"] as string;
        
        if (string.IsNullOrEmpty(billNo))
        {
            e.Cancel = true;
            this.View.ShowErrorNotification("单据编号不能为空");
            return;
        }
    }
}
```

---

## 校验插件生命周期 (AbstractOperationCheckPlugIn)

### 示例

```csharp
public class AmountCheckPlugin : AbstractOperationCheckPlugIn
{
    public override void OnAddValidateRules(AddValidateRulesEventArgs e)
    {
        // 添加校验规则
        e.AddValidateRule("FAmount", "金额必须大于零");
    }
    
    public override void Validate(ValidateEventArgs e)
    {
        var dataEntity = e.DataEntity;
        decimal amount = Convert.ToDecimal(dataEntity["FAmount"] ?? 0);
        
        if (amount <= 0)
        {
            e.AddError("FAmount", "金额必须大于零");
        }
    }
}
```
