FEAT => 本次更新项目为:

基础通信搞定了
This commit is contained in:
2025-08-01 16:29:34 +08:00
parent 325d53cad6
commit fddda27ca8
11 changed files with 1179 additions and 41 deletions

View File

@@ -2,7 +2,6 @@ import React from "react";
import { createRoot } from "react-dom/client";
import App from "./App";
import "./styles/global.scss";
// import VConsole from "vconsole";
// new VConsole();
const root = createRoot(document.getElementById("root")!);

View File

@@ -0,0 +1,278 @@
.iframe-debug-page {
min-height: 100vh;
background: var(--primary-gradient);
padding: 20px;
font-family:
-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}
.header {
text-align: center;
color: white;
margin-bottom: 30px;
h1 {
font-size: 2.5rem;
margin: 0 0 10px 0;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);
}
p {
font-size: 1.1rem;
margin: 0;
opacity: 0.9;
}
}
.content {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 30px;
margin-bottom: 30px;
@media (max-width: 768px) {
grid-template-columns: 1fr;
gap: 20px;
}
}
.control-panel,
.message-panel {
background: white;
border-radius: 15px;
padding: 25px;
box-shadow: 0 10px 30px var(--primary-shadow);
h3 {
margin: 0 0 20px 0;
color: #333;
font-size: 1.3rem;
border-bottom: 2px solid var(--primary-color);
padding-bottom: 10px;
}
}
.input-group {
display: flex;
gap: 10px;
margin-bottom: 20px;
@media (max-width: 480px) {
flex-direction: column;
}
}
.message-input {
flex: 1;
padding: 12px 15px;
border: 2px solid #e1e5e9;
border-radius: 8px;
font-size: 1rem;
transition: border-color 0.3s ease;
&:focus {
outline: none;
border-color: var(--primary-color);
box-shadow: 0 0 0 3px var(--primary-shadow-light);
}
}
.button-group {
display: flex;
gap: 10px;
flex-wrap: wrap;
}
.btn {
padding: 12px 20px;
border: none;
border-radius: 8px;
font-size: 1rem;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
text-transform: uppercase;
letter-spacing: 0.5px;
&:hover {
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
}
&:active {
transform: translateY(0);
}
&.btn-primary {
background: var(--primary-gradient);
color: white;
&:hover {
background: linear-gradient(
135deg,
var(--primary-color-dark) 0%,
var(--primary-color) 100%
);
}
}
&.btn-secondary {
background: linear-gradient(
135deg,
var(--primary-color-light) 0%,
var(--primary-color) 100%
);
color: white;
&:hover {
background: linear-gradient(
135deg,
var(--primary-color) 0%,
var(--primary-color-dark) 100%
);
}
}
&.btn-danger {
background: linear-gradient(135deg, #ff6b6b 0%, #ee5a52 100%);
color: white;
&:hover {
background: linear-gradient(135deg, #ee5a52 0%, #d63031 100%);
}
}
}
.message-list {
max-height: 400px;
overflow-y: auto;
border: 1px solid #e1e5e9;
border-radius: 8px;
padding: 10px;
background: #f8f9fa;
}
.no-messages {
text-align: center;
color: #6c757d;
font-style: italic;
padding: 20px;
}
.message-item {
background: white;
padding: 12px 15px;
margin-bottom: 8px;
border-radius: 6px;
border-left: 4px solid var(--primary-color);
box-shadow: 0 2px 4px var(--primary-shadow-light);
&:last-child {
margin-bottom: 0;
}
}
.message-text {
font-family: "Courier New", monospace;
font-size: 0.9rem;
color: #333;
word-break: break-all;
line-height: 1.4;
}
.info-panel {
background: white;
border-radius: 15px;
padding: 25px;
box-shadow: 0 10px 30px var(--primary-shadow);
h3 {
margin: 0 0 20px 0;
color: #333;
font-size: 1.3rem;
border-bottom: 2px solid var(--primary-color);
padding-bottom: 10px;
}
}
.info-item {
margin-bottom: 12px;
padding: 10px;
background: #f8f9fa;
border-radius: 6px;
border-left: 3px solid var(--primary-color);
strong {
color: #495057;
margin-right: 8px;
}
&:last-child {
margin-bottom: 0;
}
}
// 滚动条样式
.message-list::-webkit-scrollbar {
width: 8px;
}
.message-list::-webkit-scrollbar-track {
background: #f1f1f1;
border-radius: 4px;
}
.message-list::-webkit-scrollbar-thumb {
background: #c1c1c1;
border-radius: 4px;
&:hover {
background: #a8a8a8;
}
}
// 响应式设计
@media (max-width: 768px) {
.iframe-debug-page {
padding: 15px;
}
.header h1 {
font-size: 2rem;
}
.control-panel,
.message-panel,
.info-panel {
padding: 20px;
}
.btn {
padding: 10px 16px;
font-size: 0.9rem;
}
}
@media (max-width: 480px) {
.header h1 {
font-size: 1.8rem;
}
.content {
gap: 15px;
}
.control-panel,
.message-panel,
.info-panel {
padding: 15px;
}
.button-group {
flex-direction: column;
}
.btn {
width: 100%;
}
}

View File

@@ -0,0 +1,264 @@
import React, { useState, useEffect, useRef } from "react";
import style from "./index.module.scss";
// 声明全局的 uni 对象
declare global {
interface Window {
uni: any;
}
}
interface Message {
id: number;
type: string;
data: any;
timestamp: number;
}
const IframeDebugPage: React.FC = () => {
const [receivedMessages, setReceivedMessages] = useState<string[]>([]);
const [messageId, setMessageId] = useState(0);
const [inputMessage, setInputMessage] = useState("");
useEffect(() => {
// 初始化 uni-app web-view SDK
const initUniSDK = () => {
console.log("web-view SDK 初始化完成");
// 页面加载完成后发送准备就绪消息
setTimeout(() => {
sendMessageToParent({
id: 0,
type: "ready",
data: { status: "loaded", url: window.location.href },
timestamp: Date.now(),
});
}, 500);
};
// 监听 SDK 初始化完成事件
document.addEventListener("UniAppJSBridgeReady", initUniSDK);
// 检查URL参数中的消息
checkUrlMessage();
// 监听 postMessage 事件(备用方案)
const handlePostMessage = (event: MessageEvent) => {
console.log("收到 postMessage:", event.data);
// 处理 uni.postMessage 发送的消息格式
if (event.data && typeof event.data === "object") {
// uni.postMessage 发送的消息格式是 { data: message }
if (event.data.data) {
handleParentMessage(event.data.data);
} else {
// 直接发送的消息格式
handleParentMessage(event.data);
}
}
};
window.addEventListener("message", handlePostMessage);
return () => {
document.removeEventListener("UniAppJSBridgeReady", initUniSDK);
window.removeEventListener("message", handlePostMessage);
};
}, []);
// 检查URL参数中的消息
const checkUrlMessage = () => {
const urlParams = new URLSearchParams(window.location.search);
const messageParam = urlParams.get("message");
if (messageParam) {
try {
const message = JSON.parse(decodeURIComponent(messageParam));
handleParentMessage(message);
// 清除URL参数
const newUrl = window.location.pathname;
window.history.replaceState({}, "", newUrl);
} catch (e) {
console.error("解析URL消息失败:", e);
}
}
};
// 移除 localStorage 相关代码,使用 postMessage 通信
// 接收 App 发送的消息(需与 App 端 evalJS 调用的函数名一致)
const receiveFromApp = (data: any) => {
console.log("web-view 收到 App 消息:", data);
handleParentMessage(data);
};
// 将函数挂载到全局,供 App 端调用
useEffect(() => {
(window as any).receiveFromApp = receiveFromApp;
return () => {
delete (window as any).receiveFromApp;
};
}, []);
// 接收 App 发送的消息
const handleParentMessage = (message: Message) => {
console.log("web-view 收到 App 消息:", message);
const messageText = `[${new Date().toLocaleTimeString()}] 收到: ${JSON.stringify(message)}`;
setReceivedMessages(prev => [...prev, messageText]);
// 根据消息类型进行不同处理
if (message.type === "command") {
if (message.data?.action === "update") {
// 更新页面内容
console.log("执行更新操作:", message.data.content);
}
} else if (message.type === "fromApp") {
console.log("收到 App 消息:", message.data?.content);
}
};
// 向 App 发送消息
const sendMessageToParent = (message: Message) => {
console.log("web-view 发送消息到 App:", message);
// 通过 uni.postMessage 发送消息(数据必须放在 data 字段中)
if (window.uni && window.uni.postMessage) {
try {
window.uni.postMessage({
data: message,
});
console.log("通过 uni.postMessage 发送消息到 App:", message);
} catch (e) {
console.error("uni.postMessage 失败:", e);
}
} else {
console.error("uni 对象不存在,无法发送消息");
}
};
// 向 App 发送消息
const sendCustomMessage = () => {
if (!inputMessage.trim()) return;
const newMessageId = messageId + 1;
setMessageId(newMessageId);
const message: Message = {
id: newMessageId,
type: "toApp",
data: {
content: inputMessage,
source: "web-view",
timestamp: Date.now(),
},
timestamp: Date.now(),
};
sendMessageToParent(message);
setInputMessage("");
};
// 发送测试消息到 App
const sendTestMessage = () => {
const newMessageId = messageId + 1;
setMessageId(newMessageId);
const message: Message = {
id: newMessageId,
type: "toApp",
data: {
action: "ping",
content: `web-view测试消息 ${newMessageId}`,
random: Math.random(),
},
timestamp: Date.now(),
};
sendMessageToParent(message);
};
// 清空消息列表
const clearMessages = () => {
setInputMessage("");
setReceivedMessages([]);
};
return (
<div className={style["iframe-debug-page"]}>
<div className={style.header}>
<h1>iframe </h1>
<p>: {new Date().toLocaleString()}</p>
</div>
<div className={style.content}>
<div className={style["control-panel"]}>
<h3></h3>
<div className={style["input-group"]}>
<input
type="text"
value={inputMessage}
onChange={e => setInputMessage(e.target.value)}
placeholder="输入要发送的消息"
className={style["message-input"]}
/>
<button
onClick={sendCustomMessage}
className={`${style.btn} ${style["btn-primary"]}`}
>
</button>
</div>
<div className={style["button-group"]}>
<button
onClick={sendTestMessage}
className={`${style.btn} ${style["btn-secondary"]}`}
>
</button>
<button
onClick={clearMessages}
className={`${style.btn} ${style["btn-danger"]}`}
>
</button>
</div>
</div>
<div className={style["message-panel"]}>
<h3> ({receivedMessages.length})</h3>
<div className={style["message-list"]}>
{receivedMessages.length === 0 ? (
<div className={style["no-messages"]}></div>
) : (
receivedMessages.map((msg, index) => (
<div key={index} className={style["message-item"]}>
<span className={style["message-text"]}>{msg}</span>
</div>
))
)}
</div>
</div>
</div>
<div className={style["info-panel"]}>
<h3></h3>
<div className={style["info-item"]}>
<strong>URL:</strong> {window.location.href}
</div>
<div className={style["info-item"]}>
<strong>User Agent:</strong> {navigator.userAgent}
</div>
<div className={style["info-item"]}>
<strong>:</strong> {window.innerWidth} x {window.innerHeight}
</div>
<div className={style["info-item"]}>
<strong>ID:</strong> {messageId}
</div>
</div>
</div>
);
};
export default IframeDebugPage;

View File

@@ -0,0 +1,12 @@
import IframeDebugPage from "@/pages/iframe";
// iframe 调试路由
const iframeRoutes = [
{
path: "/iframe",
element: <IframeDebugPage />,
auth: false, // 不需要认证,方便调试
},
];
export default iframeRoutes;

View File

@@ -36,9 +36,9 @@ export const ENV_INFO = {
// 开发环境检查
export const checkDevEnvironment = () => {
if (isDevelopment) {
console.log("🚀 开发环境已启用");
console.log("📋 环境信息:", ENV_INFO);
console.log("⚙️ 开发特性:", DEV_FEATURES);
// console.log("🚀 开发环境已启用");
// console.log("📋 环境信息:", ENV_INFO);
// console.log("⚙️ 开发特性:", DEV_FEATURES);
}
};