2025-04-01 13:57:54 +08:00
|
|
|
|
<template>
|
2025-04-02 13:55:38 +08:00
|
|
|
|
<div>
|
|
|
|
|
|
<button @click="callPython">设置数据"123"到 Python</button>
|
|
|
|
|
|
<button @click="getPythonData">从 Python 获取数据</button>
|
|
|
|
|
|
<button @click="clickChildButton">从tk模拟点击按钮 </button>
|
|
|
|
|
|
<input type="text" id="input" v-model="inputValue"></input>
|
|
|
|
|
|
<div id="output">{{ output }}</div>
|
|
|
|
|
|
<h1>嵌入tk页面</h1>
|
|
|
|
|
|
<iframe id="myIframe" src="https://live-backstage.tiktok.com/portal/overview" width="100%" height="600px"
|
|
|
|
|
|
frameborder="0" ref="myIframe"></iframe>
|
2025-04-01 13:57:54 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
2025-04-01 16:04:54 +08:00
|
|
|
|
<script setup>
|
2025-04-02 13:55:38 +08:00
|
|
|
|
import { ref, onMounted } from 'vue';
|
2025-04-01 13:57:54 +08:00
|
|
|
|
|
2025-04-02 13:55:38 +08:00
|
|
|
|
const myIframe = ref(null);
|
|
|
|
|
|
let inputValue = ref('999');
|
|
|
|
|
|
// 确保 DOM 渲染完成后再访问 iframe
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
|
if (myIframe.value) {
|
|
|
|
|
|
// console.log('Iframe mounted:', myIframe.value);
|
|
|
|
|
|
onIframeLoad();
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2025-04-01 16:04:54 +08:00
|
|
|
|
|
2025-04-02 13:55:38 +08:00
|
|
|
|
const onIframeLoad = () => {
|
|
|
|
|
|
if (myIframe.value) {
|
|
|
|
|
|
const iframeDoc = myIframe.value.contentDocument;
|
|
|
|
|
|
|
|
|
|
|
|
// const button = iframeDoc.querySelector('button[data-id="add-host-btn"]')[0];
|
|
|
|
|
|
// if (button) {
|
|
|
|
|
|
// button.click(); // 触发点击事件
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
console.log('Iframe loaded:', iframeDoc);
|
|
|
|
|
|
if (iframeDoc) {
|
|
|
|
|
|
// console.log('Iframe loaded:', iframeDoc);
|
|
|
|
|
|
|
|
|
|
|
|
// 注入脚本
|
|
|
|
|
|
const script = iframeDoc.createElement('script');
|
|
|
|
|
|
// console.log('script:', script);
|
|
|
|
|
|
script.textContent = `
|
|
|
|
|
|
(function() {
|
|
|
|
|
|
// 拦截 XMLHttpRequest
|
|
|
|
|
|
const originalOpen = XMLHttpRequest.prototype.open;
|
|
|
|
|
|
const originalSend = XMLHttpRequest.prototype.send;
|
|
|
|
|
|
|
|
|
|
|
|
XMLHttpRequest.prototype.open = function(method, url, async, user, password) {
|
|
|
|
|
|
this._method = method; // 保存请求方法
|
|
|
|
|
|
this._url = url; // 保存请求的URL
|
|
|
|
|
|
return originalOpen.apply(this, arguments);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
XMLHttpRequest.prototype.send = function(body) {
|
|
|
|
|
|
if (this._url && this._url.includes('batch_check_anchor')) {
|
|
|
|
|
|
this.addEventListener('load', function() {
|
|
|
|
|
|
console.log('[XHR] 拦截到 batch_check_anchor 请求:');
|
|
|
|
|
|
console.log('URL:', this._url);
|
|
|
|
|
|
console.log('方法:', this._method);
|
|
|
|
|
|
console.log('请求体:', body);
|
|
|
|
|
|
console.log('响应:', this.responseText);
|
|
|
|
|
|
console.log('------------------------');
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
return originalSend.apply(this, arguments);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 拦截 fetch
|
|
|
|
|
|
const originalFetch = window.fetch;
|
|
|
|
|
|
|
|
|
|
|
|
window.fetch = async function(...args) {
|
|
|
|
|
|
const [input, init] = args;
|
|
|
|
|
|
const url = typeof input === 'string' ? input : input.url;
|
|
|
|
|
|
|
|
|
|
|
|
if (url && url.includes('batch_check_anchor')) {
|
|
|
|
|
|
console.log('[Fetch] 拦截到 batch_check_anchor 请求:');
|
|
|
|
|
|
console.log('URL:', url);
|
|
|
|
|
|
console.log('方法:', (init && init.method) || 'GET');
|
|
|
|
|
|
console.log('请求体:', (init && init.body) || null);
|
|
|
|
|
|
|
|
|
|
|
|
const response = await originalFetch.apply(this, args);
|
|
|
|
|
|
const clonedResponse = response.clone();
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
const data = await clonedResponse.json();
|
|
|
|
|
|
console.log('响应:', data);
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
const text = await clonedResponse.text();
|
|
|
|
|
|
console.log('响应:', text);
|
|
|
|
|
|
}
|
|
|
|
|
|
console.log('------------------------');
|
|
|
|
|
|
return response;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return originalFetch.apply(this, args);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
console.log('batch_check_anchor 拦截器已成功注入');
|
|
|
|
|
|
|
|
|
|
|
|
console.log("123123123123132",document.querySelectorAll('button[data-id="view-more"]'))
|
|
|
|
|
|
})();
|
|
|
|
|
|
`;
|
|
|
|
|
|
iframeDoc.body.appendChild(script);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
console.error('无法访问 iframe 的 contentDocument');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
console.log(123)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
console.error('无法获取 iframe 引用');
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const output = ref('');
|
|
|
|
|
|
const bridge = ref(null);
|
|
|
|
|
|
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
|
new QWebChannel(qt.webChannelTransport, function (channel) {
|
|
|
|
|
|
bridge.value = channel.objects.bridge;
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const callPython = () => {
|
|
|
|
|
|
if (bridge.value) {
|
|
|
|
|
|
bridge.value.stringFromJs("123")
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const getPythonData = () => {
|
|
|
|
|
|
if (bridge.value) {
|
|
|
|
|
|
bridge.value.stringToJs(function (result) {
|
|
|
|
|
|
alert(result); // 这里才会显示返回值
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const clickChildButton = () => {
|
|
|
|
|
|
const iframeDoc = myIframe.value.contentDocument;
|
|
|
|
|
|
console.log(iframeDoc)
|
|
|
|
|
|
// 查找子页面中的按钮(假设按钮 id 为 child-button)
|
|
|
|
|
|
|
|
|
|
|
|
};
|
2025-04-01 13:57:54 +08:00
|
|
|
|
</script>
|