Files
phone-app------test1-/pages/WYXD/WYXD.vue
2026-07-27 16:42:42 +08:00

327 lines
7.5 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="status-bar"></view>
<view class="wyxd-container page-container">
<!-- ===== 顶部导航栏 ===== -->
<view class="wyxd-header">
<view class="custom-navbar">
<view class="navbar-left" @click="goBack">
<view class="iconfont icon-fanhui custom-navbar-icon"></view>
<view class="navbar-before-title workspace-text">返回</view>
</view>
<view class="navbar-title workspace-text">{{ displayName }}</view>
<view class="navbar-right"></view>
</view>
</view>
<!-- ===== 主舞台 ===== -->
<view class="wyxd-content">
<!-- 加载中 / 错误状态 -->
<view v-if="loading || errorMsg" class="wyxd-state">
<view class="iconfont wyxd-state-icon"
:class="errorMsg ? 'icon-quxiao' : 'icon-sousuo'"></view>
<view class="wyxd-state-title">{{ errorMsg || statusText }}</view>
<view v-if="errorMsg" class="wyxd-state-desc">请返回重试</view>
</view>
<!-- 无内容 -->
<view v-else-if="!slides.length" class="wyxd-state">
<view class="iconfont icon-wenjianjia wyxd-state-icon"></view>
<view class="wyxd-state-title">暂无内容</view>
</view>
<!-- 幻灯片 -->
<view v-else class="wyxd-slide-area">
<scroll-view class="wyxd-slide-scroll" scroll-y :show-scrollbar="false">
<view class="wyxd-slide-card" v-html="currentSlide.html"></view>
</scroll-view>
</view>
</view>
<!-- ===== 底部翻页 ===== -->
<view class="wyxd-pager" v-if="slides.length > 1">
<view class="wyxd-pager-inner">
<view class="wyxd-nav-btn" :class="{ disabled: currentIndex <= 0 }" @click="prevSlide">
<view class="iconfont icon-fanhui" style="font-size:24rpx;"></view>
</view>
<view class="wyxd-page-indicator">
<text class="wyxd-current">{{ pad(currentIndex + 1) }}</text>
<text class="wyxd-divider">/</text>
<text class="wyxd-total">{{ pad(slides.length) }}</text>
</view>
<view class="wyxd-nav-btn" :class="{ disabled: currentIndex >= slides.length - 1 }" @click="nextSlide">
<view class="iconfont icon-fanhui" style="transform:rotate(180deg);font-size:24rpx;"></view>
</view>
</view>
</view>
</view>
</template>
<script setup>
import { ref, computed } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import {
isWyxdCached, getCachedWyxd, setCachedWyxd,
downloadWyxdAsZip, extractWyxd, parseSlides
} from '@/utils/wyxd-parser.js'
const workspaceId = ref('')
const filePath = ref('')
const fileName = ref('')
const userToken = ref('')
const slides = ref([])
const currentIndex = ref(0)
const status = ref('')
const loading = ref(false)
const errorMsg = ref('')
const statusText = computed(() => {
const map = {
downloading: '下载中...',
extracting: '解压中...',
parsing: '解析中...',
error: '加载失败'
}
return map[status.value] || '处理中...'
})
const displayName = computed(() => fileName.value || '未命名文档')
const currentSlide = computed(() => slides.value[currentIndex.value] || { html: '' })
const pad = (n) => String(n).padStart(2, '0')
const goBack = () => {
uni.navigateBack()
}
const prevSlide = () => {
if (currentIndex.value > 0) currentIndex.value--
}
const nextSlide = () => {
if (currentIndex.value < slides.value.length - 1) currentIndex.value++
}
const loadFromCache = () => {
const cached = getCachedWyxd(workspaceId.value, filePath.value)
if (!cached || !cached.slides || cached.slides.length === 0) {
startDownload()
return
}
slides.value = cached.slides
currentIndex.value = 0
loading.value = false
errorMsg.value = ''
status.value = ''
}
const startDownload = async () => {
if (!userToken.value || !workspaceId.value || !filePath.value) {
errorMsg.value = '缺少必要参数'
status.value = 'error'
return
}
try {
loading.value = true
errorMsg.value = ''
slides.value = []
currentIndex.value = 0
status.value = 'downloading'
console.log("userToken.value",userToken.value);
console.log("workspaceId.value",workspaceId.value);
console.log("filePath.value",filePath.value);
const tempPath = await downloadWyxdAsZip(
userToken.value, workspaceId.value, filePath.value
)
console.log("获取到的下载地址:",tempPath);
status.value = 'extracting'
const extracted = await extractWyxd(tempPath)
console.log("extracted",extracted);
status.value = 'parsing'
const slideList = parseSlides(extracted.html, extracted.header, extracted.images)
if (!slideList || slideList.length === 0) {
throw new Error('无法解析文档内容')
}
slides.value = slideList
currentIndex.value = 0
loading.value = false
status.value = ''
setCachedWyxd(workspaceId.value, filePath.value, {
fileName: fileName.value,
slides: slideList
})
} catch (err) {
loading.value = false
status.value = 'error'
const msg = typeof err === 'string' ? err : (err.message || '下载失败')
errorMsg.value = msg
console.error('[WYXD] download error:', err)
}
}
onLoad((options) => {
workspaceId.value = options.workspaceId || ''
filePath.value = options?.filePath ? decodeURIComponent(options.filePath) : ''
fileName.value = options?.fileName ? decodeURIComponent(options.fileName) : '未命名文档'
userToken.value = options?.userToken ?? uni.getStorageSync('user_token') ?? ''
console.log('页面接收options原始参数', options)
console.log('最终赋值变量:', {
workspaceId: workspaceId.value,
filePath: filePath.value,
fileName: fileName.value,
userToken: userToken.value
})
if (isWyxdCached(workspaceId.value, filePath.value)) {
loadFromCache()
} else {
startDownload()
}
})
</script>
<style scoped>
@import url("@/pages/WorkSpace/WorkSpace.css");
.wyxd-container {
display: flex;
flex-direction: column;
background: #f5f5f5;
overflow: hidden;
}
.wyxd-header {
flex-shrink: 0;
background: #fff;
}
.wyxd-content {
flex: 1;
min-height: 0;
overflow: hidden;
display: flex;
flex-direction: column;
}
/* ===== 状态占位 ===== */
.wyxd-state {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 40rpx;
}
.wyxd-state-icon {
font-size: 80rpx;
color: #ccc;
margin-bottom: 20rpx;
}
.wyxd-state-title {
font-size: 28rpx;
font-weight: 600;
color: #666;
margin-bottom: 8rpx;
}
.wyxd-state-desc {
font-size: 24rpx;
color: #999;
}
/* ===== 幻灯片区域 ===== */
.wyxd-slide-area {
flex: 1;
min-height: 0;
/* padding: 20rpx; */
}
.wyxd-slide-scroll {
height: 100%;
background: #fff;
border-radius: 12rpx;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.04);
}
/* .wyxd-slide-card {
padding: 32rpx;
min-height: 100%;
box-sizing: border-box;
} */
.wyxd-slide-card {
min-height: 100%;
box-sizing: border-box;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column; /* 子元素垂直排列 */
}
/* ===== 底部翻页 ===== */
.wyxd-pager {
flex-shrink: 0;
background: #fff;
border-top: 1rpx solid #eee;
padding: 16rpx 0;
padding-bottom: calc(16rpx + env(safe-area-inset-bottom));
}
.wyxd-pager-inner {
display: flex;
align-items: center;
justify-content: center;
}
.wyxd-nav-btn {
width: 64rpx;
height: 64rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: 32rpx;
background: #f5f5f5;
margin: 0 32rpx;
}
.wyxd-nav-btn:active {
background: #e0e0e0;
}
.wyxd-nav-btn.disabled {
opacity: 0.3;
pointer-events: none;
}
.wyxd-page-indicator {
font-size: 26rpx;
color: #666;
display: flex;
align-items: center;
}
.wyxd-current {
color: #3b82f6;
font-weight: 700;
}
.wyxd-divider {
margin: 0 8rpx;
color: #ccc;
}
.wyxd-total {
color: #999;
}
</style>