/** * 智能 UI 组件库 - 核心渲染引擎 * * 功能: * 1. 根据后端模块元数据自动生成界面 * 2. 提供通用 UI 组件(DataTable, FormGenerator, ActionPanel 等) * 3. 支持自动布局适配 * 4. 提供统一的事件处理和状态管理 * * 使用方式: * const renderer = new SmartUIRenderer(); * await renderer.renderModule(moduleName, moduleInfo, schema, uiConfig); */ class SmartUIRenderer { constructor() { this.components = {}; this.layouts = {}; this.registerDefaultComponents(); } /** * 注册默认组件 */ registerDefaultComponents() { // ========== 1. 数据表格组件 ========== this.components['DataTable'] = class DataTable { render(data, config) { if (!data || data.length === 0) { return '
暂无数据
'; } const columns = config.columns || []; return `
${columns.map(col => ``).join('')} ${config.actions ? '' : ''} ${data.map((row, index) => ` ${columns.map(col => ``).join('')} ${config.actions ? ` ` : ''} `).join('')}
${col.label}操作
${this.formatValue(row[col.field], col.format)} ${config.actions.map(action => ` `).join('')}
`; } formatValue(value, format) { if (value === null || value === undefined) return '-'; if (format === 'date') return new Date(value).toLocaleString(); if (format === 'currency') return '¥' + parseFloat(value).toFixed(2); if (format === 'percentage') return (value * 100).toFixed(1) + '%'; return String(value); } }; // ========== 2. 表单生成器组件 ========== this.components['FormGenerator'] = class FormGenerator { render(schema, formData = {}, onSubmit) { const fields = schema.parameters || []; return `
${fields.map(field => `
${field.label ? `` : ''} ${this.renderField(field, formData[field.name])} ${field.description ? `${field.description}` : ''}
`).join('')}
`; } renderField(field, value) { const name = field.name; const defaultValue = value || field.default || ''; if (field.enum) { return ` `; } switch(field.type) { case 'number': return ``; case 'boolean': return ``; case 'text': case 'string': if (field.multiline) { return ``; } return ``; case 'object': return ``; default: return ``; } } }; // ========== 3. 操作面板组件 ========== this.components['ActionPanel'] = class ActionPanel { render(actions, layout = 'horizontal') { return `
${actions.map(action => ` `).join('')}
`; } }; // ========== 4. 日志控制台组件 ========== this.components['LogConsole'] = class LogConsole { render(logs, autoScroll = true) { return `
📝 运行日志
${logs.map(log => `
[${new Date(log.time).toLocaleTimeString()}] ${log.message}
`).join('')}
`; } addLog(containerId, message, level = 'info') { const container = document.querySelector(`#${containerId} .log-content`); if (container) { const line = document.createElement('div'); line.className = `log-line log-${level}`; line.innerHTML = ` [${new Date().toLocaleTimeString()}] ${message} `; container.appendChild(line); // 自动滚动到底部 if (container.parentElement.dataset.autoScroll === 'true') { container.scrollTop = container.scrollHeight; } } } }; // ========== 5. 卡片网格组件 ========== this.components['CardGrid'] = class CardGrid { render(items, cardTemplate) { return `
${items.map(item => `
${cardTemplate(item)}
`).join('')}
`; } }; // ========== 6. 图表组件(简化版) ========== this.components['ChartWidget'] = class ChartWidget { render(chartType, data, options = {}) { // 实际项目中应该集成 Chart.js 或 ECharts return `
`; } }; } /** * 根据模块元数据渲染界面 */ async renderModule(moduleName, moduleInfo, schema, uiConfig) { const container = document.getElementById('module-content'); if (!container) { throw new Error('未找到内容容器 #module-content'); } const layout = uiConfig?.layout || 'default'; const actions = schema.actions || []; const dataModels = schema.data_models || []; const uiHints = schema.ui_hints || {}; // 根据功能类型选择渲染策略 let html = ''; if (uiHints.primary_action === 'start_agent' || actions.some(a => a.name.includes('start'))) { // 智能体控制类型 html = this.renderAgentControl(moduleInfo, actions, schema); } else if (dataModels.length > 0) { // 数据管理类型 html = this.renderDataManagement(moduleInfo, dataModels, actions); } else if (actions.some(a => a.parameters?.length > 0)) { // 工具函数类型 html = this.renderToolInterface(moduleInfo, actions); } else { // 默认类型 html = this.renderDefaultInterface(moduleInfo, actions); } container.innerHTML = html; // 初始化事件绑定 this.bindEvents(actions, moduleName); // 如果需要实时日志,启动日志监听 if (uiHints.realtime_monitor) { this.startLogMonitor(moduleName); } } /** * 渲染智能体控制界面 */ renderAgentControl(moduleInfo, actions, schema) { const startAction = actions.find(a => a.name === 'start_agent' || a.name === 'start'); const stopAction = actions.find(a => a.name === 'stop_agent' || a.name === 'stop'); return `

${moduleInfo.icon || ''} ${moduleInfo.name}

离线
${moduleInfo.description}
${startAction ? ` ` : ''} ${stopAction ? ` ` : ''}
${schema.ui_hints?.show_logs ? `
` : ''}
`; } /** * 渲染数据管理界面 */ renderDataManagement(moduleInfo, dataModels, actions) { const primaryModel = dataModels[0]; return `

${moduleInfo.icon || ''} ${moduleInfo.name}

${actions.map(action => ` `).join('')}
${primaryModel.fields.map(field => ``).join('')}
${field.label || field.name}
加载中...
`; } /** * 渲染工具函数界面 */ renderToolInterface(moduleInfo, actions) { return `

${moduleInfo.icon || ''} ${moduleInfo.name}

${moduleInfo.description}

${actions.map(action => `

${action.label || action.name}

${action.description || ''}

${(action.parameters || []).map(param => `
${param.label ? `` : ''} ${this.renderInput(param)}
`).join('')}
`).join('')}
`; } renderInput(param) { if (param.enum) { return ``; } if (param.type === 'number') { return ``; } if (param.type === 'boolean') { return ``; } if (param.multiline) { return ``; } return ``; } /** * 渲染默认界面 */ renderDefaultInterface(moduleInfo, actions) { return `

${moduleInfo.icon || ''} ${moduleInfo.name}

${moduleInfo.description}

${actions.map(action => `

${action.label || action.name}

${action.description || ''}

`).join('')}
`; } /** * 绑定事件 */ bindEvents(actions, moduleName) { window.SmartUI = window.SmartUI || {}; window.SmartUI.actions = window.SmartUI.actions || {}; actions.forEach(action => { if (!window.SmartUI.actions[action.name]) { window.SmartUI.actions[action.name] = async () => { try { const response = await fetch(API_CONFIG.baseURL + action.endpoint, { method: action.method || 'GET', headers: { 'Content-Type': 'application/json' }, body: action.parameters?.length ? JSON.stringify({}) : undefined }); if (!response.ok) throw new Error(`HTTP ${response.status}`); const result = await response.json(); this.showToast('success', `${action.label || action.name}成功`); return result; } catch (error) { this.showToast('error', `${action.label || action.name}失败:${error.message}`); throw error; } }; } }); } /** * 启动日志监控 */ async startLogMonitor(moduleName) { const logConsole = document.querySelector('#log-console'); if (!logConsole) return; // 简单实现:每 3 秒轮询一次日志 setInterval(async () => { try { const response = await fetch(`${API_CONFIG.baseURL}/modules/${moduleName}/logs`); if (response.ok) { const logs = await response.json(); const consoleComponent = new this.components.LogConsole(); logConsole.innerHTML = consoleComponent.render(logs); } } catch (error) { // 忽略错误 } }, 3000); } /** * 显示 Toast 提示 */ showToast(type, message) { const toast = document.createElement('div'); toast.className = `toast toast-${type}`; toast.textContent = message; toast.style.cssText = ` position: fixed; top: 20px; right: 20px; padding: 12px 24px; background: ${type === 'success' ? '#52c41a' : '#ff4d4f'}; color: white; border-radius: 4px; z-index: 9999; animation: slideIn 0.3s ease; `; document.body.appendChild(toast); setTimeout(() => { toast.style.animation = 'slideOut 0.3s ease'; setTimeout(() => toast.remove(), 300); }, 3000); } /** * 猜测 UI 配置(当后端未提供时) */ guessUIConfig(moduleInfo) { const category = moduleInfo.category || 'tool'; const layoutMap = { 'automation': 'dashboard', 'data': 'list', 'tool': 'form', 'workflow': 'dashboard', 'management': 'list' }; return { layout: layoutMap[category] || 'default', icon: this.getIconForCategory(category), color: '#4361ee', sidebar: true, breadcrumb: true }; } getIconForCategory(category) { const icons = { 'automation': '🤖', 'data': '📊', 'tool': '🛠️', 'workflow': '📋', 'management': '⚙️' }; return icons[category] || '📦'; } } // 导出全局实例 if (typeof window !== 'undefined') { window.SmartUIRenderer = SmartUIRenderer; }