/** * 数据源管线 —— schema 默认值生成、深度合并、绑定路径过滤、OADate 格式化 */ import dayjs from 'dayjs' import { is, formatterOADateNumber } from './spreadUtils' /** * 只过滤出当前 sheet 页需要的字段 */ export function getSheetBindingPathData(sheet, dataSource) { const boundFields = new Set() const tableMap = new Map() for (let row = 0; row < sheet.getRowCount(); row++) { for (let col = 0; col < sheet.getColumnCount(); col++) { const bindingPath = sheet.getBindingPath(row, col) if (bindingPath) { boundFields.add(bindingPath) } } } const tables = sheet.tables.all() || [] if (tables.length > 0) { tables.forEach(function (table) { const tableName = table.bindingPath() boundFields.add(tableName) const tableBoundFields = new Set() const columnCount = table.range().colCount for (let i = 0; i < columnCount; i++) { const field = table.getColumnDataField(i) if (field) { tableBoundFields.add(field) } } tableMap.set(tableName, [...tableBoundFields]) }) } const boundFieldsArray = [...boundFields].filter(Boolean) if (boundFieldsArray.length === 0) return {} function recombineDataSource(dataSourceObj, prekey, boundFieldsArray) { const filterResult = {} for (const key in dataSourceObj) { if (is(dataSourceObj[key], 'Object')) { const nextKey = !prekey ? key : `${prekey}.${key}` if (boundFieldsArray.findIndex((field) => field.indexOf(nextKey) >= 0) >= 0) { filterResult[key] = recombineDataSource(dataSourceObj[key], nextKey, boundFieldsArray) } continue } if (is(dataSourceObj[key], 'Array') && dataSourceObj[key].every((x) => is(x, 'Object'))) { if (boundFieldsArray.includes(key)) { filterResult[key] = Object.entries(dataSourceObj[key]).map(([i, item]) => { if (is(item, 'String')) return item const tableBoundFieldArrays = tableMap.get(key) return recombineDataSource(item, '', tableBoundFieldArrays) }) } continue } if (boundFieldsArray.includes(!prekey ? key : `${prekey}.${key}`)) { filterResult[key] = dataSourceObj[key] } } return filterResult } const newDataSource = recombineDataSource(dataSource, '', boundFieldsArray) boundFields.clear() tableMap.clear() return newDataSource } /** * 生成属性键,并填充对应默认值 */ export function generateDefaultData(schema) { const result = {} for (const key in schema.properties) { result[key] = generatePropertyDefaultValue(schema.properties[key]) } return result } /** * 为属性填充默认值 */ export function generatePropertyDefaultValue(property) { if (property.type === 'array' && property.items) { if (property.items.type !== 'object' || !property.items.properties) { return [''] } const itemValue = {} for (const itemKey in property.items.properties) { itemValue[itemKey] = generatePropertyDefaultValue(property.items.properties[itemKey]) } return [itemValue] } if (property.properties) { const objValue = {} for (const objKey in property.properties) { objValue[objKey] = generatePropertyDefaultValue(property.properties[objKey]) } return objValue } return '' } /** * 为属性填充非默认数据值 * @param target 属性值为默认值的键值数据容器 * @param source 填充数据到键值容器的数据源头 */ export function deepMergeSchemaValue(target, source) { const result = { ...target } for (const key in source) { if (source.hasOwnProperty(key)) { const targetValue = target[key] const sourceValue = source[key] if (targetValue === undefined) { continue } if (Array.isArray(targetValue) && Array.isArray(sourceValue)) { result[key] = sourceValue.length > 0 ? sourceValue : targetValue } else if ( typeof targetValue === 'object' && targetValue !== null && typeof sourceValue === 'object' && sourceValue !== null ) { result[key] = Object.keys(sourceValue).length === 0 ? targetValue : deepMergeSchemaValue(targetValue, sourceValue) } else if (sourceValue !== undefined && sourceValue !== '') { const trimmedSourceValue = sourceValue.trim() // JSON字符串需要解析为对象或数组 if ( typeof trimmedSourceValue === 'string' && (trimmedSourceValue.startsWith('{') || trimmedSourceValue.startsWith('[')) ) { result[key] = JSON.parse(trimmedSourceValue) } else { result[key] = trimmedSourceValue } } } } return result } /** * 遍历数据源,将 OADate 格式或 Date 对象统一格式化为 "YYYY年MM月DD日" */ export function generateAndReturnDataSourceOADate(dataSource) { if (!is(dataSource, 'Object') && !is(dataSource, 'Array')) return {} if (is(dataSource, 'Object')) { for (const key in dataSource) { if (is(dataSource[key], 'String') && dataSource[key].indexOf('OADate') >= 0) { dataSource[key] = dayjs(formatterOADateNumber(dataSource[key])).format('YYYY年MM月DD日') continue } else if (is(dataSource[key], 'Date')) { dataSource[key] = dayjs(dataSource[key]).format('YYYY年MM月DD日') continue } if (is(dataSource[key], 'Object') || is(dataSource[key], 'Array')) { dataSource[key] = generateAndReturnDataSourceOADate(dataSource[key]) continue } } } if (is(dataSource, 'Array')) { return dataSource.map((keyItem) => { if (is(keyItem, 'String') && keyItem.indexOf('OADate') >= 0) { return dayjs(formatterOADateNumber(keyItem)).format('YYYY年MM月DD日') } if (is(keyItem, 'Object') || is(keyItem, 'Array')) { return generateAndReturnDataSourceOADate(keyItem) } return keyItem }) } return dataSource }