/** * 投递记录管理控制器(客户端接口) * 提供客户端调用的投递记录相关接口 */ const Framework = require("../../framework/node-core-framework.js"); module.exports = { /** * @swagger * /api/apply/list: * post: * summary: 获取投递记录列表 * description: 根据设备SN码分页获取投递记录 * tags: [前端-投递管理] * requestBody: * required: true * content: * application/json: * schema: * type: object * properties: * sn_code: * type: string * description: 设备SN码 * seachOption: * type: object * description: 搜索条件 * pageOption: * type: object * description: 分页选项 * responses: * 200: * description: 获取成功 */ 'POST /apply/list': async (ctx) => { const models = Framework.getModels(); const { apply_records, op } = models; const body = ctx.getBody(); // 从query或body中获取sn_code,优先从query获取 const sn_code = ctx.query?.sn_code || body.sn_code; if (!sn_code) { return ctx.fail('请提供设备SN码'); } const seachOption = body.seachOption || {}; const pageOption = body.pageOption || {}; // 获取分页参数 const page = pageOption.page || 1; const pageSize = pageOption.pageSize || 20; const limit = pageSize; const offset = (page - 1) * pageSize; const where = { sn_code }; // 平台筛选 if (seachOption.platform) { where.platform = seachOption.platform; } // 投递状态筛选 if (seachOption.applyStatus) { where.applyStatus = seachOption.applyStatus; } // 反馈状态筛选 if (seachOption.feedbackStatus) { where.feedbackStatus = seachOption.feedbackStatus; } // 搜索:岗位名称、公司名称 if (seachOption.key && seachOption.value) { const key = seachOption.key; const value = seachOption.value; if (key === 'jobTitle') { where.jobTitle = { [op.like]: `%${value}%` }; } else if (key === 'companyName') { where.companyName = { [op.like]: `%${value}%` }; } else { // 默认搜索岗位名称或公司名称 where[op.or] = [ { jobTitle: { [op.like]: `%${value}%` } }, { companyName: { [op.like]: `%${value}%` } } ]; } } const result = await apply_records.findAndCountAll({ where, limit, offset, order: [['applyTime', 'DESC']] }); return ctx.success({ count: result.count, total: result.count, rows: result.rows, list: result.rows }); }, /** * @swagger * /api/apply/statistics: * get: * summary: 获取投递统计 * description: 根据设备SN码获取投递统计数据(包含今日、本周、本月统计) * tags: [前端-投递管理] * parameters: * - in: query * name: sn_code * required: true * schema: * type: string * description: 设备SN码 * responses: * 200: * description: 获取成功 */ 'GET /apply/statistics': async (ctx) => { const models = Framework.getModels(); const { apply_records, op } = models; const { sn_code } = ctx.query; const final_sn_code = sn_code; if (!final_sn_code) { return ctx.fail('请提供设备SN码'); } // 计算时间范围 const now = new Date(); // 今天的开始时间(00:00:00) const todayStart = new Date(now); todayStart.setHours(0, 0, 0, 0); // 本周的开始时间(周一00:00:00) const weekStart = new Date(now); const dayOfWeek = weekStart.getDay(); const diff = dayOfWeek === 0 ? 6 : dayOfWeek - 1; // 周日算作上周 weekStart.setDate(weekStart.getDate() - diff); weekStart.setHours(0, 0, 0, 0); // 本月的开始时间(1号00:00:00) const monthStart = new Date(now.getFullYear(), now.getMonth(), 1); monthStart.setHours(0, 0, 0, 0); const [ totalCount, successCount, failedCount, pendingCount, interviewCount, todayCount, weekCount, monthCount ] = await Promise.all([ // 总计 apply_records.count({ where: { sn_code: final_sn_code } }), apply_records.count({ where: { sn_code: final_sn_code, applyStatus: 'success' } }), apply_records.count({ where: { sn_code: final_sn_code, applyStatus: 'failed' } }), apply_records.count({ where: { sn_code: final_sn_code, applyStatus: 'pending' } }), apply_records.count({ where: { sn_code: final_sn_code, feedbackStatus: 'interview' } }), // 今日 apply_records.count({ where: { sn_code: final_sn_code, applyTime: { [op.gte]: todayStart } } }), // 本周 apply_records.count({ where: { sn_code: final_sn_code, applyTime: { [op.gte]: weekStart } } }), // 本月 apply_records.count({ where: { sn_code: final_sn_code, applyTime: { [op.gte]: monthStart } } }) ]); return ctx.success({ totalCount, successCount, failedCount, pendingCount, interviewCount, todayCount, weekCount, monthCount, successRate: totalCount > 0 ? ((successCount / totalCount) * 100).toFixed(2) : 0, interviewRate: totalCount > 0 ? ((interviewCount / totalCount) * 100).toFixed(2) : 0 }); }, /** * @swagger * /api/apply/detail: * get: * summary: 获取投递记录详情 * description: 根据投递ID获取详细信息 * tags: [前端-投递管理] * parameters: * - in: query * name: applyId * required: true * schema: * type: string * description: 投递记录ID * responses: * 200: * description: 获取成功 */ 'GET /apply/detail': async (ctx) => { const models = Framework.getModels(); const { apply_records } = models; // 支持 applyId 和 id 两种参数名(向后兼容) const recordId = ctx.query.applyId || ctx.query.id; if (!recordId) { return ctx.fail('投递记录ID不能为空'); } // 使用 id 字段查询(数据库主键) const record = await apply_records.findOne({ where: { id: recordId } }); if (!record) { return ctx.fail('投递记录不存在'); } return ctx.success(record); }, /** * @swagger * /api/apply/trend: * get: * summary: 获取近7天投递趋势数据 * description: 根据设备SN码获取近7天的投递数量趋势 * tags: [前端-投递管理] * parameters: * - in: query * name: sn_code * required: true * schema: * type: string * description: 设备SN码 * responses: * 200: * description: 获取成功 */ 'GET /apply/trend': async (ctx) => { const models = Framework.getModels(); const { apply_records, op } = models; const { sn_code } = ctx.query; if (!sn_code) { return ctx.fail('请提供设备SN码'); } // 计算近7天的日期范围 const today = new Date(); today.setHours(23, 59, 59, 999); const sevenDaysAgo = new Date(); sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 6); sevenDaysAgo.setHours(0, 0, 0, 0); // 查询近7天的投递记录 const records = await apply_records.findAll({ where: { sn_code: sn_code, applyTime: { [op.gte]: sevenDaysAgo, [op.lte]: today } }, attributes: ['applyTime'], raw: true }); // 生成7天的日期数组 const trendData = []; for (let i = 6; i >= 0; i--) { const date = new Date(); date.setDate(date.getDate() - i); date.setHours(0, 0, 0, 0); const dateStr = `${date.getMonth() + 1}/${date.getDate()}`; // 统计当天的投递数量 const count = records.filter(record => { const recordDate = new Date(record.applyTime); recordDate.setHours(0, 0, 0, 0); return recordDate.getTime() === date.getTime(); }).length; trendData.push({ date: dateStr, value: count }); } return ctx.success(trendData); } };