Quellcode durchsuchen

前端bug问题修改

lingmin_package@163.com vor 1 Monat
Ursprung
Commit
c34c5076cf

+ 1 - 1
index.html

@@ -4,7 +4,7 @@
     <meta charset="UTF-8">
     <link rel="icon" href="/favicon.ico">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
-    <title>SSO认证中心</title>
+    <title>四川路桥AI后台管理平台</title>
   </head>
   <body>
     <div id="app"></div>

+ 17 - 6
src/api/request.ts

@@ -75,11 +75,20 @@ request.interceptors.response.use(
     
     const { code, message } = response.data ?? {}
 
+    console.log('>>> [响应拦截器] 响应数据:', {
+      url: response.config.url,
+      code,
+      message,
+      dataKeys: response.data ? Object.keys(response.data) : 'null',
+      dataType: typeof response.data,
+      isArray: Array.isArray(response.data)
+    })
+
     // 检查业务错误码是否为401或"200002"(无效的访问令牌)
     if (code === 401 || code === '200002') {
       console.log('>>> 检测到业务错误码401或200002(HTTP状态码为200)')
       console.log('>>> 立即跳转到登录页')
-      
+
       // 清除所有存储
       try {
         localStorage.clear()
@@ -87,27 +96,29 @@ request.interceptors.response.use(
       } catch (e) {
         console.error('清除存储失败:', e)
       }
-      
+
       // 显示错误提示
       const errorMsg = message || '无效的访问令牌'
       if (!response.config.headers?.['Skip-Error-Message']) {
         ElMessage.error(errorMsg + ',请重新登录')
       }
-      
+
       // 立即跳转
       console.log('>>> 执行跳转: window.location.href = "/login"')
       window.location.href = '/login'
-      
+
       // 阻止后续执行
       return new Promise(() => {})
     }
 
     // 成功响应(兼容字符串 code="000000" 和旧的整数 code=0/200,以及无 code 的纯数据/Blob 返回)
-    if (code === '000000' || (code === '000000' || code === 0) || code === 200 || typeof code === 'undefined') {
+    if (code === '000000' || code === 0 || code === 200 || typeof code === 'undefined') {
+      console.log('>>> [响应拦截器] 响应成功,返回数据')
       return response.data
     }
-    
+
     // 其他业务错误
+    console.log('>>> [响应拦截器] 业务错误:', { code, message })
     const errorMsg = message || '请求失败'
     if (!response.config.headers?.['Skip-Error-Message']) {
       ElMessage.error(errorMsg)

+ 1 - 1
src/layouts/MainLayout.vue

@@ -4,7 +4,7 @@
       <!-- 头部 -->
       <el-header class="header">
         <div class="header-left">
-          <h1>SSO 认证中心</h1>
+          <h1>四川路桥AI后台管理平台</h1>
         </div>
         <div class="header-right">
           <el-dropdown @command="handleCommand">

+ 57 - 32
src/views/admin/Tag.vue

@@ -211,9 +211,6 @@ const tagForm = reactive({
 const tagRules = {
   name: [
     { required: true, message: '请输入标签名称', trigger: 'blur' }
-  ],
-  parent_id: [
-    { required: true, message: '请选择上级标签', trigger: 'change' }
   ]
 }
 
@@ -235,30 +232,39 @@ const filterTreeByType = (nodes: TagCategory[] = [], type: 'category' | 'label')
 }
 
 // 加载标签分类树
-const loadCategoryTree = async () => {
+const loadCategoryTree = async (silent = false) => {
   treeLoading.value = true
   try {
     const response: any = await tagApi.getCategoryTree(true)
     console.log('分类树响应:', response)
-    
+    console.log('分类树响应结构:', {
+      hasCode: 'code' in response,
+      code: response.code,
+      hasData: 'data' in response,
+      dataType: typeof response.data,
+      isArray: Array.isArray(response.data)
+    })
+
     // tree接口返回格式: { code: 200, message: '...', data: [...] }
     // data是一个数组,包含所有根节点及其嵌套的children
     const treeData = response.data || []
-    
+
     // 过滤只显示type为category的节点
     const filtered = filterTreeByType(treeData, 'category')
     console.log('过滤后的分类树:', filtered)
     categoryTree.value = filtered
   } catch (error) {
     console.error('加载分类树失败:', error)
-    ElMessage.error('加载分类树失败')
+    if (!silent) {
+      ElMessage.error('加载分类树失败')
+    }
   } finally {
     treeLoading.value = false
   }
 }
 
 // 加载标签列表
-const loadTags = async () => {
+const loadTags = async (silent = false) => {
   if (!selectedCategory.value) {
     tags.value = []
     return
@@ -272,21 +278,23 @@ const loadTags = async () => {
       page: currentPage.value,
       page_size: pageSize.value
     })
-    
+
     console.log('标签列表响应(来自list):', response)
-    
+
     // list接口返回格式: { code: 200, message: '...', data: [...], meta: {...} }
     const listData = response.data || []
-    
+
     // 筛选 type 为 label 的节点
     const labelList = listData.filter((item: any) => item.type === 'label')
-    
+
     console.log('过滤后的标签列表:', labelList)
     tags.value = labelList
     total.value = response.meta?.total || labelList.length
   } catch (error) {
     console.error('加载标签列表失败:', error)
-    ElMessage.error('加载标签列表失败')
+    if (!silent) {
+      ElMessage.error('加载标签列表失败')
+    }
   } finally {
     loading.value = false
   }
@@ -324,20 +332,26 @@ const handleSelectionChange = (selection: any[]) => {
 
 // 状态切换
 const handleStatusChange = async (tag: any) => {
+  const oldStatus = tag.status
+
   try {
     const response = await tagApi.updateCategory(tag.id, { status: tag.status })
-    if (response.code === 200) {
+    if (response.code === 200 || response.code === '000000') {
       ElMessage.success('标签状态更新成功')
     } else {
       ElMessage.error(response.message || '更新标签状态失败')
       // 恢复原状态
-      tag.status = tag.status === 1 ? 0 : 1
+      tag.status = oldStatus === 1 ? 0 : 1
+      return
     }
+
+    // 刷新列表以确保数据同步
+    await loadTags(true)
   } catch (error) {
     console.error('更新标签状态失败:', error)
     ElMessage.error('更新标签状态失败')
     // 恢复原状态
-    tag.status = tag.status === 1 ? 0 : 1
+    tag.status = oldStatus === 1 ? 0 : 1
   }
 }
 
@@ -367,14 +381,18 @@ const deleteTag = async (tag: any) => {
         type: 'warning'
       }
     )
-    
+
     const response = await tagApi.deleteCategory(tag.id, true)
-    if (response.code === 200) {
+    if (response.code === 200 || response.code === '000000') {
       ElMessage.success('标签删除成功')
-      loadTags()
     } else {
       ElMessage.error(response.message || '删除标签失败')
+      return
     }
+
+    // 刷新分类树和标签列表
+    await loadCategoryTree(true)
+    await loadTags(true)
   } catch (error) {
     if (error !== 'cancel') {
       console.error('删除标签失败:', error)
@@ -387,31 +405,35 @@ const deleteTag = async (tag: any) => {
 const saveTag = async () => {
   try {
     await tagFormRef.value.validate()
-    
+
     saving.value = true
-    
+
     let response
     if (editingTag.value) {
       response = await tagApi.updateCategory(editingTag.value.id, tagForm)
-      if (response.code === 200) {
+      if (response.code === 200 || response.code === '000000') {
         ElMessage.success('标签更新成功')
+        showCreateDialog.value = false
+        resetForm()
       } else {
         ElMessage.error(response.message || '标签更新失败')
         return
       }
     } else {
       response = await tagApi.createCategory(tagForm)
-      if (response.code === 200) {
+      if (response.code === 200 || response.code === '000000') {
         ElMessage.success('标签创建成功')
+        showCreateDialog.value = false
+        resetForm()
       } else {
         ElMessage.error(response.message || '标签创建失败')
         return
       }
     }
-    
-    showCreateDialog.value = false
-    loadCategoryTree()
-    loadTags()
+
+    // 刷新分类树和标签列表
+    await loadCategoryTree(true)
+    await loadTags(true)
   } catch (error) {
     console.error('保存标签失败:', error)
     ElMessage.error('保存标签失败')
@@ -477,7 +499,7 @@ const openEditCategoryDialog = async () => {
   
   try {
     const response = await tagApi.getCategoryDetail(selectedCategory.value.id)
-    if (response.code === 200) {
+    if (response.code === 200 || response.code === '000000') {
       editingTag.value = response.data
       Object.assign(tagForm, {
         name: response.data.name,
@@ -503,7 +525,7 @@ const deleteCategoryConfirm = async () => {
     ElMessage.warning('请先选择一个分类')
     return
   }
-  
+
   try {
     await ElMessageBox.confirm(
       `确定要删除分类 "${selectedCategory.value.name}" 吗?此操作不可恢复。`,
@@ -514,16 +536,19 @@ const deleteCategoryConfirm = async () => {
         type: 'warning'
       }
     )
-    
+
     const response = await tagApi.deleteCategory(selectedCategory.value.id, true)
-    if (response.code === 200) {
+    if (response.code === 200 || response.code === '000000') {
       ElMessage.success('分类删除成功')
-      loadCategoryTree()
       selectedCategory.value = null
       tags.value = []
     } else {
       ElMessage.error(response.message || '删除分类失败')
+      return
     }
+
+    // 刷新分类树
+    await loadCategoryTree(true)
   } catch (error) {
     if (error !== 'cancel') {
       console.error('删除分类失败:', error)

+ 1 - 1
src/views/dashboard/Index.vue

@@ -2,7 +2,7 @@
   <div class="dashboard-content">
     <div class="welcome-section">
       <h2>欢迎回来,{{ authStore.user?.username }}!</h2>
-      <p>这是您的SSO认证中心控制台</p>
+      <p>这是您的四川路桥AI后台管理平台</p>
     </div>
 
     <!-- 统计卡片 -->

+ 48 - 8
src/views/documents/Index.vue

@@ -374,10 +374,10 @@
               :key="tag.id"
               closable
               @close="handleRemoveTag(index)"
-              type="info"
+              :type="tag.type === 'category' ? 'warning' : 'primary'"
               class="tag-item"
             >
-              {{ tag.name }}
+              {{ tag.name }} <span v-if="tag.type === 'category'" class="tag-type-hint">(分类)</span>
             </el-tag>
             <el-cascader
               :key="cascaderKey"
@@ -391,7 +391,15 @@
               class="tag-adder"
             >
               <template #default="{ data }">
-                <span>{{ data.label }}</span>
+                <span>
+                  <el-icon v-if="data.type === 'category'" style="margin-right: 4px; color: #E6A23C;">
+                    <Folder />
+                  </el-icon>
+                  <el-icon v-else style="margin-right: 4px; color: #409EFF;">
+                    <Tickets />
+                  </el-icon>
+                  {{ data.label }}
+                </span>
               </template>
             </el-cascader>
           </div>
@@ -816,7 +824,7 @@
 <script setup lang="ts">
 import { ref, reactive, onMounted, onUnmounted, computed } from 'vue'
 import { ElMessage, ElMessageBox } from 'element-plus'
-import { Search, Filter, Upload, CircleCheck, Delete, Document, Warning, TopRight, Grid, DataAnalysis, Link, View, Switch, Edit, User, Download, Plus, Minus, Tickets, Refresh } from '@element-plus/icons-vue'
+import { Search, Filter, Upload, CircleCheck, Delete, Document, Warning, TopRight, Grid, DataAnalysis, Link, View, Switch, Edit, User, Download, Plus, Minus, Tickets, Refresh, Folder, FolderOpened } from '@element-plus/icons-vue'
 import request from '@/api/request'
 import axios from 'axios'
 import { downloadFile } from '@/utils/download'
@@ -869,10 +877,24 @@ const tagTree = ref<any[]>([])
 const handleAddTag = (val: any) => {
   if (!val) return
   const id = val
-  const name = findTagName(tagTree.value, id)
-  if (name && !taskForm.selectedTags.find(t => t.id === id)) {
-    taskForm.selectedTags.push({ id, name })
+  const node = findTagNode(tagTree.value, id)
+  if (!node) return
+
+  // 检查是否是标签分类(type='category')
+  if (node.type === 'category' && node.children && node.children.length > 0) {
+    // 如果是标签分类,添加该分类下的所有标签项
+    node.children.forEach(child => {
+      if (!taskForm.selectedTags.find(t => t.id === child.value)) {
+        taskForm.selectedTags.push({ id: child.value, name: child.label, type: child.type })
+      }
+    })
+  } else {
+    // 如果是标签项,直接添加
+    if (node.type !== 'category' && !taskForm.selectedTags.find(t => t.id === id)) {
+      taskForm.selectedTags.push({ id, name: node.label, type: node.type })
+    }
   }
+
   // 清空选择器并增加 key 以强制重置 (清除搜索缓存等)
   tempTagValue.value = null
   cascaderKey.value++
@@ -892,10 +914,21 @@ const findTagName = (nodes: any[], id: number): string | null => {
   }
   return null
 }
+
+const findTagNode = (nodes: any[], id: number): any | null => {
+  for (const node of nodes) {
+    if (node.value === id) return node
+    if (node.children) {
+      const found = findTagNode(node.children, id)
+      if (found) return found
+    }
+  }
+  return null
+}
 const fetchTagTree = async () => {
   try {
     const res = await documentApi.getTagTree()
-    if (res.code === 200) {
+    if (res.code === '000000' || res.code === 200 || res.code === 0) {
       tagTree.value = formatTagTree(res.data)
     }
   } catch (error) {
@@ -908,6 +941,7 @@ const formatTagTree = (data: any[]) => {
   return data.map(node => ({
     value: node.id,
     label: node.name,
+    type: node.type,
     children: node.children && node.children.length > 0 ? formatTagTree(node.children) : undefined
   }))
 }
@@ -2120,6 +2154,12 @@ onUnmounted(() => {
   margin: 2px 0;
 }
 
+.tag-type-hint {
+  font-size: 12px;
+  margin-left: 4px;
+  opacity: 0.7;
+}
+
 .tag-adder {
   width: 120px;
 }

+ 61 - 11
src/views/images/Index.vue

@@ -186,10 +186,10 @@
               :key="tag.id"
               closable
               @close="handleRemoveTag(index)"
-              type="info"
+              :type="tag.type === 'category' ? 'warning' : 'primary'"
               class="tag-item"
             >
-              {{ tag.name }}
+              {{ tag.name }} <span v-if="tag.type === 'category'" class="tag-type-hint">(分类)</span>
             </el-tag>
             <el-cascader
               :key="cascaderKey"
@@ -203,7 +203,15 @@
               class="tag-adder"
             >
               <template #default="{ data }">
-                <span>{{ data.label }}</span>
+                <span>
+                  <el-icon v-if="data.type === 'category'" style="margin-right: 4px; color: #E6A23C;">
+                    <Folder />
+                  </el-icon>
+                  <el-icon v-else style="margin-right: 4px; color: #409EFF;">
+                    <Tickets />
+                  </el-icon>
+                  {{ data.label }}
+                </span>
               </template>
             </el-cascader>
           </div>
@@ -272,10 +280,24 @@ const tagTree = ref<any[]>([])
 const handleAddTag = (val: any) => {
   if (!val) return
   const id = val
-  const name = findTagName(tagTree.value, id)
-  if (name && !taskForm.selectedTags.find(t => t.id === id)) {
-    taskForm.selectedTags.push({ id, name })
+  const node = findTagNode(tagTree.value, id)
+  if (!node) return
+
+  // 检查是否是标签分类(type='category')
+  if (node.type === 'category' && node.children && node.children.length > 0) {
+    // 如果是标签分类,添加该分类下的所有标签项
+    node.children.forEach(child => {
+      if (!taskForm.selectedTags.find(t => t.id === child.value)) {
+        taskForm.selectedTags.push({ id: child.value, name: child.label, type: child.type })
+      }
+    })
+  } else {
+    // 如果是标签项,直接添加
+    if (node.type !== 'category' && !taskForm.selectedTags.find(t => t.id === id)) {
+      taskForm.selectedTags.push({ id, name: node.label, type: node.type })
+    }
   }
+
   // 清空选择器并增加 key 以强制重置 (清除搜索缓存等)
   tempTagValue.value = null
   cascaderKey.value++
@@ -295,10 +317,21 @@ const findTagName = (nodes: any[], id: number): string | null => {
   }
   return null
 }
+
+const findTagNode = (nodes: any[], id: number): any | null => {
+  for (const node of nodes) {
+    if (node.value === id) return node
+    if (node.children) {
+      const found = findTagNode(node.children, id)
+      if (found) return found
+    }
+  }
+  return null
+}
 const fetchTagTree = async () => {
   try {
     const res = await documentApi.getTagTree()
-    if (res.code === 200) {
+    if (res.code === '000000' || res.code === 200 || res.code === 0) {
       tagTree.value = formatTagTree(res.data)
     }
   } catch (error) {
@@ -310,6 +343,7 @@ const formatTagTree = (data: any[]) => {
   return data.map(node => ({
     value: node.id,
     label: node.name,
+    type: node.type,
     children: node.children && node.children.length > 0 ? formatTagTree(node.children) : undefined
   }))
 }
@@ -404,9 +438,16 @@ const handleCategoryBatchAddToTask = async () => {
     const res = await imageApi.categoryBatchCheck(categoryId)
     loading.value = false
     
-    if (res.code !== 0) {
-      ElMessage.error(res.message || '检查分类失败')
-      return
+    //if (res.code !== 0) {
+    //  ElMessage.error(res.message || '检查分类失败')
+    //  return
+    //}
+
+    // 兼容成功错误码 "000000"、0 和 "0" 等情况
+    const successCodes = [0, "0", "000000"]
+    if (!successCodes.includes(res.code)) {
+        ElMessage.error(res.message || '检查分类失败')
+        return
     }
 
     const { image_count, sub_categories } = res.data
@@ -616,7 +657,10 @@ const startBatchUpload = async () => {
     try {
       // 1. 获取预签名 URL
       const res = await imageApi.getUploadUrl(item.file.name, item.file.type || 'application/octet-stream')
-      if (res.code !== 0) throw new Error(res.message)
+      //if (res.code !== 0) throw new Error(res.message)
+      // 兼容成功错误码 "000000"、0 和 "0" 等情况
+      const successCodes = [0, "0", "000000"]
+      if (!successCodes.includes(res.code)) throw new Error(res.message)
 
       const { upload_url, file_url } = res.data
 
@@ -714,6 +758,12 @@ onMounted(() => {
   margin: 2px 0;
 }
 
+.tag-type-hint {
+  font-size: 12px;
+  margin-left: 4px;
+  opacity: 0.7;
+}
+
 .tag-adder {
   width: 120px;
 }