提交
This commit is contained in:
56
apiRc/jobPath.js
Normal file
56
apiRc/jobPath.js
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* @Date: 2025-11-12
|
||||||
|
* @Description: 职业路径相关接口
|
||||||
|
*/
|
||||||
|
import request from '@/utilsRc/request'
|
||||||
|
|
||||||
|
// 根据职业名称获取路径列表
|
||||||
|
export function getJobPathPage(params) {
|
||||||
|
return request({
|
||||||
|
url: '/jobPath/getJobPathPage',
|
||||||
|
method: 'get',
|
||||||
|
params,
|
||||||
|
baseUrlType: 'zytp'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据职业路径ID获取详情
|
||||||
|
export function getJobPathDetail(params) {
|
||||||
|
return request({
|
||||||
|
url: '/jobPath/getJobPathDetail',
|
||||||
|
method: 'get',
|
||||||
|
params,
|
||||||
|
baseUrlType: 'zytp'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取职业路径数量
|
||||||
|
export function getJobPathNum() {
|
||||||
|
return request({
|
||||||
|
url: '/jobPath/getJobPathNum',
|
||||||
|
method: 'get',
|
||||||
|
baseUrlType: 'zytp'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导入职业路径
|
||||||
|
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'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
64
apiRc/jobRecommend.js
Normal file
64
apiRc/jobRecommend.js
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* @Date: 2025-11-12
|
||||||
|
* @Description: 职业推荐相关接口
|
||||||
|
*/
|
||||||
|
import request from '@/utilsRc/request'
|
||||||
|
|
||||||
|
function createFormData(payload = {}) {
|
||||||
|
if (typeof FormData !== 'undefined') {
|
||||||
|
const formData = new FormData()
|
||||||
|
Object.keys(payload).forEach(key => {
|
||||||
|
const value = payload[key]
|
||||||
|
if (value !== undefined && value !== null && value !== '') {
|
||||||
|
formData.append(key, value)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return formData
|
||||||
|
}
|
||||||
|
return payload
|
||||||
|
}
|
||||||
|
|
||||||
|
export function recommendJob(data) {
|
||||||
|
const formData = createFormData({
|
||||||
|
jobId: data?.jobId
|
||||||
|
})
|
||||||
|
|
||||||
|
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',
|
||||||
|
method: 'get',
|
||||||
|
params,
|
||||||
|
baseUrlType: 'zytp'
|
||||||
|
})
|
||||||
|
}
|
||||||
77
apiRc/jobSkill.js
Normal file
77
apiRc/jobSkill.js
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* @Date: 2025-11-12
|
||||||
|
* @Description: 职业技能相关接口
|
||||||
|
*/
|
||||||
|
import request from '@/utilsRc/request'
|
||||||
|
|
||||||
|
export function getJobSkillDetail(params) {
|
||||||
|
return request({
|
||||||
|
url: '/jobSkillDet/getJobSkillDet',
|
||||||
|
method: 'get',
|
||||||
|
params,
|
||||||
|
baseUrlType: 'zytp'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
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'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取技能热度分析列表
|
||||||
|
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'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -8,7 +8,7 @@ import request from '@/utilsRc/request'
|
|||||||
// 获取用户信息(职业规划推荐用)
|
// 获取用户信息(职业规划推荐用)
|
||||||
export function appUserInfo() {
|
export function appUserInfo() {
|
||||||
return request({
|
return request({
|
||||||
url: '/app/user/appUserInfo',
|
fullUrl: 'http://222.80.110.161:11111/api/ks/app/user/appUserInfo',
|
||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,7 @@
|
|||||||
"quickapp" : {},
|
"quickapp" : {},
|
||||||
/* 小程序特有相关 */
|
/* 小程序特有相关 */
|
||||||
"mp-weixin" : {
|
"mp-weixin" : {
|
||||||
"appid" : "wx9d1cbc11c8c40ba7",
|
"appid" : "wx4aa34488b965a331",
|
||||||
"setting" : {
|
"setting" : {
|
||||||
"urlCheck" : false,
|
"urlCheck" : false,
|
||||||
"es6" : true,
|
"es6" : true,
|
||||||
|
|||||||
@@ -35,10 +35,14 @@
|
|||||||
|
|
||||||
<!-- 内容区域 -->
|
<!-- 内容区域 -->
|
||||||
<scroll-view scroll-y class="content-scroll">
|
<scroll-view scroll-y class="content-scroll">
|
||||||
<component
|
<CareerRecommend
|
||||||
:is="currentComponent"
|
v-if="activeTab === 0"
|
||||||
|
:current-job-id="currentJobId"
|
||||||
|
:current-job-name="currentJobName"
|
||||||
@job-card-click="handleJobCardClick"
|
@job-card-click="handleJobCardClick"
|
||||||
></component>
|
/>
|
||||||
|
<CareerPath v-else-if="activeTab === 1" />
|
||||||
|
<SkillDevelopment v-else />
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
@@ -50,9 +54,10 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, inject, nextTick, onMounted, computed } from 'vue';
|
import { ref, inject, nextTick, onMounted } from 'vue';
|
||||||
import { onLoad } from '@dcloudio/uni-app';
|
import { onLoad } from '@dcloudio/uni-app';
|
||||||
import { appUserInfo } from '@/apiRc/user/user.js';
|
import { appUserInfo } from '@/apiRc/user/user.js';
|
||||||
|
import { getJobSkillDetail } from '@/apiRc/jobSkill.js';
|
||||||
import RemindPopup from './components/RemindPopup.vue';
|
import RemindPopup from './components/RemindPopup.vue';
|
||||||
import PageHeader from './components/PageHeader.vue';
|
import PageHeader from './components/PageHeader.vue';
|
||||||
import SkillDetailPopup from './components/SkillDetailPopup.vue';
|
import SkillDetailPopup from './components/SkillDetailPopup.vue';
|
||||||
@@ -76,12 +81,9 @@ const activeTab = ref(0);
|
|||||||
const selectedJobTitle = ref('');
|
const selectedJobTitle = ref('');
|
||||||
const selectedJobPossessedSkills = ref([]);
|
const selectedJobPossessedSkills = ref([]);
|
||||||
const selectedJobImprovementSkills = ref([]);
|
const selectedJobImprovementSkills = ref([]);
|
||||||
|
const isLoadingJobSkill = ref(false);
|
||||||
// 当前组件
|
const currentJobId = ref(null);
|
||||||
const currentComponent = computed(() => {
|
const currentJobName = ref('');
|
||||||
const components = [CareerRecommend, CareerPath, SkillDevelopment];
|
|
||||||
return components[activeTab.value];
|
|
||||||
});
|
|
||||||
|
|
||||||
// 打开弹窗
|
// 打开弹窗
|
||||||
function openRemindPopup() {
|
function openRemindPopup() {
|
||||||
@@ -105,30 +107,57 @@ function openRemindPopup() {
|
|||||||
// 获取提醒信息的接口
|
// 获取提醒信息的接口
|
||||||
async function getRemindInfo() {
|
async function getRemindInfo() {
|
||||||
try {
|
try {
|
||||||
// 接口已准备好,但暂时不使用(按用户要求)
|
const response = await appUserInfo();
|
||||||
// const response = await appUserInfo();
|
if (response && response.code === 200) {
|
||||||
// if (response && response.code === 200) {
|
const data = response.data || {};
|
||||||
// const data = response.data || {};
|
const reminders = [];
|
||||||
// const jobTitles = data.jobTitles || [];
|
|
||||||
// const appSkillsList = data.appSkillsList || [];
|
currentJobId.value = data?.jobId ?? data?.currentJobId ?? null;
|
||||||
//
|
currentJobName.value = data?.jobName ?? data?.currentJobName ?? '';
|
||||||
// remindList.value = [];
|
|
||||||
// if (!jobTitles || jobTitles.length === 0) {
|
if (Array.isArray(data.remindList) && data.remindList.length > 0) {
|
||||||
// remindList.value.push('求职期望;');
|
reminders.push(
|
||||||
// }
|
...data.remindList
|
||||||
//
|
.filter(item => typeof item === 'string' && item.trim().length > 0)
|
||||||
// if (remindList.value.length > 0) {
|
.map(item => item.trim())
|
||||||
// openRemindPopup();
|
);
|
||||||
// return;
|
} else {
|
||||||
// }
|
const jobTitles = Array.isArray(data.jobTitles) ? data.jobTitles : [];
|
||||||
// }
|
const appSkillsList = Array.isArray(data.appSkillsList) ? data.appSkillsList : [];
|
||||||
|
|
||||||
// 暂时使用测试数据显示弹窗
|
if (!currentJobName.value && jobTitles.length > 0) {
|
||||||
remindList.value = ['求职期望;'];
|
currentJobName.value = jobTitles[0];
|
||||||
openRemindPopup();
|
}
|
||||||
|
|
||||||
|
if (jobTitles.length === 0) {
|
||||||
|
reminders.push('请完善求职期望');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (appSkillsList.length === 0) {
|
||||||
|
reminders.push('请完善技能信息');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reminders.length === 0) {
|
||||||
|
reminders.push('暂无待完善信息');
|
||||||
|
}
|
||||||
|
|
||||||
|
remindList.value = reminders;
|
||||||
|
if (!currentJobName.value) {
|
||||||
|
currentJobName.value = '前端开发工程师';
|
||||||
|
}
|
||||||
|
openRemindPopup();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error('接口返回异常');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('获取提醒信息失败:', error);
|
console.error('获取提醒信息失败:', error);
|
||||||
remindList.value = ['求职期望;'];
|
currentJobId.value = null;
|
||||||
|
if (!currentJobName.value) {
|
||||||
|
currentJobName.value = '前端开发工程师';
|
||||||
|
}
|
||||||
|
remindList.value = ['获取提醒信息失败,请稍后重试'];
|
||||||
openRemindPopup();
|
openRemindPopup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -166,12 +195,105 @@ function handleMoreClick() {
|
|||||||
console.log('更多点击');
|
console.log('更多点击');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizeSkillLevel(score) {
|
||||||
|
const numericScore = Number(score);
|
||||||
|
if (Number.isNaN(numericScore)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
const rounded = Math.round(numericScore);
|
||||||
|
return Math.max(1, Math.min(6, rounded));
|
||||||
|
}
|
||||||
|
|
||||||
|
function splitSkillListByScore(skills = []) {
|
||||||
|
if (!Array.isArray(skills) || skills.length === 0) {
|
||||||
|
return {
|
||||||
|
possessed: [],
|
||||||
|
improvement: []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const sorted = [...skills].sort((a, b) => (Number(b.skillScore) || 0) - (Number(a.skillScore) || 0));
|
||||||
|
const midpoint = Math.ceil(sorted.length / 2);
|
||||||
|
const mapSkill = (item) => ({
|
||||||
|
name: item?.skillName || '',
|
||||||
|
level: normalizeSkillLevel(item?.skillScore)
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
possessed: sorted.slice(0, midpoint).map(mapSkill),
|
||||||
|
improvement: sorted.slice(midpoint).map(mapSkill)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// 处理职位卡片点击
|
// 处理职位卡片点击
|
||||||
function handleJobCardClick(job) {
|
async function handleJobCardClick(job) {
|
||||||
selectedJobTitle.value = job.title || '';
|
if (!job) {
|
||||||
selectedJobPossessedSkills.value = job.possessedSkills || [];
|
return;
|
||||||
selectedJobImprovementSkills.value = job.improvementSkills || [];
|
}
|
||||||
skillDetailPopup.value?.open();
|
|
||||||
|
selectedJobTitle.value = job.title || job.jobName || '';
|
||||||
|
selectedJobPossessedSkills.value = [];
|
||||||
|
selectedJobImprovementSkills.value = [];
|
||||||
|
|
||||||
|
if (isLoadingJobSkill.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
isLoadingJobSkill.value = true;
|
||||||
|
uni.showLoading({
|
||||||
|
title: '加载中...',
|
||||||
|
mask: true
|
||||||
|
});
|
||||||
|
|
||||||
|
const fallbackSkills = Array.isArray(job?.rawSkills) ? job.rawSkills : [];
|
||||||
|
const params = {};
|
||||||
|
if (job?.jobId) {
|
||||||
|
params.jobId = job.jobId;
|
||||||
|
}
|
||||||
|
if (job?.title) {
|
||||||
|
params.jobName = job.title;
|
||||||
|
} else if (job?.jobName) {
|
||||||
|
params.jobName = job.jobName;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await getJobSkillDetail(params);
|
||||||
|
const skillList = Array.isArray(response?.data) ? response.data : [];
|
||||||
|
const { possessed, improvement } = splitSkillListByScore(skillList);
|
||||||
|
|
||||||
|
if (possessed.length === 0 && improvement.length === 0) {
|
||||||
|
if (fallbackSkills.length === 0) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '暂无技能数据',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const fallbackSplit = splitSkillListByScore(fallbackSkills);
|
||||||
|
selectedJobPossessedSkills.value = fallbackSplit.possessed;
|
||||||
|
selectedJobImprovementSkills.value = fallbackSplit.improvement;
|
||||||
|
} else {
|
||||||
|
selectedJobPossessedSkills.value = possessed;
|
||||||
|
selectedJobImprovementSkills.value = improvement;
|
||||||
|
}
|
||||||
|
skillDetailPopup.value?.open();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取职位技能详情失败:', error);
|
||||||
|
if (fallbackSkills.length > 0) {
|
||||||
|
const fallbackSplit = splitSkillListByScore(fallbackSkills);
|
||||||
|
selectedJobPossessedSkills.value = fallbackSplit.possessed;
|
||||||
|
selectedJobImprovementSkills.value = fallbackSplit.improvement;
|
||||||
|
skillDetailPopup.value?.open();
|
||||||
|
} else {
|
||||||
|
uni.showToast({
|
||||||
|
title: '获取技能信息失败',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
isLoadingJobSkill.value = false;
|
||||||
|
uni.hideLoading();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理技能弹出层关闭
|
// 处理技能弹出层关闭
|
||||||
|
|||||||
@@ -42,6 +42,9 @@
|
|||||||
<text>查询职业发展路径</text>
|
<text>查询职业发展路径</text>
|
||||||
<uni-icons type="search" size="18" color="#FFFFFF"></uni-icons>
|
<uni-icons type="search" size="18" color="#FFFFFF"></uni-icons>
|
||||||
</button>
|
</button>
|
||||||
|
<view v-if="totalPathCount > 0" class="path-summary">
|
||||||
|
系统已收录 {{ totalPathCount }} 条职业路径
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 职业发展路径区域 -->
|
<!-- 职业发展路径区域 -->
|
||||||
@@ -113,75 +116,141 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted } from 'vue';
|
import { ref, onMounted } from 'vue';
|
||||||
|
import { getJobPathPage, getJobPathDetail, getJobPathNum } from '@/apiRc/jobPath.js';
|
||||||
|
|
||||||
// 当前职位(从接口获取,只读)
|
// 当前职位(从接口获取,只读)
|
||||||
const currentPosition = ref('前端开发工程师');
|
const currentPosition = ref('前端开发工程师');
|
||||||
|
|
||||||
// 目标职业选项(根据当前职位动态获取)
|
// 目标职业选项列表
|
||||||
const targetCareerOptions = ref([
|
const targetCareerOptions = ref([]);
|
||||||
{ label: '互联网/IT', value: 'internet_it' },
|
|
||||||
{ label: '高级前端开发工程师', value: 'senior_frontend' },
|
|
||||||
{ label: '前端架构师', value: 'frontend_architect' },
|
|
||||||
{ label: '技术总监', value: 'tech_director' }
|
|
||||||
]);
|
|
||||||
|
|
||||||
const selectedTargetIndex = ref(-1);
|
const selectedTargetIndex = ref(-1);
|
||||||
|
const selectedJobPathId = ref(null);
|
||||||
|
|
||||||
// 职业路径数据(后续从接口获取)
|
// 职业路径数量
|
||||||
const pathData = ref({
|
const totalPathCount = ref(0);
|
||||||
|
|
||||||
|
// 初始路径数据
|
||||||
|
const emptyPathData = {
|
||||||
start: {
|
start: {
|
||||||
title: '初级网络安全管理员',
|
title: '暂无数据',
|
||||||
skills: ['React', 'Node.js', 'Typescript', '数据库']
|
skills: []
|
||||||
},
|
},
|
||||||
steps: [
|
steps: [],
|
||||||
{
|
|
||||||
title: '中级网络安全工程师',
|
|
||||||
skills: ['Vue3', '微前端', '性能优化', '团队管理']
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '资深安全顾问(横向发展)',
|
|
||||||
skills: ['架构设计', '技术选型', '工程化', '团队领导']
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '高级网络安全架构师',
|
|
||||||
skills: ['架构设计', '技术选型', '工程化', '团队领导']
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '技术部门经理',
|
|
||||||
skills: ['架构设计', '技术选型', '工程化', '团队领导']
|
|
||||||
}
|
|
||||||
],
|
|
||||||
end: {
|
end: {
|
||||||
title: 'IT 项目总监',
|
title: '暂无数据',
|
||||||
skills: ['架构设计', '技术选型', '工程化', '团队领导']
|
skills: []
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
// 获取当前职位信息(从接口获取)
|
const pathData = ref({ ...emptyPathData });
|
||||||
async function getCurrentPosition() {
|
const isLoadingPath = ref(false);
|
||||||
// TODO: 调用接口获取当前职位
|
|
||||||
// const response = await getCareerCurrentPosition();
|
function parseSkillList(skillString) {
|
||||||
// if (response && response.code === 200) {
|
if (!skillString) {
|
||||||
// currentPosition.value = response.data?.position || '';
|
return [];
|
||||||
// // 根据当前职位获取目标职业选项
|
}
|
||||||
// await getTargetCareerOptions(currentPosition.value);
|
return skillString
|
||||||
// }
|
.split(/[,,]/)
|
||||||
|
.map(item => item.trim())
|
||||||
|
.filter(item => item.length > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据当前职位获取目标职业选项
|
function resetPathData() {
|
||||||
async function getTargetCareerOptions(position) {
|
pathData.value = {
|
||||||
// TODO: 调用接口获取目标职业选项
|
start: { ...emptyPathData.start },
|
||||||
// const response = await getTargetCareers(position);
|
steps: [],
|
||||||
// if (response && response.code === 200) {
|
end: { ...emptyPathData.end }
|
||||||
// targetCareerOptions.value = response.data || [];
|
};
|
||||||
// }
|
}
|
||||||
|
|
||||||
|
async function fetchTargetCareerOptions(keyword = '') {
|
||||||
|
try {
|
||||||
|
const response = await getJobPathPage({
|
||||||
|
jobName: keyword,
|
||||||
|
pageNo: 1,
|
||||||
|
pageSize: 100
|
||||||
|
});
|
||||||
|
const list = response?.data?.list || [];
|
||||||
|
targetCareerOptions.value = list.map(item => ({
|
||||||
|
label: item.endJob || item.startJob || '未知职位',
|
||||||
|
value: item.id,
|
||||||
|
startJob: item.startJob,
|
||||||
|
endJob: item.endJob,
|
||||||
|
jobOrder: item.jobOrder
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (targetCareerOptions.value.length === 0) {
|
||||||
|
selectedTargetIndex.value = -1;
|
||||||
|
selectedJobPathId.value = null;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取职业路径列表失败:', error);
|
||||||
|
targetCareerOptions.value = [];
|
||||||
|
selectedTargetIndex.value = -1;
|
||||||
|
selectedJobPathId.value = null;
|
||||||
|
uni.showToast({
|
||||||
|
title: '职业路径列表获取失败',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchPathCount() {
|
||||||
|
try {
|
||||||
|
const response = await getJobPathNum();
|
||||||
|
totalPathCount.value = response?.data ?? 0;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取职业路径数量失败:', error);
|
||||||
|
totalPathCount.value = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadPathDetail(jobPathId) {
|
||||||
|
try {
|
||||||
|
const response = await getJobPathDetail({
|
||||||
|
jobPathId
|
||||||
|
});
|
||||||
|
const details = Array.isArray(response?.data) ? response.data : [];
|
||||||
|
if (details.length === 0) {
|
||||||
|
resetPathData();
|
||||||
|
uni.showToast({
|
||||||
|
title: '暂无职业路径数据',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const normalized = details.map(item => ({
|
||||||
|
title: item?.name || '未命名职位',
|
||||||
|
skills: parseSkillList(item?.skillNameList)
|
||||||
|
}));
|
||||||
|
|
||||||
|
const start = normalized[0] || { title: '暂无数据', skills: [] };
|
||||||
|
const end = normalized[normalized.length - 1] || { title: '暂无数据', skills: [] };
|
||||||
|
const steps = normalized.slice(1, normalized.length - 1);
|
||||||
|
|
||||||
|
pathData.value = {
|
||||||
|
start,
|
||||||
|
steps,
|
||||||
|
end
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取职业路径详情失败:', error);
|
||||||
|
uni.showToast({
|
||||||
|
title: '获取路径详情失败',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleTargetChange(e) {
|
function handleTargetChange(e) {
|
||||||
selectedTargetIndex.value = e.detail.value;
|
const index = Number(e.detail.value);
|
||||||
|
selectedTargetIndex.value = index;
|
||||||
|
const option = targetCareerOptions.value[index];
|
||||||
|
selectedJobPathId.value = option ? option.value : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleQuery() {
|
async function handleQuery() {
|
||||||
if (selectedTargetIndex.value < 0) {
|
if (selectedTargetIndex.value < 0) {
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: '请选择目标职业',
|
title: '请选择目标职业',
|
||||||
@@ -189,13 +258,72 @@ function handleQuery() {
|
|||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const selectedTarget = targetCareerOptions.value[selectedTargetIndex.value];
|
|
||||||
console.log('查询职业发展路径', currentPosition.value, selectedTarget);
|
const option = targetCareerOptions.value[selectedTargetIndex.value];
|
||||||
// TODO: 调用接口查询职业路径
|
if (!option) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '目标职业数据异常',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let jobPathId = option.value;
|
||||||
|
|
||||||
|
isLoadingPath.value = true;
|
||||||
|
uni.showLoading({
|
||||||
|
title: '加载中...',
|
||||||
|
mask: true
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!jobPathId) {
|
||||||
|
const response = await getJobPathPage({
|
||||||
|
jobName: option.label,
|
||||||
|
pageNo: 1,
|
||||||
|
pageSize: 100
|
||||||
|
});
|
||||||
|
jobPathId = response?.data?.list?.[0]?.id || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!jobPathId) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '未找到职业路径',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
resetPathData();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
selectedJobPathId.value = jobPathId;
|
||||||
|
await loadPathDetail(jobPathId);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('查询职业路径失败:', error);
|
||||||
|
uni.showToast({
|
||||||
|
title: '查询失败,请重试',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
isLoadingPath.value = false;
|
||||||
|
uni.hideLoading();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
// 获取当前职位信息(从接口获取)
|
||||||
getCurrentPosition();
|
async function getCurrentPosition() {
|
||||||
|
// TODO: 调用接口获取当前职位
|
||||||
|
// const response = await getCareerCurrentPosition();
|
||||||
|
// if (response && response.code === 200) {
|
||||||
|
// currentPosition.value = response.data?.position || '';
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await getCurrentPosition();
|
||||||
|
await Promise.all([
|
||||||
|
fetchTargetCareerOptions(),
|
||||||
|
fetchPathCount()
|
||||||
|
]);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -291,6 +419,13 @@ onMounted(() => {
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.path-summary {
|
||||||
|
margin-top: 16rpx;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #666666;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
.path-section {
|
.path-section {
|
||||||
background-color: #FFFFFF;
|
background-color: #FFFFFF;
|
||||||
border-radius: 16rpx;
|
border-radius: 16rpx;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<view class="card-title">当前职位信息</view>
|
<view class="card-title">当前职位信息</view>
|
||||||
<view class="card-content">
|
<view class="card-content">
|
||||||
<text class="label">当前职位</text>
|
<text class="label">当前职位</text>
|
||||||
<text class="value">{{ currentJob || '前端开发工程师' }}</text>
|
<text class="value">{{ currentJobDisplay }}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
@@ -20,11 +20,16 @@
|
|||||||
>
|
>
|
||||||
{{ skill }}
|
{{ skill }}
|
||||||
</view>
|
</view>
|
||||||
|
<text v-if="!skillTags.length && !isLoadingSkillTags" class="empty-text">暂无技能数据</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 相似推荐职位 -->
|
<!-- 相似推荐职位 -->
|
||||||
<view class="section-title">相似推荐职位</view>
|
<view class="section-title">
|
||||||
|
相似推荐职位
|
||||||
|
<text v-if="recommendRecordCount > 0" class="recommend-count">共{{ recommendRecordCount }}条记录</text>
|
||||||
|
</view>
|
||||||
|
<view v-if="!isLoadingRecommend && recommendedJobs.length === 0" class="empty-text">暂无推荐职位</view>
|
||||||
<view
|
<view
|
||||||
class="job-item-card"
|
class="job-item-card"
|
||||||
v-for="(job, index) in recommendedJobs"
|
v-for="(job, index) in recommendedJobs"
|
||||||
@@ -49,99 +54,139 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from 'vue';
|
import { ref, computed, watch } from 'vue';
|
||||||
|
import { getJobSkillDetail } from '@/apiRc/jobSkill.js';
|
||||||
|
import { recommendJob, countJobRecommendRecords, getJobRecommendRecords } from '@/apiRc/jobRecommend.js';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
currentJobId: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
currentJobName: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const emit = defineEmits(['job-card-click']);
|
const emit = defineEmits(['job-card-click']);
|
||||||
|
|
||||||
// 当前职位信息(后续从接口获取)
|
const skillTags = ref([]);
|
||||||
// TODO: 从接口获取当前职位信息
|
const recommendedJobs = ref([]);
|
||||||
// async function getCurrentJob() {
|
const recommendRecordCount = ref(0);
|
||||||
// try {
|
const recommendRecords = ref([]);
|
||||||
// const response = await getCareerCurrentJob();
|
const isLoadingSkillTags = ref(false);
|
||||||
// if (response && response.code === 200) {
|
const isLoadingRecommend = ref(false);
|
||||||
// currentJob.value = response.data?.jobTitle || '前端开发工程师';
|
const isLoadingRecords = ref(false);
|
||||||
// }
|
|
||||||
// } catch (error) {
|
|
||||||
// console.error('获取当前职位失败:', error);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
const currentJob = ref('前端开发工程师'); // mock数据
|
|
||||||
|
|
||||||
// 技能标签列表(后续从接口获取)
|
const currentJobDisplay = computed(() => props.currentJobName || '前端开发工程师');
|
||||||
const skillTags = ref(['JavaScript', 'React', 'Vue', 'CSS3', 'HTML5', 'Git', 'Webpack', 'TypeScript']);
|
|
||||||
|
|
||||||
// 相似推荐职位列表(后续从接口获取)
|
function normalizeSkillListForDisplay(skillList = []) {
|
||||||
const recommendedJobs = ref([
|
return (Array.isArray(skillList) ? skillList : [])
|
||||||
{
|
.map(item => item?.skillName)
|
||||||
id: 1,
|
.filter(name => !!name);
|
||||||
title: '全栈开发工程师',
|
}
|
||||||
skills: ['React', 'Node.js', 'TypeScript', '数据库'],
|
|
||||||
possessedSkills: [
|
async function fetchCurrentJobSkills() {
|
||||||
{ name: 'React', level: 5 },
|
if (!props.currentJobId && !props.currentJobName) {
|
||||||
{ name: 'JavaScript', level: 5 },
|
skillTags.value = [];
|
||||||
{ name: 'HTML/CSS', level: 6 },
|
return;
|
||||||
{ name: 'Git', level: 5 }
|
|
||||||
],
|
|
||||||
improvementSkills: [
|
|
||||||
{ name: 'Node.js', level: 3 },
|
|
||||||
{ name: '数据库设计', level: 3 },
|
|
||||||
{ name: 'RESTful API', level: 3 },
|
|
||||||
{ name: 'Docker', level: 3 }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
title: '高级前端开发工程师',
|
|
||||||
skills: ['React', 'Vue', 'TypeScript', 'Webpack'],
|
|
||||||
possessedSkills: [
|
|
||||||
{ name: 'React', level: 5 },
|
|
||||||
{ name: 'Vue', level: 4 },
|
|
||||||
{ name: 'JavaScript', level: 5 }
|
|
||||||
],
|
|
||||||
improvementSkills: [
|
|
||||||
{ name: 'TypeScript', level: 3 },
|
|
||||||
{ name: 'Webpack', level: 3 }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
title: '前端架构师',
|
|
||||||
skills: ['React', 'Vue', 'TypeScript', '架构设计'],
|
|
||||||
possessedSkills: [
|
|
||||||
{ name: 'React', level: 6 },
|
|
||||||
{ name: 'Vue', level: 5 }
|
|
||||||
],
|
|
||||||
improvementSkills: [
|
|
||||||
{ name: '架构设计', level: 3 },
|
|
||||||
{ name: '技术选型', level: 3 }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 4,
|
|
||||||
title: '前端架构师',
|
|
||||||
skills: ['架构设计', '技术选型', '工程化', '团队领导'],
|
|
||||||
possessedSkills: [
|
|
||||||
{ name: '工程化', level: 4 }
|
|
||||||
],
|
|
||||||
improvementSkills: [
|
|
||||||
{ name: '架构设计', level: 3 },
|
|
||||||
{ name: '技术选型', level: 3 },
|
|
||||||
{ name: '团队领导', level: 2 }
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
]);
|
|
||||||
|
|
||||||
// TODO: 从接口获取推荐职位数据
|
isLoadingSkillTags.value = true;
|
||||||
// async function getRecommendedJobs() {
|
try {
|
||||||
// try {
|
const params = {};
|
||||||
// const response = await getCareerRecommendJobs();
|
if (props.currentJobId !== null && props.currentJobId !== undefined && props.currentJobId !== '') {
|
||||||
// if (response && response.code === 200) {
|
params.jobId = props.currentJobId;
|
||||||
// recommendedJobs.value = response.data || [];
|
}
|
||||||
// }
|
if (props.currentJobName) {
|
||||||
// } catch (error) {
|
params.jobName = props.currentJobName;
|
||||||
// console.error('获取推荐职位失败:', error);
|
}
|
||||||
// }
|
const response = await getJobSkillDetail(params);
|
||||||
// }
|
const list = Array.isArray(response?.data) ? response.data : [];
|
||||||
|
skillTags.value = normalizeSkillListForDisplay(list);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取当前职位技能失败:', error);
|
||||||
|
skillTags.value = [];
|
||||||
|
} finally {
|
||||||
|
isLoadingSkillTags.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchRecommendedJobs() {
|
||||||
|
const hasJobId = props.currentJobId !== null && props.currentJobId !== undefined && props.currentJobId !== '';
|
||||||
|
if (!hasJobId) {
|
||||||
|
recommendedJobs.value = [];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
isLoadingRecommend.value = true;
|
||||||
|
try {
|
||||||
|
const response = await recommendJob({
|
||||||
|
jobId: props.currentJobId
|
||||||
|
});
|
||||||
|
const list = Array.isArray(response?.data) ? response.data : [];
|
||||||
|
recommendedJobs.value = list.map((item, index) => {
|
||||||
|
const rawSkills = Array.isArray(item?.skillList) ? item.skillList : [];
|
||||||
|
return {
|
||||||
|
id: item?.jobId ?? index,
|
||||||
|
jobId: item?.jobId ?? null,
|
||||||
|
title: item?.jobName || `推荐职位${index + 1}`,
|
||||||
|
jobName: item?.jobName || '',
|
||||||
|
skills: normalizeSkillListForDisplay(rawSkills),
|
||||||
|
rawSkills
|
||||||
|
};
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取推荐职位失败:', error);
|
||||||
|
recommendedJobs.value = [];
|
||||||
|
} finally {
|
||||||
|
isLoadingRecommend.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchRecommendRecordInfo() {
|
||||||
|
const hasJobId = props.currentJobId !== null && props.currentJobId !== undefined && props.currentJobId !== '';
|
||||||
|
const hasJobName = !!props.currentJobName;
|
||||||
|
if (!hasJobId && !hasJobName) {
|
||||||
|
recommendRecordCount.value = 0;
|
||||||
|
recommendRecords.value = [];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
isLoadingRecords.value = true;
|
||||||
|
try {
|
||||||
|
const [countRes, listRes] = await Promise.all([
|
||||||
|
countJobRecommendRecords({
|
||||||
|
jobId: hasJobId ? props.currentJobId : undefined,
|
||||||
|
jobName: props.currentJobName
|
||||||
|
}),
|
||||||
|
getJobRecommendRecords({
|
||||||
|
jobName: props.currentJobName || '',
|
||||||
|
pageNo: 1,
|
||||||
|
pageSize: 10
|
||||||
|
})
|
||||||
|
]);
|
||||||
|
recommendRecordCount.value = Number(countRes?.data) || 0;
|
||||||
|
recommendRecords.value = Array.isArray(listRes?.data?.list) ? listRes.data.list : [];
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取推荐记录失败:', error);
|
||||||
|
recommendRecordCount.value = 0;
|
||||||
|
recommendRecords.value = [];
|
||||||
|
} finally {
|
||||||
|
isLoadingRecords.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => [props.currentJobId, props.currentJobName],
|
||||||
|
() => {
|
||||||
|
fetchCurrentJobSkills();
|
||||||
|
fetchRecommendedJobs();
|
||||||
|
fetchRecommendRecordInfo();
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
|
|
||||||
function handleJobSearch(job) {
|
function handleJobSearch(job) {
|
||||||
console.log('搜索职位:', job.title);
|
console.log('搜索职位:', job.title);
|
||||||
@@ -285,6 +330,19 @@ function handleJobCardClick(job) {
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.recommend-count {
|
||||||
|
margin-left: 12rpx;
|
||||||
|
font-size: 22rpx;
|
||||||
|
color: #666666;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-text {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #999999;
|
||||||
|
line-height: 34rpx;
|
||||||
|
}
|
||||||
|
|
||||||
button::after {
|
button::after {
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,6 +48,7 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted } from 'vue';
|
import { ref, onMounted } from 'vue';
|
||||||
import SkillWeightPopup from './SkillWeightPopup.vue';
|
import SkillWeightPopup from './SkillWeightPopup.vue';
|
||||||
|
import { getSkillNum, getSkillsHeatAnalysisList } from '@/apiRc/jobSkill.js';
|
||||||
|
|
||||||
// 技能列表(后续从接口获取)
|
// 技能列表(后续从接口获取)
|
||||||
const skillList = ref([
|
const skillList = ref([
|
||||||
@@ -77,6 +78,14 @@ const skillList = ref([
|
|||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// 技能数量
|
||||||
|
const skillCount = ref(0);
|
||||||
|
const isLoadingSkillCount = ref(false);
|
||||||
|
|
||||||
|
// 技能热度分析列表
|
||||||
|
const heatAnalysisList = ref([]);
|
||||||
|
const isLoadingHeatAnalysis = ref(false);
|
||||||
|
|
||||||
// 弹出层引用
|
// 弹出层引用
|
||||||
const skillWeightPopup = ref(null);
|
const skillWeightPopup = ref(null);
|
||||||
|
|
||||||
@@ -85,6 +94,43 @@ const selectedSkillName = ref('');
|
|||||||
const selectedSkillWeight = ref('');
|
const selectedSkillWeight = ref('');
|
||||||
const selectedSkillLevel = ref(0);
|
const selectedSkillLevel = ref(0);
|
||||||
|
|
||||||
|
// 获取技能数量
|
||||||
|
async function fetchSkillNum(skillType = null) {
|
||||||
|
isLoadingSkillCount.value = true;
|
||||||
|
try {
|
||||||
|
const response = await getSkillNum({
|
||||||
|
skillType: skillType
|
||||||
|
});
|
||||||
|
skillCount.value = response?.data ?? 0;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取技能数量失败:', error);
|
||||||
|
skillCount.value = 0;
|
||||||
|
} finally {
|
||||||
|
isLoadingSkillCount.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取技能热度分析列表
|
||||||
|
async function fetchSkillsHeatAnalysis(startDate, endDate) {
|
||||||
|
isLoadingHeatAnalysis.value = true;
|
||||||
|
try {
|
||||||
|
const params = {};
|
||||||
|
if (startDate) {
|
||||||
|
params.startDate = startDate;
|
||||||
|
}
|
||||||
|
if (endDate) {
|
||||||
|
params.endDate = endDate;
|
||||||
|
}
|
||||||
|
const response = await getSkillsHeatAnalysisList(params);
|
||||||
|
heatAnalysisList.value = Array.isArray(response?.data) ? response.data : [];
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取技能热度分析失败:', error);
|
||||||
|
heatAnalysisList.value = [];
|
||||||
|
} finally {
|
||||||
|
isLoadingHeatAnalysis.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 获取技能发展数据(从接口获取)
|
// 获取技能发展数据(从接口获取)
|
||||||
async function getSkillDevelopmentData() {
|
async function getSkillDevelopmentData() {
|
||||||
// TODO: 调用接口获取技能发展数据
|
// TODO: 调用接口获取技能发展数据
|
||||||
@@ -109,6 +155,23 @@ function handlePopupClose() {
|
|||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getSkillDevelopmentData();
|
getSkillDevelopmentData();
|
||||||
|
// 获取技能数量(不传skillType获取全部)
|
||||||
|
fetchSkillNum();
|
||||||
|
|
||||||
|
// 获取技能热度分析(默认查询最近7天)
|
||||||
|
const endDate = new Date();
|
||||||
|
const startDate = new Date();
|
||||||
|
startDate.setDate(startDate.getDate() - 7);
|
||||||
|
const formatDate = (date) => {
|
||||||
|
const year = date.getFullYear();
|
||||||
|
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||||
|
const day = String(date.getDate()).padStart(2, '0');
|
||||||
|
const hours = String(date.getHours()).padStart(2, '0');
|
||||||
|
const minutes = String(date.getMinutes()).padStart(2, '0');
|
||||||
|
const seconds = String(date.getSeconds()).padStart(2, '0');
|
||||||
|
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
||||||
|
};
|
||||||
|
fetchSkillsHeatAnalysis(formatDate(startDate), formatDate(endDate));
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
35
project.config.json
Normal file
35
project.config.json
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"setting": {
|
||||||
|
"es6": true,
|
||||||
|
"postcss": true,
|
||||||
|
"minified": true,
|
||||||
|
"uglifyFileName": false,
|
||||||
|
"enhance": true,
|
||||||
|
"packNpmRelationList": [],
|
||||||
|
"babelSetting": {
|
||||||
|
"ignore": [],
|
||||||
|
"disablePlugins": [],
|
||||||
|
"outputPath": ""
|
||||||
|
},
|
||||||
|
"useCompilerPlugins": false,
|
||||||
|
"minifyWXML": true,
|
||||||
|
"compileWorklet": false,
|
||||||
|
"uploadWithSourceMap": true,
|
||||||
|
"packNpmManually": false,
|
||||||
|
"minifyWXSS": true,
|
||||||
|
"localPlugins": false,
|
||||||
|
"disableUseStrict": false,
|
||||||
|
"condition": false,
|
||||||
|
"swc": false,
|
||||||
|
"disableSWC": true
|
||||||
|
},
|
||||||
|
"compileType": "miniprogram",
|
||||||
|
"simulatorPluginLibVersion": {},
|
||||||
|
"packOptions": {
|
||||||
|
"ignore": [],
|
||||||
|
"include": []
|
||||||
|
},
|
||||||
|
"appid": "wx4aa34488b965a331",
|
||||||
|
"editorSetting": {},
|
||||||
|
"libVersion": "3.11.1"
|
||||||
|
}
|
||||||
22
project.private.config.json
Normal file
22
project.private.config.json
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"libVersion": "3.11.1",
|
||||||
|
"projectname": "ks-app-employment-service",
|
||||||
|
"setting": {
|
||||||
|
"urlCheck": true,
|
||||||
|
"coverView": true,
|
||||||
|
"lazyloadPlaceholderEnable": false,
|
||||||
|
"skylineRenderEnable": false,
|
||||||
|
"preloadBackgroundData": false,
|
||||||
|
"autoAudits": false,
|
||||||
|
"showShadowRootInWxmlPanel": true,
|
||||||
|
"compileHotReLoad": true,
|
||||||
|
"useApiHook": true,
|
||||||
|
"useApiHostProcess": true,
|
||||||
|
"useStaticServer": false,
|
||||||
|
"useLanDebug": false,
|
||||||
|
"showES6CompileOption": false,
|
||||||
|
"checkInvalidKey": true,
|
||||||
|
"ignoreDevUnusedFiles": true,
|
||||||
|
"bigPackageSizeSupport": false
|
||||||
|
}
|
||||||
|
}
|
||||||
55
unpackage/dist/dev/mp-weixin/project.config.json
vendored
55
unpackage/dist/dev/mp-weixin/project.config.json
vendored
@@ -1,36 +1,35 @@
|
|||||||
{
|
{
|
||||||
"description": "项目配置文件。",
|
|
||||||
"packOptions": {
|
|
||||||
"ignore": []
|
|
||||||
},
|
|
||||||
"setting": {
|
"setting": {
|
||||||
"urlCheck": false,
|
|
||||||
"es6": true,
|
"es6": true,
|
||||||
"postcss": true,
|
"postcss": true,
|
||||||
"minified": true,
|
"minified": true,
|
||||||
"newFeature": true,
|
"uglifyFileName": false,
|
||||||
"bigPackageSizeSupport": true
|
"enhance": true,
|
||||||
|
"packNpmRelationList": [],
|
||||||
|
"babelSetting": {
|
||||||
|
"ignore": [],
|
||||||
|
"disablePlugins": [],
|
||||||
|
"outputPath": ""
|
||||||
|
},
|
||||||
|
"useCompilerPlugins": false,
|
||||||
|
"minifyWXML": true,
|
||||||
|
"compileWorklet": false,
|
||||||
|
"uploadWithSourceMap": true,
|
||||||
|
"packNpmManually": false,
|
||||||
|
"minifyWXSS": true,
|
||||||
|
"localPlugins": false,
|
||||||
|
"disableUseStrict": false,
|
||||||
|
"condition": false,
|
||||||
|
"swc": false,
|
||||||
|
"disableSWC": true
|
||||||
},
|
},
|
||||||
"compileType": "miniprogram",
|
"compileType": "miniprogram",
|
||||||
"libVersion": "3.5.7",
|
"simulatorPluginLibVersion": {},
|
||||||
"appid": "wx9d1cbc11c8c40ba7",
|
"packOptions": {
|
||||||
"projectname": "qingdao-employment-service",
|
"ignore": [],
|
||||||
"condition": {
|
"include": []
|
||||||
"search": {
|
},
|
||||||
"current": -1,
|
"appid": "wx4aa34488b965a331",
|
||||||
"list": []
|
"editorSetting": {},
|
||||||
},
|
"libVersion": "3.11.1"
|
||||||
"conversation": {
|
|
||||||
"current": -1,
|
|
||||||
"list": []
|
|
||||||
},
|
|
||||||
"game": {
|
|
||||||
"current": -1,
|
|
||||||
"list": []
|
|
||||||
},
|
|
||||||
"miniprogram": {
|
|
||||||
"current": -1,
|
|
||||||
"list": []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -19,8 +19,8 @@ let exports = {
|
|||||||
// baseUrl: 'http://10.160.0.5:8903', // 演示环境外网
|
// baseUrl: 'http://10.160.0.5:8903', // 演示环境外网
|
||||||
|
|
||||||
// baseUrl: 'http://111.34.80.140:8081/prod-api', // 正式环境(不要轻易连接)
|
// baseUrl: 'http://111.34.80.140:8081/prod-api', // 正式环境(不要轻易连接)
|
||||||
|
baseUrl: 'http://ks.zhaopinzao8dian.com/api/ks',
|
||||||
baseUrl: 'http://10.160.0.5:8907', // 正式环境在济南人才上部署(不要轻易连接)
|
zytpBaseUrl: 'http://ks.zhaopinzao8dian.com/api/ks',
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import { toast, showConfirm, tansParams } from '@/utilsRc/common'
|
|||||||
|
|
||||||
let timeout = 10000
|
let timeout = 10000
|
||||||
const baseUrl = configRc.baseUrl
|
const baseUrl = configRc.baseUrl
|
||||||
|
const zytpBaseUrl = configRc.zytpBaseUrl || ''
|
||||||
|
|
||||||
const request = config => {
|
const request = config => {
|
||||||
// 是否需要设置 token
|
// 是否需要设置 token
|
||||||
@@ -22,20 +23,27 @@ const request = config => {
|
|||||||
}
|
}
|
||||||
config.header['Authorization'] = 'Bearer ' + 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpblR5cGUiOiJsb2dpbiIsImxvZ2luSWQiOiJzeXNfdXNlcjoxIiwicm5TdHIiOiJVMDRocERSZjdZMXJUbUxXb05uOUpzYUdDZzBNazJJQSIsInVzZXJJZCI6MX0.LZ29vvA4tK3b9Hki4nU9Jb1himXZM2AEOue3CMRY95w'
|
config.header['Authorization'] = 'Bearer ' + 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpblR5cGUiOiJsb2dpbiIsImxvZ2luSWQiOiJzeXNfdXNlcjoxIiwicm5TdHIiOiJVMDRocERSZjdZMXJUbUxXb05uOUpzYUdDZzBNazJJQSIsInVzZXJJZCI6MX0.LZ29vvA4tK3b9Hki4nU9Jb1himXZM2AEOue3CMRY95w'
|
||||||
// get请求映射params参数
|
// get请求映射params参数
|
||||||
|
const baseType = config.baseUrlType
|
||||||
|
const requestBaseUrl = baseType === 'zytp' && zytpBaseUrl ? zytpBaseUrl : baseUrl
|
||||||
|
let requestUrl = config.fullUrl ? config.fullUrl : (requestBaseUrl + (config.url || ''))
|
||||||
|
|
||||||
if (config.params) {
|
if (config.params) {
|
||||||
let url = config.url + '?' + tansParams(config.params)
|
let url = tansParams(config.params)
|
||||||
url = url.slice(0, -1)
|
url = url.slice(0, -1)
|
||||||
config.url = url
|
if (url) {
|
||||||
|
requestUrl += (requestUrl.includes('?') ? '&' : '?') + url
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
uni.request({
|
uni.request({
|
||||||
method: config.method || 'get',
|
method: config.method || 'get',
|
||||||
timeout: config.timeout || timeout,
|
timeout: config.timeout || timeout,
|
||||||
url: baseUrl + config.url,
|
url: requestUrl,
|
||||||
// url: 'https://gccrcdh.sd-talent.cn:80/zhq' + config.url,
|
// url: 'https://gccrcdh.sd-talent.cn:80/zhq' + config.url,
|
||||||
data: config.data,
|
data: config.data,
|
||||||
header: config.header,
|
header: config.header,
|
||||||
dataType: 'json'
|
dataType: 'json',
|
||||||
|
responseType: config.responseType || 'text'
|
||||||
}).then(response => {
|
}).then(response => {
|
||||||
let res = response.data
|
let res = response.data
|
||||||
let error = response.errMsg!='request:ok'
|
let error = response.errMsg!='request:ok'
|
||||||
|
|||||||
Reference in New Issue
Block a user