chenkun 4 hete
szülő
commit
b4db7a01f4

+ 2 - 0
src/api/document.ts

@@ -25,6 +25,8 @@ export interface DocumentItem {
   error_message?: string // 兼容旧代码
   created_by?: string
   updated_by?: string
+  creator_name?: string
+  updater_name?: string
   created_time: string
   updated_time: string
   created_at?: string // 兼容旧代码

+ 11 - 1
src/api/request.ts

@@ -5,9 +5,19 @@ import { useAuthStore } from '@/stores/auth'
 import { getToken, getRefreshToken } from '@/utils/auth'
 import router from '@/router'
 
+// 获取基础 URL
+const getBaseURL = () => {
+  let url = import.meta.env.VITE_API_BASE_URL || 'http://localhost:8000'
+  // 自动处理跨电脑访问:如果配置是 localhost 但当前通过 IP 访问,则自动替换为当前 IP
+  if (url.includes('localhost') && typeof window !== 'undefined' && window.location.hostname !== 'localhost' && window.location.hostname !== '127.0.0.1') {
+    url = url.replace('localhost', window.location.hostname)
+  }
+  return url
+}
+
 // 创建axios实例
 const request: AxiosInstance = axios.create({
-  baseURL: import.meta.env.VITE_API_BASE_URL || 'http://localhost:8000',
+  baseURL: getBaseURL(),
   timeout: 30000, // 调整为 30 秒,避免长时间挂起
   headers: {
     'Content-Type': 'application/json'

+ 10 - 2
src/utils/download.ts

@@ -12,8 +12,16 @@ export const downloadFile = async (url: string, filename?: string) => {
   const token = getToken()
   if (!token) return
   
-  // 构建下载代理 URL
-  const downloadUrl = `/api/v1/sample/documents/download?url=${encodeURIComponent(url)}${filename ? `&filename=${encodeURIComponent(filename)}` : ''}&token=${token}`
+  // 获取 API 基础地址,确保与 axios 配置一致
+  let baseURL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:8000'
+  
+  // 自动处理跨电脑访问:如果配置是 localhost 但当前通过 IP 访问,则自动替换为当前 IP
+  if (baseURL.includes('localhost') && window.location.hostname !== 'localhost' && window.location.hostname !== '127.0.0.1') {
+    baseURL = baseURL.replace('localhost', window.location.hostname)
+  }
+  
+  // 构建下载代理 URL (使用绝对路径,避免在非代理环境下失效)
+  const downloadUrl = `${baseURL.replace(/\/$/, '')}/api/v1/sample/documents/download?url=${encodeURIComponent(url)}${filename ? `&filename=${encodeURIComponent(filename)}` : ''}&token=${token}`
   
   try {
     // 使用 fetch 预检下载,这样可以捕获错误响应

+ 28 - 0
src/utils/file.ts

@@ -0,0 +1,28 @@
+/**
+ * 获取文件后缀名
+ * @param row 包含 file_url 和可选 file_extension 的对象
+ * @returns 后缀名(带点,如 .pdf)
+ */
+export const getFileExtension = (row: { file_url?: string; file_extension?: string }) => {
+  // 1. 优先使用数据库存储的后缀
+  if (row.file_extension) {
+    return row.file_extension.startsWith('.') ? row.file_extension : `.${row.file_extension}`
+  }
+  
+  // 2. 如果数据库没有,再尝试从 URL 解析
+  const url = row.file_url
+  if (!url) return ''
+  try {
+    const path = new URL(url).pathname
+    const lastDotIndex = path.lastIndexOf('.')
+    if (lastDotIndex === -1) return ''
+    const ext = path.slice(lastDotIndex).toLowerCase()
+    if (ext.length > 6 || ext === '.') return ''
+    return ext
+  } catch (e) {
+    const lastDotIndex = url.lastIndexOf('.')
+    if (lastDotIndex === -1) return ''
+    const ext = url.slice(lastDotIndex).split(/[?#]/)[0].toLowerCase()
+    return ext.length <= 6 ? ext : ''
+  }
+}

+ 6 - 3
src/views/admin/TaskManagement.vue

@@ -10,7 +10,8 @@
       <el-tabs v-model="activeTab" @tab-change="handleTabChange">
         <el-tab-pane label="信息任务管理" name="data">
           <el-table v-loading="loading" :data="taskList" border stripe style="width: 100%">
-            <el-table-column prop="id" label="基本信息ID" min-width="180" />
+            <el-table-column prop="id" label="任务序号" width="100" />
+            <el-table-column prop="business_id" label="基本信息ID" min-width="180" />
             <el-table-column prop="name" label="名称" min-width="250" show-overflow-tooltip />
             <el-table-column prop="task_id" label="任务ID (task_id)" min-width="200">
               <template #default="{ row }">
@@ -23,7 +24,8 @@
 
         <el-tab-pane label="图片任务管理" name="image">
           <el-table v-loading="loading" :data="taskList" border stripe style="width: 100%">
-            <el-table-column prop="id" label="图片ID" min-width="180" />
+            <el-table-column prop="id" label="任务序号" width="100" />
+            <el-table-column prop="business_id" label="图片ID" min-width="180" />
             <el-table-column prop="name" label="名称" min-width="250" show-overflow-tooltip />
             <el-table-column prop="task_id" label="任务ID (task_id)" min-width="200">
               <template #default="{ row }">
@@ -44,7 +46,8 @@ import { ElMessage } from 'element-plus'
 import request from '@/api/request'
 
 interface TaskItem {
-  id: string
+  id: number
+  business_id: string
   task_id: string | null
   type: string
   name: string

+ 115 - 23
src/views/basic-info/Index.vue

@@ -158,16 +158,16 @@
             {{ scope.row.note || '-' }}
           </template>
         </el-table-column>
-        <el-table-column prop="created_by" label="创建人" width="100" />
-        <el-table-column prop="created_at" label="创建时间" width="180">
+        <el-table-column prop="creator_name" label="创建人" width="100" />
+        <el-table-column prop="created_time" label="创建时间" width="180">
           <template #default="scope">
-            {{ formatDateTime(scope.row.created_at) }}
+            {{ formatDateTime(scope.row.created_time) }}
           </template>
         </el-table-column>
-        <el-table-column prop="updated_by" label="修改人" width="100" />
-        <el-table-column prop="updated_at" label="修改时间" width="180">
+        <el-table-column prop="updater_name" label="修改人" width="100" />
+        <el-table-column prop="updated_time" label="修改时间" width="180">
           <template #default="scope">
-            {{ formatDateTime(scope.row.updated_at) }}
+            {{ formatDateTime(scope.row.updated_time) }}
           </template>
         </el-table-column>
         <el-table-column label="操作" width="180" fixed="right" align="center">
@@ -289,9 +289,15 @@
             </el-form-item>
           </el-col>
 
-          <el-col :span="12" v-if="infoType === 'basis'">
+          <el-col :span="24" v-if="infoType === 'basis'">
             <el-form-item label="参编单位">
-              <el-input v-model="editForm.participating_units" placeholder="请输入参编单位" />
+              <div v-for="(unit, index) in participatingUnitsList" :key="index" class="dynamic-input-row">
+                <el-input v-model="participatingUnitsList[index]" placeholder="请输入参编单位" />
+                <div class="row-actions">
+                  <el-button :icon="Plus" circle size="small" @click="addListItem(participatingUnitsList)" />
+                  <el-button :icon="Minus" circle size="small" type="danger" @click="removeListItem(participatingUnitsList, index)" />
+                </div>
+              </div>
             </el-form-item>
           </el-col>
 
@@ -301,9 +307,15 @@
             </el-form-item>
           </el-col>
 
-          <el-col :span="12" v-if="infoType === 'basis'">
+          <el-col :span="24" v-if="infoType === 'basis'">
             <el-form-item label="引用依据">
-              <el-input v-model="editForm.reference_basis" placeholder="请输入引用依据" />
+              <div v-for="(basis, index) in referenceBasisList" :key="index" class="dynamic-input-row">
+                <el-input v-model="referenceBasisList[index]" placeholder="请输入引用依据" />
+                <div class="row-actions">
+                  <el-button :icon="Plus" circle size="small" @click="addListItem(referenceBasisList)" />
+                  <el-button :icon="Minus" circle size="small" type="danger" @click="removeListItem(referenceBasisList, index)" />
+                </div>
+              </div>
             </el-form-item>
           </el-col>
 
@@ -363,8 +375,14 @@
               </el-form-item>
             </el-col>
             <el-col :span="24">
-              <el-form-item label="编制依据">
-                <el-input v-model="editForm.compilation_basis" type="textarea" :rows="3" placeholder="请输入编制依据,多个依据请用逗号分隔" />
+              <el-form-item label="施工标准规范">
+                <div v-for="(basis, index) in compilationBasisList" :key="index" class="dynamic-input-row">
+                  <el-input v-model="compilationBasisList[index]" placeholder="请输入施工标准规范" />
+                  <div class="row-actions">
+                    <el-button :icon="Plus" circle size="small" @click="addListItem(compilationBasisList)" />
+                    <el-button :icon="Minus" circle size="small" type="danger" @click="removeListItem(compilationBasisList, index)" />
+                  </div>
+                </div>
               </el-form-item>
             </el-col>
           </template>
@@ -389,7 +407,7 @@
           </el-col>
 
           <el-col :span="24">
-            <el-form-item label="文件链接">
+            <el-form-item label="文件预览链接" v-if="false">
               <el-input v-model="editForm.file_url" placeholder="请输入文件预览链接 (URL)" />
             </el-form-item>
           </el-col>
@@ -410,6 +428,18 @@
         <el-descriptions-item :label="dateLabel">{{ formatDate(currentItem?.release_date) }}</el-descriptions-item>
         <el-descriptions-item label="文档类型" v-if="infoType === 'basis' || infoType === 'job'">{{ currentItem?.document_type || '-' }}</el-descriptions-item>
         <el-descriptions-item label="专业领域" v-if="infoType === 'basis'">{{ currentItem?.professional_field || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="参编单位" v-if="infoType === 'basis'">
+          <div v-if="currentItem?.participating_units">
+            <div v-for="(unit, idx) in currentItem.participating_units.split(';')" :key="idx">{{ unit }}</div>
+          </div>
+          <span v-else>-</span>
+        </el-descriptions-item>
+        <el-descriptions-item label="引用依据" v-if="infoType === 'basis'">
+          <div v-if="currentItem?.reference_basis">
+            <div v-for="(basis, idx) in currentItem.reference_basis.split(';')" :key="idx">{{ basis }}</div>
+          </div>
+          <span v-else>-</span>
+        </el-descriptions-item>
         <el-descriptions-item label="时效性" v-if="infoType === 'basis'">
           <el-tag :type="getValidityType(currentItem?.validity)">{{ currentItem?.validity || '现行' }}</el-tag>
         </el-descriptions-item>
@@ -422,10 +452,17 @@
           <el-descriptions-item label="三级分类">{{ currentItem?.level_3_classification || '-' }}</el-descriptions-item>
           <el-descriptions-item label="四级分类">{{ currentItem?.level_4_classification || '-' }}</el-descriptions-item>
           <el-descriptions-item label="方案摘要">{{ currentItem?.plan_summary || '-' }}</el-descriptions-item>
-          <el-descriptions-item label="编制依据">{{ currentItem?.compilation_basis || '-' }}</el-descriptions-item>
+          <el-descriptions-item label="施工标准规范">
+            <div v-if="currentItem?.compilation_basis">
+              <div v-for="(basis, idx) in currentItem.compilation_basis.split(';')" :key="idx">{{ basis }}</div>
+            </div>
+            <span v-else>-</span>
+          </el-descriptions-item>
         </template>
-        <el-descriptions-item label="创建人">{{ currentItem?.created_by }}</el-descriptions-item>
-        <el-descriptions-item label="创建时间">{{ formatDateTime(currentItem?.created_at) }}</el-descriptions-item>
+        <el-descriptions-item label="创建人">{{ currentItem?.creator_name || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="创建时间">{{ formatDateTime(currentItem?.created_time) }}</el-descriptions-item>
+        <el-descriptions-item label="修改人">{{ currentItem?.updater_name || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="修改时间">{{ formatDateTime(currentItem?.updated_time) }}</el-descriptions-item>
       </el-descriptions>
       <template #footer>
         <el-button @click="detailDialogVisible = false">关闭</el-button>
@@ -466,12 +503,13 @@
 <script setup lang="ts">
 import { ref, onMounted, computed, watch, reactive } from 'vue'
 import { useRoute } from 'vue-router'
-import { Search, View, Monitor, Download, Edit, Delete, Refresh, Plus, Document } from '@element-plus/icons-vue'
+import { Search, View, Monitor, Download, Edit, Delete, Refresh, Plus, Minus, Document } from '@element-plus/icons-vue'
 import { ElMessage, ElMessageBox } from 'element-plus'
 import request from '@/api/request'
 import type { ApiResponse } from '@/types/auth'
 import dayjs from 'dayjs'
 import { downloadFile } from '@/utils/download'
+import { getFileExtension } from '@/utils/file'
 import { useAuthStore } from '@/stores/auth'
 
 const route = useRoute()
@@ -491,6 +529,23 @@ const previewLoading = ref(false)
 const previewUrl = ref('')
 const previewTitle = ref('')
 
+// 动态列表字段存储
+const participatingUnitsList = ref<string[]>([''])
+const referenceBasisList = ref<string[]>([''])
+const compilationBasisList = ref<string[]>([''])
+
+const addListItem = (list: string[]) => {
+  list.push('')
+}
+
+const removeListItem = (list: string[], index: number) => {
+  if (list.length > 1) {
+    list.splice(index, 1)
+  } else {
+    list[0] = ''
+  }
+}
+
 // 当前操作的数据
 const currentItem = ref<any>(null)
 const editForm = reactive<any>({
@@ -584,7 +639,7 @@ const infoType = computed(() => {
 
 const pageTitle = computed(() => {
   switch (infoType.value) {
-    case 'basis': return '编制依据管理'
+    case 'basis': return '施工标准规范管理'
     case 'work': return '施工方案管理'
     case 'job': return '办公制度管理'
     default: return '基本信息管理'
@@ -593,7 +648,7 @@ const pageTitle = computed(() => {
 
 const moduleName = computed(() => {
   switch (infoType.value) {
-    case 'basis': return '编制依据'
+    case 'basis': return '施工标准规范'
     case 'work': return '施工方案'
     case 'job': return '办公制度'
     default: return ''
@@ -712,7 +767,10 @@ const getValidityType = (validity: string) => {
 const proxyPreviewUrl = computed(() => {
   if (!previewUrl.value) return ''
   // 使用后端代理接口查看外部网页,附加 token 以通过认证
-  const baseUrl = import.meta.env.VITE_API_BASE_URL || 'http://localhost:8000'
+  let baseUrl = import.meta.env.VITE_API_BASE_URL || 'http://localhost:8000'
+  if (baseUrl.includes('localhost') && window.location.hostname !== 'localhost' && window.location.hostname !== '127.0.0.1') {
+    baseUrl = baseUrl.replace('localhost', window.location.hostname)
+  }
   return `${baseUrl}/api/v1/sample/documents/proxy-view?url=${encodeURIComponent(previewUrl.value)}&token=${authStore.token}`
 })
 
@@ -743,7 +801,9 @@ const handleAction = async (action: string, row: any) => {
       break
     case 'download':
       if (row.file_url) {
-        downloadFile(row.file_url, row.title)
+        const ext = getFileExtension(row)
+        const filename = row.title.endsWith(ext) ? row.title : `${row.title}${ext}`
+        downloadFile(row.file_url, filename)
       } else {
         ElMessage.warning('该文档暂无下载链接')
       }
@@ -752,6 +812,11 @@ const handleAction = async (action: string, row: any) => {
       Object.keys(editForm).forEach(key => {
         editForm[key] = row[key] || ''
       })
+      // 处理动态列表字段
+      participatingUnitsList.value = row.participating_units ? row.participating_units.split(';') : ['']
+      referenceBasisList.value = row.reference_basis ? row.reference_basis.split(';') : ['']
+      compilationBasisList.value = row.compilation_basis ? row.compilation_basis.split(';') : ['']
+      
       editForm.id = row.id
       formDialogVisible.value = true
       break
@@ -787,6 +852,11 @@ const handleAdd = () => {
       editForm[key] = ''
     }
   })
+  // 初始化动态列表字段
+   participatingUnitsList.value = ['']
+   referenceBasisList.value = ['']
+   compilationBasisList.value = ['']
+  
   editForm.id = null
   formDialogVisible.value = true
 }
@@ -796,6 +866,11 @@ const submitForm = async () => {
     return ElMessage.warning('请输入名称')
   }
   
+  // 提交前合并动态列表字段,过滤掉空行并用分号连接
+  editForm.participating_units = participatingUnitsList.value.filter(item => item.trim() !== '').join(';')
+  editForm.reference_basis = referenceBasisList.value.filter(item => item.trim() !== '').join(';')
+  editForm.compilation_basis = compilationBasisList.value.filter(item => item.trim() !== '').join(';')
+  
   submitting.value = true
   try {
     const isEdit = !!editForm.id
@@ -820,8 +895,8 @@ const submitForm = async () => {
 }
 
 const openInNewWindow = () => {
-  if (previewUrl.value) {
-    window.open(previewUrl.value, '_blank')
+  if (proxyPreviewUrl.value) {
+    window.open(proxyPreviewUrl.value, '_blank')
   }
 }
 
@@ -876,6 +951,23 @@ onMounted(() => {
   margin-top: 10px;
 }
 
+.dynamic-input-row {
+  display: flex;
+  align-items: center;
+  margin-bottom: 8px;
+  width: 100%;
+}
+
+.dynamic-input-row:last-child {
+  margin-bottom: 0;
+}
+
+.row-actions {
+  display: flex;
+  gap: 5px;
+  margin-left: 10px;
+}
+
 .table-card {
   padding: 10px;
 }

+ 26 - 39
src/views/documents/Index.vue

@@ -50,7 +50,7 @@
         <div class="filter-group">
           <el-select v-model="searchQuery.table_type" placeholder="所属知识库" clearable class="filter-select">
             <el-option label="全部知识库" :value="null" />
-            <el-option label="编制依据知识库" value="basis" />
+            <el-option label="施工标准规范知识库" value="basis" />
             <el-option label="施工方案知识库" value="work" />
             <el-option label="办公制度知识库" value="job" />
           </el-select>
@@ -151,7 +151,7 @@
           </template>
         </el-table-column>
 
-        <el-table-column prop="created_by" label="上传人" min-width="100" show-overflow-tooltip />
+        <el-table-column prop="creator_name" label="上传人" min-width="100" show-overflow-tooltip />
 
         <el-table-column label="上传时间" min-width="150" prop="created_time">
           <template #default="scope">
@@ -159,7 +159,7 @@
           </template>
         </el-table-column>
 
-        <el-table-column prop="updated_by" label="修改人" min-width="100" show-overflow-tooltip />
+        <el-table-column prop="updater_name" label="修改人" min-width="100" show-overflow-tooltip />
 
         <el-table-column label="修改时间" min-width="150" prop="updated_time">
           <template #default="scope">
@@ -294,7 +294,7 @@
       <el-form :model="uploadForm" label-width="100px">
         <el-form-item label="所属知识库" required>
           <el-select v-model="uploadForm.table_type" placeholder="请选择知识库">
-            <el-option label="编制依据知识库" value="basis" />
+            <el-option label="施工标准规范知识库" value="basis" />
             <el-option label="施工方案知识库" value="work" />
             <el-option label="办公制度知识库" value="job" />
           </el-select>
@@ -307,6 +307,7 @@
         </el-form-item>
         <el-form-item label="文件上传">
           <el-upload
+            ref="uploadRef"
             class="upload-demo"
             action="#"
             :http-request="customUpload"
@@ -338,7 +339,7 @@
         <el-divider content-position="left">基础信息</el-divider>
         <el-form-item label="所属知识库" required>
           <el-select v-model="editForm.table_type" disabled placeholder="请选择知识库" style="width: 100%">
-            <el-option label="编制依据知识库" value="basis" />
+            <el-option label="施工标准规范知识库" value="basis" />
             <el-option label="施工方案知识库" value="work" />
             <el-option label="办公制度知识库" value="job" />
           </el-select>
@@ -346,13 +347,13 @@
         <el-form-item label="文档标题" required>
           <el-input v-model="editForm.title" placeholder="请输入文档标题" />
         </el-form-item>
-        <el-form-item label="文档链接">
+        <el-form-item label="文档链接" v-if="false">
           <el-input v-model="editForm.file_url" placeholder="请输入文档链接 (URL)" />
         </el-form-item>
         
         <el-divider content-position="left">专业属性补全</el-divider>
         
-        <!-- 编制依据特有字段 -->
+        <!-- 施工标准规范特有字段 -->
         <template v-if="editForm.table_type === 'basis'">
           <el-form-item label="标准编号">
             <el-input v-model="editForm.standard_no" placeholder="如:GB/T 50001-2017" />
@@ -452,8 +453,8 @@
           <el-form-item label="方案摘要">
             <el-input v-model="editForm.plan_summary" type="textarea" :rows="3" placeholder="请输入方案摘要" />
           </el-form-item>
-          <el-form-item label="编制依据">
-            <el-input v-model="editForm.compilation_basis" type="textarea" :rows="3" placeholder="请输入编制依据,多个依据请用逗号分隔" />
+          <el-form-item label="施工标准规范">
+            <el-input v-model="editForm.compilation_basis" type="textarea" :rows="3" placeholder="请输入施工标准规范,多个依据请用逗号分隔" />
           </el-form-item>
         </template>
 
@@ -486,8 +487,10 @@
       <el-descriptions :column="1" border>
         <el-descriptions-item label="名称">{{ currentDoc?.title }}</el-descriptions-item>
         <el-descriptions-item label="知识库">{{ getKnowledgeBaseName(currentDoc?.source_type) }}</el-descriptions-item>
-        <el-descriptions-item label="上传人">{{ currentDoc?.created_by }}</el-descriptions-item>
+        <el-descriptions-item label="上传人">{{ currentDoc?.creator_name || '-' }}</el-descriptions-item>
         <el-descriptions-item label="上传时间">{{ formatDate(currentDoc?.created_time) }}</el-descriptions-item>
+        <el-descriptions-item label="最后修改人" v-if="currentDoc?.updater_name">{{ currentDoc?.updater_name }}</el-descriptions-item>
+        <el-descriptions-item label="修改时间" v-if="currentDoc?.updated_time">{{ formatDate(currentDoc?.updated_time) }}</el-descriptions-item>
         <el-descriptions-item label="入库状态">
           <el-tag :type="isEntered(currentDoc?.whether_to_enter) ? 'success' : 'info'">
             {{ isEntered(currentDoc?.whether_to_enter) ? '已入库' : '未入库' }}
@@ -511,7 +514,7 @@
           <el-descriptions-item label="方案摘要">
             <div class="content-preview">{{ currentDoc?.plan_summary || '-' }}</div>
           </el-descriptions-item>
-          <el-descriptions-item label="编制依据">
+          <el-descriptions-item label="施工标准规范">
             <div class="content-preview">{{ currentDoc?.compilation_basis || '-' }}</div>
           </el-descriptions-item>
         </template>
@@ -550,6 +553,7 @@ import { Search, Filter, Upload, CircleCheck, Delete, Document, Warning, TopRigh
 import request from '@/api/request'
 import axios from 'axios'
 import { downloadFile } from '@/utils/download'
+import { getFileExtension } from '@/utils/file'
 import { useAuthStore } from '@/stores/auth'
 import dayjs from 'dayjs'
 import { documentApi, type DocumentItem } from '@/api/document'
@@ -559,6 +563,7 @@ import { documentApi, type DocumentItem } from '@/api/document'
 // 状态变量
 const loading = ref(false)
 const submitting = ref(false)
+const uploadRef = ref<any>(null)
 const uploadDialogVisible = ref(false)
 const editDialogVisible = ref(false)
 const detailDialogVisible = ref(false)
@@ -632,7 +637,10 @@ const uploadForm = reactive({
 const proxyPreviewUrl = computed(() => {
   if (!previewUrl.value) return ''
   // 使用后端代理接口查看外部网页,附加 token 以通过认证
-  const baseUrl = import.meta.env.VITE_API_BASE_URL || 'http://localhost:8000'
+  let baseUrl = import.meta.env.VITE_API_BASE_URL || 'http://localhost:8000'
+  if (baseUrl.includes('localhost') && window.location.hostname !== 'localhost' && window.location.hostname !== '127.0.0.1') {
+    baseUrl = baseUrl.replace('localhost', window.location.hostname)
+  }
   return `${baseUrl}/api/v1/sample/documents/proxy-view?url=${encodeURIComponent(previewUrl.value)}&token=${authStore.token}`
 })
 
@@ -654,30 +662,6 @@ const formatDate = (date: string | undefined | null, formatStr: string = 'YYYY-M
 
 
 
-const getFileExtension = (row: DocumentItem) => {
-  // 1. 优先使用数据库存储的后缀
-  if (row.file_extension) {
-    return row.file_extension.startsWith('.') ? row.file_extension : `.${row.file_extension}`
-  }
-  
-  // 2. 如果数据库没有,再尝试从 URL 解析
-  const url = row.file_url
-  if (!url) return ''
-  try {
-    const path = new URL(url).pathname
-    const lastDotIndex = path.lastIndexOf('.')
-    if (lastDotIndex === -1) return ''
-    const ext = path.slice(lastDotIndex).toLowerCase()
-    if (ext.length > 6 || ext === '.') return ''
-    return ext
-  } catch (e) {
-    const lastDotIndex = url.lastIndexOf('.')
-    if (lastDotIndex === -1) return ''
-    const ext = url.slice(lastDotIndex).split(/[?#]/)[0].toLowerCase()
-    return ext.length <= 6 ? ext : ''
-  }
-}
-
 const getFileIcon = (row: DocumentItem) => {
   const ext = getFileExtension(row).replace('.', '').toLowerCase()
   if (['pdf'].includes(ext)) return 'pdf'
@@ -694,7 +678,7 @@ const getFileIconClass = (row: DocumentItem) => {
 
 const getKnowledgeBaseName = (sourceType: string | null | undefined) => {
   const names: Record<string, string> = {
-    basis: '编制依据知识库',
+    basis: '施工标准规范知识库',
     work: '施工方案知识库',
     job: '办公制度知识库'
   }
@@ -703,7 +687,7 @@ const getKnowledgeBaseName = (sourceType: string | null | undefined) => {
 
 const getKnowledgeBaseShortName = (sourceType: string | null | undefined) => {
   const names: Record<string, string> = {
-    basis: '编制依据',
+    basis: '施工标准规范',
     work: '施工方案',
     job: '办公制度'
   }
@@ -1001,6 +985,9 @@ const handleUpload = () => {
   uploadForm.title = ''
   uploadForm.note = ''
   uploadForm.file_url = ''
+  if (uploadRef.value) {
+    uploadRef.value.clearFiles()
+  }
   uploadDialogVisible.value = true
 }
 
@@ -1158,7 +1145,7 @@ const handleConvert = async (row: DocumentItem) => {
   if (row.conversion_status === 2) {
     try {
       await ElMessageBox.confirm(
-        '该数据已经转换,再次转换会覆盖数据',
+        '该文档已经转换完成,再次转换将覆盖原转换后端文件,你继续吗?',
         '再次转换确认',
         {
           confirmButtonText: '确定',