|
@@ -0,0 +1,122 @@
|
|
|
|
|
+<template>
|
|
|
|
|
+ <view class="webview-wrapper">
|
|
|
|
|
+ <!-- 加载状态提示 -->
|
|
|
|
|
+ <view class="loading-mask" v-if="isLoading">
|
|
|
|
|
+ <uni-loading-icon type="circle" size="24" color="#333"></uni-loading-icon>
|
|
|
|
|
+ <text class="loading-txt">加载中...</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+
|
|
|
|
|
+ <web-view
|
|
|
|
|
+ :src="h5Url"
|
|
|
|
|
+ id="any-id"
|
|
|
|
|
+ @load="onWebViewLoad"
|
|
|
|
|
+ @error="onWebViewError"
|
|
|
|
|
+ @message="onWebViewMessage"
|
|
|
|
|
+ ></web-view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+</template>
|
|
|
|
|
+
|
|
|
|
|
+<script setup>
|
|
|
|
|
+import { ref, onUnmounted } from "vue";
|
|
|
|
|
+import { onLoad } from "@dcloudio/uni-app";
|
|
|
|
|
+import { H5_BASE_URL, TOKENNAME, WHITELIST } from "@/config/app";
|
|
|
|
|
+import { useAppStore } from "@/stores/app";
|
|
|
|
|
+import { toLogin, checkLogin } from "@/libs/login";
|
|
|
|
|
+
|
|
|
|
|
+const h5Url = ref("");
|
|
|
|
|
+const appStore = useAppStore();
|
|
|
|
|
+const isLoading = ref(true);
|
|
|
|
|
+const errorMsg = ref("");
|
|
|
|
|
+
|
|
|
|
|
+onUnmounted(() => {
|
|
|
|
|
+ isLoading.value = false;
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+onLoad((query) => {
|
|
|
|
|
+ console.log('query',query)
|
|
|
|
|
+ try {
|
|
|
|
|
+ h5Url.value = query.path;
|
|
|
|
|
+ } catch (err) {
|
|
|
|
|
+ console.error("WebView 初始化失败:", err);
|
|
|
|
|
+ uni.showToast({ title: "页面加载异常", icon: "none", duration: 1500 });
|
|
|
|
|
+ setTimeout(() => uni.navigateBack(), 1500);
|
|
|
|
|
+ }
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+// 标准化H5路径
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * web-view 加载成功
|
|
|
|
|
+ */
|
|
|
|
|
+const onWebViewLoad = () => {
|
|
|
|
|
+ isLoading.value = false; // 隐藏加载中
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * web-view 加载失败
|
|
|
|
|
+ * @param {object} err - 错误信息
|
|
|
|
|
+ */
|
|
|
|
|
+const onWebViewError = (err) => {
|
|
|
|
|
+ isLoading.value = false;
|
|
|
|
|
+ errorMsg.value = `页面加载失败:${err.detail.errMsg}`;
|
|
|
|
|
+ uni.showToast({ title: errorMsg.value, icon: "none", duration: 2000 });
|
|
|
|
|
+ console.error("WebView 加载错误:", err);
|
|
|
|
|
+ setTimeout(() => uni.navigateBack(), 1500);
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 接收 H5 发送的消息
|
|
|
|
|
+ * @param {object} e - 消息事件
|
|
|
|
|
+ */
|
|
|
|
|
+const onWebViewMessage = (e) => {
|
|
|
|
|
+ const h5Msg = e.detail.data[0]; // H5 发送的消息格式为 { data: [消息体] }
|
|
|
|
|
+ console.log("接收 H5 消息:", h5Msg);
|
|
|
|
|
+
|
|
|
|
|
+ // 示例:H5 触发「返回小程序」
|
|
|
|
|
+ if (h5Msg.type === "navigateBack") {
|
|
|
|
|
+ uni.navigateBack({ delta: h5Msg.delta || 1 });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (h5Msg.type === "refreshToken") {
|
|
|
|
|
+ appStore.refreshToken().then((newToken) => {
|
|
|
|
|
+ const webview = uni.createSelectorQuery().select("#any-id");
|
|
|
|
|
+ webview
|
|
|
|
|
+ .context((res) => {
|
|
|
|
|
+ res.context.postMessage({
|
|
|
|
|
+ data: { type: "newToken", token: newToken },
|
|
|
|
|
+ });
|
|
|
|
|
+ })
|
|
|
|
|
+ .exec();
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+};
|
|
|
|
|
+</script>
|
|
|
|
|
+
|
|
|
|
|
+<style scoped>
|
|
|
|
|
+.webview-wrapper {
|
|
|
|
|
+ width: 100vw;
|
|
|
|
|
+ height: 100vh;
|
|
|
|
|
+ position: relative;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.loading-mask {
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ top: 0;
|
|
|
|
|
+ left: 0;
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ height: 100%;
|
|
|
|
|
+ background: rgba(255, 255, 255, 0.8);
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ z-index: 999;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.loading-txt {
|
|
|
|
|
+ margin-top: 16rpx;
|
|
|
|
|
+ font-size: 28rpx;
|
|
|
|
|
+ color: #666;
|
|
|
|
|
+}
|
|
|
|
|
+</style>
|