From 967317367c2107b95faa08d0d3dd5a63827461d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=B3?= Date: Wed, 12 Nov 2025 19:31:46 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apiRc/jobPath.js | 36 +- apiRc/jobRecommend.js | 43 +-- apiRc/jobSkill.js | 88 ++--- apiRc/user/user.js | 2 +- components/CustomTabBar/CustomTabBar.vue | 10 +- docs/职业图谱接口说明.md | 237 ++++++++++++ pages/chat/chat.vue | 2 +- pages/service/career-planning.vue | 296 +++++++++++---- pages/service/components/CareerPath.vue | 56 ++- pages/service/components/CareerRecommend.vue | 177 +++++---- pages/service/components/PageHeader.vue | 23 +- pages/service/components/RemindPopup.vue | 8 +- pages/service/components/SkillDevelopment.vue | 189 +++++----- stores/useUserStore.js | 346 +++++++++--------- utilsRc/auth.js | 2 +- utilsRc/config.js | 8 +- utilsRc/request.js | 39 +- 17 files changed, 1002 insertions(+), 560 deletions(-) create mode 100644 docs/职业图谱接口说明.md diff --git a/apiRc/jobPath.js b/apiRc/jobPath.js index d0930e6..9324074 100644 --- a/apiRc/jobPath.js +++ b/apiRc/jobPath.js @@ -16,10 +16,21 @@ export function getJobPathPage(params) { // 根据职业路径ID获取详情 export function getJobPathDetail(params) { + const requestParams = {}; + if (params?.jobPathId !== undefined && params?.jobPathId !== null && params?.jobPathId !== '') { + requestParams.id = params.jobPathId; + } else if (params?.id !== undefined && params?.id !== null && params?.id !== '') { + requestParams.id = params.id; + } + + if (!requestParams.id) { + return Promise.reject('缺少必需的 id 参数'); + } + return request({ - url: '/jobPath/getJobPathDetail', + url: '/jobPath/getJobPathById', method: 'get', - params, + params: requestParams, baseUrlType: 'zytp' }) } @@ -33,24 +44,3 @@ export function getJobPathNum() { }) } -// 导入职业路径 -export function importJobPath(data) { - return request({ - url: '/jobPath/importJobPath', - method: 'post', - data, - baseUrlType: 'zytp' - }) -} - -// 导出职业路径 -export function exportJobPath(params) { - return request({ - url: '/jobPath/exportJobPath', - method: 'get', - params, - baseUrlType: 'zytp', - responseType: 'arraybuffer' - }) -} - diff --git a/apiRc/jobRecommend.js b/apiRc/jobRecommend.js index df1ef7c..59f9282 100644 --- a/apiRc/jobRecommend.js +++ b/apiRc/jobRecommend.js @@ -19,46 +19,15 @@ function createFormData(payload = {}) { } export function recommendJob(data) { - const formData = createFormData({ - jobId: data?.jobId - }) + const params = {}; + if (data?.jobName !== undefined && data?.jobName !== null && data?.jobName !== '') { + params.jobName = String(data.jobName); + } return request({ - url: '/job/recommendJob', - method: 'post', - data: formData, - baseUrlType: 'zytp', - header: { - 'content-type': 'multipart/form-data' - } - }) -} - -export function countJobRecommendRecords(data) { - const formData = createFormData({ - jobId: data?.jobId, - jobName: data?.jobName, - recommendType: data?.recommendType, - startDate: data?.startDate, - endDate: data?.endDate - }) - - return request({ - url: '/jobRecommendRecord/countJobRecommendRecords', - method: 'post', - data: formData, - baseUrlType: 'zytp', - header: { - 'content-type': 'multipart/form-data' - } - }) -} - -export function getJobRecommendRecords(params) { - return request({ - url: '/jobRecommendRecord/getJobRecommendRecords', + url: '/job/recommendJobByJobName', method: 'get', - params, + params: params, baseUrlType: 'zytp' }) } diff --git a/apiRc/jobSkill.js b/apiRc/jobSkill.js index 1ebeedb..4c9f8ac 100644 --- a/apiRc/jobSkill.js +++ b/apiRc/jobSkill.js @@ -13,65 +13,33 @@ export function getJobSkillDetail(params) { }) } -export function getJobPathSkill(data) { - let formData - if (typeof FormData !== 'undefined') { - formData = new FormData() - if (data?.pathId !== undefined && data?.pathId !== null) { - formData.append('pathId', data.pathId) - } - if (data?.currentJobName !== undefined && data?.currentJobName !== null) { - formData.append('currentJobName', data.currentJobName) - } - } else { - formData = { - pathId: data?.pathId ?? '', - currentJobName: data?.currentJobName ?? '' - } - } +// 暂未使用 - 如果需要在 CareerPath.vue 中点击路径职位查看详细技能信息时使用 +// 使用场景:获取职业路径中某个职位的详细技能信息(包含技能分数、类型等) +// export function getJobPathSkill(data) { +// let formData +// if (typeof FormData !== 'undefined') { +// formData = new FormData() +// if (data?.pathId !== undefined && data?.pathId !== null) { +// formData.append('pathId', data.pathId) +// } +// if (data?.currentJobName !== undefined && data?.currentJobName !== null) { +// formData.append('currentJobName', data.currentJobName) +// } +// } else { +// formData = { +// pathId: data?.pathId ?? '', +// currentJobName: data?.currentJobName ?? '' +// } +// } - return request({ - url: '/jobSkillDet/getJobPathSkill', - method: 'post', - data: formData, - baseUrlType: 'zytp', - header: { - 'content-type': 'multipart/form-data' - } - }) -} +// return request({ +// url: '/jobSkillDet/getJobPathSkill', +// method: 'post', +// data: formData, +// baseUrlType: 'zytp', +// header: { +// 'content-type': 'multipart/form-data' +// } +// }) +// } -// 获取技能热度分析列表 -export function getSkillsHeatAnalysisList(params) { - return request({ - url: '/skillsHeatAnalysis/list', - method: 'get', - params, - baseUrlType: 'zytp' - }) -} - -// 获取技能数量 -export function getSkillNum(data) { - let formData - if (typeof FormData !== 'undefined') { - formData = new FormData() - if (data?.skillType !== undefined && data?.skillType !== null) { - formData.append('skillType', data.skillType) - } - } else { - formData = { - skillType: data?.skillType ?? '' - } - } - - return request({ - url: '/skill/getSkillNum', - method: 'post', - data: formData, - baseUrlType: 'zytp', - header: { - 'content-type': 'multipart/form-data' - } - }) -} diff --git a/apiRc/user/user.js b/apiRc/user/user.js index a40ac31..07ae540 100644 --- a/apiRc/user/user.js +++ b/apiRc/user/user.js @@ -8,7 +8,7 @@ import request from '@/utilsRc/request' // 获取用户信息(职业规划推荐用) export function appUserInfo() { return request({ - fullUrl: 'http://222.80.110.161:11111/api/ks/app/user/appUserInfo', + url: '/app/user/appUserInfo', method: 'get' }) } diff --git a/components/CustomTabBar/CustomTabBar.vue b/components/CustomTabBar/CustomTabBar.vue index 72cc36a..83d3fd0 100644 --- a/components/CustomTabBar/CustomTabBar.vue +++ b/components/CustomTabBar/CustomTabBar.vue @@ -4,7 +4,8 @@ class="tabbar-item" v-for="(item, index) in tabbarList" :key="index" - @click="switchTab(item, index)" + @click.stop="switchTab(item, index)" + @tap.stop="switchTab(item, index)" > userInfo.value, (newUserInfo, oldUserInfo) => { // 切换tab const switchTab = (item, index) => { + console.log('switchTab called', item, index); + // 检查是否为"发布岗位"页面,需要判断企业信息是否完整 if (item.path === '/pages/job/publishJob') { // 检查用户是否已登录 @@ -270,8 +273,9 @@ onMounted(() => { display: flex; align-items: center; padding-bottom: env(safe-area-inset-bottom); - z-index: 999; + z-index: 9999; box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.1); + pointer-events: auto; } .tabbar-item { @@ -285,6 +289,8 @@ onMounted(() => { font-size: 22rpx; position: relative; cursor: pointer; + pointer-events: auto; + -webkit-tap-highlight-color: transparent; } .tabbar-icon { diff --git a/docs/职业图谱接口说明.md b/docs/职业图谱接口说明.md new file mode 100644 index 0000000..7615a1c --- /dev/null +++ b/docs/职业图谱接口说明.md @@ -0,0 +1,237 @@ +# 职业图谱功能接口说明 + +## 📋 目录 +- [一、职业路径相关接口](#一职业路径相关接口) +- [二、职业技能相关接口](#二职业技能相关接口) +- [三、职业推荐相关接口](#三职业推荐相关接口) +- [四、接口使用场景](#四接口使用场景) + +--- + +## 一、职业路径相关接口 + +### 1. `getJobPathPage` - 根据职业名称获取路径列表 +- **接口路径**: `/jobPath/getJobPathPage` +- **请求方法**: `GET` +- **接口类型**: `zytp` +- **参数**: + - `jobName` (可选): 职业名称,用于搜索 + - `pageNo`: 页码 + - `pageSize`: 每页数量 +- **返回数据**: + ```json + { + "code": 0, + "data": { + "list": [ + { + "id": 1, + "startJobId": 1, + "startJob": "AI产品经理", + "endJobId": 1, + "endJob": "推荐算法", + "jobOrder": "AI产品经理,AI训练师,图像识别,导航算法,推荐算法", + "jobCount": 5 + } + ], + "total": 16 + } + } + ``` +- **使用场景**: + - ✅ **CareerPath.vue**: 获取目标职业选项列表(下拉选择器) + - ✅ **CareerRecommend.vue**: 通过 `jobName` 查询获取 `jobId`(当缺少 jobId 时) + - ✅ **CareerPath.vue**: 查询时如果没有 jobPathId,通过 jobName 查找 + +--- + +### 2. ``getJobPathById`- 根据职业路径ID获取详情 +- **接口路径**: `/jobPath/getJobPathById` +- **请求方法**: `GET` +- **接口类型**: `zytp` +- **参数**: + - `jobPathId`: 职业路径ID +- **返回数据**: + ```json + { + "data": [ + { + "name": "职位名称", + "skillNameList": "技能1,技能2,技能3" + } + ] + } + ``` +- **使用场景**: + - ✅ **CareerPath.vue**: 获取职业路径的详细信息(起点、中间步骤、终点及每个职位的技能列表) + - 用于显示完整的职业发展路径时间线 + +--- + +### 3. `getJobPathNum` - 获取职业路径数量 +- **接口路径**: `/jobPath/getJobPathNum` +- **请求方法**: `GET` +- **接口类型**: `zytp` +- **参数**: 无 +- **返回数据**: + ```json + { + "data": 16 // 路径总数 + } + ``` +- **使用场景**: + - ✅ **CareerPath.vue**: 显示"系统已收录 X 条职业路径" + +--- + +## 二、职业技能相关接口 + +### 4. `getJobSkillDetail` - 获取职位技能详情 +- **接口路径**: `/jobSkillDet/getJobSkillDet` +- **请求方法**: `GET` +- **接口类型**: `zytp` +- **参数**: + - `jobId` (必需): 职位ID + - `jobName` (可选): 职位名称 +- **返回数据**: + ```json + { + "data": [ + { + "skillName": "技能名称", + "skillScore": "技能分数" + } + ] + } + ``` +- **使用场景**: + - ✅ **career-planning.vue**: 点击推荐职位卡片时,获取该职位的技能详情(用于技能详情弹窗 `SkillDetailPopup`) + - **调用位置**: `handleJobCardClick` 函数中 + +--- + +### 5. `getJobPathSkill` - 获取职业路径技能(已隐藏,暂未使用) +- **接口路径**: `/jobSkillDet/getJobPathSkill` +- **请求方法**: `POST` +- **接口类型**: `zytp` +- **参数**: + - `pathId`: 路径ID + - `currentJobName`: 当前职位名称 +- **返回数据**: `List` (包含技能分数、类型等详细信息) +- **使用场景**: + - ❌ 暂未在代码中使用 + - 💡 **潜在使用场景**: 在 `CareerPath.vue` 中,如果用户点击路径中的某个职位,需要查看该职位在路径中的详细技能信息(包含技能分数、类型等)时,可以使用此接口 + - **当前状态**: 接口已注释隐藏,如需使用请取消注释 + +--- + +## 三、职业推荐相关接口 + +### 8. `recommendJob` - 推荐职位 +- **接口路径**: `/job/recommendJobByJobName` +- **请求方法**: `GET` +- **接口类型**: `zytp` +- **参数**: + - `jobName` (必需): 当前职位名称(从缓存中获取),通过 URL 参数传递,格式:`/job/recommendJobByJobName?jobName=职位名称` +- **返回数据**: + ```json + { + "data": [ + { + "jobId": 123, + "jobName": "推荐职位名称", + "skillList": [ + { + "skillName": "技能名称" + } + ] + } + ] + } + ``` +- **使用场景**: + - ✅ **CareerRecommend.vue**: 根据当前职位名称(从缓存中获取),获取相似推荐职位列表(显示在"相似推荐职位"区域) + +--- + +## 四、接口使用场景 + +### 📍 页面结构 +``` +career-planning.vue (主页面) +├── Tab 0: 职业推荐 (CareerRecommend.vue) +├── Tab 1: 职业路径 (CareerPath.vue) +└── Tab 2: 技能发展 (SkillDevelopment.vue) +``` + +### 📍 职业推荐 Tab (CareerRecommend.vue) +1. **进入页面时**: + - `getJobSkillDetail` - 获取当前职位的技能标签(需要 `jobId`,如果没有 `jobId` 则跳过) + - `recommendJob` - 获取相似推荐职位(需要 `jobId`) + +2. **点击职位卡片时**: + - `getJobSkillDetail` - 获取该职位的技能详情(显示在技能详情弹窗中) + +**注意**: `getJobPathPage` 接口**只在职业路径流程中使用**,不在职业推荐流程中使用。 + +### 📍 职业路径 Tab (CareerPath.vue) +1. **进入页面时**: + - `getJobPathPage` - 获取所有职业路径列表(填充目标职业下拉选择器) + - `getJobPathNum` - 获取职业路径总数(显示"系统已收录 X 条职业路径") + +2. **选择目标职业并点击查询时**: + - `getJobPathPage` - 如果没有 `jobPathId`,通过 `jobName` 查找 + - `getJobPathDetail` (实际: `getJobPathById`) - 获取职业路径详情(显示完整路径时间线) + +### 📍 技能发展 Tab (SkillDevelopment.vue) +1. **进入页面时**: + - 暂无接口调用 + +--- + +## 🔑 关键接口调用流程 + +### 流程1: 获取当前职位技能 +``` +CareerRecommend.vue +└── getJobSkillDetail(jobId, jobName) → 获取技能列表 + (如果没有 jobId,则跳过获取技能) +``` + +### 流程2: 查询职业路径 +``` +CareerPath.vue +├── getJobPathPage() → 获取路径列表(填充下拉选择器) +├── 用户选择目标职业 +└── getJobPathById(jobPathId) → 获取路径详情(显示时间线) +``` + +### 流程3: 获取推荐职位 +``` +CareerRecommend.vue +└── recommendJob(jobId) → 获取相似推荐职位列表 +``` + +--- + +## ⚠️ 注意事项 + +1. **接口返回码**: + - `code: 0` 和 `code: 200` 都表示成功 + - 已在 `request.js` 中处理 + +2. **参数要求**: + - `getJobSkillDetail` 必须提供 `jobId`,如果没有 `jobId` 则跳过获取技能 + - `getJobPathPage` **只在职业路径流程中使用**,不在职业推荐流程中使用 + +3. **数据格式**: + - `getJobPathPage` 返回的 `list` 在 `response.data.list` 中 + - `getJobPathById` 返回的详情在 `response.data` 中(数组格式) + +4. **接口使用范围**: + - `getJobPathPage` **只在职业路径流程(CareerPath.vue)中使用** + - 职业推荐流程(CareerRecommend.vue)**不使用** `getJobPathPage` 接口 + +5. **接口前缀**: + - 所有 `zytp` 类型的接口使用: `http://ks.zhaopinzao8dian.com/api/ks_zytp/admin-api/zytp` + diff --git a/pages/chat/chat.vue b/pages/chat/chat.vue index 33a7157..e43c8fa 100644 --- a/pages/chat/chat.vue +++ b/pages/chat/chat.vue @@ -177,7 +177,7 @@ footer-height = 98rpx /* 页面容器 */ .container { position: fixed; - z-index: 1000; + z-index: 1; width: 100vw; height: calc(100% - var(--window-bottom)); overflow: hidden; diff --git a/pages/service/career-planning.vue b/pages/service/career-planning.vue index 3d8c31d..89a48c5 100644 --- a/pages/service/career-planning.vue +++ b/pages/service/career-planning.vue @@ -40,9 +40,20 @@ :current-job-id="currentJobId" :current-job-name="currentJobName" @job-card-click="handleJobCardClick" + @skills-updated="handleRecommendSkillsUpdated" + /> + + - - @@ -56,8 +67,8 @@ @@ -349,7 +510,6 @@ onMounted(() => { position: relative; z-index: 1; overflow: hidden; - padding-bottom: 88rpx; } @@ -357,6 +517,8 @@ onMounted(() => { flex: 1; height: 0; width: 100%; + padding-bottom: calc(88rpx + env(safe-area-inset-bottom)); + box-sizing: border-box; } .tabbar-wrapper { @@ -366,4 +528,4 @@ onMounted(() => { right: 0; z-index: 999; } - \ No newline at end of file + diff --git a/pages/service/components/CareerPath.vue b/pages/service/components/CareerPath.vue index c8e0a0b..6aae2c6 100644 --- a/pages/service/components/CareerPath.vue +++ b/pages/service/components/CareerPath.vue @@ -13,7 +13,7 @@ @@ -115,11 +115,21 @@