| 
					
				 | 
			
			
				@@ -1,6 +1,6 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const express = require('express'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const router = express.Router(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-const {Article} = require('../../models') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const {Article, Category} = require('../../models') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const {Op} = require('sequelize') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /*  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -23,17 +23,53 @@ router.get('/', async function(req, res, next) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         const condition = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             order:[['id','DESC']], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             limit:pageSize, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            offset 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            offset, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            include: [{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                model: Category, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                as: 'categoryInfo', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                attributes: ['id', 'name', 'level', 'parentId'], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                required: false // LEFT JOIN,即使没有分类也能返回文章 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            }] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 构建查询条件 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const whereConditions = {}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 标题搜索 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if(query.title){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            condition.where = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                title:{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    [Op.like]:`%${query.title}%` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            whereConditions.title = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                [Op.like]:`%${query.title}%` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 分类筛选 - 支持多选和包含子分类 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if(query.categoryIds){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            let categoryIds = []; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 处理categoryIds参数(支持逗号分隔的多个ID) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if(typeof query.categoryIds === 'string'){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                categoryIds = query.categoryIds.split(',').map(id => parseInt(id.trim())).filter(id => !isNaN(id)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } else if(Array.isArray(query.categoryIds)){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                categoryIds = query.categoryIds.map(id => parseInt(id)).filter(id => !isNaN(id)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                categoryIds = [parseInt(query.categoryIds)].filter(id => !isNaN(id)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if(categoryIds.length > 0){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // 获取所有选中的分类及其子分类的ID 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                const allCategoryIds = await getAllCategoryIdsWithChildren(categoryIds); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                whereConditions.category = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    [Op.in]: allCategoryIds 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 如果有查询条件,添加到condition中 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if(Object.keys(whereConditions).length > 0){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            condition.where = whereConditions; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         const {count ,rows} = await Article.findAndCountAll(condition) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         res.json({ 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -67,7 +103,14 @@ router.get('/:id', async function(req, res, next) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         const {id} = req.params 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         //查询文章 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        const article = await Article.findByPk(id) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const article = await Article.findByPk(id, { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            include: [{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                model: Category, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                as: 'categoryInfo', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                attributes: ['id', 'name', 'level', 'parentId'], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                required: false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            }] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        }) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if(article){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             res.json({ 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -241,6 +284,50 @@ router.put('/:id', async function(req, res, next) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 获取分类及其所有子分类的ID列表 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @param {Array} categoryIds - 分类ID数组 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @returns {Promise<Array>} 包含所有分类ID的数组 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+async function getAllCategoryIdsWithChildren(categoryIds) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let allIds = [...categoryIds]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 递归获取所有子分类 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        async function getChildrenIds(parentIds) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (parentIds.length === 0) return []; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            const children = await Category.findAll({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                where: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    parentId: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        [Op.in]: parentIds 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                attributes: ['id'] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            const childrenIds = children.map(child => child.id); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (childrenIds.length > 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                allIds = allIds.concat(childrenIds); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // 递归获取子分类的子分类 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                const grandChildrenIds = await getChildrenIds(childrenIds); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                allIds = allIds.concat(grandChildrenIds); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return childrenIds; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        await getChildrenIds(categoryIds); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 去重并返回 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return [...new Set(allIds)]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } catch (error) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        console.error('获取分类ID列表错误:', error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 如果出错,返回原始ID列表 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return categoryIds; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 function filterBody(req){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         // 数据清理和验证 
			 |