233 lines
6.3 KiB
Plaintext
233 lines
6.3 KiB
Plaintext
<template>
|
|
<!-- #ifdef H5 || WEB -->
|
|
<!-- 自定义导航栏 -->
|
|
<custom-nav-bar :title="displayPageTitle">
|
|
<template v-slot:left>
|
|
<text class="iconfont icon-a-Chevronleft" @tap="onBackClick"></text>
|
|
</template>
|
|
</custom-nav-bar>
|
|
<!-- #endif -->
|
|
|
|
<web-view
|
|
class="web-view page-container"
|
|
v-if="url.length != 0"
|
|
:src="url"
|
|
id="webview"
|
|
@error="handleWebviewError"
|
|
@load="handleWebviewLoad"
|
|
@message="handleWebviewMessage"
|
|
></web-view>
|
|
</template>
|
|
|
|
<script lang="uts" setup>
|
|
import { computed, ref } from "vue";
|
|
import { removeQueryCompat } from "@/utils/common.uts";
|
|
import { NO_LOGIN_CHECK_URL } from "@/constants/config";
|
|
import { apiUserTicketCreate } from "@/servers/agentDev";
|
|
import { SUCCESS_CODE } from "@/constants/codes.constants";
|
|
import { onAddToFavorites } from "@dcloudio/uni-app";
|
|
import { isHttpUrl } from "@/utils/common.uts";
|
|
import { isTabPage } from "@/utils/commonBusiness.uts";
|
|
import { useI18n } from "@/utils/i18n";
|
|
|
|
const { t } = useI18n();
|
|
|
|
const url = ref("");
|
|
const method = ref("");
|
|
const data_type = ref("");
|
|
const request_id = ref("");
|
|
const pageTitle = ref("");
|
|
const displayPageTitle = computed(
|
|
() => pageTitle.value || t("Mobile.Webview.defaultTitle"),
|
|
);
|
|
|
|
const getQueryParams = (url) => {
|
|
const queryString = url.split("?")[1] || "";
|
|
const pairs = queryString.split("&");
|
|
const params = {};
|
|
for (let pair of pairs) {
|
|
if (!pair) continue;
|
|
const [k, v] = pair.split("=");
|
|
params[decodeURIComponent(k)] = decodeURIComponent(v || "");
|
|
}
|
|
return params;
|
|
};
|
|
|
|
// 判断是否需要调用接口
|
|
const isNeedCallApi = computed(() => {
|
|
return !!(
|
|
method.value === "browser_navigate_page" &&
|
|
data_type.value &&
|
|
request_id.value
|
|
);
|
|
});
|
|
|
|
// WebView 加载错误处理
|
|
const handleWebviewError = (e: any) => {
|
|
console.error("WebView 加载错误:", e);
|
|
uni.showToast({
|
|
title: t("Mobile.Webview.loadFailed"),
|
|
icon: "none",
|
|
duration: 2000,
|
|
});
|
|
};
|
|
|
|
// WebView 加载完成
|
|
const handleWebviewLoad = (e: any) => {
|
|
// #ifdef MP-WEIXIN
|
|
if (isNeedCallApi.value) {
|
|
uni.showLoading({
|
|
title: t("Mobile.Webview.aiReading"),
|
|
mask: true,
|
|
});
|
|
setTimeout(() => {
|
|
uni.navigateBack({ delta: 1 });
|
|
uni.hideLoading();
|
|
}, 4000);
|
|
}
|
|
// #endif
|
|
};
|
|
|
|
/**
|
|
* WebView 消息处理
|
|
*
|
|
* ⚠️ 重要:微信小程序的 @message 不会实时触发!
|
|
* 触发时机:
|
|
* 1. 用户点击返回按钮(最常用)
|
|
* 2. 组件销毁时
|
|
* 3. 分享时
|
|
*
|
|
* 调试方法:
|
|
* 1. 网页发送消息后,点击小程序的返回按钮
|
|
* 2. 查看控制台是否有 "收到消息" 日志
|
|
* 3. 如果没有,检查网页端代码是否正确调用 wx.miniProgram.postMessage
|
|
*/
|
|
const handleWebviewMessage = (e: any) => {
|
|
// #ifdef MP-WEIXIN
|
|
|
|
// e.detail.data 是一个数组,包含所有 postMessage 发送的消息
|
|
const messages = e.detail.data;
|
|
|
|
if (isNeedCallApi.value && messages && messages.length > 0) {
|
|
// 处理最后一条消息 - 读取首页内容
|
|
uni.$emit("browser_navigate_page", {
|
|
method: method.value,
|
|
data_type: data_type.value,
|
|
html: messages[messages.length - 1].html,
|
|
request_id: request_id.value,
|
|
});
|
|
} else {
|
|
console.warn("消息数组为空");
|
|
}
|
|
// #endif
|
|
};
|
|
|
|
/**
|
|
* 获取分享链接
|
|
*/
|
|
const getSharingLink = () => {
|
|
const newUrl = removeQueryCompat(url.value, ["_ticket", "jump_type"]);
|
|
const andStr = newUrl.includes("?") ? "&" : "?";
|
|
const currentUrl = newUrl + andStr + "jump_type=outer";
|
|
return encodeURIComponent(currentUrl);
|
|
};
|
|
|
|
const onBackClick = () => {
|
|
const backUrl = uni.getStorageSync("backUrl");
|
|
// 首页是 tabbar 页面,必须使用 switchTab 跳转
|
|
const toUrl = backUrl && backUrl !== "/" ? backUrl : "/pages/index/index";
|
|
|
|
if (isTabPage(toUrl)) {
|
|
uni.switchTab({ url: toUrl });
|
|
} else {
|
|
uni.redirectTo({ url: toUrl });
|
|
}
|
|
uni.removeStorageSync("backUrl");
|
|
};
|
|
|
|
// 初始化加载
|
|
const onLoadInit = async (params: UTSJSONObject) => {
|
|
if (params.url) {
|
|
let currentUrl = decodeURIComponent(params.url);
|
|
const queryParams = getQueryParams(currentUrl);
|
|
|
|
// 设置页面标题
|
|
const title = queryParams.title || t("Mobile.Webview.defaultTitle");
|
|
pageTitle.value = title;
|
|
uni.setNavigationBarTitle({
|
|
title: title,
|
|
});
|
|
|
|
// #ifdef H5 || WEB
|
|
if (isHttpUrl(currentUrl)) {
|
|
url.value = currentUrl;
|
|
} else {
|
|
url.value = window.location.origin + currentUrl;
|
|
}
|
|
// #endif
|
|
|
|
// #ifdef MP-WEIXIN
|
|
// 判断当前url是否不需要登录检查
|
|
if (NO_LOGIN_CHECK_URL.includes(currentUrl)) {
|
|
url.value = currentUrl;
|
|
return;
|
|
}
|
|
|
|
if (queryParams.method) {
|
|
method.value = queryParams.method;
|
|
}
|
|
if (queryParams.data_type) {
|
|
data_type.value = queryParams.data_type;
|
|
}
|
|
if (queryParams.request_id) {
|
|
request_id.value = queryParams.request_id;
|
|
}
|
|
|
|
// 判断是否存在 _ticket
|
|
if (queryParams._ticket) {
|
|
url.value = currentUrl;
|
|
} else {
|
|
// 暂存当前url
|
|
globalThis.appConfig.redirectUrl = params.url; // 未解码
|
|
const ticketResult = await apiUserTicketCreate();
|
|
if (ticketResult.code === SUCCESS_CODE && ticketResult.data) {
|
|
const andStr = currentUrl.includes("?") ? "&" : "?";
|
|
url.value = currentUrl + andStr + `_ticket=${ticketResult.data}`;
|
|
}
|
|
}
|
|
// #endif
|
|
}
|
|
};
|
|
|
|
onLoad((params) => {
|
|
// 加载初始化数据
|
|
onLoadInit(params);
|
|
});
|
|
|
|
// #ifdef MP-WEIXIN
|
|
// 转发给朋友
|
|
onShareAppMessage(() => {
|
|
return {
|
|
title:
|
|
getQueryParams(url.value)?.["title"] || t("Mobile.Common.appName"),
|
|
path: "/subpackages/pages/webview/webview?url=" + getSharingLink(),
|
|
};
|
|
});
|
|
|
|
// 收藏
|
|
onAddToFavorites(() => {
|
|
return {
|
|
title:
|
|
getQueryParams(url.value)?.["title"] || t("Mobile.Common.appName"),
|
|
query: "url=" + getSharingLink(),
|
|
};
|
|
});
|
|
// #endif
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.web-view {
|
|
width: 100%;
|
|
}
|
|
</style>
|