/** * MobileFunctionNav - 手机端功能标签导航组件 * * 功能特性: * - 横向滚动文字按钮 * - 点击触发对应工作流场景 * - 支持自定义颜色和图标 * - 触摸优化,丝滑体验 * * @example * const nav = new MobileFunctionNav('function-nav', { * functions: [ * { name: 'content-generation', label: '📝 内容生成', color: '#667eea' }, * { name: 'video-generation', label: '🎬 视频生成', color: '#764ba2' } * ], * onFunctionClick: (funcName) => { * triggerWorkflow(funcName); * } * }); * nav.render(); */ class MobileFunctionNav { constructor(containerId, options = {}) { this.containerId = containerId; this.container = document.getElementById(containerId); this.functions = options.functions || []; this.onFunctionClick = options.onFunctionClick || null; this.styles = { primaryColor: '#667eea', secondaryColor: '#764ba2' }; } /** * 渲染功能标签导航 */ render() { if (!this.container) { console.error(`MobileFunctionNav: 容器 #${this.containerId} 不存在`); return; } this.container.innerHTML = ` ${this.functions.map(fn => ` `).join('')} `; } } // 全局函数:处理功能标签点击 function handleFunctionClick(funcName, funcLabel) { console.log(`[功能导航] 点击了:${funcName} - ${funcLabel}`); // 触发工作流 if (typeof startWorkflow === 'function') { startWorkflow(funcName); } else { // 如果没有 startWorkflow,直接发送消息给 AI const input = document.getElementById('chat-input'); if (input) { input.value = `帮我${funcLabel}`; sendMessage(); } } } // 启动工作流函数 function startWorkflow(workflowType) { console.log(`[启动工作流] 类型:${workflowType}`); // ✅ 修复:根据类型调用不同的AI军团能力 const workflowConfig = { 'content-generation': { task_type: 'copywriting', prompt: '请帮我创作一段优质内容,主题是什么?', agent_id: 'marketing_copy_agent' }, 'video-generation': { task_type: 'video_generation', prompt: '请帮我生成一个视频,主题和风格是什么?', agent_id: 'video_generator_agent' }, 'image-generation': { task_type: 'image_generation', prompt: '请帮我生成一张图片,描述一下您想要的内容?', agent_id: 'image_generator_agent' }, 'ppt-generation': { task_type: 'ppt_generation', prompt: '请帮我生成一个PPT,主题是什么?', agent_id: 'ppt_generator_agent' }, 'code-generation': { task_type: 'code_generation', prompt: '请帮我生成代码,需要实现什么功能?', agent_id: 'code_generator_agent' }, 'image-analysis': { task_type: 'image_analysis', prompt: '请上传需要分析的图片', agent_id: 'image_processor_agent' }, 'video-analysis': { task_type: 'video_analysis', prompt: '请上传需要分析的视频', agent_id: 'video_parser_agent' }, 'publish-management': { task_type: 'query_task_status', prompt: '正在查询发布任务状态...', agent_id: 'video_publisher_agent' }, 'scheduled-tasks': { task_type: 'query_task_status', prompt: '正在查询定时任务...', agent_id: 'task_scheduler_agent' } }; const config = workflowConfig[workflowType]; if (!config) { console.warn(`[未知工作流] ${workflowType}`); return; } // ✅ 修复:直接调用AI军团智能接口 // 2026-09-18 P0-12: 与桌面端同源 -> 统一走协调员对话链路(frontend_content_coordinator_agent) // 原实现依赖 window.API.callSmartProcessor(该 API 不存在) -> 每次点击都 alert("系统初始化未完成") var input = document.getElementById('chat-input'); if (input) { input.value = config.prompt; input.focus(); if (typeof window.v2tip === 'function') { window.v2tip('需求已预填,补充内容后点「发送」'); } } else { console.error('未找到对话输入框 chat-input'); alert('系统初始化未完成,请刷新页面'); } } // ✅ 新增:文件上传并分析 async function uploadFileAndAnalyze(workflowType, config) { const fileType = workflowType === 'image-analysis' ? 'image' : 'video'; // 创建隐藏的文件输入框 const input = document.createElement('input'); input.type = 'file'; input.accept = fileType === 'image' ? 'image/*' : 'video/*'; input.onchange = async (e) => { const file = e.target.files[0]; if (!file) return; console.log(`[选择文件] ${file.name}, ${file.size} bytes`); try { // 1. 上传文件 addMessageToChat(`正在上传 ${file.name}...`, 'ai'); const uploadMethod = fileType === 'image' ? 'uploadImage' : 'uploadVideo'; const uploadResult = await window.API[uploadMethod](file); console.log('[上传成功]', uploadResult); // 2. 调用AI分析 addMessageToChat('正在分析文件内容...', 'ai'); const analysisMethod = fileType === 'image' ? 'analyzeImage' : 'analyzeVideo'; const analysisResult = await window.API[analysisMethod](uploadResult.file_url); console.log('[分析完成]', analysisResult); // 3. 显示分析结果 removeLoadingMessage(); addMessageToChat(`✅ 分析完成!\n\n${JSON.stringify(analysisResult, null, 2)}`, 'ai'); } catch (error) { console.error('[文件处理失败]', error); removeLoadingMessage(); addMessageToChat(`❌ 处理失败: ${error.message}`, 'ai'); } }; input.click(); } // 切换 Tab function switchTab(tabName) { console.log(`[切换 Tab] ${tabName}`); // 更新所有导航项样式 document.querySelectorAll('.nav-item').forEach(item => { item.style.color = '#999'; }); // 设置当前选中项 event.currentTarget.style.color = '#667eea'; // ✅ 修复: 调用mobile_fix_patch.js中的全局函数 switch(tabName) { case 'home': showHomeView(); break; case 'workflow': // ✅ 调用mobile_fix_patch.js中的showWorkflowView if (typeof window.showWorkflowView === 'function') { window.showWorkflowView(); } else { alert('工作流页面开发中...'); } break; case 'video': // ✅ 调用mobile_fix_patch.js中的showVideoView if (typeof window.showVideoView === 'function') { window.showVideoView(); } else { alert('视频管理页面开发中...'); } break; case 'profile': // ✅ 调用mobile_fix_patch.js中的showProfileView if (typeof window.showProfileView === 'function') { window.showProfileView(); } else { showProfile(); } break; } } // 显示首页视图 function showHomeView() { const chatContainer = document.getElementById('chat-container'); const functionNav = document.getElementById('function-nav'); const inputArea = document.getElementById('input-area'); if (chatContainer) chatContainer.style.display = 'block'; if (functionNav) functionNav.style.display = 'flex'; if (inputArea) inputArea.style.display = 'block'; } // 显示工作流视图 function showWorkflowView() { alert('工作流页面开发中...'); } // 显示个人中心视图 function showProfileView() { showProfile(); } // 显示个人中心 function showProfile() { const modal = document.getElementById('profile-modal'); const token = localStorage.getItem('authToken'); if (!token) { // 未登录,显示登录框 showLogin(); return; } // 已登录,显示个人信息 modal.style.display = 'block'; modal.innerHTML = `

