192 lines
4.7 KiB
JavaScript
192 lines
4.7 KiB
JavaScript
// pythonBridge.js
|
|
// 适配 pywebview API (替代原有的 QWebChannel)
|
|
import { ref, onMounted } from 'vue';
|
|
|
|
const bridge = ref(null);
|
|
const isReady = ref(false);
|
|
|
|
/**
|
|
* 等待 pywebview API 准备就绪
|
|
* @returns {Promise<void>}
|
|
*/
|
|
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,
|
|
};
|
|
}
|