Browse Source

1. 新增类别是类别id不传0
2. 报告详情资讯分类进行排序
3. 解决资讯管理选择资讯切换分页后选择的消失了的bug

zhuliu 1 tháng trước cách đây
mục cha
commit
68a6352ce6

+ 1 - 1
src/views/CategoryList.vue

@@ -127,7 +127,7 @@ const saveCategory = async () => {
       return
       return
     }
     }
     const params = {
     const params = {
-      categoryId: currentCategory.value.id,
+      categoryId: currentCategory.value.id || null,
       name: currentCategory.value.name,
       name: currentCategory.value.name,
     }
     }
     await categoryApi.createCategory(params)
     await categoryApi.createCategory(params)

+ 57 - 9
src/views/NewsList.vue

@@ -16,7 +16,7 @@
       <!-- Search form -->
       <!-- Search form -->
       <div class="search-container">
       <div class="search-container">
         <el-form :model="searchForm" label-width="100px" class="search-form">
         <el-form :model="searchForm" label-width="100px" class="search-form">
-          <el-row :gutter="20">
+          <el-row :gutter="5">
             <el-col :span="6">
             <el-col :span="6">
               <el-form-item label="资讯发布日期">
               <el-form-item label="资讯发布日期">
                 <div class="dateRange">
                 <div class="dateRange">
@@ -40,12 +40,12 @@
                 </div>
                 </div>
               </el-form-item>
               </el-form-item>
             </el-col>
             </el-col>
-            <el-col :span="4">
+            <el-col :span="5">
               <el-form-item label="来源名称">
               <el-form-item label="来源名称">
                 <el-input v-model="searchForm.sourceName" placeholder="请输入来源" />
                 <el-input v-model="searchForm.sourceName" placeholder="请输入来源" />
               </el-form-item>
               </el-form-item>
             </el-col>
             </el-col>
-            <el-col :span="4">
+            <el-col :span="5">
               <el-form-item label="关键字">
               <el-form-item label="关键字">
                 <el-input v-model="searchForm.key" placeholder="请输入关键字" />
                 <el-input v-model="searchForm.key" placeholder="请输入关键字" />
               </el-form-item>
               </el-form-item>
@@ -67,7 +67,7 @@
                 </el-select>
                 </el-select>
               </el-form-item>
               </el-form-item>
             </el-col>
             </el-col>
-            <el-col :span="5" class="search-actions">
+            <el-col :span="4" class="search-actions">
               <el-form-item label=" ">
               <el-form-item label=" ">
                 <el-button type="primary" @click="handleSearch">搜索</el-button>
                 <el-button type="primary" @click="handleSearch">搜索</el-button>
                 <el-button @click="resetSearch">重置</el-button>
                 <el-button @click="resetSearch">重置</el-button>
@@ -83,7 +83,9 @@
         :data="newsList"
         :data="newsList"
         style="width: 100%; flex: 1"
         style="width: 100%; flex: 1"
         v-loading="loading"
         v-loading="loading"
-        @selection-change="handleSelectionChange"
+        row-key="articleId"
+        @select="handleSelect"
+        @select-all="handleSelectAll"
         border
         border
         stripe
         stripe
         highlight-current-row
         highlight-current-row
@@ -136,7 +138,7 @@
               v-if="scope.row.isEditing"
               v-if="scope.row.isEditing"
               v-model="scope.row.digest"
               v-model="scope.row.digest"
               type="textarea"
               type="textarea"
-              :rows="4"
+              :rows="8"
               style="width: 100%"
               style="width: 100%"
             />
             />
             <span v-else>{{ scope.row.digest }}</span>
             <span v-else>{{ scope.row.digest }}</span>
@@ -176,6 +178,7 @@
                 <el-button size="small" @click="showAddToReportDialog = true"
                 <el-button size="small" @click="showAddToReportDialog = true"
                   >加入已有报告</el-button
                   >加入已有报告</el-button
                 >
                 >
+                <el-button size="small" @click="clearSelection">清空选择</el-button>
               </div>
               </div>
             </div>
             </div>
           </div>
           </div>
@@ -305,6 +308,8 @@ const categories = ref<Category[]>([])
 const reports = ref<Report[]>([])
 const reports = ref<Report[]>([])
 const loading = ref(false)
 const loading = ref(false)
 const selectedNews = ref<EditableNewsItem[]>([])
 const selectedNews = ref<EditableNewsItem[]>([])
+// 存储当前页选中的数据(用于跨页选中)
+const currentPageSelected = ref<Set<number>>(new Set())
 const showCreateReportDialog = ref(false)
 const showCreateReportDialog = ref(false)
 const showAddToReportDialog = ref(false)
 const showAddToReportDialog = ref(false)
 const showSelectedNews = ref(false)
 const showSelectedNews = ref(false)
