/** * 岗位表(job_postings)客户端接口:仅查本表字段,不连表 */ const Framework = require('../../framework/node-core-framework.js'); /** * 从 resume_info.job_listings 解析 Boss Tab 文案列表(与 get_job_listings 一致) * @param {unknown} job_listings * @returns {string[]} */ function parse_resume_tab_labels(job_listings) { if (job_listings == null) return []; let arr = job_listings; if (typeof arr === 'string') { try { arr = JSON.parse(arr); } catch (e) { return []; } } if (!Array.isArray(arr)) return []; const out = []; arr.forEach((item) => { if (item == null) return; if (typeof item === 'string') { const s = item.trim(); if (s) out.push(s); return; } if (typeof item === 'object' && item.text != null) { const s = String(item.text).trim(); if (s) out.push(s); } }); return [...new Set(out)]; } module.exports = { /** * 按设备 SN 拉取 jobId -> 投递结果字段(is_delivered、deliver_failed_reason、applyStatus) * 用于 Electron 职位列表页合并展示,不查 apply_records */ 'POST /job_postings/deliver_status_map': async (ctx) => { const models = Framework.getModels(); const { job_postings, op } = models; const body = ctx.getBody() || {}; const sn_code = body.sn_code || ctx.query?.sn_code; const platform = body.platform || 'boss'; const startTime = body.startTime; const endTime = body.endTime; if (!sn_code) { return ctx.fail('请提供设备SN码'); } const where = { sn_code, platform }; if (startTime || endTime) { where.last_modify_time = {}; if (startTime) { where.last_modify_time[op.gte] = new Date(startTime); } if (endTime) { const end = new Date(endTime); end.setHours(23, 59, 59, 999); where.last_modify_time[op.lte] = end; } } const rows = await job_postings.findAll({ where, attributes: ['jobId', 'is_delivered', 'deliver_failed_reason', 'applyStatus', 'last_modify_time'], order: [['last_modify_time', 'DESC']], limit: Math.min(Number(body.limit) || 2000, 5000) }); const list = rows.map((r) => { const j = r.toJSON ? r.toJSON() : r; return { jobId: j.jobId, is_delivered: !!j.is_delivered, deliver_failed_reason: j.deliver_failed_reason || '', applyStatus: j.applyStatus || 'pending', last_modify_time: j.last_modify_time }; }); return ctx.success({ list }); }, /** * 按设备 SN 分页查询 job_postings(仅本表字段,用于 Electron 职位列表只读展示) */ 'POST /job_postings/page_list': async (ctx) => { const models = Framework.getModels(); const { job_postings, resume_info, op } = models; const body = ctx.getBody() || {}; const sn_code = body.sn_code || ctx.query?.sn_code; const platform = body.platform || 'boss'; if (!sn_code) { return ctx.fail('请提供设备SN码'); } const page = Math.max(1, Number(body.page) || 1); const raw_page_size = body.page_size ?? body.pageSize ?? 20; const page_size = Math.min(100, Math.max(1, Number(raw_page_size) || 20)); const offset = (page - 1) * page_size; const base_where = { sn_code, platform }; const startTime = body.startTime; const endTime = body.endTime; if (startTime || endTime) { base_where.last_modify_time = {}; if (startTime) { base_where.last_modify_time[op.gte] = new Date(startTime); } if (endTime) { const end = new Date(endTime); end.setHours(23, 59, 59, 999); base_where.last_modify_time[op.lte] = end; } } let tab_labels = []; if (resume_info) { const resume = await resume_info.findOne({ where: { sn_code, platform, isActive: true }, order: [['last_modify_time', 'DESC']] }); if (resume) { const rj = resume.toJSON ? resume.toJSON() : resume; tab_labels = parse_resume_tab_labels(rj.job_listings); } } /** 不按「当前投递标签」过滤;列表为设备+平台下库中全部职位(各标签写入的 keyword 均会出现在列表中)。tab_labels 供前端展示「账户已同步的全部 Tab」 */ const where = base_where; const { rows, count } = await job_postings.findAndCountAll({ where, attributes: [ 'id', 'jobId', 'jobTitle', 'companyName', 'salary', 'location', 'education', 'experience', 'last_modify_time', 'create_time', 'is_delivered', 'deliver_failed_reason', 'applyStatus', 'platform', 'keyword', 'aiMatchScore' ], limit: page_size, offset, order: [['last_modify_time', 'DESC']] }); const list = rows.map((r) => { const j = r.toJSON ? r.toJSON() : r; return j; }); return ctx.success({ list, total: count, page, page_size, tab_labels }); } };