Parcourir la source

feat:修改创建接口报错500问题

wangsisi il y a 18 heures
Parent
commit
201c11dcb8

+ 20 - 0
migrations/20250914034529-update-article-title-to-text.js

@@ -0,0 +1,20 @@
+'use strict';
+
+/** @type {import('sequelize-cli').Migration} */
+module.exports = {
+  async up (queryInterface, Sequelize) {
+    // 将title字段从STRING改为TEXT以支持更长的标题
+    await queryInterface.changeColumn('Articles', 'title', {
+      type: Sequelize.TEXT,
+      allowNull: false
+    });
+  },
+
+  async down (queryInterface, Sequelize) {
+    // 回滚时将title字段改回STRING
+    await queryInterface.changeColumn('Articles', 'title', {
+      type: Sequelize.STRING,
+      allowNull: false
+    });
+  }
+};

+ 20 - 0
migrations/20250914040554-update-article-content-to-longtext.js

@@ -0,0 +1,20 @@
+'use strict';
+
+/** @type {import('sequelize-cli').Migration} */
+module.exports = {
+  async up (queryInterface, Sequelize) {
+    // 将content字段从TEXT改为LONGTEXT以支持更大的内容
+    await queryInterface.changeColumn('Articles', 'content', {
+      type: Sequelize.TEXT('long'),
+      allowNull: true
+    });
+  },
+
+  async down (queryInterface, Sequelize) {
+    // 回滚时将content字段改回TEXT
+    await queryInterface.changeColumn('Articles', 'content', {
+      type: Sequelize.TEXT,
+      allowNull: true
+    });
+  }
+};

+ 4 - 4
models/article.js