@@ -366,6 +371,14 @@ const fetchNews = async () => {
       isEditing: false,
       isEditing: false,
     }))
     }))
     pagination.value.total = response.data.total
     pagination.value.total = response.data.total
+    // 下一帧恢复选中状态(确保表格渲染完成)
+    nextTick(() => {
+      newsList.value.forEach((row) => {
+        if (currentPageSelected.value.has(row.articleId)) {
+          toggleRowSelection(row, true)
+        }
+      })
+    })
   } catch (error) {
   } catch (error) {
     ElMessage.error('获取资讯列表失败')
     ElMessage.error('获取资讯列表失败')
   } finally {
   } finally {
@@ -373,6 +386,10 @@ const fetchNews = async () => {
   }
   }
 }
 }
 
 
+const toggleRowSelection = (row: EditableNewsItem, selected: boolean) => {
+  newsTableRef.value?.toggleRowSelection(row, selected)
+}
+
 const handleSearch = () => {
 const handleSearch = () => {
   // 重置到第一页
   // 重置到第一页
   pagination.value.currentPage = 1
   pagination.value.currentPage = 1
@@ -504,6 +521,7 @@ const removeFromSelection = (news: EditableNewsItem) => {
   const index = selectedNews.value.findIndex((item) => item.articleId === news.articleId)
   const index = selectedNews.value.findIndex((item) => item.articleId === news.articleId)
   if (index > -1) {
   if (index > -1) {
     selectedNews.value.splice(index, 1)
     selectedNews.value.splice(index, 1)
+    currentPageSelected.value.delete(news.articleId)
     newsTableRef.value?.toggleRowSelection(news, false)
     newsTableRef.value?.toggleRowSelection(news, false)
   }
   }
 }
 }
@@ -511,13 +529,43 @@ const removeFromSelection = (news: EditableNewsItem) => {
 // Clear all selections
 // Clear all selections
 const clearSelection = async () => {
 const clearSelection = async () => {
   selectedNews.value = []
   selectedNews.value = []
+  currentPageSelected.value = new Set()
   // Also clear selection in the table
   // Also clear selection in the table
   newsTableRef.value?.clearSelection()
   newsTableRef.value?.clearSelection()
 }
 }
 
 
-// Event handlers
-const handleSelectionChange = (selection: EditableNewsItem[]) => {
-  selectedNews.value = selection
+// 选中某一行时触发
+const handleSelect = (selection: EditableNewsItem[], row: EditableNewsItem) => {
+  if (selection.includes(row)) {
+    // 选中
+    selectedNews.value.push(row)
+    currentPageSelected.value.add(row.articleId)
+  } else {
+    // 取消选中
+    selectedNews.value = selectedNews.value.filter((item) => item.articleId !== row.articleId)
+    currentPageSelected.value.delete(row.articleId)
+  }
+}
+
+// 全选/取消全选
+const handleSelectAll = (selection: NewsItem[]) => {
+  const currentPageIds = new Set(newsList.value.map((item) => item.articleId))
+
+  if (selection.length > 0) {
+    // 全选
+    selection.forEach((item) => {
+      if (!selectedNews.value.some((selected) => selected.articleId === item.articleId)) {
+        selectedNews.value.push(item)
+      }
+    })
+    currentPageSelected.value = new Set([...currentPageSelected.value, ...currentPageIds])
+  } else {
+    // 取消全选
+    selectedNews.value = selectedNews.value.filter((item) => !currentPageIds.has(item.articleId))
+    currentPageSelected.value = new Set(
+      [...currentPageSelected.value].filter((articleId) => !currentPageIds.has(articleId))
+    )
+  }
 }
 }
 
 
 const handleSizeChange = (val: number) => {
 const handleSizeChange = (val: number) => {

+ 47 - 31
src/views/ReportDetail.vue

@@ -22,14 +22,10 @@
 
 
         <!-- News by category -->
         <!-- News by category -->
         <div class="news-by-category" v-loading="loading">
         <div class="news-by-category" v-loading="loading">
-          <div
-            v-for="(newsList, category) in newsByCategory"
-            :key="category"
-            class="category-section"
-          >
-            <h3 class="category-title">{{ category }}</h3>
+          <div v-for="item in newsByCategory" :key="item.categoryName" class="category-section">
+            <h3 class="category-title">{{ item.categoryName }}</h3>
             <div class="news-list">
             <div class="news-list">
-              <div v-for="news in newsList" :key="news.articleId" class="news-item">
+              <div v-for="news in item.data" :key="news.articleId" class="news-item">
                 <div class="news-item-header">
                 <div class="news-item-header">
                   <el-link :href="news.articleUrl" target="_blank" :underline="false">
                   <el-link :href="news.articleUrl" target="_blank" :underline="false">
                     <h4 class="news-title">{{ news.title }}</h4>
                     <h4 class="news-title">{{ news.title }}</h4>
@@ -143,7 +139,12 @@ const report = ref<Report>({
   createTime: new Date(),
   createTime: new Date(),
 })
 })
 
 
-const newsByCategory = ref<Record<string, NewsItem[]>>({})
+const newsByCategory = ref<
+  {
+    categoryName: string
+    data: NewsItem[]
+  }[]
+>([])
 const categories = ref<Category[]>([])
 const categories = ref<Category[]>([])
 const loading = ref(false)
 const loading = ref(false)
 
 
@@ -181,8 +182,24 @@ const fetchReportNews = async () => {
       }
       }
       grouped[news.categoryName].push(news)
       grouped[news.categoryName].push(news)
     })
     })
