feat:app嵌套h5返回键

This commit is contained in:
LHY\18810
2025-03-14 23:29:14 +08:00
parent d9ecd839db
commit ef9e1a4e48
6 changed files with 145 additions and 131 deletions

View File

@@ -1,21 +1,18 @@
<script setup lang="ts"> <script lang="ts">
import { RouterView } from 'vue-router'; import { defineComponent } from 'vue';
import { onMounted } from 'vue'; import AndroidBackHandler from '@/components/AndroidBackHandler.vue';
import appBridge from '@/assets/js/appBridge';
import utils from '@/assets/js/common';
onMounted(async() => { export default defineComponent({
if (utils.getSessionStorage('xToken')) { name: 'App',
// 隐藏/显示 header components: {
appBridge.setHeaderShown(false); AndroidBackHandler
// 设置系统状态栏明暗主题
appBridge.setStatusBarStyle('light');
} }
}); });
</script> </script>
<template> <template>
<div> <div id="app">
<RouterView /> <AndroidBackHandler />
<router-view></router-view>
</div> </div>
</template> </template>

View File

@@ -49,9 +49,20 @@ export default {
* @returns {Boolean} 操作是否成功 * @returns {Boolean} 操作是否成功
*/ */
navigateBack() { navigateBack() {
return this.postMessageToRN({ if (!this.isInReactNative()) {
type: 'back' return false;
}); }
try {
window.ReactNativeWebView.postMessage(JSON.stringify({
type: 'back',
data: {
force: false // 不强制返回,让原生端判断是否可以返回
}
}));
return true;
} catch (error) {
return false;
}
}, },
/** /**
@@ -127,9 +138,20 @@ export default {
* @returns {Boolean} 操作是否成功 * @returns {Boolean} 操作是否成功
*/ */
takeOverAndroidBack() { takeOverAndroidBack() {
return this.postMessageToRN({ if (!this.isInReactNative()) {
type: 'takeOverAndroidBack' return false;
}); }
try {
window.ReactNativeWebView.postMessage(JSON.stringify({
type: 'takeOverAndroidBack',
data: {
enabled: true
}
}));
return true;
} catch (error) {
return false;
}
}, },
/** /**

View File

@@ -0,0 +1,58 @@
<template>
<div></div>
</template>
<script lang="ts">
import { defineComponent, onMounted, onUnmounted } from 'vue';
import { useRouter, useRoute } from 'vue-router';
import appBridge from '@/assets/js/appBridge';
export default defineComponent({
name: 'AndroidBackHandler',
setup() {
const router = useRouter();
const route = useRoute();
// 检查是否可以返回
const canGoBack = () => {
// 检查是否有历史记录
if (window.history.length > 1) {
return true;
}
// 检查路由状态
const position = router.options.history.state?.position;
return typeof position === 'number' && position > 0;
};
// 检查是否是首页
const isHomePage = () => {
// 根据实际路由配置修改这里的判断逻辑
return route.path === '/' || route.path === '/home';
};
// 处理返回按钮事件
const handleBack = () => {
// 如果有历史记录,说明是从其他页面进入的
if (canGoBack()) {
router.go(-1);
return false;
} else {
appBridge.navigateBack();
}
};
onMounted(() => {
// 设置禁止原生返回
appBridge.takeOverAndroidBack();
// 添加返回按钮监听
window.onAndroidBack = handleBack;
});
onUnmounted(() => {
// 移除返回按钮监听
window.onAndroidBack = null;
});
return {};
}
});
</script>

View File

@@ -12,50 +12,30 @@ import appBridge from '@/assets/js/appBridge';
import VConsole from 'vconsole'; import VConsole from 'vconsole';
const app = createApp(App); const app = createApp(App);
// import VConsole from 'vconsole';
// let vconsole;
if (import.meta.env.VITE_APP_ENV !== 'production') { if (import.meta.env.VITE_APP_ENV !== 'production') {
const vconsole = new VConsole(); const vconsole = new VConsole();
app.use(vconsole); app.use(vconsole);
// eslint-disable-next-line no-unused-vars
// vconsole = new VConsole();
} }
// 添加 TypeScript 类型声明,在文件顶部添加
declare global { declare global {
interface Window { interface Window {
onAndroidBack: (() => void) | null; onAndroidBack: (() => void) | null;
appBridge?: any; // 同时添加 appBridge 类型声明 appBridge?: any;
} }
} }
// 隐藏/显示 header
appBridge.setHeaderShown(false);
// 设置系统状态栏明暗主题
appBridge.setStatusBarStyle('light');
router.beforeEach((to, from, next) => { router.beforeEach((to, from, next) => {
if (to.query.digitalYiliToken) { if (to.query.digitalYiliToken) {
utils.setSessionStorage('xToken', to.query.digitalYiliToken); utils.setSessionStorage('xToken', to.query.digitalYiliToken);
} }
// appBridge.setTitle(to.meta.title as string); // 设置 header 标题
// 设置禁止原生返回 appBridge.setTitle(to.meta.title as string);
appBridge.takeOverAndroidBack();
// 定义路由是否可以返回的判断
const routerCanGoBack = () => {
const position = router.options.history.state?.position;
return typeof position === 'number' && position > 0;
};
// 定义调用APP返回的方法
const callAppGoBack = () => {
appBridge.navigateBack(); // 使用现有的navigateBack方法替代不存在的goBack方法
};
// 添加 Android 返回按钮监听方法
window.onAndroidBack = () => {
if (routerCanGoBack()) {
router.back();
} else {
callAppGoBack();
}
};
next(); next();
}); });
app.use(createPinia()); app.use(createPinia());
app.use(router); app.use(router);
app.mount('#app'); app.mount('#app');

View File

@@ -8,23 +8,24 @@ import { onMounted, ref } from 'vue';
// import { showFailToast } from 'vant'; // import { showFailToast } from 'vant';
const contentShow = ref(false); const contentShow = ref(false);
onMounted(async() => { onMounted(async() => {
if (utils.getSessionStorage('xToken')) {
const appToken = utils.getParameter('digitalYiliToken');
getUserInfo(appToken).then((res) => {
if (res.data) {
contentShow.value = true; contentShow.value = true;
utils.setSessionStorage('userInfo', res.data.data); // if (utils.getSessionStorage('xToken')) {
} else { // const appToken = utils.getParameter('digitalYiliToken');
contentShow.value = false; // getUserInfo(appToken).then((res) => {
showFailToast(error.response.data?.message || error.data?.message || error.message || '服务器错误'); // if (res.data) {
} // contentShow.value = true;
}).catch((error) => { // utils.setSessionStorage('userInfo', res.data.data);
contentShow.value = false; // } else {
showFailToast(error?.response?.data?.message || error?.message || '服务器错误'); // contentShow.value = false;
}); // showFailToast(error.response.data?.message || error.data?.message || error.message || '服务器错误');
} else { // }
contentShow.value = true; // }).catch((error) => {
} // contentShow.value = false;
// showFailToast(error?.response?.data?.message || error?.message || '服务器错误');
// });
// } else {
// contentShow.value = true;
// }
}); });
</script> </script>

View File

@@ -5,11 +5,9 @@
<!-- <van-cell-group v-if="status === 1" inset style="padding-top: 15px"> --> <!-- <van-cell-group v-if="status === 1" inset style="padding-top: 15px"> -->
<van-cell-group inset style="padding-top: 15px"> <van-cell-group inset style="padding-top: 15px">
<div> <div>
<img <img width="100%"
width="100%"
src="https://files.axshare.com/gsc/DR6075/44/1a/03/441a03a8b1004755a7a392b311acf97f/images/%E6%8A%95%E6%94%BE/u14.jpg?pageId=2f9ba10c-92b8-4c9b-b40b-04e65a0b4333" src="https://files.axshare.com/gsc/DR6075/44/1a/03/441a03a8b1004755a7a392b311acf97f/images/%E6%8A%95%E6%94%BE/u14.jpg?pageId=2f9ba10c-92b8-4c9b-b40b-04e65a0b4333"
alt="" alt="" />
/>
</div> </div>
<div class="qrcode"> <div class="qrcode">
<img :src="publishInfo.img_url" alt="" width="100px" height="100px" /> <img :src="publishInfo.img_url" alt="" width="100px" height="100px" />
@@ -42,8 +40,8 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { useRoute, useRouter } from 'vue-router'; import { useRoute } from 'vue-router';
import { onMounted, onBeforeUnmount, reactive, ref, watch } from 'vue'; import { onMounted, reactive, ref, watch } from 'vue';
import { showFailToast, showToast } from 'vant'; import { showFailToast, showToast } from 'vant';
import utils from '@/assets/js/common'; import utils from '@/assets/js/common';
import appBridge from '@/assets/js/appBridge'; import appBridge from '@/assets/js/appBridge';
@@ -52,7 +50,6 @@ import { getQrcode } from '@/api/publish';
import configUrl from '../../../../config'; import configUrl from '../../../../config';
const route = useRoute(); const route = useRoute();
const router = useRouter();
const surveyTitle = route.meta.title as string; const surveyTitle = route.meta.title as string;
appBridge.setTitle(surveyTitle); appBridge.setTitle(surveyTitle);
const sn = route.query.sn; const sn = route.query.sn;
@@ -143,48 +140,7 @@ watch(status, (val) => {
getCode(); getCode();
} }
}); });
// 判断路由是否可以返回
const routerCanGoBack = () => {
const position = router.options.history.state?.position;
return typeof position === 'number' && position > 0;
};
// 处理返回逻辑
const handleBack = () => {
if (routerCanGoBack()) {
console.log('h5返回');
router.back(); // 执行 h5 路由返回
return true; // 表示已处理返回事件
} else {
console.log('app返回');
// 没有更多历史记录尝试使用appBridge处理返回
if ((window as any).appBridge && (window as any).appBridge.closeWebView) {
(window as any).appBridge.closeWebView();
}
return false; // 表示未处理返回事件应由APP处理
}
};
// 清理全局事件处理
onBeforeUnmount(() => {
(window as any).onAndroidBack = null;
});
onMounted(async () => { onMounted(async () => {
// 为window添加返回处理方法
(window as any).onAndroidBack = () => {
// 设置禁止原生返回如果有appBridge对象
if ((window as any).appBridge && (window as any).appBridge.takeOverAndroidBack) {
(window as any).appBridge.takeOverAndroidBack();
}
return handleBack();
};
// 如果有appBridge设置返回按钮动作
if ((window as any).appBridge && (window as any).appBridge.setBackButtonAction) {
(window as any).appBridge.setBackButtonAction(() => {
return handleBack();
});
}
// fetchInfo(); // fetchInfo();
getCode(); getCode();
}); });
@@ -224,7 +180,7 @@ function shareLink() {
scene: 0 // 朋友圈1 微信好友0 scene: 0 // 朋友圈1 微信好友0
}; };
console.log('shareUrl', publishInfo.value.url); console.log('shareUrl', publishInfo.value.url);
appBridge.shareToWeChat(params); appBridge.shareToWeChat(params, () => { });
} }
// 下载二维码 // 下载二维码