Files
yunzerwebsiteallinone/uniapp/pages/apps/webview.vue
T
2026-10-03 23:46:55 +08:00

150 lines
3.3 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="page">
<!--
小程序端 web-view 组件会自动铺满整屏(不受样式约束),
因此该端使用原生导航栏(pages.json 里 navigationStyle 保持 default);
H5 / App 端 web-view 渲染为 iframe,需要自绘标题栏。
-->
<!-- #ifndef MP-WEIXIN -->
<view class="bar">
<view class="bar-btn" @tap="goBack">
<FaIcon name="chevron-left" color="#1f2b48" :size="20" />
</view>
<text class="bar-title">{{ title }}</text>
<view class="bar-btn" @tap="onReload">
<FaIcon name="rotate" color="#5b6780" :size="18" />
</view>
</view>
<!-- #endif -->
<web-view v-if="url" :src="url" @message="onMessage" />
<view v-else class="empty">
<FaIcon name="triangle-exclamation" color="#c0c4cc" :size="40" />
<text class="empty-text">没有可打开的页面地址</text>
</view>
</view>
</template>
<script setup>
import { ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { resolveWebConsoleURL, resolveWebSSOURL } from '@/api/config.js'
const url = ref('')
const title = ref('功能')
/**
* 参数解码。
* 各端行为不一致:H5(vue-router)会先解一次码,小程序不会。
* 这里对纯 ASCII 参数(path / ticket)重复解码是幂等的,安全;
* 含中文的 title 解码一次后已无可解字符,再解也是空操作。
*/
function decodeParam(v) {
if (!v) return ''
try {
return decodeURIComponent(v)
} catch (e) {
return v
}
}
onLoad((options) => {
const opt = options || {}
const raw = decodeParam(opt.p || opt.url)
const ticket = decodeParam(opt.k)
title.value = decodeParam(opt.t || opt.title) || '功能'
if (!raw) {
uni.setNavigationBarTitle({ title: title.value })
return
}
// 带票据 → 走 Web 端免登录兑换页;否则按普通深链打开
if (ticket) {
url.value = resolveWebSSOURL(raw, ticket)
} else if (/^https?:\/\//i.test(raw)) {
url.value = raw
} else {
url.value = resolveWebConsoleURL(raw)
}
uni.setNavigationBarTitle({ title: title.value })
})
function goBack() {
const pages = getCurrentPages()
if (pages.length > 1) {
uni.navigateBack()
} else {
uni.reLaunch({ url: '/pages/nav/nav' })
}
}
// 重新加载:改 src 强制 webview/iframe 刷新
function onReload() {
const cur = url.value
if (!cur) return
const sep = cur.includes('?') ? '&' : '?'
url.value = cur + sep + '_t=' + Date.now()
}
function onMessage() {
// 预留:Web 端 postMessage 回传(如通知外层刷新数据)
}
</script>
<style lang="scss" scoped>
@import '@/src/styles/page-common.scss';
.page {
@include page-shell;
}
.bar {
flex-shrink: 0;
display: flex;
align-items: center;
gap: 12rpx;
height: 88rpx;
padding: 0 16rpx;
background: $color-card;
border-bottom: 1rpx solid $color-border;
}
.bar-btn {
width: 64rpx;
height: 64rpx;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.bar-title {
flex: 1;
min-width: 0;
text-align: center;
font-size: 30rpx;
font-weight: 500;
color: $color-text;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.empty {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 20rpx;
}
.empty-text {
font-size: 26rpx;
color: $color-text-muted;
}
</style>