// pythonBridge.js // 适配 pywebview API (替代原有的 QWebChannel) import { ref, onMounted } from 'vue'; const bridge = ref(null); const isReady = ref(false); /** * 等待 pywebview API 准备就绪 * @returns {Promise} */ const waitForPywebview = () => { return new Promise((resolve) => { // 如果已经存在,直接返回 if (window.pywebview && window.pywebview.api) { resolve(); return; } // 监听 pywebviewready 事件 window.addEventListener('pywebviewready', () => { resolve(); }, { once: true }); }); }; /** * 统一安全调用 pywebview API * pywebview 的方法调用会返回 Promise */ const callBridge = async (method, ...args) => { if (!bridge.value || typeof bridge.value[method] !== 'function') { console.warn(`[pythonBridge] 方法不存在: ${method}`); return null; } try { const result = await bridge.value[method](...args); return result; } catch (error) { console.error(`[pythonBridge] 调用 ${method} 失败:`, error); return null; } }; /** * 初始化 pywebview 桥接 */ const initBridge = async () => { // 监听 DevTools 快捷键 (Ctrl + Shift + P) window.addEventListener('keydown', (e) => { // 1. 自定义快捷键: Ctrl + Shift + P -> 调用后端 if (e.ctrlKey && e.shiftKey && (e.key === 'p' || e.key === 'P')) { e.preventDefault(); callBridge('openDevTools'); return; } // 2. 屏蔽 F12 (防止用户按下 F12 打开) if (e.key === 'F12') { e.preventDefault(); return; } }); // 开发环境 (localhost) 不初始化 if (/localhost/.test(window.location.href)) { console.log('[pythonBridge] 开发环境,跳过初始化'); return; } await waitForPywebview(); if (window.pywebview && window.pywebview.api) { bridge.value = window.pywebview.api; isReady.value = true; console.log('[pythonBridge] 初始化成功'); } else { console.error('[pythonBridge] pywebview API 初始化失败'); } }; export function usePythonBridge() { // 调用 Python 方法 const fetchDataConfig = async (data) => { if (!bridge.value) return null; return await callBridge('fetchDataConfig', data); }; // 查询获取主播的数据 const fetchDataCount = async () => { if (!bridge.value) return null; const result = await callBridge('fetchDataCount'); // pywebview 返回的是字符串,需要解析 try { return typeof result === 'string' ? JSON.parse(result) : result; } catch { return result; } }; // 打开 tk 后台 const loginTikTok = () => { callBridge('loginTikTok'); }; // 登录 tk 后台 const loginBackStage = (data) => { if (data.index == 0) { callBridge('loginBackStage', JSON.stringify(data)); } else if (data.index == 1) { callBridge('loginBackStageCopy', JSON.stringify(data)); } }; // 跳转到主播页面 const givePyAnchorId = (id) => { callBridge('givePyAnchorId', id); }; // 查询登录状态 const backStageloginStatus = async () => { if (!bridge.value) return null; const result = await callBridge('backStageloginStatus'); try { return typeof result === 'string' ? JSON.parse(result) : result; } catch { return result; } }; // 查询登录状态(副账号) const backStageloginStatusCopy = async () => { if (!bridge.value) return null; const result = await callBridge('backStageloginStatusCopy'); try { return typeof result === 'string' ? JSON.parse(result) : result; } catch { return result; } }; // 导出表格 const exportToExcel = (data) => { callBridge('exportToExcel', JSON.stringify(data)); }; const stopScript = () => { callBridge('stopScript'); }; // 获取版本号 const getVersion = async () => { if (!bridge.value) return null; return await callBridge('currentVersion'); }; // 存储账号信息 const storageAccountInfo = async (key, data) => { if (!bridge.value) return false; return await callBridge('storageAccountInfo', key, JSON.stringify(data)); }; // 读取账号信息 const readAccountInfo = async (key) => { if (!bridge.value) return null; const result = await callBridge('readAccountInfo', key); try { return typeof result === 'string' ? JSON.parse(result) : result; } catch { return result; } }; // 在组件挂载时初始化桥接 onMounted(initBridge); return { isReady, fetchDataConfig, fetchDataCount, loginBackStage, loginTikTok, givePyAnchorId, backStageloginStatus, backStageloginStatusCopy, exportToExcel, stopScript, getVersion, storageAccountInfo, readAccountInfo, }; }