import { tableConfig } from './tableConfig' function extractRecords(obj, fields) { for (const field of fields) { if (field in obj && Array.isArray(obj[field])) { return obj[field] } } return [] } function extractTotal(obj, records, fields) { for (const field of fields) { if (field in obj && typeof obj[field] === 'number') { return obj[field] } } return records.length } function extractPagination(obj, data) { const result = {} const sources = [obj, data ?? {}] const currentFields = tableConfig.currentFields for (const src of sources) { for (const field of currentFields) { if (field in src && typeof src[field] === 'number') { result.current = src[field] break } } if (result.current !== void 0) break } const sizeFields = tableConfig.sizeFields for (const src of sources) { for (const field of sizeFields) { if (field in src && typeof src[field] === 'number') { result.size = src[field] break } } if (result.size !== void 0) break } if (result.current === void 0 && result.size === void 0) return void 0 return result } const defaultResponseAdapter = (response) => { const recordFields = tableConfig.recordFields if (!response) { return { records: [], total: 0 } } if (Array.isArray(response)) { return { records: response, total: response.length } } if (typeof response !== 'object') { console.warn( '[tableUtils] 无法识别的响应格式,支持的格式包括: 数组、包含' + recordFields.join('/') + '字段的对象、嵌套data对象。当前格式:', response ) return { records: [], total: 0 } } const res = response let records = [] let total = 0 let pagination records = extractRecords(res, recordFields) total = extractTotal(res, records, tableConfig.totalFields) pagination = extractPagination(res) if (records.length === 0 && 'data' in res && typeof res.data === 'object') { const data = res.data records = extractRecords(data, ['list', 'records', 'items']) total = extractTotal(data, records, tableConfig.totalFields) pagination = extractPagination(res, data) if (Array.isArray(res.data)) { records = res.data total = records.length } } if (!recordFields.some((field) => field in res) && records.length === 0) { console.warn('[tableUtils] 无法识别的响应格式') console.warn('支持的字段包括: ' + recordFields.join('、'), response) console.warn('扩展字段请到 utils/table/tableConfig 文件配置') } const result = { records, total } if (pagination) { Object.assign(result, pagination) } return result } const extractTableData = (response) => { const data = response.records || response.data || [] return Array.isArray(data) ? data : [] } const updatePaginationFromResponse = (pagination, response) => { pagination.total = response.total ?? pagination.total ?? 0 if (response.current !== void 0) { pagination.current = response.current } const maxPage = Math.max(1, Math.ceil(pagination.total / (pagination.size || 1))) if (pagination.current > maxPage) { pagination.current = maxPage } } const createSmartDebounce = (fn, delay) => { let timeoutId = null let lastArgs = null let lastResolve = null let lastReject = null const debouncedFn = (...args) => { return new Promise((resolve, reject) => { if (timeoutId) clearTimeout(timeoutId) lastArgs = args lastResolve = resolve lastReject = reject timeoutId = setTimeout(async () => { try { const result = await fn(...args) resolve(result) } catch (error) { reject(error) } finally { timeoutId = null lastArgs = null lastResolve = null lastReject = null } }, delay) }) } debouncedFn.cancel = () => { if (timeoutId) clearTimeout(timeoutId) timeoutId = null lastArgs = null lastResolve = null lastReject = null } debouncedFn.flush = async () => { if (timeoutId && lastArgs && lastResolve && lastReject) { clearTimeout(timeoutId) timeoutId = null const args = lastArgs const resolve = lastResolve const reject = lastReject lastArgs = null lastResolve = null lastReject = null try { const result = await fn(...args) resolve(result) return result } catch (error) { reject(error) throw error } } return Promise.resolve() } return debouncedFn } const createErrorHandler = (onError, enableLog = false) => { const logger = { error: (message, ...args) => { if (enableLog) console.error(`[useTable] ${message}`, ...args) } } return (err, context) => { const tableError = { code: 'UNKNOWN_ERROR', message: '未知错误', details: err } if (err instanceof Error) { tableError.message = err.message tableError.code = err.name } else if (typeof err === 'string') { tableError.message = err } logger.error(`${context}:`, err) onError?.(tableError) return tableError } } export { createErrorHandler, createSmartDebounce, defaultResponseAdapter, extractTableData, updatePaginationFromResponse }