👤 个人中心

👤

用户名: user123

手机号: 138****1234

会员等级: VIP

`; } // 退出登录 function logout() { if (confirm('确定要退出登录吗?')) { localStorage.removeItem('authToken'); location.reload(); } } // 多模态输入相关函数 let currentMode = 'text'; function toggleMultimodal() { const options = document.getElementById('multimodal-options'); options.style.display = options.style.display === 'none' ? 'flex' : 'none'; } function selectMode(mode) { currentMode = mode; console.log(`[选择模式] ${mode}`); // 更新按钮状态 document.querySelectorAll('.mode-btn').forEach(btn => { btn.style.background = '#f5f5f5'; btn.style.borderColor = '#ddd'; }); event.target.style.background = '#667eea'; event.target.style.borderColor = '#667eea'; event.target.style.color = 'white'; } function uploadFile(fileType) { console.log(`[上传文件] 类型:${fileType}`); // 创建隐藏的文件输入框 const input = document.createElement('input'); input.type = 'file'; input.accept = fileType === 'image' ? 'image/*' : fileType === 'video' ? 'video/*' : '*/*'; input.onchange = async (e) => { const file = e.target.files[0]; if (file) { console.log(`[选择文件] ${file.name}, ${file.size} bytes`); // TODO: 调用后端 API 上传文件 alert(`已选择文件:${file.name}\n上传功能需要对接后端 API`); } }; input.click(); } // 发送消息 async function sendMessage() { const input = document.getElementById('chat-input'); const message = input.value.trim(); if (!message) return; console.log(`[发送消息] ${message}`); // 显示用户消息到聊天区域 addMessageToChat(message, 'user'); input.value = ''; // 显示加载状态 addMessageToChat('AI 思考中...', 'ai', true); // ✅ 修复:使用callBackend统一调用,替换不存在的window.API.aiChat try { const response = await callBackend('ai_chat', { message: message, mode: 'chat' }); // 移除加载提示 removeLoadingMessage(); if (response && response.success) { // 显示 AI 回复 const reply = response.data?.reply || response.data?.content || response.data?.message || JSON.stringify(response.data); addMessageToChat(reply, 'ai'); } else { addMessageToChat('❌ AI 响应失败,请稍后重试', 'ai'); } } catch (error) { removeLoadingMessage(); console.error('[AI 调用失败]', error); addMessageToChat('❌ 网络连接失败,请检查网络', 'ai'); } } // 添加消息到聊天区域 function addMessageToChat(text, sender, isLoading = false) { const chatWrapper = document.getElementById('ai-chat-wrapper'); if (!chatWrapper) { console.error('❌ 找不到聊天容器'); return; } // 如果是第一条消息,隐藏欢迎卡片 const welcomeCard = document.querySelector('.welcome-card'); if (welcomeCard && chatWrapper.children.length === 0) { welcomeCard.style.display = 'none'; } // 创建消息元素 const messageDiv = document.createElement('div'); messageDiv.className = `chat-message ${sender}`; messageDiv.style.cssText = ` margin-bottom: 15px; padding: 12px 15px; border-radius: 12px; max-width: 85%; word-wrap: break-word; ${sender === 'user' ? 'background: linear-gradient(135deg, #667eea, #764ba2); color: white; margin-left: auto;' : 'background: #f5f5f5; color: #333; margin-right: auto;'} `; if (isLoading) { messageDiv.id = 'loading-message'; messageDiv.innerHTML = `${text || 'AI 思考中...'}`; } else { // 简单处理换行和链接(添加undefined检查) const safeText = text || ''; // WR-562k12: 除了 http(s) 绝对链接, 也把"根相对媒体路径"转成 , 否则 // 后端偶发返回 /static/...mp4 时正文里只是纯文本 -> 成片卡升级脚本扫不到 -> 不能播放。 const formattedText = safeText .replace(/\n/g, '
') .replace(/(^|[^A-Za-z0-9_\-.\/])(\/(?!\/)[^\s<>"'()\uFF09]+?\.(?:mp4|mov|webm|m4v|avi|mkv|jpg|jpeg|png|gif|webp|mp3|wav|txt|pdf))(?=$|[\s)\uFF09<])/gi, '$1
$2') .replace(/(https?:\/\/[^\s<]+)/g, '$1'); messageDiv.innerHTML = formattedText; } chatWrapper.appendChild(messageDiv); // 滚动到底部 chatWrapper.scrollTop = chatWrapper.scrollHeight; } // 移除加载提示 function removeLoadingMessage() { const loadingMsg = document.getElementById('loading-message'); if (loadingMsg) { loadingMsg.remove(); } } // 导出到全局 window.MobileFunctionNav = MobileFunctionNav; window.handleFunctionClick = handleFunctionClick; window.startWorkflow = startWorkflow; window.switchTab = switchTab; window.showProfile = showProfile; window.logout = logout; window.toggleMultimodal = toggleMultimodal; window.selectMode = selectMode; window.uploadFile = uploadFile; window.sendMessage = sendMessage; window.addMessageToChat = addMessageToChat; window.removeLoadingMessage = removeLoadingMessage;