const express = require('express'); const router = express.Router(); const {Article} = require('../../models') const {Op} = require('sequelize') /* 查询文章列表 GET /admin/articles */ router.get('/', async function(req, res, next) { try { const query = req.query //当前是第几页,如果不传,那就是第一页 const currentPage = Math.abs(Number(query.currentPage)) || 1 //每页显示多少条数据,如果不传,那就显示10条 const pageSize = Math.abs(Number(query.pageSize)) || 10 //计算 offset const offset = (currentPage - 1) * pageSize const condition = { order:[['id','DESC']], limit:pageSize, offset } if(query.title){ condition.where = { title:{ [Op.like]:`%${query.title}%` } } } const {count ,rows} = await Article.findAndCountAll(condition) res.json({ status:true, message:'成功', data:{ articles:rows, pagination:{ total:count, currentPage, pageSize } } }); }catch(error){ res.status(500).json({ status:false, message:'失败', errors:[error.message] }); } }); /* 查询文章详情 GET /admin/articles/:id */ router.get('/:id', async function(req, res, next) { try { //获取文章id const {id} = req.params //查询文章 const article = await Article.findByPk(id) if(article){ res.json({ status:true, message:'成功', data:article }); }else{ res.status(404).json({ status:false, message:'文章未找到', }); } }catch(error){ res.status(500).json({ status:false, message:'失败', errors:[error.message] }); } }); /* 创建文章 POST /admin/articles/ */ router.post('/', async function(req, res, next) { try { //白名单过滤 const body = filterBody(req) // 添加调试日志 console.log('创建文章请求体大小:', JSON.stringify(body).length); console.log('Content字段长度:', body.content ? body.content.length : 0); const article = await Article.create(body) res.status(201).json({ status:true, message:'成功', data:article }); }catch(error){ // 添加详细的错误日志 console.error('创建文章错误:', error); console.error('错误堆栈:', error.stack); console.error('请求体:', JSON.stringify(req.body, null, 2)); 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'){ res.status(500).json({ status:false, message:'数据库错误', errors:[error.message] }); }else if(error.name === 'SequelizeConnectionError'){ res.status(500).json({ status:false, message:'数据库连接错误', errors:[error.message] }); }else{ res.status(500).json({ status:false, message:'服务器内部错误', errors:[error.message] }); } } }); /* 删除文章 GET /admin/articles/:id */ router.delete('/:id', async function(req, res, next) { try { //获取文章id const {id} = req.params //查询文章 const article = await Article.findByPk(id) if(article){ await article.destroy() res.json({ status:true, message:'成功', }); }else{ res.status(404).json({ status:false, message:'文章未找到', }); } }catch(error){ res.status(500).json({ status:false, message:'失败', errors:[error.message] }); } }); /* 更新文章 GET /admin/articles/:id */ router.put('/:id', async function(req, res, next) { try { //获取文章id const {id} = req.params //查询文章 const article = await Article.findByPk(id) //白名单过滤 const body = filterBody(req) if(article){ await article.update(body) res.json({ status:true, message:'成功', data:article }); }else{ res.status(404).json({ status:false, message:'文章未找到', }); } }catch(error){ res.status(500).json({ status:false, message:'失败', errors:[error.message] }); } }); 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('标题不能为空'); } if (!body.content) { throw new Error('内容不能为空'); } // 验证标题长度 if (body.title.length > 255) { throw new Error('标题长度不能超过255个字符'); } return body; } module.exports = router;