// 引入 Vue 功能 import { ref, reactive, nextTick, watch, onMounted } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'; export default { // 接收父组件(main.js)传来的数据:是否打开窗口、API配置 props: ['isOpen', 'apiConfig'], emits: ['close'], // 定义可以向父组件发送的事件 setup(props, { emit }) { // === 1. 数据定义 === const qqData = reactive({ chatList: [], currentChatId: null, inputMsg: '', isSending: false }); const isSettingsOpen = ref(false); const tempSettings = reactive({}); const chatContainer = ref(null); // === 2. 核心逻辑 === // 读取/保存存档 const STORAGE_KEY = 'my_phone_qq_data_v1'; onMounted(() => { const saved = localStorage.getItem(STORAGE_KEY); if (saved) qqData.chatList = JSON.parse(saved); }); watch(() => qqData.chatList, () => { localStorage.setItem(STORAGE_KEY, JSON.stringify(qqData.chatList)); }, { deep: true }); // 创建新聊天 const createChat = () => { const name = prompt("请输入 AI 的本名:"); if (!name) return; const remark = prompt("备注名 (可选):", name); qqData.chatList.unshift({ id: Date.now(), name, remark: remark || name, avatar: '', userAvatar: '', gender: '未知', aiPersona: '', userPersona: '', messages: [], lastMsg: '新好友', lastTime: '刚刚' }); }; const enterChat = (id) => { qqData.currentChatId = id; nextTick(() => scrollToBottom()); }; const getCurrentChat = () => qqData.chatList.find(c => c.id === qqData.currentChatId) || {}; const scrollToBottom = () => { if (chatContainer.value) chatContainer.value.scrollTop = chatContainer.value.scrollHeight; }; // 发送消息 (核心 AI 对话逻辑) const sendMessage = async () => { if (!qqData.inputMsg.trim() || qqData.isSending) return; // 检查 API 配置 (从 props 获取) if (!props.apiConfig.key) { alert("⚠️ 请先去【系统设置】配置 API!"); return; } const chat = getCurrentChat(); const text = qqData.inputMsg; qqData.inputMsg = ''; // 用户消息上屏 chat.messages.push({ role: 'user', content: text }); chat.lastMsg = text; nextTick(() => scrollToBottom()); qqData.isSending = true; try { // 构建 Prompt let systemPrompt = `你扮演:${chat.name}。${chat.gender !== '未知' ? '性别:'+chat.gender : ''}。`; if (chat.aiPersona) systemPrompt += `\n人设:${chat.aiPersona}`; if (chat.userPersona) systemPrompt += `\n用户设定:${chat.userPersona}`; systemPrompt += `\n请沉浸角色,直接回复内容。`; const messages = [ { role: "system", content: systemPrompt }, ...chat.messages.slice(-10).map(m => ({ role: m.role, content: m.content })) ]; // 调用 API let baseUrl = props.apiConfig.endpoint.replace(/\/+$/, ''); if (baseUrl.endsWith('/v1')) baseUrl = baseUrl.slice(0, -3); const res = await fetch(`${baseUrl}/v1/chat/completions`, { method: 'POST', headers: { 'Authorization': `Bearer ${props.apiConfig.key}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ model: props.apiConfig.model || 'gpt-3.5-turbo', messages: messages }) }); const data = await res.json(); const reply = data.choices[0].message.content; chat.messages.push({ role: 'assistant', content: reply }); chat.lastMsg = reply; nextTick(() => scrollToBottom()); } catch (e) { alert("发送失败: " + e.message); } finally { qqData.isSending = false; } }; // === 3. 界面模板 (HTML) === // 注意:这里使用反引号 ` ` 包裹 HTML return { qqData, isSettingsOpen, tempSettings, chatContainer, createChat, enterChat, getCurrentChat, sendMessage, closeWindow: () => emit('close') }; }, template: `
消息列表
+
关闭
{{ chat.remark }}
{{ chat.lastMsg }}
‹ 列表
{{ getCurrentChat().remark }}
⚙️
{{ msg.content }}
` }