-
-    newsByCategory.value = grouped
+    const arr = []
+    for (const key in grouped) {
+      arr.push({
+        categoryName: key,
+        data: grouped[key],
+      })
+    }
+    arr.sort((a, b) => {
+      return (
+        categories.value.findIndex((item) => {
+          return item.name == a.categoryName
+        }) -
+        categories.value.findIndex((item) => {
+          return item.name == b.categoryName
+        })
+      )
+    })
+    newsByCategory.value = arr
   } catch (error) {
   } catch (error) {
     ElMessage.error('获取报告资讯失败')
     ElMessage.error('获取报告资讯失败')
   } finally {
   } finally {
@@ -231,44 +248,43 @@ const exportReportInfo = async () => {
     const reportId = parseInt(route.params.id as string)
     const reportId = parseInt(route.params.id as string)
     const response = await reportApi.exportReportInfo({ reportId: reportId })
     const response = await reportApi.exportReportInfo({ reportId: reportId })
     ElMessage.success('导出报告成功')
     ElMessage.success('导出报告成功')
-    if(response.code == 200){
+    if (response.code == 200) {
       const guid = response.data
       const guid = response.data
       //执行下载
       //执行下载
-      downLoad2(guid,report.value.reportName)
+      downLoad2(guid, report.value.reportName)
     }
     }
-    
   } catch (error) {
   } catch (error) {
     ElMessage.error('导出报告失败')
     ElMessage.error('导出报告失败')
   }
   }
 }
 }
 
 
 //获取下载地址
 //获取下载地址
-const getDownloadPath = (guid:string)=>{
-  if(!guid){
-      return ''
+const getDownloadPath = (guid: string) => {
+  if (!guid) {
+    return ''
   }
   }
   return `/api/fileManager/downloadFile?fileId=${guid}`
   return `/api/fileManager/downloadFile?fileId=${guid}`
 }
 }
 
 
-const downLoad2 = (guid:string,fileName="download") => {
+const downLoad2 = (guid: string, fileName = 'download') => {
   //获取下载地址
   //获取下载地址
   const href = getDownloadPath(guid)
   const href = getDownloadPath(guid)
-  if(!href){
+  if (!href) {
     return
     return
   }
   }
-  const anchor = document.createElement('a');
+  const anchor = document.createElement('a')
   if ('download' in anchor) {
   if ('download' in anchor) {
-    anchor.href = href;
-    anchor.setAttribute("download", fileName);
-    anchor.className = "download-js-link";
-    anchor.innerHTML = "downloading...";
-    anchor.style.display = "none";
-    document.body.appendChild(anchor);
+    anchor.href = href
+    anchor.setAttribute('download', fileName)
+    anchor.className = 'download-js-link'
+    anchor.innerHTML = 'downloading...'
+    anchor.style.display = 'none'
+    document.body.appendChild(anchor)
     setTimeout(function () {
     setTimeout(function () {
-      anchor.click();
-      document.body.removeChild(anchor);
-    }, 66);
-    return true;
+      anchor.click()
+      document.body.removeChild(anchor)
+    }, 66)
+    return true
   }
   }
 }
 }
 
 
@@ -302,10 +318,10 @@ const formatDate = (date: Date) => {
 }
 }
 
 
 // Lifecycle
 // Lifecycle
-onMounted(() => {
+onMounted(async () => {
   fetchReport()
   fetchReport()
+  await fetchCategories()
   fetchReportNews()
   fetchReportNews()
-  fetchCategories()
 })
 })
 </script>
 </script>