You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
318 lines
6.7 KiB
318 lines
6.7 KiB
<template>
|
|
<view class="dashboard-webview">
|
|
<uni-nav-bar
|
|
:statusBar="true"
|
|
backgroundColor="#181A20"
|
|
color="#fff"
|
|
:title="pageTitle"
|
|
leftIcon="back"
|
|
@clickLeft="goBack"
|
|
/>
|
|
|
|
<!-- 加载状态 -->
|
|
<view v-if="isLoading" class="loading-container">
|
|
<uni-icons type="spinner-cycle" size="32" color="#29d3b4"></uni-icons>
|
|
<text class="loading-text">加载中...</text>
|
|
</view>
|
|
|
|
<!-- WebView容器 -->
|
|
<web-view
|
|
v-else
|
|
:src="webViewUrl"
|
|
@message="handleMessage"
|
|
@error="handleError"
|
|
@load="handleLoad"
|
|
class="webview-container"
|
|
></web-view>
|
|
|
|
<!-- 错误提示 -->
|
|
<view v-if="hasError" class="error-container">
|
|
<uni-icons type="close-filled" size="48" color="#ff5722"></uni-icons>
|
|
<text class="error-title">页面加载失败</text>
|
|
<text class="error-desc">{{ errorMessage }}</text>
|
|
<button class="retry-btn" @click="retry">重试</button>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
export default {
|
|
name: 'DashboardWebView',
|
|
props: {
|
|
// WebView页面类型:my_data, dept_data, campus_data
|
|
pageType: {
|
|
type: String,
|
|
required: true
|
|
},
|
|
// 页面标题
|
|
title: {
|
|
type: String,
|
|
default: '数据统计'
|
|
}
|
|
},
|
|
data() {
|
|
return {
|
|
isLoading: true,
|
|
hasError: false,
|
|
errorMessage: '',
|
|
baseUrl: 'http://localhost:20080', // 后端基础URL
|
|
userToken: '',
|
|
userInfo: {}
|
|
}
|
|
},
|
|
computed: {
|
|
pageTitle() {
|
|
const titleMap = {
|
|
'my_data': '我的数据',
|
|
'dept_data': '部门数据',
|
|
'campus_data': '校区数据'
|
|
};
|
|
return titleMap[this.pageType] || this.title;
|
|
},
|
|
webViewUrl() {
|
|
if (!this.userToken) {
|
|
return '';
|
|
}
|
|
// 构建WebView URL,包含token和页面类型
|
|
const params = new URLSearchParams({
|
|
token: this.userToken,
|
|
type: this.pageType,
|
|
platform: 'uniapp'
|
|
});
|
|
return `${this.baseUrl}/api/dashboard/webview?${params.toString()}`;
|
|
}
|
|
},
|
|
onLoad() {
|
|
this.initWebView();
|
|
},
|
|
methods: {
|
|
async initWebView() {
|
|
try {
|
|
// 获取用户信息和token
|
|
await this.getUserInfo();
|
|
|
|
// 延迟一下确保URL构建完成
|
|
setTimeout(() => {
|
|
this.isLoading = false;
|
|
}, 500);
|
|
} catch (error) {
|
|
console.error('初始化WebView失败:', error);
|
|
this.showError('初始化失败');
|
|
}
|
|
},
|
|
|
|
getUserInfo() {
|
|
return new Promise((resolve, reject) => {
|
|
try {
|
|
// 从本地存储获取用户信息
|
|
const userInfo = uni.getStorageSync('userInfo');
|
|
const token = uni.getStorageSync('token');
|
|
|
|
if (!userInfo || !token) {
|
|
throw new Error('用户信息或token不存在');
|
|
}
|
|
|
|
this.userInfo = userInfo;
|
|
this.userToken = token;
|
|
resolve();
|
|
} catch (error) {
|
|
reject(error);
|
|
}
|
|
});
|
|
},
|
|
|
|
handleMessage(event) {
|
|
console.log('收到WebView消息:', event.detail.data);
|
|
const data = event.detail.data[0];
|
|
|
|
// 处理来自WebView的消息
|
|
switch (data.type) {
|
|
case 'navigate':
|
|
// 处理页面跳转
|
|
this.handleNavigate(data.url);
|
|
break;
|
|
case 'refresh':
|
|
// 处理刷新请求
|
|
this.refresh();
|
|
break;
|
|
case 'share':
|
|
// 处理分享功能
|
|
this.handleShare(data.content);
|
|
break;
|
|
default:
|
|
console.log('未处理的消息类型:', data.type);
|
|
}
|
|
},
|
|
|
|
handleError(event) {
|
|
console.error('WebView加载错误:', event);
|
|
this.showError('页面加载失败,请检查网络连接');
|
|
},
|
|
|
|
handleLoad(event) {
|
|
console.log('WebView加载完成:', event);
|
|
this.isLoading = false;
|
|
this.hasError = false;
|
|
},
|
|
|
|
handleNavigate(url) {
|
|
// 处理页面跳转,可以是UniApp页面或外部链接
|
|
if (url.startsWith('/pages')) {
|
|
// UniApp内部页面跳转
|
|
uni.navigateTo({
|
|
url: url,
|
|
fail: (err) => {
|
|
console.error('页面跳转失败:', err);
|
|
uni.showToast({
|
|
title: '页面跳转失败',
|
|
icon: 'none'
|
|
});
|
|
}
|
|
});
|
|
} else {
|
|
// 外部链接,可以在当前WebView中打开或提示用户
|
|
uni.showModal({
|
|
title: '提示',
|
|
content: '是否在浏览器中打开链接?',
|
|
success: (res) => {
|
|
if (res.confirm) {
|
|
uni.showToast({
|
|
title: '功能开发中',
|
|
icon: 'none'
|
|
});
|
|
}
|
|
}
|
|
});
|
|
}
|
|
},
|
|
|
|
handleShare(content) {
|
|
// 处理分享功能
|
|
uni.share({
|
|
provider: "weixin",
|
|
scene: "WXSceneSession",
|
|
type: 0,
|
|
href: content.url || '',
|
|
title: content.title || this.pageTitle,
|
|
summary: content.summary || '数据统计分享',
|
|
imageUrl: content.image || '',
|
|
success: (res) => {
|
|
console.log('分享成功:', res);
|
|
uni.showToast({
|
|
title: '分享成功',
|
|
icon: 'success'
|
|
});
|
|
},
|
|
fail: (err) => {
|
|
console.error('分享失败:', err);
|
|
uni.showToast({
|
|
title: '分享失败',
|
|
icon: 'none'
|
|
});
|
|
}
|
|
});
|
|
},
|
|
|
|
refresh() {
|
|
// 刷新页面
|
|
this.isLoading = true;
|
|
this.hasError = false;
|
|
|
|
// 重新初始化
|
|
setTimeout(() => {
|
|
this.initWebView();
|
|
}, 300);
|
|
},
|
|
|
|
retry() {
|
|
// 重试加载
|
|
this.hasError = false;
|
|
this.isLoading = true;
|
|
this.initWebView();
|
|
},
|
|
|
|
showError(message) {
|
|
this.isLoading = false;
|
|
this.hasError = true;
|
|
this.errorMessage = message;
|
|
},
|
|
|
|
goBack() {
|
|
uni.navigateBack({
|
|
delta: 1,
|
|
fail: () => {
|
|
// 如果无法返回,则跳转到首页
|
|
uni.reLaunch({
|
|
url: '/pages/common/home/index'
|
|
});
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
.dashboard-webview {
|
|
height: 100vh;
|
|
background-color: #181A20;
|
|
}
|
|
|
|
.loading-container {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
height: calc(100vh - 44px - var(--status-bar-height));
|
|
background-color: #181A20;
|
|
}
|
|
|
|
.loading-text {
|
|
margin-top: 16px;
|
|
font-size: 14px;
|
|
color: #29d3b4;
|
|
}
|
|
|
|
.webview-container {
|
|
height: calc(100vh - 44px - var(--status-bar-height));
|
|
}
|
|
|
|
.error-container {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
height: calc(100vh - 44px - var(--status-bar-height));
|
|
background-color: #181A20;
|
|
padding: 40px;
|
|
}
|
|
|
|
.error-title {
|
|
margin-top: 16px;
|
|
font-size: 18px;
|
|
font-weight: bold;
|
|
color: #fff;
|
|
}
|
|
|
|
.error-desc {
|
|
margin-top: 8px;
|
|
font-size: 14px;
|
|
color: rgba(255, 255, 255, 0.6);
|
|
text-align: center;
|
|
line-height: 1.5;
|
|
}
|
|
|
|
.retry-btn {
|
|
margin-top: 24px;
|
|
padding: 12px 24px;
|
|
background-color: #29d3b4;
|
|
color: #fff;
|
|
border-radius: 6px;
|
|
border: none;
|
|
font-size: 14px;
|
|
}
|
|
|
|
.retry-btn:active {
|
|
background-color: #1a9b7c;
|
|
}
|
|
</style>
|