formCreate.ts 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. /**
  2. * 针对 https://github.com/xaboy/form-create-designer 封装的工具类
  3. */
  4. import { isRef } from 'vue'
  5. // 编码表单 Conf
  6. export const encodeConf = (designerRef: object) => {
  7. // @ts-ignore
  8. return JSON.stringify(designerRef.value.getOption())
  9. }
  10. // 编码表单 Fields
  11. export const encodeFields = (designerRef: object) => {
  12. // @ts-ignore
  13. const rule = JSON.parse(designerRef.value.getJson())
  14. const fields: string[] = []
  15. rule.forEach((item) => {
  16. fields.push(JSON.stringify(item))
  17. })
  18. return fields
  19. }
  20. // 解码表单 Fields
  21. export const decodeFields = (fields: string[]) => {
  22. const rule: object[] = []
  23. fields.forEach((item) => {
  24. rule.push(JSON.parse(item))
  25. })
  26. return rule
  27. }
  28. // 设置表单的 Conf 和 Fields,适用 FcDesigner 场景
  29. export const setConfAndFields = (designerRef: object, conf: string, fields: string) => {
  30. // @ts-ignore
  31. designerRef.value.setOption(JSON.parse(conf))
  32. // @ts-ignore
  33. designerRef.value.setRule(decodeFields(fields))
  34. }
  35. // 设置表单的 Conf 和 Fields,适用 form-create 场景
  36. export const setConfAndFields2 = (
  37. detailPreview: object,
  38. conf: string,
  39. fields: string[],
  40. value?: object
  41. ) => {
  42. if (isRef(detailPreview)) {
  43. // @ts-ignore
  44. detailPreview = detailPreview.value
  45. }
  46. // 修复所有函数类型(解决设计器保存后函数变成字符串的问题)。例如说:
  47. // https://t.zsxq.com/rADff
  48. // https://t.zsxq.com/ZfbGt
  49. // https://t.zsxq.com/mHOoj
  50. // https://t.zsxq.com/BSylB
  51. const option = JSON.parse(conf)
  52. const rule = decodeFields(fields)
  53. // 🔧 修复所有函数类型 - 解决设计器保存后函数变成字符串的问题
  54. const fixFunctions = (obj: any) => {
  55. if (obj && typeof obj === 'object') {
  56. Object.keys(obj).forEach((key) => {
  57. // 检查是否是函数相关的属性
  58. if (isFunctionProperty(key)) {
  59. // 如果不是函数类型,重新构建为函数
  60. if (typeof obj[key] !== 'function') {
  61. obj[key] = createDefaultFunction(key)
  62. }
  63. } else if (typeof obj[key] === 'object' && obj[key] !== null) {
  64. // 递归处理嵌套对象
  65. fixFunctions(obj[key])
  66. }
  67. })
  68. }
  69. }
  70. // 判断是否是函数属性
  71. const isFunctionProperty = (key: string): boolean => {
  72. const functionKeys = [
  73. 'beforeFetch', // 请求前处理
  74. 'afterFetch', // 请求后处理
  75. 'onSubmit', // 表单提交
  76. 'onReset', // 表单重置
  77. 'onChange', // 值变化
  78. 'onInput', // 输入事件
  79. 'onClick', // 点击事件
  80. 'onFocus', // 获取焦点
  81. 'onBlur', // 失去焦点
  82. 'onMounted', // 组件挂载
  83. 'onCreated', // 组件创建
  84. 'onReload', // 重新加载
  85. 'remoteMethod', // 远程搜索方法
  86. 'parseFunc', // 解析函数
  87. 'validator', // 验证器
  88. 'asyncValidator', // 异步验证器
  89. 'formatter', // 格式化函数
  90. 'parser', // 解析函数
  91. 'beforeUpload', // 上传前处理
  92. 'onSuccess', // 成功回调
  93. 'onError', // 错误回调
  94. 'onProgress', // 进度回调
  95. 'onPreview', // 预览回调
  96. 'onRemove', // 移除回调
  97. 'onExceed', // 超出限制回调
  98. 'filterMethod', // 过滤方法
  99. 'sortMethod', // 排序方法
  100. 'loadData', // 加载数据
  101. 'renderContent', // 渲染内容
  102. 'render' // 渲染函数
  103. ]
  104. // 检查是否以函数相关前缀开头
  105. const functionPrefixes = ['on', 'before', 'after', 'handle']
  106. return functionKeys.includes(key) || functionPrefixes.some((prefix) => key.startsWith(prefix))
  107. }
  108. // 根据函数名创建默认函数
  109. const createDefaultFunction = (key: string): Function => {
  110. switch (key) {
  111. case 'beforeFetch':
  112. return (config: any) => {
  113. // 添加 Token 认证头。例如说:
  114. // https://t.zsxq.com/hK3FO
  115. const token = localStorage.getItem('token')
  116. if (token) {
  117. config.headers = {
  118. ...config.headers,
  119. Authorization: 'Bearer ' + token
  120. }
  121. }
  122. // 添加通用请求头
  123. config.headers = {
  124. ...config.headers,
  125. 'Content-Type': 'application/json',
  126. 'X-Requested-With': 'XMLHttpRequest'
  127. }
  128. // 添加时间戳防止缓存
  129. config.params = {
  130. ...config.params,
  131. _t: Date.now()
  132. }
  133. return config
  134. }
  135. case 'afterFetch':
  136. return (data: any) => {
  137. return data
  138. }
  139. case 'onSubmit':
  140. return (_formData: any) => {
  141. return true
  142. }
  143. case 'onReset':
  144. return () => {
  145. return true
  146. }
  147. case 'onChange':
  148. return (_value: any, _oldValue: any) => {}
  149. case 'remoteMethod':
  150. return (query: string) => {
  151. console.log('remoteMethod被调用:', query)
  152. }
  153. case 'parseFunc':
  154. return (data: any) => {
  155. // 默认解析逻辑:如果是数组直接返回,否则尝试获取list属性
  156. if (Array.isArray(data)) {
  157. return data
  158. }
  159. return data?.list || data?.data || []
  160. }
  161. case 'validator':
  162. return (_rule: any, _value: any, callback: Function) => {
  163. callback()
  164. }
  165. case 'beforeUpload':
  166. return (_file: any) => {
  167. return true
  168. }
  169. default:
  170. // 通用默认函数
  171. return (...args: any[]) => {
  172. // 对于事件处理函数,返回true表示继续执行
  173. if (key.startsWith('on') || key.startsWith('handle')) {
  174. return true
  175. }
  176. // 对于其他函数,返回第一个参数(通常是数据传递)
  177. return args[0]
  178. }
  179. }
  180. }
  181. // 修复 option 中的所有函数
  182. fixFunctions(option)
  183. // 修复 rule 中的所有函数(包括组件的 props)
  184. if (Array.isArray(rule)) {
  185. rule.forEach((item: any) => {
  186. fixFunctions(item)
  187. })
  188. }
  189. // @ts-ignore
  190. detailPreview.option = option
  191. // @ts-ignore
  192. detailPreview.rule = rule
  193. if (value) {
  194. // @ts-ignore
  195. detailPreview.value = value
  196. }
  197. }