@@ -15,7 +15,7 @@ module.exports = (sequelize, DataTypes) => {
   }
   Article.init({
     title: {
-      type:DataTypes.STRING,
+      type:DataTypes.TEXT,
       allowNull:false,
       validate:{
         notNull:{
@@ -25,12 +25,12 @@ module.exports = (sequelize, DataTypes) => {
           msg:'标题不能为空'
         },
         len:{
-          args:[1,45],
-          msg:'标题长度需要子1~45个字符之间'
+          args:[1,500],
+          msg:'标题长度需要在1~500个字符之间'
         }
       }
     },
-    content: DataTypes.TEXT,
+    content: DataTypes.TEXT('long'),
     type:DataTypes.INTEGER,
     img:DataTypes.TEXT,
     date:DataTypes.DATE,

+ 76 - 37
routes/admin/articles.js

@@ -96,14 +96,27 @@ router.get('/:id', async function(req, res, next) {
  */
 router.post('/', async function(req, res, next) {
     try {
+        // 添加请求日志
+        console.log('=== 创建文章请求开始 ===');
+        console.log('请求体大小:', JSON.stringify(req.body).length);
+        console.log('Content字段长度:', req.body.content ? req.body.content.length : 0);
+        console.log('Title字段长度:', req.body.title ? req.body.title.length : 0);
+
         //白名单过滤
         const body = filterBody(req)
 
-        // 添加调试日志
-        console.log('创建文章请求体大小:', JSON.stringify(body).length);
-        console.log('Content字段长度:', body.content ? body.content.length : 0);
+        console.log('过滤后的数据:', {
+            titleLength: body.title ? body.title.length : 0,
+            contentLength: body.content ? body.content.length : 0,
+            hasImage: !!body.img,
+            type: body.type
+        });
 
         const article = await Article.create(body)
+        
+        console.log('文章创建成功, ID:', article.id);
+        console.log('=== 创建文章请求结束 ===');
+        
         res.status(201).json({
             status:true,
             message:'成功',
@@ -111,35 +124,45 @@ router.post('/', async function(req, res, next) {
         }); 
     }catch(error){
         // 添加详细的错误日志
-        console.error('创建文章错误:', error);
+        console.error('=== 创建文章错误 ===');
+        console.error('错误名称:', error.name);
+        console.error('错误消息:', error.message);
         console.error('错误堆栈:', error.stack);
+        console.error('请求体大小:', JSON.stringify(req.body).length);
         console.error('请求体:', JSON.stringify(req.body, null, 2));
 
-        if(error.name === 'SequelizeValidationError'){
-            const errors = error.errors.map(e =>e.message)
-
+        if(error.message === '标题不能为空' || error.message === '内容不能为空' || 
+           error.message.includes('长度不能超过') || error.message.includes('不允许的脚本标签')){
             res.status(400).json({ 
                 status:false,
                 message:'请求参数错误',
+                errors:[error.message]
+            });
+        }else if(error.name === 'SequelizeValidationError'){
+            const errors = error.errors.map(e => e.message)
+            res.status(400).json({ 
+                status:false,
+                message:'数据验证失败',
                 errors
             });
         }else if(error.name === 'SequelizeDatabaseError'){
+            console.error('数据库错误详情:', error.original);
             res.status(500).json({ 
                 status:false,
                 message:'数据库错误',
-                errors:[error.message]
+                errors:['数据库操作失败,请稍后重试']
             });
         }else if(error.name === 'SequelizeConnectionError'){
             res.status(500).json({ 
                 status:false,
                 message:'数据库连接错误',
-                errors:[error.message]
+                errors:['数据库连接失败,请稍后重试']
             });
         }else{
             res.status(500).json({ 
                 status:false,
                 message:'服务器内部错误',
-                errors:[error.message]
+                errors:['服务器处理请求时发生错误,请稍后重试']
             });
         }
         
@@ -219,35 +242,51 @@ router.put('/:id', async function(req, res, next) {
 });
 
 function filterBody(req){
-    // 数据清理和验证
-    const body = {
-        title: req.body.title ? String(req.body.title).trim() : null,
-        content: req.body.content ? String(req.body.content) : null,
-        type: req.body.type ? parseInt(req.body.type) : null,
-        img: req.body.img ? String(req.body.img).trim() : null,
-        date: req.body.date ? new Date(req.body.date) : null,
-        author: req.body.author ? String(req.body.author).trim() : null,
-        category: req.body.category ? parseInt(req.body.category) : null,
-        crop: req.body.crop ? parseInt(req.body.crop) : null,
-        seoKeyword: req.body.seoKeyword ? String(req.body.seoKeyword).trim() : null,
-        seoDescription: req.body.seoDescription ? String(req.body.seoDescription).trim() : null
-    };
-
-    // 验证必填字段
-    if (!body.title) {
-        throw new Error('标题不能为空');
-    }
+    try {
+        // 数据清理和验证
+        const body = {
+            title: req.body.title ? String(req.body.title).trim() : null,
+            content: req.body.content ? String(req.body.content) : null,
+            type: req.body.type ? parseInt(req.body.type) : null,
+            img: req.body.img ? String(req.body.img).trim() : null,
+            date: req.body.date ? new Date(req.body.date) : null,
+            author: req.body.author ? String(req.body.author).trim() : null,
+            category: req.body.category ? parseInt(req.body.category) : null,
+            crop: req.body.crop ? parseInt(req.body.crop) : null,
+            seoKeyword: req.body.seoKeyword ? String(req.body.seoKeyword).trim() : null,
+            seoDescription: req.body.seoDescription ? String(req.body.seoDescription).trim() : null
+        };
 
-    if (!body.content) {
-        throw new Error('内容不能为空');
-    }
+        // 验证必填字段
+        if (!body.title) {
+            throw new Error('标题不能为空');
+        }
 
-    // 验证标题长度
-    if (body.title.length > 255) {
-        throw new Error('标题长度不能超过255个字符');
-    }
+        if (!body.content) {
+            throw new Error('内容不能为空');
+        }
+
+        // 验证标题长度 - 放宽限制以适应富文本编辑器
+        if (body.title.length > 500) {
+            throw new Error('标题长度不能超过500个字符');
+        }
+
+        // 验证内容长度 - 防止过大的内容
+        if (body.content.length > 5000000) { // 5MB限制
+            throw new Error('内容过长,请减少内容长度');
+        }
 
-    return body;
+        // 检查富文本内容是否包含危险标签或脚本
+        const dangerousTags = /<script[^>]*>.*?<\/script>/gi;
+        if (dangerousTags.test(body.content)) {
+            throw new Error('内容包含不允许的脚本标签');
+        }
+
+        return body;
+    } catch (error) {
+        console.error('filterBody错误:', error);
+        throw error;
+    }
 }
 
-module.exports = router;
+module.exports = router;