Files
autoAiWorkSys/api/controller_admin/pla_account.js
张成 7ee92b8905 1
2025-12-25 22:11:34 +08:00

772 lines
23 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 平台账号管理API - 后台管理
* 提供平台账号的查询和管理功能
*/
const Framework = require("../../framework/node-core-framework.js");
const plaAccountService = require('../services/pla_account_service');
module.exports = {
'GET /pla_account/getById': async (ctx) => {
const { id } = ctx.getQuery();
const accountData = await plaAccountService.getAccountById(id);
return ctx.success(accountData);
},
'POST /account/detail': async (ctx) => {
const { id } = ctx.getBody();
const accountData = await plaAccountService.getAccountById(id);
return ctx.success(accountData);
},
/**
* @swagger
* /admin_api/account/getBySnCode:
* post:
* summary: 通过设备SN码获取账号信息
* description: 根据设备SN码直接获取对应的账号信息
* tags: [后台-账号管理]
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - sn_code
* properties:
* sn_code:
* type: string
* description: 设备SN码
* responses:
* 200:
* description: 获取成功
*/
'POST /account/getBySnCode': async (ctx) => {
const { sn_code } = ctx.getBody();
const accountData = await plaAccountService.getAccountBySnCode(sn_code);
return ctx.success(accountData);
},
/**
* @swagger
* /admin_api/account/list:
* post:
* summary: 获取账号列表
* description: 分页获取所有平台账号
* tags: [后台-账号管理]
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* properties:
* page:
* type: integer
* description: 页码
* pageSize:
* type: integer
* description: 每页数量
* key:
* type: string
* description: 搜索字段
* value:
* type: string
* description: 搜索值
* platform_type:
* type: string
* description: 平台类型ID
* is_online:
* type: boolean
* description: 是否在线
* responses:
* 200:
* description: 获取成功
*/
'POST /account/list': async (ctx) => {
const body = ctx.getBody();
// 支持两种参数格式:直接传参或通过 seachOption 传递
const seachOption = body.seachOption || {};
const pageOption = body.pageOption || {};
// 获取搜索参数(优先使用 seachOption兼容直接传参
const key = seachOption.key || body.key;
const value = seachOption.value || body.value;
const platform_type = seachOption.platform_type || body.platform_type;
const is_online = seachOption.is_online !== undefined ? seachOption.is_online : body.is_online;
// 获取分页参数
const page = pageOption.page || body.page || 1;
const pageSize = pageOption.pageSize || body.pageSize || 20;
const limit = pageSize;
const offset = (page - 1) * pageSize;
const result = await plaAccountService.getAccountList({
key,
value,
platform_type,
is_online,
limit,
offset
});
return ctx.success(result);
},
/**
* @swagger
* /admin_api/account/add:
* post:
* summary: 新增账号
* description: 创建新的平台账号
* tags: [后台-账号管理]
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - name
* - sn_code
* - platform_type
* - login_name
* properties:
* name:
* type: string
* description: 账户名
* sn_code:
* type: string
* description: 设备SN码
* platform_type:
* type: string
* description: 平台类型ID
* login_name:
* type: string
* description: 登录名
* pwd:
* type: string
* description: 密码
* keyword:
* type: string
* description: 搜索关键词
* search_url:
* type: string
* description: 搜索页网址
* responses:
* 200:
* description: 创建成功
*/
'POST /account/add': async (ctx) => {
const body = ctx.getBody();
const account = await plaAccountService.createAccount(body);
return ctx.success({ message: '账号创建成功', data: account });
},
/**
* @swagger
* /admin_api/account/update:
* post:
* summary: 更新账号信息
* description: 更新平台账号信息
* tags: [后台-账号管理]
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - id
* properties:
* id:
* type: integer
* description: 账号ID
* responses:
* 200:
* description: 更新成功
*/
'POST /account/update': async (ctx) => {
const body = ctx.getBody();
const { id, ...updateData } = body;
await plaAccountService.updateAccount(id, updateData);
return ctx.success({ message: '账号信息更新成功' });
},
/**
* @swagger
* /admin_api/account/delete:
* post:
* summary: 删除账号
* description: 删除指定的平台账号(软删除)
* tags: [后台-账号管理]
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - id
* properties:
* id:
* type: integer
* description: 账号ID
* responses:
* 200:
* description: 删除成功
*/
'POST /account/delete': async (ctx) => {
const body = ctx.getBody();
const { id } = body;
await plaAccountService.deleteAccount(id);
return ctx.success({ message: '账号删除成功' });
},
/**
* @swagger
* /admin_api/account/stopTasks:
* post:
* summary: 停止账号的所有任务
* description: 停止指定账号的所有待执行和正在执行的任务
* tags: [后台-账号管理]
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - id
* properties:
* id:
* type: integer
* description: 账号ID
* sn_code:
* type: string
* description: 设备SN码可选如果提供id则不需要
* responses:
* 200:
* description: 停止成功
*/
'POST /account/stopTasks': async (ctx) => {
const body = ctx.getBody();
const result = await plaAccountService.stopTasks(body);
return ctx.success(result);
},
/**
* @swagger
* /admin_api/pla_account/tasks:
* get:
* summary: 获取账号的任务列表
* description: 根据账号ID获取该账号的所有任务列表支持分页
* tags: [后台-账号管理]
* parameters:
* - in: query
* name: id
* required: true
* schema:
* type: integer
* description: 账号ID
* - in: query
* name: page
* schema:
* type: integer
* description: 页码
* - in: query
* name: pageSize
* schema:
* type: integer
* description: 每页数量
* responses:
* 200:
* description: 获取成功
*/
'GET /pla_account/tasks': async (ctx) => {
const { id } = ctx.getQuery();
const { limit, offset } = ctx.getPageSize();
const result = await plaAccountService.getAccountTasks({
id,
limit,
offset
});
return ctx.success(result);
},
/**
* @swagger
* /admin_api/pla_account/commands:
* get:
* summary: 获取账号的指令列表
* description: 根据账号ID获取该账号的所有指令列表支持分页
* tags: [后台-账号管理]
* parameters:
* - in: query
* name: id
* required: true
* schema:
* type: integer
* description: 账号ID
* - in: query
* name: page
* schema:
* type: integer
* description: 页码
* - in: query
* name: pageSize
* schema:
* type: integer
* description: 每页数量
* responses:
* 200:
* description: 获取成功
*/
'GET /pla_account/commands': async (ctx) => {
const { id } = ctx.getQuery();
const { limit, offset } = ctx.getPageSize();
const result = await plaAccountService.getAccountCommands({
id,
limit,
offset
});
return ctx.success(result);
},
/**
* @swagger
* /admin_api/pla_account/runTask:
* post:
* summary: 执行账号指令
* description: 为指定账号直接执行指令(如用户登录、获取简历等)
* tags: [后台-账号管理]
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - id
* - taskType
* properties:
* id:
* type: integer
* description: 账号ID
* taskType:
* type: string
* description: 指令类型: get_login_qr_code-登录检查, get_resume-获取简历, search_jobs-搜索岗位
* taskName:
* type: string
* description: 指令名称
* responses:
* 200:
* description: 指令执行成功
*/
'POST /pla_account/runTask': async (ctx) => {
const body = ctx.getBody();
const task = await plaAccountService.runTask(body);
return ctx.success(task);
},
/**
* @swagger
* /admin_api/pla_account/runCommand:
* post:
* summary: 执行账号指令
* description: 为指定账号直接执行指令(如用户登录、获取简历等)
* tags: [后台-账号管理]
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - id
* - commandType
* properties:
* id:
* type: integer
* description: 账号ID
* commandType:
* type: string
* description: 指令类型: get_login_qr_code-登录检查, get_resume-获取简历, search_jobs-搜索岗位
* commandName:
* type: string
* description: 指令名称
* responses:
* 200:
* description: 指令执行成功
*/
'POST /pla_account/runCommand': async (ctx) => {
const body = ctx.getBody();
const result = await plaAccountService.runCommand(body);
return ctx.success(result);
},
/**
* @swagger
* /admin_api/pla_account/commandDetail:
* get:
* summary: 获取指令详情
* description: 根据账号ID和指令ID获取指令的详细信息
* tags: [后台-账号管理]
* parameters:
* - in: query
* name: accountId
* required: true
* schema:
* type: integer
* description: 账号ID
* - in: query
* name: commandId
* required: true
* schema:
* type: integer
* description: 指令ID
* responses:
* 200:
* description: 获取成功
*/
'GET /pla_account/commandDetail': async (ctx) => {
const { accountId, commandId } = ctx.getQuery();
const commandDetail = await plaAccountService.getCommandDetail({
accountId,
commandId
});
return ctx.success(commandDetail);
},
/**
* @swagger
* /admin_api/pla_account/retryCommand:
* post:
* summary: 重试指令
* description: 重新执行失败的指令
* tags: [后台-账号管理]
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - commandId
* properties:
* commandId:
* type: integer
* description: 指令ID
* responses:
* 200:
* description: 重试成功
*/
'POST /pla_account/retryCommand': async (ctx) => {
const body = ctx.getBody();
const result = await plaAccountService.retryCommand(body);
return ctx.success(result);
},
/**
* @swagger
* /admin_api/pla_account/parseLocation:
* post:
* summary: 解析地址并更新经纬度
* description: 根据账号ID解析地址获取经纬度并更新到账号信息中
* tags: [后台-账号管理]
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - id
* properties:
* id:
* type: integer
* description: 账号ID
* address:
* type: string
* description: 地址(可选,如果不提供则使用账号中的地址)
* responses:
* 200:
* description: 解析成功
*/
'POST /pla_account/parseLocation': async (ctx) => {
const body = ctx.getBody();
const result = await plaAccountService.parseLocation(body);
return ctx.success(result);
},
/**
* @swagger
* /admin_api/pla_account/batchParseLocation:
* post:
* summary: 批量解析地址并更新经纬度
* description: 批量解析多个账号的地址,获取经纬度并更新到账号信息中
* tags: [后台-账号管理]
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - ids
* properties:
* ids:
* type: array
* items:
* type: integer
* description: 账号ID数组
* responses:
* 200:
* description: 批量解析完成
*/
'POST /pla_account/batchParseLocation': async (ctx) => {
const body = ctx.getBody();
const { ids } = body;
const result = await plaAccountService.batchParseLocation(ids);
return ctx.success(result);
},
/**
* @swagger
* /admin_api/account/check-authorization:
* post:
* summary: 检查账号授权状态
* description: 根据账号ID或SN码检查账号的授权状态剩余天数、是否过期等
* tags: [后台-账号管理]
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* properties:
* id:
* type: integer
* description: 账号ID可选如果提供id则不需要sn_code
* sn_code:
* type: string
* description: 设备SN码可选如果提供sn_code则不需要id
* responses:
* 200:
* description: 检查成功
*/
'POST /account/check-authorization': async (ctx) => {
const { id, sn_code } = ctx.getBody();
const models = await Framework.getModels();
const { pla_account } = models;
const dayjs = require('dayjs');
if (!id && !sn_code) {
return ctx.fail('请提供账号ID或SN码');
}
const where = id ? { id } : { sn_code };
const account = await pla_account.findOne({ where });
if (!account) {
return ctx.fail('账号不存在');
}
const accountData = account.toJSON();
const authDate = accountData.authorization_date;
const authDays = accountData.authorization_days || 0;
// 计算剩余天数
const { calculateRemainingDays } = require('../utils/account_utils');
const remaining_days = calculateRemainingDays(authDate, authDays);
const is_expired = remaining_days <= 0;
let end_date = null;
if (authDate && authDays > 0) {
const startDate = dayjs(authDate);
end_date = startDate.add(authDays, 'day').toDate();
}
return ctx.success({
id: accountData.id,
sn_code: accountData.sn_code,
name: accountData.name,
authorization_date: authDate,
authorization_days: authDays,
remaining_days: remaining_days,
end_date: end_date,
is_expired: is_expired,
is_authorized: !is_expired && remaining_days > 0
});
},
/**
* @swagger
* /admin_api/account/update-authorization:
* post:
* summary: 更新账号授权信息
* description: 更新账号的授权日期和授权天数
* tags: [后台-账号管理]
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - id
* properties:
* id:
* type: integer
* description: 账号ID
* authorization_date:
* type: string
* format: date-time
* description: 授权日期(可选,不提供则使用当前时间)
* authorization_days:
* type: integer
* description: 授权天数(必填)
* responses:
* 200:
* description: 更新成功
*/
'POST /account/update-authorization': async (ctx) => {
const { id, authorization_date, authorization_days } = ctx.getBody();
const models = await Framework.getModels();
const { pla_account } = models;
const dayjs = require('dayjs');
if (!id) {
return ctx.fail('账号ID不能为空');
}
if (authorization_days === undefined || authorization_days === null) {
return ctx.fail('授权天数不能为空');
}
if (authorization_days < 0) {
return ctx.fail('授权天数不能为负数');
}
const account = await pla_account.findOne({ where: { id } });
if (!account) {
return ctx.fail('账号不存在');
}
// 如果提供了授权日期,使用提供的日期;否则使用当前时间
const authDate = authorization_date ? new Date(authorization_date) : new Date();
await account.update({
authorization_date: authDate,
authorization_days: authorization_days
});
// 计算更新后的剩余天数
const { calculateRemainingDays } = require('../utils/account_utils');
const remaining_days = calculateRemainingDays(authDate, authorization_days);
const end_date = dayjs(authDate).add(authorization_days, 'day').toDate();
return ctx.success({
message: '授权信息更新成功',
data: {
id: account.id,
authorization_date: authDate,
authorization_days: authorization_days,
remaining_days: remaining_days,
end_date: end_date
}
});
},
/**
* @swagger
* /admin_api/pla_account/parse-resume:
* post:
* summary: 解析账号在线简历
* description: 获取指定账号的在线简历并进行AI分析返回简历详情
* tags: [后台-账号管理]
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - id
* properties:
* id:
* type: integer
* description: 账号ID
* responses:
* 200:
* description: 解析成功返回简历ID
*/
'POST /pla_account/parse-resume': async (ctx) => {
const { id } = ctx.getBody();
const models = await Framework.getModels();
const { pla_account } = models;
const mqttClient = require('../middleware/mqtt/mqttClient');
const resumeManager = require('../middleware/job/resumeManager');
if (!id) {
return ctx.fail('账号ID不能为空');
}
// 获取账号信息
const account = await pla_account.findOne({ where: { id } });
if (!account) {
return ctx.fail('账号不存在');
}
const { sn_code, platform_type } = account;
if (!sn_code) {
return ctx.fail('该账号未绑定设备');
}
try {
// 调用简历管理器获取并保存简历
const resumeData = await resumeManager.get_online_resume(sn_code, mqttClient, {
platform: platform_type || 'boss'
});
// 从返回数据中获取 resumeId
// resumeManager 已经保存了简历到数据库,我们需要查询获取 resumeId
const resume_info = models.resume_info;
const savedResume = await resume_info.findOne({
where: {
sn_code,
platform: platform_type || 'boss',
isActive: true
},
order: [['syncTime', 'DESC']]
});
if (!savedResume) {
return ctx.fail('简历解析失败:未找到保存的简历记录');
}
return ctx.success({
message: '简历解析成功',
resumeId: savedResume.resumeId,
data: resumeData
});
} catch (error) {
console.error('[解析简历] 失败:', error);
return ctx.fail('解析简历失败: ' + (error.message || '未知错误'));
}
}
};