Commit 72646b39 by chenjinjing

2025.02.20部署

parent 2ab94404
This source diff could not be displayed because it is too large. You can view the blob instead.
<config>
<port>40031</port>
<sign>xxx90909082fsdahfjosadjfpoiwausjorip2hjklrhn1ioud0u124rx0qwejfokasjfolksaujfoas</sign>
<dbServer>http://192.168.0.71:40031</dbServer>
<port>13275</port>
<sign></sign>
<dbServer>http://127.0.0.1:13275</dbServer>
<mysqldb>
<!-- 本地mysql配置 -->
<mysqlHost>192.168.0.71</mysqlHost>
......@@ -11,9 +11,9 @@
<dataBase>px_answer</dataBase>
<!-- 服务器mysql配置 -->
<!-- <mysqlHost>127.0.0.1</mysqlHost>
<mysqlPort>3306</mysqlPort>
<mysqlPort>13306</mysqlPort>
<mysqlUser>root</mysqlUser>
<mysqlPwd>Yfs123456_</mysqlPwd>
<dataBase>yfs</dataBase> -->
<mysqlPwd>root</mysqlPwd>
<dataBase>px_answer</dataBase> -->
</mysqldb>
</config>
import moment from "moment";
import { TABLENAME } from "../config/dbEnum";
import { selectDataCountByParam, selectDataListByParam, selectDataListToPageByParam, selectOneDataByParam } from "../data/findData";
import { CHAPTER, HLDTYPE, QUESTION, TESTTYPE } from "../config/enum";
import { changeEnumValue } from "../tools/eccEnum";
import { BizError } from "../util/bizError";
import { ERRORENUM } from "../config/errorEnum";
/**
* 登录
* @param username
* @param password
*/
export async function login(username, password) {
let findUserData = await selectOneDataByParam(TABLENAME.超级管理员表, {username, password}, []);
let findUser = findUserData.data;
if (!findUser || !findUser.username) throw new BizError(ERRORENUM.账号或密码错误);
if (findUser.password != password ) throw new BizError(ERRORENUM.账号或密码错误);
let dataInfo = {
username: findUser.username,
realName: findUser.real_name,
phone: findUser.phone,
sex: findUser.sex,
mail: findUser.mail,
remark: findUser.remark
};
return dataInfo;
}
/**
* 获取用户列表
* @param card
* @param createStartTime
* @param createEndTime
* @param area
* @param current
* @returns
*/
export async function getUserList(card, createStartTime, createEndTime, area, current) {
let selectParam = {"name":{"%ne%":"362527199309194932"}, "phone":{"%ne%":"17255558888"}};
if (card) selectParam["card"] = card;
if (createStartTime && createEndTime) selectParam["create_time"] = {"%between%":[createStartTime, createEndTime]};
if (area) selectParam["area"] = area;
let findData = await selectDataListToPageByParam(TABLENAME.测试信息表, selectParam, ["infoid", "name", "card", "phone", "email", "area", "create_time", "test_type"], current, 10);
let dataCount = await selectDataCountByParam(TABLENAME.测试信息表, selectParam);
let dataList = [];
findData.data.forEach( info => {
let {infoid, name, card, phone, email, area, create_time, test_type} = info;
dataList.push({
infoid, name, card, phone, email, area,
createTime: moment(create_time).format("YYYY-MM-DD"),
testType: test_type
})
})
return {dataList, dataCount:dataCount.data};
}
/**
* 查看列表详情
* @param infoid
* @param test_type
* @returns
*/
export async function getUserInfoById(infoid, test_type) {
let testReport = {};
if (test_type == TESTTYPE.创业) {
testReport = await getChuangYe(infoid);
} else if (test_type == TESTTYPE.霍兰德) {
testReport = await getHuoLanDe(infoid);
}
return testReport;
}
/**
* 创业答题详情
* @param infoid
* @returns
*/
async function getChuangYe(infoid) {
let findUserData = await selectOneDataByParam(TABLENAME.测试信息表, {infoid}, []);
let findData = await selectDataListByParam(TABLENAME.测试信息记录表, {infoid}, []);
let optionsInfo = [];
let score = 0;
for (let data = 0; data < findData.data.length; data++) {
let info = findData.data[data];
let {chapter, title_str, option_str} = info;
// optionsInfo[chapter] = {};
let title = JSON.parse(title_str);
let option = JSON.parse(option_str);
for (let i = 0; i < option.length; i++) {
let optionList = option[i];
let optionName = "";
for (let o = 0; o < optionList.length; o++) {
let findOption = await selectOneDataByParam(TABLENAME.题目选项表, {oid:optionList[o]}, []);
score += findOption.data["points"];
optionName = findOption.data["option_name"].slice(2);
}
optionsInfo.push({title:title[i], option:optionName});
}
}
let testReport = {
name:findUserData.data.name,
card:findUserData.data.card,
phone:findUserData.data.phone,
score,
time: moment(new Date()).format("YYYY年MM月DD日HH时mm分"),
report:optionsInfo,
};
return testReport;
}
/**
* 霍兰德详情
* @param infoid
* @returns
*/
async function getHuoLanDe(infoid) {
let findUserData = await selectOneDataByParam(TABLENAME.测试信息表, {infoid}, []);
let findData = await selectDataListByParam(TABLENAME.测试信息记录表, {infoid}, []);
let optionsInfo = {};
for (let data = 0; data < findData.data.length; data++) {
let info = findData.data[data];
let {chapter, title_str, option_str} = info;
optionsInfo[chapter] = {};
let title = JSON.parse(title_str);
let option = JSON.parse(option_str);
for (let i = 0; i < option.length; i++) {
let optionList = option[i];
let score = 0;
for (let o = 0; o < optionList.length; o++) {
let findOption = await selectOneDataByParam(TABLENAME.题目选项表, {oid:optionList[o]}, []);
score += findOption.data["points"];
}
optionsInfo[chapter][title[i]] = score;
}
}
let optionData = [];
let countInfo = {};
for (let key in optionsInfo) {
let maxKey = "";
let maxValue = 0;
for (let values in optionsInfo[key]) {
const value = optionsInfo[key][values];
if (value > maxValue) {
maxKey = values;
maxValue = value;
}
if(!countInfo[values]) countInfo[values] = 0
countInfo[values] += value;
}
let title = changeEnumValue(CHAPTER, parseInt(key));
let maxNum = HLDTYPE[maxKey];
optionData.push({key:title, value:maxKey, index:maxNum});
}
let countData = [];
for (let key in countInfo) {
let keyNum = HLDTYPE[key];
let keyName = changeEnumValue(QUESTION, keyNum);
countData.push({key:keyName, value:countInfo[key]});
}
let sortedEntries:any = Object.entries(countInfo);
sortedEntries.sort((a, b) => b[1] - a[1]);
let topThreeKeys = sortedEntries.slice(0, 3).map(entry => entry[0]);
let topThreeStr = topThreeKeys.join("");
let findCareer = await selectOneDataByParam(TABLENAME.职业对照表, {statistics:topThreeStr}, []);
let testReport = {
name:findUserData.data.name,
card:findUserData.data.card,
phone:findUserData.data.phone,
time: moment(new Date()).format("YYYY年MM月DD日HH时mm分"),
report1:optionData,
report2:countData,
statistics:topThreeStr,
recommend:findCareer.data.recommend
}
return testReport;
}
/**
* 数据导出
* @param card
* @param createStartTime
* @param createEndTime
* @param area
* @param current
* @returns
*/
export async function outPutData(card, createStartTime, createEndTime, area) {
let selectParam = {"name":{"%ne%":"362527199309194932"}, "phone":{"%ne%":"17255558888"}};
// let selectParam = {};
if (card) selectParam["card"] = card;
if (createStartTime && createEndTime) selectParam["create_time"] = {"%between%":[createStartTime, createEndTime]};
if (area) selectParam["area"] = area;
let findData = await selectDataListByParam(TABLENAME.测试信息表, selectParam, ["infoid", "name", "card", "phone", "email", "area", "create_time", "test_type"]);
let dataTitle = ["姓名", "身份证号", "联系方式", "电子邮箱", "所属区域", "测试日期", "测评类型"];
let dataList = [dataTitle];
findData.data.forEach( info => {
let {name, card, phone, email, area, create_time, test_type} = info;
let createTime = moment(create_time).format("YYYY-MM-DD");
let testType = changeEnumValue(TESTTYPE, test_type);
let subList = [
name || "",
card || "",
phone || "",
email || "",
area || "",
createTime || "",
testType || ""
];
dataList.push(subList);
})
return dataList;
}
......@@ -2,120 +2,318 @@
* 霍兰德
*/
import moment from "moment";
import { TABLENAME } from "../config/dbEnum";
import { QUESTIONTITLE, TESTTYPE } from "../config/enum";
import { selectDataToTableAssociation } from "../data/findData";
import { eccEnumValue } from "../tools/eccEnum";
import { CHAPTER, HLDTYPE, QUESTION, QUESTIONTITLE, TESTTYPE } from "../config/enum";
import { ERRORENUM } from "../config/errorEnum";
import { addData } from "../data/addData";
import { selectDataListByParam, selectDataToTableAssociation, selectOneDataByParam } from "../data/findData";
import { changeEnumValue, eccEnumValue } from "../tools/eccEnum";
import { BizError } from "../util/bizError";
import { updateManyData } from "../data/updateData";
/**
* 获取题目
* 个人信息填写
* @param test_type 题目类型:1. 霍兰德
* @param card
* @param name
* @param phone
* @param area
* @param email 非必填,没有传null
* @returns
*/
export async function addUsers(testType, name, card, phone, area, email?) {
let findCardData = await selectOneDataByParam(TABLENAME.测试信息表, {test_type:testType, card}, []);
// if (findCardData.data.core) throw new BizError(ERRORENUM.该身份证号码重复);
let addParam = {
test_type:testType,
name,
card,
phone,
area,
test_date:moment(new Date()).format("YYYY-MM-DD 00:00:00")
};
if (email) addParam[email] = email;
if (!findCardData.data.card) {
await addData(TABLENAME.测试信息表, addParam);
} else {
await updateManyData(TABLENAME.测试信息表, {test_type:testType, card}, addParam);
}
let userInfo = await selectOneDataByParam(TABLENAME.测试信息表, {test_type:testType, card}, ["infoid", "name"]);
return userInfo.data;
}
/**
* 下拉选择所属区域
*/
export async function getArea() {
let findData = await selectDataListByParam(TABLENAME.省市区表, {pid:"310100"}, ["id", "name"]);
return findData.data;
}
/**
* 获取题目
* @param test_type 题目类型:1. 霍兰德 2. 创业
* @param chapter 章节
* 1.霍兰德(一、我感兴趣的活动)2.霍兰德(二、我能完成的活动)3.霍兰德(三、我喜欢的职业)
* 4.霍兰德(四、我的能力类型简评A)5.霍兰德(四、我的能力类型简评B)
* 6.创业(技能)7.创业(经验)8.创业(您开办的新创业组织)9.创业(创办企业)10.符合你的特点
* @param isTest 是否演示版 0:否 1:是
* @returns
*/
export async function getQuestion(test_type, chapter) {
eccEnumValue("获取题目", "test_type", TESTTYPE, test_type);
eccEnumValue("获取题目", "chapter", QUESTIONTITLE, chapter);
export async function getQuestion(testType, chapter, isTest) {
if(!testType) testType = 1;
eccEnumValue("获取题目", "test_type", TESTTYPE, testType);
eccEnumValue("获取题目", "chapter", CHAPTER, chapter);
let selectParam:any = {is_del:0, test_type:1, chapter:1};
let selectParam:any = {};
if (testType == TESTTYPE.霍兰德) selectParam = {is_del:0, test_type:1, chapter:1};
else if (testType == TESTTYPE.创业) selectParam = {is_del:0, test_type:2, chapter:6};
if (test_type) selectParam.test_type = test_type;
if (testType) selectParam.test_type = testType;
if (chapter) selectParam.chapter = chapter;
/** includeConf:关联表配置*/
let includeConf = {};
includeConf[TABLENAME.题目选项表] = {colum:["option_name", "points"], where:{is_del:0} }; // colum:关联表需要查询的字段,where:关联表查询条件
/** questionInfo:多表联查*/
let questionInfo = await selectDataToTableAssociation(TABLENAME.题目表, includeConf, selectParam, ["chapter", "title"]);
let questionInfo = await selectDataToTableAssociation(TABLENAME.题目表, includeConf, selectParam, ["qid", "sort", "chapter", "title"]);
let questionData = [];
questionInfo.data.forEach( info => {
let {qid, title, options} = info;
let optionList = [];
options.forEach( option => {
let {sort, oid, option_name, points} = option;
optionList.push({oid, optionName:option_name, points, sort});
})
let chapter = changeEnumValue(CHAPTER, info.chapter);
questionData.push({sort:info.sort, qid, chapter, title, option:optionList})
})
// return {};
return questionInfo;
if (testType == TESTTYPE.创业) questionData = getRandomQuestions(questionData, chapter);
if (isTest == 1) questionData = getRandomQuestions(questionData, chapter, isTest);
return questionData;
}
/**
* 添加测试信息记录
* @param infoid 测试用户id
* @param chapter 章节 一个章节一条数据
* @param option [{ qid:1, answerIds:[1,2,3] }, { qid:2, answerIds:[4,5,6] }, ......]
* @param test_type 题目类型:1. 霍兰德 2. 创业
* @param isTest 是否演示版 0:否 1:是
*/
export async function addUsersInfo(infoid, chapter, option, testType, isTest) {
// if(findData.data && findData.data.length) throw new BizError("不可重复提交"); //判断一个用户一个章节答题不可重复提交
let addParam = {infoid, chapter, title_str:"", option_str:""}
let optionData = JSON.parse(option);
let title_str = [];
let option_str = [];
for(let i = 0; i < optionData.length; i++) {
let info = optionData[i];
let {qid, answerIds} = info;
let findData = await selectOneDataByParam(TABLENAME.题目表, {qid}, []);
let title = "";
if (testType == TESTTYPE.霍兰德) title = findData.data["title"].charAt(0);
else if (testType == TESTTYPE.创业) title = findData.data["title"];
title_str.push(title);
option_str.push(answerIds);
}
addParam.title_str = JSON.stringify(title_str);
addParam.option_str = JSON.stringify(option_str);
if (isTest == 1) await addData(TABLENAME.演示版测试信息记录表, addParam);
else if (isTest == 0) {
let findData = await selectDataListByParam(TABLENAME.测试信息记录表, {infoid, chapter}, []);
if (findData.data && findData.data.length) {
await updateManyData(TABLENAME.测试信息记录表, {infoid, chapter}, addParam);
} else {
await addData(TABLENAME.测试信息记录表, addParam);
}
}
return {isSuccess:true};
}
/**
* 计算霍兰德职业兴趣测试分数并汇总最高三个字母
* @param answers 用户的答案对象数组
* @returns 包含测试结果的对象
* 霍兰德 获取分数
* @param infoid 测试用户id
*/
export function calculateHollandScore(answers: any[]): { topThree: string; scores: Record<string, number> } {
//初始化分数统计对象
const scoreCounts = {
R: 0,// Realistic
I: 0, // Investigative
A: 0, // Artistic
S: 0, // Social
E: 0, // Enterprising
C: 0 // Conventional
};
export async function getFinalScore(infoid, isTest) {
let findUserData = await selectOneDataByParam(TABLENAME.测试信息表, {infoid}, []);
let findData:any = {};
if (isTest == 1) findData = await selectDataListByParam(TABLENAME.演示版测试信息记录表, {infoid}, []);
else if (isTest == 0) findData = await selectDataListByParam(TABLENAME.测试信息记录表, {infoid}, []);
let optionsInfo = {};
for (let data = 0; data < findData.data.length; data++) {
let info = findData.data[data];
let {chapter, title_str, option_str} = info;
optionsInfo[chapter] = {};
let title = JSON.parse(title_str);
let option = JSON.parse(option_str);
for (let i = 0; i < option.length; i++) {
let optionList = option[i];
let score = 0;
for (let o = 0; o < optionList.length; o++) {
let findOption = await selectOneDataByParam(TABLENAME.题目选项表, {oid:optionList[o]}, []);
score += findOption.data["points"];
}
optionsInfo[chapter][title[i]] = score;
}
}
let optionData = [];
let countInfo = {};
for (let key in optionsInfo) {
let maxKey = "";
let maxValue = 0;
for (let values in optionsInfo[key]) {
const value = optionsInfo[key][values];
if (value > maxValue) {
maxKey = values;
maxValue = value;
}
// 遍历用户答案并累加相应类型的分数
for (const answer of answers) {
const points = answer.points;
switch (answer.title) {
case 'R:实际型活动':
scoreCounts.R += points;
break;
case 'S:社会型活动':
scoreCounts.S += points;
break;
case 'I:研究型活动':
scoreCounts.I += points;
break;
case 'E;事业型活动':
scoreCounts.E += points;
break;
case 'A:艺术型活动':
scoreCounts.A += points;
break;
case 'C:常规型(传统型)活动':
scoreCounts.C += points;
break;
default:
console.warn(`未知的霍兰德类型: ${answer.type}`);
if(!countInfo[values]) countInfo[values] = 0
countInfo[values] += value;
}
let title = changeEnumValue(CHAPTER, parseInt(key));
let maxNum = HLDTYPE[maxKey];
optionData.push({key:title, value:maxKey, index:maxNum});
}
let countData = [];
for (let key in countInfo) {
let keyNum = HLDTYPE[key];
let keyName = changeEnumValue(QUESTION, keyNum);
countData.push({key:keyName, value:countInfo[key]});
}
//计算最高三个字母分数
const scoredArray = Object.entries(scoreCounts).map(([key, value]) => ({ type: key, score: value }));
scoredArray.sort((a, b) => b.score - a.score);
let sortedEntries:any = Object.entries(countInfo);
sortedEntries.sort((a, b) => b[1] - a[1]);
let topThreeKeys = sortedEntries.slice(0, 3).map(entry => entry[0]);
let topThreeStr = topThreeKeys.join("");
// let selectParam = {"$and":[]};
// topThreeKeys.forEach( info => {
// selectParam["$and"].push({"statistics":{"%regexp%":`[${info}]`}});
// })
//获取最高三个字母
const topThree = scoredArray.slice(0, 3).map(item => item.type).join('');
let selectParam = {"%literal%":``};
topThreeKeys.forEach( info => {
if (!selectParam["%literal%"]) selectParam["%literal%"] = `statistics REGEXP '[${info}]' `;
selectParam["%literal%"] += `and statistics REGEXP '[${info}]' `;
})
let findCareer = await selectDataListByParam(TABLENAME.职业对照表, selectParam, []);
//返回结果对象
return {
topThree,
scores: scoreCounts
};
let testReport = {
name:findUserData.data.name,
time: moment(new Date()).format("YYYY年MM月DD日HH时mm分"),
report1:optionData,
report2:countData,
statistics:topThreeStr,
recommend:""
}
findCareer.data.forEach( info => {
testReport.recommend += info.recommend;
})
return testReport;
}
/**
* 统计并汇总最高三个字母
* @param scores 分数统计对象
* @returns 包含统计结果的对象
* 创业 获取分数
* 评分标准为:A.5分;B.4分;C. 3分;D.2分;E.1分
* @param infoid 测试用户id
* @returns 姓名、分数、所有题目和所选答案
*/
export function summarizeScores(scores: Record<string, number>): { highestLetter: string; secondHighestLetter: string; thirdHighestLetter: string } {
const scoredArray = Object.entries(scores).map(([key, value]) => ({ type: key, score: value }));
scoredArray.sort((a, b) => b.score - a.score);
//获取最高三个字母
const highestLetter = scoredArray[0].type;
const secondHighestLetter = scoredArray[1]?.type || '';
const thirdHighestLetter = scoredArray[2]?.type || '';
return {
highestLetter,
secondHighestLetter,
thirdHighestLetter
};
export async function getChuangYeScore(infoid, isTest) {
let findUserData = await selectOneDataByParam(TABLENAME.测试信息表, {infoid}, []);
let findData:any = {};
if (isTest == 1) findData = await selectDataListByParam(TABLENAME.演示版测试信息记录表, {infoid}, []);
else if (isTest == 0) findData = await selectDataListByParam(TABLENAME.测试信息记录表, {infoid}, []);
let optionsInfo = [];
let score = 0;
for (let data = 0; data < findData.data.length; data++) {
let info = findData.data[data];
let {chapter, title_str, option_str} = info;
// optionsInfo[chapter] = {};
let title = JSON.parse(title_str);
let option = JSON.parse(option_str);
for (let i = 0; i < option.length; i++) {
let optionList = option[i];
let optionName = "";
for (let o = 0; o < optionList.length; o++) {
let findOption = await selectOneDataByParam(TABLENAME.题目选项表, {oid:optionList[o]}, []);
score += findOption.data["points"];
optionName = findOption.data["option_name"].slice(2);
}
optionsInfo.push({title:title[i], option:optionName});
}
}
let testReport = {
score,
name:findUserData.data.name,
time: moment(new Date()).format("YYYY年MM月DD日HH时mm分"),
report:optionsInfo,
}
if (isTest == 1) testReport.score = 91;
return testReport;
}
/**
* 创业 根据不同章节返回不同数量的题目
* 题目抽取比例为:技能取3题;经验取4题;您开办的新创业组织取5题;创办企业取8题;以下的每一条描述,你觉得它在多大程度上符合你的特点取10题
* @param data
* @param chapter 章节
* @returns
*/
function getRandomQuestions(data, chapter, isTest?) {
let numberOfQuestions = 0;
if (chapter == CHAPTER.技能) numberOfQuestions = 3;
else if (chapter == CHAPTER.经验) numberOfQuestions = 4;
else if (chapter == CHAPTER.您开办的新创业组织) numberOfQuestions = 5;
else if (chapter == CHAPTER.创办企业) numberOfQuestions = 8;
else if (chapter == CHAPTER.符合你的特点) numberOfQuestions = 10;
if (isTest == 1) numberOfQuestions = 1;
// 使用 Fisher-Yates 洗牌算法打乱数组
function shuffleArray(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]]; // 交换元素
}
return array;
}
// 打乱数据集
const shuffledData = shuffleArray([...data]);
// 返回打乱后的前 numberOfQuestions 个条目
return shuffledData.slice(0, numberOfQuestions);
}
......@@ -24,6 +24,10 @@ export enum TABLENAME {
题目表 = 'question',
题目选项表 = 'option',
测试信息表 = 'testinfo',
测试信息记录表 = 'inforecord',
演示版测试信息记录表 = 'inforecord_test',
职业对照表 = 'career_contrast',
超级管理员表 = 'sys_user',
}
......
......@@ -18,18 +18,34 @@ export enum FILETYPE {
}
export enum TESTTYPE {
"霍兰德" = 1,
"创业" = 2,
}
/**
* 题目大标题
*/
export enum TESTTYPE {
"一、我感兴趣的活动" = 1,
"二、我能完成的活动" = 2,
"三、我喜欢的职业" = 3,
"四、我的能力类型简评A" = 4,
"四、我的能力类型简评B" = 5,
export enum CHAPTER {
"一、我感兴趣的活动(多选)" = 1,
"二、我能完成的活动(多选)" = 2,
"三、我喜欢的职业(多选)" = 3,
"四、我的能力类型简评A(单选)" = 4,
"四、我的能力类型简评B(单选)" = 5,
"技能" = 6,
"经验" = 7,
"您开办的新创业组织" = 8,
"创办企业" = 9,
"符合你的特点" = 10
}
/**
* 题型
*/
......@@ -43,5 +59,66 @@ export enum QUESTIONTITLE {
}
// "R:实际型活动" = 1,
// "S:社会型活动" = 2,
// "I:研究型活动" = 3,
// "E:事业型活动" = 4,
// "A:艺术型活动" = 5,
// "C:常规型(传统型)活动" = 6,
// "R:实际型活动" = 7,
// "S:社会型活动" = 8,
// "I:研究型活动" = 9,
// "E:事业型活动" = 10,
// "A:艺术型活动" = 11,
// "C:常规型(传统型)活动" = 12,
// "R:实际型活动" = 13,
// "S:社会型活动" = 14,
// "I:研究型活动" = 15,
// "E:事业型活动" = 16,
// "A:艺术型活动" = 17,
// "C:常规型(传统型)活动" = 18,
// "R型:机械操作能力" = 19,
// "I型:科学研究能力" = 20,
// "A型:艺术创作能力" = 21,
// "S型:解释表达能力" = 22,
// "E型:商业洽谈能力" = 23,
// "C型:事务执行能力" = 24,
// "R型:体育技能" = 25,
// "I型:数学技能" = 26,
// "A型:音乐技能" = 27,
// "S型:交际技能" = 28,
// "E型:领导技能" = 29,
// "C型:办公技能" = 30,
/**
* 题型简称
*/
export enum HLDTYPE {
"R" = 1,
"S" = 2,
"I" = 3,
"E" = 4,
"A" = 5,
"C" = 6
}
/**
* 返回给前端题型
*/
export enum QUESTION {
"R型实际型" = 1,
"S型社会型" = 2,
"I型研究型" = 3,
"E型事业型" = 4,
"A型艺术型" = 5,
"C型常规型" = 6,
}
......@@ -16,7 +16,9 @@ export enum ERRORENUM {
数据联合查询失败,
INVALID_REQUEST,
INTERNAL_SERVER_ERROR,
文件不存在
文件不存在,
该身份证号码重复,
账号或密码错误
}
/**
......
......@@ -5,50 +5,49 @@ const { Sequelize, DataTypes } = require('sequelize');
export const TablesConfig = [
{
tableNameCn:'题目表',
tableName:'question',
tableNameCn:'题目选项表',
tableName:'option',
schema:{
qid: {
oid: {
type:DataTypes.INTEGER(11), //表示属性的数据类型
allowNull:false, //表示当前列是否允许为空, false表示该列不能为空
primaryKey:true, //表示主键
unique:true, //表示该列的值必须唯一
autoIncrement:true //设置为主键并自增
},
title: {type:DataTypes.STRING(255)}, //题目类型:1. 霍兰德
test_type: {type:DataTypes.TINYINT(1)}, //章节:1.霍兰德(一、我感兴趣的活动)2.霍兰德(二、我能完成的活动)3.霍兰德(三、我喜欢的职业)4.霍兰德(四、我的能力类型简评A)5.霍兰德(四、我的能力类型简评B)
chapter: {type:DataTypes.TINYINT(2)}, //章节
sort: {type:DataTypes.INTEGER(255)}, //排序
qid: {type:DataTypes.INTEGER(11)}, //题目ID
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)}, //创建时间
is_del: {type:DataTypes.TINYINT(1)}, //是否删除 0.正常 1.已删除
},
association: [
{type:"hasMany", check:"option", foreignKey:"qid"}
// {type: "hasMany", check: "question", foreignKey: "qid"}
]
},
{
tableNameCn:'题目选项表',
tableName:'option',
tableNameCn:'题目表',
tableName:'question',
schema:{
oid: {
qid: {
type:DataTypes.INTEGER(11), //表示属性的数据类型
allowNull:false, //表示当前列是否允许为空, false表示该列不能为空
primaryKey:true, //表示主键
unique:true, //表示该列的值必须唯一
autoIncrement:true //设置为主键并自增
},
qid: {type:DataTypes.INTEGER(11)}, //题目ID
option_name: {type:DataTypes.STRING(255)}, //选项名称
points: {type:DataTypes.INTEGER(11)}, //分值
sort: {type:DataTypes.INTEGER(11)}, //排序
title: {type:DataTypes.STRING(255)}, //题目类型:1. 霍兰德
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)}, //创建时间
is_del: {type:DataTypes.TINYINT(1)}, //是否删除 0.正常 1.已删除
},
association: [
{type: "hasMany", check: "question", foreignKey: "qid"}
// {type: "belongsTo", check: "question", foreignKey:"qid"}
{type:"hasMany", check:"option", foreignKey:"qid"},
]
},
{
......@@ -77,7 +76,7 @@ export const TablesConfig = [
tableName:'testinfo',
schema:{
infoid: {
type:DataTypes.INTEGER, //表示属性的数据类型
type:DataTypes.INTEGER(11), //表示属性的数据类型
allowNull:false, //表示当前列是否允许为空, false表示该列不能为空
primaryKey:true, //表示主键
unique:true, //表示该列的值必须唯一
......@@ -90,13 +89,13 @@ export const TablesConfig = [
email: {type:DataTypes.STRING(255)}, //电子邮箱
area:{type:DataTypes.STRING(255)}, //所在区域
final_score: {type:DataTypes.INTEGER}, //最终得分
test_time: {type:DataTypes.DATE}, //测试时间
test_date: {type:DataTypes.DATE}, //测试时间
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}, //第三高分字母
// highest_letter: {type:DataTypes.TINYINT}, //最高分字母
// second_highest_letter: {type:DataTypes.TINYINT}, //第二高分字母
// third_highest_letter: {type:DataTypes.TINYINT}, //第三高分字母
},
association: [
// { type: "hasMany", check: "inforecord", foreignKey: "infoid" }
......@@ -124,75 +123,75 @@ export const TablesConfig = [
association: [
//{ type: "belongsTo", check: "testinfo", foreignKey: "infoid" }
]
},
{
tableNameCn:'测试信息记录表',
tableName:'inforecord_test',
schema:{
irid: {
type:DataTypes.INTEGER(11), //表示属性的数据类型
allowNull:false, //表示当前列是否允许为空, false表示该列不能为空
primaryKey:true, //表示主键
unique:true, //表示该列的值必须唯一
autoIncrement:true //设置为主键并自增
},
infoid: {type:DataTypes.INTEGER(11),allowNull:false}, //测试信息ID
chapter: {type:DataTypes.TINYINT(2),allowNull:false}, //章节 1.霍兰德(一、我感兴趣的活动)2.霍兰德(二、我能完成的活动)3.霍兰德(三、我喜欢的职业)4.霍兰德(四、我的能力类型简评A)5.霍兰德(四、我的能力类型简评B)
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}, //创建时间
is_del: {type:DataTypes.TINYINT(1),allowNull:false}, //是否删除 0.正常 1.已删除
},
association: [
//{ type: "belongsTo", check: "testinfo", foreignKey: "infoid" }
]
},
{
tableNameCn:'职业对照表',
tableName:'career_contrast',
schema:{
cid: {
type:DataTypes.INTEGER(11), //表示属性的数据类型
allowNull:false, //表示当前列是否允许为空, false表示该列不能为空
primaryKey:true, //表示主键
unique:true, //表示该列的值必须唯一
autoIncrement:true //设置为主键并自增
},
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}, //创建时间
is_del: {type:DataTypes.TINYINT(1),allowNull:false}, //是否删除 0.正常 1.已删除
},
association: [
//{ type: "belongsTo", check: "testinfo", foreignKey: "infoid" }
]
},
{
tableNameCn:'管理员表',
tableName:'sys_user',
schema:{
id: {
type:DataTypes.INTEGER(11), //表示属性的数据类型
allowNull:false, //表示当前列是否允许为空, false表示该列不能为空
primaryKey:true, //表示主键
unique:true, //表示该列的值必须唯一
autoIncrement:true //设置为主键并自增
},
username: {type:DataTypes.STRING(255),allowNull:false}, //用户名
password: {type:DataTypes.STRING(255),allowNull:false}, //密码
real_name: {type:DataTypes.STRING(255),allowNull:false}, //真实姓名
phone: {type:DataTypes.STRING(255),allowNull:false}, //手机号码
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}, //最后修改时间
},
association: [
]
}
// {
// tableNameCn:'企业基础信息表',
// tableName:'enterprise',
// schema:{
// eId:{
// type:DataTypes.INTEGER, //表示属性的数据类型
// allowNull:false, //表示当前列是否允许为空, false表示该列不能为空
// primaryKey:true, //表示主键
// unique:true, //表示该列的值必须唯一
// autoIncrement:true //设置为主键并自增
// },
// enterpriseName: {type:DataTypes.STRING(255), allowNull:false}, //企业名称
// uscc: {type:DataTypes.STRING(18), allowNull:false}, //统一信用代码
// zhuCeHao:{type:DataTypes.STRING(100)},//注册号
// zuZhiJiGouDaiMa: {type:DataTypes.STRING(18)}, //组织机构代码
// gengDuoDianHua: {type:DataTypes.STRING(255)}, //更多电话
// mainBusiness: {type:DataTypes.TEXT}, //主营业务
// logonTime: {type:DataTypes.DATE}, //注册日期
// mail: {type:DataTypes.STRING(255)}, //邮箱
// isNaturalPersonHolding: {type:DataTypes.INTEGER}, //是否自然人控股企业(1表示是,0表示否) 【枚举】
// industry: {type:DataTypes.STRING(255)}, //领域
// moreMail: {type:DataTypes.STRING(255)}, //更多邮箱
// // dianHua: {type:DataTypes.STRING(100)}, //电话
// logonAddress: {type:DataTypes.STRING(255)}, //注册地址
// tongXinDiZhi: {type:DataTypes.STRING(255)}, //通信地址
// liaison: {type:DataTypes.STRING(50)}, //联系人
// liaisonPhone: {type:DataTypes.STRING(255)}, //联系电话
// dengJiJiGuan: {type:DataTypes.STRING(255)}, //登记机关
// qiYeGuiMo: {type:DataTypes.STRING(50)}, //企业规模
// RAS: {type:DataTypes.STRING(50)}, //登记状态
// guanWang: {type:DataTypes.STRING(255)}, //官网地址
// yingYeQiXian: {type:DataTypes.STRING(50)}, //营业期限
// logOffMS: {type:DataTypes.DATE}, //注销时间
// shijiaoziben: {type:DataTypes.STRING(255)}, //实缴资本
// enterpriseType: {type:DataTypes.STRING(50)}, //企业机构类型
// jianJie: {type:DataTypes.TEXT}, //简介
// zhuceziben: {type:DataTypes.STRING(255)}, //注册资本
// naShuiRenZiZhi: {type:DataTypes.STRING(50)}, //纳税人资质
// operatingAddress: {type:DataTypes.STRING(255)}, //经营地址
// oldLogonAddress: {type:DataTypes.STRING(255)},//迁入前注册地址
// shuiHao:{type:DataTypes.STRING(255)},//税号
// shuiWuJu:{type:DataTypes.STRING(255)},//税务局
// jingYingFanWei:{type:DataTypes.TEXT},//经营范围
// //状态标识
// register:{type:DataTypes.INTEGER},//是否通过申请 0=否 1=是
// state:{type:DataTypes.INTEGER},//是否通过入孵审核 0=否 1=是
// //临时填充信息用的验证码
// randomCode:{type:DataTypes.STRING(255)}
// },
// association: [
// {type: "hasMany", check: "enterprise_fuhua", foreignKey:"eId"},
// {type: "hasMany", check: "enterprise_lease", foreignKey:"eId"},
// {type: "hasMany", check: "enterprise_user", foreignKey:"eId"},
// {type: "hasMany", check: "enterprise_financing", foreignKey:"eId"},
// {type: "hasMany", check: "enterprise_honor", foreignKey:"eId"},
// {type: "hasMany", check: "enterprise_manage", foreignKey:"eId"},
// {type: "hasMany", check: "enterprise_qualification", foreignKey:"eId"},
// {type: "hasMany", check: "enterprise_canbao", foreignKey:"eId"},
// {type: "hasMany", check: "enterprise_team", foreignKey:"eId"},
// {type: "hasMany", check: "enterprise_ipr", foreignKey:"eId"},
// {type: "hasMany", check: "enterprise_legal_person", foreignKey:"eId"},
// {type: "hasMany", check: "enterprise_patent", foreignKey:"eId"},
// {type: "hasMany", check: "enterprise_service", foreignKey:"eId"}
// ]
// },
];
\ No newline at end of file
......@@ -16,8 +16,7 @@ export async function initConfig() {
let {port, sign, dbServer, mysqldb } = configInfo.config;
systemConfig.port = parseInt(port[0]);
systemConfig.sign = sign[0];
systemConfig.sign = sign[0]
systemConfig.dbPath = dbServer[0]
......
......@@ -7,7 +7,7 @@ export class ServerConfig {
/**系统配置 */
port:number;
sign:string;
dbPath:String;
dbPath:string;
mysqldb:{
host:string,
......
......@@ -6,7 +6,8 @@ import { mysqlModelMap } from "../model/sqlModelBind";
* @param data
* @returns
*/
export async function addData(tableModel, data:any) {
export async function addData(tableName:string, data:any) {
let tableModel = mysqlModelMap[tableName];
let dataArray = [];
if (!Array.isArray(data)) {
dataArray.push(data);
......
......@@ -23,6 +23,7 @@ function analysisParamToWhere(param, column) {
let where = {};
let order = [];
let group = "";
let literal = "";
let limit = 0;
for (let key in param) {
if (typeof param[key] == "object") {
......@@ -56,6 +57,12 @@ function analysisParamToWhere(param, column) {
case "%notIn%":
where[key][Op.notIn] = param[key]["%notIn%"];
break;
case "%ne%":
where[key][Op.ne] = param[key]["%ne%"];
break;
case "%regexp%":
where[key][Op.regexp] = param[key]["%regexp%"];
break;
}
}
} else {
......@@ -72,6 +79,9 @@ function analysisParamToWhere(param, column) {
case "%group%":
group = param[key];
break;
case "%literal%":
literal = param["%literal%"];
break;
default: where[key] = param[key];
}
}
......@@ -82,6 +92,7 @@ function analysisParamToWhere(param, column) {
if (order && order.length) selectParam.order = order;
if (limit) selectParam.limit = limit;
if (group) selectParam.group = group;
if (literal) selectParam.where = Sequelize.literal(literal);
return selectParam;
}
......@@ -91,7 +102,8 @@ function analysisParamToWhere(param, column) {
* @param param
* @returns
*/
export async function selectOneDataByParam(tableModel, param, column) {
export async function selectOneDataByParam(tableName, param, column) {
let tableModel = mysqlModelMap[tableName];
let selectParam = analysisParamToWhere(param, column);
let data = await tableModel.findOne(selectParam);
data = data || {};
......@@ -105,7 +117,8 @@ export async function selectOneDataByParam(tableModel, param, column) {
* @param param
* @returns
*/
export async function selectDataListByParam(tableModel, param, column) {
export async function selectDataListByParam(tableName, param, column) {
let tableModel = mysqlModelMap[tableName];
let selectParam = analysisParamToWhere(param, column);
let data = await tableModel.findAll(selectParam);
return { data };
......@@ -120,7 +133,8 @@ export async function selectDataListByParam(tableModel, param, column) {
* @param pageSize
* @returns
*/
export async function selectDataListToPageByParam(tableModel, param, column, pageNumber: number, pageSize: number) {
export async function selectDataListToPageByParam(tableName, param, column, pageNumber: number, pageSize: number) {
let tableModel = mysqlModelMap[tableName];
let selectParam: any = analysisParamToWhere(param, column);
selectParam.limit = pageSize || 10;
selectParam.offset = (pageNumber - 1) * 10;
......@@ -128,7 +142,8 @@ export async function selectDataListToPageByParam(tableModel, param, column, pag
return { data };
}
export async function selectDataCountByParam(tableModel, param) {
export async function selectDataCountByParam(tableName, param) {
let tableModel = mysqlModelMap[tableName];
let selectParam: any = analysisParamToWhere(param, []);
let data = await tableModel.count(selectParam);
return { data };
......@@ -162,7 +177,8 @@ export async function associationSelect(tableName: string, param) {
* @returns
*/
// question
export async function selectDataToTableAssociation(tableModel, includeConf, param, column) {
export async function selectDataToTableAssociation(tableName, includeConf, param, column) {
let tableModel = mysqlModelMap[tableName];
let include = [];
for (let tableName in includeConf) {
if (!mysqlModelMap[tableName]) throw new BizError(ERRORENUM.不存在表, `尝试进行多表联查,但是不存在${tableName}`);
......@@ -170,8 +186,7 @@ export async function selectDataToTableAssociation(tableModel, includeConf, para
let includeInfomation = analysisParamToWhere(where, column);
includeInfomation.model = mysqlModelMap[tableName];
include.push(includeInfomation);
}
}
let selectParam: any = analysisParamToWhere(param, column);
selectParam.include = include;
......@@ -179,7 +194,7 @@ export async function selectDataToTableAssociation(tableModel, includeConf, para
return { data };
}
/**
* 多表联查 分页
......@@ -189,7 +204,8 @@ export async function selectDataToTableAssociation(tableModel, includeConf, para
* @param column
* @returns
*/
export async function selectDataToTableAssociationToPage(tableModel, includeConf, param, column, pageNumber: number, pageSize: number) {
export async function selectDataToTableAssociationToPage(tableName, includeConf, param, column, pageNumber: number, pageSize: number) {
let tableModel = mysqlModelMap[tableName];
let include = [];
for (let tableName in includeConf) {
if (!mysqlModelMap[tableName]) throw new BizError(ERRORENUM.不存在表, `尝试进行多表联查,但是不存在${tableName}`);
......@@ -217,7 +233,8 @@ export async function selectDataToTableAssociationToPage(tableModel, includeConf
* @param column
* @returns
*/
export async function selectOneDataToTableAssociation(tableModel, includeConf, param, column) {
export async function selectOneDataToTableAssociation(tableName, includeConf, param, column) {
let tableModel = mysqlModelMap[tableName];
let include = [];
for (let tableName in includeConf) {
if (!mysqlModelMap[tableName]) throw new BizError(ERRORENUM.不存在表, `尝试进行多表联查,但是不存在${tableName}`);
......
import { Op, Sequelize } from "sequelize";
import { mysqlModelMap } from "../model/sqlModelBind";
/**
......@@ -77,7 +78,8 @@ function analysisParamToWhere(param) {
}
export async function updateManyData(tableModel, param:object, data:object) {
export async function updateManyData(tableName, param:object, data:object) {
let tableModel = mysqlModelMap[tableName];
let where = analysisParamToWhere(param);
await tableModel.update(data, where);
......
......@@ -18,7 +18,6 @@ async function lanuch() {
/**创建http服务 */
httpServer.createServer(systemConfig.port);
// await smsTask();
console.log('This indicates that the server is started successfully.');
}
......
import asyncHandler from 'express-async-handler';
import * as adminBiz from '../biz/admin';
// 霍兰德测试接口
export function setRouter(httpServer){
httpServer.post('/admin/login', asyncHandler(login));
httpServer.post('/admin/userlist', asyncHandler(getUserList));
httpServer.post('/admin/details', asyncHandler(getUserInfoById));
httpServer.post('/admin/output', asyncHandler(outPutData));
};
async function login(req, res) {
let {username, password} = req.body;
let result = await adminBiz.login(username, password);
res.success(result);
}
async function getUserList(req, res) {
let {card, createStartTime, createEndTime, area, current} = req.body;
let result = await adminBiz.getUserList(card, createStartTime, createEndTime, area, current);
res.success(result);
}
async function getUserInfoById(req, res) {
let {infoid, testType} = req.body;
let result = await adminBiz.getUserInfoById(infoid, testType);
res.success(result);
}
async function outPutData(req, res) {
let {card, createStartTime, createEndTime, area} = req.body;
let result = await adminBiz.outPutData(card, createStartTime, createEndTime, area);
res.success(result);
}
import * as asyncHandler from 'express-async-handler'
import { checkMySqlSign } from '../middleware/user';
import { eccReqParamater } from '../tools/eccParam';
import { BizError } from '../util/bizError';
import { ERRORENUM } from '../config/errorEnum';
import {calculateHollandScore} from '../biz/huolande';
import * as winston from 'winston';
import { error } from 'console';
const logger = winston.createLogger({
level: 'info',
format: winston.format.json(),
transports: [
new winston.transports.File({ filename: 'error.log', level: 'error' }),
new winston.transports.File({ filename: 'combined.log' })
]
});
import asyncHandler from 'express-async-handler';
import * as huolandeBiz from '../biz/huolande';
// 霍兰德测试接口
export function setRouter(httpServer){
httpServer.post('/question/getarea', asyncHandler(getArea));
httpServer.post('/question/addusers', asyncHandler(addUsers));
httpServer.post('/question/question', asyncHandler(getQuestion));
httpServer.post('/question/addusersinfo', asyncHandler(addUsersInfo));
httpServer.post('/huolande/finalscore', asyncHandler(getFinalScore));
httpServer.post('/chuangye/finalscore', asyncHandler(getChuangYeScore));
};
async function addUsers(req, res) {
let {testType, name, card, phone, email, area} = req.body;
let result = await huolandeBiz.addUsers(testType, name, card, phone, area, email);
res.success(result);
}
async function getArea(req, res) {
let result = await huolandeBiz.getArea();
res.success(result);
}
async function getQuestion(req, res) {
let { testType, chapter, isTest } = req.body;
let result = await huolandeBiz.getQuestion(testType, chapter, isTest);
res.success(result);
}
async function addUsersInfo(req, res) {
let {infoid, chapter, option, testType, isTest} = req.body;
let result = await huolandeBiz.addUsersInfo(infoid, chapter, option, testType, isTest);
res.success(result);
}
httpServer.post('/api/test/submit', async (req, res) => {
try {
const { answers } = req.body; // 假设答案通过请求体传递
// 校验参数
if (!answers || !Array.isArray(answers)) {
return res.status(400).send({ error: '无效的答案格式' });
// throw new BizError(ERRORENUM.INVALID_REQUEST, '无效的答案格式');
}
// 计算霍兰德测试分数并获取最高三个字母
const result = calculateHollandScore(answers);
// 返回结果给客户端
return res.status(200).json({
message: '答题成功',
hollandResult: {
topThree: result.topThree,
scores: result.scores
}
});
} catch (error) {
console.error('答题提交失败:', error);
return res.status(500).send({ error: '服务器错误' });
// throw new BizError(ERRORENUM.INTERNAL_SERVER_ERROR, '服务器错误');
}
});
const logger = winston.createLogger({
level: 'info',
format: winston.format.json(),
transports: [
new winston.transports.File({ filename: 'error.log', level: 'error' }),
new winston.transports.File({ filename: 'combined.log' })
]
});
logger.info('答题提交成功');
logger.error('答题提交失败:', { error });
async function getFinalScore(req, res) {
let {infoid, isTest} = req.body;
let result = await huolandeBiz.getFinalScore(infoid, isTest);
res.success(result);
}
// export function setRouter(httpServer){
// }
async function getChuangYeScore(req, res) {
let {infoid, isTest} = req.body;
let result = await huolandeBiz.getChuangYeScore(infoid, isTest);
res.success(result);
}
......@@ -3,7 +3,9 @@
*/
import * as huolandeRouter from './huolande';
import * as adminRouter from './admin';
export function setRouter(httpServer){
huolandeRouter.setRouter(httpServer);
adminRouter.setRouter(httpServer);
}
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