Files
giftlaw/pages/rules/rules.vue
T

221 lines
4.7 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="content">
<view class="page-header">
<text class="header-back" @tap="goBack">‹</text>
<text class="header-title">活动规则</text>
</view>
<view class="preview-wrap">
<view class="loading-box" v-if="loading">
<u-loading mode="circle" size="40"></u-loading>
<text class="loading-text">内容加载中...</text>
</view>
<scroll-view class="doc-scroll" scroll-y v-if="!loading && !error">
<rich-text class="doc-content" :nodes="htmlContent"></rich-text>
<view style="height:30rpx;"></view>
</scroll-view>
<view class="error-box" v-if="error">
<text class="error-text">{{ error }}</text>
<button class="preview-btn" @tap="loadDoc">重新加载</button>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
docUrl: 'https://goldnar.hntgov.net/img/gift_rules.docx',
loading: false,
error: '',
htmlContent: ''
}
},
onReady() {
this.loadDoc()
},
methods: {
goBack() {
uni.navigateBack()
},
loadDoc() {
this.loading = true
this.error = ''
this.htmlContent = ''
this.ensureMammoth().then(() => {
return this.fetchDocx(this.docUrl)
}).then(arrayBuffer => {
return window.mammoth.convertToHtml({
arrayBuffer
})
}).then(result => {
this.htmlContent = result.value || ''
this.loading = false
}).catch(err => {
console.error('加载文档失败', err)
this.loading = false
this.error = '文档加载失败,请重试'
})
},
ensureMammoth() {
if (window.mammoth) return Promise.resolve()
return new Promise((resolve, reject) => {
const urls = [
'/static/mammoth.browser.min.js',
'https://unpkg.com/mammoth@1.6.0/mammoth.browser.min.js'
]
let i = 0
const loadNext = () => {
if (i >= urls.length) {
reject(new Error('解析组件加载失败'))
return
}
const s = document.createElement('script')
s.src = urls[i++]
s.onload = () => window.mammoth ? resolve() : loadNext()
s.onerror = loadNext
document.head.appendChild(s)
}
loadNext()
})
},
fetchDocx(url) {
return new Promise((resolve, reject) => {
if (typeof fetch !== 'undefined') {
fetch(url).then(res => {
if (!res.ok) throw new Error('HTTP ' + res.status)
return res.arrayBuffer()
}).then(resolve).catch(() => this.downloadDocx(url).then(resolve).catch(reject))
return
}
this.downloadDocx(url).then(resolve).catch(reject)
})
},
downloadDocx(url) {
return new Promise((resolve, reject) => {
uni.downloadFile({
url: url,
success: (res) => {
if (res.statusCode !== 200) {
reject(new Error('下载失败'))
return
}
uni.getFileSystemManager().readFile({
filePath: res.tempFilePath,
success: (r) => resolve(r.data),
fail: () => {
if (res.tempFilePath && typeof fetch !== 'undefined') {
fetch(res.tempFilePath).then(r => r.arrayBuffer())
.then(resolve).catch(reject)
} else {
reject(new Error('读取文件失败'))
}
}
})
},
fail: reject
})
})
}
}
}
</script>
<style lang="scss">
page {
background-color: #F8F8F8;
}
.content {
position: relative;
display: flex;
flex-direction: column;
height: 100vh;
height: 100dvh;
}
.page-header {
display: flex;
align-items: center;
padding: 20rpx 30rpx;
background: linear-gradient(135deg, #FD5401, #FF7A3D);
flex-shrink: 0;
}
.header-back {
font-size: 48rpx;
color: #fff;
line-height: 1;
margin-right: 16rpx;
padding: 0 10rpx;
}
.header-title {
font-size: 30rpx;
font-weight: 600;
color: #fff;
flex: 1;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.preview-wrap {
flex: 1;
background: #fff;
overflow: hidden;
}
.loading-box {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%;
}
.loading-text {
font-size: 26rpx;
color: #999;
margin-top: 20rpx;
}
.error-box {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%;
}
.error-text {
font-size: 26rpx;
color: #999;
margin-bottom: 30rpx;
}
.preview-btn {
width: 300rpx;
height: 76rpx;
line-height: 76rpx;
background: linear-gradient(135deg, #FD5401, #FF7A3D);
color: #fff;
font-size: 28rpx;
font-weight: 600;
border: none;
border-radius: 38rpx;
}
.doc-scroll {
height: 100%;
padding: 20rpx 30rpx;
box-sizing: border-box;
}
.doc-content {
font-size: 28rpx;
color: #333;
line-height: 1.8;
}
</style>