智慧教务系统
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.
 
 
 
 
 
 

281 lines
6.3 KiB

<template>
<view class="dashboard-webview">
<!-- 加载状态 -->
<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-if="!hasError"
: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>
import { img_domian } from '@/common/config.js'
export default {
data() {
return {
pageType: '',
pageTitle: '',
isLoading: true,
hasError: false,
errorMessage: '',
baseUrl: img_domian, // 后端基础URL
userToken: '',
userInfo: {},
}
},
computed: {
webViewUrl() {
if (!this.userToken) {
return ''
}
// 构建WebView URL,包含token和页面类型
const params = [
`token=${encodeURIComponent(this.userToken)}`,
`type=${encodeURIComponent(this.pageType)}`,
`platform=uniapp`,
]
return `${this.baseUrl}/api/dashboard/webview?${params.join('&')}`
},
},
onLoad(options) {
// 从URL参数获取页面类型
this.pageType = options.type || 'my_data'
// 设置页面标题
const titleMap = {
'my_data': '我的数据',
'dept_data': '部门数据',
'campus_data': '校区数据',
}
this.pageTitle = titleMap[this.pageType] || '数据统计'
// 设置导航栏标题
uni.setNavigationBarTitle({
title: this.pageTitle,
})
// 初始化WebView
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 (!token) {
// 如果没有token,使用测试token
this.userToken = 'test123'
this.userInfo = { name: '测试用户' }
} else {
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.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
},
},
}
</script>
<style scoped>
.dashboard-webview {
height: 100vh;
background-color: #181A20;
}
.loading-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
background-color: #181A20;
}
.loading-text {
margin-top: 16px;
font-size: 14px;
color: #29d3b4;
}
.webview-container {
height: 100vh;
width: 100%;
}
.error-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
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>