'use strict'; const Service = require('egg').Service; /** * 新闻服务 - NewsService * * 封装新闻相关的数据库查询操作。 * 支持按组别过滤、按置顶过滤、分页查询。 */ class NewsService extends Service { /** * 查询新闻列表(支持分页和过滤) * * 过滤参数: * - group: 组别筛选(如 zhongzhi, gaozhi, benke, jiaoshi),同时包含 group='all' 的通用新闻 * - pinned: 是否仅查询置顶新闻(true/false) * * 排序规则:pinned DESC, publish_time DESC * * @param {Object} params - 查询参数 * @param {string} [params.group] - 目标组别 * @param {string|boolean} [params.pinned] - 是否只查置顶 * @param {number} [params.page=1] - 页码 * @param {number} [params.pageSize=20] - 每页数量 * @returns {Promise<{list: Array, total: number, page: number, pageSize: number}>} 分页结果 */ async list(params = {}) { const { ctx } = this; const { Sequelize } = ctx.app; const { group, pinned, page, pageSize } = params; // 分页参数,默认第 1 页,每页 20 条 const currentPage = parseInt(page) || 1; const currentPageSize = parseInt(pageSize) || 20; const offset = (currentPage - 1) * currentPageSize; // 构建查询条件 const where = {}; // 组别过滤:同时包含指定组别和通用(all)新闻 if (group) { where.group = { [Sequelize.Op.in]: [group, 'all'], }; } // 置顶过滤 if (pinned !== undefined && pinned !== null && pinned !== '') { where.pinned = pinned === 'true' || pinned === true; } // 构建查询 const queryOptions = { where, order: [ ['pinned', 'DESC'], ['sort_order', 'ASC'], ['publish_time', 'DESC'], ], attributes: ['id', 'title', 'content', 'publish_time', 'pinned', 'group', 'tags', 'sort_order', 'created_at', 'updated_at'], offset, limit: currentPageSize, }; // 查询新闻列表和总数 const [list, total] = await Promise.all([ ctx.model.News.findAll(queryOptions), ctx.model.News.count({ where }), ]); return { list, total, page: currentPage, pageSize: currentPageSize, }; } /** * 获取各分组新闻计数(用于首页 Tab 显示数量) * @returns {Promise} { all: number, zhongzhi: number, gaozhi: number, benke: number, jiaoshi: number } */ async getGroupCounts() { const { ctx } = this; const { Sequelize } = ctx.app; const groups = ['all', 'zhongzhi', 'gaozhi', 'benke', 'jiaoshi']; const counts = { all: 0, zhongzhi: 0, gaozhi: 0, benke: 0, jiaoshi: 0 }; // 并行查询各分组计数 await Promise.all(groups.map(async group => { const where = {}; // 对于具体组别,同时包含该组别和 all 通用新闻 if (group !== 'all') { where.group = { [Sequelize.Op.in]: [group, 'all'] }; } counts[group] = await ctx.model.News.count({ where }); })); return counts; } /** * 根据 ID 查询新闻详情 * * @param {number} id - 新闻 ID * @returns {Promise} 新闻模型对象或 null */ async findById(id) { const { ctx } = this; return await ctx.model.News.findOne({ where: { id }, attributes: ['id', 'title', 'content', 'publish_time', 'pinned', 'group', 'tags', 'sort_order', 'created_at', 'updated_at'], }); } /** * 批量更新新闻排序 * @param {Array<{id: number, sort_order: number}>} orders - 排序信息数组 * @returns {Promise} */ async updateSortOrder(orders) { const { ctx } = this; await Promise.all(orders.map(async ({ id, sort_order }) => { await ctx.model.News.update({ sort_order }, { where: { id } }); })); } } module.exports = NewsService;