field.js 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. import _ from 'lodash-es'
  2. import { nanoid } from './nanoid'
  3. const fieldsRe = /^(input|textarea|number|radio|checkbox|select|time|date|rate|switch|slider|html|cascader|uploadfile|signature|region|subform)$/
  4. const deepTraversal = (node, fn) => {
  5. fn(node)
  6. const nodes = node.type === 'subform' ? node.list[0] : (node.list || node.rows || node.columns || node.children || [])
  7. nodes.forEach(e => {
  8. deepTraversal(e, fn)
  9. })
  10. }
  11. const wrapElement = (element, fn) => {
  12. const result = element
  13. deepTraversal(result, (node) => {
  14. if (Array.isArray(node)) return false
  15. if (!node.style) {
  16. node.style = {}
  17. }
  18. if (!node.id) {
  19. // node.id = nanoid()
  20. node.id = new Date().getTime()
  21. }
  22. if (!node.key) {
  23. node.key = `${node.type}${node.id}`
  24. }
  25. if (/^(grid|tabs|collapse|table|divider)$/.test(node.type)) {
  26. node.style = {
  27. width: '100%'
  28. }
  29. }
  30. if (checkIsField(node)) {
  31. node.style = {
  32. width: {
  33. pc: '100%',
  34. mobile: '100%'
  35. }
  36. }
  37. }
  38. if (/^(tabs)$/.test(node.type)) {
  39. node.columns = new Array(3).fill('').map((e, index) => {
  40. const data = renderFieldData('tabsCol')
  41. data.label = `Tab ${index + 1}`
  42. data.options = {}
  43. return data
  44. })
  45. }
  46. if (/^(collapse)$/.test(node.type)) {
  47. node.columns = new Array(3).fill('').map((e, index) => {
  48. const data = renderFieldData('collapseCol')
  49. data.label = `Tab ${index + 1}`
  50. data.options = {}
  51. return data
  52. })
  53. }
  54. fn && fn(node)
  55. })
  56. return result
  57. }
  58. const renderFieldData = (type) => {
  59. const result = {
  60. id: nanoid(),
  61. type,
  62. label: '',
  63. list: [],
  64. style: {}
  65. }
  66. return result
  67. }
  68. const excludes = ['grid', 'col', 'table', 'tr', 'td', 'tabs', 'tabsCol', 'collapse', 'collapseCol', 'divider', 'inline']
  69. const flatNodes = (nodes, excludes, fn, excludesFn) => {
  70. return nodes.reduce((res, node, currentIndex) => {
  71. if (excludes.indexOf(node.type) === -1) {
  72. res.push(node)
  73. fn && fn(nodes, node, currentIndex)
  74. } else {
  75. excludesFn && excludesFn(nodes, node, currentIndex)
  76. }
  77. const children = node.type === 'subform' ? node.list[0] : (node.list || node.rows || node.columns || node.children || [])
  78. res = res.concat(flatNodes(children, excludes, fn, excludesFn))
  79. return res
  80. }, [])
  81. }
  82. const getAllFields = (store) => flatNodes(store, excludes)
  83. const pickfields = (list) => {
  84. return flatNodes(list, excludes)
  85. }
  86. const processField = (list) => flatNodes(list, excludes, (nodes, node, currentIndex) => {
  87. nodes[currentIndex] = node.id
  88. })
  89. const disassemblyData1 = (data) => {
  90. const result = {
  91. list: data.list,
  92. config: data.config,
  93. fields: processField(data.list),
  94. data: data.data,
  95. logic: data.logic
  96. }
  97. return result
  98. }
  99. const combinationData1 = (data) => {
  100. const result = {
  101. list: data.list,
  102. config: data.config,
  103. data: data.data,
  104. fields: data.fields,
  105. logic: data.logic
  106. }
  107. const fn = (nodes, node, currentIndex) => {
  108. const cur = _.find(data.fields, { id: node })
  109. if (!_.isEmpty(cur)) {
  110. if (cur.type === 'subform') {
  111. flatNodes(cur.list[0], excludes, fn)
  112. }
  113. nodes[currentIndex] = cur
  114. }
  115. }
  116. flatNodes(data.list, excludes, fn)
  117. return result
  118. }
  119. const combinationData2 = (list, fields) => {
  120. const fn = (nodes, node, currentIndex) => {
  121. const cur = _.find(fields, { id: node })
  122. if (!_.isEmpty(cur)) {
  123. if (cur.type === 'subform') {
  124. flatNodes(cur.list[0], excludes, fn)
  125. }
  126. nodes[currentIndex] = cur
  127. }
  128. }
  129. flatNodes(list, excludes, fn)
  130. }
  131. const repairLayout = (layout, fields) => {
  132. flatNodes(layout, excludes, (nodes, node, currentIndex) => {
  133. if (_.isString(node)) {
  134. if (!_.isEmpty(_.find(fields, { id: node }))) {
  135. nodes.splice(currentIndex, 1)
  136. }
  137. }
  138. })
  139. const temporary = []
  140. flatNodes(layout, excludes, null, (nodes, node, currentIndex) => {
  141. if (node.type === 'inline') {
  142. if (!node.columns.length) {
  143. temporary.unshift({
  144. nodes,
  145. currentIndex
  146. })
  147. }
  148. }
  149. })
  150. temporary.forEach(e => {
  151. e.nodes.splice(e.currentIndex, 1)
  152. })
  153. }
  154. const disassemblyData2 = (list) => {
  155. flatNodes(list, excludes, (nodes, node, currentIndex) => {
  156. nodes[currentIndex] = node.id && node.id
  157. })
  158. }
  159. const checkIslineChildren = (node) => node.context.parent.type === 'inline'
  160. const checkIsField = (node) => fieldsRe.test(node.type)
  161. const calculateAverage = (count, total = 100) => {
  162. const base = Number((total / count).toFixed(2))
  163. const result = []
  164. for (let i = 0; i < count; i++) {
  165. // result.push(base + (i < rest ? 1 : 0))
  166. result.push(base)
  167. }
  168. return result
  169. }
  170. const syncWidthByPlatform = (node, platform, syncFullplatform = false, value) => {
  171. // debugger
  172. const isArray = _.isArray(node)
  173. if (!isArray) {
  174. if (_.isObject(node.style.width)) {
  175. if (syncFullplatform) {
  176. node.style.width.pc = node.style.width.mobile = value + '%'
  177. } else {
  178. node.style.width[platform] = value + '%'
  179. }
  180. } else {
  181. node.style.width = value + '%'
  182. }
  183. }
  184. const otherNodes = isArray ? node : node.context.parent.columns.filter(e => e !== node)
  185. const averageWidths = calculateAverage(otherNodes.length, isArray ? 100 : 100 - value)
  186. otherNodes.forEach((node, index) => {
  187. const isFieldWidth = _.isObject(node.style.width)
  188. if (isFieldWidth) {
  189. if (syncFullplatform) {
  190. node.style.width.pc = node.style.width.mobile = averageWidths[index] + '%'
  191. } else {
  192. node.style.width[platform] = averageWidths[index] + '%'
  193. }
  194. } else {
  195. node.style.width = averageWidths[index] + '%'
  196. }
  197. })
  198. }
  199. const transferLabelPath = (node) => {
  200. const inputTypeFlag = node.type === 'input' // input框
  201. const selectTypeFlag = node.type === 'select' // select框
  202. const cascaderTypeFlag = node.type === 'cascader' // cascader
  203. let defaultFields = ''
  204. if (inputTypeFlag || selectTypeFlag || cascaderTypeFlag) {
  205. defaultFields = `${node.type}.${node.options.renderType - 1}`
  206. } else {
  207. defaultFields = `${node.type}`
  208. }
  209. return `er.fields.${defaultFields}`
  210. }
  211. const fieldLabel = (t, node) => t(transferLabelPath(node))
  212. const transferData = (lang, path, locale, options = {}) => {
  213. let result = ''
  214. if (_.isEmpty(options)) {
  215. result = _.get(locale[lang], path, '')
  216. } else {
  217. result = _.template(_.get(locale[lang], path, ''))(options)
  218. }
  219. return result
  220. }
  221. const isNull = (e) => e === '' || e === null || e === undefined
  222. const checkIsInSubform = (node) => {
  223. if (!node) return false
  224. let result = false
  225. let parent = node.context.parent
  226. while (parent && !result) {
  227. if (parent.type === 'subform') {
  228. result = true
  229. }
  230. parent = parent.context?.parent
  231. }
  232. return result
  233. }
  234. const getSubFormValues = (subform) => subform.list.map(e => {
  235. const cur = {}
  236. const children = []
  237. e.forEach(e => {
  238. e.columns.forEach(e => {
  239. children.push(e)
  240. })
  241. })
  242. children.forEach(e => {
  243. cur[e.key] = e.options.defaultValue
  244. })
  245. return cur
  246. })
  247. const findSubFormAllFields = (subform) => {
  248. const result = []
  249. subform.list.forEach(e => {
  250. e.forEach(e => {
  251. result.push(...e.columns)
  252. })
  253. })
  254. return result
  255. }
  256. export {
  257. syncWidthByPlatform,
  258. wrapElement,
  259. deepTraversal,
  260. renderFieldData,
  261. getAllFields,
  262. disassemblyData1,
  263. combinationData1,
  264. disassemblyData2,
  265. combinationData2,
  266. checkIslineChildren,
  267. checkIsField,
  268. pickfields,
  269. fieldLabel,
  270. transferData,
  271. transferLabelPath,
  272. isNull,
  273. repairLayout,
  274. checkIsInSubform,
  275. getSubFormValues,
  276. findSubFormAllFields,
  277. processField
  278. }