1
This commit is contained in:
354
api/model/apply_records.js
Normal file
354
api/model/apply_records.js
Normal file
@@ -0,0 +1,354 @@
|
||||
const dayjs = require('dayjs');
|
||||
const Sequelize = require('sequelize');
|
||||
|
||||
/**
|
||||
* 投递记录表模型
|
||||
* 记录简历投递的详细信息和结果
|
||||
*/
|
||||
module.exports = (db) => {
|
||||
const apply_records = db.define('apply_records', {
|
||||
// 投递基本信息
|
||||
sn_code: {
|
||||
comment: '设备SN码',
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: false,
|
||||
defaultValue: ''
|
||||
},
|
||||
platform: {
|
||||
comment: '平台: boss-Boss直聘, liepin-猎聘',
|
||||
type: Sequelize.STRING(20),
|
||||
allowNull: false,
|
||||
defaultValue: 'boss'
|
||||
},
|
||||
|
||||
// 岗位信息
|
||||
jobId: {
|
||||
comment: '岗位ID',
|
||||
type: Sequelize.STRING(100),
|
||||
allowNull: false,
|
||||
defaultValue: ''
|
||||
},
|
||||
encryptBossId: {
|
||||
comment: 'Boss加密ID',
|
||||
type: Sequelize.STRING(100),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
jobTitle: {
|
||||
comment: '岗位名称',
|
||||
type: Sequelize.STRING(200),
|
||||
allowNull: false,
|
||||
defaultValue: ''
|
||||
},
|
||||
companyId: {
|
||||
comment: '公司ID',
|
||||
type: Sequelize.STRING(100),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
companyName: {
|
||||
comment: '公司名称',
|
||||
type: Sequelize.STRING(200),
|
||||
allowNull: false,
|
||||
defaultValue: ''
|
||||
},
|
||||
salary: {
|
||||
comment: '薪资范围',
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
location: {
|
||||
comment: '工作地点',
|
||||
type: Sequelize.STRING(100),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
|
||||
// 简历信息
|
||||
resumeId: {
|
||||
comment: '简历ID',
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
resumeName: {
|
||||
comment: '简历名称',
|
||||
type: Sequelize.STRING(100),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
|
||||
// 投递状态
|
||||
applyStatus: {
|
||||
comment: '投递状态: pending-待投递, applying-投递中, success-投递成功, failed-投递失败, duplicate-重复投递',
|
||||
type: Sequelize.STRING(20),
|
||||
allowNull: false,
|
||||
defaultValue: 'pending'
|
||||
},
|
||||
applyTime: {
|
||||
comment: '投递时间',
|
||||
type: Sequelize.DATE,
|
||||
allowNull: true,
|
||||
get: function() {
|
||||
return dayjs(this.getDataValue('applyTime')).format('YYYY-MM-DD HH:mm:ss');
|
||||
}
|
||||
},
|
||||
|
||||
// 反馈状态
|
||||
feedbackStatus: {
|
||||
comment: '反馈状态: none-无反馈, viewed-已查看, interested-感兴趣, not_suitable-不合适, interview-面试邀约',
|
||||
type: Sequelize.STRING(20),
|
||||
allowNull: true,
|
||||
defaultValue: 'none'
|
||||
},
|
||||
feedbackTime: {
|
||||
comment: '反馈时间',
|
||||
type: Sequelize.DATE,
|
||||
allowNull: true
|
||||
},
|
||||
feedbackContent: {
|
||||
comment: '反馈内容',
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
|
||||
// HR信息
|
||||
hrName: {
|
||||
comment: 'HR姓名',
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
hrTitle: {
|
||||
comment: 'HR职位',
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
hrId: {
|
||||
comment: 'HR ID',
|
||||
type: Sequelize.STRING(100),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
|
||||
// 查看信息
|
||||
isViewed: {
|
||||
comment: '是否被查看',
|
||||
type: Sequelize.BOOLEAN,
|
||||
allowNull: true,
|
||||
defaultValue: false
|
||||
},
|
||||
viewTime: {
|
||||
comment: '查看时间',
|
||||
type: Sequelize.DATE,
|
||||
allowNull: true
|
||||
},
|
||||
viewCount: {
|
||||
comment: '查看次数',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
defaultValue: 0
|
||||
},
|
||||
|
||||
// 沟通信息
|
||||
hasChatted: {
|
||||
comment: '是否已沟通',
|
||||
type: Sequelize.BOOLEAN,
|
||||
allowNull: true,
|
||||
defaultValue: false
|
||||
},
|
||||
firstChatTime: {
|
||||
comment: '首次沟通时间',
|
||||
type: Sequelize.DATE,
|
||||
allowNull: true
|
||||
},
|
||||
lastChatTime: {
|
||||
comment: '最后沟通时间',
|
||||
type: Sequelize.DATE,
|
||||
allowNull: true
|
||||
},
|
||||
chatCount: {
|
||||
comment: '沟通次数',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
defaultValue: 0
|
||||
},
|
||||
|
||||
// 面试信息
|
||||
hasInterview: {
|
||||
comment: '是否有面试',
|
||||
type: Sequelize.BOOLEAN,
|
||||
allowNull: true,
|
||||
defaultValue: false
|
||||
},
|
||||
interviewTime: {
|
||||
comment: '面试时间',
|
||||
type: Sequelize.DATE,
|
||||
allowNull: true
|
||||
},
|
||||
interviewLocation: {
|
||||
comment: '面试地点',
|
||||
type: Sequelize.STRING(200),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
interviewType: {
|
||||
comment: '面试类型: online-线上, offline-线下',
|
||||
type: Sequelize.STRING(20),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
interviewStatus: {
|
||||
comment: '面试状态: pending-待面试, completed-已完成, passed-通过, failed-未通过, cancelled-已取消',
|
||||
type: Sequelize.STRING(20),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
|
||||
// Offer信息
|
||||
hasOffer: {
|
||||
comment: '是否收到Offer',
|
||||
type: Sequelize.BOOLEAN,
|
||||
allowNull: true,
|
||||
defaultValue: false
|
||||
},
|
||||
offerTime: {
|
||||
comment: 'Offer时间',
|
||||
type: Sequelize.DATE,
|
||||
allowNull: true
|
||||
},
|
||||
offerSalary: {
|
||||
comment: 'Offer薪资',
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
offerStatus: {
|
||||
comment: 'Offer状态: pending-待确认, accepted-已接受, rejected-已拒绝',
|
||||
type: Sequelize.STRING(20),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
|
||||
// AI匹配信息
|
||||
matchScore: {
|
||||
comment: 'AI匹配度评分(0-100)',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
defaultValue: 0
|
||||
},
|
||||
isOutsourcing: {
|
||||
comment: '是否外包岗位',
|
||||
type: Sequelize.BOOLEAN,
|
||||
allowNull: true,
|
||||
defaultValue: false
|
||||
},
|
||||
|
||||
// 投递策略
|
||||
priority: {
|
||||
comment: '投递优先级(1-10)',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
defaultValue: 5
|
||||
},
|
||||
isAutoApply: {
|
||||
comment: '是否自动投递',
|
||||
type: Sequelize.BOOLEAN,
|
||||
allowNull: true,
|
||||
defaultValue: true
|
||||
},
|
||||
|
||||
// 关联信息
|
||||
taskId: {
|
||||
comment: '关联任务ID',
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
keyword: {
|
||||
comment: '搜索关键词',
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
|
||||
// 统计信息
|
||||
responseDuration: {
|
||||
comment: '响应时长(小时)',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
defaultValue: 0
|
||||
},
|
||||
|
||||
// 其他信息
|
||||
originalData: {
|
||||
comment: '原始数据(JSON)',
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
errorMessage: {
|
||||
comment: '错误信息',
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
notes: {
|
||||
comment: '备注',
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
}
|
||||
}, {
|
||||
timestamps: false,
|
||||
indexes: [
|
||||
{
|
||||
unique: false,
|
||||
fields: ['sn_code']
|
||||
},
|
||||
{
|
||||
unique: false,
|
||||
fields: ['jobId']
|
||||
},
|
||||
{
|
||||
unique: false,
|
||||
fields: ['encryptBossId']
|
||||
},
|
||||
{
|
||||
unique: false,
|
||||
fields: ['applyStatus']
|
||||
},
|
||||
{
|
||||
unique: false,
|
||||
fields: ['feedbackStatus']
|
||||
},
|
||||
{
|
||||
unique: false,
|
||||
fields: ['isViewed']
|
||||
},
|
||||
{
|
||||
unique: false,
|
||||
fields: ['hasChatted']
|
||||
},
|
||||
{
|
||||
unique: false,
|
||||
fields: ['hasInterview']
|
||||
},
|
||||
{
|
||||
unique: false,
|
||||
fields: ['hasOffer']
|
||||
},
|
||||
{
|
||||
unique: false,
|
||||
fields: ['applyTime']
|
||||
},
|
||||
]
|
||||
});
|
||||
|
||||
// apply_records.sync({ force: true });
|
||||
return apply_records
|
||||
};
|
||||
|
||||
288
api/model/chat_records.js
Normal file
288
api/model/chat_records.js
Normal file
@@ -0,0 +1,288 @@
|
||||
const Sequelize = require('sequelize');
|
||||
|
||||
/**
|
||||
* 聊天记录表模型
|
||||
* 记录与HR的聊天内容和效果
|
||||
*/
|
||||
module.exports = (db) => {
|
||||
const chat_records = db.define("chat_records", {
|
||||
// 聊天基本信息
|
||||
sn_code: {
|
||||
comment: '设备SN码',
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: false,
|
||||
defaultValue: ''
|
||||
},
|
||||
platform: {
|
||||
comment: '平台: boss-Boss直聘, liepin-猎聘',
|
||||
type: Sequelize.STRING(20),
|
||||
allowNull: false,
|
||||
defaultValue: 'boss'
|
||||
},
|
||||
|
||||
// 岗位关联
|
||||
jobId: {
|
||||
comment: '岗位ID',
|
||||
type: Sequelize.STRING(100),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
encryptBossId: {
|
||||
comment: 'Boss加密ID',
|
||||
type: Sequelize.STRING(100),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
jobTitle: {
|
||||
comment: '岗位名称',
|
||||
type: Sequelize.STRING(200),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
companyName: {
|
||||
comment: '公司名称',
|
||||
type: Sequelize.STRING(200),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
|
||||
// HR信息
|
||||
hrName: {
|
||||
comment: 'HR姓名',
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
hrTitle: {
|
||||
comment: 'HR职位',
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
hrId: {
|
||||
comment: 'HR ID',
|
||||
type: Sequelize.STRING(100),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
|
||||
// 聊天内容
|
||||
chatType: {
|
||||
comment: '聊天类型: greeting-打招呼, follow_up-跟进, interview-面试邀约, reply-回复',
|
||||
type: Sequelize.STRING(20),
|
||||
allowNull: false,
|
||||
defaultValue: 'greeting'
|
||||
},
|
||||
direction: {
|
||||
comment: '消息方向: sent-发送, received-接收',
|
||||
type: Sequelize.STRING(20),
|
||||
allowNull: false,
|
||||
defaultValue: 'sent'
|
||||
},
|
||||
content: {
|
||||
comment: '聊天内容',
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: false,
|
||||
defaultValue: ''
|
||||
},
|
||||
contentType: {
|
||||
comment: '内容类型: text-文本, image-图片, file-文件',
|
||||
type: Sequelize.STRING(20),
|
||||
allowNull: true,
|
||||
defaultValue: 'text'
|
||||
},
|
||||
|
||||
// AI生成信息
|
||||
isAiGenerated: {
|
||||
comment: '是否AI生成',
|
||||
type: Sequelize.BOOLEAN,
|
||||
allowNull: true,
|
||||
defaultValue: false
|
||||
},
|
||||
aiPrompt: {
|
||||
comment: 'AI生成的提示词',
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
aiModel: {
|
||||
comment: 'AI模型名称',
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
|
||||
// 发送状态
|
||||
sendStatus: {
|
||||
comment: '发送状态: pending-待发送, sending-发送中, sent-已发送, failed-发送失败',
|
||||
type: Sequelize.STRING(20),
|
||||
allowNull: true,
|
||||
defaultValue: 'pending'
|
||||
},
|
||||
sendTime: {
|
||||
comment: '发送时间',
|
||||
type: Sequelize.DATE,
|
||||
allowNull: true
|
||||
},
|
||||
receiveTime: {
|
||||
comment: '接收时间',
|
||||
type: Sequelize.DATE,
|
||||
allowNull: true
|
||||
},
|
||||
|
||||
// 回复信息
|
||||
hasReply: {
|
||||
comment: '是否有回复',
|
||||
type: Sequelize.BOOLEAN,
|
||||
allowNull: true,
|
||||
defaultValue: false
|
||||
},
|
||||
replyTime: {
|
||||
comment: '回复时间',
|
||||
type: Sequelize.DATE,
|
||||
allowNull: true
|
||||
},
|
||||
replyContent: {
|
||||
comment: '回复内容',
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
replyDuration: {
|
||||
comment: '回复时长(分钟)',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
defaultValue: 0
|
||||
},
|
||||
|
||||
// 面试邀约信息
|
||||
isInterviewInvitation: {
|
||||
comment: '是否包含面试邀约',
|
||||
type: Sequelize.BOOLEAN,
|
||||
allowNull: true,
|
||||
defaultValue: false
|
||||
},
|
||||
interviewTime: {
|
||||
comment: '面试时间',
|
||||
type: Sequelize.DATE,
|
||||
allowNull: true
|
||||
},
|
||||
interviewLocation: {
|
||||
comment: '面试地点',
|
||||
type: Sequelize.STRING(200),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
interviewType: {
|
||||
comment: '面试类型: online-线上, offline-线下',
|
||||
type: Sequelize.STRING(20),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
interviewStatus: {
|
||||
comment: '面试状态: pending-待确认, confirmed-已确认, completed-已完成, cancelled-已取消',
|
||||
type: Sequelize.STRING(20),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
|
||||
// 效果评估
|
||||
effectScore: {
|
||||
comment: '效果评分(0-100)',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
defaultValue: 0
|
||||
},
|
||||
sentiment: {
|
||||
comment: '情感倾向: positive-正面, neutral-中性, negative-负面',
|
||||
type: Sequelize.STRING(20),
|
||||
allowNull: true,
|
||||
defaultValue: 'neutral'
|
||||
},
|
||||
|
||||
// 会话信息
|
||||
conversationId: {
|
||||
comment: '会话ID(同一个岗位的聊天属于一个会话)',
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
messageIndex: {
|
||||
comment: '消息序号(会话内的消息顺序)',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
defaultValue: 0
|
||||
},
|
||||
|
||||
// 关联信息
|
||||
taskId: {
|
||||
comment: '关联任务ID',
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
|
||||
// 其他信息
|
||||
originalData: {
|
||||
comment: '原始数据(JSON)',
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
errorMessage: {
|
||||
comment: '错误信息',
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
notes: {
|
||||
comment: '备注',
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
|
||||
|
||||
}, {
|
||||
timestamps: false,
|
||||
indexes: [
|
||||
{
|
||||
unique: false,
|
||||
fields: ['sn_code']
|
||||
},
|
||||
{
|
||||
unique: false,
|
||||
fields: ['jobId']
|
||||
},
|
||||
{
|
||||
unique: false,
|
||||
fields: ['encryptBossId']
|
||||
},
|
||||
{
|
||||
unique: false,
|
||||
fields: ['conversationId']
|
||||
},
|
||||
{
|
||||
unique: false,
|
||||
fields: ['chatType']
|
||||
},
|
||||
{
|
||||
unique: false,
|
||||
fields: ['sendStatus']
|
||||
},
|
||||
{
|
||||
unique: false,
|
||||
fields: ['hasReply']
|
||||
},
|
||||
|
||||
]
|
||||
});
|
||||
|
||||
//chat_records.sync({ force: true });
|
||||
|
||||
return chat_records
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
309
api/model/device_status.js
Normal file
309
api/model/device_status.js
Normal file
@@ -0,0 +1,309 @@
|
||||
const Sequelize = require('sequelize');
|
||||
|
||||
/**
|
||||
* 设备状态表模型
|
||||
* 记录pydp客户端设备的实时状态和运行信息
|
||||
*/
|
||||
module.exports = (db) => {
|
||||
const device_status= db.define("device_status", {
|
||||
// 设备基本信息
|
||||
sn_code: {
|
||||
comment: '设备SN码(唯一标识)',
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: false,
|
||||
primaryKey: true
|
||||
},
|
||||
device_id:{
|
||||
comment: '设备ID',
|
||||
type: Sequelize.STRING(200),
|
||||
allowNull: false,
|
||||
primaryKey: true
|
||||
},
|
||||
|
||||
deviceName: {
|
||||
comment: '设备名称',
|
||||
type: Sequelize.STRING(100),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
deviceType: {
|
||||
comment: '设备类型',
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: true,
|
||||
defaultValue: 'pydp'
|
||||
},
|
||||
|
||||
// 在线状态
|
||||
isOnline: {
|
||||
comment: '是否在线',
|
||||
type: Sequelize.BOOLEAN,
|
||||
allowNull: false,
|
||||
defaultValue: false
|
||||
},
|
||||
isRunning: {
|
||||
comment: '是否运行中',
|
||||
type: Sequelize.BOOLEAN,
|
||||
allowNull: false,
|
||||
defaultValue: false
|
||||
},
|
||||
lastOnlineTime: {
|
||||
comment: '最后在线时间',
|
||||
type: Sequelize.DATE,
|
||||
allowNull: true
|
||||
},
|
||||
lastOfflineTime: {
|
||||
comment: '最后离线时间',
|
||||
type: Sequelize.DATE,
|
||||
allowNull: true
|
||||
},
|
||||
onlineDuration: {
|
||||
comment: '在线时长(分钟)',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
defaultValue: 0
|
||||
},
|
||||
|
||||
// 运行状态
|
||||
currentTask: {
|
||||
comment: '当前执行任务',
|
||||
type: Sequelize.STRING(100),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
currentTaskId: {
|
||||
comment: '当前任务ID',
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
taskStatus: {
|
||||
comment: '任务状态',
|
||||
type: Sequelize.STRING(20),
|
||||
allowNull: true,
|
||||
defaultValue: 'idle'
|
||||
},
|
||||
lastTaskTime: {
|
||||
comment: '最后任务时间',
|
||||
type: Sequelize.DATE,
|
||||
allowNull: true
|
||||
},
|
||||
|
||||
// 平台信息
|
||||
platform: {
|
||||
comment: '当前使用平台: boss-Boss直聘, liepin-猎聘',
|
||||
type: Sequelize.STRING(20),
|
||||
allowNull: true,
|
||||
defaultValue: 'boss'
|
||||
},
|
||||
isLoggedIn: {
|
||||
comment: '是否已登录平台',
|
||||
type: Sequelize.BOOLEAN,
|
||||
allowNull: true,
|
||||
defaultValue: false
|
||||
},
|
||||
loginTime: {
|
||||
comment: '登录时间',
|
||||
type: Sequelize.DATE,
|
||||
allowNull: true
|
||||
},
|
||||
accountName: {
|
||||
comment: '账号名称',
|
||||
type: Sequelize.STRING(100),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
|
||||
// 性能信息
|
||||
cpuUsage: {
|
||||
comment: 'CPU使用率(%)',
|
||||
type: Sequelize.FLOAT,
|
||||
allowNull: true,
|
||||
defaultValue: 0
|
||||
},
|
||||
memoryUsage: {
|
||||
comment: '内存使用率(%)',
|
||||
type: Sequelize.FLOAT,
|
||||
allowNull: true,
|
||||
defaultValue: 0
|
||||
},
|
||||
diskUsage: {
|
||||
comment: '磁盘使用率(%)',
|
||||
type: Sequelize.FLOAT,
|
||||
allowNull: true,
|
||||
defaultValue: 0
|
||||
},
|
||||
|
||||
// 网络信息
|
||||
ipAddress: {
|
||||
comment: 'IP地址',
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
macAddress: {
|
||||
comment: 'MAC地址',
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
networkStatus: {
|
||||
comment: '网络状态: good-良好, slow-缓慢, offline-离线',
|
||||
type: Sequelize.STRING(20),
|
||||
allowNull: true,
|
||||
defaultValue: 'good'
|
||||
},
|
||||
|
||||
// 心跳信息
|
||||
lastHeartbeatTime: {
|
||||
comment: '最后心跳时间',
|
||||
type: Sequelize.DATE,
|
||||
allowNull: true
|
||||
},
|
||||
heartbeatInterval: {
|
||||
comment: '心跳间隔(秒)',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
defaultValue: 30
|
||||
},
|
||||
missedHeartbeats: {
|
||||
comment: '丢失的心跳次数',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
defaultValue: 0
|
||||
},
|
||||
|
||||
// 版本信息
|
||||
clientVersion: {
|
||||
comment: '客户端版本',
|
||||
type: Sequelize.STRING(20),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
pythonVersion: {
|
||||
comment: 'Python版本',
|
||||
type: Sequelize.STRING(20),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
osVersion: {
|
||||
comment: '操作系统版本',
|
||||
type: Sequelize.STRING(100),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
|
||||
// 统计信息
|
||||
totalTasksCompleted: {
|
||||
comment: '完成任务总数',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
defaultValue: 0
|
||||
},
|
||||
totalTasksFailed: {
|
||||
comment: '失败任务总数',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
defaultValue: 0
|
||||
},
|
||||
totalJobsSearched: {
|
||||
comment: '搜索岗位总数',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
defaultValue: 0
|
||||
},
|
||||
totalApplies: {
|
||||
comment: '投递简历总数',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
defaultValue: 0
|
||||
},
|
||||
totalChats: {
|
||||
comment: '聊天总数',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
defaultValue: 0
|
||||
},
|
||||
|
||||
// 错误信息
|
||||
lastError: {
|
||||
comment: '最后错误信息',
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
lastErrorTime: {
|
||||
comment: '最后错误时间',
|
||||
type: Sequelize.DATE,
|
||||
allowNull: true
|
||||
},
|
||||
errorCount: {
|
||||
comment: '错误次数',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
defaultValue: 0
|
||||
},
|
||||
|
||||
// 健康状态
|
||||
healthStatus: {
|
||||
comment: '健康状态: healthy-健康, warning-警告, error-错误, unknown-未知',
|
||||
type: Sequelize.STRING(20),
|
||||
allowNull: true,
|
||||
defaultValue: 'unknown'
|
||||
},
|
||||
healthScore: {
|
||||
comment: '健康评分(0-100)',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
defaultValue: 0
|
||||
},
|
||||
|
||||
// 配置信息
|
||||
config: {
|
||||
comment: '设备配置(JSON)',
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
|
||||
// 其他信息
|
||||
notes: {
|
||||
comment: '备注',
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
|
||||
}, {
|
||||
timestamps: false,
|
||||
indexes: [
|
||||
{
|
||||
unique: false,
|
||||
fields: ['isOnline']
|
||||
},
|
||||
{
|
||||
unique: false,
|
||||
fields: ['isRunning']
|
||||
},
|
||||
{
|
||||
unique: false,
|
||||
fields: ['healthStatus']
|
||||
},
|
||||
{
|
||||
unique: false,
|
||||
fields: ['platform']
|
||||
},
|
||||
{
|
||||
unique: false,
|
||||
fields: ['lastHeartbeatTime']
|
||||
},
|
||||
|
||||
]
|
||||
});
|
||||
|
||||
// device_status.sync({ force: true });
|
||||
|
||||
return device_status
|
||||
|
||||
// device_status.sync({ force: true
|
||||
};
|
||||
|
||||
243
api/model/job_postings.js
Normal file
243
api/model/job_postings.js
Normal file
@@ -0,0 +1,243 @@
|
||||
const Sequelize = require('sequelize');
|
||||
|
||||
/**
|
||||
* 岗位信息表模型
|
||||
* 存储从招聘平台获取的岗位信息及AI分析结果
|
||||
*/
|
||||
module.exports = (db) => {
|
||||
const job_postings = db.define("job_postings", {
|
||||
sn_code: {
|
||||
comment: '设备SN码',
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
// 岗位基础信息
|
||||
encryptBossId: {
|
||||
comment: 'Boss加密ID',
|
||||
type: Sequelize.STRING(100),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
securityId: {
|
||||
comment: '安全ID',
|
||||
type: Sequelize.STRING(255),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
jobId: {
|
||||
comment: '岗位ID',
|
||||
type: Sequelize.STRING(100),
|
||||
allowNull: false,
|
||||
defaultValue: ''
|
||||
},
|
||||
jobTitle: {
|
||||
comment: '岗位名称',
|
||||
type: Sequelize.STRING(200),
|
||||
allowNull: false,
|
||||
defaultValue: ''
|
||||
},
|
||||
companyId: {
|
||||
comment: '公司ID',
|
||||
type: Sequelize.STRING(100),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
|
||||
companyName: {
|
||||
comment: '公司名称',
|
||||
type: Sequelize.STRING(200),
|
||||
allowNull: false,
|
||||
defaultValue: ''
|
||||
},
|
||||
companySize: {
|
||||
comment: '公司规模',
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
companyIndustry: {
|
||||
comment: '公司行业',
|
||||
type: Sequelize.STRING(100),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
salary: {
|
||||
comment: '薪资范围',
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
jobRequirements: {
|
||||
comment: '岗位要求',
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
jobDescription: {
|
||||
comment: '岗位描述',
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
location: {
|
||||
comment: '工作地点',
|
||||
type: Sequelize.STRING(100),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
|
||||
// 经度
|
||||
longitude: {
|
||||
comment: '经度',
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
// 纬度
|
||||
latitude: {
|
||||
comment: '纬度',
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
|
||||
experience: {
|
||||
comment: '工作经验要求',
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
education: {
|
||||
comment: '学历要求',
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
// AI分析结果
|
||||
aiMatchScore: {
|
||||
comment: 'AI匹配度评分',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
defaultValue: 0
|
||||
},
|
||||
aiSkillMatch: {
|
||||
comment: 'AI技能匹配度',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
defaultValue: 0
|
||||
},
|
||||
aiExperienceMatch: {
|
||||
comment: 'AI经验匹配度',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
defaultValue: 0
|
||||
},
|
||||
aiSalaryReasonable: {
|
||||
comment: 'AI薪资合理性评分',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
defaultValue: 0
|
||||
},
|
||||
aiCompanyQuality: {
|
||||
comment: 'AI公司质量评分',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
defaultValue: 0
|
||||
},
|
||||
isOutsourcing: {
|
||||
comment: '是否外包岗位',
|
||||
type: Sequelize.BOOLEAN,
|
||||
allowNull: true,
|
||||
defaultValue: false
|
||||
},
|
||||
aiAnalysis: {
|
||||
comment: 'AI详细分析结果(JSON)',
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
outsourcingAnalysis: {
|
||||
comment: '外包识别分析结果',
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
// 投递状态
|
||||
applyStatus: {
|
||||
comment: '投递状态: pending-待投递, applied-已投递, rejected-被拒绝, accepted-已接受',
|
||||
type: Sequelize.STRING(20),
|
||||
allowNull: true,
|
||||
defaultValue: 'pending'
|
||||
},
|
||||
applyTime: {
|
||||
comment: '投递时间',
|
||||
type: Sequelize.DATE,
|
||||
allowNull: true
|
||||
},
|
||||
chatStatus: {
|
||||
comment: '聊天状态: none-未聊天, sent-已发送, replied-已回复',
|
||||
type: Sequelize.STRING(20),
|
||||
allowNull: true,
|
||||
defaultValue: 'none'
|
||||
},
|
||||
chatTime: {
|
||||
comment: '聊天时间',
|
||||
type: Sequelize.DATE,
|
||||
allowNull: true
|
||||
},
|
||||
// 关联信息
|
||||
platform: {
|
||||
comment: '平台: boss-Boss直聘, liepin-猎聘',
|
||||
type: Sequelize.STRING(20),
|
||||
allowNull: false,
|
||||
defaultValue: 'boss'
|
||||
},
|
||||
|
||||
keyword: {
|
||||
comment: '搜索关键词',
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
// 其他信息
|
||||
originalData: {
|
||||
comment: '原始数据(JSON)',
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
}
|
||||
}, {
|
||||
timestamps: true,
|
||||
createdAt: 'create_time',
|
||||
updatedAt: 'last_modify_time',
|
||||
indexes: [
|
||||
{
|
||||
unique: false,
|
||||
fields: ['jobId']
|
||||
},
|
||||
{
|
||||
unique: false,
|
||||
fields: ['encryptBossId']
|
||||
},
|
||||
{
|
||||
unique: false,
|
||||
fields: ['sn_code']
|
||||
},
|
||||
{
|
||||
unique: false,
|
||||
fields: ['applyStatus']
|
||||
},
|
||||
{
|
||||
unique: false,
|
||||
fields: ['aiMatchScore']
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
// job_postings.sync({ force: true });
|
||||
|
||||
return job_postings
|
||||
|
||||
// job_postings.sync({ force: true
|
||||
};
|
||||
61
api/model/job_types.js
Normal file
61
api/model/job_types.js
Normal file
@@ -0,0 +1,61 @@
|
||||
const Sequelize = require('sequelize');
|
||||
|
||||
/**
|
||||
* 职位类型表模型
|
||||
* 存储不同职位类型的技能关键词和排除关键词配置
|
||||
*/
|
||||
module.exports = (db) => {
|
||||
const job_types = db.define("job_types", {
|
||||
name: {
|
||||
comment: '职位类型名称(如:前端开发、后端开发、全栈开发等)',
|
||||
type: Sequelize.STRING(100),
|
||||
allowNull: false,
|
||||
defaultValue: ''
|
||||
},
|
||||
description: {
|
||||
comment: '职位类型描述',
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
commonSkills: {
|
||||
comment: '常见技能关键词(JSON数组)',
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true,
|
||||
defaultValue: '[]'
|
||||
},
|
||||
excludeKeywords: {
|
||||
comment: '排除关键词(JSON数组)',
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true,
|
||||
defaultValue: '[]'
|
||||
},
|
||||
is_enabled: {
|
||||
comment: '是否启用(1=启用,0=禁用)',
|
||||
type: Sequelize.TINYINT(1),
|
||||
allowNull: false,
|
||||
defaultValue: 1
|
||||
},
|
||||
sort_order: {
|
||||
comment: '排序顺序',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
defaultValue: 0
|
||||
}
|
||||
}, {
|
||||
timestamps: false,
|
||||
indexes: [
|
||||
{
|
||||
unique: false,
|
||||
fields: ['is_enabled']
|
||||
},
|
||||
{
|
||||
unique: false,
|
||||
fields: ['name']
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
return job_types;
|
||||
}
|
||||
|
||||
153
api/model/pla_account.js
Normal file
153
api/model/pla_account.js
Normal file
@@ -0,0 +1,153 @@
|
||||
const dayjs = require("dayjs");
|
||||
const Sequelize = require('sequelize');
|
||||
|
||||
module.exports = (db) => {
|
||||
const pla_account = db.define("pla_account", {
|
||||
name: {
|
||||
comment: '账户名',
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: false,
|
||||
defaultValue: ''
|
||||
},
|
||||
sn_code: {
|
||||
comment: '唯一标识码',
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: false,
|
||||
defaultValue: ''
|
||||
},
|
||||
platform_type: {
|
||||
comment: '平台',
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: false,
|
||||
defaultValue: ''
|
||||
},
|
||||
login_name: {
|
||||
comment: '登录名',
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: false,
|
||||
defaultValue: ''
|
||||
},
|
||||
pwd: {
|
||||
comment: '密码',
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: false,
|
||||
defaultValue: ''
|
||||
},
|
||||
keyword: {
|
||||
comment: '关键词',
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: false,
|
||||
defaultValue: ''
|
||||
},
|
||||
|
||||
is_enabled: {
|
||||
comment: '账号启用状态(1=启用,0=禁用)',
|
||||
type: Sequelize.TINYINT(1),
|
||||
allowNull: false,
|
||||
defaultValue: 1
|
||||
},
|
||||
job_type_id: {
|
||||
comment: '职位类型ID(关联 job_types 表)',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
defaultValue: null
|
||||
},
|
||||
|
||||
//优先 排序 ,距离,薪资,工作年限 ,学历
|
||||
is_salary_priority: {
|
||||
comment: '排序优先级',
|
||||
type: Sequelize.JSON(),
|
||||
allowNull: false,
|
||||
get: function () {
|
||||
return JSON.parse(this.getDataValue('is_salary_priority'));
|
||||
},
|
||||
set: function (value) {
|
||||
this.setDataValue('is_salary_priority', JSON.stringify(value));
|
||||
},
|
||||
defaultValue: [ { "key": "distance", "weight": 50 }, { "key": "salary", "weight": 20 }, { "key": "work_years", "weight": 10 }, { "key": "education", "weight": 20} ]
|
||||
},
|
||||
|
||||
|
||||
// 用户地址
|
||||
user_address: {
|
||||
comment: '用户地址',
|
||||
type: Sequelize.STRING(200),
|
||||
allowNull: false,
|
||||
defaultValue: ''
|
||||
},
|
||||
// 用户经度
|
||||
user_longitude: {
|
||||
comment: '用户经度',
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: false,
|
||||
defaultValue: ''
|
||||
},
|
||||
// 用户纬度
|
||||
user_latitude: {
|
||||
comment: '用户纬度',
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: false,
|
||||
defaultValue: ''
|
||||
},
|
||||
|
||||
// 自动投递相关配置
|
||||
auto_deliver: {
|
||||
comment: '自动投递开关',
|
||||
type: Sequelize.TINYINT(1),
|
||||
allowNull: false,
|
||||
defaultValue: 0
|
||||
},
|
||||
min_salary: {
|
||||
comment: '最低薪资(单位:元)',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
defaultValue: 0
|
||||
},
|
||||
max_salary: {
|
||||
comment: '最高薪资(单位:元)',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
defaultValue: 0
|
||||
},
|
||||
// 自动沟通相关配置
|
||||
auto_chat: {
|
||||
comment: '自动沟通开关',
|
||||
type: Sequelize.TINYINT(1),
|
||||
allowNull: false,
|
||||
defaultValue: 0
|
||||
},
|
||||
chat_interval: {
|
||||
comment: '沟通间隔(单位:分钟)',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
defaultValue: 30
|
||||
},
|
||||
auto_reply: {
|
||||
comment: '自动回复开关',
|
||||
type: Sequelize.TINYINT(1),
|
||||
allowNull: false,
|
||||
defaultValue: 0
|
||||
},
|
||||
// 自动活跃相关配置
|
||||
auto_active: {
|
||||
comment: '自动活跃开关',
|
||||
type: Sequelize.TINYINT(1),
|
||||
allowNull: false,
|
||||
defaultValue: 0
|
||||
},
|
||||
// 是否沟通外包岗位
|
||||
is_chat_outsourcing: {
|
||||
comment: '是否沟通外包岗位',
|
||||
type: Sequelize.TINYINT(1),
|
||||
allowNull: false,
|
||||
defaultValue: 0
|
||||
},
|
||||
|
||||
|
||||
});
|
||||
|
||||
//pla_account.sync({ force: true });
|
||||
return pla_account
|
||||
|
||||
|
||||
};
|
||||
281
api/model/resume_info.js
Normal file
281
api/model/resume_info.js
Normal file
@@ -0,0 +1,281 @@
|
||||
const Sequelize = require('sequelize');
|
||||
|
||||
/**
|
||||
* 简历信息表模型
|
||||
* 存储用户简历的核心要素和分析结果
|
||||
*/
|
||||
module.exports = (db) => {
|
||||
const resume_info = db.define("resume_info", {
|
||||
// 基本信息
|
||||
sn_code: {
|
||||
comment: '设备SN码',
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: false,
|
||||
defaultValue: ''
|
||||
},
|
||||
account_id: {
|
||||
comment: '用户ID',
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: false,
|
||||
defaultValue: ''
|
||||
},
|
||||
platform: {
|
||||
comment: '平台: boss-Boss直聘, liepin-猎聘',
|
||||
type: Sequelize.STRING(20),
|
||||
allowNull: false,
|
||||
defaultValue: 'boss'
|
||||
},
|
||||
resumeId: {
|
||||
comment: '简历ID',
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: false,
|
||||
defaultValue: ''
|
||||
},
|
||||
|
||||
// 个人信息
|
||||
fullName: {
|
||||
comment: '姓名',
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
gender: {
|
||||
comment: '性别',
|
||||
type: Sequelize.STRING(10),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
age: {
|
||||
comment: '年龄',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
defaultValue: 0
|
||||
},
|
||||
phone: {
|
||||
comment: '电话',
|
||||
type: Sequelize.STRING(20),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
email: {
|
||||
comment: '邮箱',
|
||||
type: Sequelize.STRING(100),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
location: {
|
||||
comment: '所在地',
|
||||
type: Sequelize.STRING(100),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
|
||||
// 教育背景
|
||||
education: {
|
||||
comment: '学历',
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
major: {
|
||||
comment: '专业',
|
||||
type: Sequelize.STRING(100),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
school: {
|
||||
comment: '毕业院校',
|
||||
type: Sequelize.STRING(200),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
graduationYear: {
|
||||
comment: '毕业年份',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
defaultValue: 0
|
||||
},
|
||||
|
||||
// 工作经验
|
||||
workYears: {
|
||||
comment: '工作年限',
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
currentPosition: {
|
||||
comment: '当前职位',
|
||||
type: Sequelize.STRING(100),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
currentCompany: {
|
||||
comment: '当前公司',
|
||||
type: Sequelize.STRING(200),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
currentSalary: {
|
||||
comment: '当前薪资',
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
|
||||
// 期望信息
|
||||
expectedPosition: {
|
||||
comment: '期望职位',
|
||||
type: Sequelize.STRING(100),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
expectedSalary: {
|
||||
comment: '期望薪资',
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
expectedLocation: {
|
||||
comment: '期望工作地点',
|
||||
type: Sequelize.STRING(100),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
expectedIndustry: {
|
||||
comment: '期望行业',
|
||||
type: Sequelize.STRING(100),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
|
||||
// 技能和专长
|
||||
skills: {
|
||||
comment: '技能标签(JSON数组)',
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
skillDescription: {
|
||||
comment: '技能描述',
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
certifications: {
|
||||
comment: '证书资质(JSON数组)',
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
|
||||
// 项目经验
|
||||
projectExperience: {
|
||||
comment: '项目经验(JSON数组)',
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
|
||||
// 工作经历
|
||||
workExperience: {
|
||||
comment: '工作经历(JSON数组)',
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
|
||||
// AI分析结果
|
||||
aiSkillTags: {
|
||||
comment: 'AI提取的技能标签(JSON数组)',
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
aiStrengths: {
|
||||
comment: 'AI分析的优势',
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
aiWeaknesses: {
|
||||
comment: 'AI分析的劣势',
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
aiCareerSuggestion: {
|
||||
comment: 'AI职业建议',
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
aiCompetitiveness: {
|
||||
comment: 'AI竞争力评分(0-100)',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
defaultValue: 0
|
||||
},
|
||||
|
||||
// 简历内容
|
||||
resumeContent: {
|
||||
comment: '简历完整内容(HTML或文本)',
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
|
||||
// 原始数据
|
||||
originalData: {
|
||||
comment: '原始数据(JSON)',
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
|
||||
// 状态信息
|
||||
isActive: {
|
||||
comment: '是否活跃简历',
|
||||
type: Sequelize.BOOLEAN,
|
||||
allowNull: true,
|
||||
defaultValue: true
|
||||
},
|
||||
isPublic: {
|
||||
comment: '是否公开',
|
||||
type: Sequelize.BOOLEAN,
|
||||
allowNull: true,
|
||||
defaultValue: true
|
||||
},
|
||||
|
||||
syncTime: {
|
||||
comment: '同步时间',
|
||||
type: Sequelize.DATE,
|
||||
allowNull: true,
|
||||
defaultValue: Sequelize.NOW
|
||||
}
|
||||
}, {
|
||||
timestamps: true,
|
||||
createdAt: 'create_time',
|
||||
updatedAt: 'last_modify_time',
|
||||
indexes: [
|
||||
{
|
||||
unique: false,
|
||||
fields: ['sn_code']
|
||||
},
|
||||
{
|
||||
unique: false,
|
||||
fields: ['platform']
|
||||
},
|
||||
{
|
||||
unique: false,
|
||||
fields: ['isActive']
|
||||
},
|
||||
|
||||
]
|
||||
});
|
||||
|
||||
// resume_info.sync({ force: true });
|
||||
return resume_info
|
||||
|
||||
|
||||
};
|
||||
|
||||
129
api/model/system_config.js
Normal file
129
api/model/system_config.js
Normal file
@@ -0,0 +1,129 @@
|
||||
const Sequelize = require('sequelize');
|
||||
|
||||
/**
|
||||
* 系统配置表模型
|
||||
* 存储系统的各种配置参数
|
||||
*/
|
||||
module.exports = (db) => {
|
||||
const system_config= db.define("system_config", {
|
||||
// 配置基本信息
|
||||
configKey: {
|
||||
comment: '配置键(唯一)',
|
||||
type: Sequelize.STRING(100),
|
||||
allowNull: false,
|
||||
unique: true
|
||||
},
|
||||
configValue: {
|
||||
comment: '配置值',
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
configType: {
|
||||
comment: '配置类型: string-字符串, number-数字, boolean-布尔, json-JSON对象',
|
||||
type: Sequelize.STRING(20),
|
||||
allowNull: false,
|
||||
defaultValue: 'string'
|
||||
},
|
||||
|
||||
// 分类信息
|
||||
category: {
|
||||
comment: '配置分类: system-系统, ai-AI服务, mqtt-MQTT, schedule-调度, platform-平台',
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: false,
|
||||
defaultValue: 'system'
|
||||
},
|
||||
|
||||
// 描述信息
|
||||
configName: {
|
||||
comment: '配置名称',
|
||||
type: Sequelize.STRING(200),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
description: {
|
||||
comment: '配置描述',
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
|
||||
// 默认值
|
||||
defaultValue: {
|
||||
comment: '默认值',
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
|
||||
// 验证规则
|
||||
validationRule: {
|
||||
comment: '验证规则(JSON)',
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
|
||||
// 状态信息
|
||||
isActive: {
|
||||
comment: '是否启用',
|
||||
type: Sequelize.BOOLEAN,
|
||||
allowNull: false,
|
||||
defaultValue: true
|
||||
},
|
||||
isSystem: {
|
||||
comment: '是否系统配置(系统配置不可删除)',
|
||||
type: Sequelize.BOOLEAN,
|
||||
allowNull: false,
|
||||
defaultValue: false
|
||||
},
|
||||
isEncrypted: {
|
||||
comment: '是否加密存储',
|
||||
type: Sequelize.BOOLEAN,
|
||||
allowNull: false,
|
||||
defaultValue: false
|
||||
},
|
||||
|
||||
// 排序和显示
|
||||
sortOrder: {
|
||||
comment: '排序顺序',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
defaultValue: 0
|
||||
},
|
||||
isVisible: {
|
||||
comment: '是否在界面显示',
|
||||
type: Sequelize.BOOLEAN,
|
||||
allowNull: false,
|
||||
defaultValue: true
|
||||
},
|
||||
|
||||
|
||||
}, {
|
||||
timestamps: false,
|
||||
indexes: [
|
||||
{
|
||||
unique: true,
|
||||
fields: ['configKey']
|
||||
},
|
||||
{
|
||||
unique: false,
|
||||
fields: ['category']
|
||||
},
|
||||
{
|
||||
unique: false,
|
||||
fields: ['isActive']
|
||||
},
|
||||
{
|
||||
unique: false,
|
||||
fields: ['sortOrder']
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
// system_config.sync({ force: true });
|
||||
|
||||
return system_config
|
||||
|
||||
};
|
||||
|
||||
125
api/model/task_commands.js
Normal file
125
api/model/task_commands.js
Normal file
@@ -0,0 +1,125 @@
|
||||
const dayjs = require("dayjs");
|
||||
const Sequelize = require('sequelize');
|
||||
|
||||
module.exports = (db) => {
|
||||
const task_commands = db.define("task_commands", {
|
||||
task_id: {
|
||||
comment: '任务ID',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
defaultValue: null
|
||||
// 不添加外键关联,避免数据库层面的约束
|
||||
},
|
||||
command_type: {
|
||||
comment: '指令类型',
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: false,
|
||||
defaultValue: ''
|
||||
},
|
||||
command_name: {
|
||||
comment: '指令名称',
|
||||
type: Sequelize.STRING(100),
|
||||
allowNull: false,
|
||||
defaultValue: ''
|
||||
},
|
||||
command_params: {
|
||||
comment: '指令参数',
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true,
|
||||
defaultValue: null
|
||||
},
|
||||
status: {
|
||||
comment: '指令状态',
|
||||
type: Sequelize.ENUM('pending', 'running', 'completed', 'failed', 'cancelled'),
|
||||
allowNull: false,
|
||||
defaultValue: 'pending'
|
||||
},
|
||||
priority: {
|
||||
comment: '优先级',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
defaultValue: 1
|
||||
},
|
||||
sequence: {
|
||||
comment: '执行顺序',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
defaultValue: 1
|
||||
},
|
||||
retry_count: {
|
||||
comment: '重试次数',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
defaultValue: 0
|
||||
},
|
||||
max_retries: {
|
||||
comment: '最大重试次数',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
defaultValue: 3
|
||||
},
|
||||
start_time: {
|
||||
comment: '开始时间',
|
||||
type: Sequelize.DATE,
|
||||
allowNull: true,
|
||||
defaultValue: null
|
||||
},
|
||||
end_time: {
|
||||
comment: '结束时间',
|
||||
type: Sequelize.DATE,
|
||||
allowNull: true,
|
||||
defaultValue: null
|
||||
},
|
||||
duration: {
|
||||
comment: '执行时长(毫秒)',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
defaultValue: null
|
||||
},
|
||||
result: {
|
||||
comment: '执行结果',
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true,
|
||||
defaultValue: null
|
||||
},
|
||||
error_message: {
|
||||
comment: '错误信息',
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true,
|
||||
defaultValue: null
|
||||
},
|
||||
error_stack: {
|
||||
comment: '错误堆栈',
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true,
|
||||
defaultValue: null
|
||||
},
|
||||
progress: {
|
||||
comment: '执行进度(0-100)',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
defaultValue: 0
|
||||
},
|
||||
}, {
|
||||
tableName: 'task_commands',
|
||||
indexes: [
|
||||
{
|
||||
fields: ['task_id']
|
||||
},
|
||||
{
|
||||
fields: ['status']
|
||||
},
|
||||
{
|
||||
fields: ['command_type']
|
||||
},
|
||||
{
|
||||
fields: ['priority', 'sequence']
|
||||
},
|
||||
|
||||
]
|
||||
});
|
||||
|
||||
// task_commands.sync({ force: true });
|
||||
|
||||
return task_commands;
|
||||
};
|
||||
190
api/model/task_status.js
Normal file
190
api/model/task_status.js
Normal file
@@ -0,0 +1,190 @@
|
||||
const Sequelize = require('sequelize');
|
||||
|
||||
/**
|
||||
* 任务状态表模型
|
||||
* 记录每个设备的任务执行状态和历史
|
||||
*/
|
||||
module.exports = (db) => {
|
||||
const task_status= db.define("task_status", {
|
||||
// 框架自动创建自增id字段作为主键
|
||||
// 任务基本信息
|
||||
sn_code: {
|
||||
comment: '设备SN码',
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: false,
|
||||
defaultValue: ''
|
||||
},
|
||||
taskType: {
|
||||
comment: '任务类型: get_login_qr_code-登录检查, get_resume-获取简历, search_jobs-搜索岗位, get_job_list-获取岗位列表, auto_deliver-自动投递, chat-聊天, apply-投递',
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: false,
|
||||
defaultValue: ''
|
||||
},
|
||||
taskName: {
|
||||
comment: '任务名称',
|
||||
type: Sequelize.STRING(200),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
// 任务状态
|
||||
status: {
|
||||
comment: '任务状态: pending-待执行, running-执行中, completed-已完成, failed-失败, timeout-超时, cancelled-已取消',
|
||||
type: Sequelize.STRING(20),
|
||||
allowNull: false,
|
||||
defaultValue: 'pending'
|
||||
},
|
||||
progress: {
|
||||
comment: '任务进度(0-100)',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
defaultValue: 0
|
||||
},
|
||||
currentStep: {
|
||||
comment: '当前执行步骤',
|
||||
type: Sequelize.STRING(100),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
totalSteps: {
|
||||
comment: '总步骤数',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
defaultValue: 0
|
||||
},
|
||||
// 任务参数
|
||||
taskParams: {
|
||||
comment: '任务参数(JSON)',
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
// 执行结果
|
||||
result: {
|
||||
comment: '执行结果(JSON)',
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
errorMessage: {
|
||||
comment: '错误信息',
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
errorStack: {
|
||||
comment: '错误堆栈',
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
// 重试信息
|
||||
retryCount: {
|
||||
comment: '重试次数',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
defaultValue: 0
|
||||
},
|
||||
maxRetries: {
|
||||
comment: '最大重试次数',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
defaultValue: 3
|
||||
},
|
||||
startTime: {
|
||||
comment: '开始执行时间',
|
||||
type: Sequelize.DATE,
|
||||
allowNull: true
|
||||
},
|
||||
endTime: {
|
||||
comment: '结束时间',
|
||||
type: Sequelize.DATE,
|
||||
allowNull: true
|
||||
},
|
||||
duration: {
|
||||
comment: '执行时长(毫秒)',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
defaultValue: 0
|
||||
},
|
||||
// 统计信息
|
||||
jobsSearched: {
|
||||
comment: '搜索的岗位数',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
defaultValue: 0
|
||||
},
|
||||
jobsFiltered: {
|
||||
comment: '筛选后的岗位数',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
defaultValue: 0
|
||||
},
|
||||
chatsProcessed: {
|
||||
comment: '处理的聊天数',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
defaultValue: 0
|
||||
},
|
||||
appliesSubmitted: {
|
||||
comment: '投递的简历数',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
defaultValue: 0
|
||||
},
|
||||
// 其他信息
|
||||
platform: {
|
||||
comment: '平台: boss-Boss直聘, liepin-猎聘',
|
||||
type: Sequelize.STRING(20),
|
||||
allowNull: true,
|
||||
defaultValue: 'boss'
|
||||
},
|
||||
keyword: {
|
||||
comment: '搜索关键词',
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
priority: {
|
||||
comment: '任务优先级(1-10,数字越大优先级越高)',
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
defaultValue: 5
|
||||
},
|
||||
scheduledTime: {
|
||||
comment: '计划执行时间',
|
||||
type: Sequelize.DATE,
|
||||
allowNull: true
|
||||
},
|
||||
notes: {
|
||||
comment: '备注',
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
}
|
||||
}, {
|
||||
timestamps: false,
|
||||
indexes: [
|
||||
{
|
||||
unique: false,
|
||||
fields: ['sn_code']
|
||||
},
|
||||
{
|
||||
unique: false,
|
||||
fields: ['status']
|
||||
},
|
||||
{
|
||||
unique: false,
|
||||
fields: ['taskType']
|
||||
},
|
||||
{
|
||||
unique: false,
|
||||
fields: ['priority']
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
// task_status.sync({ force: true });
|
||||
|
||||
return task_status
|
||||
|
||||
};
|
||||
Reference in New Issue
Block a user