Files
competition-website/app/service/news.js

133 lines
3.8 KiB
JavaScript
Raw Normal View History

'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<Object>} { 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<Model|null>} 新闻模型对象或 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<void>}
*/
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;