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

View File

@@ -49,9 +49,20 @@ export default {
* @returns {Boolean} 操作是否成功
*/
navigateBack() {
return this.postMessageToRN({
type: 'back'
});
if (!this.isInReactNative()) {
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} 操作是否成功
*/
takeOverAndroidBack() {
return this.postMessageToRN({
type: 'takeOverAndroidBack'
});
if (!this.isInReactNative()) {
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';
const app = createApp(App);
// import VConsole from 'vconsole';
// let vconsole;
if (import.meta.env.VITE_APP_ENV !== 'production') {
const vconsole = new VConsole();
app.use(vconsole);
// eslint-disable-next-line no-unused-vars
// vconsole = new VConsole();
}
// 添加 TypeScript 类型声明,在文件顶部添加
declare global {
interface Window {
onAndroidBack: (() => void) | null;
appBridge?: any; // 同时添加 appBridge 类型声明
appBridge?: any;
}
}
// 隐藏/显示 header
appBridge.setHeaderShown(false);
// 设置系统状态栏明暗主题
appBridge.setStatusBarStyle('light');
router.beforeEach((to, from, next) => {
if (to.query.digitalYiliToken) {
utils.setSessionStorage('xToken', to.query.digitalYiliToken);
}
// 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();
}
};
// 设置 header 标题
appBridge.setTitle(to.meta.title as string);
next();
});
app.use(createPinia());
app.use(router);
app.mount('#app');

View File

@@ -8,23 +8,24 @@ import { onMounted, ref } from 'vue';
// import { showFailToast } from 'vant';
const contentShow = ref(false);
onMounted(async() => {
if (utils.getSessionStorage('xToken')) {
const appToken = utils.getParameter('digitalYiliToken');
getUserInfo(appToken).then((res) => {
if (res.data) {
contentShow.value = true;
utils.setSessionStorage('userInfo', res.data.data);
} else {
contentShow.value = false;
showFailToast(error.response.data?.message || error.data?.message || error.message || '服务器错误');
}
}).catch((error) => {
contentShow.value = false;
showFailToast(error?.response?.data?.message || error?.message || '服务器错误');
});
} else {
contentShow.value = true;
}
contentShow.value = true;
// if (utils.getSessionStorage('xToken')) {
// const appToken = utils.getParameter('digitalYiliToken');
// getUserInfo(appToken).then((res) => {
// if (res.data) {
// contentShow.value = true;
// utils.setSessionStorage('userInfo', res.data.data);
// } else {
// contentShow.value = false;
// showFailToast(error.response.data?.message || error.data?.message || error.message || '服务器错误');
// }
// }).catch((error) => {
// contentShow.value = false;
// showFailToast(error?.response?.data?.message || error?.message || '服务器错误');
// });
// } else {
// contentShow.value = true;
// }
});
</script>
@@ -45,13 +46,13 @@ onMounted(async() => {
padding: 0 10px 60px;
background: linear-gradient(0deg, #f5f5f5 0%, #f5f5f5 84%, #a5d380 100%);
& > :first-child {
&> :first-child {
display: flex;
justify-content: space-around;
border-radius: 6px;
background-color: white;
& > div {
&>div {
display: flex;
flex-direction: column;
width: 50px;

View File

@@ -5,11 +5,9 @@
<!-- <van-cell-group v-if="status === 1" inset style="padding-top: 15px"> -->
<van-cell-group inset style="padding-top: 15px">
<div>
<img
width="100%"
<img 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"
alt=""
/>
alt="" />
</div>
<div class="qrcode">
<img :src="publishInfo.img_url" alt="" width="100px" height="100px" />
@@ -42,8 +40,8 @@
</template>
<script setup lang="ts">
import { useRoute, useRouter } from 'vue-router';
import { onMounted, onBeforeUnmount, reactive, ref, watch } from 'vue';
import { useRoute } from 'vue-router';
import { onMounted, reactive, ref, watch } from 'vue';
import { showFailToast, showToast } from 'vant';
import utils from '@/assets/js/common';
import appBridge from '@/assets/js/appBridge';
@@ -52,7 +50,6 @@ import { getQrcode } from '@/api/publish';
import configUrl from '../../../../config';
const route = useRoute();
const router = useRouter();
const surveyTitle = route.meta.title as string;
appBridge.setTitle(surveyTitle);
const sn = route.query.sn;
@@ -111,7 +108,7 @@ type OperateItem = (typeof operateList)[0];
// }
// }
function getCode() {
function getCode () {
publishInfo.value.img_url
= 'https://test-cxp-pubcos.yili.com/uat-yls//survey-api/publish/202503130938138261340.png';
publishInfo.value.url = `${configUrl.proxyDomain}/publish?sn=${sn && sn !== undefined ? sn : ''}`;
@@ -143,68 +140,27 @@ watch(status, (val) => {
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() => {
// 为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();
});
}
onMounted(async () => {
// fetchInfo();
getCode();
});
const operateBtn = (item: OperateItem) => {
switch (item.type) {
case 'shareLink':
shareLink();
break;
case 'copyLink':
copyLink();
break;
case 'qrCode':
downLoadImg();
break;
default:
break;
case 'shareLink':
shareLink();
break;
case 'copyLink':
copyLink();
break;
case 'qrCode':
downLoadImg();
break;
default:
break;
}
};
// 复制链接
function copyLink() {
function copyLink () {
const input = document.createElement('input');
input.value = publishInfo.value.url;
document.body.appendChild(input);
@@ -214,7 +170,7 @@ function copyLink() {
showToast('复制成功');
}
// 分享链接
function shareLink() {
function shareLink () {
const params = {
type: 'shareToWx',
title: publishInfo.value.download_url.title,
@@ -224,11 +180,11 @@ function shareLink() {
scene: 0 // 朋友圈1 微信好友0
};
console.log('shareUrl', publishInfo.value.url);
appBridge.shareToWeChat(params);
appBridge.shareToWeChat(params, () => { });
}
// 下载二维码
function downLoadImg() {
function downLoadImg () {
const { title, url } = publishInfo.value.download_url;
if (utils.getSessionStorage('xToken')) {
appBridge.save2Album(url, () => {