# FlameFramework attrFields onChange 支持修改文档

## 问题描述

FlameFramework 的 `attrFields` 配置中的 `props.onChange` 回调无法被触发，导致级联选择（项目 → 表 → 字段）无法在属性面板中实现。

## 问题根因

### 文件：`/Users/albert/Workspaces/poba/flame-plus/src/packages/components/complex/flmForm/flmForm.vue`

在 `controlDom` 函数（约第 215-266 行）中：

```javascript
const controlDom = (
  prop: string,
  controlType: ControlTypes,
  controlConfig: ControlConfig
) => {
  const config: FormModel = { ...controlConfig }
  const event = controlType === ControlTypes['flmInput'] ? 'onInput' : 'onChange'
  config[event] = (value: any) => formChange(value, prop)  // ⚠️ 这里覆盖了原有的 onChange
  config['modelValue'] = formModel[prop]
  // ...
}
```

**问题**：`flmForm` 在渲染控件时，**强制覆盖**了 `onChange`/`onInput` 事件处理器，导致 `attrFields.props` 中传入的 `onChange` 回调被替换，永远不会被调用。

## 修改方案

### 方案一：保留原有 onChange 并链式调用（推荐）

修改 `flmForm.vue` 中的 `controlDom` 函数：

```javascript
const controlDom = (
  prop: string,
  controlType: ControlTypes,
  controlConfig: ControlConfig
) => {
  const config: FormModel = { ...controlConfig }
  const event = controlType === ControlTypes['flmInput'] ? 'onInput' : 'onChange'

  // 保存原有的 onChange/onInput 回调
  const originalHandler = controlConfig[event]

  // 链式调用：先调用内部 formChange，再调用原有回调
  config[event] = (value: any) => {
    formChange(value, prop)
    if (typeof originalHandler === 'function') {
      originalHandler(value)
    }
  }

  config['modelValue'] = formModel[prop]

  // ... 后续代码保持不变
}
```

### 方案二：新增 `onValueChange` 专用回调属性

在 `types.ts` 中扩展 `AttrFieldConfig`：

```typescript
// /Users/albert/Workspaces/poba/flame-plus/src/packages/components/framework/types.ts

export interface AttrFieldConfig {
  key: string
  label: string
  component: AttrFieldComponent
  props?: Record<string, unknown>
  /** 值变化时的回调，不同于 props.onChange，此回调不会被覆盖 */
  onValueChange?: (value: unknown, model: Record<string, unknown>) => void
  visible?: (model: Record<string, unknown>) => boolean
}
```

然后在 `FrameworkAttrFieldsForm.vue` 中处理：

```javascript
// FrameworkAttrFieldsForm.vue

const formItems = computed(() => {
  return visibleFields.value
    .filter((f) => componentToControlType[f.component])
    .map((f) => {
      const controlType = componentToControlType[f.component] as ControlTypes
      return {
        prop: f.key,
        label: f.label,
        controlType,
        controlConfig: {
          ...(f.props ?? {}),
          'model-value': shadowModel[f.key],
          // 传递 onValueChange 回调
          _onValueChange: f.onValueChange
        }
      }
    })
})
```

然后在 `flmForm.vue` 中调用：

```javascript
config[event] = (value: any) => {
  formChange(value, prop)
  // 调用自定义回调
  if (typeof controlConfig._onValueChange === 'function') {
    controlConfig._onValueChange(value, formModel)
  }
}
```

## 推荐方案：方案一

方案一修改最小，只需修改 `flmForm.vue` 一个文件，且保持向后兼容。

## 修改步骤

### Step 1: 修改 flmForm.vue

文件路径：`/Users/albert/Workspaces/poba/flame-plus/src/packages/components/complex/flmForm/flmForm.vue`

找到 `controlDom` 函数（约第 215 行），修改如下：

```javascript
const controlDom = (
  prop: string,
  controlType: ControlTypes,
  controlConfig: ControlConfig
) => {
  const config: FormModel = { ...controlConfig }
  const event = controlType === ControlTypes['flmInput'] ? 'onInput' : 'onChange'

  // ====== 新增：保存并链式调用原有回调 ======
  const originalHandler = controlConfig[event]
  config[event] = (value: any) => {
    // 1. 内部表单状态更新
    formChange(value, prop)
    // 2. 调用外部传入的回调（如果有）
    if (typeof originalHandler === 'function') {
      originalHandler(value)
    }
  }
  // ====== 修改结束 ======

  config['modelValue'] = formModel[prop]

  // ... 后续代码保持不变
}
```

### Step 2: 重新构建 flame-plus

```bash
cd /Users/albert/Workspaces/poba/flame-plus
pnpm run build
```

### Step 3: 更新 gmp-frontend 依赖

```bash
cd /Users/albert/Workspaces/gmp/gmp-frontend/gmp-platform
pnpm update flame-plus
```

## 验证方式

修改完成后，在 `MasterForm.vue` 的 `attrFields` 中使用 `onChange`：

```typescript
attrFields: [
  {
    key: 'config.projectName',
    label: '项目',
    component: 'select',
    props: {
      placeholder: '请选择项目',
      filterable: true,
      options: PROJECT_OPTIONS,
      onChange: (val: string) => {
        console.log('项目已选择:', val)
        if (val) loadTableOptions(val)
      }
    }
  },
  // ...
]
```

当用户在属性面板中选择项目时，控制台应输出 `项目已选择: xxx`，并且 `loadTableOptions` 应被调用。

## 相关文件

| 文件 | 说明 |
|------|------|
| `/Users/albert/Workspaces/poba/flame-plus/src/packages/components/complex/flmForm/flmForm.vue` | 核心修改文件 |
| `/Users/albert/Workspaces/poba/flame-plus/src/packages/components/framework/components/FrameworkAttrFieldsForm.vue` | attrFields 渲染组件 |
| `/Users/albert/Workspaces/poba/flame-plus/src/packages/components/framework/types.ts` | 类型定义 |
