/** * SmartUI AutoLoader - 智能 UI 组件自动加载系统(生产增强版) * * 核心功能: * 1. 自动识别后端功能模块 * 2. 根据模块类型智能匹配 UI 组件(54 个组件完整映射) * 3. 字段层级自动渲染(支持 20+ 种字段类型) * 4. Schema 驱动的界面生成 * 5. 动态加载对应的后端 API 接口 * 6. 自动注入 AI 对话组件 * 7. 支持热插拔式模块扩展 * * 使用方式: * * */ (function(global) { 'use strict'; // 配置选项 const defaultConfig = { apiBaseUrl: 'http://124.70.146.192:8001', cdnBaseUrl: 'https://console-test.duoweiying.cn/smart-control-center', enableAIChat: true, autoLoadComponents: true, debug: false, timeout: 10000 }; // ========== 核心优化 1: 完整的 54 个组件映射表 ========== const MODULE_COMPONENT_MAP = { // ===== P0 核心业务组件 (10 个) ===== 'digital_human_live': { component: 'digital-human-live-component', icon: '🎭', category: 'core_business', apiPrefix: '/api/digital-human', title: '数字人直播' }, 'short_video_platform': { component: 'short-video-platform-component', icon: '📹', category: 'core_business', apiPrefix: '/api/short-video', title: '短视频平台' }, 'material_library': { component: 'material-library-component', icon: '📦', category: 'core_business', apiPrefix: '/api/materials', title: '素材库管理' }, 'content_generation': { component: 'content-generation-workbench', icon: '✍️', category: 'core_business', apiPrefix: '/api/content', title: '内容创作工作台' }, 'platform_integration': { component: 'platform-integration-manager', icon: '🔗', category: 'core_business', apiPrefix: '/api/platforms', title: '平台集成管理' }, 'live_stream_control': { component: 'live-stream-control-component', icon: '🎬', category: 'core_business', apiPrefix: '/api/live-stream', title: '直播控制' }, 'multi_platform_publisher': { component: 'multi-platform-publisher', icon: '📢', category: 'core_business', apiPrefix: '/api/publish', title: '多平台发布' }, 'ai_content_optimizer': { component: 'ai-content-optimizer', icon: '✨', category: 'core_business', apiPrefix: '/api/ai-optimize', title: 'AI 内容优化' }, 'data_analytics': { component: 'data-analytics-dashboard', icon: '📊', category: 'core_business', apiPrefix: '/api/analytics', title: '数据分析看板' }, 'user_behavior_tracker': { component: 'user-behavior-tracker', icon: '👁️', category: 'core_business', apiPrefix: '/api/user-tracking', title: '用户行为追踪' }, // ===== P1 重要组件 (7 个) ===== 'desktop_automation': { component: 'desktop-automation-console', icon: '🖥️', category: 'important', apiPrefix: '/api/desktop', title: '桌面自动化控制台' }, 'project_collaboration': { component: 'project-collaboration-component', icon: '🤝', category: 'important', apiPrefix: '/api/projects', title: '项目协作' }, 'profit_sharing': { component: 'profit-sharing-component', icon: '💰', category: 'important', apiPrefix: '/api/profit', title: '利润分配' }, 'premium_user_management': { component: 'premium-user-management-component', icon: '👑', category: 'important', apiPrefix: '/api/premium-users', title: '付费用户管理' }, 'global_search': { component: 'global-search-component', icon: '🔍', category: 'important', apiPrefix: '/api/search', title: '全局搜索' }, 'newrank_platform': { component: 'newrank-platform-component', icon: '📈', category: 'important', apiPrefix: '/api/newrank', title: '新榜平台' }, 'contribution_rewards': { component: 'contribution-rewards-component', icon: '🏆', category: 'important', apiPrefix: '/api/rewards', title: '贡献奖励' }, // ===== P2 辅助组件 (15 个) ===== 'traffic_pool': { component: 'traffic-pool-component', icon: '🚦', category: 'auxiliary', apiPrefix: '/api/traffic', title: '流量池管理' }, 'video_generation': { component: 'video-generation-workflow', icon: '🎥', category: 'auxiliary', apiPrefix: '/api/video-gen', title: '视频生成工作流' }, 'feature_switch': { component: 'feature-switch-component', icon: '🔧', category: 'auxiliary', apiPrefix: '/api/features', title: '功能开关' }, 'folder_manager': { component: 'folder-manager-component', icon: '📁', category: 'auxiliary', apiPrefix: '/api/files', title: '文件管理器' }, 'navigation_assistant': { component: 'navigation-assistant-component', icon: '🧭', category: 'auxiliary', apiPrefix: '/api/navigation', title: '导航助手' }, 'resource_management': { component: 'resource-management-component', icon: '📚', category: 'auxiliary', apiPrefix: '/api/resources', title: '资源管理' }, 'storage_quota': { component: 'storage-quota-component', icon: '💾', category: 'auxiliary', apiPrefix: '/api/storage', title: '存储配额' }, 'security_center': { component: 'security-center-component', icon: '🛡️', category: 'auxiliary', apiPrefix: '/api/security', title: '安全中心' }, 'dialog': { component: 'dialog-component', icon: '💬', category: 'auxiliary', apiPrefix: null, title: '对话框' }, 'drawer': { component: 'drawer-component', icon: '🗄️', category: 'auxiliary', apiPrefix: null, title: '抽屉面板' }, 'form': { component: 'form-component', icon: '📝', category: 'auxiliary', apiPrefix: null, title: '表单生成器' }, 'data_table': { component: 'data-table-component', icon: '📋', category: 'auxiliary', apiPrefix: null, title: '数据表格' }, 'chart': { component: 'chart-component', icon: '📈', category: 'auxiliary', apiPrefix: null, title: '图表组件' }, 'loading': { component: 'loading-component', icon: '⏳', category: 'auxiliary', apiPrefix: null, title: '加载动画' }, 'ad_manager': { component: 'ad-manager', icon: '📣', category: 'auxiliary', apiPrefix: '/api/ads', title: '广告管理' }, // ===== P3 增强组件 (22 个) ===== 'data_import_export': { component: 'data-import-export-component', icon: '🔄', category: 'enhanced', apiPrefix: '/api/import-export', title: '数据导入导出' }, 'notification_center': { component: 'notification-center-component', icon: '🔔', category: 'enhanced', apiPrefix: '/api/notifications', title: '通知中心' }, 'performance_monitor': { component: 'performance-monitor-component', icon: '⚡', category: 'enhanced', apiPrefix: '/api/performance', title: '性能监控' }, 'log_query': { component: 'log-query-component', icon: '📜', category: 'enhanced', apiPrefix: '/api/logs', title: '日志查询' }, 'task_scheduler': { component: 'task-scheduler-component', icon: '⏰', category: 'enhanced', apiPrefix: '/api/tasks', title: '任务调度' }, 'api_gateway': { component: 'api-gateway-component', icon: '🌐', category: 'enhanced', apiPrefix: '/api/gateway', title: 'API 网关' }, 'cache_manager': { component: 'cache-manager-component', icon: '🗄️', category: 'enhanced', apiPrefix: '/api/cache', title: '缓存管理' }, 'ai_model_management': { component: 'ai-model-management-component', icon: '🧠', category: 'enhanced', apiPrefix: '/api/ai-models', title: 'AI 模型管理' }, 'ai_skill_registry': { component: 'ai-skill-registry-component', icon: '⚙️', category: 'enhanced', apiPrefix: '/api/ai-skills', title: 'AI 技能注册' }, 'health_monitor': { component: 'health-monitor-component', icon: '❤️', category: 'enhanced', apiPrefix: '/api/health', title: '健康监控' }, 'auth_manager': { component: 'auth-manager', icon: '🔐', category: 'enhanced', apiPrefix: '/api/auth', title: '认证授权' }, 'billing_admin': { component: 'billing-admin', icon: '💳', category: 'enhanced', apiPrefix: '/api/billing', title: '计费管理' }, 'system_admin_panel': { component: 'system-admin-panel', icon: '🎛️', category: 'enhanced', apiPrefix: '/api/admin', title: '系统管理面板' }, 'user_admin': { component: 'user-admin', icon: '👥', category: 'enhanced', apiPrefix: '/api/users', title: '用户管理' }, 'training_platform': { component: 'training-platform', icon: '🎓', category: 'enhanced', apiPrefix: '/api/training', title: '训练平台' }, 'tuike_dashboard': { component: 'tuike-dashboard', icon: '💸', category: 'enhanced', apiPrefix: '/api/tuike', title: '推客仪表板' }, 'workflow_editor': { component: 'workflow-editor', icon: '📊', category: 'enhanced', apiPrefix: '/api/workflows', title: '工作流编辑器' }, 'moderation_panel': { component: 'moderation-panel', icon: '✅', category: 'enhanced', apiPrefix: '/api/moderation', title: '审核面板' }, 'chat_client': { component: 'chat-client', icon: '💬', category: 'enhanced', apiPrefix: '/api/chat', title: '聊天客户端' }, 'ai_chat': { component: 'ai-chat-component', icon: '🤖', category: 'enhanced', apiPrefix: '/api/ai-chat', title: 'AI 聊天' }, 'smart_ui_autoloader': { component: 'smart-ui-autoloader', icon: '🚀', category: 'enhanced', apiPrefix: null, title: 'UI 自动加载器' }, 'ui_core': { component: 'ui-core', icon: '⚙️', category: 'enhanced', apiPrefix: null, title: 'UI 核心引擎' } }; // ========== 核心优化 2: 字段层级自动匹配系统 ========== const FIELD_TYPE_MAPPING = { // 基础类型 'string': { component: 'text-input', type: 'input', icon: '📝' }, 'text': { component: 'textarea', type: 'input', icon: '📄' }, 'number': { component: 'number-input', type: 'input', icon: '🔢' }, 'integer': { component: 'number-input', type: 'input', icon: '🔢' }, 'float': { component: 'number-input', type: 'input', icon: '🔢', step: 'any' }, 'double': { component: 'number-input', type: 'input', icon: '🔢', step: 'any' }, 'boolean': { component: 'checkbox', type: 'input', icon: '☑️' }, 'bool': { component: 'checkbox', type: 'input', icon: '☑️' }, 'date': { component: 'date-picker', type: 'input', icon: '📅' }, 'datetime': { component: 'datetime-picker', type: 'input', icon: '🕐' }, 'time': { component: 'time-picker', type: 'input', icon: '⏰' }, 'timestamp': { component: 'datetime-picker', type: 'input', icon: '🕐' }, // 选择类型 'enum': { component: 'select-dropdown', type: 'select', icon: '📋' }, 'choice': { component: 'select-dropdown', type: 'select', icon: '📋' }, 'options': { component: 'select-dropdown', type: 'select', icon: '📋' }, 'radio': { component: 'radio-group', type: 'select', icon: '🔘' }, 'checkbox': { component: 'checkbox-group', type: 'select', icon: '☑️' }, 'multiple_choice': { component: 'checkbox-group', type: 'select', icon: '☑️' }, // 复杂类型 'array': { component: 'data-table', type: 'complex', icon: '📊' }, 'list': { component: 'data-table', type: 'complex', icon: '📊' }, 'object': { component: 'nested-form', type: 'complex', icon: '📁' }, 'json': { component: 'code-editor', type: 'complex', icon: '💻' }, 'map': { component: 'key-value-editor', type: 'complex', icon: '🗺️' }, // 媒体类型 'image': { component: 'image-uploader', type: 'media', icon: '🖼️' }, 'images': { component: 'image-gallery-uploader', type: 'media', icon: '🖼️' }, 'video': { component: 'video-uploader', type: 'media', icon: '🎬' }, 'videos': { component: 'video-gallery-uploader', type: 'media', icon: '🎬' }, 'audio': { component: 'audio-uploader', type: 'media', icon: '🎵' }, 'file': { component: 'file-uploader', type: 'media', icon: '📎' }, 'files': { component: 'file-gallery-uploader', type: 'media', icon: '📎' }, // 特殊类型 'url': { component: 'url-input', type: 'special', icon: '🔗' }, 'email': { component: 'email-input', type: 'special', icon: '📧' }, 'phone': { component: 'tel-input', type: 'special', icon: '📱' }, 'mobile': { component: 'tel-input', type: 'special', icon: '📱' }, 'color': { component: 'color-picker', type: 'special', icon: '🎨' }, 'range': { component: 'slider', type: 'special', icon: '📏' }, 'tags': { component: 'tag-input', type: 'special', icon: '🏷️' }, 'category': { component: 'category-selector', type: 'special', icon: '📂' }, 'search': { component: 'search-input', type: 'special', icon: '🔍' }, 'password': { component: 'password-input', type: 'special', icon: '🔒' }, 'hidden': { component: 'hidden-input', type: 'special', icon: '👁️' } }; // 通用 UI 组件库 (所有模块共享) const SHARED_COMPONENTS = [ { name: 'toast', path: '/shared/components/feedback/toast.js', loaded: false }, { name: 'loading', path: '/shared/components/feedback/loading.js', loaded: false }, { name: 'dialog', path: '/shared/components/feedback/dialog.js', loaded: false }, { name: 'data-table', path: '/shared/components/data/table.js', loaded: false }, { name: 'stat-card', path: '/shared/components/display/stat-card.js', loaded: false }, { name: 'ai-chat', path: '/components/ai-chat-component.js', loaded: false } ]; // Schema 渲染器类 class FieldSchemaRenderer { constructor() { this.fieldMapping = FIELD_TYPE_MAPPING; } /** * 根据 Schema 自动渲染表单 */ renderForm(schema, formData = {}, onSubmit) { if (!schema || !schema.fields) { console.error('Invalid schema'); return ''; } const formId = `form-${schema.name}-${Date.now()}`; return `
${schema.fields.map(field => this.renderField(field, formData[field.name])).join('')}
`; } /** * 渲染单个字段 */ renderField(field, value) { const fieldType = field.type || 'string'; const componentConfig = this.fieldMapping[fieldType] || this.fieldMapping['string']; return `
${field.label ? `` : ''} ${this.createInput(componentConfig.component, field, value)} ${field.description ? `${field.description}` : ''} ${field.required ? '*' : ''}
`; } /** * 创建输入控件 */ createInput(componentType, field, value) { const name = field.name; const defaultValue = value !== undefined ? value : field.default || ''; const required = field.required ? 'required' : ''; // 根据 componentType 创建对应的 HTML switch(componentType) { case 'text-input': return ``; case 'number-input': const step = field.step || 1; return ``; case 'checkbox': return ``; case 'select-dropdown': const options = field.options || field.enum || []; return ` `; case 'textarea': const rows = field.rows || 4; return ``; case 'date-picker': return ``; case 'datetime-picker': return ``; case 'data-table': return this.renderDataTable(field, value); case 'image-uploader': return this.renderImageUploader(field, value); case 'file-uploader': return this.renderFileUploader(field, value); case 'tag-input': return this.renderTagInput(field, value); default: return ``; } } /** * 渲染数据表格 */ renderDataTable(field, data) { if (!data || !Array.isArray(data) || data.length === 0) { return '
暂无数据
'; } const columns = field.columns || Object.keys(data[0]); return `
${columns.map(col => ``).join('')} ${data.map((row, index) => ` ${columns.map(col => ``).join('')} `).join('')}
${col}
${row[col]}
`; } /** * 渲染图片上传器 */ renderImageUploader(field, value) { return `
${value ? `
` : ''}
`; } /** * 渲染文件上传器 */ renderFileUploader(field, value) { return `
${value ? `
📄 ${value}
` : ''}
`; } /** * 渲染标签输入器 */ renderTagInput(field, value) { const tags = Array.isArray(value) ? value.join(', ') : (value || ''); return ` `; } } // 主加载器对象 const SmartUILoader = { config: null, loadedModules: new Set(), loadedComponents: new Set(), currentModule: null, schemaRenderer: new FieldSchemaRenderer(), /** * 初始化加载器 */ initialize(userConfig = {}) { this.config = { ...defaultConfig, ...userConfig }; if (this.config.debug) { console.log('[SmartUI] 初始化配置:', this.config); console.log('[SmartUI] 已注册组件映射:', Object.keys(MODULE_COMPONENT_MAP).length, '个'); console.log('[SmartUI] 已注册字段类型:', Object.keys(FIELD_TYPE_MAPPING).length, '种'); } // 加载共享组件 this.loadSharedComponents(); // 监听 DOM 就绪 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => this.onDOMReady()); } else { this.onDOMReady(); } return this; }, /** * DOM 就绪后的处理 */ async onDOMReady() { if (this.config.debug) { console.log('[SmartUI] DOM 已就绪,开始自动加载...'); } // 1. 检测当前页面所在的模块 await this.detectCurrentModule(); // 2. 如果启用了自动加载,加载对应模块的组件 if (this.config.autoLoadComponents && this.currentModule) { await this.loadModuleComponents(this.currentModule); } // 3. 注入 AI 对话组件 (如果启用) if (this.config.enableAIChat) { this.injectAIChat(); } }, /** * 检测当前模块 */ async detectCurrentModule() { // 方法 1: 从 URL 路径识别 const pathParts = window.location.pathname.split('/').filter(Boolean); const moduleName = pathParts[pathParts.length - 1]; if (moduleName && MODULE_COMPONENT_MAP[moduleName]) { this.currentModule = moduleName; if (this.config.debug) { console.log(`[SmartUI] 从 URL 检测到模块:${moduleName}`); } return; } // 方法 2: 从页面 data 属性读取 const moduleData = document.querySelector('[data-module]'); if (moduleData) { const moduleName = moduleData.getAttribute('data-module'); if (MODULE_COMPONENT_MAP[moduleName]) { this.currentModule = moduleName; if (this.config.debug) { console.log(`[SmartUI] 从 data-module 检测到模块:${moduleName}`); } return; } } // 方法 3: 从页面标题匹配 const pageTitle = document.title.toLowerCase(); for (const [key, config] of Object.entries(MODULE_COMPONENT_MAP)) { if (pageTitle.includes(config.title.toLowerCase())) { this.currentModule = key; if (this.config.debug) { console.log(`[SmartUI] 从页面标题匹配到模块:${key}`); } return; } } if (this.config.debug) { console.warn('[SmartUI] 未检测到匹配的模块'); } }, /** * 加载模块组件 */ async loadModuleComponents(moduleName) { const moduleConfig = MODULE_COMPONENT_MAP[moduleName]; if (!moduleConfig) { console.error(`[SmartUI] 未找到模块配置:${moduleName}`); return; } if (this.config.debug) { console.log(`[SmartUI] 加载模块组件:${moduleConfig.title}`, moduleConfig); } // 1. 动态加载组件 JS 文件 await this.loadComponent(moduleConfig.component); // 2. 查找或创建容器 const container = this.findOrCreateContainer(moduleName); // 3. 渲染组件 this.renderComponent(container, moduleConfig); // 4. 加载 API 数据(如果有) if (moduleConfig.apiPrefix) { await this.loadAPIData(moduleConfig.apiPrefix, container); } }, /** * 查找或创建容器 */ findOrCreateContainer(moduleName) { // 尝试从 data 属性获取容器 let container = document.querySelector(`[data-module="${moduleName}"]`); if (!container) { // 尝试通过 ID 查找 container = document.getElementById(`${moduleName}-container`) || document.getElementById(`${moduleName.replace(/_/g, '-')}-container`); } if (!container) { // 创建默认容器 container = document.createElement('div'); container.id = `${moduleName}-container`; container.className = 'smart-module-container'; container.style.cssText = 'max-width: 1400px; margin: 0 auto; padding: 20px;'; // 添加到 body document.body.appendChild(container); } return container; }, /** * 渲染组件(修复版) */ renderComponent(container, moduleConfig) { if (this.config.debug) { console.log(`[SmartUI] 开始渲染组件:${moduleConfig.title}`); console.log(`[SmartUI] 容器:`, container); console.log(`[SmartUI] 组件名:${moduleConfig.component}`); } // 检查组件是否已加载 const componentName = moduleConfig.component.replace(/-/g, '_'); const ComponentClass = global[componentName] || global[moduleConfig.component]; if (this.config.debug) { console.log(`[SmartUI] ComponentClass:`, ComponentClass); } if (!ComponentClass) { console.error(`[SmartUI] ❌ 组件类不存在:${moduleConfig.component}`); container.innerHTML = `

⚠️ 组件未找到

组件 "${moduleConfig.component}" 尚未加载或不存在

请检查 CDN 上是否有该组件文件

`; return; } try { // ✅ 关键修复:正确传递参数 // 组件构造函数期望:constructor(containerId, options) const instance = new ComponentClass( container.id, // 第一个参数:containerId { // 第二个参数:options container: container, apiBaseUrl: this.config.apiBaseUrl + (moduleConfig.apiPrefix || ''), moduleKey: this.currentModule, moduleConfig: moduleConfig, debug: this.config.debug } ); if (this.config.debug) { console.log(`[SmartUI] 组件实例已创建:`, instance); console.log(`[SmartUI] API 地址:${instance.options?.apiBaseUrl || '未设置'}`); } // ✅ 关键修复:调用组件的 initialize 或 render 方法 if (typeof instance.initialize === 'function') { console.log(`[SmartUI] 调用组件 initialize 方法`); instance.initialize().then(() => { if (this.config.debug) { console.log(`[SmartUI] ✅ 组件 ${moduleConfig.title} 初始化完成`); } }).catch(error => { console.error(`[SmartUI] ❌ 组件初始化失败:`, error); container.innerHTML += `
❌ 初始化失败
${error.message}
`; }); } else if (typeof instance.render === 'function') { console.log(`[SmartUI] 调用组件 render 方法`); instance.render(); if (this.config.debug) { console.log(`[SmartUI] ✅ 组件 ${moduleConfig.title} 已渲染`); } } else { console.warn(`[SmartUI] ⚠️ 组件 ${moduleConfig.component} 没有 initialize 或 render 方法`); container.innerHTML = `

⚠️ 组件缺少必要的方法

请确保组件类有 initialize() 或 render() 方法

`; } // 存储组件实例引用 if (!this.loadedInstances) { this.loadedInstances = {}; } this.loadedInstances[moduleConfig.component] = instance; if (this.config.debug) { console.log(`[SmartUI] ✅ 组件 ${moduleConfig.title} 渲染完成`); } } catch (error) { console.error(`[SmartUI] ❌ 组件渲染异常:`, error); container.innerHTML = `

❌ 组件渲染失败

${error.message}

${error.stack}
`; } }, /** * 加载 API 数据 */ async loadAPIData(apiPrefix, container) { try { const response = await fetch(`${this.config.apiBaseUrl}${apiPrefix}/list`, { method: 'GET', headers: { 'Content-Type': 'application/json' } }); if (response.ok) { const data = await response.json(); if (this.config.debug) { console.log(`[SmartUI] API 数据已加载:`, data); } // 触发数据更新事件 const event = new CustomEvent('smart-ui:data-loaded', { detail: data }); container.dispatchEvent(event); } } catch (error) { if (this.config.debug) { console.warn(`[SmartUI] API 数据加载失败:`, error); } } }, /** * 加载单个组件 */ async loadComponent(componentName) { const scriptUrl = `${this.config.cdnBaseUrl}/components/${componentName}.js`; if (this.loadedComponents.has(scriptUrl)) { return Promise.resolve(); } return new Promise((resolve, reject) => { const script = document.createElement('script'); script.src = scriptUrl; script.onload = () => { this.loadedComponents.add(scriptUrl); if (this.config.debug) { console.log(`[SmartUI] 组件已加载:${componentName}`); } resolve(); }; script.onerror = () => { console.error(`[SmartUI] 组件加载失败:${componentName}`); reject(new Error(`Failed to load ${componentName}`)); }; document.head.appendChild(script); }); }, /** * 加载共享组件 */ loadSharedComponents() { SHARED_COMPONENTS.forEach(component => { if (!component.loaded) { const script = document.createElement('script'); script.src = `${this.config.cdnBaseUrl}${component.path}`; script.onload = () => { component.loaded = true; if (this.config.debug) { console.log(`[SmartUI] 共享组件已加载:${component.name}`); } }; document.head.appendChild(script); } }); }, /** * 注入 AI 聊天组件 */ injectAIChat() { const chatContainer = document.createElement('div'); chatContainer.id = 'ai-chat-widget'; chatContainer.style.cssText = 'position: fixed; bottom: 20px; right: 20px; width: 350px; height: 500px; z-index: 9999;'; document.body.appendChild(chatContainer); this.loadComponent('ai-chat-component').then(() => { const AIChatComponent = global['ai_chat_component'] || global['ai-chat-component']; if (AIChatComponent) { new AIChatComponent({ containerId: 'ai-chat-widget', apiBaseUrl: this.config.apiBaseUrl + '/api/ai-chat' }).initialize(); } }); }, /** * 渲染 Schema 表单(公开方法) */ renderSchemaForm(schema, formData = {}, onSubmit) { return this.schemaRenderer.renderForm(schema, formData, onSubmit); }, /** * 🚀 自动发现所有后端模块(应用市场模式核心) */ async discoverModules() { console.log('[SmartUI] 正在从后端自动发现模块...'); try { const response = await fetch(`${this.config.apiBaseUrl}/api/modules`, { method: 'GET', headers: { 'Content-Type': 'application/json' } }); if (!response.ok) { throw new Error(`HTTP ${response.status}`); } const data = await response.json(); const modules = data.modules || []; console.log(`[SmartUI] ✅ 发现 ${modules.length} 个模块`); // 为每个模块智能匹配 UI组件 modules.forEach(module => { module.component = this.matchComponent(module); module.loaded = false; if (this.config.debug) { console.log(`[SmartUI] 模块 "${module.name}" → 组件 "${module.component}"`); } }); return modules; } catch (error) { console.warn('[SmartUI] ⚠️ 自动发现失败,使用内置映射表:', error); // 降级方案:返回内置的 MODULE_COMPONENT_MAP return Object.keys(MODULE_COMPONENT_MAP).map(key => ({ key: key, ...MODULE_COMPONENT_MAP[key], loaded: false })); } }, /** * 🎯 智能匹配 UI组件(基于规则引擎) */ matchComponent(module) { // 规则 1: 如果 MODULE_COMPONENT_MAP 中有定义,优先使用 if (MODULE_COMPONENT_MAP[module.key]) { return MODULE_COMPONENT_MAP[module.key].component; } // 规则 2: 根据 category 匹配 const categoryRules = { 'core_business': 'business-workbench-component', 'important': 'advanced-form-component', 'auxiliary': 'simple-form-component', 'enhanced': 'generic-module-component' }; if (categoryRules[module.category]) { return categoryRules[module.category]; } // 规则 3: 根据名称关键词匹配 const name = module.name || ''; const keywordRules = [ { keywords: ['直播', 'stream', 'live'], component: 'live-stream-component' }, { keywords: ['视频', 'video'], component: 'video-component' }, { keywords: ['数据', 'data', '分析', 'analytics'], component: 'data-dashboard-component' }, { keywords: ['内容', 'content', '创作'], component: 'content-generation-component' }, { keywords: ['素材', 'material', '资源'], component: 'material-library-component' }, { keywords: ['发布', 'publish', '分发'], component: 'publisher-component' }, { keywords: ['AI', '智能', '优化'], component: 'ai-optimizer-component' }, { keywords: ['搜索', 'search'], component: 'search-component' }, { keywords: ['管理', 'manage'], component: 'management-component' }, { keywords: ['监控', 'monitor', '监控'], component: 'monitor-component' } ]; for (const rule of keywordRules) { if (rule.keywords.some(keyword => name.toLowerCase().includes(keyword))) { return rule.component; } } // 规则 4: 根据 schema 复杂度匹配 if (module.schema && module.schema.fields) { const fieldCount = module.schema.fields.length; if (fieldCount > 20) { return 'advanced-form-component'; } else if (fieldCount > 10) { return 'intermediate-form-component'; } else { return 'simple-form-component'; } } // 默认组件 return 'generic-module-component'; }, /** * 👤 检查用户权限(简化版) */ isUserVIP() { // TODO: 实际应该调用后端 API 检查用户权限 // 这里返回 true 用于测试 return true; }, /** * 💬 发送消息到 AI(统一入口) */ sendToAI(message) { if (!message) return; console.log('[SmartUI] 发送消息到 AI:', message); // 如果 AI 聊天窗口已加载,直接发送 const chatWidget = document.getElementById('ai-chat-widget'); if (chatWidget && chatWidget._chatComponent) { chatWidget._chatComponent.sendMessage(message); } else { // 否则先注入 AI 聊天窗口 this.injectAIChat(); setTimeout(() => { const widget = document.getElementById('ai-chat-widget'); if (widget && widget._chatComponent) { widget._chatComponent.sendMessage(message); } }, 500); } } }; // 导出到全局 global.SmartUILoader = SmartUILoader; global.MODULE_COMPONENT_MAP = MODULE_COMPONENT_MAP; global.FIELD_TYPE_MAPPING = FIELD_TYPE_MAPPING; global.FieldSchemaRenderer = FieldSchemaRenderer; })(typeof window !== 'undefined' ? window : this); /** * 多模态消息发送(支持文件/图片/视频上传) */ async sendMultimodalMessage(message, attachments = {}) { const { files = [], images = [], videos = [] } = attachments; // 检查是否需要登录(如果有附件或长消息) const requiresAuth = files.length > 0 || images.length > 0 || videos.length > 0 || message.length > 100; if (requiresAuth && !this.isAuthenticated()) { await this.showLoginModal(); return; } // 显示用户消息 this.appendUserMessage(message, attachments); // 构建 FormData 用于上传文件 const formData = new FormData(); formData.append('message', message); files.forEach((file, index) => formData.append(`files[]`, file)); images.forEach((file, index) => formData.append(`images[]`, file)); videos.forEach((file, index) => formData.append(`videos[]`, file)); try { const token = localStorage.getItem('authToken') || localStorage.getItem('admin_token'); const response = await fetch(`${this.config.apiBaseUrl}/api/chat/multimodal`, { method: 'POST', headers: token ? { 'Authorization': `Bearer ${token}` } : {}, body: formData }); const data = await response.json(); if (data.reply) { this.appendAIMessage(data.reply); } else if (data.detail) { this.appendSystemMessage('处理失败:' + data.detail); } } catch (error) { console.error('[多模态聊天] 发送失败:', error); this.appendSystemMessage('发送失败,请检查网络连接'); } } /** * 检查是否已认证 */ isAuthenticated() { const token = localStorage.getItem('authToken') || localStorage.getItem('admin_token'); return !!token; } /** * 显示登录弹窗 */ async showLoginModal() { // 检查是否已有登录弹窗 if (document.querySelector('.login-modal-overlay')) { return; } const modal = document.createElement('div'); modal.className = 'login-modal-overlay'; modal.style.cssText = ` position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); display: flex; justify-content: center; align-items: center; z-index: 10000; `; modal.innerHTML = `

🔐 请先登录

此功能需要登录后才能使用

`; document.body.appendChild(modal); } /** * 执行弹窗登录 */ async performModalLogin() { const username = document.getElementById('modal-login-username').value; const password = document.getElementById('modal-login-password').value; if (!username || !password) { alert('请输入用户名和密码'); return; } try { const response = await fetch(`${this.config.apiBaseUrl}/auth/login`, { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ username, password }) }); const data = await response.json(); if (response.ok && data.token) { localStorage.setItem('authToken', data.token); localStorage.setItem('user_info', JSON.stringify({ username: data.username || username, role: data.role || 'user', permissions: data.permissions || [] })); alert('✅ 登录成功!'); document.querySelector('.login-modal-overlay').remove(); // 重新触发之前的操作 location.reload(); } else { throw new Error(data.detail || '登录失败'); } } catch (error) { alert('❌ 登录失败:' + error.message); } } /** * 显示用户消息(支持附件) */ appendUserMessage(message, attachments = {}) { const messagesContainer = document.getElementById('ai-chat-messages'); if (!messagesContainer) return; const userMsg = document.createElement('div'); userMsg.style.cssText = 'text-align: right; margin-bottom: 15px;'; let attachmentsHtml = ''; if (attachments.files?.length > 0) { attachmentsHtml += `
📎 附件:${attachments.files.length}个文件
`; } if (attachments.images?.length > 0) { attachmentsHtml += `
🖼️ 图片:${attachments.images.length}张
`; } if (attachments.videos?.length > 0) { attachmentsHtml += `
🎬 视频:${attachments.videos.length}个
`; } userMsg.innerHTML = ` ${message} ${attachmentsHtml} `; messagesContainer.appendChild(userMsg); messagesContainer.scrollTop = messagesContainer.scrollHeight; }