Commit 263ea354 by chenjinjing

no message

parent 5e1bae8d
......@@ -4,6 +4,8 @@
/test
/public
/logs
/files
/img
/video
*.logs
*.zip
......@@ -2,6 +2,7 @@
<port>13275</port>
<sign></sign>
<dbServer>http://127.0.0.1:13275</dbServer>
<imgUrl>http://127.0.0.1:13275</imgUrl>
<mysqldb>
<!-- 本地mysql配置 -->
<mysqlHost>192.168.0.71</mysqlHost>
......
......@@ -195,6 +195,7 @@ async function getHuoLanDe(infoid) {
let findCareer = await selectDataListByParam(TABLENAME.职业对照表, selectParam, []);
let testReport = {
infoid: findUserData.data.infoid,
name:findUserData.data.name,
card:findUserData.data.card,
phone:findUserData.data.phone,
......
import { TABLENAME } from "../config/dbEnum";
import { selectDataCountByParam, selectDataListByParam, selectDataListToPageByParam, selectOneDataByParam } from "../data/findData";
import * as splitResultConfig from '../config/splitResultConfig';
import { extractData } from "../util/piecemeal";
import { systemConfig } from "../config/serverConfig";
import { BizError } from "../util/bizError";
import { ERRORENUM } from "../config/errorEnum";
import { AIJobAddConfig, AIJobSeekerAddConfig, JobAddConfig, JobSeekersAddConfig, JobSeekersUpdateConfig, JobUpdateConfig, POLICT, PolicyAddConfig, PolicyUpdateConfig, POSITION, REPORT, REPORTBASIC, TRAINING, TrainingCourseAddConfig, TrainingCourseUpdateConfig } from "../config/eccParam/admin";
import { eccFormParam } from "../util/verificationParam";
import { addData } from "../data/addData";
import moment from "moment";
import { updateManyData } from "../data/updateData";
import * as configEnum from "../config/enum";
import { changeEnumNameByCode, changeEnumValue } from "../tools/eccEnum";
import { getVerticalPolicy } from "../tools/systemTools";
// ===============================政策文件相关方法======================================
/**
* 获取政策文件列表(分页)
* @param fileName 政策文件名称
* @param policyStartTime 政策开始时间
* @param policyEndTime 政策结束时间
* @param page 页码
*/
export async function getPolicyList(fileName:string, policyStartTime:number, policyEndTime:number, page:number) {
let selectParam:any = {is_deleted: false};
if (fileName) {
selectParam.file_name = { "%like%": fileName };
}
// 处理时间查询逻辑 - 查找有重叠的政策
let startTime = moment(policyStartTime).format("YYYY-MM-DD");
let endTime = moment(policyEndTime).format("YYYY-MM-DD");
if (policyStartTime && policyEndTime) {
// 查询逻辑:查找所有与传入时间段有重叠的政策
// 条件:政策的开始时间 <= 传入的结束时间 AND 政策的结束时间 >= 传入的开始时间
selectParam.policy_start_time = { "%lte%": endTime };
selectParam.policy_end_time = { "%gte%": startTime };
}
// 如果只传入了开始时间,查询在传入时间之后开始的政策
else if (policyStartTime) {
selectParam.policy_start_time = { "%gte%": startTime };
}
// 如果只传入了结束时间,查询在传入时间之前结束的政策
else if (policyEndTime) {
selectParam.policy_end_time = { "%lte%": endTime };
}
let policyDBList = await selectDataListToPageByParam(TABLENAME.政策文件表, selectParam, [], page, 10);
let dataCount = await selectDataCountByParam(TABLENAME.政策文件表, selectParam);
/**组合返回结果 */
let dataList = [];
policyDBList.data.forEach(info => {
/**截取返回数据 */
let changeData:any = extractData(splitResultConfig.policyListConfig, info, true);
/**政策文件地址拼接 */
let policyFileUrl = `${systemConfig.imgUrl}${changeData.policy_file_url}`;
changeData.policy_file_url = policyFileUrl;
let policy_imgname = JSON.parse(changeData.policy_imgname);
let policyImgList = getVerticalPolicy(changeData.policy_file_img, policy_imgname)
changeData.policy_imgname = policyImgList;
dataList.push(changeData);
})
return {dataList, dataCount:dataCount.data};
}
/**
* 政策文件回显
* @param id
*/
export async function getPrlicyInfo(id:number) {
let policyDBInfo = await selectOneDataByParam(TABLENAME.政策文件表, {id}, []);
if (!policyDBInfo || !policyDBInfo.data) throw new BizError(ERRORENUM.数据不存在);
let policyInfo = policyDBInfo.data;
/**政策文件地址拼接 */
let policy_imgname = JSON.parse(policyInfo.policy_imgname);
let policyImgList = getVerticalPolicy(policyInfo.policy_file_img, policy_imgname)
let dataInfo = {
file_name: policyInfo.file_name,
subsidy_scope: policyInfo.subsidy_scope,
full_text: policyInfo.full_text,
policy_file_url: policyInfo.policy_file_url,
policy_file_img: policyInfo.policy_file_img,
policy_imgname: policyImgList,
policy_start_time: moment(policyInfo.policy_start_time).format("YYYY-MM-DD"),
policy_end_time: moment(policyInfo.policy_end_time).format("YYYY-MM-DD"),
}
return {dataInfo};
}
/**
* 新增政策文件
* @param param
*/
export async function addPolicy(param) {
/**校验表单参数 */
eccFormParam("新增政策文件", PolicyAddConfig, param);
// 准备政策文件数据
let policy_imgname = JSON.stringify(param.policy_imgname);
let policyAddParam = {
file_name: param.file_name,
subsidy_scope: param.subsidy_scope,
full_text: param.full_text,
policy_file_url: param.policy_file_url,
policy_file_img: param.policy_file_img,
policy_imgname,
policy_start_time: moment(param.policy_start_time).format("YYYY-MM-DD HH:mm:ss"),
policy_end_time: moment(param.policy_end_time).format("YYYY-MM-DD HH:mm:ss"),
createTime: moment(new Date()).format("YYYY-MM-DD HH:mm:ss"),
updated_at: moment(new Date()).format("YYYY-MM-DD HH:mm:ss"),
}
// 保存政策文件数据
await addData(TABLENAME.政策文件表, policyAddParam);
return { isSuccess: true };
}
/**
* 修改政策文件
* @param id
* @param param
*/
export async function policyUpdate(id:number, param) {
/**校验表单参数 */
eccFormParam("修改政策文件", PolicyUpdateConfig, param);
let policyDBInfo = await selectOneDataByParam(TABLENAME.政策文件表, {id}, []);
if (!policyDBInfo || !policyDBInfo.data) throw new BizError(ERRORENUM.数据不存在);
// 准备政策文件数据
let policy_imgname = JSON.stringify(param.policy_imgname);
let updateInfo = {
file_name: param.file_name,
subsidy_scope: param.subsidy_scope,
full_text: param.full_text,
policy_file_url: param.policy_file_url,
policy_file_img: param.policy_file_img,
policy_imgname,
policy_start_time: param.policy_start_time,
policy_end_time: param.policy_end_time,
updated_at: moment(new Date()).format("YYYY-MM-DD HH:mm:ss"),
}
await updateManyData(TABLENAME.政策文件表, {id}, updateInfo );
return {isSuccess:true};
}
/**
* 删除政策文件(软删除)
* @param id
*/
export async function deletePolicy(id:number) {
let policyDBInfo = await selectOneDataByParam(TABLENAME.政策文件表, {id}, []);
if (!policyDBInfo || !policyDBInfo.data) throw new BizError(ERRORENUM.数据不存在);
let updateInfo = {
is_deleted:true,
updated_at:moment(new Date()).format("YYYY-MM-DD HH:mm:ss")
};
await updateManyData(TABLENAME.政策文件表, {id}, updateInfo);
return {isSuccess:true};
}
// ===============================岗位信息相关方法======================================
/**
* 岗位信息列表
* @param company_name 公司名称
* @param job_title 岗位名称
* @param priority_type 岗位类型
* @param job_status 岗位状态
* @param page 页码
*/
export async function getJobList(company_name:string, job_title:string, priority_type:number, job_status:number, page:number) {
let selectParam:any = {is_deleted: false};
if (job_title) {
selectParam.job_title = { "%like%": job_title };
}
if (company_name) {
selectParam.company_name = { "%like%": company_name };
}
if (priority_type !== undefined) {
selectParam.priority_type = priority_type;
}
if (job_status !== undefined) {
selectParam.job_status = job_status;
}
let JobDBList = await selectDataListToPageByParam(TABLENAME.岗位信息表, selectParam, [], page, 10);
let dataCount = await selectDataCountByParam(TABLENAME.岗位信息表, selectParam);
/**组合返回结果 */
let dataList = [];
JobDBList.data.forEach(info => {
/**截取返回数据 */
let changeData:any = extractData(splitResultConfig.jobListConfig, info, true);
/**将枚举值转为字符 */
changeData.priority_type = changeEnumNameByCode(configEnum.PRIORITYTYPE, info.priority_type);
changeData.job_status = changeEnumNameByCode(configEnum.JOBSTATUS, info.job_status);
changeData.education_requirement = changeEnumNameByCode(configEnum.EDUCATION, info.education_requirement);
dataList.push(changeData);
})
return {dataList, dataCount:dataCount.data};
}
/**
* 岗位信息回显
* @param id
*/
export async function getJobInfo(id:number) {
let jobDBInfo = await selectOneDataByParam(TABLENAME.岗位信息表, {id}, []);
if (!jobDBInfo || !jobDBInfo.data) throw new BizError(ERRORENUM.数据不存在);
let jobInfo = jobDBInfo.data;
let dataInfo = {
company_name: jobInfo.company_name,
job_title: jobInfo.job_title,
recruitment_count: jobInfo.recruitment_count,
publish_date: moment(jobInfo.publish_date).format("YYYY-MM-DD"),
salary_range: jobInfo.salary_range,
working_hours: jobInfo.working_hours,
work_location: jobInfo.work_location,
job_responsibilities: jobInfo.job_responsibilities,
priority_type: jobInfo.priority_type,
job_status: jobInfo.job_status,
education_requirement: jobInfo.education_requirement,
experience_requirement: jobInfo.experience_requirement,
contact_info: jobInfo.contact_info,
}
return {dataInfo};
}
/**
* 新增岗位信息
* @param param
*/
export async function addJob(param) {
/**校验表单参数 */
eccFormParam("新增岗位信息", JobAddConfig, param);
// 准备岗位信息数据
let jobAddParam = {
company_name: param.company_name,
job_title: param.job_title,
recruitment_count: param.recruitment_count,
publish_date: moment().format("YYYY-MM-DD HH:mm:ss"),
salary_range: param.salary_range,
working_hours: param.working_hours,
work_location: param.work_location,
job_responsibilities: param.job_responsibilities,
priority_type: param.priority_type,
job_status: param.job_status,
education_requirement: param.education_requirement,
experience_requirement: param.experience_requirement,
contact_info: param.contact_info,
createTime: moment(new Date()).format("YYYY-MM-DD HH:mm:ss"),
updated_at: moment(new Date()).format("YYYY-MM-DD HH:mm:ss"),
}
// 保存岗位信息数据
await addData(TABLENAME.岗位信息表, jobAddParam);
return { isSuccess: true };
}
/**
* 修改岗位信息
* @param id
* @param param
*/
export async function jobUpdate(id:number, param) {
/**校验表单参数 */
eccFormParam("修改岗位信息", JobUpdateConfig, param);
let jobDBInfo = await selectOneDataByParam(TABLENAME.岗位信息表, {id}, []);
if (!jobDBInfo || !jobDBInfo.data) throw new BizError(ERRORENUM.数据不存在);
let updateInfo = {
company_name: param.company_name,
job_title: param.job_title,
recruitment_count: param.recruitment_count,
publish_date: param.publish_date,
salary_range: param.salary_range,
working_hours: param.working_hours,
work_location: param.work_location,
job_responsibilities: param.job_responsibilities,
priority_type: param.priority_type,
job_status: param.job_status,
education_requirement: param.education_requirement,
experience_requirement: param.experience_requirement,
contact_info: param.contact_info,
updated_at: moment(new Date()).format("YYYY-MM-DD HH:mm:ss"),
}
await updateManyData(TABLENAME.岗位信息表, {id}, updateInfo );
return {isSuccess:true};
}
/**
* 删除岗位信息(软删除)
* @param id
*/
export async function deleteJob(id:number) {
let jobDBInfo = await selectOneDataByParam(TABLENAME.岗位信息表, {id}, []);
if (!jobDBInfo || !jobDBInfo.data) throw new BizError(ERRORENUM.数据不存在);
let updateInfo = {
is_deleted:true,
updated_at:moment(new Date()).format("YYYY-MM-DD HH:mm:ss")
};
await updateManyData(TABLENAME.岗位信息表, {id}, updateInfo);
return {isSuccess:true};
}
// ===============================培训课程相关方法======================================
/**
* 培训课程列表
* @param course_name 课程名称
* @param page 页码
*/
export async function getTrainingCourseList(course_name:string, page:number) {
let selectParam:any = {is_deleted: false};
if (course_name) {
selectParam.course_name = { "%like%": course_name };
}
let trainingCourseDBList = await selectDataListToPageByParam(TABLENAME.培训课程表, selectParam, [], page, 10);
let dataCount = await selectDataCountByParam(TABLENAME.培训课程表, selectParam);
/**组合返回结果 */
let dataList = [];
trainingCourseDBList.data.forEach(info => {
/**截取返回数据 */
let changeData:any = extractData(splitResultConfig.trainingCourseListConfig, info, true);
/**将枚举值转为字符 */
changeData.course_type = changeEnumValue(configEnum.COURSETYPE, info.course_type);
changeData.course_level = changeEnumValue(configEnum.COURSELEVEL, info.course_level);
changeData.certificate_type = changeEnumValue(configEnum.CERTIFICATETYPE, info.certificate_type);
dataList.push(changeData);
})
return {dataList, dataCount:dataCount.data};
}
/**
* 培训课程回显
* @param id
*/
export async function getTrainingCourseInfo(id:number) {
let trainingCourseDBInfo = await selectOneDataByParam(TABLENAME.培训课程表, {id}, []);
if (!trainingCourseDBInfo || !trainingCourseDBInfo.data) throw new BizError(ERRORENUM.数据不存在);
let trainingCourseInfo = trainingCourseDBInfo.data;
let dataInfo = {
course_name: trainingCourseInfo.course_name,
course_type: trainingCourseInfo.course_type,
course_level: trainingCourseInfo.course_level,
course_content: trainingCourseInfo.course_content,
offline_training_fee: trainingCourseInfo.offline_training_fee,
offline_material_fee: trainingCourseInfo.offline_material_fee,
certificate_name: trainingCourseInfo.certificate_name,
certificate_type: trainingCourseInfo.certificate_type,
apply_conditions: trainingCourseInfo.apply_conditions,
contact_phone: trainingCourseInfo.contact_phone,
}
return {dataInfo};
}
/**
* 新增培训课程
* @param param
*/
export async function addTrainingCourse(param) {
/**校验表单参数 */
eccFormParam("新增培训课程", TrainingCourseAddConfig, param);
// 准备培训课程数据
let trainingCourseAddParam = {
course_name: param.course_name,
course_type: param.course_type,
course_level: param.course_level,
course_content: param.course_content,
offline_training_fee: param.offline_training_fee,
offline_material_fee: param.offline_material_fee,
certificate_name: param.certificate_name,
certificate_type: param.certificate_type,
apply_conditions: param.apply_conditions,
contact_phone: param.contact_phone,
created_at: moment(new Date()).format("YYYY-MM-DD HH:mm:ss"),
updated_at: moment(new Date()).format("YYYY-MM-DD HH:mm:ss"),
}
// 保存培训课程数据
await addData(TABLENAME.培训课程表, trainingCourseAddParam);
return { isSuccess: true };
}
/**
* 修改培训课程
* @param id
* @param param
*/
export async function updateTrainingCourse(id:number, param) {
/**校验表单参数 */
eccFormParam("修改培训课程", TrainingCourseUpdateConfig, param);
let trainingCourseDBInfo = await selectOneDataByParam(TABLENAME.培训课程表, {id}, []);
if (!trainingCourseDBInfo || !trainingCourseDBInfo.data) throw new BizError(ERRORENUM.数据不存在);
let updateInfo = {
course_name: param.course_name,
course_type: param.course_type,
course_level: param.course_level,
course_content: param.course_content,
offline_training_fee: param.offline_training_fee,
offline_material_fee: param.offline_material_fee,
certificate_name: param.certificate_name,
certificate_type: param.certificate_type,
apply_conditions: param.apply_conditions,
contact_phone: param.contact_phone,
updated_at: moment(new Date()).format("YYYY-MM-DD HH:mm:ss"),
}
await updateManyData(TABLENAME.培训课程表, {id}, updateInfo );
return {isSuccess:true};
}
/**
* 删除培训课程(软删除)
* @param id
*/
export async function deleteTrainingCourse(id:number) {
let trainingCourseDBInfo = await selectOneDataByParam(TABLENAME.培训课程表, {id}, []);
if (!trainingCourseDBInfo || !trainingCourseDBInfo.data) throw new BizError(ERRORENUM.数据不存在);
let updateInfo = {
is_deleted:true,
updated_at:moment(new Date()).format("YYYY-MM-DD HH:mm:ss")
};
await updateManyData(TABLENAME.培训课程表, {id}, updateInfo);
return {isSuccess:true};
}
// ===============================求职信息相关方法======================================
/**
* 求职信息列表
* @param name 姓名
* @param phone 手机号码
* @param id_card 身份证号码
* @param page
* @returns
*/
export async function getJobSeekersList(name:string, phone:string, id_card:string, page:number) {
let selectParam:any = {is_deleted: false};
if (name) {
selectParam.name = { "%like%": name };
}
if (phone) {
selectParam.phone = { "%like%": phone };
}
if (id_card) {
selectParam.id_card = { "%like%": id_card };
}
let jobSeekersDBList = await selectDataListToPageByParam(TABLENAME.求职信息表, selectParam, [], page, 10);
let dataCount = await selectDataCountByParam(TABLENAME.求职信息表, selectParam);
/**组合返回结果 */
let dataList = [];
jobSeekersDBList.data.forEach(info => {
/**截取返回数据 */
let changeData:any = extractData(splitResultConfig.jobSeekersListConfig, info, true);
/**将枚举值转为字符 */
changeData.gender = changeEnumValue(configEnum.GENDER, info.gender);
let special_identity = [];
if (info.special_identity) {
let jsonSpecialIdentity = JSON.parse(info.special_identity);
jsonSpecialIdentity.forEach( item => {
special_identity.push(changeEnumValue(configEnum.SPECIALIDENTITY, item));
})
}
changeData.special_identity = special_identity;
changeData.education = changeEnumValue(configEnum.EDUCATION, info.education);
let applied_position = [];
if (info.applied_position) applied_position = JSON.parse(info.applied_position);
changeData.applied_position = applied_position;
dataList.push(changeData);
})
return {dataList, dataCount:dataCount.data};
}
/**
* 求职信息回显
* @param id
*/
export async function getJobSeekersInfo(id:number) {
let jobSeekersDBInfo = await selectOneDataByParam(TABLENAME.求职信息表, {id}, []);
if (!jobSeekersDBInfo || !jobSeekersDBInfo.data) throw new BizError(ERRORENUM.数据不存在);
let jobSeekersInfo:any = jobSeekersDBInfo.data;
/**将枚举值转为字符 */
// let gender = changeEnumValue(configEnum.GENDER, jobSeekersInfo.gender);
// let special_identity = [];
// if (jobSeekersInfo.special_identity) {
// let jsonSpecialIdentity = JSON.parse(jobSeekersInfo.special_identity);
// jsonSpecialIdentity.forEach( item => {
// special_identity.push(changeEnumValue(configEnum.SPECIALIDENTITY, item));
// })
// }
// let education = changeEnumValue(configEnum.EDUCATION, jobSeekersInfo.education);
// let applied_position = [];
// if (jobSeekersInfo.applied_position) applied_position = JSON.parse(jobSeekersInfo.applied_position);
let dataInfo = {
/**基本信息 */
name: jobSeekersInfo.name,
gender: jobSeekersInfo.gender,
age: jobSeekersInfo.age,
phone: jobSeekersInfo.phone,
id_card: jobSeekersInfo.id_card,
address: jobSeekersInfo.address,
education: jobSeekersInfo.education,
household: jobSeekersInfo.household,
/**求职意向 */
applied_position: JSON.parse(jobSeekersInfo.applied_position),
expected_salary_min: jobSeekersInfo.expected_salary_min,
expected_salary_max: jobSeekersInfo.expected_salary_max,
expected_area: jobSeekersInfo.expected_area,
/**特殊身份 */
special_identity:JSON.parse(jobSeekersInfo.special_identity),
}
return {dataInfo};
}
/**
* 新增求职信息
* @param param
*/
export async function addJobSeekers(param) {
/**校验表单参数 */
eccFormParam("新增求职信息", JobSeekersAddConfig, param);
// 准备求职信息数据
let applied_position = JSON.stringify(param.applied_position);
let special_identity = JSON.stringify(param.special_identity);
let time_at = moment(new Date()).format("YYYY-MM-DD HH:mm:ss");
let JobSeekersAddParam = {
/**基本信息 */
name: param.name,
gender: param.gender,
age: param.age,
phone: param.phone,
id_card: param.id_card,
address: param.address,
education: param.education,
household: param.household,
/**求职意向 */
applied_position,
expected_salary_min: param.expected_salary_min,
expected_salary_max: param.expected_salary_max,
expected_area: param.expected_area,
/**特殊身份 */
special_identity,
/** 系统字段 */
created_at: time_at,
updated_at: time_at,
}
// 保存求职信息数据
await addData(TABLENAME.求职信息表, JobSeekersAddParam);
/**获取求职信息 */
let selectParam = {name:param.name, id_card:param.id_card, created_at:time_at};
let jobSeekersDBInfo = await selectOneDataByParam(TABLENAME.求职信息表, selectParam, []);
if (!jobSeekersDBInfo || !jobSeekersDBInfo.data) throw new BizError(ERRORENUM.数据不存在);
let jobSeekersInfo:any = jobSeekersDBInfo.data;
let dataInfo = {
id:jobSeekersInfo.id,
name: jobSeekersInfo.name,
gender: jobSeekersInfo.gender,
age: jobSeekersInfo.age,
phone: jobSeekersInfo.phone,
id_card: jobSeekersInfo.id_card,
}
return { dataInfo };
}
/**
* 修改求职信息
* @param id
* @param param
*/
export async function updateJobSeekers(id:number, param) {
/**校验表单参数 */
eccFormParam("修改求职信息", JobSeekersUpdateConfig, param);
let jobSeekersDBInfo = await selectOneDataByParam(TABLENAME.求职信息表, {id}, []);
if (!jobSeekersDBInfo || !jobSeekersDBInfo.data) throw new BizError(ERRORENUM.数据不存在);
let applied_position;
if (param.applied_position) applied_position = JSON.stringify(param.applied_position);
let special_identity;
if (param.special_identity) special_identity = JSON.stringify(param.special_identity);
let updateInfo = {
/**基本信息 */
name: param.name,
gender: param.gender,
age: param.age,
phone: param.phone,
id_card: param.id_card,
address: param.address,
education: param.education,
household: param.household,
/**求职意向 */
applied_position,
expected_salary_min: param.expected_salary_min,
expected_salary_max: param.expected_salary_max,
expected_area: param.expected_area,
/**特殊身份 */
special_identity,
/** 系统字段 */
updated_at: moment(new Date()).format("YYYY-MM-DD HH:mm:ss"),
}
await updateManyData(TABLENAME.求职信息表, {id}, updateInfo );
return {isSuccess:true};
}
/**
* 删除求职信息(软删除)
* @param id
*/
export async function deleteJobSeekers(id:number) {
let jobSeekersDBInfo = await selectOneDataByParam(TABLENAME.求职信息表, {id}, []);
if (!jobSeekersDBInfo || !jobSeekersDBInfo.data) throw new BizError(ERRORENUM.数据不存在);
let updateInfo = {
is_deleted:true,
updated_at:moment(new Date()).format("YYYY-MM-DD HH:mm:ss")
};
await updateManyData(TABLENAME.求职信息表, {id}, updateInfo);
return {isSuccess:true};
}
// ===============================AI岗位推荐相关方法======================================
/**
* 新增AI岗位推荐信息
* @param source_type 推荐来源类型 1=手机求职 2=电脑测评
* @param param AI岗位推荐信息
*/
export async function addAIJob(source_type, param) {
/**校验表单参数 */
if (source_type == 1) {
eccFormParam("新增AI岗位推荐信息-手机", AIJobSeekerAddConfig, param);
} else if (source_type == 2) {
eccFormParam("新增AI岗位推荐信息-电脑", AIJobAddConfig, param);
eccFormParam("新增AI岗位推荐信息-测评报告", REPORT, param.report);
eccFormParam("新增AI岗位推荐信息-测评报告-基础信息", REPORTBASIC, param.report.basicInfo);
}
param.position.forEach( info => {
eccFormParam("新增AI岗位推荐信息-岗位推荐", POSITION, info);
})
param.policy.forEach( info => {
eccFormParam("新增AI岗位推荐信息-政策匹配", POLICT, info);
})
param.training.forEach( info => {
eccFormParam("新增AI岗位推荐信息-培训推荐", TRAINING, info);
})
/**准备AI岗位推荐信息数据 */
let 测评报告 = param.report;
let 基础信息 = param.report.basicInfo;
let 岗位推荐 = param.position;
let 政策匹配 = param.policy;
let 培训推荐 = param.training;
let job_id = [];
岗位推荐.forEach( info => {
job_id.push(info.job_id);
})
let policy_id = [];
政策匹配.forEach( info => {
policy_id.push(info.policy_id);
})
let training_id = [];
培训推荐.forEach( info => {
training_id.push(info.training_id);
})
let aiJob = {};
if (source_type == 1) {
//手机用
let aiJobSeeker = {
seeker_id: 基础信息.id, //求职者ID
job_id: JSON.stringify(job_id), //推荐的岗位ID
policy_id: JSON.stringify(policy_id), //推荐的政策ID
training_id: JSON.stringify(training_id), //推荐的培训课程ID
source_type, //推荐来源类型 1=求职推荐
recommended_jobs: JSON.stringify(岗位推荐), //推荐的岗位列表JSON
recommended_policies: JSON.stringify(政策匹配), //推荐的政策列表JSON
recommended_trainings: JSON.stringify(培训推荐), //推荐的培训列表JSON
created_at: moment(new Date()).format("YYYY-MM-DD HH:mm:ss"), //创建时间
updated_at: moment(new Date()).format("YYYY-MM-DD HH:mm:ss"), //更新时间
is_deleted: false, //软删除标记
};
aiJob = aiJobSeeker;
} else if (source_type == 2) {
//电脑用
let aiJobTestinfo = {
testinfo_id: 基础信息.id, //测试信息ID
job_id: JSON.stringify(job_id), //推荐的岗位ID
policy_id: JSON.stringify(policy_id), //推荐的政策ID
training_id: JSON.stringify(training_id), //推荐的培训课程ID
source_type, //推荐来源类型 2=测评推荐
holland_code: 基础信息.holland, //霍兰德职业代码
report_json: JSON.stringify(测评报告), //完整的测评报告JSON
recommended_jobs: JSON.stringify(岗位推荐), //推荐的岗位列表JSON
recommended_policies: JSON.stringify(政策匹配), //推荐的政策列表JSON
recommended_trainings: JSON.stringify(培训推荐), //推荐的培训列表JSON
created_at: moment(new Date()).format("YYYY-MM-DD HH:mm:ss"), //创建时间
updated_at: moment(new Date()).format("YYYY-MM-DD HH:mm:ss"), //更新时间
is_deleted: false, //软删除标记
}
aiJob = aiJobTestinfo;
}
// 保存AI岗位推荐信息数据
await addData(TABLENAME.AI推荐记录表, aiJob);
return { isSuccess: true };
}
/**
* 获取全部政策文件
* @param file_name 政策文件名称
* @returns
*/
export async function getPolicyListAll(file_name:string) {
let selectParam:any = {is_deleted: false};
if (file_name) {
selectParam.file_name = { "%like%": file_name };
}
let policyDBList = await selectDataListByParam(TABLENAME.政策文件表, selectParam, []);
/**组合返回结果 */
let dataList = [];
policyDBList.data.forEach(info => {
/**截取返回数据 */
let changeData:any = extractData(splitResultConfig.policyListConfig, info, true);
/**政策文件地址拼接 */
let policyFileUrl = `${systemConfig.imgUrl}${changeData.policy_file_url}`;
changeData.policy_file_url = policyFileUrl;
let policy_imgname = JSON.parse(changeData.policy_imgname);
let policyImgList = getVerticalPolicy(changeData.policy_file_img, policy_imgname)
changeData.policy_imgname = policyImgList;
dataList.push(changeData);
})
return dataList;
}
/**
* 获取全部岗位信息
* @param company_name 公司名称
* @returns
*/
export async function getJobListAll(company_name) {
let selectParam:any = {is_deleted: false};
if (company_name) {
selectParam.company_name = { "%like%": company_name };
}
let JobDBList = await selectDataListByParam(TABLENAME.岗位信息表, selectParam, []);
/**组合返回结果 */
let dataList = [];
JobDBList.data.forEach(info => {
/**截取返回数据 */
let changeData:any = extractData(splitResultConfig.jobListConfig, info, true);
/**将枚举值转为字符 */
changeData.priority_type = changeEnumNameByCode(configEnum.PRIORITYTYPE, info.priority_type);
changeData.job_status = changeEnumNameByCode(configEnum.JOBSTATUS, info.job_status);
changeData.education_requirement = changeEnumNameByCode(configEnum.EDUCATION, info.education_requirement);
dataList.push(changeData);
})
return dataList;
}
/**
* 获取全部培训课程
*/
export async function getTrainingCourseListAll() {
let selectParam:any = {is_deleted: false};
let trainingCourseDBList = await selectDataListByParam(TABLENAME.培训课程表, selectParam, []);
/**组合返回结果 */
let dataList = [];
trainingCourseDBList.data.forEach(info => {
/**截取返回数据 */
let changeData:any = extractData(splitResultConfig.trainingCourseListConfig, info, true);
/**将枚举值转为字符 */
changeData.course_type = changeEnumValue(configEnum.COURSETYPE, info.course_type);
changeData.course_level = changeEnumValue(configEnum.COURSELEVEL, info.course_level);
changeData.certificate_type = changeEnumValue(configEnum.CERTIFICATETYPE, info.certificate_type);
dataList.push(changeData);
})
return dataList;
}
/**
* 手机-我要求职点击进入AI
*/
export async function jobApplication() {
let data = {
"position": [
{
"job_id": 4,
"company_name": "上海申浦物业管理有限公司",
"job_title": "项目经理",
"salary_range": "6000-10000元/月",
"working_hours": "2025/5/29",
"work_location": "上海市浦东新区按工作需求具体安排",
"job_responsibilities": "主持项目点日常工作,制定年度工作计划和年度培训计划;定期组织员工业务知识与技能操作培训,不断完善和提升物业服务品质;定期召开各项管理会议,落实相关会议内容,并做好会后反馈与跟踪落实;开展招聘工作,确保项目点岗位员工及时到岗,正常开展各岗位日常工作;与业主方保持良好的工作沟通关系,有效落实各项工作需求;做好上通下达的管理角色,将公司各项制度要求及时传达至员工;完成上级领导交办的其他工作。",
"career_match": "73%",
"matching_point": [
"职业匹配度高",
"薪资匹配",
"地点匹配"
],
"recommend_reason": "您的AES职业代码与运营专员岗位高度契合,能发挥专业所长。6000-10000元的月薪符合您的期望,工作地点在上海,通勤便利。"
}
],
"policy": [
{
"policy_id": 1,
"file_name": "浦东新区困难就业稳岗补贴",
"policy_level": "区级",
"subsidy_standard": "1200元/人/月",
"applicable_state": "您符合此政策的所有条件,建议申请",
"satisfied": [
"年龄符合(35岁以上)",
"浦东新区户籍",
"失业6个月以上",
"一线非管理类岗位(待确认)"
],
"to_be_fulfilled": [
"无(全部满足)"
]
}
],
"training": [
{
"training_id": 1,
"course_name": "西式面点师",
"course_type": "第三方",
"course_level": "中级",
"course_content": "蝴蝶酥 、鲜奶泡芙、酥皮泡芙、天鹅泡芙、硬质吐司、法棍、瑞士卷、咖啡卷、裸麦面包、杂粮面包、裱花生日蛋糕等近四十款市场热门作品制作",
"offline_training_fee": "3180.00",
"offline_material_fee": "800.00",
"certificate_name": "技能等级证书",
"certificate_type": "四级证书",
"apply_conditions": "(1)累计从事本职业或相关职业工作满5年。(2)取得本职业或相关职业五级/初级工职业资格(职业技能等级)证书后,累计从事本职业或相关职业工作满3年。(3)取得本专业或相关专业的技工院校或中等及以上职业院校、专科及以上普通高等学校毕业证书(含在读应届毕业生)。",
"contact_phone": "021-50650867",
"career_match": "73%",
}
]
};
return data;
}
/**
* 电脑-就业测评点击进入AI
*/
export async function employmentEvaluation() {
let data = {
"report": {
"basicInfo": {
"name": "王明",
"age": "35",
"holland": "AES"
},
"personalityTraits": {
"dominate": {
"title": "A型",
"type": "艺术型",
"score": "30",
"desc": "您的测评结果显示,艺术型(A型)是您最突出的特质(得分30分)。这意味着您天生具备强烈的创造力、审美意识和自我表达欲望。您可能喜欢通过艺术、设计、文字或表演等方式展现自己的想法,注重独特性和美感,不愿意被刻板的规则束缚。在工作中,您倾向于寻找能够发挥想象力和创新思维的机会,同时也渴望自己的工作成果能传递情感或价值观。"
},
"secondary": [
{
"title": "E型",
"type": "事业型",
"score": "28",
"desc": "您具备较强的领导力和影响力,善于说服他人、推动项目,并渴望在职业中获得成就感和认可。这一特质能帮助您将创意转化为实际成果,并在团队或组织中担任协调或决策角色。"
},
{
"title": "S型",
"type": "社会型",
"score": "25",
"desc": "您乐于与人互动,关心他人的需求,并希望通过工作带来积极的社会影响。这一特质使您在团队合作、客户沟通或公益相关领域中能自然发挥同理心和协作能力。"
}
],
"combination": "AES组合代表了一种“创意推动者”的性格类型:您既能够提出新颖的创意(A型),也有能力组织资源、带领团队实现目标(E型),同时注重与他人的连接与社会价值(S型)。这种组合非常适合需要兼顾艺术表达、人际互动与项目管理的工作场景。"
},
"specialty": [
{
"title": "创新与审美能力(A型主导)",
"desc": "您擅长从独特视角发现问题或设计解决方案,适合需要原创性思维的工作,如策划、设计或内容创作。"
},
{
"title": "领导与影响力(E型辅助)",
"desc": "您能主动推动项目进展,激励团队成员,并在商业或组织环境中有效传达理念。"
},
{
"title": "人际沟通与共情力(S型辅助)",
"desc": "您善于理解他人需求,适合需要频繁互动、服务或教育他人的岗位,能快速建立信任关系。"
},
{
"title": "多元协调能力(AES综合)",
"desc": "您能灵活平衡创意、管理和人际需求,在跨领域工作中表现突出。"
}
],
"suitableWork": {
"suitable": [
{
"title": "开放包容的平台",
"desc": "例如文化创意公司、教育机构、社会企业或创新型团队,允许自由表达观点并鼓励实验性尝试。"
},
{
"title": "与人互动的场景",
"desc": "需要频繁沟通、培训、策划或协作的环境,如活动策划、咨询或公益项目。"
},
{
"title": "成果可见的领域",
"desc": "能通过项目成果获得成就感,例如品牌建设、产品设计、文化传播等。"
}
],
"avoid": [
{
"title": "高度重复或机械化的岗位",
"desc": "如数据录入、流水线作业等,会压抑您的创造欲。"
},
{
"title": "严格层级化的组织",
"desc": "过于僵化的规章制度可能限制您的自主性和灵活性。"
},
{
"title": "孤立的工作模式",
"desc": "长期独立作业且缺乏人际交流的岗位会削弱您的社会型需求。"
}
]
},
"development": {
"suggestion": [
{
"title": "聚焦“创意+管理”复合角色",
"desc": "可尝试向创意总监、品牌经理、项目策划等职位发展,既能发挥艺术天赋,也能运用领导力统筹资源。"
},
{
"title": "拓展社会影响力相关领域",
"desc": "结合S型特质,参与教育、文化传播或社会责任项目,使工作更具意义感。"
},
{
"title": "建立个人品牌或作品集",
"desc": "通过展示您的创意成果(如设计作品、策划案例)提升行业认可度,为职业晋升铺垫。"
}
],
"improvable": [
{
"title": "项目管理工具",
"desc": "(如Trello、Notion)提升效率"
},
{
"title": "公众表达或谈判技巧",
"desc": "强化影响力"
},
{
"title": "数字化技能",
"desc": "(如基础设计软件、新媒体运营)以适应趋势"
}
]
},
"recommendJob": [
{
"title": "创意总监/艺术指导",
"desc": "统筹视觉或内容创作,契合A型创造力与E型管理需求。"
},
{
"title": "品牌策划经理",
"desc": "结合市场策略与创意表达,需频繁对接团队与客户(A+E+S)。"
},
{
"title": "社会企业项目经理",
"desc": "通过创新方案解决社会问题,满足S型价值感与A型实践欲。"
},
{
"title": "教育培训顾问",
"desc": "设计课程并与人互动,发挥S型辅导能力与A型内容创作力。"
},
{
"title": "文化活动策划",
"desc": "组织展览、演出等活动,兼顾创意落地与人际协调。"
},
{
"title": "用户体验(UX)设计师",
"desc": "以用户为中心进行创新设计,需同理心(S)与美学能力(A)。"
},
{
"title": "媒体内容主编",
"desc": "主导内容策划与团队协作,适合A型表达与E型领导特质。"
}
],
"encourage": "您的职业性格组合充满潜力,既敏感于美与创新,也踏实于行动与人际。35岁正是经验与创造力并存的黄金阶段,请自信地选择能激发您热情的方向,逐步打造独一无二的职业路径!如有具体职业困惑,欢迎进一步交流",
"generationTime": "2026年1月20日"
},
"position": [
{
"job_id": 4,
"company_name": "上海申浦物业管理有限公司",
"job_title": "项目经理",
"salary_range": "6000-10000元/月",
"working_hours": "2025/5/29",
"work_location": "上海市浦东新区按工作需求具体安排",
"job_responsibilities": "主持项目点日常工作,制定年度工作计划和年度培训计划;定期组织员工业务知识与技能操作培训,不断完善和提升物业服务品质;定期召开各项管理会议,落实相关会议内容,并做好会后反馈与跟踪落实;开展招聘工作,确保项目点岗位员工及时到岗,正常开展各岗位日常工作;与业主方保持良好的工作沟通关系,有效落实各项工作需求;做好上通下达的管理角色,将公司各项制度要求及时传达至员工;完成上级领导交办的其他工作。",
"career_match": "73%",
"matching_point": [
"职业匹配度高",
"薪资匹配",
"地点匹配"
],
"recommend_reason": "您的AES职业代码与运营专员岗位高度契合,能发挥专业所长。6000-10000元的月薪符合您的期望,工作地点在上海,通勤便利。"
}
],
"policy": [
{
"policy_id": 1,
"file_name": "浦东新区困难就业稳岗补贴",
"policy_level": "区级",
"subsidy_standard": "1200元/人/月",
"applicable_state": "您符合此政策的所有条件,建议申请",
"satisfied": [
"年龄符合(35岁以上)",
"浦东新区户籍",
"失业6个月以上",
"一线非管理类岗位(待确认)"
],
"to_be_fulfilled": [
"无(全部满足)"
]
}
],
"training": [
{
"training_id": 1,
"course_name": "西式面点师",
"course_type": "第三方",
"course_level": "中级",
"course_content": "蝴蝶酥 、鲜奶泡芙、酥皮泡芙、天鹅泡芙、硬质吐司、法棍、瑞士卷、咖啡卷、裸麦面包、杂粮面包、裱花生日蛋糕等近四十款市场热门作品制作",
"offline_training_fee": "3180.00",
"offline_material_fee": "800.00",
"certificate_name": "技能等级证书",
"certificate_type": "四级证书",
"apply_conditions": "(1)累计从事本职业或相关职业工作满5年。(2)取得本职业或相关职业五级/初级工职业资格(职业技能等级)证书后,累计从事本职业或相关职业工作满3年。(3)取得本专业或相关专业的技工院校或中等及以上职业院校、专科及以上普通高等学校毕业证书(含在读应届毕业生)。",
"contact_phone": "021-50650867",
"career_match": "73%",
}
]
};
return data;
}
/**
* 导入相关数据
*/
import moment from "moment";
import { TABLENAME } from "../config/dbEnum";
import { selectDataCountByParam } from "../data/findData";
import { CERTIFICATETYPE, COURSELEVEL, EDUCATION, JOBSTATUS, PRIORITYTYPE } from "../config/enum";
import { addData } from "../data/addData";
let xlsx = require('node-xlsx');
let path = require('path');
/**
* 获取单个excel文件数据
* @param filePath
* @returns
*/
function getExcel(filePath) {
let workSheetsFromFile = xlsx.parse(filePath);
let sheetMap = {};
let sheetList = [];
for (let i = 0; i < workSheetsFromFile.length; i++) {
let sheetInfo = workSheetsFromFile[i];
sheetMap[sheetInfo.name] = sheetInfo.data;
sheetList.push(sheetInfo);
}
return {sheetMap, sheetList}
}
/**
* 导入岗位信息数据
* @returns
*/
export async function addJobData() {
try {
//检查是否已有数据
let dataCount = await selectDataCountByParam(TABLENAME.岗位信息表, {});
if (dataCount.data > 10) {
console.log("*** 岗位数据 无需初始化");
return;
}
// 读取Excel文件
let {sheetMap} = getExcel(path.join(__dirname.substring(0,__dirname.indexOf("out")), "res", '招聘岗位信息.xlsx' ));
// 获取工作表数据(根据Excel中的工作表名称)
let sheetName = '岗位发布';
let dataList = sheetMap[sheetName];
if (!dataList || dataList.length === 0) {
console.log(`工作表 ${sheetName} 无数据`);
return;
}
console.log(`读取到 ${dataList.length} 行数据`);
// 表头映射
let titleMap = {
"0": "gsmc", //公司名称
"1": "gwmc", //岗位名称
"2": "zprs", //招聘人数
"3": "fbsj", //发布时间
"4": "xzdy", //薪资待遇
"5": "gzsj", //工作时间
"6": "gzdd", //工作地点
"7": "gwzz", //岗位职责
"8": "lggw", //零工岗位
"9": "tyjryx", //退役军人优先
"10": "syyhgw", //生育友好岗
"11": "lgg", //临公岗
}
let titleIndexList = Object.keys(titleMap);
let currentTime = new Date().valueOf();
let addList = [];
// 提取表头行(第0行)
let headerRow = dataList[0] || [];
// 处理每一行数据(从第1行开始)
for (let rowIndex = 1; rowIndex < dataList.length; rowIndex++) {
let subList = dataList[rowIndex];
// 构建行数据对象(用于标签解析)
let rowData:any = {};
titleIndexList.forEach((colIndex, idx) => {
let key = titleMap[colIndex];
let value = subList[parseInt(colIndex)];
rowData[key] = value;
});
let time_at = moment(new Date()).format("YYYY-MM-DD HH:mm:ss");
//处理特殊身份
let priority_type = 0;
if (rowData.lggw) {
priority_type = PRIORITYTYPE.零工岗位;
} else if (rowData.tyjryx) {
priority_type = PRIORITYTYPE.退役军人优先;
} else if (rowData.syyhgw) {
priority_type = PRIORITYTYPE.生育友好岗;
} else if (rowData.lgg) {
priority_type = PRIORITYTYPE.临公岗;
}
let publish_date = moment(new Date(rowData.fbsj)).format("YYYY-MM-DD") + " 00:00:00";
// 创建企业数据对象
let addDataInfo:any = {
company_name: rowData.gsmc,
job_title: rowData.gwmc,
recruitment_count: rowData.zprs,
publish_date,
salary_range: rowData.xzdy,
working_hours: rowData.gzsj,
work_location: rowData.gzdd,
job_responsibilities: rowData.gwzz,
priority_type: priority_type,
job_status: JOBSTATUS.招聘中,
education_requirement: EDUCATION.,
experience_requirement: "无",
contact_info: "",
created_at: time_at, //创建时间
updated_at: time_at, //更新时间
is_deleted: false, //软删除标记
};
addList.push(addDataInfo);
}
console.log(`准备导入 ${addList.length} 条岗位数据`);
await addData(TABLENAME.岗位信息表, addList);
} catch (error) {
console.error("初始化岗位数据失败:", error);
throw error;
}
}
/**
* 导入培训信息数据
*/
export async function addTrainingCourseData() {
try {
//检查是否已有数据
let dataCount = await selectDataCountByParam(TABLENAME.培训课程表, {});
if (dataCount.data > 10) {
console.log("*** 培训数据 无需初始化");
return;
}
// 读取Excel文件
let {sheetMap} = getExcel(path.join(__dirname.substring(0,__dirname.indexOf("out")), "res", '凯达职业技能等级认定项目资料2026年.xlsx' ));
// 获取工作表数据(根据Excel中的工作表名称)
let sheetName = '职业技能认定';
let dataList = sheetMap[sheetName];
if (!dataList || dataList.length === 0) {
console.log(`工作表 ${sheetName} 无数据`);
return;
}
console.log(`读取到 ${dataList.length} 行数据`);
// 表头映射
let titleMap = {
"0": "xh", //序号
"1": "xm", //项目
"2": "jb", //级别
"3": "kcnr", //课程内容
"4": "xxkcpxf", //线下课程培训费
"5": "xxkcclf", //线下课程材料费
"6": "bfzsmc", //颁发证书名称
"7": "bfzsdj", //颁发证书等级
"8": "bz", //备注(报考条件)
"9": "pxzxdh", //培训咨询电话
}
let titleIndexList = Object.keys(titleMap);
let addList = [];
// 提取表头行(第0行)
let headerRow = dataList[0] || [];
// 处理每一行数据(从第1行开始)
for (let rowIndex = 1; rowIndex < dataList.length; rowIndex++) {
let subList = dataList[rowIndex];
// 构建行数据对象(用于标签解析)
let rowData:any = {};
titleIndexList.forEach((colIndex, idx) => {
let key = titleMap[colIndex];
let value = subList[parseInt(colIndex)];
rowData[key] = value;
});
let time_at = moment(new Date()).format("YYYY-MM-DD HH:mm:ss");
let course_level = COURSELEVEL[rowData.jb];
let certificate_type = CERTIFICATETYPE[rowData.bfzsdj];
// 创建企业数据对象
let addDataInfo:any = {
course_name: rowData.xm,
course_type: 1,
course_level,
course_content: rowData.kcnr,
offline_training_fee: rowData.xxkcpxf,
offline_material_fee: rowData.xxkcclf,
certificate_name: rowData.bfzsmc,
certificate_type,
apply_conditions: rowData.bz,
contact_phone: rowData.pxzxdh,
created_at: time_at,
updated_at: time_at,
is_deleted: false,
};
addList.push(addDataInfo);
}
console.log(`准备导入 ${addList.length} 条培训课程数据`);
await addData(TABLENAME.培训课程表, addList);
} catch (error) {
console.error("初始化培训课程数据失败:", error);
throw error;
}
}
......@@ -8,7 +8,7 @@ import { CHAPTER, HLDTYPE, HUOLANDE, QUESTION, QUESTIONTITLE, TESTTYPE } from ".
import { ERRORENUM } from "../config/errorEnum";
import { addData } from "../data/addData";
import { selectDataListByParam, selectDataToTableAssociation, selectDataToTableAssociationToPage, selectOneDataByParam } from "../data/findData";
import { changeEnumValue, eccEnumValue } from "../tools/eccEnum";
import { changeEnumNameByCode, changeEnumValue, eccEnumValue } from "../tools/eccEnum";
import { BizError } from "../util/bizError";
import { updateManyData } from "../data/updateData";
......@@ -22,7 +22,7 @@ import { updateManyData } from "../data/updateData";
* @param area
* @param email 非必填,没有传null
* @returns
*/
*/
export async function addUsers(testType, name, phone, card?) {
let findCardData = await selectOneDataByParam(TABLENAME.测试信息表, {test_type:testType, name, phone}, []);
// if (findCardData.data.core) throw new BizError(ERRORENUM.该身份证号码重复);
......@@ -239,7 +239,7 @@ export async function getFinalScore(infoid, isTest) {
for (let enumkey in HLDTYPE) {
let anyKey: any = enumkey;
let keyNum = 0;
let keyName = changeEnumValue(QUESTION, HLDTYPE[enumkey]);
let keyName = changeEnumNameByCode(QUESTION, HLDTYPE[enumkey]);
if (isNaN(anyKey)) {
if (countInfo[enumkey]) keyNum = countInfo[enumkey];
countData.push({key:keyName, value:keyNum});
......@@ -263,12 +263,13 @@ export async function getFinalScore(infoid, isTest) {
let findCareer = await selectDataListByParam(TABLENAME.职业对照表, selectParam, []);
let time = moment(new Date()).format("YYYY年MM月DD日HH时mm分");
let testReport = {
name:findUserData.data.name,
infoid: findUserData.data.infoid,
name: findUserData.data.name,
time,
report1:optionData,
report2:countData,
statistics:topThreeStr,
recommend:""
report1: optionData,
report2: countData,
statistics: topThreeStr,
recommend: ""
}
findCareer.data.forEach( info => {
......
......@@ -28,6 +28,11 @@ export enum TABLENAME {
演示版测试信息记录表 = 'inforecord_test',
职业对照表 = 'career_contrast',
超级管理员表 = 'sys_user',
政策文件表 = 'policy_info',
岗位信息表 = 'job_info',
培训课程表 = 'training_course',
求职信息表 = 'job_seekers',
AI推荐记录表 = "ai_recommendation_record",
}
......
/**
* 校验表单参数配置 【管理后台端】
* 使用场景: 验证客户端请求参数
* 限制: 1.使用端不同不能共用一份配置
* 2.需要搭配 util/verificationParam -> eccFormParam() 方法使用
* 说明: notMustHave = true 时说明该字段是非必填的;不配该字段说明是必填的
*/
/**
* 使用端: 管理后台
* 场景: 新增政策文件
* 备注: 所有参数为必填
*/
export const PolicyAddConfig = {
file_name:{type:"String"}, //政策文件名称
subsidy_scope:{type:"String"}, //补贴范围对象
full_text:{type:"String"}, //政策内容
policy_file_url:{type:"String"}, //政策文件地址
policy_file_img:{type:"String"}, //政策文件图片文件夹
policy_imgname:{type:"[]"}, //政策文件图片地址
policy_start_time:{type:"String"}, //政策开始时间
policy_end_time:{type:"String"}, //政策结束时间
}
/**
* 使用端: 管理后台
* 场景: 修改政策文件
* 备注: 所有参数为必填
*/
export const PolicyUpdateConfig = {
file_name:{type:"String"}, //政策文件名称
subsidy_scope:{type:"String"}, //补贴范围对象
full_text:{type:"String"}, //政策内容
policy_file_url:{type:"String"}, //政策文件地址
policy_file_img:{type:"String"}, //政策文件图片文件夹
policy_imgname:{type:"[]"}, //政策文件图片地址
policy_start_time:{type:"String"}, //政策开始时间
policy_end_time:{type:"String"}, //政策结束时间
}
/**
* 使用端: 管理后台
* 场景: 新增岗位信息
* 备注: 所有参数为必填
*/
export const JobAddConfig = {
company_name:{type:"String"}, //公司名称
job_title:{type:"String"}, //岗位名称
recruitment_count:{type:"Number"}, //招聘人数
publish_date:{type:"String"}, //发布时间
salary_range:{type:"String"}, //薪资待遇
working_hours:{type:"String"}, //工作时间
work_location:{type:"String"}, //工作地点
job_responsibilities:{type:"String"}, //岗位职责
priority_type:{type:"Number"}, //岗位类型
job_status:{type:"Number"}, //岗位状态
education_requirement:{type:"Number", notMustHave:true}, //学历要求
experience_requirement:{type:"String", notMustHave:true}, //工作经验要求
contact_info:{type:"String", notMustHave:true}, //联系方式
}
/**
* 使用端: 管理后台
* 场景: 修改岗位信息
* 备注: 所有参数为必填
*/
export const JobUpdateConfig = {
company_name:{type:"String"}, //公司名称
job_title:{type:"String"}, //岗位名称
recruitment_count:{type:"Number"}, //招聘人数
publish_date:{type:"String"}, //发布时间
salary_range:{type:"String"}, //薪资待遇
working_hours:{type:"String"}, //工作时间
work_location:{type:"String"}, //工作地点
job_responsibilities:{type:"String"}, //岗位职责
priority_type:{type:"Number"}, //岗位类型
job_status:{type:"Number"}, //岗位状态
education_requirement:{type:"Number", notMustHave:true}, //学历要求
experience_requirement:{type:"String", notMustHave:true}, //工作经验要求
contact_info:{type:"String", notMustHave:true}, //联系方式
}
/**
* 使用端: 管理后台
* 场景: 新增培训课程
* 备注: 所有参数为必填
*/
export const TrainingCourseAddConfig = {
course_name:{type:"String"}, //课程名称
course_type:{type:"Number"}, //课程类型
course_level:{type:"Number"}, //课程级别
course_content:{type:"String"}, //课程内容
offline_training_fee:{type:"String"}, //线下课程培训费(元)
offline_material_fee:{type:"String"}, //线下课程材料费(元)
certificate_name:{type:"String"}, //颁发证书名称
certificate_type:{type:"Number"}, //颁发证书等级
apply_conditions:{type:"String"}, //备注(报考条件)
contact_phone:{type:"String"}, //培训咨询电话
}
/**
* 使用端: 管理后台
* 场景: 修改培训课程
* 备注: 所有参数为必填
*/
export const TrainingCourseUpdateConfig = {
course_name:{type:"String"}, //课程名称
course_type:{type:"Number"}, //课程类型
course_level:{type:"Number"}, //课程级别
course_content:{type:"String"}, //课程内容
offline_training_fee:{type:"String"}, //线下课程培训费(元)
offline_material_fee:{type:"String"}, //线下课程材料费(元)
certificate_name:{type:"String"}, //颁发证书名称
certificate_type:{type:"Number"}, //颁发证书等级
apply_conditions:{type:"String"}, //备注(报考条件)
contact_phone:{type:"String"}, //培训咨询电话
}
/**
* 使用端: 管理后台
* 场景: 新增求职信息
* 备注: 所有参数为必填
*/
export const JobSeekersAddConfig = {
/** 基本信息 */
name:{type:"String"}, //姓名
gender:{type:"Number"}, //性别
age:{type:"Number"}, //年龄
phone:{type:"String"}, //手机号码
id_card:{type:"String"}, //身份证号码
address:{type:"String"}, //居住地址
education:{type:"Number"}, //学历
household:{type:"String"}, //户籍
/**求职意向 */
applied_position:{type:"[]"}, //应聘岗位
expected_salary_min:{type:"String"}, //期望最低薪资(元/月)
expected_salary_max:{type:"String"}, //期望最高薪资(元/月)
expected_area:{type:"String"}, //期望工作区域
/** 特殊身份 */
special_identity:{type:"[]"}, //特殊身份
}
/**
* 使用端: 管理后台
* 场景: 修改求职信息
* 备注: 所有参数为必填
*/
export const JobSeekersUpdateConfig = {
/** 基本信息 */
name:{type:"String"}, //姓名
gender:{type:"Number"}, //性别
age:{type:"Number"}, //年龄
phone:{type:"String"}, //手机号码
id_card:{type:"String"}, //身份证号码
address:{type:"String"}, //居住地址
education:{type:"Number"}, //学历
household:{type:"String"}, //户籍
/**求职意向 */
applied_position:{type:"[]"}, //应聘岗位
expected_salary_min:{type:"String"}, //期望最低薪资(元/月)
expected_salary_max:{type:"String"}, //期望最高薪资(元/月)
expected_area:{type:"String"}, //期望工作区域
/** 特殊身份 */
special_identity:{type:"[]"}, //特殊身份
}
/**
* 使用端: 管理后台
* 场景: 新增求职信息-手机
* 备注: 所有参数为必填
*/
export const AIJobSeekerAddConfig = {
position:{type:"[]"}, //岗位推荐
policy:{type:"[]"}, //政策匹配
training:{type:"[]"}, //培训推荐
}
/**
* 使用端: 管理后台
* 场景: 新增求职信息-电脑
* 备注: 所有参数为必填
*/
export const AIJobAddConfig = {
report:{type:"{}"}, //测评报告
position:{type:"[]"}, //岗位推荐
policy:{type:"[]"}, //政策匹配
training:{type:"[]"}, //培训推荐
}
/**
* 使用端: 管理后台
* 场景: 新增求职信息-测评报告
* 备注: 所有参数为必填
*/
export const REPORT = {
basicInfo:{type:"{}"}, //求职者基础信息
personalityTraits:{type:"{}"}, //1.职业性格特征分析
specialty:{type:"[]"}, //2.职业优势与特长
suitableWork:{type:"{}"}, //3.适合的工作环境
development:{type:"{}"}, //4.职业发展建议
recommendJob:{type:"[]"}, //5.推荐职业方向
encourage:{type:"String"}, //最后的小鼓励
generationTime:{type:"String"}, //报告生成时间
}
/**
* 使用端: 管理后台
* 场景: 新增求职信息-测评报告-基础信息
* 备注: 所有参数为必填
*/
export const REPORTBASIC = {
id:{type:"Number"}, //id标识
name:{type:"String"}, //姓名
age:{type:"String"}, //年龄
holland:{type:"String"}, //霍兰德代码
}
/**
* 使用端: 管理后台
* 场景: 新增求职信息-岗位推荐
* 备注: 所有参数为必填
*/
export const POSITION = {
job_id:{type:"Number"}, //岗位id标识
company_name:{type:"String"}, //公司名称
job_title:{type:"String"}, //岗位名称
salary_range:{type:"String"}, //薪资待遇
working_hours:{type:"String"}, //工作时间
work_location:{type:"String"}, //工作地点
job_responsibilities:{type:"String"}, //岗位职责
career_match:{type:"String"}, //职业匹配度
matching_point:{type:"[]"}, //匹配点
recommend_reason:{type:"String"}, //推荐理由
}
/**
* 使用端: 管理后台
* 场景: 新增求职信息-政策匹配
* 备注: 所有参数为必填
*/
export const POLICT = {
policy_id:{type:"Number"}, //政策id标识
file_name:{type:"String"}, //政策文件名称
policy_level:{type:"String"}, //政策级别
subsidy_standard:{type:"String"}, //补贴标准
applicable_state:{type:"String"}, //适用状态
satisfied:{type:"[String]"}, //已满足条件
to_be_fulfilled:{type:"[String]"}, //待满足条件
}
/**
* 使用端: 管理后台
* 场景: 新增求职信息-培训推荐
* 备注: 所有参数为必填
*/
export const TRAINING = {
training_id:{type:"Number"}, //培训课程id标识
course_name:{type:"String"}, //课程名称
course_type:{type:"String"}, //课程类型
course_level:{type:"String"}, //课程级别
course_content:{type:"String"}, //课程内容
offline_training_fee:{type:"String"}, //线下课程培训费(元)
offline_material_fee:{type:"String"}, //线下课程材料费(元)
certificate_name:{type:"String"}, //颁发证书名称
certificate_type:{type:"String"}, //颁发证书等级
apply_conditions:{type:"String"}, //备注(报考条件)
contact_phone:{type:"String"}, //培训咨询电话
}
......@@ -129,6 +129,94 @@ export enum HUOLANDE {
}
/**
* 岗位类型
*/
export enum PRIORITYTYPE {
普通岗位 = 0,
零工岗位,
退役军人优先,
生育友好岗,
临公岗
}
/**
* 岗位状态
*/
export enum JOBSTATUS {
招聘中 = 0,
已结束,
}
/**
* 课程类型
*/
export enum COURSETYPE {
就业服务站 = 0,
第三方
}
/**
* 课程级别
*/
export enum COURSELEVEL {
初级 = 1,
中级,
高级,
}
/**
* 颁发证书等级
*/
export enum CERTIFICATETYPE {
一级证书 = 1,
二级证书,
三级证书,
四级证书,
五级证书,
}
/**
* 学历
*/
export enum EDUCATION {
= 0,
小学 = 1,
初中,
高中,
中专,
大专,
本科,
硕士,
博士,
其他,
}
/**
* 性别
*/
export enum GENDER {
= 1,
,
}
/**
* 特殊身份
*/
export enum SPECIALIDENTITY {
= 0,
退役军人 = 1,
残疾人 = 2,
应届毕业生 = 3,
}
......@@ -18,7 +18,14 @@ export enum ERRORENUM {
INTERNAL_SERVER_ERROR,
文件不存在,
该身份证号码重复,
账号或密码错误
账号或密码错误,
数据不存在,
地址数据不完整,
请完善信息,
删除失败,
空文件失败,
文件上传失败,
只能上传docdocxexcelpngjpg图片
}
/**
......
......@@ -19,13 +19,11 @@ export const TablesConfig = [
option_name: {type:DataTypes.STRING(255)}, //选项名称
points: {type:DataTypes.INTEGER(11)}, //分值
sort: {type:DataTypes.INTEGER(11)}, //排序
last_update_time: {type:DataTypes.DATE(0)}, //最后修改时间
create_time: {type:DataTypes.DATE(0)}, //创建时间
last_update_time: {type:DataTypes.DATE}, //最后修改时间
create_time: {type:DataTypes.DATE}, //创建时间
is_del: {type:DataTypes.TINYINT(1)}, //是否删除 0.正常 1.已删除
},
association: [
// {type: "hasMany", check: "question", foreignKey: "qid"}
]
association: []
},
{
tableNameCn:'题目表',
......@@ -42,8 +40,8 @@ export const TablesConfig = [
test_type: {type:DataTypes.TINYINT(1)}, //章节:1.霍兰德(一、我感兴趣的活动)2.霍兰德(二、我能完成的活动)3.霍兰德(三、我喜欢的职业)4.霍兰德(四、我的能力类型简评A)5.霍兰德(四、我的能力类型简评B)
chapter: {type:DataTypes.TINYINT(2)}, //章节
sort: {type:DataTypes.INTEGER(255)}, //排序
last_update_time: {type:DataTypes.DATE(0)}, //最后修改时间
create_time: {type:DataTypes.DATE(0)}, //创建时间
last_update_time: {type:DataTypes.DATE}, //最后修改时间
create_time: {type:DataTypes.DATE}, //创建时间
is_del: {type:DataTypes.TINYINT(1)}, //是否删除 0.正常 1.已删除
},
association: [
......@@ -67,9 +65,7 @@ export const TablesConfig = [
displayorder: {type:DataTypes.INTEGER(11)}, //显示顺序
level: {type:DataTypes.TINYINT(3)}, //层级别 1.省 2.市 3.区
},
association: [
// {type: "belongsTo", check: "area", foreignKey:"pid"}
]
association: []
},
{
tableNameCn:'测试信息表',
......@@ -93,12 +89,9 @@ export const TablesConfig = [
last_update_time: {type:DataTypes.DATE,allowNull:false}, //最后修改时间
create_time: {type:DataTypes.DATE,allowNull:false}, //创建时间
is_del: {type:DataTypes.TINYINT,allowNull:false}, //是否删除 0.正常 1.已删除
// highest_letter: {type:DataTypes.TINYINT}, //最高分字母
// second_highest_letter: {type:DataTypes.TINYINT}, //第二高分字母
// third_highest_letter: {type:DataTypes.TINYINT}, //第三高分字母
},
association: [
// { type: "hasMany", check: "inforecord", foreignKey: "infoid" }
{type:"hasMany", check:"ai_recommendation_record", foreignKey:"testinfo_id"},
]
},
{
......@@ -117,13 +110,11 @@ export const TablesConfig = [
test_type: {type:DataTypes.TINYINT(1)}, //题目类型:1. 霍兰德
title_str: {type:DataTypes.STRING(255),allowNull:false}, //记录标题用逗号隔开
option_str: {type:DataTypes.STRING(255),allowNull:false}, //记录结果用逗号隔开
last_update_time: {type:DataTypes.DATE(0),allowNull:false}, //最后修改时间
create_time: {type:DataTypes.DATE(0),allowNull:false}, //创建时间
last_update_time: {type:DataTypes.DATE,allowNull:false}, //最后修改时间
create_time: {type:DataTypes.DATE,allowNull:false}, //创建时间
is_del: {type:DataTypes.TINYINT(1),allowNull:false}, //是否删除 0.正常 1.已删除
},
association: [
//{ type: "belongsTo", check: "testinfo", foreignKey: "infoid" }
]
association: []
},
{
tableNameCn:'测试信息记录表',
......@@ -141,13 +132,11 @@ export const TablesConfig = [
test_type: {type:DataTypes.TINYINT(1)}, //题目类型:1. 霍兰德
title_str: {type:DataTypes.STRING(255),allowNull:false}, //记录标题用逗号隔开
option_str: {type:DataTypes.STRING(255),allowNull:false}, //记录结果用逗号隔开
last_update_time: {type:DataTypes.DATE(0),allowNull:false}, //最后修改时间
create_time: {type:DataTypes.DATE(0),allowNull:false}, //创建时间
last_update_time: {type:DataTypes.DATE,allowNull:false}, //最后修改时间
create_time: {type:DataTypes.DATE,allowNull:false}, //创建时间
is_del: {type:DataTypes.TINYINT(1),allowNull:false}, //是否删除 0.正常 1.已删除
},
association: [
//{ type: "belongsTo", check: "testinfo", foreignKey: "infoid" }
]
association: []
},
{
tableNameCn:'职业对照表',
......@@ -162,13 +151,11 @@ export const TablesConfig = [
},
statistics: {type:DataTypes.STRING(255),allowNull:false}, //记录标题用逗号隔开
recommend: {type:DataTypes.STRING(255),allowNull:false}, //记录结果用逗号隔开
last_update_time: {type:DataTypes.DATE(0),allowNull:false}, //最后修改时间
create_time: {type:DataTypes.DATE(0),allowNull:false}, //创建时间
last_update_time: {type:DataTypes.DATE,allowNull:false}, //最后修改时间
create_time: {type:DataTypes.DATE,allowNull:false}, //创建时间
is_del: {type:DataTypes.TINYINT(1),allowNull:false}, //是否删除 0.正常 1.已删除
},
association: [
//{ type: "belongsTo", check: "testinfo", foreignKey: "infoid" }
]
association: []
},
{
tableNameCn:'管理员表',
......@@ -188,12 +175,169 @@ export const TablesConfig = [
sex: {type:DataTypes.STRING(255),allowNull:false}, //性别 1、男 2、女
mail: {type:DataTypes.STRING(255),allowNull:false}, //邮箱
remark: {type:DataTypes.STRING(255),allowNull:false}, //备注
create_time: {type:DataTypes.DATE(0),allowNull:false}, //创建时间
last_update_time: {type:DataTypes.DATE(0),allowNull:false}, //最后修改时间
create_time: {type:DataTypes.DATE,allowNull:false}, //创建时间
last_update_time: {type:DataTypes.DATE,allowNull:false}, //最后修改时间
},
association: []
},
/**
* AI岗位推荐新增相关数据表
*/
{
tableNameCn:'政策文件',
tableName:'policy_info',
schema:{
id: {
type:DataTypes.INTEGER(11), //表示属性的数据类型
allowNull:false, //表示当前列是否允许为空, false表示该列不能为空
primaryKey:true, //表示主键
unique:true, //表示该列的值必须唯一
autoIncrement:true //设置为主键并自增
},
file_name: {type:DataTypes.STRING(255),allowNull:false}, //政策文件名称
subsidy_scope: {type:DataTypes.TEXT,allowNull:false}, //补贴范围对象
full_text: {type:DataTypes.TEXT,allowNull:false}, //政策内容
policy_file_url: {type:DataTypes.STRING(255),allowNull:false}, //政策文件地址
policy_file_img: {type:DataTypes.STRING(255),allowNull:false}, //政策文件图片文件夹地址
policy_imgname: {type:DataTypes.TEXT,allowNull:false,defaultValue:'[]'}, //政策文件图片 '["", ""]'
policy_start_time: {type:DataTypes.DATE,allowNull:false}, //政策开始时间
policy_end_time: {type:DataTypes.DATE,allowNull:false}, //政策结束时间
created_at: {type:DataTypes.DATE,allowNull:false,defaultValue:DataTypes.NOW}, //创建时间
updated_at: {type:DataTypes.DATE,allowNull:false,defaultValue:DataTypes.NOW}, //更新时间
is_deleted: {type: DataTypes.BOOLEAN,allowNull:false,defaultValue:false} //软删除标记
},
association: []
},
{
tableNameCn:'岗位信息',
tableName:'job_info',
schema:{
id: {
type:DataTypes.INTEGER(11), //表示属性的数据类型
allowNull:false, //表示当前列是否允许为空, false表示该列不能为空
primaryKey:true, //表示主键
unique:true, //表示该列的值必须唯一
autoIncrement:true //设置为主键并自增
},
company_name: {type:DataTypes.STRING(200),allowNull:false}, //公司名称
job_title: {type:DataTypes.STRING(200),allowNull:false}, //岗位名称
recruitment_count: {type:DataTypes.INTEGER(11),allowNull:false,defaultValue:1}, //招聘人数
publish_date: {type:DataTypes.DATE,allowNull:false}, //发布时间
salary_range: {type:DataTypes.STRING(100),allowNull:false}, //薪资待遇
working_hours: {type:DataTypes.STRING(100),allowNull:false}, //工作时间
work_location: {type:DataTypes.STRING(500),allowNull:false}, //工作地点
job_responsibilities: {type:DataTypes.TEXT,allowNull:false}, //岗位职责
priority_type: {type:DataTypes.TINYINT(1),allowNull:false,defaultValue:0},//岗位类型 '普通岗位=0','零工岗位=1','退役军人优先=2','生育友好岗=3','临公岗=4'
job_status: {type:DataTypes.TINYINT(1),allowNull:false,defaultValue:0}, //岗位状态 '招聘中=0', '已结束=1'
education_requirement: {type:DataTypes.TINYINT(1),allowNull:true,defaultValue:0}, //学历要求 '无"=0 EDUCATION
experience_requirement: {type:DataTypes.STRING(100),allowNull:true}, //工作经验要求
contact_info: {type:DataTypes.STRING(200),allowNull:true}, //联系方式
created_at: {type:DataTypes.DATE,allowNull:false,defaultValue:DataTypes.NOW}, //创建时间
updated_at: {type:DataTypes.DATE,allowNull:false,defaultValue:DataTypes.NOW}, //更新时间
is_deleted: {type:DataTypes.BOOLEAN,allowNull:false,defaultValue:false} //软删除标记
},
association: []
},
{
tableNameCn:'培训课程',
tableName:'training_course',
schema:{
id: {
type:DataTypes.INTEGER(11), //表示属性的数据类型
allowNull:false, //表示当前列是否允许为空, false表示该列不能为空
primaryKey:true, //表示主键
unique:true, //表示该列的值必须唯一
autoIncrement:true //设置为主键并自增
},
course_name: {type:DataTypes.STRING(255),allowNull:false}, //课程名称
course_type: {type:DataTypes.TINYINT(1),allowNull:false}, //课程类型 '就业服务站=0', '第三方=1'
course_level: {type:DataTypes.TINYINT(1),allowNull:false,defaultValue:0}, // 课程级别 '初级=0', '中级=1', '高级=2'
course_content: {type:DataTypes.TEXT,allowNull:true}, //课程内容
offline_training_fee: {type:DataTypes.STRING(255),allowNull:true}, //线下课程培训费(元)
offline_material_fee: {type:DataTypes.STRING(255),allowNull:true}, //线下课程材料费(元)
certificate_name: {type:DataTypes.STRING(255),allowNull:true}, //颁发证书名称(如:技能等级证书等)
certificate_type: {type:DataTypes.TINYINT(1),allowNull:true}, //颁发证书等级
apply_conditions: {type:DataTypes.TEXT,allowNull:true}, //备注(报考条件)
contact_phone: {type:DataTypes.STRING(50),allowNull:true}, //培训咨询电话
created_at: {type:DataTypes.DATE,allowNull:false,defaultValue:DataTypes.NOW}, //创建时间
updated_at: {type:DataTypes.DATE,allowNull:false,defaultValue:DataTypes.NOW}, //更新时间
is_deleted: {type: DataTypes.BOOLEAN,allowNull: false,defaultValue: false} //软删除标记
},
association: []
},
{
tableNameCn: '求职信息',
tableName: 'job_seekers',
schema: {
id: {
type:DataTypes.INTEGER(11), //表示属性的数据类型
allowNull:false, //表示当前列是否允许为空, false表示该列不能为空
primaryKey:true, //表示主键
unique:true, //表示该列的值必须唯一
autoIncrement:true //设置为主键并自增
},
/** 基本信息 */
name: {type:DataTypes.STRING(50),allowNull:false}, //姓名
gender: {type:DataTypes.TINYINT(1),allowNull:false}, //性别:1=男,2=女
age: {type:DataTypes.INTEGER(3),allowNull:false}, //年龄
phone: {type:DataTypes.STRING(20),allowNull:false}, //手机号码
id_card: {type:DataTypes.STRING(18),allowNull:false}, //身份证号码
address: {type:DataTypes.STRING(500),allowNull:false}, //居住地址
education: {type:DataTypes.TINYINT(2),allowNull:false}, //学历 1=小学,2=初中,3=高中,4=中专,5=大专,6=本科,7=硕士,8=博士,9=其他
household: {type:DataTypes.STRING(100),allowNull:false}, //户籍
/** 求职意向 */
applied_position: {type:DataTypes.STRING(200),allowNull:false,defaultValue:'[]'}, //应聘岗位(数组)'[]'
expected_salary_min: {type:DataTypes.DECIMAL(10, 2),allowNull:false}, //期望最低薪资(元/月)
expected_salary_max: {type:DataTypes.DECIMAL(10, 2),allowNull:false}, //期望最高薪资(元/月)
expected_area: {type:DataTypes.STRING(500),allowNull:false}, //期望工作区域
/** 特殊身份 */
special_identity: {type:DataTypes.STRING(200),allowNull:false,defaultValue:'[0]'}, //特殊身份(数组)'[2, 3]' 0=无,1=退役军人,2=残疾人,3=应届毕业生
/** 系统字段 */
created_at: {type:DataTypes.DATE,allowNull:false,defaultValue:DataTypes.NOW}, //创建时间
updated_at: {type:DataTypes.DATE,allowNull:false,defaultValue:DataTypes.NOW}, //更新时间
is_deleted: {type:DataTypes.BOOLEAN,allowNull:false,defaultValue:false} //软删除标记
},
association: [
{type:"hasMany", check:"ai_recommendation_record", foreignKey:"seeker_id"},
]
},
{
tableNameCn: 'AI推荐记录表',
tableName: 'ai_recommendation_record',
schema: {
id: {
type:DataTypes.INTEGER(11), //表示属性的数据类型
allowNull:false, //表示当前列是否允许为空, false表示该列不能为空
primaryKey:true, //表示主键
unique:true, //表示该列的值必须唯一
autoIncrement:true //设置为主键并自增
},
// 关联信息 - 二选一
seeker_id: {type:DataTypes.INTEGER(11),allowNull:true}, //求职者ID,关联job_seekers.id(手机用)
testinfo_id: {type:DataTypes.INTEGER(11),allowNull:true}, //测试信息ID,关联testinfo.infoid(电脑用)
// 结果关联信息
job_id: {type:DataTypes.TEXT,allowNull:true,defaultValue:'[]'}, //推荐的岗位ID,关联job_info.id '[]'
policy_id: {type:DataTypes.TEXT,allowNull:true,defaultValue:'[]'}, //推荐的政策ID,关联policy_info.id '[]'
training_id: {type:DataTypes.TEXT,allowNull:true,defaultValue:'[]'}, //推荐的培训课程ID,关联training_course.id '[]'
// 推荐来源类型
source_type: {type:DataTypes.TINYINT(1),allowNull:false,defaultValue:1}, //1=求职推荐(手机), 2=测评推荐(电脑)
// 霍兰德测评相关(接口2专用)
holland_code: {type:DataTypes.STRING(10),allowNull:true}, //霍兰德职业代码,如AES(电脑用)
//完整的测评报告JSON(电脑用),格式:{basicInfo, personalityTraits, specialty, suitableWork, development, recommendJob, encourage, generationTime}
report_json: {type:DataTypes.TEXT,allowNull:true,defaultValue:'{}'},
/**推荐内容 - 用JSON存储多个推荐项 */
//推荐的岗位列表JSON,格式:[{job_id, career_match, matching_points, recommend_reason, ...}]
recommended_jobs: {type:DataTypes.TEXT,allowNull:true,defaultValue:'[]'},
//推荐的政策列表JSON,格式:[{policy_id, applicable_state, satisfied, to_be_fulfilled, ...}]
recommended_policies: {type:DataTypes.TEXT,allowNull:true,defaultValue:'[]'},
//推荐的培训列表JSON,格式:[{training_id, ...}]
recommended_trainings: {type:DataTypes.TEXT,allowNull:true,defaultValue:'[]'},
// 系统字段
created_at: {type:DataTypes.DATE,allowNull:false,defaultValue:DataTypes.NOW}, //创建时间
updated_at: {type:DataTypes.DATE,allowNull:false,defaultValue:DataTypes.NOW}, //更新时间
is_deleted: {type: DataTypes.BOOLEAN,allowNull:false,defaultValue:false} //软删除标记
},
association: []
}
];
\ No newline at end of file
];
\ No newline at end of file
......@@ -14,11 +14,11 @@ export async function initConfig() {
if (!configInfo || !configInfo.config) throw new BizError('xml中无配置');
else {
let {port, sign, dbServer, mysqldb } = configInfo.config;
let {port, sign, dbServer, imgUrl, mysqldb } = configInfo.config;
systemConfig.port = parseInt(port[0]);
systemConfig.sign = sign[0]
systemConfig.dbPath = dbServer[0]
systemConfig.sign = sign[0];
systemConfig.dbPath = dbServer[0];
systemConfig.imgUrl = imgUrl[0];
if (mysqldb) {
let dbConfigInfo = mysqldb[0];
......
/**
* 拆分返回结果配置
* 使用场景:逻辑层中需要返回数据给客户端的地方
* 限制:使用端不同不能共用一份配置
*/
/**政策文件列表 */
export const policyListConfig = {
id:{key:"标识"},
file_name:{key:"政策文件名称"},
subsidy_scope:{key:"补贴范围对象"},
full_text:{key:"政策内容"},
policy_file_url:{key:"政策文件地址"},
policy_file_img:{key:"政策文件图片文件夹"},
policy_imgname:{key:"政策文件图片地址"},
policy_start_time:{key:"政策开始时间", changeDate:true},
policy_end_time:{key:"政策结束时间", changeDate:true},
}
/**岗位信息列表 */
export const jobListConfig = {
id:{key:"标识"},
company_name:{key:"公司名称"},
job_title:{key:"岗位名称"},
recruitment_count:{key:"招聘人数"},
publish_date:{key:"发布时间", changeDate:true},
salary_range:{key:"薪资待遇"},
working_hours:{key:"工作时间"},
work_location:{key:"工作地点"},
job_responsibilities:{key:"岗位职责"},
priority_type:{key:"岗位类型"},
job_status:{key:"岗位状态"},
education_requirement:{key:"学历要求"},
experience_requirement:{key:"工作经验要求"},
contact_info:{key:"联系方式"},
}
/**培训课程列表 */
export const trainingCourseListConfig = {
id:{key:"标识"},
course_name:{key:"课程名称"},
course_type:{key:"课程类型"},
course_level:{key:"课程级别"},
course_content:{key:"课程内容"},
offline_training_fee:{key:"线下课程培训费(元)"},
offline_material_fee:{key:"线下课程材料费(元)"},
certificate_name:{key:"颁发证书名称"},
certificate_type:{key:"颁发证书等级"},
apply_conditions:{key:"备注(报考条件)"},
contact_phone:{key:"培训咨询电话"},
}
/**求职信息列表 */
export const jobSeekersListConfig = {
id:{key:"标识"},
/** 基本信息 */
name:{key:"姓名"},
gender:{key:"性别"},
age:{key:"年龄"},
phone:{key:"手机号码"},
id_card:{key:"身份证号码"},
address:{key:"居住地址"},
education:{key:"学历"},
household:{key:"户籍"},
/**求职意向 */
applied_position:{key:"应聘岗位"},
expected_salary_min:{key:"期望最低薪资(元/月)"},
expected_salary_max:{key:"期望最高薪资(元/月)"},
expected_area:{key:"期望工作区域"},
/** 特殊身份 */
special_identity:{key:"特殊身份"},
}
......@@ -8,7 +8,7 @@ export class ServerConfig {
port:number;
sign:string;
dbPath:string;
imgUrl:string;
mysqldb:{
host:string,
port:number,
......
import { addJobData, addTrainingCourseData } from "./biz/dataInit";
import { initConfig, systemConfig} from "./config/serverConfig";
import * as mysqlDB from "./db/mysqlInit";
import { initMysqlModel } from "./model/sqlModelBind";
import { httpServer } from "./net/http_server";
async function lanuch() {
/**初始化配置解析 */
await initConfig();
......@@ -20,8 +19,21 @@ async function lanuch() {
// await smsTask();
console.log('This indicates that the server is started successfully.');
console.log("开始岗位信息同步");
await addJobData();
console.log("岗位信息同步成功");
console.log("开始培训课程同步");
await addTrainingCourseData();
console.log("培训课程信息同步成功");
}
lanuch();
lanuch();
\ No newline at end of file
import { ERRORENUM } from "../config/errorEnum";
import { BizError } from "../util/bizError";
var formidable = require("formidable");
const path = require('path');
const fs = require('fs');
export async function parseFormParam(req, res, next) {
// 临时上传目录
const tempUploadDir = path.join(__dirname.substring(0, __dirname.indexOf("out")), 'files', 'temp');
// 确保临时目录存在
if (!fs.existsSync(tempUploadDir)) {
fs.mkdirSync(tempUploadDir, { recursive: true });
}
var form = new formidable.IncomingForm({
uploadDir: tempUploadDir,
maxFileSize: 50 * 1024 * 1024, // 增大到 50MB,支持多文件
keepExtensions: true,
multiples: true // 启用多文件支持
});
form.parse(req, (err, fields, files) => {
if (err) {
return next(err);
} else if (!files || Object.keys(files).length === 0) {
return next(new BizError(ERRORENUM.空文件失败));
}
else {
req.fields = fields;
req.body = fields;
req.files = {};
// 处理多文件上传:files.formData 可能是数组
if (files.formData) {
req.files.formData = files.formData;
} else if (files.file) {
req.files.formData = files.file;
} else if (files.files) {
req.files.formData = files.files;
}
// 检查是否有文件
let hasFile = false;
let fileList = Array.isArray(req.files.formData) ? req.files.formData : [req.files.formData];
for (let file of fileList) {
if (file && file.name) {
hasFile = true;
break;
}
}
if (!hasFile) {
return next(new BizError(ERRORENUM.文件上传失败));
}
// 获取 targetDir
req.targetDir = fields.targetDir || req.query?.targetDir;
console.log("目标目录:", req.targetDir);
console.log("文件数量:", fileList.length);
// 只验证第一个文件的类型(或者你可以遍历验证)
let firstFile = fileList[0];
if (firstFile && firstFile.name) {
const fileExtension = firstFile.name.split('.').pop().toLowerCase();
if (firstFile.type == 'image/png') {
req.fileType = '.png';
} else if (firstFile.type == 'image/jpg' || firstFile.type == 'image/jpeg') {
req.fileType = '.jpg';
} else if (firstFile.type == "application/pdf") {
req.fileType = '.pdf';
} else if (firstFile.type == "application/vnd.openxmlformats-officedocument.wordprocessingml.document" || fileExtension == 'docx') {
req.fileType = '.docx';
} else if (firstFile.type == "application/msword") {
req.fileType = '.doc';
} else if (firstFile.type == "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") {
req.fileType = '.xlsx';
} else if (firstFile.type == "application/vnd.ms-excel") {
req.fileType = '.xls';
} else {
return next(new BizError(ERRORENUM.只能上传docdocxexcelpngjpg图片));
}
}
return next();
}
});
}
/**
* AI岗位推荐
*/
import asyncHandler from 'express-async-handler';
import * as aiPositionBiz from '../biz/aiPosition';
import { eccReqParamater } from '../util/verificationParam';
export function setRouter(httpServer){
/**政策文件 */
httpServer.post('/aiposition/policy/list', asyncHandler(policyList));
httpServer.post('/aiposition/policy/info', asyncHandler(policyInfo));
httpServer.post('/aiposition/policy/add', asyncHandler(addPolicy));
httpServer.post('/aiposition/policy/update', asyncHandler(updatePolicy));
httpServer.post('/aiposition/policy/del', asyncHandler(delPolicy));
/**岗位信息 */
httpServer.post('/aiposition/job/list', asyncHandler(jobList));
httpServer.post('/aiposition/job/info', asyncHandler(jobInfo));
httpServer.post('/aiposition/job/add', asyncHandler(addJob));
httpServer.post('/aiposition/job/update', asyncHandler(updateJob));
httpServer.post('/aiposition/job/del', asyncHandler(delJob));
/**培训课程 */
httpServer.post('/aiposition/training/list', asyncHandler(trainingCourseList));
httpServer.post('/aiposition/training/info', asyncHandler(trainingCourseInfo));
httpServer.post('/aiposition/training/add', asyncHandler(addTrainingCourse));
httpServer.post('/aiposition/training/update', asyncHandler(updateTrainingCourse));
httpServer.post('/aiposition/training/del', asyncHandler(delTrainingCourse));
/**求职信息 */
httpServer.post('/aiposition/jobseekers/list', asyncHandler(jobSeekersList));
httpServer.post('/aiposition/jobseekers/info', asyncHandler(jobSeekersInfo));
httpServer.post('/aiposition/jobseekers/add', asyncHandler(addJobSeekers));
httpServer.post('/aiposition/jobseekers/update', asyncHandler(updateJobSeekers));
httpServer.post('/aiposition/jobseekers/del', asyncHandler(delJobSeekers));
/**AI岗位推荐数据保存 */
httpServer.post('/aiposition/policy/alllist', asyncHandler(policyListAll));
httpServer.post('/aiposition/job/alllist', asyncHandler(jobListAll));
httpServer.post('/aiposition/training/alllist', asyncHandler(trainingCourseListAll));
httpServer.post('/aiposition/aijob/add', asyncHandler(addAIJob));
httpServer.post('/aiposition/job/application', asyncHandler(jobApplication));
httpServer.post('/aiposition/employment/evaluation', asyncHandler(employmentEvaluation));
};
// =========================================政策文件============================================
/**
* 政策文件-列表
*/
async function policyList(req, res) {
let reqConf = {fileName:'String', policyStartTime:'Number', policyEndTime:'Number', page:'Number'};
const NotMustHaveKeys = ['fileName', 'policyStartTime', 'policyEndTime'];
let { fileName, policyStartTime, policyEndTime, page } = eccReqParamater(reqConf, req.body, NotMustHaveKeys);
let result = await aiPositionBiz.getPolicyList(fileName, policyStartTime, policyEndTime, page);
res.success(result);
}
/**
* 政策文件-回显
*/
async function policyInfo(req, res) {
let reqConf = {id:'Number'};
let { id } = eccReqParamater(reqConf, req.body);
let result = await aiPositionBiz.getPrlicyInfo(id);
res.success(result);
}
/**
* 政策文件-新增
*/
async function addPolicy(req, res) {
let reqConf = {param:"Object"};
let { param } = eccReqParamater(reqConf, req.body);
let result = await aiPositionBiz.addPolicy(param);
res.success(result);
}
/**
* 政策文件-修改
*/
async function updatePolicy(req, res) {
let reqConf = {id:"Number", param:"Object"};
let { id, param } = eccReqParamater(reqConf, req.body);
let result = await aiPositionBiz.policyUpdate(id, param);
res.success(result);
}
/**
* 政策文件-删除
*/
async function delPolicy(req, res) {
let reqConf = {id:"Number"};
let { id } = eccReqParamater(reqConf, req.body);
let result = await aiPositionBiz.deletePolicy(id);
res.success(result);
}
// =========================================岗位信息============================================
/**
* 岗位信息-列表
*/
async function jobList(req, res) {
let reqConf = {company_name:'String', job_title:'String', priority_type:'Number', job_status:'Number', page:'Number'};
const NotMustHaveKeys = ['company_name', 'job_title', 'priority_type', 'job_status'];
let { company_name, job_title, priority_type, job_status, page } = eccReqParamater(reqConf, req.body, NotMustHaveKeys);
let result = await aiPositionBiz.getJobList(company_name, job_title, priority_type, job_status, page);
res.success(result);
}
/**
* 岗位信息-回显
*/
async function jobInfo(req, res) {
let reqConf = {id:'Number'};
let { id } = eccReqParamater(reqConf, req.body);
let result = await aiPositionBiz.getJobInfo(id);
res.success(result);
}
/**
* 岗位信息-新增
*/
async function addJob(req, res) {
let reqConf = {param:"Object"};
let { param } = eccReqParamater(reqConf, req.body);
let result = await aiPositionBiz.addJob(param);
res.success(result);
}
/**
* 岗位信息-修改
*/
async function updateJob(req, res) {
let reqConf = {id:"Number", param:"Object"};
let { id, param } = eccReqParamater(reqConf, req.body);
let result = await aiPositionBiz.jobUpdate(id, param);
res.success(result);
}
/**
* 岗位信息-删除
*/
async function delJob(req, res) {
let reqConf = {id:"Number"};
let { id } = eccReqParamater(reqConf, req.body);
let result = await aiPositionBiz.deleteJob(id);
res.success(result);
}
// =========================================培训课程============================================
/**
* 培训课程-列表
*/
async function trainingCourseList(req, res) {
let reqConf = {course_name:'String', page:'Number'};
const NotMustHaveKeys = ['course_name'];
let { course_name, page } = eccReqParamater(reqConf, req.body, NotMustHaveKeys);
let result = await aiPositionBiz.getTrainingCourseList(course_name, page);
res.success(result);
}
/**
* 培训课程-回显
*/
async function trainingCourseInfo(req, res) {
let reqConf = {id:'Number'};
let { id } = eccReqParamater(reqConf, req.body);
let result = await aiPositionBiz.getTrainingCourseInfo(id);
res.success(result);
}
/**
* 培训课程-新增
*/
async function addTrainingCourse(req, res) {
let reqConf = {param:"Object"};
let { param } = eccReqParamater(reqConf, req.body);
let result = await aiPositionBiz.addTrainingCourse(param);
res.success(result);
}
/**
* 培训课程-修改
*/
async function updateTrainingCourse(req, res) {
let reqConf = {id:"Number", param:"Object"};
let { id, param } = eccReqParamater(reqConf, req.body);
let result = await aiPositionBiz.updateTrainingCourse(id, param);
res.success(result);
}
/**
* 培训课程-删除
*/
async function delTrainingCourse(req, res) {
let reqConf = {id:"Number"};
let { id } = eccReqParamater(reqConf, req.body);
let result = await aiPositionBiz.deleteTrainingCourse(id);
res.success(result);
}
// =========================================求职信息============================================
/**
* 求职信息-列表
*/
async function jobSeekersList(req, res) {
let reqConf = {name:'String', phone:'String', id_card:'String', page:'Number'};
const NotMustHaveKeys = ['name', 'phone', 'id_card'];
let { name, phone, id_card, page } = eccReqParamater(reqConf, req.body, NotMustHaveKeys);
let result = await aiPositionBiz.getJobSeekersList(name, phone, id_card, page);
res.success(result);
}
/**
* 求职信息-回显
*/
async function jobSeekersInfo(req, res) {
let reqConf = {id:'Number'};
let { id } = eccReqParamater(reqConf, req.body);
let result = await aiPositionBiz.getJobSeekersInfo(id);
res.success(result);
}
/**
* 求职信息-新增
*/
async function addJobSeekers(req, res) {
let reqConf = {param:"Object"};
let { param } = eccReqParamater(reqConf, req.body);
let result = await aiPositionBiz.addJobSeekers(param);
res.success(result);
}
/**
* 求职信息-修改
*/
async function updateJobSeekers(req, res) {
let reqConf = {id:"Number", param:"Object"};
let { id, param } = eccReqParamater(reqConf, req.body);
let result = await aiPositionBiz.updateJobSeekers(id, param);
res.success(result);
}
/**
* 求职信息-删除
*/
async function delJobSeekers(req, res) {
let reqConf = {id:"Number"};
let { id } = eccReqParamater(reqConf, req.body);
let result = await aiPositionBiz.deleteJobSeekers(id);
res.success(result);
}
/**
* 新增AI岗位推荐信息
*/
async function addAIJob(req, res) {
let reqConf = {source_type:"Number", param:"Object"};
let { source_type, param } = eccReqParamater(reqConf, req.body);
let result = await aiPositionBiz.addAIJob(source_type, param);
res.success(result);
}
/**
* 全部政策文件
*/
async function policyListAll(req, res) {
let reqConf = {file_name:'String'};
const NotMustHaveKeys = ['file_name'];
let { file_name } = eccReqParamater(reqConf, req.body, NotMustHaveKeys);
let result = await aiPositionBiz.getPolicyListAll(file_name);
res.success(result);
}
/**
* 全部岗位信息
*/
async function jobListAll(req, res) {
let reqConf = {company_name:'String'};
const NotMustHaveKeys = ['company_name'];
let { company_name } = eccReqParamater(reqConf, req.body, NotMustHaveKeys);
let result = await aiPositionBiz.getJobListAll(company_name);
res.success(result);
}
/**
* 全部培训课程
*/
async function trainingCourseListAll(req, res) {
let result = await aiPositionBiz.getTrainingCourseListAll();
res.success(result);
}
/**
* 手机-我要求职点击进入AI
*/
async function jobApplication(req, res) {
let result = await aiPositionBiz.jobApplication();
res.success(result);
}
/**
* 电脑-就业测评点击进入AI
*/
async function employmentEvaluation(req, res) {
let result = await aiPositionBiz.employmentEvaluation();
res.success(result);
}
/**
* 文件管理 路由
*/
import asyncHandler = require('express-async-handler');
import { parseFormParam } from '../middleware/fromParam';
import moment from 'moment';
const fs = require('fs');
const path = require('path');
export function setRouter(httpServer) {
httpServer.post('/aiposition/files/up', parseFormParam, asyncHandler(upFiles));
// 新增:支持指定目录的上传接口(单文件)
httpServer.post('/aiposition/files/upwithdir', parseFormParam, asyncHandler(upFilesWithDir));
// 新增:支持多文件上传到指定目录
httpServer.post('/aiposition/files/upwithdir/multiple', parseFormParam, asyncHandler(upMultipleFilesWithDir));
}
/**
* 上传文件(原有逻辑,保持兼容)
*/
async function upFiles(req, res) {
let fileType = req.fileType;
let { name } = req.files.formData;
let docPath = req.files.formData.path;
let fileDir = path.resolve(docPath, '..');
let fileName = `${getFilesId(fileType, name)}${fileType}`;
let newPath = path.join(fileDir, fileName);
fs.renameSync(docPath, newPath);
console.log("上传文件", fileName, "成功");
res.success({ isSuccess: true, url: `/${fileName}`, fileName });
}
/**
* 单文件上传到指定目录
*/
async function upFilesWithDir(req, res) {
let fileType = req.fileType;
let { name } = req.files.formData;
let docPath = req.files.formData.path;
let targetDir = req.body.targetDir || req.query.targetDir;
// 获取项目根目录下的 files 目录路径
const baseDir = path.join(__dirname.substring(0, __dirname.indexOf("out")), 'files');
// 构建完整的目标目录路径
let fileDir = targetDir ? path.join(baseDir, targetDir) : baseDir;
// 确保目录存在
if (!fs.existsSync(fileDir)) {
fs.mkdirSync(fileDir, { recursive: true });
}
// 保留原始文件名
let fileName = name;
let newPath = path.join(fileDir, fileName);
// 如果文件名已存在,添加时间戳避免覆盖
if (fs.existsSync(newPath)) {
let ext = path.extname(fileName);
let baseName = path.basename(fileName, ext);
fileName = `${baseName}_${moment().format("YYYYMMDD_HHmmSS")}${ext}`;
newPath = path.join(fileDir, fileName);
}
fs.renameSync(docPath, newPath);
console.log("上传文件到目录", targetDir, ",文件名", fileName, "成功");
// 返回相对路径(相对于 files 目录)
let relativeUrl = targetDir ? `/${targetDir}/${fileName}` : `/${fileName}`;
res.success({ isSuccess: true, url: relativeUrl, fileName, targetDir });
}
/**
* 多文件上传到指定目录
* 支持同时上传多个文件到同一个目标目录
*/
async function upMultipleFilesWithDir(req, res) {
const baseDir = path.join(__dirname.substring(0, __dirname.indexOf("out")), 'files');
let targetDir = req.body.targetDir || req.query.targetDir;
// 获取所有上传的文件(支持 formData 数组或单个文件)
let uploadedFiles = [];
let filesList = [];
// formidable 中多个同名文件会被处理为数组
if (req.files.formData) {
filesList = Array.isArray(req.files.formData) ? req.files.formData : [req.files.formData];
} else if (req.files.files) {
filesList = Array.isArray(req.files.files) ? req.files.files : [req.files.files];
}
if (filesList.length === 0) {
return res.error({ isSuccess: false, message: "没有找到上传的文件" });
}
// 构建完整的目标目录路径
let fileDir = targetDir ? path.join(baseDir, targetDir) : path.join(baseDir, 'uploads');
// 确保目录存在
if (!fs.existsSync(fileDir)) {
fs.mkdirSync(fileDir, { recursive: true });
}
// 处理每个文件
for (let file of filesList) {
let docPath = file.path;
let originalName = file.name;
let fileName = originalName;
let newPath = path.join(fileDir, fileName);
// 如果文件名已存在,添加时间戳避免覆盖
if (fs.existsSync(newPath)) {
let ext = path.extname(fileName);
let baseName = path.basename(fileName, ext);
fileName = `${baseName}_${moment().format("YYYYMMDD_HHmmSS")}${ext}`;
newPath = path.join(fileDir, fileName);
}
fs.renameSync(docPath, newPath);
console.log("上传文件到目录", targetDir, ",文件名", fileName, "成功");
// 记录上传成功的文件信息
uploadedFiles.push({
originalName: originalName,
fileName: fileName,
url: targetDir ? `/${targetDir}/${fileName}` : `/${fileName}`,
size: file.size
});
}
res.success({
isSuccess: true,
targetDir: targetDir,
fileCount: uploadedFiles.length,
files: uploadedFiles
});
}
export function getFilesId(type: string, fileName: string) {
return `${fileName.replace(type, "")}${moment().format("YYYYMMDD_HHmmSS")}`;
}
/**
* 公共资源路由
*/
import asyncHandler = require('express-async-handler');
import * as enumConfig from '../config/enum';
import { eccReqParamater } from '../util/verificationParam';
const config = {
"/public/prioritytype":enumConfig.PRIORITYTYPE, //岗位类型
"/public/jobstatus":enumConfig.JOBSTATUS, //岗位状态
"/public/coursetype":enumConfig.COURSETYPE, //课程类型
"/public/courselevel":enumConfig.COURSELEVEL, //课程级别
"/public/education":enumConfig.EDUCATION, //学历要求
"/public/certificatetype":enumConfig.CERTIFICATETYPE, //颁发证书类型
"/public/specialidentity":enumConfig.SPECIALIDENTITY, //特殊身份
}
export function setRouter(httpServer) {
for (let modelKey in config) {
httpServer.post(modelKey, asyncHandler(getEnum(config[modelKey])));
}
}
/**
* 获取枚举
* @param enumCof
* @returns
*/
function getEnum(enumCof) {
return async function (req, res) {
let dataList = [];
for (let key in enumCof) {
let anyKey:any = key;
if (isNaN(anyKey)) {
dataList.push({key, value:enumCof[key]});
}
}
res.success({dataList});
}
}
......@@ -4,8 +4,14 @@
import * as huolandeRouter from './huolande';
import * as adminRouter from './admin';
import * as publicRouter from './public';
import * as aiPositionRouter from './aiPosition';
import * as filesRouter from './files';
export function setRouter(httpServer){
huolandeRouter.setRouter(httpServer);
adminRouter.setRouter(httpServer);
publicRouter.setRouter(httpServer);
aiPositionRouter.setRouter(httpServer);
filesRouter.setRouter(httpServer);
}
......@@ -27,41 +27,107 @@ export function eccEnumValue(name:string, key:string, enumConf, value:any) {
/**
* 将枚举值转换成对应的枚举名(key)
* @param enumConf 目标枚举
* @param value 目标值
* @param value 目标值
* @returns string 返回字符串 如果传入多个枚举值,就拼接字符串
*/
export function changeEnumValue(enumConf, value:any) {
if (!value) return '';
if ( typeof value == 'number' ) {
let str = enumConf[value];
/**特化处理 */
if(/_dou/.test(str)) str = str.replace(/_dou/gm, ",");
if(/_zyh/.test(str)) str = str.replace(/_zyh/gm, "“");
if(/_yyh/.test(str)) str = str.replace(/_yyh/gm, "”");
if(/_dun/.test(str)) str = str.replace(/_dun/gm, "、");
if(/_ju/.test(str)) str = str.replace(/_ju/gm, "。");
/** 特化处理 中文引号在枚举中不适用*/
if (str == "_投资__孵化_类型") {
str = str.replace("__","+");
str = str.replace("_","“");
str = str.replace("_","”");
}
if (str == "经营成本过高_场地成本或人员成本_" || str == "办公空间拓展_无合适办公空间_") {
str = str.replace("_","(");
str = str.replace("_",")");
}
if (str == "迁出孵化器_仍在张江" || str == "迁出张江_仍在浦东" || str == "迁出浦东_仍在上海") {
str = str.replace("_",",");
}
if (str == "科技金融_风险投资_" || str == "科技金融_其他_" || str == "技术专家_法律专家_") {
str = str.replace("_","(");
str = str.replace("_",")");
}
return str
} else if (typeof value == 'string') {
try {//兼容数据库 '[1,2,3]'
value = JSON.parse(value);
}catch(err) {
return enumConf[parseInt(value)];
}
}
let str = "";
value.forEach((item, index) => {
let subStr = enumConf[item];
/**特化处理 */
if(/_dou/.test(subStr)) subStr = subStr.replace(/_dou/gm, ",");
if(/_zyh/.test(subStr)) subStr = subStr.replace(/_zyh/gm, "“");
if(/_yyh/.test(subStr)) subStr = subStr.replace(/_yyh/gm, "”");
if(/_dun/.test(subStr)) subStr = subStr.replace(/_dun/gm, "、");
if(/_ju/.test(subStr)) subStr = subStr.replace(/_ju/gm, "。");
/** 特化处理 中文引号在枚举中不适用*/
if (subStr == "_投资__孵化_类型") {
subStr = subStr.replace("__","+");
subStr = subStr.replace("_","“");
subStr = subStr.replace("_","”");
}
if (subStr == "经营成本过高_场地成本或人员成本_" || subStr == "办公空间拓展_无合适办公空间_") {
subStr = subStr.replace("_","(");
subStr = subStr.replace("_",")");
}
if (subStr == "迁出孵化器_仍在张江" || subStr == "迁出张江_仍在浦东" || subStr == "迁出浦东_仍在上海") {
subStr = subStr.replace("_",",");
}
if (subStr == "科技金融_风险投资_" || subStr == "科技金融_其他_" || subStr == "技术专家_法律专家_") {
subStr = subStr.replace("_","(");
subStr = subStr.replace("_",")");
}
str += subStr;
if (index == value.length-1) str+="";
else str += ","
});
return str;
}
\ No newline at end of file
}
export function changeEnumManyValue(enumConf, value:any) {
let list = [];
value.forEach((item, index) => {
let subStr = enumConf[item];
/** 特化处理 中文引号在枚举中不适用*/
if (subStr == "_投资__孵化_类型") {
subStr = subStr.replace("__","+");
subStr = subStr.replace("_","“");
subStr = subStr.replace("_","”");
}
if (subStr == "经营成本过高_场地成本或人员成本_" || subStr == "办公空间拓展_无合适办公空间_") {
subStr = subStr.replace("_","(");
subStr = subStr.replace("_",")");
}
if (subStr == "迁出孵化器_仍在张江" || subStr == "迁出张江_仍在浦东" || subStr == "迁出浦东_仍在上海") {
subStr = subStr.replace("_",",");
}
if (subStr == "科技金融_风险投资_" || subStr == "科技金融_其他_" || subStr == "技术专家_法律专家_") {
subStr = subStr.replace("_","(");
subStr = subStr.replace("_",")");
}
list.push(subStr);
});
return list;
}
/**
* 根据枚举值反向获取名称
* @param enumConf
* @param code
* @returns
*/
export function changeEnumNameByCode(enumConf, code: string) {
for (const [name, value] of Object.entries(enumConf)) {
if (value === code) {
return name;
}
}
return '未知行业';
}
......@@ -2,8 +2,21 @@ import moment = require("moment");
import { ERRORENUM } from "../config/errorEnum";
import { BizError } from "../util/bizError";
import { FILETYPE } from "../config/enum";
import { systemConfig } from "../config/serverConfig";
const md5 = require("md5");
let fs = require("fs");
const path = require('path');
/**
* 获取随机id
* @param uscc
*/
export function randomId(tableName:string) {
let randomStr = `${new Date().valueOf()}_${Math.ceil(Math.random()*100000)}`;
return `${tableName}_${md5(randomStr)}`;
}
export function getUserToken(loginId:string) {
return md5(`${loginId}_${Math.ceil(Math.random()*1000)}${new Date().valueOf()}`);
......@@ -49,3 +62,60 @@ export function getFileType(fileName) {
});
return fileType;
}
/**
* 获取政策文件图片地址
* @param dirPath 政策文件图片目录路径(如:/政策文件图片/上海市毕业生就业补贴政策)
* @param imgNames 图片文件名数组
*/
export function getVerticalPolicy(dirPath, imgNames = []) {
// 如果目录路径为空,返回空数组
if (!dirPath || typeof dirPath !== 'string') {
return [];
}
// 如果没有图片文件名数组,返回空数组
if (!Array.isArray(imgNames) || imgNames.length === 0) {
return [];
}
try {
let fileList = [];
for (let i = 0; i < imgNames.length; i++) {
const fileName = imgNames[i];
// 构建完整的文件系统路径进行验证
const baseDir = 'img'; // 基础目录
const fullPath = path.join(baseDir, dirPath, fileName);
// 检查文件是否存在(可选,根据需求决定是否要验证)
// if (fs.existsSync(fullPath)) {
// 构建图片访问路径
// 例如:/政策文件图片/上海市毕业生就业补贴政策/1.png
const imagePath = `${systemConfig.imgUrl}${dirPath}/${fileName}`;
fileList.push(imagePath);
// } else {
// console.warn(`政策文件图片不存在: ${fullPath}`);
// }
}
return fileList;
} catch (error) {
console.error('构建政策文件图片路径出错:', error);
return [];
}
}
/**
* 校验参数工具
*
*/
import { ERRORENUM } from "../config/errorEnum";
import { BizError } from "./bizError";
/**
* 通过config校验表单参数param
* 包括类型 String, Number, Boolean, [Number], [Object]
* 参数是必填
* 方法会校验表单中存在的多余字段
* @param name 被调用的方法名
* @param config 校验配置
* @param param 需要校验的参数
* @returns true 无需关注返回
*/
export function eccFormParam(name:string, keyTypeConf:object, param:object) {
/**校验多余字段 */
for (let key in param) {
if (!keyTypeConf[key]) throw new BizError(ERRORENUM.参数错误, name, `多余${key}字段`);
}
/**校验已填参数 */
for (let key in keyTypeConf ) {
let {type, notMustHave} = keyTypeConf[key];
let isError = false; //校验是否异常
let errorStr = "";//异常说明
let value = param[key];
let valueType = typeof value;
if ( value == null || value == undefined ) {
if (!notMustHave) throw new BizError(ERRORENUM.参数错误, name, `缺失${key}字段`);
} else {
switch(type) {
case 'Number':
if ( type.toLowerCase() != valueType ) {
isError = true;
} else {
if ((""+param[key]).indexOf('.') > -1) {
param[key] = parseInt(`${param[key] *1000}`)/1000;
}
}
break;
case 'String':
case 'Boolean':
if ( type.toLowerCase() != valueType ) isError = true;
break;
case '[Number]':
if ( !Array.isArray(param[key]) ) isError = true;
for (let i =0; i < param[key].length; i++) {
let item = param[key][i];
if ( typeof item != 'number' ) {
isError = true;
errorStr = `${key}应是number型数组其中下标${i}${typeof item}`;
}
}
break;
case '[Object]':
if ( !Array.isArray(param[key]) ) isError = true;
for (let i =0; i < param[key].length; i++) {
let item = param[key][i];
if ( typeof item != 'object' ) {
isError = true;
errorStr = `${key}应是object型数组其中下标${i}${typeof item}`;
}
}
break;
case 'Address':
/**地址类型 基本数据类型为数组字符串但是要判断层级关系 */
if ( !Array.isArray(param[key]) ) {
isError = true;
errorStr = `${key}应是数组形`;
}
if ( param[key].length != 4) {
isError = true;
errorStr = `${key}超过特定长度4 目前长度 ${param[key].length}`;
}
for (let i =0; i < param[key].length; i++) {
let item = param[key][i];
if ( typeof item != 'string' ) {
isError = true;
errorStr = `${key}应是string型数组其中下标${i}${typeof item}`;
}
}
/** 不符合规则的 */
let nullIndex = -1;
for (let i = 0; i < param[key].length; i++) {
if (nullIndex != -1) {//出现过空 第一次出现后的位置 都不能有值
if (param[key]) {
//做一个特化
throw new BizError(ERRORENUM.地址数据不完整, name, `${key} 下标 ${nullIndex} 为空 `);
}
}
if (nullIndex == -1 && !param[key][i]) {
/**按顺序第一次赋值 */
nullIndex = i;
}
}
break;
}
errorStr = isError && errorStr == "" ? `${key}应该是${type}型 而不是${valueType}`: errorStr;
if ( isError ) throw new BizError(ERRORENUM.请完善信息, name, errorStr);
}
}
return true;
}
/**
* 根据conf配置校验请求参数
* @param conf 配置
* @param param 表单
* @param skipKeys []不必填的字段
*/
export function eccReqParamater(conf:object, param, skipKeys?) {
skipKeys = skipKeys || [];
let skipMap = {};
skipKeys.forEach(keyName => {
skipMap[keyName] = 1;
});
/**校验多余字段 */
for (let key in param) {
if (!conf[key]) throw new BizError(ERRORENUM.参数错误, `多余${key}字段`);
}
/**校验必填和缺失字段 */
for (let key in conf) {
let confType = conf[key];
let value = param[key];
let valueType = typeof value;
if ( value == null || value == undefined ) {
if (!skipMap[key]) throw new BizError(ERRORENUM.参数错误, `缺失${key}字段`);
} else {
let isError = false;
let errorStr = "";
switch(confType) {
case 'Number':
if ( confType.toLowerCase() != valueType ) isError = true;
else {
if ((""+param[key]).indexOf('.') > -1) {
param[key] = parseInt(`${param[key] *100}`)/100;
}
}
break;
case 'String':
case 'Boolean':
if ( confType.toLowerCase() != valueType ) isError = true;
break;
case '[Number]':
if ( !Array.isArray(param[key]) ) isError = true;
for (let i =0; i < param[key].length; i++) {
let item = param[key][i];
if ( typeof item != 'number' ) {
isError = true;
errorStr = `${key}应是number型数组其中下标${i}${typeof item}`;
}
}
break;
case '[Object]':
if ( !Array.isArray(param[key]) ) isError = true;
for (let i =0; i < param[key].length; i++) {
let item = param[key][i];
if ( typeof item != 'object' ) {
isError = true;
errorStr = `${key}应是object型数组其中下标${i}${typeof item}`;
}
}
break;
case 'Address':
/**地址类型 基本数据类型为数组字符串但是要判断层级关系 */
if ( !Array.isArray(param[key]) ) {
isError = true;
errorStr = `${key}应是数组形`;
}
if ( param[key].length != 4) {
isError = true;
errorStr = `${key}超过特定长度4 目前长度 ${param[key].length}`;
}
for (let i =0; i < param[key].length; i++) {
let item = param[key][i];
if ( typeof item != 'string' ) {
isError = true;
errorStr = `${key}应是string型数组其中下标${i}${typeof item}`;
}
}
/** 不符合规则的 */
let nullIndex = -1;
for (let i = 0; i < param[key].length; i++) {
if (nullIndex != -1) {//出现过空 第一次出现后的位置 都不能有值
if (param[key]) {
//做一个特化
throw new BizError(ERRORENUM.地址数据不完整, `${key} 下标 ${nullIndex} 为空 `);
}
}
if (nullIndex == -1 && !param[key][i]) {
/**按顺序第一次赋值 */
nullIndex = i;
}
}
break;
}
errorStr = isError && errorStr == "" ? `${key}应该是${confType}型 而不是${valueType}`: errorStr;
if (isError) throw new BizError(ERRORENUM.参数错误, errorStr);
}
}
return param;
}
\ No newline at end of file
......@@ -6,20 +6,13 @@
"rootDir":"./src",
"outDir":"./out",
"esModuleInterop": true,
// "strict": true,
"allowSyntheticDefaultImports": true,
"strict": false,
"noImplicitAny": false,
"strictNullChecks": false,
"types": ["node"]
},
"exclude": [
"node_modules",
]
}
// {
// "compilerOptions": {
// "target": "ES6",
// "module": "commonjs",
// "esModuleInterop": true,
// "outDir": "./dist",
// "strict": true
// },
// "include": ["src/**/*"]
// }
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment