From 6efd77d2b56fc0d4584ed9356f72268ca60ac866 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E6=88=90?= Date: Fri, 26 Dec 2025 13:12:53 +0800 Subject: [PATCH] 1 --- admin/src/api/profile/resume_info_server.js | 9 ++ .../src/views/account/resume_info_detail.vue | 28 ++++++ api/controller_admin/resume_info.js | 94 +++++++++++++++++++ 3 files changed, 131 insertions(+) diff --git a/admin/src/api/profile/resume_info_server.js b/admin/src/api/profile/resume_info_server.js index 08fbff1..8d10ffe 100644 --- a/admin/src/api/profile/resume_info_server.js +++ b/admin/src/api/profile/resume_info_server.js @@ -48,6 +48,15 @@ class ResumeInfoServer { analyzeWithAI(resumeId) { return window.framework.http.post('/resume/analyze-with-ai', { resumeId }) } + + /** + * 同步在线简历 + * @param {String} resumeId - 简历ID + * @returns {Promise} + */ + syncOnline(resumeId) { + return window.framework.http.post('/resume/sync-online', { resumeId }) + } } export default new ResumeInfoServer() diff --git a/admin/src/views/account/resume_info_detail.vue b/admin/src/views/account/resume_info_detail.vue index 1c81b8f..264a4e4 100644 --- a/admin/src/views/account/resume_info_detail.vue +++ b/admin/src/views/account/resume_info_detail.vue @@ -8,6 +8,7 @@ @back="handleBack" > @@ -272,6 +273,7 @@ export default { return { loading: false, analyzing: false, + syncing: false, resumeData: null, skillTags: [], workExperience: [], @@ -317,6 +319,32 @@ export default { } return field }, + async handleSyncOnline() { + if (!this.resumeData || !this.resumeData.resumeId) { + this.$Message.warning('简历ID不存在') + return + } + + if (!this.resumeData.sn_code) { + this.$Message.warning('该简历未绑定设备,无法同步在线简历') + return + } + + this.syncing = true + try { + const res = await resumeInfoServer.syncOnline(this.resumeData.resumeId) + this.$Message.success(res.message || '同步在线简历成功') + // 重新加载数据 + await this.loadResumeData(this.resumeData.resumeId) + } catch (error) { + console.error('同步在线简历失败:', error) + // 优先从 error.response.data.message 获取,然后是 error.message + const errorMsg = error.response?.data?.message || error.message || '请稍后重试' + this.$Message.error(errorMsg) + } finally { + this.syncing = false + } + }, async handleAnalyzeAI() { if (!this.resumeData || !this.resumeData.resumeId) { this.$Message.warning('简历ID不存在') diff --git a/api/controller_admin/resume_info.js b/api/controller_admin/resume_info.js index cbff157..6d3bcb0 100644 --- a/api/controller_admin/resume_info.js +++ b/api/controller_admin/resume_info.js @@ -358,6 +358,100 @@ return ctx.success({ message: '简历删除成功' }); console.error('AI 分析失败:', error); return ctx.fail('AI 分析失败: ' + error.message); } + }, + + /** + * @swagger + * /admin_api/resume/sync-online: + * post: + * summary: 同步在线简历 + * description: 通过MQTT指令获取用户在线简历并更新到数据库 + * tags: [后台-简历管理] + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * required: + * - resumeId + * properties: + * resumeId: + * type: string + * description: 简历ID + * responses: + * 200: + * description: 同步成功 + */ + 'POST /resume/sync-online': async (ctx) => { + const models = Framework.getModels(); + const { resume_info } = models; + const { resumeId } = ctx.getBody(); + + if (!resumeId) { + return ctx.fail('简历ID不能为空'); + } + + const resume = await resume_info.findOne({ where: { resumeId } }); + + if (!resume) { + return ctx.fail('简历不存在'); + } + + const { sn_code, platform } = resume; + + if (!sn_code) { + return ctx.fail('该简历未绑定设备SN码'); + } + + try { + const scheduleManager = require('../middleware/schedule'); + const resumeManager = require('../middleware/job/resumeManager'); + + // 检查 MQTT 客户端是否已初始化 + if (!scheduleManager.mqttClient) { + return ctx.fail('MQTT客户端未初始化,请检查调度系统是否正常启动'); + } + + // 检查设备是否在线 + // const deviceManager = require('../middleware/schedule/deviceManager'); + // if (!deviceManager.isDeviceOnline(sn_code)) { + // return ctx.fail('设备离线,无法同步在线简历'); + // } + + // 调用简历管理器获取并保存简历 + const resumeData = await resumeManager.get_online_resume(sn_code, scheduleManager.mqttClient, { + platform: platform || 'boss' + }); + + // 重新获取更新后的简历数据 + const updatedResume = await resume_info.findOne({ where: { resumeId } }); + if (!updatedResume) { + return ctx.fail('同步成功但未找到更新后的简历记录'); + } + + const resumeDetail = updatedResume.toJSON(); + + // 解析 JSON 字段 + const jsonFields = ['skills', 'certifications', 'projectExperience', 'workExperience', 'aiSkillTags']; + jsonFields.forEach(field => { + if (resumeDetail[field]) { + try { + resumeDetail[field] = JSON.parse(resumeDetail[field]); + } catch (e) { + console.error(`解析字段 ${field} 失败:`, e); + } + } + }); + + return ctx.success({ + message: '同步在线简历成功', + data: resumeDetail + }); + } catch (error) { + console.error('同步在线简历失败:', error); + return ctx.fail('同步在线简历失败: ' + (error.message || '未知错误')); + } } };