308 lines
9.8 KiB
JavaScript
308 lines
9.8 KiB
JavaScript
const Framework = require("../../framework/node-core-framework.js");
|
||
|
||
module.exports = {
|
||
/**
|
||
* @swagger
|
||
* /api/user/login:
|
||
* post:
|
||
* summary: 用户登录
|
||
* description: 通过手机号和密码登录,返回token、device_id和用户信息
|
||
* tags: [前端-用户管理]
|
||
* requestBody:
|
||
* required: true
|
||
* content:
|
||
* application/json:
|
||
* schema:
|
||
* type: object
|
||
* required:
|
||
* - phone
|
||
* - password
|
||
* properties:
|
||
* phone:
|
||
* type: string
|
||
* description: 手机号(登录名)
|
||
* example: '13800138000'
|
||
* password:
|
||
* type: string
|
||
* description: 密码
|
||
* example: 'password123'
|
||
* device_id:
|
||
* type: string
|
||
* description: 设备ID(客户端生成,可选,如果提供则使用提供的,否则使用数据库中的)
|
||
* example: 'device_1234567890abcdef'
|
||
* responses:
|
||
* 200:
|
||
* description: 登录成功
|
||
* content:
|
||
* application/json:
|
||
* schema:
|
||
* type: object
|
||
* properties:
|
||
* code:
|
||
* type: integer
|
||
* description: 状态码,0表示成功
|
||
* example: 0
|
||
* message:
|
||
* type: string
|
||
* description: 响应消息
|
||
* example: 'success'
|
||
* data:
|
||
* type: object
|
||
* properties:
|
||
* token:
|
||
* type: string
|
||
* description: 认证token
|
||
* example: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
|
||
* device_id:
|
||
* type: string
|
||
* description: 设备ID
|
||
* example: 'device_123456'
|
||
* user:
|
||
* type: object
|
||
* description: 用户信息
|
||
* 400:
|
||
* description: 参数错误或用户不存在
|
||
* content:
|
||
* application/json:
|
||
* schema:
|
||
* type: object
|
||
* properties:
|
||
* code:
|
||
* type: integer
|
||
* example: 400
|
||
* message:
|
||
* type: string
|
||
* example: '用户不存在或密码错误'
|
||
*/
|
||
"POST /user/login": async (ctx) => {
|
||
const { phone, password, device_id: client_device_id } = ctx.getBody();
|
||
const dayjs = require('dayjs');
|
||
|
||
// 验证参数
|
||
if (!phone || !password) {
|
||
return ctx.fail('手机号和密码不能为空');
|
||
}
|
||
|
||
const { pla_account } = await Framework.getModels();
|
||
|
||
// 根据手机号(login_name)和密码查找用户
|
||
const user = await pla_account.findOne({
|
||
where: {
|
||
login_name: phone,
|
||
pwd: password
|
||
}
|
||
});
|
||
|
||
if (!user) {
|
||
return ctx.fail('手机号或密码错误');
|
||
}
|
||
|
||
// 检查账号是否启用
|
||
if (!user.is_enabled) {
|
||
return ctx.fail('账号已被禁用');
|
||
}
|
||
|
||
// 检查授权状态
|
||
const userData = user.toJSON();
|
||
const authDate = userData.authorization_date;
|
||
const authDays = userData.authorization_days || 0;
|
||
|
||
if (authDate && authDays > 0) {
|
||
const startDate = dayjs(authDate);
|
||
const endDate = startDate.add(authDays, 'day');
|
||
const now = dayjs();
|
||
const remaining = endDate.diff(now, 'day', true);
|
||
const remaining_days = Math.max(0, Math.ceil(remaining));
|
||
|
||
if (remaining_days <= 0) {
|
||
return ctx.fail('账号授权已过期,请联系管理员续费');
|
||
}
|
||
}
|
||
|
||
// 处理设备ID:优先使用客户端传递的 device_id,如果没有则使用数据库中的
|
||
let device_id = client_device_id || user.device_id;
|
||
|
||
// 如果客户端提供了 device_id 且与数据库中的不同,则更新数据库
|
||
if (client_device_id && client_device_id !== user.device_id) {
|
||
await pla_account.update(
|
||
{ device_id: client_device_id },
|
||
{ where: { id: user.id } }
|
||
);
|
||
device_id = client_device_id;
|
||
}
|
||
|
||
// 如果既没有客户端传递的,数据库中也为空,则返回错误(不应该发生,因为客户端会生成)
|
||
if (!device_id) {
|
||
return ctx.fail('设备ID不能为空,请重新登录');
|
||
}
|
||
|
||
// 创建token
|
||
const token = Framework.getServices().tokenService.create({
|
||
sn_code: user.sn_code,
|
||
device_id: device_id,
|
||
user_id: user.id
|
||
});
|
||
|
||
// 计算剩余天数
|
||
let remaining_days = 0;
|
||
if (authDate && authDays > 0) {
|
||
const startDate = dayjs(authDate);
|
||
const endDate = startDate.add(authDays, 'day');
|
||
const now = dayjs();
|
||
const remaining = endDate.diff(now, 'day', true);
|
||
remaining_days = Math.max(0, Math.ceil(remaining));
|
||
}
|
||
|
||
const userInfo = user.toJSON();
|
||
userInfo.remaining_days = remaining_days;
|
||
// 不返回密码
|
||
delete userInfo.pwd;
|
||
|
||
return ctx.success({
|
||
token,
|
||
device_id,
|
||
user: userInfo
|
||
});
|
||
},
|
||
|
||
/**
|
||
* @swagger
|
||
* /api/user/delivery-config:
|
||
* get:
|
||
* summary: 获取投递配置
|
||
* description: 根据设备SN码获取用户的投递配置
|
||
* tags: [前端-用户管理]
|
||
* parameters:
|
||
* - in: query
|
||
* name: sn_code
|
||
* required: true
|
||
* schema:
|
||
* type: string
|
||
* description: 设备SN码
|
||
* responses:
|
||
* 200:
|
||
* description: 获取成功
|
||
*/
|
||
'GET /user/delivery-config': async (ctx) => {
|
||
try {
|
||
const { sn_code } = ctx.query;
|
||
|
||
if (!sn_code) {
|
||
return ctx.fail('请提供设备SN码');
|
||
}
|
||
|
||
const { pla_account } = await Framework.getModels();
|
||
const user = await pla_account.findOne({
|
||
where: { sn_code }
|
||
});
|
||
|
||
if (!user) {
|
||
return ctx.fail('用户不存在');
|
||
}
|
||
|
||
// 从数据库获取配置
|
||
const autoDelivery = user.auto_deliver === 1;
|
||
const deliverConfig = user.deliver_config || {};
|
||
|
||
// 转换配置格式为前端需要的格式
|
||
const config = {
|
||
autoDelivery: autoDelivery,
|
||
interval: deliverConfig.deliver_interval || 30,
|
||
minSalary: deliverConfig.min_salary || 0,
|
||
maxSalary: deliverConfig.max_salary || 0,
|
||
scrollPages: deliverConfig.page_count || 3,
|
||
maxPerBatch: deliverConfig.max_deliver || 10,
|
||
filterKeywords: deliverConfig.filter_keywords || [],
|
||
excludeKeywords: deliverConfig.exclude_keywords || [],
|
||
startTime: deliverConfig.time_range?.start_time || '09:00',
|
||
endTime: deliverConfig.time_range?.end_time || '18:00',
|
||
workdaysOnly: deliverConfig.time_range?.workdays_only === 1 || deliverConfig.time_range?.workdays_only === true
|
||
};
|
||
|
||
return ctx.success(config);
|
||
} catch (error) {
|
||
console.error('获取投递配置失败:', error);
|
||
return ctx.fail('获取投递配置失败: ' + error.message);
|
||
}
|
||
},
|
||
|
||
/**
|
||
* @swagger
|
||
* /api/user/delivery-config:
|
||
* post:
|
||
* summary: 保存投递配置
|
||
* description: 根据设备SN码保存用户的投递配置
|
||
* tags: [前端-用户管理]
|
||
* requestBody:
|
||
* required: true
|
||
* content:
|
||
* application/json:
|
||
* schema:
|
||
* type: object
|
||
* required:
|
||
* - sn_code
|
||
* properties:
|
||
* sn_code:
|
||
* type: string
|
||
* description: 设备SN码
|
||
* config:
|
||
* type: object
|
||
* description: 投递配置
|
||
* responses:
|
||
* 200:
|
||
* description: 保存成功
|
||
*/
|
||
'POST /user/delivery-config': async (ctx) => {
|
||
try {
|
||
const body = ctx.getBody();
|
||
const { sn_code, config } = body;
|
||
|
||
if (!sn_code) {
|
||
return ctx.fail('请提供设备SN码');
|
||
}
|
||
|
||
if (!config) {
|
||
return ctx.fail('请提供配置信息');
|
||
}
|
||
|
||
const { pla_account } = await Framework.getModels();
|
||
const user = await pla_account.findOne({
|
||
where: { sn_code }
|
||
});
|
||
|
||
if (!user) {
|
||
return ctx.fail('用户不存在');
|
||
}
|
||
|
||
// 转换前端配置格式为数据库格式
|
||
const deliverConfig = {
|
||
deliver_interval: config.interval || 30,
|
||
min_salary: config.minSalary || 0,
|
||
max_salary: config.maxSalary || 0,
|
||
page_count: config.scrollPages || 3,
|
||
max_deliver: config.maxPerBatch || 10,
|
||
filter_keywords: config.filterKeywords || [],
|
||
exclude_keywords: config.excludeKeywords || [],
|
||
time_range: {
|
||
start_time: config.startTime || '09:00',
|
||
end_time: config.endTime || '18:00',
|
||
workdays_only: config.workdaysOnly ? 1 : 0
|
||
}
|
||
};
|
||
|
||
// 更新数据库
|
||
await pla_account.update(
|
||
{
|
||
auto_deliver: config.autoDelivery ? 1 : 0,
|
||
deliver_config: deliverConfig
|
||
},
|
||
{ where: { sn_code } }
|
||
);
|
||
|
||
return ctx.success({ message: '配置保存成功' });
|
||
} catch (error) {
|
||
console.error('保存投递配置失败:', error);
|
||
return ctx.fail('保存投递配置失败: ' + error.message);
|
||
}
|
||
}
|
||
} |