From afeeed281e60466b576fbe74d339634cc5d07b82 Mon Sep 17 00:00:00 2001
From: Codex Assistant <codex@example.com>
Date: 星期三, 08 十月 2025 08:56:42 +0800
Subject: [PATCH] 修复评审功能和用户认证问题

---
 web/src/views/review-detail.vue |  114 ++++++++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 97 insertions(+), 17 deletions(-)

diff --git a/web/src/views/review-detail.vue b/web/src/views/review-detail.vue
index 848948b..fd0a3be 100644
--- a/web/src/views/review-detail.vue
+++ b/web/src/views/review-detail.vue
@@ -168,13 +168,17 @@
     <!-- 鏂囦欢棰勮瀵硅瘽妗� -->
     <el-dialog v-model="previewVisible" title="鏂囦欢棰勮" width="80%" center>
       <div class="preview-content">
-        <iframe 
-          v-if="previewUrl" 
-          :src="previewUrl" 
-          style="width: 100%; height: 500px; border: none;"
-        ></iframe>
+        <!-- 鍥剧墖棰勮 -->
+        <img v-if="previewType === 'image' && previewUrl" :src="previewUrl" style="max-width: 100%; max-height: 70vh; object-fit: contain;" />
+        <!-- 瑙嗛棰勮 -->
+        <video v-else-if="previewType === 'video' && previewUrl" :src="previewUrl" controls style="width: 100%; max-height: 70vh;"></video>
+        <!-- PDF 棰勮 -->
+        <iframe v-else-if="previewType === 'pdf' && previewUrl" :src="previewUrl" style="width: 100%; height: 70vh; border: none;"></iframe>
+        <!-- DOCX 棰勮 -->
+        <div v-else-if="previewType === 'docx'" ref="docxContainer" class="docx-preview"></div>
+        <!-- 鍏跺畠涓嶆敮鎸� -->
         <div v-else class="preview-error">
-          <el-empty description="鏃犳硶棰勮姝ゆ枃浠剁被鍨�" />
+          <el-empty description="鏃犳硶棰勮姝ゆ枃浠剁被鍨嬶紝璇蜂笅杞芥煡鐪�" />
         </div>
       </div>
     </el-dialog>
@@ -204,6 +208,8 @@
 const ratingComment = ref('')
 const previewVisible = ref(false)
 const previewUrl = ref('')
+const previewType = ref('') // image | video | pdf | docx | unknown
+const docxContainer = ref(null)
 
 // 鏉冮檺楠岃瘉鐩稿叧
 const currentJudge = ref(null)
@@ -446,17 +452,84 @@
   }
 }
 
-// 鏂囦欢棰勮
-const previewFile = (file) => {
-  // 鏍规嵁鏂囦欢绫诲瀷鍐冲畾棰勮鏂瑰紡
-  const fileExtension = file.name.split('.').pop().toLowerCase()
-  const previewableTypes = ['pdf', 'txt', 'jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'mp4', 'avi', 'mov', 'wmv', 'flv', 'webm']
-  
-  if (previewableTypes.includes(fileExtension)) {
-    // 鍦ㄦ柊绐楀彛涓墦寮�棰勮
-    window.open(file.url, '_blank')
-  } else {
-    ElMessage.warning('姝ゆ枃浠剁被鍨嬩笉鏀寔棰勮锛岃涓嬭浇鏌ョ湅')
+/**
+ * 鏂囦欢棰勮锛氭寜鎵╁睍鍚嶅垎鍙戝埌鍥剧墖/瑙嗛/PDF/DOCX
+ */
+const previewFile = async (file) => {
+  const ext = (file.name?.split('.').pop() || '').toLowerCase()
+  previewVisible.value = true
+  previewUrl.value = ''
+  previewType.value = ''
+  // 缁熶竴鍙栧彲鐢ㄧ殑瀹屾暣 URL
+  const url = file.url || file.fullUrl || file.full_path || file.path
+
+  const imageExts = ['jpg','jpeg','png','gif','bmp','webp']
+  const videoExts = ['mp4','webm','ogg','avi','mov','wmv','flv','mkv']
+
+  if (imageExts.includes(ext)) {
+    previewType.value = 'image'
+    previewUrl.value = url
+    return
+  }
+  if (videoExts.includes(ext)) {
+    previewType.value = 'video'
+    previewUrl.value = url
+    return
+  }
+  if (ext === 'pdf') {
+    previewType.value = 'pdf'
+    previewUrl.value = url
+    return
+  }
+  if (ext === 'docx') {
+    previewType.value = 'docx'
+    try {
+      await renderDocx(url)
+    } catch (e) {
+      console.error('DOCX 棰勮澶辫触:', e)
+      ElMessage.warning('DOCX 棰勮澶辫触锛屽缓璁笅杞芥煡鐪�')
+      previewType.value = 'unknown'
+    }
+    return
+  }
+  if (ext === 'doc') {
+    ElMessage.info('鏆備笉鏀寔 .doc 棰勮锛岃涓嬭浇鏌ョ湅')
+    previewType.value = 'unknown'
+    return
+  }
+
+  ElMessage.warning('姝ゆ枃浠剁被鍨嬩笉鏀寔棰勮锛岃涓嬭浇鏌ョ湅')
+  previewType.value = 'unknown'
+}
+
+/**
+ * 鍔ㄦ�佸姞杞� docx-preview 骞舵覆鏌� DOCX
+ */
+const renderDocx = async (url) => {
+  const ensureScript = () => new Promise((resolve, reject) => {
+    if (window.docx && window.docx.renderAsync) return resolve(true)
+    const existed = document.querySelector('script[data-docx-preview]')
+    if (existed) {
+      existed.addEventListener('load', () => resolve(true))
+      existed.addEventListener('error', reject)
+      return
+    }
+    const s = document.createElement('script')
+    s.src = 'https://unpkg.com/docx-preview/dist/docx-preview.min.js'
+    s.async = true
+    s.setAttribute('data-docx-preview', '1')
+    s.onload = () => resolve(true)
+    s.onerror = reject
+    document.head.appendChild(s)
+  })
+
+  await ensureScript()
+  const res = await fetch(url, { credentials: 'include' })
+  if (!res.ok) throw new Error('鑾峰彇 DOCX 澶辫触: ' + res.status)
+  const blob = await res.blob()
+  if (docxContainer.value) {
+    docxContainer.value.innerHTML = ''
+    await window.docx.renderAsync(blob, docxContainer.value, null, { inWrapper: true })
   }
 }
 
@@ -699,6 +772,13 @@
 .preview-content {
   text-align: center;
 }
+.docx-preview {
+  text-align: left;
+  max-height: 70vh;
+  overflow: auto;
+  background: #fff;
+  padding: 12px;
+}
 
 .preview-error {
   padding: 40px 0;

--
Gitblit v1.8.0