1
This commit is contained in:
211
api/controller_front/apply.js
Normal file
211
api/controller_front/apply.js
Normal file
@@ -0,0 +1,211 @@
|
|||||||
|
/**
|
||||||
|
* 投递记录管理控制器(客户端接口)
|
||||||
|
* 提供客户端调用的投递记录相关接口
|
||||||
|
*/
|
||||||
|
|
||||||
|
const Framework = require("../../framework/node-core-framework.js");
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /api/apply/list:
|
||||||
|
* post:
|
||||||
|
* summary: 获取投递记录列表
|
||||||
|
* description: 根据设备SN码分页获取投递记录
|
||||||
|
* tags: [前端-投递管理]
|
||||||
|
* requestBody:
|
||||||
|
* required: true
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* type: object
|
||||||
|
* properties:
|
||||||
|
* sn_code:
|
||||||
|
* type: string
|
||||||
|
* description: 设备SN码
|
||||||
|
* seachOption:
|
||||||
|
* type: object
|
||||||
|
* description: 搜索条件
|
||||||
|
* pageOption:
|
||||||
|
* type: object
|
||||||
|
* description: 分页选项
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: 获取成功
|
||||||
|
*/
|
||||||
|
'POST /apply/list': async (ctx) => {
|
||||||
|
try {
|
||||||
|
const models = Framework.getModels();
|
||||||
|
const { apply_records, op } = models;
|
||||||
|
const body = ctx.getBody();
|
||||||
|
|
||||||
|
// 从query或body中获取sn_code,优先从query获取
|
||||||
|
const sn_code = ctx.query?.sn_code || body.sn_code;
|
||||||
|
|
||||||
|
if (!sn_code) {
|
||||||
|
return ctx.fail('请提供设备SN码');
|
||||||
|
}
|
||||||
|
|
||||||
|
const seachOption = body.seachOption || {};
|
||||||
|
const pageOption = body.pageOption || {};
|
||||||
|
|
||||||
|
// 获取分页参数
|
||||||
|
const page = pageOption.page || 1;
|
||||||
|
const pageSize = pageOption.pageSize || 20;
|
||||||
|
const limit = pageSize;
|
||||||
|
const offset = (page - 1) * pageSize;
|
||||||
|
|
||||||
|
const where = { sn_code };
|
||||||
|
|
||||||
|
// 平台筛选
|
||||||
|
if (seachOption.platform) {
|
||||||
|
where.platform = seachOption.platform;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 投递状态筛选
|
||||||
|
if (seachOption.applyStatus) {
|
||||||
|
where.applyStatus = seachOption.applyStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 反馈状态筛选
|
||||||
|
if (seachOption.feedbackStatus) {
|
||||||
|
where.feedbackStatus = seachOption.feedbackStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 搜索:岗位名称、公司名称
|
||||||
|
if (seachOption.key && seachOption.value) {
|
||||||
|
const key = seachOption.key;
|
||||||
|
const value = seachOption.value;
|
||||||
|
|
||||||
|
if (key === 'jobTitle') {
|
||||||
|
where.jobTitle = { [op.like]: `%${value}%` };
|
||||||
|
} else if (key === 'companyName') {
|
||||||
|
where.companyName = { [op.like]: `%${value}%` };
|
||||||
|
} else {
|
||||||
|
// 默认搜索岗位名称或公司名称
|
||||||
|
where[op.or] = [
|
||||||
|
{ jobTitle: { [op.like]: `%${value}%` } },
|
||||||
|
{ companyName: { [op.like]: `%${value}%` } }
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await apply_records.findAndCountAll({
|
||||||
|
where,
|
||||||
|
limit,
|
||||||
|
offset,
|
||||||
|
order: [['applyTime', 'DESC']]
|
||||||
|
});
|
||||||
|
|
||||||
|
return ctx.success({
|
||||||
|
count: result.count,
|
||||||
|
total: result.count,
|
||||||
|
rows: result.rows,
|
||||||
|
list: result.rows
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取投递记录列表失败:', error);
|
||||||
|
return ctx.fail('获取投递记录列表失败: ' + error.message);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /api/apply/statistics:
|
||||||
|
* get:
|
||||||
|
* summary: 获取投递统计
|
||||||
|
* description: 根据设备SN码获取投递统计数据
|
||||||
|
* tags: [前端-投递管理]
|
||||||
|
* parameters:
|
||||||
|
* - in: query
|
||||||
|
* name: sn_code
|
||||||
|
* required: true
|
||||||
|
* schema:
|
||||||
|
* type: string
|
||||||
|
* description: 设备SN码
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: 获取成功
|
||||||
|
*/
|
||||||
|
'GET /apply/statistics': async (ctx) => {
|
||||||
|
try {
|
||||||
|
const models = Framework.getModels();
|
||||||
|
const { apply_records } = models;
|
||||||
|
const { sn_code } = ctx.query;
|
||||||
|
const final_sn_code = sn_code;
|
||||||
|
|
||||||
|
if (!final_sn_code) {
|
||||||
|
return ctx.fail('请提供设备SN码');
|
||||||
|
}
|
||||||
|
|
||||||
|
const [
|
||||||
|
totalCount,
|
||||||
|
successCount,
|
||||||
|
failedCount,
|
||||||
|
pendingCount,
|
||||||
|
interviewCount
|
||||||
|
] = await Promise.all([
|
||||||
|
apply_records.count({ where: { sn_code: final_sn_code } }),
|
||||||
|
apply_records.count({ where: { sn_code: final_sn_code, applyStatus: 'success' } }),
|
||||||
|
apply_records.count({ where: { sn_code: final_sn_code, applyStatus: 'failed' } }),
|
||||||
|
apply_records.count({ where: { sn_code: final_sn_code, applyStatus: 'pending' } }),
|
||||||
|
apply_records.count({ where: { sn_code: final_sn_code, feedbackStatus: 'interview' } })
|
||||||
|
]);
|
||||||
|
|
||||||
|
return ctx.success({
|
||||||
|
totalCount,
|
||||||
|
successCount,
|
||||||
|
failedCount,
|
||||||
|
pendingCount,
|
||||||
|
interviewCount,
|
||||||
|
successRate: totalCount > 0 ? ((successCount / totalCount) * 100).toFixed(2) : 0,
|
||||||
|
interviewRate: totalCount > 0 ? ((interviewCount / totalCount) * 100).toFixed(2) : 0
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取投递统计失败:', error);
|
||||||
|
return ctx.fail('获取投递统计失败: ' + error.message);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /api/apply/detail:
|
||||||
|
* get:
|
||||||
|
* summary: 获取投递记录详情
|
||||||
|
* description: 根据投递ID获取详细信息
|
||||||
|
* tags: [前端-投递管理]
|
||||||
|
* parameters:
|
||||||
|
* - in: query
|
||||||
|
* name: applyId
|
||||||
|
* required: true
|
||||||
|
* schema:
|
||||||
|
* type: string
|
||||||
|
* description: 投递记录ID
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: 获取成功
|
||||||
|
*/
|
||||||
|
'GET /apply/detail': async (ctx) => {
|
||||||
|
try {
|
||||||
|
const models = Framework.getModels();
|
||||||
|
const { apply_records } = models;
|
||||||
|
const { applyId } = ctx.query;
|
||||||
|
|
||||||
|
if (!applyId) {
|
||||||
|
return ctx.fail('投递记录ID不能为空');
|
||||||
|
}
|
||||||
|
|
||||||
|
const record = await apply_records.findOne({ where: { applyId } });
|
||||||
|
|
||||||
|
if (!record) {
|
||||||
|
return ctx.fail('投递记录不存在');
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx.success(record);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取投递记录详情失败:', error);
|
||||||
|
return ctx.fail('获取投递记录详情失败: ' + error.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
159
api/controller_front/feedback.js
Normal file
159
api/controller_front/feedback.js
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
/**
|
||||||
|
* 意见反馈管理控制器(客户端接口)
|
||||||
|
* 提供客户端调用的意见反馈相关接口
|
||||||
|
*/
|
||||||
|
|
||||||
|
const Framework = require("../../framework/node-core-framework.js");
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /api/feedback/submit:
|
||||||
|
* post:
|
||||||
|
* summary: 提交反馈
|
||||||
|
* description: 提交用户反馈
|
||||||
|
* tags: [前端-意见反馈]
|
||||||
|
* requestBody:
|
||||||
|
* required: true
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* type: object
|
||||||
|
* required:
|
||||||
|
* - type
|
||||||
|
* - content
|
||||||
|
* properties:
|
||||||
|
* type:
|
||||||
|
* type: string
|
||||||
|
* description: 反馈类型
|
||||||
|
* content:
|
||||||
|
* type: string
|
||||||
|
* description: 反馈内容
|
||||||
|
* contact:
|
||||||
|
* type: string
|
||||||
|
* description: 联系方式(可选)
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: 提交成功
|
||||||
|
*/
|
||||||
|
'POST /feedback/submit': async (ctx) => {
|
||||||
|
try {
|
||||||
|
// 从body中获取user_id和sn_code,实际应该从token中解析
|
||||||
|
const body = ctx.getBody();
|
||||||
|
const user_id = body.user_id;
|
||||||
|
const sn_code = body.sn_code;
|
||||||
|
|
||||||
|
if (!user_id) {
|
||||||
|
return ctx.fail('请先登录');
|
||||||
|
}
|
||||||
|
const { type, content, contact } = body;
|
||||||
|
|
||||||
|
if (!type || !content) {
|
||||||
|
return ctx.fail('反馈类型和内容不能为空');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 这里可以将反馈保存到数据库,暂时只返回成功
|
||||||
|
// 如果需要保存,可以创建一个 feedback 表
|
||||||
|
|
||||||
|
return ctx.success({
|
||||||
|
message: '反馈提交成功,感谢您的反馈!',
|
||||||
|
feedbackId: `FB${Date.now()}`
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('提交反馈失败:', error);
|
||||||
|
return ctx.fail('提交反馈失败: ' + error.message);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /api/feedback/list:
|
||||||
|
* post:
|
||||||
|
* summary: 获取反馈列表
|
||||||
|
* description: 根据用户ID获取反馈列表
|
||||||
|
* tags: [前端-意见反馈]
|
||||||
|
* requestBody:
|
||||||
|
* required: true
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* type: object
|
||||||
|
* properties:
|
||||||
|
* page:
|
||||||
|
* type: integer
|
||||||
|
* description: 页码
|
||||||
|
* pageSize:
|
||||||
|
* type: integer
|
||||||
|
* description: 每页数量
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: 获取成功
|
||||||
|
*/
|
||||||
|
'POST /feedback/list': async (ctx) => {
|
||||||
|
try {
|
||||||
|
// 从body中获取user_id,实际应该从token中解析
|
||||||
|
const body = ctx.getBody();
|
||||||
|
const user_id = body.user_id;
|
||||||
|
|
||||||
|
if (!user_id) {
|
||||||
|
return ctx.fail('请先登录');
|
||||||
|
}
|
||||||
|
const page = body.page || 1;
|
||||||
|
const pageSize = body.pageSize || 20;
|
||||||
|
|
||||||
|
// 这里可以从数据库查询反馈列表,暂时返回空列表
|
||||||
|
return ctx.success({
|
||||||
|
count: 0,
|
||||||
|
total: 0,
|
||||||
|
rows: [],
|
||||||
|
list: []
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取反馈列表失败:', error);
|
||||||
|
return ctx.fail('获取反馈列表失败: ' + error.message);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /api/feedback/detail:
|
||||||
|
* get:
|
||||||
|
* summary: 获取反馈详情
|
||||||
|
* description: 根据反馈ID获取详细信息
|
||||||
|
* tags: [前端-意见反馈]
|
||||||
|
* parameters:
|
||||||
|
* - in: query
|
||||||
|
* name: feedbackId
|
||||||
|
* required: true
|
||||||
|
* schema:
|
||||||
|
* type: string
|
||||||
|
* description: 反馈ID
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: 获取成功
|
||||||
|
*/
|
||||||
|
'GET /feedback/detail': async (ctx) => {
|
||||||
|
try {
|
||||||
|
// 从body中获取user_id,实际应该从token中解析
|
||||||
|
const body = ctx.getBody() || {};
|
||||||
|
const user_id = body.user_id;
|
||||||
|
|
||||||
|
if (!user_id) {
|
||||||
|
return ctx.fail('请先登录');
|
||||||
|
}
|
||||||
|
|
||||||
|
const { feedbackId } = ctx.query;
|
||||||
|
|
||||||
|
if (!feedbackId) {
|
||||||
|
return ctx.fail('反馈ID不能为空');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 这里可以从数据库查询反馈详情,暂时返回空
|
||||||
|
return ctx.fail('反馈记录不存在');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取反馈详情失败:', error);
|
||||||
|
return ctx.fail('获取反馈详情失败: ' + error.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
114
api/controller_front/invite.js
Normal file
114
api/controller_front/invite.js
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
/**
|
||||||
|
* 推广邀请管理控制器(客户端接口)
|
||||||
|
* 提供客户端调用的推广邀请相关接口
|
||||||
|
*/
|
||||||
|
|
||||||
|
const Framework = require("../../framework/node-core-framework.js");
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /api/invite/info:
|
||||||
|
* get:
|
||||||
|
* summary: 获取邀请信息
|
||||||
|
* description: 根据用户ID获取邀请码和邀请链接
|
||||||
|
* tags: [前端-推广邀请]
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: 获取成功
|
||||||
|
*/
|
||||||
|
'GET /invite/info': async (ctx) => {
|
||||||
|
try {
|
||||||
|
// 从query或body中获取user_id,实际应该从token中解析
|
||||||
|
const body = ctx.getBody();
|
||||||
|
const user_id = body.user_id || ctx.query?.user_id;
|
||||||
|
|
||||||
|
if (!user_id) {
|
||||||
|
return ctx.fail('请先登录');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成邀请码(基于用户ID)
|
||||||
|
const invite_code = `INV${user_id}${Date.now().toString(36).toUpperCase()}`;
|
||||||
|
const invite_link = `https://work.light120.com/invite?code=${invite_code}`;
|
||||||
|
|
||||||
|
return ctx.success({
|
||||||
|
invite_code,
|
||||||
|
invite_link,
|
||||||
|
user_id
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取邀请信息失败:', error);
|
||||||
|
return ctx.fail('获取邀请信息失败: ' + error.message);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /api/invite/statistics:
|
||||||
|
* get:
|
||||||
|
* summary: 获取邀请统计
|
||||||
|
* description: 根据用户ID获取邀请统计数据
|
||||||
|
* tags: [前端-推广邀请]
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: 获取成功
|
||||||
|
*/
|
||||||
|
'GET /invite/statistics': async (ctx) => {
|
||||||
|
try {
|
||||||
|
// 从query或body中获取user_id,实际应该从token中解析
|
||||||
|
const body = ctx.getBody() || {};
|
||||||
|
const user_id = body.user_id || ctx.query?.user_id;
|
||||||
|
|
||||||
|
if (!user_id) {
|
||||||
|
return ctx.fail('请先登录');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 这里可以从数据库查询邀请统计,暂时返回模拟数据
|
||||||
|
return ctx.success({
|
||||||
|
totalInvites: 0,
|
||||||
|
activeInvites: 0,
|
||||||
|
rewardPoints: 0,
|
||||||
|
rewardAmount: 0
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取邀请统计失败:', error);
|
||||||
|
return ctx.fail('获取邀请统计失败: ' + error.message);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /api/invite/generate:
|
||||||
|
* post:
|
||||||
|
* summary: 生成邀请码
|
||||||
|
* description: 为用户生成新的邀请码
|
||||||
|
* tags: [前端-推广邀请]
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: 生成成功
|
||||||
|
*/
|
||||||
|
'POST /invite/generate': async (ctx) => {
|
||||||
|
try {
|
||||||
|
// 从query或body中获取user_id,实际应该从token中解析
|
||||||
|
const body = ctx.getBody() || {};
|
||||||
|
const user_id = body.user_id || ctx.query?.user_id;
|
||||||
|
|
||||||
|
if (!user_id) {
|
||||||
|
return ctx.fail('请先登录');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成新的邀请码
|
||||||
|
const invite_code = `INV${user_id}${Date.now().toString(36).toUpperCase()}`;
|
||||||
|
const invite_link = `https://work.light120.com/invite?code=${invite_code}`;
|
||||||
|
|
||||||
|
return ctx.success({
|
||||||
|
invite_code,
|
||||||
|
invite_link
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('生成邀请码失败:', error);
|
||||||
|
return ctx.fail('生成邀请码失败: ' + error.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
@@ -26,6 +26,10 @@ module.exports = {
|
|||||||
* type: string
|
* type: string
|
||||||
* description: 密码
|
* description: 密码
|
||||||
* example: 'password123'
|
* example: 'password123'
|
||||||
|
* device_id:
|
||||||
|
* type: string
|
||||||
|
* description: 设备ID(客户端生成,可选,如果提供则使用提供的,否则使用数据库中的)
|
||||||
|
* example: 'device_1234567890abcdef'
|
||||||
* responses:
|
* responses:
|
||||||
* 200:
|
* 200:
|
||||||
* description: 登录成功
|
* description: 登录成功
|
||||||
@@ -71,9 +75,8 @@ module.exports = {
|
|||||||
* example: '用户不存在或密码错误'
|
* example: '用户不存在或密码错误'
|
||||||
*/
|
*/
|
||||||
"POST /user/login": async (ctx) => {
|
"POST /user/login": async (ctx) => {
|
||||||
const { phone, password } = ctx.getBody();
|
const { phone, password, device_id: client_device_id } = ctx.getBody();
|
||||||
const dayjs = require('dayjs');
|
const dayjs = require('dayjs');
|
||||||
const crypto = require('crypto');
|
|
||||||
|
|
||||||
// 验证参数
|
// 验证参数
|
||||||
if (!phone || !password) {
|
if (!phone || !password) {
|
||||||
@@ -116,18 +119,21 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 生成设备ID(如果不存在,基于手机号和机器特征生成)
|
// 处理设备ID:优先使用客户端传递的 device_id,如果没有则使用数据库中的
|
||||||
let device_id = user.device_id;
|
let device_id = client_device_id || user.device_id;
|
||||||
if (!device_id) {
|
|
||||||
// 生成唯一设备ID
|
|
||||||
const machineInfo = `${phone}_${Date.now()}_${Math.random()}`;
|
|
||||||
device_id = crypto.createHash('sha256').update(machineInfo).digest('hex').substring(0, 32);
|
|
||||||
|
|
||||||
// 保存设备ID到账号表
|
// 如果客户端提供了 device_id 且与数据库中的不同,则更新数据库
|
||||||
|
if (client_device_id && client_device_id !== user.device_id) {
|
||||||
await pla_account.update(
|
await pla_account.update(
|
||||||
{ device_id: device_id },
|
{ device_id: client_device_id },
|
||||||
{ where: { id: user.id } }
|
{ where: { id: user.id } }
|
||||||
);
|
);
|
||||||
|
device_id = client_device_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果既没有客户端传递的,数据库中也为空,则返回错误(不应该发生,因为客户端会生成)
|
||||||
|
if (!device_id) {
|
||||||
|
return ctx.fail('设备ID不能为空,请重新登录');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建token
|
// 创建token
|
||||||
|
|||||||
146
api/model/ai_messages.js
Normal file
146
api/model/ai_messages.js
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
const Sequelize = require('sequelize');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AI消息表模型
|
||||||
|
* 记录用户与AI的交互消息
|
||||||
|
*/
|
||||||
|
module.exports = (db) => {
|
||||||
|
const ai_messages = db.define("ai_messages", {
|
||||||
|
// 用户信息
|
||||||
|
user_id: {
|
||||||
|
comment: '用户ID',
|
||||||
|
type: Sequelize.INTEGER,
|
||||||
|
allowNull: false,
|
||||||
|
defaultValue: 0
|
||||||
|
},
|
||||||
|
nickname: {
|
||||||
|
comment: '用户昵称',
|
||||||
|
type: Sequelize.STRING(100),
|
||||||
|
allowNull: true,
|
||||||
|
defaultValue: ''
|
||||||
|
},
|
||||||
|
|
||||||
|
// 消息信息
|
||||||
|
message_type: {
|
||||||
|
comment: '消息类型: question-提问, feedback-反馈, suggestion-建议',
|
||||||
|
type: Sequelize.STRING(50),
|
||||||
|
allowNull: false,
|
||||||
|
defaultValue: 'question'
|
||||||
|
},
|
||||||
|
content: {
|
||||||
|
comment: '消息内容',
|
||||||
|
type: Sequelize.TEXT,
|
||||||
|
allowNull: false,
|
||||||
|
defaultValue: ''
|
||||||
|
},
|
||||||
|
|
||||||
|
// AI回复信息
|
||||||
|
ai_response: {
|
||||||
|
comment: 'AI回复内容',
|
||||||
|
type: Sequelize.TEXT,
|
||||||
|
allowNull: true,
|
||||||
|
defaultValue: ''
|
||||||
|
},
|
||||||
|
ai_model: {
|
||||||
|
comment: 'AI模型名称',
|
||||||
|
type: Sequelize.STRING(50),
|
||||||
|
allowNull: true,
|
||||||
|
defaultValue: ''
|
||||||
|
},
|
||||||
|
ai_prompt: {
|
||||||
|
comment: 'AI提示词',
|
||||||
|
type: Sequelize.TEXT,
|
||||||
|
allowNull: true,
|
||||||
|
defaultValue: ''
|
||||||
|
},
|
||||||
|
|
||||||
|
// 处理状态
|
||||||
|
status: {
|
||||||
|
comment: '处理状态: pending-待处理, processing-处理中, completed-已完成, failed-处理失败',
|
||||||
|
type: Sequelize.STRING(20),
|
||||||
|
allowNull: false,
|
||||||
|
defaultValue: 'pending'
|
||||||
|
},
|
||||||
|
process_time: {
|
||||||
|
comment: '处理时间(毫秒)',
|
||||||
|
type: Sequelize.INTEGER,
|
||||||
|
allowNull: true,
|
||||||
|
defaultValue: 0
|
||||||
|
},
|
||||||
|
|
||||||
|
// 关联信息
|
||||||
|
related_id: {
|
||||||
|
comment: '关联ID(如职位ID、聊天记录ID等)',
|
||||||
|
type: Sequelize.STRING(100),
|
||||||
|
allowNull: true,
|
||||||
|
defaultValue: ''
|
||||||
|
},
|
||||||
|
related_type: {
|
||||||
|
comment: '关联类型: job-职位, chat-聊天, resume-简历',
|
||||||
|
type: Sequelize.STRING(50),
|
||||||
|
allowNull: true,
|
||||||
|
defaultValue: ''
|
||||||
|
},
|
||||||
|
|
||||||
|
// 其他信息
|
||||||
|
error_message: {
|
||||||
|
comment: '错误信息',
|
||||||
|
type: Sequelize.TEXT,
|
||||||
|
allowNull: true,
|
||||||
|
defaultValue: ''
|
||||||
|
},
|
||||||
|
notes: {
|
||||||
|
comment: '备注',
|
||||||
|
type: Sequelize.TEXT,
|
||||||
|
allowNull: true,
|
||||||
|
defaultValue: ''
|
||||||
|
},
|
||||||
|
|
||||||
|
// 时间戳
|
||||||
|
create_time: {
|
||||||
|
comment: '创建时间',
|
||||||
|
type: Sequelize.DATE,
|
||||||
|
allowNull: false,
|
||||||
|
defaultValue: Sequelize.NOW
|
||||||
|
},
|
||||||
|
update_time: {
|
||||||
|
comment: '更新时间',
|
||||||
|
type: Sequelize.DATE,
|
||||||
|
allowNull: false,
|
||||||
|
defaultValue: Sequelize.NOW
|
||||||
|
},
|
||||||
|
is_delete: {
|
||||||
|
comment: '是否删除',
|
||||||
|
type: Sequelize.BOOLEAN,
|
||||||
|
allowNull: false,
|
||||||
|
defaultValue: false
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
timestamps: false,
|
||||||
|
indexes: [
|
||||||
|
{
|
||||||
|
unique: false,
|
||||||
|
fields: ['user_id']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
unique: false,
|
||||||
|
fields: ['message_type']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
unique: false,
|
||||||
|
fields: ['status']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
unique: false,
|
||||||
|
fields: ['create_time']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
unique: false,
|
||||||
|
fields: ['is_delete']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
return ai_messages;
|
||||||
|
};
|
||||||
|
|
||||||
Reference in New Issue
Block a user