Files
cunkebao_v3/ckApp/pages/index/index.vue
超级老白兔 2e01757519 FEAT => 本次更新项目为:
定版本app通信
2025-08-02 11:32:04 +08:00

594 lines
13 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="content">
<view class="header">
123
</view>
<!-- iframe 容器 -->
<view class="iframe-container" :class="'iframe-' + iframeSize">
<web-view
ref="webviewRef"
:src="iframeUrl"
@message="handleMessage"
:fullscreen="false"
:webview-styles="{
width:'100%',
height:'260px'
}"
></web-view>
</view>
<!-- 控制按钮 -->
<view class="controls">
<button @click="sendMessageToIframe" class="btn">发送消息到iframe</button>
<button @click="toggleIframeSize" class="btn btn-secondary">切换iframe大小</button>
<button @click="refreshIframe" class="btn btn-refresh">刷新iframe</button>
</view>
<!-- URL 参数控制区域 -->
<view class="url-controls">
<text class="url-title">URL 参数控制</text>
<view class="param-buttons">
<button @click="addUrlParam('testParam', 'testValue')" class="btn-param">添加测试参数</button>
<button @click="updateUrlParams({theme: 'light', userId: '67890'})" class="btn-param">更新主题和用户ID</button>
<button @click="removeUrlParam('token')" class="btn-param btn-danger">移除token</button>
<button @click="demoUrlParams()" class="btn-param btn-demo">演示参数传递</button>
</view>
<view class="current-url">
<text class="url-label">当前URL</text>
<text class="url-text">{{iframeUrl}}</text>
</view>
</view>
<!-- 消息显示区域 -->
<view class="message-area">
<text class="message-title">接收到的消息</text>
<view class="message-list">
<view v-for="(msg, index) in receivedMessages" :key="index" class="message-item">
<text class="message-text">{{msg}}</text>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
title: 'iframe 通信示例',
// iframeUrl: 'http://localhost:3000/iframe',
baseUrl: 'https://kr-op.quwanzhi.com/iframe',
iframeUrl: '', // 动态构建的 URL
receivedMessages: [],
messageId: 0,
iframeSize: 'medium', // 控制 iframe 大小small, medium, large
// URL 参数配置
urlParams: {
userId: '12345',
token: 'abc123',
theme: 'dark',
language: 'zh-CN',
timestamp: Date.now()
}
}
},
onLoad() {
// 页面加载时的初始化
console.log('页面加载完成');
this.buildIframeUrl();
},
methods: {
// 构建 iframe URL包含参数
buildIframeUrl() {
// 使用兼容的方式构建 URL 参数
const params = [];
// 添加所有参数
Object.keys(this.urlParams).forEach(key => {
const value = this.urlParams[key];
if (value !== null && value !== undefined) {
// 对参数进行 URL 编码
const encodedKey = encodeURIComponent(key);
const encodedValue = encodeURIComponent(String(value));
params.push(`${encodedKey}=${encodedValue}`);
}
});
// 构建完整 URL
const queryString = params.join('&');
this.iframeUrl = queryString ? `${this.baseUrl}?${queryString}` : this.baseUrl;
console.log('构建的 iframe URL:', this.iframeUrl);
},
// 更新 URL 参数
updateUrlParams(newParams) {
this.urlParams = { ...this.urlParams, ...newParams };
this.buildIframeUrl();
console.log('URL 参数已更新:', this.urlParams);
},
// 添加新的 URL 参数
addUrlParam(key, value) {
this.urlParams[key] = value;
this.buildIframeUrl();
console.log(`添加参数: ${key} = ${value}`);
},
// 移除 URL 参数
removeUrlParam(key) {
if (this.urlParams.hasOwnProperty(key)) {
delete this.urlParams[key];
this.buildIframeUrl();
console.log(`移除参数: ${key}`);
}
},
// 刷新 iframe重新加载页面
refreshIframe() {
this.buildIframeUrl();
console.log('iframe 已刷新,新 URL:', this.iframeUrl);
},
// 演示 URL 参数传递
demoUrlParams() {
// 模拟不同的参数组合
const demos = [
{
name: '用户登录',
params: {
userId: 'user123',
token: 'auth_token_456',
theme: 'light',
language: 'zh-CN'
}
},
{
name: '管理员模式',
params: {
userId: 'admin001',
token: 'admin_token_789',
theme: 'dark',
language: 'en-US',
role: 'admin',
permissions: 'all'
}
},
{
name: '测试模式',
params: {
userId: 'test_user',
token: 'test_token',
theme: 'blue',
language: 'zh-CN',
debug: 'true',
version: '1.0.0'
}
}
];
// 随机选择一个演示
const demo = demos[Math.floor(Math.random() * demos.length)];
this.updateUrlParams(demo.params);
uni.showToast({
title: `已切换到${demo.name}`,
icon: 'success'
});
},
// 接收 web-view 发送的消息
handleMessage(event) {
// 消息在 event.detail.data 中(是一个数组,取最后一条)
const webData = event.detail.data[0];
console.log('App 收到 web-view 消息:', webData);
// 将消息添加到显示列表
this.receivedMessages.push(`[${new Date().toLocaleTimeString()}] ${JSON.stringify(webData)}`);
// 根据消息类型处理逻辑
if (webData.type === 'ready') {
console.log('web-view 已准备就绪');
uni.showToast({
title: 'web-view 连接成功',
icon: 'success'
});
} else if (webData.type === 'toApp') {
uni.showToast({
title: `收到:${webData.content}`,
icon: 'none'
});
} else if (webData.type === 'data') {
console.log('收到数据:', webData.data);
}
},
// App 发送消息到 web-view
sendMessageToIframe() {
this.messageId++;
const message = {
id: this.messageId,
type: 'fromApp',
content: `Hello我是 App 发送的消息 ${this.messageId}`,
timestamp: Date.now()
};
// 通过 evalJS 发送消息到 web-view
this.sendMessageToWebView(message);
},
// App 向 web-view 发送消息
sendMessageToWebView(message) {
// 通过 ref 获取 web-view 实例,调用 evalJS 执行 web-view 中的函数
// 验证 message 参数
if (!message) {
console.error('message 参数为空');
return;
}
// 安全地序列化消息
let safeMessage;
try {
safeMessage = JSON.parse(JSON.stringify(message));
} catch (e) {
console.error('消息序列化失败:', e);
// 如果序列化失败,创建一个简单的消息对象
safeMessage = {
id: message.id || 0,
type: message.type || 'fromApp',
content: String(message.content || ''),
timestamp: message.timestamp || Date.now()
};
}
console.log('webviewRef:', this.$refs.webviewRef);
if (this.$refs.webviewRef && this.$refs.webviewRef.evalJS) {
try {
const jsCode = `receiveFromApp(${JSON.stringify(safeMessage)})`;
console.log('要执行的 JS 代码:', jsCode);
this.$refs.webviewRef.evalJS(jsCode);
console.log('App 发送消息到 web-view', safeMessage);
} catch (e) {
console.error('evalJS 执行失败:', e);
}
} else {
console.error('web-view ref 不存在或 evalJS 方法不可用');
}
},
// 移除 localStorage 相关代码,使用 postMessage 通信
// 切换 iframe 大小
toggleIframeSize() {
const sizes = ['small', 'medium', 'large'];
const currentIndex = sizes.indexOf(this.iframeSize);
const nextIndex = (currentIndex + 1) % sizes.length;
this.iframeSize = sizes[nextIndex];
console.log('iframe 大小切换为:', this.iframeSize);
}
},
// 移除 mounted 生命周期,因为 uni-app 中可能不支持
// 移除 onUnload因为不再需要清理定时器
}
</script>
<style lang="scss" scoped>
// 主容器
.content {
display: flex;
flex-direction: column;
height: 100vh;
background-color: #f8f9fa;
}
// 头部区域
.header {
height: 46rpx;
background: #fff;
}
// iframe 容器
.iframe-container {
overflow: hidden;
background: white;
position: relative;
margin: 20rpx;
border-radius: 20rpx;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1);
// 针对 web-view 的特殊样式
:deep(web-view) {
width: 100% !important;
height: 100% !important;
border: none !important;
outline: none !important;
box-shadow: none !important;
}
// 兼容不同平台的 web-view 样式
:deep(iframe) {
border: none !important;
outline: none !important;
box-shadow: none !important;
}
// 不同大小的样式
&.iframe-small {
height: 300rpx;
min-height: 300rpx;
}
&.iframe-medium {
height: 500rpx;
min-height: 500rpx;
}
&.iframe-large {
height: 700rpx;
min-height: 700rpx;
}
}
// 控制按钮区域
.controls {
display: flex;
gap: 20rpx;
padding: 20rpx;
background: white;
border-bottom: 2rpx solid #f0f0f0;
flex-wrap: wrap;
}
.btn {
flex: 1;
background: linear-gradient(135deg, #188eee 0%, #096dd9 100%);
color: white;
border: none;
border-radius: 20rpx;
padding: 24rpx 20rpx;
font-size: 28rpx;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 4rpx 12rpx rgba(24, 142, 238, 0.3);
&:active {
transform: translateY(2rpx);
box-shadow: 0 2rpx 8rpx rgba(24, 142, 238, 0.4);
}
&:hover {
background: linear-gradient(135deg, #096dd9 0%, #0050b3 100%);
}
}
.btn-secondary {
background: linear-gradient(135deg, #6c757d 0%, #5a6268 100%);
box-shadow: 0 4rpx 12rpx rgba(108, 117, 125, 0.3);
&:active {
transform: translateY(2rpx);
box-shadow: 0 2rpx 8rpx rgba(108, 117, 125, 0.4);
}
&:hover {
background: linear-gradient(135deg, #5a6268 0%, #495057 100%);
}
}
.btn-refresh {
background: linear-gradient(135deg, #ff9800 0%, #f57c00 100%);
box-shadow: 0 4rpx 12rpx rgba(255, 152, 0, 0.3);
&:hover {
background: linear-gradient(135deg, #f57c00 0%, #ef6c00 100%);
}
}
// URL 参数控制区域
.url-controls {
padding: 20rpx;
background: #f0f0f0;
border-bottom: 2rpx solid #e0e0e0;
display: flex;
flex-direction: column;
gap: 16rpx;
}
.url-title {
font-size: 28rpx;
color: #333;
font-weight: 600;
margin-bottom: 16rpx;
padding-bottom: 16rpx;
border-bottom: 2rpx solid #d0d0d0;
}
.param-buttons {
display: flex;
gap: 16rpx;
flex-wrap: wrap;
}
.btn-param {
flex: 1;
background: linear-gradient(135deg, #4caf50 0%, #388e3c 100%);
color: white;
border: none;
border-radius: 20rpx;
padding: 20rpx 16rpx;
font-size: 26rpx;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 4rpx 12rpx rgba(76, 175, 80, 0.3);
&:active {
transform: translateY(2rpx);
box-shadow: 0 2rpx 8rpx rgba(76, 175, 80, 0.4);
}
&:hover {
background: linear-gradient(135deg, #388e3c 0%, #2e7d32 100%);
}
}
.btn-danger {
background: linear-gradient(135deg, #f44336 0%, #d32f2f 100%);
box-shadow: 0 4rpx 12rpx rgba(244, 67, 54, 0.3);
&:active {
transform: translateY(2rpx);
box-shadow: 0 2rpx 8rpx rgba(244, 67, 54, 0.4);
}
&:hover {
background: linear-gradient(135deg, #d32f2f 0%, #c62828 100%);
}
}
.btn-demo {
background: linear-gradient(135deg, #007bff 0%, #0056b3 100%);
box-shadow: 0 4rpx 12rpx rgba(0, 123, 255, 0.3);
&:active {
transform: translateY(2rpx);
box-shadow: 0 2rpx 8rpx rgba(0, 123, 255, 0.4);
}
&:hover {
background: linear-gradient(135deg, #0056b3 0%, #004085 100%);
}
}
.current-url {
display: flex;
align-items: center;
gap: 16rpx;
font-size: 24rpx;
color: #555;
}
.url-label {
font-weight: 600;
}
.url-text {
font-family: "Courier New", monospace;
word-break: break-all;
line-height: 1.5;
}
// 消息显示区域
.message-area {
flex: 1;
padding: 20rpx;
background: white;
overflow: hidden;
display: flex;
flex-direction: column;
}
.message-title {
font-size: 28rpx;
color: #333;
margin-bottom: 20rpx;
display: block;
font-weight: 600;
border-bottom: 2rpx solid #f0f0f0;
padding-bottom: 16rpx;
}
.message-list {
flex: 1;
overflow-y: auto;
border: 2rpx solid #f0f0f0;
border-radius: 16rpx;
padding: 16rpx;
background: #fafafa;
// 自定义滚动条
&::-webkit-scrollbar {
width: 8rpx;
}
&::-webkit-scrollbar-track {
background: #f1f1f1;
border-radius: 4rpx;
}
&::-webkit-scrollbar-thumb {
background: #c1c1c1;
border-radius: 4rpx;
&:hover {
background: #a8a8a8;
}
}
}
.message-item {
background: white;
padding: 20rpx;
margin-bottom: 16rpx;
border-radius: 12rpx;
border-left: 6rpx solid #188eee;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.08);
transition: all 0.3s ease;
&:last-child {
margin-bottom: 0;
}
&:hover {
transform: translateX(4rpx);
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.12);
}
}
.message-text {
font-size: 24rpx;
color: #333;
word-break: break-all;
line-height: 1.5;
font-family: "Courier New", monospace;
}
// 响应式设计
@media (max-width: 768rpx) {
.content {
padding: 0;
}
.iframe-container {
margin: 16rpx;
border-radius: 16rpx;
}
.controls {
padding: 16rpx;
gap: 16rpx;
}
.btn {
padding: 20rpx 16rpx;
font-size: 26rpx;
}
.message-area {
padding: 16rpx;
}
.message-item {
padding: 16rpx;
margin-bottom: 12rpx;
}
}
</style>