@whynotsnow/dynamic-form
Version:
DynamicForm 是一个基于 React 和 Ant Design 的动态表单组件,支持复杂的表单联动、自定义处理器、状态管理和性能优化。
1 lines • 146 kB
Source Map (JSON)
{"version":3,"sources":["../src/components/FormContent.tsx","../src/hooks/useStateSync.ts","../src/utils/logger.ts","../src/utils/utils.ts","../config/defaultConfig.ts","../src/resultProcessor/handlers.ts","../src/utils/initializationChecker.ts","../src/hooks/useStoreInit.ts","../src/resultProcessor/core.ts","../src/resultProcessor/init.ts","../src/resultProcessor/batchUpdate.ts","../src/configProcessor/configParser.ts","../src/reducer.ts","../src/hooks/useFormChainContext.ts","../src/hooks/useInitHandlers.ts","../src/fieldComponentRegistry.tsx","../src/fieldComponentRenderer.tsx","../src/components/FormChainEffectEngineWrapper.tsx","../src/index.tsx"],"sourcesContent":["import React, { useMemo } from 'react';\nimport { Form, Button, Card, Row, Col } from 'antd';\nimport type { FormContentProps, FieldState, GroupField, GroupFieldState } from '../types';\nimport { useFormChainContext } from '../hooks';\nimport { log, LogCategory } from '../utils/logger';\nimport { ComponentRegistryManager } from '../fieldComponentRegistry';\nimport FieldComponentRenderer from '../fieldComponentRenderer';\n\nconst FormContent: React.FC<FormContentProps> = (props) => {\n const {\n onSubmit,\n submitButtonText,\n componentRegistry,\n renderFormInner,\n renderFieldItem,\n renderGroupItem,\n renderFields,\n renderGroups,\n form\n } = props;\n // 获取默认配置\n\n // 合并用户配置和默认配置\n const finalSubmitButtonText = submitButtonText ?? '提交';\n\n const { state, onValuesChange, syncFormStateToStore } = useFormChainContext();\n const { dynamicUIConfig, fieldValues, initialized, fields, groupFields } = state;\n\n // 创建组件注册器实例\n const registryManager = useMemo(() => {\n if (componentRegistry) {\n return new ComponentRegistryManager(componentRegistry);\n }\n return null;\n }, [componentRegistry]);\n\n const handleFinish = (values: Record<string, any>) => {\n log.info(LogCategory.FORM, '表单提交:', values, form.getFieldsValue());\n onSubmit?.(values);\n };\n\n const handleFinishValuesChange = (\n changedValues: Record<string, any>,\n allValues: Record<string, any>\n ) => {\n syncFormStateToStore(changedValues, allValues);\n\n form.validateFields(Object.keys(changedValues));\n // effect chain Run\n onValuesChange?.(changedValues);\n };\n\n /** 单字段渲染(最小单元,必须兜底) */\n const internalRenderFieldItem = (field: FieldState) => {\n if (!initialized || field.meta?.visible === false) return null;\n\n const defaultRender = (\n <FieldComponentRenderer\n key={field.id}\n field={field}\n form={form}\n fieldValue={fieldValues[field.id]}\n componentRegistry={registryManager}\n dynamicUIConfig={dynamicUIConfig}\n />\n );\n\n if (renderFieldItem) {\n return renderFieldItem({\n field,\n form,\n fieldValue: fieldValues[field.id],\n renderField: internalRenderFieldItem, // 递归给自己\n defaultRender\n });\n }\n\n return defaultRender;\n };\n\n /** 一组字段渲染(提供 renderFieldItem 能力) */\n const internalRenderFields = (fieldsArr: FieldState[]) => {\n const defaultRender = (\n <Row {...dynamicUIConfig.rowProps}>\n {fieldsArr.map((field) => {\n if (!initialized || field.meta?.visible === false) return null;\n return (\n <Col\n key={field.id}\n {...dynamicUIConfig.colProps}\n span={field.span || dynamicUIConfig.colProps?.span}\n >\n {internalRenderFieldItem(field)}\n </Col>\n );\n })}\n </Row>\n );\n\n return renderFields\n ? renderFields({\n fields: fieldsArr,\n renderFieldItem: internalRenderFieldItem,\n defaultRender\n })\n : defaultRender;\n };\n\n /** 单个分组渲染(提供 renderFields / renderFieldItem 能力) */\n const internalRenderGroupItem = (group: GroupFieldState) => {\n if (group.meta?.visible === false) return null;\n\n const defaultRender = (\n <Card key={group.id} title={group.title ?? group.id} {...dynamicUIConfig.cardProps}>\n {internalRenderFields(Object.values(group.fields))}\n </Card>\n );\n\n return renderGroupItem\n ? renderGroupItem({\n group,\n dynamicUIConfig,\n renderFields: internalRenderFields,\n renderFieldItem: internalRenderFieldItem,\n defaultRender\n })\n : defaultRender;\n };\n\n /** 分组集合渲染(提供 renderGroupItem / renderFields / renderFieldItem 能力) */\n const internalRenderGroups = (groups: Record<string, GroupFieldState>) => {\n const defaultRender = Object.values(groups).map(internalRenderGroupItem);\n\n return renderGroups\n ? renderGroups({\n groupFields: groups,\n renderGroupItem: internalRenderGroupItem,\n renderFields: internalRenderFields,\n renderFieldItem: internalRenderFieldItem,\n defaultRender\n })\n : defaultRender;\n };\n\n /** 提交区渲染 */\n const internalRenderSubmit = () => (\n <div style={{ textAlign: 'center', marginTop: 24 }} {...dynamicUIConfig.submitAreaProps}>\n <Button type=\"primary\" htmlType=\"submit\" {...dynamicUIConfig.buttonProps}>\n {finalSubmitButtonText}\n </Button>\n </div>\n );\n\n /** 最终组装:优先分组,否则平铺字段 */\n const formBlocks = {\n fieldsArea:\n Object.keys(groupFields).length > 0\n ? internalRenderGroups(groupFields)\n : internalRenderFields(Object.values(fields)),\n submitArea: internalRenderSubmit()\n };\n\n const finalFormBody = renderFormInner ? (\n renderFormInner({\n form,\n fields,\n groupFields,\n dynamicUIConfig,\n renderGroups: internalRenderGroups,\n renderGroupItem: internalRenderGroupItem,\n renderFields: internalRenderFields,\n renderFieldItem: internalRenderFieldItem,\n defaultRender: formBlocks\n })\n ) : (\n <>\n {formBlocks.fieldsArea}\n {formBlocks.submitArea}\n </>\n );\n log.info(LogCategory.RENDER, 'render FormContent', state, form.getFieldsValue(true));\n\n return (\n <Form\n form={form}\n onFinish={handleFinish}\n onValuesChange={handleFinishValuesChange}\n initialValues={fieldValues}\n style={{ marginTop: 24 }}\n scrollToFirstError\n {...dynamicUIConfig.formProps}\n >\n {finalFormBody}\n </Form>\n );\n};\n\nexport default FormContent;\n","import { useEffect, useRef, useCallback } from 'react';\nimport type { FormInstance } from 'antd';\nimport type { FormState, FormAction } from '../types';\nimport { log, LogCategory } from '../utils/logger';\nimport { getValueByPath, deepEqual, setValueByPath, deepMerge } from '../utils';\n\nexport interface UseFormSyncProps {\n form: FormInstance;\n state: FormState;\n dispatch: React.Dispatch<FormAction>;\n}\n\nexport interface SyncStoreStateToFormOptions {\n stateValues: Record<string, any>;\n initialized: boolean;\n form: FormInstance;\n}\n\nexport function useStateSync({ form, state, dispatch }: UseFormSyncProps) {\n const pendingUpdatesRef = useRef<Record<string, any>>({});\n\n // 批量更新函数\n const batchDispatch = useCallback(() => {\n const updates = pendingUpdatesRef.current;\n if (Object.keys(updates).length === 0) return;\n\n log.info(LogCategory.EFFECT_RESULT, 'batchDispatch Run ', updates);\n\n // 分离值更新和元数据更新\n const valueUpdates = updates.values || {};\n const metaUpdates = updates.meta || {};\n\n // 调试:详细记录更新内容\n log.info(LogCategory.BATCH_UPDATE, '执行批量更新,详细数据:', {\n updates,\n valueUpdates,\n metaUpdates,\n currentState: state.fieldValues\n });\n\n dispatch({\n type: 'BATCH_UPDATE',\n payload: {\n values: valueUpdates,\n meta: metaUpdates\n }\n });\n\n // 清空待更新队列\n clearUpdateQueue();\n }, [dispatch]);\n\n // 清空队列函数(供外部调用)\n const clearUpdateQueue = useCallback(() => {\n pendingUpdatesRef.current = {};\n }, []);\n\n // OPTIMIZE 需要检查性能\n // 添加更新到队列\n const addToUpdateQueue = useCallback((key: string, value: any) => {\n if (key === 'values' || key === 'meta') {\n // 新的结构化方式\n if (!pendingUpdatesRef.current[key]) {\n pendingUpdatesRef.current[key] = {};\n }\n // 使用深合并代替浅合并\n deepMerge(pendingUpdatesRef.current[key], value);\n\n // 调试:记录添加到队列的内容\n log.info(LogCategory.BATCH_UPDATE, '添加到队列:', {\n key,\n value,\n currentQueue: pendingUpdatesRef.current\n });\n } else {\n // 向后兼容:直接设置值\n pendingUpdatesRef.current[key] = value;\n }\n }, []);\n\n // 检查是否有待更新的内容\n const hasPendingUpdates = useCallback(() => {\n return Object.keys(pendingUpdatesRef.current).length > 0;\n }, []);\n\n // 同步 React State 到 Form\n useEffect(() => {\n syncStoreStateToForm({\n stateValues: state.fieldValues,\n initialized: state.initialized,\n form\n });\n }, [state.fieldValues, state.initialized, form]);\n\n // OPTIMIZE 性能优化\n function syncStoreStateToForm({ stateValues, initialized, form }: SyncStoreStateToFormOptions) {\n if (!initialized) {\n log.debug(LogCategory.SYNC, '跳过同步:state 未初始化');\n return;\n }\n\n const formValues = form.getFieldsValue(true); // 获取表单的当前所有字段值\n const valuesToUpdate: Record<string, any> = {};\n let hasChanges = false;\n\n Object.entries(stateValues).forEach(([fieldPath, stateValue]) => {\n const formValue = getValueByPath(formValues, fieldPath);\n // 主要处理值类型的数据比较,对象类型默认需要同步\n if (!deepEqual(formValue, stateValue)) {\n setValueByPath(valuesToUpdate, fieldPath, stateValue);\n hasChanges = true;\n log.dataFlow(\n LogCategory.SYNC,\n `State(${JSON.stringify(stateValue)})`,\n `Form(${JSON.stringify(formValue)})`,\n fieldPath\n );\n }\n });\n\n if (hasChanges) {\n log.sync(LogCategory.SYNC, 'State→Form', valuesToUpdate);\n form.setFieldsValue(valuesToUpdate);\n } else {\n log.info(LogCategory.SYNC, '无需同步:所有值已一致');\n }\n }\n\n // 将表单值变化,同步到 React State\n const syncFormStateToStore = (\n changedValues: Record<string, any>,\n allValues: Record<string, any>\n ) => {\n // 收集所有需要更新的字段\n const updatedFields: string[] = [];\n Object.entries(changedValues).forEach(([fieldId, value]) => {\n const currentStateValue = state.fieldValues[fieldId];\n\n // 如果值发生了变化,则添加到更新队列,默认需要同步\n if (currentStateValue !== value) {\n log.dataFlow(LogCategory.SYNC, `Form(${value})`, `State(${currentStateValue})`, fieldId);\n\n const updatedFieldsValue = { [fieldId]: value };\n // 对象类型从allValue中获取所有值更新\n if (typeof value === 'object') {\n updatedFieldsValue[fieldId] = allValues[fieldId];\n }\n addToUpdateQueue('values', updatedFieldsValue);\n updatedFields.push(fieldId);\n }\n });\n\n if (updatedFields.length > 0) {\n log.info(LogCategory.BATCH_UPDATE, '执行表单值变化 导致的批量更新,字段:', updatedFields);\n // 执行批量更新\n batchDispatch();\n }\n };\n\n return {\n syncFormStateToStore,\n syncStoreStateToForm,\n batchDispatch,\n addToUpdateQueue,\n hasPendingUpdates,\n clearUpdateQueue\n };\n}\n","// 统一的日志管理工具\n\nexport enum LogLevel {\n DEBUG = 0,\n INFO = 1,\n WARN = 2,\n ERROR = 3\n}\n\nexport enum LogCategory {\n // 核心流程\n INIT = 'INIT',\n RENDER = 'RENDER',\n SYNC = 'SYNC',\n UPDATE = 'UPDATE',\n\n // 表单相关\n FORM = 'FORM',\n FIELD = 'FIELD',\n VALIDATION = 'VALIDATION',\n\n // 初始值计算相关\n INITIAL_VALUE = 'INITIAL_VALUE',\n\n // Effect 相关\n EFFECT = 'EFFECT',\n EFFECT_CHAIN = 'EFFECT_CHAIN',\n EFFECT_RESULT = 'EFFECT_RESULT',\n\n // 处理器生命周期相关\n HANDLER_LIFECYCLE = 'HANDLER_LIFECYCLE',\n HANDLER_REGISTRATION = 'HANDLER_REGISTRATION',\n HANDLER_EXECUTION = 'HANDLER_EXECUTION',\n HANDLER_VALIDATION = 'HANDLER_VALIDATION',\n\n // 性能相关\n PERFORMANCE = 'PERFORMANCE',\n BATCH_UPDATE = 'BATCH_UPDATE',\n PERFORMANCE_MONITOR = 'PERFORMANCE_MONITOR',\n\n // 调试相关\n DEBUG = 'DEBUG',\n STATE = 'STATE',\n DATA_FLOW = 'DATA_FLOW'\n}\n\ninterface LoggerConfig {\n level: LogLevel;\n enabledCategories: Set<LogCategory>;\n showTimestamp: boolean;\n showCategory: boolean;\n showLevel: boolean;\n}\n\nclass Logger {\n private config: LoggerConfig = {\n level: LogLevel.INFO,\n enabledCategories: new Set([\n // LogCategory.RENDER,\n // LogCategory.HANDLER_LIFECYCLE,\n // LogCategory.HANDLER_REGISTRATION,\n // LogCategory.HANDLER_EXECUTION,\n // LogCategory.HANDLER_VALIDATION\n ]),\n showTimestamp: true,\n showCategory: true,\n showLevel: false\n };\n private configShown = false;\n\n // 设置日志级别\n setLevel(level: LogLevel) {\n this.config.level = level;\n }\n\n // 启用/禁用特定分类\n enableCategory(category: LogCategory) {\n this.config.enabledCategories.add(category);\n }\n\n disableCategory(category: LogCategory) {\n this.config.enabledCategories.delete(category);\n }\n\n // 启用/禁用多个分类\n enableCategories(categories: LogCategory[]) {\n categories.forEach((cat) => this.config.enabledCategories.add(cat));\n }\n\n disableCategories(categories: LogCategory[]) {\n categories.forEach((cat) => this.config.enabledCategories.delete(cat));\n }\n\n // 设置显示选项\n setDisplayOptions(options: Partial<LoggerConfig>) {\n Object.assign(this.config, options);\n }\n\n // 获取当前启用的分类\n getEnabledCategories(): LogCategory[] {\n return Array.from(this.config.enabledCategories);\n }\n\n // 显示当前日志配置\n showCurrentConfig() {\n const enabledCategories = this.getEnabledCategories().join(', ');\n const configInfo = [\n `级别: ${LogLevel[this.config.level]}`,\n `分类: [${enabledCategories}]`,\n `时间戳: ${this.config.showTimestamp ? '✓' : '✗'}`,\n `分类标签: ${this.config.showCategory ? '✓' : '✗'}`,\n `级别标签: ${this.config.showLevel ? '✓' : '✗'}`\n ].join(' | ');\n\n console.log(`🔧 日志配置: ${configInfo}`);\n }\n\n // 重置配置显示状态,下次输出日志时会重新显示配置\n resetConfigDisplay() {\n this.configShown = false;\n }\n\n // 主动显示当前配置(用于应用启动时)\n showConfigOnStartup() {\n if (this.config.enabledCategories.size > 0) {\n this.showCurrentConfig();\n this.configShown = true;\n }\n }\n\n // 格式化日志前缀\n private formatPrefix(level: LogLevel, category: LogCategory): string {\n const parts: string[] = [];\n\n if (this.config.showTimestamp) {\n parts.push(new Date().toLocaleTimeString());\n }\n\n if (this.config.showLevel) {\n parts.push(`[${LogLevel[level]}]`);\n }\n\n if (this.config.showCategory) {\n // 为不同分类添加不同的图标\n const categoryIcon = this.getCategoryIcon(category);\n parts.push(`${categoryIcon} [${category}]`);\n }\n\n return parts.join(' ');\n }\n\n // 获取分类图标\n private getCategoryIcon(category: LogCategory): string {\n const iconMap: Record<LogCategory, string> = {\n [LogCategory.INIT]: '🚀',\n [LogCategory.RENDER]: '🎨',\n [LogCategory.SYNC]: '🔄',\n [LogCategory.UPDATE]: '📝',\n [LogCategory.FORM]: '📋',\n [LogCategory.FIELD]: '🏷️',\n [LogCategory.VALIDATION]: '✅',\n [LogCategory.INITIAL_VALUE]: '💡',\n [LogCategory.EFFECT]: '⚡',\n [LogCategory.EFFECT_CHAIN]: '🔗',\n [LogCategory.EFFECT_RESULT]: '🎯',\n [LogCategory.HANDLER_LIFECYCLE]: '🔧',\n [LogCategory.HANDLER_REGISTRATION]: '📝',\n [LogCategory.HANDLER_EXECUTION]: '⚙️',\n [LogCategory.HANDLER_VALIDATION]: '🔍',\n [LogCategory.PERFORMANCE]: '⚡',\n [LogCategory.BATCH_UPDATE]: '📦',\n [LogCategory.PERFORMANCE_MONITOR]: '📊',\n [LogCategory.DEBUG]: '🐛',\n [LogCategory.STATE]: '💾',\n [LogCategory.DATA_FLOW]: '🌊'\n };\n return iconMap[category] || '📄';\n }\n\n // 检查是否应该输出日志\n private shouldLog(level: LogLevel, category: LogCategory): boolean {\n return level >= this.config.level && this.config.enabledCategories.has(category);\n }\n\n // 日志输出方法\n private log(level: LogLevel, category: LogCategory, message: string, ...args: any[]) {\n if (!this.shouldLog(level, category)) return;\n\n // 在第一次输出日志之前显示配置\n if (!this.configShown && this.config.enabledCategories.size > 0) {\n this.showCurrentConfig();\n this.configShown = true;\n // 在配置信息后添加一个空行,让日志更清晰\n console.log('');\n }\n\n const prefix = this.formatPrefix(level, category);\n const fullMessage = `${prefix} ${message}`;\n\n switch (level) {\n case LogLevel.DEBUG:\n console.debug(fullMessage, ...args);\n break;\n case LogLevel.INFO:\n console.info(fullMessage, ...args);\n break;\n case LogLevel.WARN:\n console.warn(fullMessage, ...args);\n break;\n case LogLevel.ERROR:\n console.error(fullMessage, ...args);\n break;\n }\n }\n\n // 便捷方法\n debug(category: LogCategory, message: string, ...args: any[]) {\n this.log(LogLevel.DEBUG, category, message, ...args);\n }\n\n info(category: LogCategory, message: string, ...args: any[]) {\n this.log(LogLevel.INFO, category, message, ...args);\n }\n\n warn(category: LogCategory, message: string, ...args: any[]) {\n this.log(LogLevel.WARN, category, message, ...args);\n }\n\n error(category: LogCategory, message: string, ...args: any[]) {\n this.log(LogLevel.ERROR, category, message, ...args);\n }\n\n // 分组日志\n group(category: LogCategory, title: string, fn: () => void) {\n if (!this.shouldLog(LogLevel.INFO, category)) return;\n\n const prefix = this.formatPrefix(LogLevel.INFO, category);\n console.group(`${prefix} ${title}`);\n fn();\n console.groupEnd();\n }\n\n // 表格日志\n table(category: LogCategory, data: any, title?: string) {\n if (!this.shouldLog(LogLevel.INFO, category)) return;\n\n const prefix = this.formatPrefix(LogLevel.INFO, category);\n if (title) {\n console.log(`${prefix} ${title}`);\n }\n console.table(data);\n }\n\n // 状态日志\n state(category: LogCategory, stateName: string, state: any) {\n this.info(category, `${stateName}:`, state);\n }\n\n // 数据流日志\n dataFlow(category: LogCategory, from: string, to: string, data: any) {\n this.info(category, `${from} → ${to}:`, data);\n }\n\n // 性能日志\n performance(category: LogCategory, operation: string, duration: number) {\n this.info(category, `⚡ ${operation}: ${duration.toFixed(2)}ms`);\n }\n\n // 批量更新日志\n batchUpdate(category: LogCategory, updates: Record<string, any>) {\n this.info(category, `📦 批量更新:`, updates);\n }\n\n // Effect 日志\n effect(category: LogCategory, fieldName: string, value: any, result?: any) {\n if (result) {\n this.info(category, `Effect 【${fieldName}】字段:【${value}】 → ${JSON.stringify(result)}`);\n } else {\n this.info(category, `Effect 【${fieldName}】字段: 【${value}】`);\n }\n }\n\n // 字段渲染日志\n fieldRender(category: LogCategory, fieldId: string, componentType: string) {\n this.info(category, `🎨 渲染字段 ${fieldId} - 组件类型: ${componentType}`);\n }\n\n // 初始值计算日志\n initialValue(\n category: LogCategory,\n fieldId: string,\n value: any,\n type:\n | 'static'\n | 'function'\n | 'effect'\n | 'function-value'\n | 'function-visible'\n | 'function-disabled'\n | 'function-groupVisible'\n | 'function-other'\n | 'function-simple'\n ) {\n const typeText: Record<string, string> = {\n static: '静态初始值',\n function: '函数计算初始值',\n effect: 'Effect计算初始值',\n 'function-value': '函数计算-值',\n 'function-visible': '函数计算-可见性',\n 'function-disabled': '函数计算-禁用状态',\n 'function-groupVisible': '函数计算-分组可见性',\n 'function-other': '函数计算-其他属性',\n 'function-simple': '函数计算-简单值'\n };\n this.info(category, `字段 ${fieldId} ${typeText[type]}: ${value}`);\n }\n\n // 初始值计算过程日志\n initialValueProcess(category: LogCategory, fieldId: string, allValues: Record<string, any>) {\n this.info(category, `计算字段 ${fieldId} 的初始值`);\n }\n\n // 初始值最终结果日志\n initialValueResult(category: LogCategory, finalValues: Record<string, any>) {\n this.info(category, `最终初始值结果:`, finalValues);\n }\n\n // 同步日志\n sync(category: LogCategory, direction: 'Form→State' | 'State→Form', changes: any) {\n const directionIcon = direction === 'Form→State' ? '📤' : '📥';\n this.info(category, `${directionIcon} ${direction} 同步:`, changes);\n }\n\n // 性能监控日志\n performanceMonitor(\n category: LogCategory,\n operation: 'enable' | 'disable' | 'start' | 'end' | 'skip' | 'report' | 'compare',\n fieldId?: string,\n data?: any\n ) {\n const operationIcon: Record<string, string> = {\n enable: '🟢',\n disable: '🔴',\n start: '▶️',\n end: '⏹️',\n skip: '⏭️',\n report: '📊',\n compare: '⚖️'\n };\n\n const operationText: Record<string, string> = {\n enable: '启用性能监控',\n disable: '禁用性能监控',\n start: '开始渲染',\n end: '渲染完成',\n skip: '跳过渲染',\n report: '性能报告',\n compare: '性能对比'\n };\n\n const icon = operationIcon[operation];\n const text = operationText[operation];\n\n if (fieldId) {\n this.info(category, `${icon} ${text} - 字段: ${fieldId}`, data);\n } else {\n this.info(category, `${icon} ${text}`, data);\n }\n }\n\n // 渲染性能日志\n renderPerformance(\n category: LogCategory,\n fieldId: string,\n operation: 'start' | 'end' | 'skip',\n duration?: number\n ) {\n const operationIcon: Record<string, string> = {\n start: '▶️',\n end: '⏹️',\n skip: '⏭️'\n };\n\n const operationText: Record<string, string> = {\n start: '开始渲染',\n end: '渲染完成',\n skip: '跳过渲染'\n };\n\n const icon = operationIcon[operation];\n const text = operationText[operation];\n\n if (duration !== undefined) {\n this.info(category, `${icon} 字段 ${fieldId} ${text},耗时: ${duration.toFixed(2)}ms`);\n } else {\n this.info(category, `${icon} 字段 ${fieldId} ${text}`);\n }\n }\n\n // 性能报告日志\n performanceReport(\n category: LogCategory,\n metrics: {\n renderCount: number;\n skippedRenders: number;\n renderTime: number;\n optimizationRate: number;\n avgRenderTime: number;\n totalFields: number;\n duration: number;\n }\n ) {\n this.group(category, '🚀 渲染性能监控报告', () => {\n this.info(category, `⏱️ 监控时长: ${metrics.duration}ms`);\n this.info(category, `📈 总渲染次数: ${metrics.renderCount}`);\n this.info(category, `⏭️ 跳过渲染次数: ${metrics.skippedRenders}`);\n this.info(category, `📊 优化率: ${metrics.optimizationRate.toFixed(2)}%`);\n this.info(category, `⚡ 平均渲染时间: ${metrics.avgRenderTime.toFixed(2)}ms`);\n this.info(category, `📋 总字段数: ${metrics.totalFields}`);\n });\n }\n\n // 字段性能详情日志\n fieldPerformanceDetails(\n category: LogCategory,\n fieldMetrics: Record<string, { renderCount: number; skippedCount: number }>\n ) {\n this.group(category, '📊 字段详情', () => {\n Object.entries(fieldMetrics).forEach(([fieldId, metrics]) => {\n const renderIcon = metrics.renderCount > 0 ? '🎨' : '⚪';\n const skipIcon = metrics.skippedCount > 0 ? '⏭️' : '⚪';\n this.info(\n category,\n `${fieldId}: ${renderIcon}渲染${metrics.renderCount}次 ${skipIcon}跳过${metrics.skippedCount}次`\n );\n });\n });\n }\n\n // 处理器生命周期相关日志方法\n handlerRegistration(\n category: LogCategory,\n handlerName: string,\n description?: string,\n metadata?: Record<string, any>\n ) {\n this.info(category, `注册处理器: ${handlerName}`, {\n description,\n ...metadata\n });\n }\n\n handlerExecution(\n category: LogCategory,\n handlerName: string,\n operation: 'start' | 'end' | 'skip' | 'error',\n fieldName?: string,\n data?: any\n ) {\n const operationText = {\n start: '开始执行',\n end: '执行完成',\n skip: '跳过执行',\n error: '执行错误'\n }[operation];\n\n this.info(category, `${operationText}处理器: ${handlerName}`, {\n fieldName,\n data\n });\n }\n\n handlerValidation(\n category: LogCategory,\n handlerName: string,\n validation: 'pass' | 'fail' | 'skip',\n reason?: string,\n data?: any\n ) {\n const validationText = {\n pass: '验证通过',\n fail: '验证失败',\n skip: '跳过验证'\n }[validation];\n\n this.info(category, `${validationText}处理器: ${handlerName}`, {\n reason,\n data\n });\n }\n\n handlerLifecycle(\n category: LogCategory,\n handlerName: string,\n lifecycle: 'register' | 'unregister' | 'update' | 'init' | 'cleanup',\n metadata?: Record<string, any>\n ) {\n const lifecycleText = {\n register: '注册',\n unregister: '注销',\n update: '更新',\n init: '初始化',\n cleanup: '清理'\n }[lifecycle];\n\n this.info(category, `${lifecycleText}处理器: ${handlerName}`, metadata);\n }\n}\n\n// 创建全局日志实例\nexport const logger = new Logger();\n\n// 预设的日志配置\nexport const LogPresets = {\n // 只显示核心流程\n CORE_ONLY: () => {\n logger.enableCategories([\n LogCategory.INIT,\n LogCategory.RENDER,\n LogCategory.SYNC,\n LogCategory.UPDATE\n ]);\n },\n\n // 显示初始值计算\n INITIAL_VALUE_FOCUS: () => {\n logger.enableCategories([LogCategory.INIT, LogCategory.INITIAL_VALUE]);\n },\n\n // 显示表单相关\n FORM_FOCUS: () => {\n logger.enableCategories([\n LogCategory.FORM,\n LogCategory.FIELD,\n LogCategory.VALIDATION,\n LogCategory.SYNC\n ]);\n },\n\n // 显示 Effect 相关\n EFFECT_FOCUS: () => {\n logger.enableCategories([\n LogCategory.EFFECT,\n LogCategory.EFFECT_CHAIN,\n LogCategory.EFFECT_RESULT\n ]);\n },\n\n // 显示处理器生命周期相关\n HANDLER_FOCUS: () => {\n logger.enableCategories([\n LogCategory.HANDLER_LIFECYCLE,\n LogCategory.HANDLER_REGISTRATION,\n LogCategory.HANDLER_EXECUTION,\n LogCategory.HANDLER_VALIDATION\n ]);\n },\n\n // 显示性能相关\n PERFORMANCE_FOCUS: () => {\n logger.enableCategories([\n LogCategory.PERFORMANCE,\n LogCategory.BATCH_UPDATE,\n LogCategory.PERFORMANCE_MONITOR\n ]);\n },\n\n // 显示性能监控相关\n PERFORMANCE_MONITOR_FOCUS: () => {\n logger.enableCategories([LogCategory.PERFORMANCE_MONITOR, LogCategory.PERFORMANCE]);\n },\n\n // 显示所有日志\n ALL: () => {\n logger.enableCategories(Object.values(LogCategory));\n },\n\n // 静默模式\n SILENT: () => {\n logger.disableCategories(Object.values(LogCategory));\n }\n};\n\n// 便捷的日志方法\nexport const log = {\n debug: (category: LogCategory, message: string, ...args: any[]) =>\n logger.debug(category, message, ...args),\n\n info: (category: LogCategory, message: string, ...args: any[]) =>\n logger.info(category, message, ...args),\n\n warn: (category: LogCategory, message: string, ...args: any[]) =>\n logger.warn(category, message, ...args),\n\n error: (category: LogCategory, message: string, ...args: any[]) =>\n logger.error(category, message, ...args),\n\n group: (category: LogCategory, title: string, fn: () => void) =>\n logger.group(category, title, fn),\n\n table: (category: LogCategory, data: any, title?: string) => logger.table(category, data, title),\n\n state: (category: LogCategory, stateName: string, state: any) =>\n logger.state(category, stateName, state),\n\n dataFlow: (category: LogCategory, from: string, to: string, data: any) =>\n logger.dataFlow(category, from, to, data),\n\n performance: (category: LogCategory, operation: string, duration: number) =>\n logger.performance(category, operation, duration),\n\n batchUpdate: (category: LogCategory, updates: Record<string, any>) =>\n logger.batchUpdate(category, updates),\n\n effect: (category: LogCategory, fieldName: string, value: any, result?: any) =>\n logger.effect(category, fieldName, value, result),\n\n fieldRender: (category: LogCategory, fieldId: string, componentType: string) =>\n logger.fieldRender(category, fieldId, componentType),\n\n initialValue: (\n category: LogCategory,\n fieldId: string,\n value: any,\n type: 'static' | 'function' | 'effect'\n ) => logger.initialValue(category, fieldId, value, type),\n\n initialValueProcess: (category: LogCategory, fieldId: string, allValues: Record<string, any>) =>\n logger.initialValueProcess(category, fieldId, allValues),\n\n initialValueResult: (category: LogCategory, finalValues: Record<string, any>) =>\n logger.initialValueResult(category, finalValues),\n\n sync: (category: LogCategory, direction: 'Form→State' | 'State→Form', changes: any) =>\n logger.sync(category, direction, changes),\n\n // 性能监控相关\n performanceMonitor: (\n category: LogCategory,\n operation: 'enable' | 'disable' | 'start' | 'end' | 'skip' | 'report' | 'compare',\n fieldId?: string,\n data?: any\n ) => logger.performanceMonitor(category, operation, fieldId, data),\n\n renderPerformance: (\n category: LogCategory,\n fieldId: string,\n operation: 'start' | 'end' | 'skip',\n duration?: number\n ) => logger.renderPerformance(category, fieldId, operation, duration),\n\n performanceReport: (\n category: LogCategory,\n metrics: {\n renderCount: number;\n skippedRenders: number;\n renderTime: number;\n optimizationRate: number;\n avgRenderTime: number;\n totalFields: number;\n duration: number;\n }\n ) => logger.performanceReport(category, metrics),\n\n fieldPerformanceDetails: (\n category: LogCategory,\n fieldMetrics: Record<string, { renderCount: number; skippedCount: number }>\n ) => logger.fieldPerformanceDetails(category, fieldMetrics),\n\n // 处理器生命周期相关便捷方法\n handlerRegistration: (\n category: LogCategory,\n handlerName: string,\n description?: string,\n metadata?: Record<string, any>\n ) => logger.handlerRegistration(category, handlerName, description, metadata),\n\n handlerExecution: (\n category: LogCategory,\n handlerName: string,\n operation: 'start' | 'end' | 'skip' | 'error',\n fieldName?: string,\n data?: any\n ) => logger.handlerExecution(category, handlerName, operation, fieldName, data),\n\n handlerValidation: (\n category: LogCategory,\n handlerName: string,\n validation: 'pass' | 'fail' | 'skip',\n reason?: string,\n data?: any\n ) => logger.handlerValidation(category, handlerName, validation, reason, data),\n\n handlerLifecycle: (\n category: LogCategory,\n handlerName: string,\n lifecycle: 'register' | 'unregister' | 'update' | 'init' | 'cleanup',\n metadata?: Record<string, any>\n ) => logger.handlerLifecycle(category, handlerName, lifecycle, metadata),\n\n // 配置相关\n getEnabledCategories: () => logger.getEnabledCategories(),\n showCurrentConfig: () => logger.showCurrentConfig(),\n resetConfigDisplay: () => logger.resetConfigDisplay(),\n showConfigOnStartup: () => logger.showConfigOnStartup()\n};\n","import { FieldMeta, FormConfig } from '../types';\n\n// 浅比较\nexport function shallowEqual(objA: any, objB: any) {\n if (objA === objB) return true;\n\n if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) {\n return false;\n }\n\n const keysA = Object.keys(objA);\n const keysB = Object.keys(objB);\n\n if (keysA.length !== keysB.length) return false;\n\n for (let i = 0; i < keysA.length; i++) {\n if (objA[keysA[i]] !== objB[keysA[i]]) {\n return false;\n }\n }\n\n return true;\n}\n\nexport function isGroupedConfig(config: FormConfig) {\n return config && typeof config === 'object' && 'groups' in config;\n}\n\nexport function mergeIntoDraft(draft: any, source: any) {\n if (Array.isArray(source)) {\n source.forEach((item, index) => {\n if (typeof item === 'object' && item !== null) {\n if (!draft[index]) draft[index] = Array.isArray(item) ? [] : {};\n mergeIntoDraft(draft[index], item);\n } else {\n draft[index] = item;\n }\n });\n } else if (typeof source === 'object' && source !== null) {\n Object.entries(source).forEach(([key, value]) => {\n if (typeof value === 'object' && value !== null) {\n if (!draft[key]) draft[key] = Array.isArray(value) ? [] : {};\n mergeIntoDraft(draft[key], value);\n } else {\n draft[key] = value;\n }\n });\n }\n}\n\nexport function arraysEqual(a: any[], b: any[]) {\n if (a.length !== b.length) return false;\n return a.every((item, index) => item === b[index]);\n}\n\n// 原生实现 get,支持类似 \"projects[0].members[1].name\" 路径\nexport function getValueByPath(obj: any, path: string): any {\n if (!obj || !path) return undefined;\n // 把类似 'projects[0].members[1].name' 转成 ['projects', '0', 'members', '1', 'name']\n const keys = path.replace(/\\[(\\d+)\\]/g, '.$1').split('.');\n let cur = obj;\n for (const key of keys) {\n if (cur == null) return undefined;\n cur = cur[key];\n }\n return cur;\n}\n\n// 原生实现 set,支持嵌套路径,自动创建对象/数组\nexport function setValueByPath(obj: any, path: string, value: any) {\n if (!obj || !path) return;\n const keys = path.replace(/\\[(\\d+)\\]/g, '.$1').split('.');\n let cur = obj;\n for (let i = 0; i < keys.length; i++) {\n const key = keys[i];\n if (i === keys.length - 1) {\n cur[key] = value;\n } else {\n if (cur[key] == null) {\n // 判断下一个 key 是数字就创建数组,否则对象\n cur[key] = /^\\d+$/.test(keys[i + 1]) ? [] : {};\n }\n cur = cur[key];\n }\n }\n}\n\n// 原生深度比较,简单版(只比较基础类型、数组、对象)\nexport function deepEqual(a: any, b: any): boolean {\n if (a === b) return true;\n\n if (typeof a !== typeof b) return false;\n if (a == null || b == null) return false;\n\n if (Array.isArray(a) && Array.isArray(b)) {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (!deepEqual(a[i], b[i])) return false;\n }\n return true;\n }\n\n if (typeof a === 'object' && typeof b === 'object') {\n const keysA = Object.keys(a);\n const keysB = Object.keys(b);\n if (keysA.length !== keysB.length) return false;\n for (const key of keysA) {\n if (!deepEqual(a[key], b[key])) return false;\n }\n return true;\n }\n\n return false;\n}\n\nexport function deepMerge(target: Record<string, any>, source: Record<string, any>) {\n for (const key in source) {\n const srcVal = source[key];\n\n // 跳过 undefined 和 null\n if (srcVal == null) continue;\n\n const srcIsObj = typeof srcVal === 'object' && !Array.isArray(srcVal);\n const tgtVal = target[key];\n const tgtIsObj = typeof tgtVal === 'object' && !Array.isArray(tgtVal);\n\n if (srcIsObj) {\n // 如果目标不是对象,初始化为空对象\n if (!tgtIsObj) {\n target[key] = {};\n }\n // 如果引用相同,跳过\n if (target[key] !== srcVal) {\n deepMerge(target[key], srcVal);\n }\n } else {\n // 如果值没有变化,跳过赋值\n if (tgtVal !== srcVal) {\n target[key] = srcVal;\n }\n }\n }\n return target;\n}\n\nexport const mockFetchFormData = (data: any): Promise<Record<string, any>> => {\n return new Promise((resolve) => setTimeout(() => resolve(data), 800));\n};\n\nexport function mergeFieldMetaPatch(\n targetMeta: FieldMeta | undefined,\n patch: Partial<FieldMeta>\n): FieldMeta {\n const result: FieldMeta = {\n ...(targetMeta || {}) // 如果 base 是 undefined,默认空对象\n };\n\n (Object.keys(patch) as (keyof FieldMeta)[]).forEach((key) => {\n if (key === 'formItemProps' || key === 'componentProps') {\n result[key] = {\n ...(result[key] || {}),\n ...(patch[key] || {})\n };\n } else {\n result[key] = patch[key]!;\n }\n });\n\n return result;\n}\n","import { CustomEffectResultHandler } from '@/resultProcessor';\nimport { log, LogCategory } from '../src/utils/logger';\n\n/**\n * DynamicForm 默认配置接口\n */\nexport interface DynamicFormDefaultConfig {\n /** 默认处理器列表 */\n baseHandlers?: CustomEffectResultHandler[];\n // 定义保留关键字列表\n reservedKeys: Set<string>;\n\n /** 是否启用默认处理器,默认为 true */\n enableDefaultHandlers?: boolean;\n\n /** 默认处理器注册选项 */\n defaultHandlersOptions?: {\n override?: boolean;\n };\n\n /** 是否启用调试模式,默认为 false */\n debug?: boolean;\n}\n\n/**\n * 基础处理器定义\n */\nconst baseHandlers: CustomEffectResultHandler[] = [\n {\n name: 'value',\n description: '处理字段值的更新,支持批量更新机制',\n canHandle: (key) => key === 'value',\n handle: (context, value) => {\n log.effect(LogCategory.EFFECT_RESULT, 'valueHandle', context.fieldName, value);\n\n // 使用批量更新 API,不立即执行,让 handleEffectResult 统一处理\n context.setFieldValueBatch(value);\n }\n },\n {\n name: 'visible',\n description: '处理字段可见性状态',\n canHandle: (key) => key === 'visible',\n handle: (context, visible) => {\n // 使用语义化的 API\n context.updateFieldMeta({ visible });\n }\n },\n {\n name: 'disabled',\n description: '处理字段禁用状态',\n canHandle: (key) => key === 'disabled',\n handle: (context, disabled) => {\n // 使用语义化的 API\n context.updateFieldMeta({ componentProps: { disabled } });\n }\n },\n {\n name: 'groupsVisible',\n description: '处理分组可见性状态',\n canHandle: (key) => key === 'groupsVisible',\n handle: (context, groupsVisible) => {\n Object.entries(groupsVisible).forEach(([groupId, visible]) => {\n context.setGroupVisible(groupId, visible as boolean);\n });\n }\n },\n\n // 字段级别配置处理器\n {\n name: 'formItemProps',\n description: '处理Form.Item组件配置,存储到字段meta.formItemProps',\n canHandle: (key) => key === 'formItemProps',\n handle: (context, value) => {\n log.effect(LogCategory.EFFECT_RESULT, 'formItemPropsHandle ', context.fieldName, value);\n\n context.updateFieldMetaBatch({ formItemProps: value });\n }\n },\n // componentProps 承载内部组件属性,存储到 meta.componentProps\n {\n name: 'componentProps',\n description: '处理组件属性配置,合并存储到 meta.componentProps',\n canHandle: (key) => key === 'componentProps',\n handle: (context, value) => {\n log.effect(LogCategory.EFFECT_RESULT, 'componentProps', context.fieldName, value);\n context.updateFieldMetaBatch({\n componentProps: value\n });\n }\n },\n\n // 全局UIConfig配置处理器\n {\n name: 'formProps',\n description: '处理Form组件配置,存储到全局dynamicUIConfig',\n canHandle: (key) => key === 'formProps',\n handle: (context, value) => {\n log.effect(LogCategory.EFFECT_RESULT, 'formProps handle Run ', context.fieldName, value);\n // 直接dispatch到store,更新全局配置\n context.updateDynamicUIConfig({ formProps: value });\n }\n },\n {\n name: 'buttonProps',\n description: '处理Button组件配置,存储到全局dynamicUIConfig',\n canHandle: (key) => key === 'buttonProps',\n handle: (context, value) => {\n log.effect(LogCategory.EFFECT_RESULT, 'buttonProps handle Run ', context.fieldName, value);\n context.updateDynamicUIConfig({ buttonProps: value });\n }\n },\n {\n name: 'cardProps',\n description: '处理Card组件配置,存储到全局dynamicUIConfig',\n canHandle: (key) => key === 'cardProps',\n handle: (context, value) => {\n log.effect(LogCategory.EFFECT_RESULT, 'cardProps handle Run ', context.fieldName, value);\n context.updateDynamicUIConfig({ cardProps: value });\n }\n },\n {\n name: 'rowProps',\n description: '处理Row组件配置,存储到全局dynamicUIConfig',\n canHandle: (key) => key === 'rowProps',\n handle: (context, value) => {\n log.effect(LogCategory.EFFECT_RESULT, 'rowProps handle Run ', context.fieldName, value);\n context.updateDynamicUIConfig({ rowProps: value });\n }\n },\n {\n name: 'colProps',\n description: '处理Col组件配置,存储到全局dynamicUIConfig',\n canHandle: (key) => key === 'colProps',\n handle: (context, value) => {\n log.effect(LogCategory.EFFECT_RESULT, 'colProps handle Run ', context.fieldName, value);\n context.updateDynamicUIConfig({ colProps: value });\n }\n },\n {\n name: 'submitAreaProps',\n description: '处理提交区域配置,存储到全局dynamicUIConfig',\n canHandle: (key) => key === 'submitAreaProps',\n handle: (context, value) => {\n log.effect(\n LogCategory.EFFECT_RESULT,\n 'submitAreaProps handle Run ',\n context.fieldName,\n value\n );\n context.updateDynamicUIConfig({ submitAreaProps: value });\n }\n }\n];\n/**\n * 默认配置\n */\nexport const defaultConfig: DynamicFormDefaultConfig = {\n baseHandlers,\n reservedKeys: new Set(baseHandlers.map((i) => i.name)),\n enableDefaultHandlers: true,\n defaultHandlersOptions: {\n override: false\n },\n debug: false\n};\n\n/**\n * 配置管理器\n */\nclass ConfigManager {\n private config: DynamicFormDefaultConfig = { ...defaultConfig };\n\n /**\n * 设置配置\n */\n setConfig(newConfig: Partial<DynamicFormDefaultConfig>) {\n this.config = { ...this.config, ...newConfig };\n }\n\n /**\n * 获取配置\n */\n getConfig(): DynamicFormDefaultConfig {\n return { ...this.config };\n }\n\n /**\n * 获取特定配置项\n */\n get<K extends keyof DynamicFormDefaultConfig>(key: K): DynamicFormDefaultConfig[K] {\n return this.config[key];\n }\n\n /**\n * 重置为默认配置\n */\n reset() {\n this.config = { ...defaultConfig };\n }\n\n /**\n * 合并配置\n */\n mergeConfig(userConfig: Partial<DynamicFormDefaultConfig>) {\n this.config = { ...this.config, ...userConfig };\n }\n}\n\n// 创建全局配置管理器实例\nexport const configManager = new ConfigManager();\n\n/**\n * 设置全局默认配置\n */\nexport function setDefaultConfig(config: Partial<DynamicFormDefaultConfig>) {\n configManager.setConfig(config);\n}\n\n/**\n * 获取全局默认配置\n */\nexport function getDefaultConfig(): DynamicFormDefaultConfig {\n return configManager.getConfig();\n}\n\n/**\n * 重置为默认配置\n */\nexport function resetDefaultConfig() {\n configManager.reset();\n}\n","import type { CustomEffectResultHandler, HandlerRegistrationOptions } from './types';\nimport { getDefaultConfig } from '../../config/defaultConfig';\n\n/**\n * 处理器注册表\n *\n * 使用 Map 结构存储所有已注册的处理器,支持快速查找\n */\nconst handlers = new Map<string, CustomEffectResultHandler>();\n\n/**\n * 初始化状态跟踪\n */\nlet isInitialized = false;\nlet initializationCheckPerformed = false;\nconst initializationWarnings = new Set<string>();\n\n/**\n * 获取处理器注册表\n * @returns 处理器注册表\n */\nexport function getHandlers(): Map<string, CustomEffectResultHandler> {\n return handlers;\n}\n\n/**\n * 标记处理器已初始化\n */\nexport function markHandlersInitialized() {\n isInitialized = true;\n}\n\n/**\n * 检查处理器是否已初始化\n */\nexport function isHandlersInitialized(): boolean {\n return isInitialized;\n}\n\n/**\n * 早期检测初始化状态\n * 在组件渲染前就检测,避免运行时才发现问题\n */\nexport function checkInitializationStatus() {\n if (initializationCheckPerformed) {\n return;\n }\n\n initializationCheckPerformed = true;\n\n if (!isInitialized) {\n const warningKey = 'initialization_warning';\n if (!initializationWarnings.has(warningKey)) {\n initializationWarnings.add(warningKey);\n console.warn(\n '⚠️ DynamicForm 警告: 检测到可能缺少 useInitHandlers 调用。\\n' +\n '建议在组件顶层添加: const { isInitialized } = useInitHandlers(config);\\n' +\n '这将确保默认处理器正确初始化。'\n );\n }\n }\n}\n\n/**\n * 获取未注册的保留关键字\n * 用于检测哪些默认处理器没有注册\n */\nexport function getUnregisteredReservedKeys(): string[] {\n const { reservedKeys } = getDefaultConfig();\n const registeredKeys = Array.from(handlers.keys());\n\n return Array.from(reservedKeys as Set<string>).filter((key) => !registeredKeys.includes(key));\n}\n\n/**\n * 注册单个自定义结果处理器\n *\n * @param handler 要注册的处理器\n * @param options 注册选项\n *\n * @throws {Error} 当处理器缺少必要属性时\n * @throws {Error} 当处理器已存在且未设置覆盖选项时\n *\n * @example\n * ```typescript\n * registerCustomEffectResultHandler({\n * name: 'customStyle',\n * description: '处理自定义样式',\n * canHandle: (key) => key === 'customStyle',\n * handle: (context, value) => {\n * context.updateFieldMeta({ style: value });\n * }\n * });\n * ```\n */\nexport function registerCustomEffectResultHandler(\n handler: CustomEffectResultHandler,\n options?: HandlerRegistrationOptions\n) {\n const { override = false } = options || {};\n\n // 验证处理器\n if (!handler.name || !handler.canHandle || !handler.handle) {\n throw new Error('Invalid handler: missing required properties');\n }\n\n // 检查是否已存在\n if (handlers.has(handler.name) && !override) {\n throw new Error(`Handler '${handler.name}' already exists. Use override option to replace.`);\n }\n\n // 注册处理器\n handlers.set(handler.name, handler);\n\n // log.handlerRegistration(LogCategory.HANDLER_REGISTRATION, handler.name, handler.description);\n}\n\n/**\n * 批量注册自定义结果处理器\n *\n * @param handlers 要注册的处理器数组\n * @param options 注册选项\n *\n * @example\n * ```typescript\n * registerCustomEffectResultHandlers([\n * customStyleHandler,\n * dataTransformHandler,\n * conditionalDisplayHandler\n * ], { override: false });\n * ```\n */\nexport function registerCustomEffectResultHandlers(\n handlerList: CustomEffectResultHandler[],\n options?: HandlerRegistrationOptions\n) {\n const errors: string[] = [];\n\n for (const handler of handlerList) {\n try {\n registerCustomEffectResultHandler(handler, options);\n } catch (error) {\n // 如果是重复注册错误,根据选项决定是否忽略\n if (error instanceof Error && error.message.includes('already exists')) {\n if (options?.override) {\n // 如果允许覆盖,重新注册\n try {\n registerCustomEffectResultHandler(handler, { override: true });\n } catch (retryError) {\n errors.push(retryError instanceof Error ? retryError.message : '未知错误');\n }\n } else {\n // 如果不允许覆盖,记录错误但不抛出异常\n console.warn(`处理器 ${handler.name} 已存在,跳过注册`);\n }\n } else {\n errors.push(error instanceof Error ? error.message : '未知错误');\n }\n }\n }\n\n if (errors.length > 0) {\n throw new Error(`注册失败: ${errors.join(', ')}`);\n }\n}\n\n/**\n * 移除指定的结果处理器\n *\n * @param name 要移除的处理器名称\n *\n * @example\n * ```typescript\n * unregisterEffectResultHandler('customStyle');\n * ```\n */\nexport function unregisterEffectResultHandler(name: string) {\n handlers.delete(name);\n}\n\n/**\n * 获取所有已注册的结果处理器\n *\n * @returns 所有处理器的数组\n *\n * @example\n * ```typescript\n * const allHandlers = getAllEffectResultHandlers();\n * console.log('已注册的处理器:', allHandlers.map(h => h.name));\n * ```\n */\nexport function getAllEffectResultHandlers(): CustomEffectResultHandler[] {\n return Array.from(handlers.values()) as CustomEffectResultHandler[];\n}\n\n/**\n * 获取指定处理器的详细信息\n *\n * @param name 处理器名称\n * @returns 处理器信息,如果不存在则返回 undefined\n *\n * @example\n * ```typescript\n * const handler = getEffectResultHandlerInfo('customStyle');\n * if (handler) {\n * console.log('处理器描述:', handler.description);\n * }\n * ```\n */\nexport function getEffectResultHandlerInfo(name: string): CustomEffectResultHandler | undefined {\n return handlers.get(name) as CustomEffectResultHandler | undefined;\n}\n\n/**\n * 检查指定处理器是否存在\n *\n * @param name 处理器名称\n * @returns 是否存在\n *\n * @example\n * ```typescript\n * if (hasEffectResultHandler('customStyle')) {\n * console.log('customStyle 处理器已注册');\n * }\n * ```\n */\nexport function hasEffectResultHandler(name: string): boolean {\n return handlers.has(name);\n}\n","import { isHandlersInitialized, getUnregisteredReservedKeys } from '../resultProcessor/handlers';\nimport { getDefaultConfig } from '../../config/defaultConfig';\nimport { log, LogCategory } from './logger';\n/**\n * 初始化检测器\n * 用于在组件渲染前检测初始化状态和潜在问题\n */\nexport class InitializationChecker {\n private static instance: InitializationChecker;\n private hasWarned = false;\n private constructor() {\n // 私有构造函数,防止外部实例化\n }\n static getInstance(): InitializationChecker {\n if (!InitializationChecker.instance) {\n InitializationChecker.instance = new InitializationChecker();\n }\n return InitializationChecker.instance;\n }\n /**\n * 执行完整的初始化状态检测\n */\n checkInitializationStatus(): {\n isInitialized: boolean;\n missingHandlers: string[];\n warnings: string[];\n recommendations: string[];\n } {\n // 移除缓存机制,每次都重新检测\n const warnings: string[] = [];\n const recommendations: string[] = [];\n\n // 检查基本初始化状态\n const isInitialized = isHandlersInitialized();\n if (!isInitialized && !this.hasWarned) {\n warnings.push('检测到处理器系统未初始化');\n recommendations.push('在组件顶层添加 useInitHandlers 调用');\n this.hasWarned = true;\n }\n\n // 检查缺失的默认处理器\n const missingHandlers = getUnregisteredReservedKeys();\n if (missingHandlers.length > 0) {\n warnings.push(\n `发现 ${missingHandlers.length} 个未注册的默认处理器: ${missingHandlers.join(', ')}`\n );\n recommendations.push('确保在 useInitHandlers 中正确配置了默认处理器');\n }\n\n // 检查配置状态\n const defaultConfig = getDefaultConfig();\n if (!defaultConfig.enableDefaultHandlers) {\n warnings.push('默认处理器已被禁用,这可能导致某些功能不可用');\n recommendations.push('考虑启用默认处理器或确保自定义处理器覆盖了所有必要功能');\n }\n\n const result = {\n isInitialized,\n missingHandlers,\n warnings,\n recommendations\n };\n\n // 记录检测结果\n log.group(LogCategory.HANDLER_REGISTRATION, '初始化状态检测', () => {\n log.info(LogCategory.HANDLER_REGISTRATION, '检测结果:', result);\n\n if (warnings.length > 0) {\n log.warn(LogCategory.HANDLER_REGISTRATION, '发现的问题:', warnings);\n log.info(LogCategory.HANDLER_REGISTRATION, '建议:', recommendations);\n }\n });\n\n return result;\n }\n\n /**\n * 重置检测状态(主要用于测试)\n */\n reset() {\n this.hasWarned = false;\n }\n\n /**\n * 获取初始化状态摘要\n */\n getStatusSummary(): string {\n const result = this.checkInitializationStatusSilent();\n\n if (result.isInitialized && result.warnings.length === 0) {\n return '✅ 处理器系统初始化正常';\n }\n\n const issues = result.warnings.length;\n const missing = result.missingHandlers.length;\n\n return `⚠️ 发现 ${issues} 个问题,${missing} 个缺失处理器`;\n }\n\n /**\n * 静默检查初始化状态(不输出日志)\n */\n checkInitializationStatusSilent(): {\n isInitialize