dataSourceProcessor.ts 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /**
  2. * 数据源管线 —— schema 默认值生成、深度合并、绑定路径过滤、OADate 格式化
  3. */
  4. import dayjs from 'dayjs'
  5. import { is, formatterOADateNumber } from './spreadUtils'
  6. /**
  7. * 只过滤出当前 sheet 页需要的字段
  8. */
  9. export function getSheetBindingPathData(sheet, dataSource) {
  10. const boundFields = new Set()
  11. const tableMap = new Map()
  12. for (let row = 0; row < sheet.getRowCount(); row++) {
  13. for (let col = 0; col < sheet.getColumnCount(); col++) {
  14. const bindingPath = sheet.getBindingPath(row, col)
  15. if (bindingPath) {
  16. boundFields.add(bindingPath)
  17. }
  18. }
  19. }
  20. const tables = sheet.tables.all() || []
  21. if (tables.length > 0) {
  22. tables.forEach(function (table) {
  23. const tableName = table.bindingPath()
  24. boundFields.add(tableName)
  25. const tableBoundFields = new Set()
  26. const columnCount = table.range().colCount
  27. for (let i = 0; i < columnCount; i++) {
  28. const field = table.getColumnDataField(i)
  29. if (field) {
  30. tableBoundFields.add(field)
  31. }
  32. }
  33. tableMap.set(tableName, [...tableBoundFields])
  34. })
  35. }
  36. const boundFieldsArray = [...boundFields].filter(Boolean)
  37. if (boundFieldsArray.length === 0) return {}
  38. function recombineDataSource(dataSourceObj, prekey, boundFieldsArray) {
  39. const filterResult = {}
  40. for (const key in dataSourceObj) {
  41. if (is(dataSourceObj[key], 'Object')) {
  42. const nextKey = !prekey ? key : `${prekey}.${key}`
  43. if (boundFieldsArray.findIndex((field) => field.indexOf(nextKey) >= 0) >= 0) {
  44. filterResult[key] = recombineDataSource(dataSourceObj[key], nextKey, boundFieldsArray)
  45. }
  46. continue
  47. }
  48. if (is(dataSourceObj[key], 'Array') && dataSourceObj[key].every((x) => is(x, 'Object'))) {
  49. if (boundFieldsArray.includes(key)) {
  50. filterResult[key] = Object.entries(dataSourceObj[key]).map(([i, item]) => {
  51. if (is(item, 'String')) return item
  52. const tableBoundFieldArrays = tableMap.get(key)
  53. return recombineDataSource(item, '', tableBoundFieldArrays)
  54. })
  55. }
  56. continue
  57. }
  58. if (boundFieldsArray.includes(!prekey ? key : `${prekey}.${key}`)) {
  59. filterResult[key] = dataSourceObj[key]
  60. }
  61. }
  62. return filterResult
  63. }
  64. const newDataSource = recombineDataSource(dataSource, '', boundFieldsArray)
  65. boundFields.clear()
  66. tableMap.clear()
  67. return newDataSource
  68. }
  69. /**
  70. * 生成属性键,并填充对应默认值
  71. */
  72. export function generateDefaultData(schema) {
  73. const result = {}
  74. for (const key in schema.properties) {
  75. result[key] = generatePropertyDefaultValue(schema.properties[key])
  76. }
  77. return result
  78. }
  79. /**
  80. * 为属性填充默认值
  81. */
  82. export function generatePropertyDefaultValue(property) {
  83. if (property.type === 'array' && property.items) {
  84. if (property.items.type !== 'object' || !property.items.properties) {
  85. return ['']
  86. }
  87. const itemValue = {}
  88. for (const itemKey in property.items.properties) {
  89. itemValue[itemKey] = generatePropertyDefaultValue(property.items.properties[itemKey])
  90. }
  91. return [itemValue]
  92. }
  93. if (property.properties) {
  94. const objValue = {}
  95. for (const objKey in property.properties) {
  96. objValue[objKey] = generatePropertyDefaultValue(property.properties[objKey])
  97. }
  98. return objValue
  99. }
  100. return ''
  101. }
  102. /**
  103. * 为属性填充非默认数据值
  104. * @param target 属性值为默认值的键值数据容器
  105. * @param source 填充数据到键值容器的数据源头
  106. */
  107. export function deepMergeSchemaValue(target, source) {
  108. const result = { ...target }
  109. for (const key in source) {
  110. if (source.hasOwnProperty(key)) {
  111. const targetValue = target[key]
  112. const sourceValue = source[key]
  113. if (targetValue === undefined) {
  114. continue
  115. }
  116. if (Array.isArray(targetValue) && Array.isArray(sourceValue)) {
  117. result[key] = sourceValue.length > 0 ? sourceValue : targetValue
  118. } else if (
  119. typeof targetValue === 'object' &&
  120. targetValue !== null &&
  121. typeof sourceValue === 'object' &&
  122. sourceValue !== null
  123. ) {
  124. result[key] =
  125. Object.keys(sourceValue).length === 0
  126. ? targetValue
  127. : deepMergeSchemaValue(targetValue, sourceValue)
  128. } else if (sourceValue !== undefined && sourceValue !== '') {
  129. const trimmedSourceValue = sourceValue.trim()
  130. // JSON字符串需要解析为对象或数组
  131. if (
  132. typeof trimmedSourceValue === 'string' &&
  133. (trimmedSourceValue.startsWith('{') || trimmedSourceValue.startsWith('['))
  134. ) {
  135. result[key] = JSON.parse(trimmedSourceValue)
  136. } else {
  137. result[key] = trimmedSourceValue
  138. }
  139. }
  140. }
  141. }
  142. return result
  143. }
  144. /**
  145. * 遍历数据源,将 OADate 格式或 Date 对象统一格式化为 "YYYY年MM月DD日"
  146. */
  147. export function generateAndReturnDataSourceOADate(dataSource) {
  148. if (!is(dataSource, 'Object') && !is(dataSource, 'Array')) return {}
  149. if (is(dataSource, 'Object')) {
  150. for (const key in dataSource) {
  151. if (is(dataSource[key], 'String') && dataSource[key].indexOf('OADate') >= 0) {
  152. dataSource[key] = dayjs(formatterOADateNumber(dataSource[key])).format('YYYY年MM月DD日')
  153. continue
  154. } else if (is(dataSource[key], 'Date')) {
  155. dataSource[key] = dayjs(dataSource[key]).format('YYYY年MM月DD日')
  156. continue
  157. }
  158. if (is(dataSource[key], 'Object') || is(dataSource[key], 'Array')) {
  159. dataSource[key] = generateAndReturnDataSourceOADate(dataSource[key])
  160. continue
  161. }
  162. }
  163. }
  164. if (is(dataSource, 'Array')) {
  165. return dataSource.map((keyItem) => {
  166. if (is(keyItem, 'String') && keyItem.indexOf('OADate') >= 0) {
  167. return dayjs(formatterOADateNumber(keyItem)).format('YYYY年MM月DD日')
  168. }
  169. if (is(keyItem, 'Object') || is(keyItem, 'Array')) {
  170. return generateAndReturnDataSourceOADate(keyItem)
  171. }
  172. return keyItem
  173. })
  174. }
  175. return dataSource
  176. }