This commit is contained in:
张成
2026-04-08 16:39:27 +08:00
parent 048c40d802
commit f2a8e61016
8 changed files with 597 additions and 66 deletions

View File

@@ -5,6 +5,57 @@
const Framework = require("../../framework/node-core-framework.js");
/**
* 为 job_types 行批量附加 pla_account列表/详情展示)
* @param {import('sequelize').Model[]} rowInstances
* @param {object} models
* @returns {Promise<object[]>}
*/
async function attachPlaAccountToJobTypeRows(rowInstances, models) {
const { pla_account, op } = models;
const plain = (rowInstances || []).map((r) => (r && typeof r.toJSON === 'function' ? r.toJSON() : r));
const ids = [...new Set(plain.map((row) => row.pla_account_id).filter((id) => id != null && id !== ''))];
if (!pla_account || ids.length === 0) {
return plain.map((row) => ({ ...row, pla_account: null }));
}
const accounts = await pla_account.findAll({
where: { id: { [op.in]: ids } },
attributes: ['id', 'name', 'sn_code', 'login_name']
});
const map = {};
accounts.forEach((a) => {
const j = a.toJSON();
map[j.id] = j;
});
return plain.map((row) => ({
...row,
pla_account: row.pla_account_id != null ? map[row.pla_account_id] || null : null
}));
}
/**
* @param {*} raw
* @param {object} pla_account
* @returns {Promise<{ ok: boolean, value?: number|null, message?: string }>}
*/
async function normalizePlaAccountId(raw, pla_account) {
if (raw === undefined) {
return { ok: true, skip: true };
}
if (raw === null || raw === '') {
return { ok: true, value: null };
}
const n = parseInt(raw, 10);
if (Number.isNaN(n) || n < 1) {
return { ok: false, message: '关联账户ID无效' };
}
const acc = await pla_account.findByPk(n);
if (!acc) {
return { ok: false, message: '关联账户不存在' };
}
return { ok: true, value: n };
}
module.exports = {
/**
* @swagger
@@ -37,14 +88,26 @@ module.exports = {
const models = Framework.getModels();
const { job_types, op } = models;
const body = ctx.getBody();
const { name } = body;
const seachOption = body.seachOption || {};
// 获取分页参数
const { limit, offset } = ctx.getPageSize();
const where = {};
if (name) {
where.name = { [op.like]: `%${name}%` };
const key = seachOption.key || body.key;
const value = seachOption.value !== undefined && seachOption.value !== null ? seachOption.value : body.value;
if (key && value !== undefined && value !== null && String(value).trim() !== '') {
const v = String(value).trim();
if (key === 'pla_account_id') {
const n = parseInt(v, 10);
if (!Number.isNaN(n)) {
where.pla_account_id = n;
}
} else if (key === 'name' || key === 'description') {
where[key] = { [op.like]: `%${v}%` };
}
}
if (seachOption.is_enabled !== undefined && seachOption.is_enabled !== null) {
where.is_enabled = seachOption.is_enabled;
}
const result = await job_types.findAndCountAll({
@@ -54,7 +117,8 @@ module.exports = {
order: [['sort_order', 'ASC'], ['id', 'ASC']]
});
return ctx.success(result);
const rows = await attachPlaAccountToJobTypeRows(result.rows, models);
return ctx.success({ rows, count: result.count });
},
/**
@@ -89,7 +153,8 @@ module.exports = {
return ctx.fail('职位类型不存在');
}
return ctx.success(jobType);
const [enriched] = await attachPlaAccountToJobTypeRows([jobType], models);
return ctx.success(enriched);
},
/**
@@ -120,6 +185,9 @@ module.exports = {
* excludeKeywords:
* type: array
* description: 排除关键词JSON数组
* titleIncludeKeywords:
* type: array
* description: 职位标题须同时包含的子串JSON数组仅匹配岗位标题
* is_enabled:
* type: integer
* description: 是否启用1=启用0=禁用)
@@ -132,9 +200,9 @@ module.exports = {
*/
'POST /job_type/create': async (ctx) => {
const models = Framework.getModels();
const { job_types } = models;
const { job_types, pla_account } = models;
const body = ctx.getBody();
const { name, description, commonSkills, excludeKeywords, is_enabled, sort_order } = body;
const { name, description, commonSkills, excludeKeywords, titleIncludeKeywords, is_enabled, sort_order } = body;
if (!name) {
return ctx.fail('职位类型名称不能为空');
@@ -146,16 +214,30 @@ module.exports = {
return ctx.fail('职位类型名称已存在');
}
let pla_account_id = null;
const paResolved = await normalizePlaAccountId(body.pla_account_id, pla_account);
if (!paResolved.ok) {
return ctx.fail(paResolved.message || '关联账户校验失败');
}
if (!paResolved.skip) {
pla_account_id = paResolved.value === undefined ? null : paResolved.value;
}
const jobType = await job_types.create({
name,
description: description || '',
commonSkills: Array.isArray(commonSkills) ? JSON.stringify(commonSkills) : (commonSkills || '[]'),
excludeKeywords: Array.isArray(excludeKeywords) ? JSON.stringify(excludeKeywords) : (excludeKeywords || '[]'),
titleIncludeKeywords: Array.isArray(titleIncludeKeywords)
? JSON.stringify(titleIncludeKeywords)
: (titleIncludeKeywords || '[]'),
pla_account_id,
is_enabled: is_enabled !== undefined ? is_enabled : 1,
sort_order: sort_order || 0
});
return ctx.success(jobType);
const [enriched] = await attachPlaAccountToJobTypeRows([jobType], models);
return ctx.success(enriched);
},
/**
@@ -189,6 +271,9 @@ module.exports = {
* excludeKeywords:
* type: array
* description: 排除关键词JSON数组
* titleIncludeKeywords:
* type: array
* description: 职位标题须同时包含的子串JSON数组
* is_enabled:
* type: integer
* description: 是否启用1=启用0=禁用)
@@ -201,9 +286,9 @@ module.exports = {
*/
'POST /job_type/update': async (ctx) => {
const models = Framework.getModels();
const { job_types } = models;
const { job_types, pla_account } = models;
const body = ctx.getBody();
const { id, name, description, commonSkills, excludeKeywords, is_enabled, sort_order } = body;
const { id, name, description, commonSkills, excludeKeywords, titleIncludeKeywords, is_enabled, sort_order } = body;
if (!id) {
return ctx.fail('职位类型ID不能为空');
@@ -231,16 +316,32 @@ module.exports = {
if (excludeKeywords !== undefined) {
updateData.excludeKeywords = Array.isArray(excludeKeywords) ? JSON.stringify(excludeKeywords) : excludeKeywords;
}
if (titleIncludeKeywords !== undefined) {
updateData.titleIncludeKeywords = Array.isArray(titleIncludeKeywords)
? JSON.stringify(titleIncludeKeywords)
: titleIncludeKeywords;
}
if (body.pla_account_id !== undefined) {
const paResolved = await normalizePlaAccountId(body.pla_account_id, pla_account);
if (!paResolved.ok) {
return ctx.fail(paResolved.message || '关联账户校验失败');
}
if (!paResolved.skip) {
updateData.pla_account_id = paResolved.value === undefined ? null : paResolved.value;
}
}
if (is_enabled !== undefined) updateData.is_enabled = is_enabled;
if (sort_order !== undefined) updateData.sort_order = sort_order;
await job_types.update(updateData, { where: { id } });
// 清除缓存
const jobFilterService = require('../middleware/job/job_filter_service.js');
const jobFilterService = require('../middleware/job/services/jobFilterService.js');
jobFilterService.clearCache(id);
return ctx.success({ message: '职位类型更新成功' });
const updated = await job_types.findByPk(id);
const [enriched] = await attachPlaAccountToJobTypeRows([updated], models);
return ctx.success(enriched);
},
/**
@@ -289,7 +390,7 @@ module.exports = {
await job_types.destroy({ where: { id } });
// 清除缓存
const jobFilterService = require('../middleware/job/job_filter_service.js');
const jobFilterService = require('../middleware/job/services/jobFilterService.js');
jobFilterService.clearCache(id);
return ctx.success({ message: '职位类型删除成功' });