wwf
6 小时以前 a1d7e81859f554f3a53680cc35f0f49bf1f77098
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
import {
  useDictSelectRule,
  useEditorRule,
  useSelectRule,
  useUploadFileRule,
  useUploadImgRule,
  useUploadImgsRule
} from './config'
import { Ref } from 'vue'
import { Menu } from '@/components/FormCreate/src/type'
import { apiSelectRule } from '@/components/FormCreate/src/config/selectRule'
import { generateUUID } from '@/utils'
 
/**
 * 表单设计器增强 hook
 * 新增
 * - 文件上传
 * - 单图上传
 * - 多图上传
 * - 字典选择器
 * - 用户选择器
 * - 部门选择器
 * - 富文本
 */
export const useFormCreateDesigner = async (designer: Ref) => {
  const editorRule = useEditorRule()
  const uploadFileRule = useUploadFileRule()
  const uploadImgRule = useUploadImgRule()
  const uploadImgsRule = useUploadImgsRule()
 
  /**
   * 构建表单组件
   */
  const buildFormComponents = () => {
    // 移除自带的上传组件规则,使用 uploadFileRule、uploadImgRule、uploadImgsRule 替代
    designer.value?.removeMenuItem('upload')
    // 移除自带的富文本组件规则,使用 editorRule 替代
    designer.value?.removeMenuItem('fcEditor')
    const components = [editorRule, uploadFileRule, uploadImgRule, uploadImgsRule]
    components.forEach((component) => {
      // 插入组件规则
      designer.value?.addComponent(component)
      // 插入拖拽按钮到 `main` 分类下
      designer.value?.appendMenuItem('main', {
        icon: component.icon,
        name: component.name,
        label: component.label
      })
    })
  }
 
  const userSelectRule = useSelectRule({
    name: 'UserSelect',
    label: '用户选择器',
    icon: 'icon-user-o'
  })
  const deptSelectRule = useSelectRule({
    name: 'DeptSelect',
    label: '部门选择器',
    icon: 'icon-address-card-o',
    props: [
      {
        type: 'select',
        field: 'returnType',
        title: '返回值类型',
        value: 'id',
        options: [
          { label: '部门编号', value: 'id' },
          { label: '部门名称', value: 'name' }
        ]
      }
    ]
  })
  const dictSelectRule = useDictSelectRule()
  const apiSelectRule0 = useSelectRule({
    name: 'ApiSelect',
    label: '接口选择器',
    icon: 'icon-server',
    props: [...apiSelectRule],
    event: ['click', 'change', 'visibleChange', 'clear', 'blur', 'focus']
  })
 
  /**
   * 构建系统字段菜单
   */
  const buildSystemMenu = () => {
    // 移除自带的下拉选择器组件,使用 currencySelectRule 替代
    // designer.value?.removeMenuItem('select')
    // designer.value?.removeMenuItem('radio')
    // designer.value?.removeMenuItem('checkbox')
    const components = [userSelectRule, deptSelectRule, dictSelectRule, apiSelectRule0]
    const menu: Menu = {
      name: 'system',
      title: '系统字段',
      list: components.map((component) => {
        // 插入组件规则
        designer.value?.addComponent(component)
        // 插入拖拽按钮到 `system` 分类下
        return {
          icon: component.icon,
          name: component.name,
          label: component.label
        }
      })
    }
    designer.value?.addMenu(menu)
  }
 
  /**
   * 修复重复的字段 ID 问题
   * 当复制组件时,自动为新组件生成新的字段 ID
   *
   * 对应 issue:https://gitee.com/yudaocode/yudao-ui-admin-vue3/issues/ICM22X
   */
  const fixDuplicateFields = () => {
    // 获取当前所有规则
    const rules = designer.value?.getRule() || []
    const fieldIds = new Set<string>()
    let hasChanges = false
 
    // 遍历所有规则,检测并修复重复的字段 ID
    rules.forEach((rule: any) => {
      if (rule.field) {
        if (fieldIds.has(rule.field)) {
          // 发现重复,生成新的ID
          const oldField = rule.field
          const newField = generateUUID()
          console.log(`[FormCreate] 检测到重复字段ID: ${oldField}, 已自动更新为: ${newField}`)
          rule.field = newField
          hasChanges = true
        } else {
          fieldIds.add(rule.field)
        }
      }
    })
 
    // 如果有重复字段被修复,更新设计器
    if (hasChanges) {
      designer.value?.setRule(rules)
    }
 
    return hasChanges
  }
 
  onMounted(async () => {
    await nextTick()
    buildFormComponents()
    buildSystemMenu()
 
    // 监听设计器内容变化,自动修复重复字段ID
    let isFixing = false // 防止无限循环
    watch(
      () => designer.value?.getRule(),
      async () => {
        if (!isFixing) {
          isFixing = true
          await nextTick()
          fixDuplicateFields()
          isFixing = false
        }
      },
      { deep: true }
    )
  })
}