certPreview.vue 2.86 KB
<template>
  <view class="preview-container">
    <!-- 加载提示 -->
    <view class="loading-tip" v-if="loading">
      <view class="loading-icon"></view>
      <text>加载中...</text>
    </view>
    
    <!-- 错误提示 -->
    <view class="error-tip" v-else-if="showError">
      <text class="error-icon">⚠️</text>
      <text class="error-text">{{ errorMsg }}</text>
      <view class="retry-btn" @click="retryLoad">重试</view>
    </view>

    <!-- 方式1:使用 web-view(备选) -->
    <web-view 
      v-if="pdfUrl && !showError && useWebView" 
      :src="pdfUrl"
      @message="onWebViewMessage"
    ></web-view>
  </view>
</template>

<script setup>
import { ref } from "vue";
import { onLoad } from "@dcloudio/uni-app";
import { previewAttachment } from '@/common/utils.js'

const pdfUrl = ref("");
const loading = ref(false);
const showError = ref(false);
const errorMsg = ref("");
const useWebView = ref(false); // 是否使用 web-view 降级方案
const currentUrl = ref('')

onLoad((option) => {
  if (option.url) {
    currentUrl.value = decodeURIComponent(option.url);
    openAttachment(currentUrl.value);
  } else {
    loading.value = false;
    showError.value = true;
    errorMsg.value = "参数错误";
  }
});

const openAttachment = (url) => {
  showError.value = false;
  errorMsg.value = "";
  loading.value = false;
  previewAttachment(url, { title: '证书预览' })
};

// web-view 消息接收(可选)
const onWebViewMessage = (e) => {
  console.log("web-view message:", e.detail);
};

// 重试加载
const retryLoad = () => {
  showError.value = false;
  loading.value = false;
  useWebView.value = false;
  errorMsg.value = "";
  if (currentUrl.value) openAttachment(currentUrl.value);
};
</script>

<style lang="scss" scoped>
.preview-container {
  width: 100vw;
  height: 100vh;
  background: #f5f5f5;
  position: relative;
}

.loading-tip {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 20rpx;
  
  .loading-icon {
    width: 60rpx;
    height: 60rpx;
    border: 4rpx solid #e0e0e0;
    border-top-color: #AD181F;
    border-radius: 50%;
    animation: rotate 1s linear infinite;
  }
  
  text {
    font-size: 28rpx;
    color: #666;
  }
}

@keyframes rotate {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

.error-tip {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 20rpx;
  
  .error-icon {
    font-size: 80rpx;
  }
  
  .error-text {
    font-size: 28rpx;
    color: #C40F18;
  }
  
  .retry-btn {
    margin-top: 30rpx;
    padding: 16rpx 40rpx;
    background: #AD181F;
    color: #fff;
    border-radius: 40rpx;
    font-size: 28rpx;
  }
}

web-view {
  width: 100%;
  height: 100%;
}
</style>