主包体积太大,相关代码迁移
This commit is contained in:
514
packageA/pages/service/career-planning.vue
Normal file
514
packageA/pages/service/career-planning.vue
Normal file
@@ -0,0 +1,514 @@
|
||||
<!--suppress HtmlUnknownTag, NpmUsedModulesInstalled, JSFileReferences -->
|
||||
<script setup>
|
||||
import { ref, inject, nextTick, onMounted } from 'vue';
|
||||
import { onLoad, onShow } from '@dcloudio/uni-app';
|
||||
import { appUserInfo } from '@/apiRc/user/user.js';
|
||||
import RemindPopup from './components/RemindPopup.vue';
|
||||
import PageHeader from './components/PageHeader.vue';
|
||||
import SkillDetailPopup from './components/SkillDetailPopup.vue';
|
||||
import CareerRecommend from './components/CareerRecommend.vue';
|
||||
import CareerPath from './components/CareerPath.vue';
|
||||
import SkillDevelopment from './components/SkillDevelopment.vue';
|
||||
import CustomTabBar from '@/components/CustomTabBar/CustomTabBar.vue';
|
||||
|
||||
const { navBack, navTo } = inject('globalFunction');
|
||||
|
||||
// 弹窗引用
|
||||
const remindPopup = ref(null);
|
||||
const skillDetailPopup = ref(null);
|
||||
// 提醒列表(由接口返回)
|
||||
const remindList = ref([]);
|
||||
// 是否显示页面内容
|
||||
const showContent = ref(false);
|
||||
// 当前激活的tab
|
||||
const activeTab = ref(0);
|
||||
// 选中的职位信息
|
||||
const selectedJobTitle = ref('');
|
||||
const selectedJobPossessedSkills = ref([]);
|
||||
const selectedJobImprovementSkills = ref([]);
|
||||
const currentJobId = ref(null);
|
||||
const currentJobName = ref('');
|
||||
|
||||
|
||||
const pathSkillsData = ref({
|
||||
pathData: {
|
||||
start: { title: '', skills: [] },
|
||||
steps: [],
|
||||
end: { title: '', skills: [] }
|
||||
},
|
||||
targetCareer: ''
|
||||
});
|
||||
|
||||
// 打开弹窗
|
||||
function openRemindPopup() {
|
||||
nextTick(() => {
|
||||
if (remindPopup.value) {
|
||||
try {
|
||||
remindPopup.value.open();
|
||||
} catch (error) {
|
||||
// 静默处理错误
|
||||
}
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
if (remindPopup.value) {
|
||||
try {
|
||||
remindPopup.value.open();
|
||||
} catch (error) {
|
||||
// 静默处理错误
|
||||
}
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
if (remindPopup.value) {
|
||||
try {
|
||||
remindPopup.value.open();
|
||||
} catch (error) {
|
||||
// 静默处理错误
|
||||
}
|
||||
}
|
||||
}, 500);
|
||||
}
|
||||
}, 500);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 检查用户是否完善了个人信息(调用接口获取)
|
||||
let hasCheckedRemindInfo = false;
|
||||
// 保存缺失信息的标识
|
||||
const missingInfo = ref({
|
||||
hasJobInfo: false,
|
||||
hasSkills: false
|
||||
});
|
||||
|
||||
async function getRemindInfo() {
|
||||
if (hasCheckedRemindInfo) {
|
||||
return;
|
||||
}
|
||||
|
||||
hasCheckedRemindInfo = true;
|
||||
|
||||
try {
|
||||
const response = await appUserInfo();
|
||||
const userInfo = response?.data || {};
|
||||
|
||||
// 检查 idCard(身份证)- 必须项
|
||||
let idCard = userInfo?.resume?.idCard ?? userInfo?.idCard ?? null;
|
||||
const cachedUserInfo = uni.getStorageSync('userInfo') || {};
|
||||
if (!idCard || idCard === null || idCard === '') {
|
||||
idCard = cachedUserInfo?.resume?.idCard ?? cachedUserInfo?.idCard ?? null;
|
||||
}
|
||||
const hasIdCard = idCard !== null && idCard !== undefined && idCard !== '';
|
||||
|
||||
// 检查职位信息:优先从 jobTitles 数组获取
|
||||
const jobTitles = Array.isArray(userInfo?.jobTitles) ? userInfo.jobTitles : [];
|
||||
const hasJobTitle = jobTitles.length > 0;
|
||||
|
||||
// 如果 jobTitles 为空,尝试从其他字段获取
|
||||
let jobName = '';
|
||||
if (!hasJobTitle) {
|
||||
jobName = userInfo?.jobName ??
|
||||
userInfo?.currentJobName ??
|
||||
userInfo?.resume?.jobName ??
|
||||
userInfo?.resume?.currentJobName ??
|
||||
'';
|
||||
}
|
||||
const hasJobInfo = hasJobTitle || (jobName && jobName.trim() !== '');
|
||||
|
||||
// 检查技能标签:从 appSkillsList 获取
|
||||
const appSkillsList = Array.isArray(userInfo?.appSkillsList) ? userInfo.appSkillsList : [];
|
||||
// 检查是否有有效的技能(name 或 nameStr 不为空)
|
||||
const hasSkills = appSkillsList.some(skill => {
|
||||
const skillName = skill?.name || skill?.nameStr;
|
||||
return skillName && skillName.trim() !== '';
|
||||
});
|
||||
|
||||
// 保存缺失信息标识(只保存职位信息和技能标签,身份证信息跳转到个人信息页面)
|
||||
missingInfo.value.hasJobInfo = hasJobInfo;
|
||||
missingInfo.value.hasSkills = hasSkills;
|
||||
|
||||
// 判断信息是否完整(idCard、职位信息、技能标签都必须有)
|
||||
const isComplete = hasIdCard && hasJobInfo && hasSkills;
|
||||
|
||||
if (!isComplete) {
|
||||
// 收集缺失的信息提示
|
||||
const missingItems = [];
|
||||
if (!hasIdCard) {
|
||||
missingItems.push('身份证信息');
|
||||
}
|
||||
if (!hasJobInfo) {
|
||||
missingItems.push('职位信息');
|
||||
}
|
||||
if (!hasSkills) {
|
||||
missingItems.push('技能标签');
|
||||
}
|
||||
remindList.value = [`请完善${missingItems.join('、')}`];
|
||||
} else {
|
||||
// 信息完整,设置职位信息
|
||||
if (hasJobTitle) {
|
||||
currentJobName.value = jobTitles[0];
|
||||
} else {
|
||||
currentJobName.value = jobName;
|
||||
currentJobId.value = userInfo?.jobId ??
|
||||
userInfo?.currentJobId ??
|
||||
userInfo?.resume?.jobId ??
|
||||
userInfo?.resume?.currentJobId ??
|
||||
null;
|
||||
}
|
||||
// 信息完整,直接显示页面内容
|
||||
showContent.value = true;
|
||||
return;
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
openRemindPopup();
|
||||
}, 500);
|
||||
} catch (error) {
|
||||
// 接口调用失败时,使用缓存作为降级方案
|
||||
const cachedUserInfo = uni.getStorageSync('userInfo') || {};
|
||||
|
||||
// 检查 idCard
|
||||
const idCard = cachedUserInfo?.resume?.idCard ?? cachedUserInfo?.idCard ?? null;
|
||||
const hasIdCard = idCard !== null && idCard !== undefined && idCard !== '';
|
||||
|
||||
// 检查职位信息
|
||||
const cachedJobTitles = Array.isArray(cachedUserInfo?.jobTitles) ? cachedUserInfo.jobTitles : [];
|
||||
const hasJobTitle = cachedJobTitles.length > 0;
|
||||
let jobName = '';
|
||||
if (!hasJobTitle) {
|
||||
jobName = cachedUserInfo?.jobName ??
|
||||
cachedUserInfo?.currentJobName ??
|
||||
cachedUserInfo?.resume?.jobName ??
|
||||
cachedUserInfo?.resume?.currentJobName ??
|
||||
'';
|
||||
}
|
||||
const hasJobInfo = hasJobTitle || (jobName && jobName.trim() !== '');
|
||||
|
||||
// 检查技能标签
|
||||
const cachedAppSkillsList = Array.isArray(cachedUserInfo?.appSkillsList) ? cachedUserInfo.appSkillsList : [];
|
||||
const hasSkills = cachedAppSkillsList.some(skill => {
|
||||
const skillName = skill?.name || skill?.nameStr;
|
||||
return skillName && skillName.trim() !== '';
|
||||
});
|
||||
|
||||
// 保存缺失信息标识
|
||||
missingInfo.value.hasJobInfo = hasJobInfo;
|
||||
missingInfo.value.hasSkills = hasSkills;
|
||||
|
||||
// 判断信息是否完整(idCard、职位信息、技能标签都必须有)
|
||||
const isComplete = hasIdCard && hasJobInfo && hasSkills;
|
||||
|
||||
if (!isComplete) {
|
||||
// 收集缺失的信息提示
|
||||
const missingItems = [];
|
||||
if (!hasIdCard) {
|
||||
missingItems.push('身份证信息');
|
||||
}
|
||||
if (!hasJobInfo) {
|
||||
missingItems.push('职位信息');
|
||||
}
|
||||
if (!hasSkills) {
|
||||
missingItems.push('技能标签');
|
||||
}
|
||||
remindList.value = [`请完善${missingItems.join('、')}`];
|
||||
} else {
|
||||
// 信息完整,设置职位信息
|
||||
if (hasJobTitle) {
|
||||
currentJobName.value = cachedJobTitles[0];
|
||||
} else {
|
||||
currentJobName.value = jobName;
|
||||
currentJobId.value = cachedUserInfo?.jobId ??
|
||||
cachedUserInfo?.currentJobId ??
|
||||
cachedUserInfo?.resume?.jobId ??
|
||||
cachedUserInfo?.resume?.currentJobId ??
|
||||
null;
|
||||
}
|
||||
// 信息完整,直接显示页面内容
|
||||
showContent.value = true;
|
||||
return;
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
openRemindPopup();
|
||||
}, 500);
|
||||
}
|
||||
}
|
||||
|
||||
// 取消按钮
|
||||
function handleCancel() {
|
||||
remindPopup.value?.close();
|
||||
navBack();
|
||||
}
|
||||
|
||||
// 确认按钮
|
||||
async function handleConfirm() {
|
||||
remindPopup.value?.close();
|
||||
|
||||
const { hasJobInfo, hasSkills } = missingInfo.value;
|
||||
|
||||
// 如果同时缺少职位信息和技能标签:先跳转到职位信息页面,并传递参数表示完成后需要继续跳转到技能页面
|
||||
if (!hasJobInfo && !hasSkills) {
|
||||
// 跳转到职位信息页面,传递参数表示完成后需要继续跳转到技能页面
|
||||
navTo('/packageA/pages/jobExpect/jobExpect?needSkill=true');
|
||||
}
|
||||
// 如果只缺少技能标签:直接跳转到技能页面(个人信息页面的技能部分)
|
||||
else if (!hasSkills) {
|
||||
navTo('/packageA/pages/personalInfo/personalInfo');
|
||||
}
|
||||
// 如果只缺少职位信息:直接跳转到职位信息页面
|
||||
else if (!hasJobInfo) {
|
||||
navTo('/packageA/pages/jobExpect/jobExpect');
|
||||
}
|
||||
// 如果只缺少身份证信息:跳转到个人信息页面
|
||||
else {
|
||||
navTo('/packageA/pages/personalInfo/personalInfo');
|
||||
}
|
||||
}
|
||||
|
||||
// 切换tab
|
||||
function switchTab(index) {
|
||||
activeTab.value = index;
|
||||
|
||||
if (index === 0 && !currentJobId.value) {
|
||||
const cachedUserInfo = uni.getStorageSync('userInfo') || {};
|
||||
|
||||
// 优先从缓存中的 jobTitles 数组获取职位信息(取第一个)
|
||||
const cachedJobTitles = Array.isArray(cachedUserInfo?.jobTitles) ? cachedUserInfo.jobTitles : [];
|
||||
let newJobName = '';
|
||||
|
||||
if (cachedJobTitles.length > 0) {
|
||||
newJobName = cachedJobTitles[0];
|
||||
} else {
|
||||
// 如果缓存中没有 jobTitles,从其他字段获取
|
||||
newJobName = currentJobName.value ||
|
||||
(cachedUserInfo?.jobName ??
|
||||
cachedUserInfo?.currentJobName ??
|
||||
cachedUserInfo?.resume?.jobName ??
|
||||
cachedUserInfo?.resume?.currentJobName ??
|
||||
'市场专员');
|
||||
}
|
||||
|
||||
const newJobId = cachedUserInfo?.jobId ??
|
||||
cachedUserInfo?.currentJobId ??
|
||||
cachedUserInfo?.resume?.jobId ??
|
||||
cachedUserInfo?.resume?.currentJobId ??
|
||||
null;
|
||||
|
||||
currentJobId.value = newJobId;
|
||||
currentJobName.value = newJobName;
|
||||
}
|
||||
}
|
||||
|
||||
// 搜索点击
|
||||
function handleSearchClick() {
|
||||
navTo('/pages/search/search');
|
||||
}
|
||||
|
||||
// 菜单点击
|
||||
function handleMenuClick() {
|
||||
// TODO: 实现菜单功能
|
||||
}
|
||||
|
||||
// 更多点击
|
||||
function handleMoreClick() {
|
||||
// TODO: 实现更多功能
|
||||
}
|
||||
|
||||
// 处理职业路径数据更新
|
||||
function handlePathDataUpdated(data) {
|
||||
pathSkillsData.value = {
|
||||
pathData: data.pathData || {
|
||||
start: { title: '', skills: [] },
|
||||
steps: [],
|
||||
end: { title: '', skills: [] }
|
||||
},
|
||||
targetCareer: data.targetCareer || ''
|
||||
};
|
||||
}
|
||||
|
||||
onLoad(() => {
|
||||
getRemindInfo();
|
||||
});
|
||||
|
||||
onShow(() => {
|
||||
// 返回本页后,如果之前因为信息缺失未展示内容,则重新检查
|
||||
if (!showContent.value) {
|
||||
hasCheckedRemindInfo = false;
|
||||
getRemindInfo();
|
||||
}
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
if (remindList.value.length > 0 && !showContent.value) {
|
||||
setTimeout(() => {
|
||||
if (remindPopup.value) {
|
||||
openRemindPopup();
|
||||
}
|
||||
}, 300);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="career-planning-page">
|
||||
<!-- 提醒弹窗 -->
|
||||
<RemindPopup
|
||||
ref="remindPopup"
|
||||
:remind-list="remindList"
|
||||
@cancel="handleCancel"
|
||||
@confirm="handleConfirm"
|
||||
/>
|
||||
|
||||
<!-- 技能详情弹出层 -->
|
||||
<SkillDetailPopup
|
||||
ref="skillDetailPopup"
|
||||
:job-title="selectedJobTitle"
|
||||
:possessed-skills="selectedJobPossessedSkills"
|
||||
:improvement-skills="selectedJobImprovementSkills"
|
||||
/>
|
||||
|
||||
<!-- 页面内容 -->
|
||||
<div class="page-content" v-if="showContent">
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<!-- 小程序背景图片 -->
|
||||
<image class="mp-background" src="/static/icon/background2.png" mode="aspectFill"></image>
|
||||
<!-- #endif -->
|
||||
|
||||
<!-- 头部区域 -->
|
||||
<PageHeader
|
||||
:active-tab="activeTab"
|
||||
@tab-change="switchTab"
|
||||
@search-click="handleSearchClick"
|
||||
@menu-click="handleMenuClick"
|
||||
@more-click="handleMoreClick"
|
||||
/>
|
||||
|
||||
<!-- 内容区域 -->
|
||||
<scroll-view scroll-y class="content-scroll">
|
||||
<CareerRecommend v-if="activeTab === 0"/>
|
||||
<CareerPath v-else-if="activeTab === 1" />
|
||||
<SkillDevelopment v-else />
|
||||
</scroll-view>
|
||||
</div>
|
||||
|
||||
<!-- 底部导航栏 -->
|
||||
<div class="tabbar-wrapper" v-if="showContent">
|
||||
<CustomTabBar :currentPage="0" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.query-btn {
|
||||
width: 100%;
|
||||
height: 80rpx;
|
||||
line-height: 40rpx;
|
||||
border-radius: 14rpx;
|
||||
background: linear-gradient(180deg, rgba(18, 125, 240, 1) 0%, rgba(59, 14, 123, 0.71) 100%);
|
||||
color: rgba(255, 255, 255, 1);
|
||||
font-size: 28rpx;
|
||||
text-align: center;
|
||||
font-family: '阿里巴巴普惠体3.0-regular', 'PingFang SC', 'Helvetica Neue', Helvetica, Arial, 'Microsoft YaHei', sans-serif;
|
||||
border: 2rpx solid rgba(187, 187, 187, 1);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 12rpx;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
font-size: 26rpx;
|
||||
text-align: center;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.input-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 30rpx;
|
||||
}
|
||||
|
||||
.input-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12rpx;
|
||||
}
|
||||
|
||||
.picker-field {
|
||||
background-color: #F5F5F5;
|
||||
border: 1rpx solid #E0E0E0;
|
||||
border-radius: 12rpx;
|
||||
padding: 20rpx 24rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.picker-text {
|
||||
font-size: 28rpx;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
.picker-placeholder {
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.career-planning-page {
|
||||
width: 100vw;
|
||||
/* #ifdef H5 */
|
||||
height: calc(100vh - var(--window-top) - var(--status-bar-height) - var(--window-bottom));
|
||||
background: url('@/static/icon/background2.png') 0 0 no-repeat;
|
||||
background-size: 100% 728rpx;
|
||||
/* #endif */
|
||||
/* #ifdef MP-WEIXIN */
|
||||
height: 100vh;
|
||||
position: relative;
|
||||
/* #endif */
|
||||
background-color: #FFFFFF;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* #ifdef MP-WEIXIN */
|
||||
.mp-background {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 728rpx;
|
||||
z-index: 0;
|
||||
}
|
||||
/* #endif */
|
||||
|
||||
.page-content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
|
||||
.content-scroll {
|
||||
flex: 1;
|
||||
height: 0;
|
||||
width: 100%;
|
||||
padding-bottom: calc(88rpx + env(safe-area-inset-bottom));
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tabbar-wrapper {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 999;
|
||||
}
|
||||
</style>
|
||||
250
packageA/pages/service/components/CareerPath.vue
Normal file
250
packageA/pages/service/components/CareerPath.vue
Normal file
@@ -0,0 +1,250 @@
|
||||
<!--suppress JSFileReferences, NpmUsedModulesInstalled, VueMissingComponentImportInspection, HtmlUnknownTag -->
|
||||
<script setup>
|
||||
import { useCareerPathStore } from '@/stores/useCareerPathStore';
|
||||
|
||||
|
||||
const store = useCareerPathStore();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="career-path">
|
||||
<!-- 职业路径查询区域 -->
|
||||
<div class="query-section">
|
||||
<div class="section-title">
|
||||
<uni-icons color="#286BFA" size="18" type="search"></uni-icons>
|
||||
<span class="title-text">职业路径查询</span>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<div class="input-item">
|
||||
<span class="label">当前职位</span>
|
||||
<picker @change="store.eventProfession" :value="store.professionIndex" :range="store.professionsRef" range-key="label">
|
||||
<div class="picker-field">
|
||||
<span :class="store.professionLabel ? 'picker-text' : 'picker-placeholder'">
|
||||
{{ store.professionLabel || '请选择职位' }}
|
||||
</span>
|
||||
<uni-icons color="#999999" size="16" type="down"></uni-icons>
|
||||
</div>
|
||||
</picker>
|
||||
</div>
|
||||
<div class="input-item">
|
||||
<span class="label">目标职业</span>
|
||||
<picker :range="store.pathsRef" :value="store.targetCareerIndex" range-key="label" @change="store.eventTargetCareer">
|
||||
<div class="picker-field">
|
||||
<span :class="store.targetCareerLabel ? 'picker-text' : 'picker-placeholder'">
|
||||
{{ store.targetCareerLabel || '请选择目标职业' }}
|
||||
</span>
|
||||
<uni-icons color="#999999" size="16" type="down"></uni-icons>
|
||||
</div>
|
||||
</picker>
|
||||
</div>
|
||||
<button class="query-btn" @click="store.eventSearch">
|
||||
<span>查询职业发展路径</span>
|
||||
<uni-icons type="search" size="18" color="#FFFFFF"></uni-icons>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 职业发展路径区域 -->
|
||||
<div class="path-section">
|
||||
<div class="section-title">
|
||||
<uni-icons color="#000000" size="24" type="person-filled"></uni-icons>
|
||||
<text class="title-text">职业发展路径</text>
|
||||
</div>
|
||||
|
||||
<div class="timeline">
|
||||
<div v-for="(step, index) in store.result" :key="index" class="timeline-item" :class="[step.type]">
|
||||
<div class="timeline-marker" :class="[`${step.type}-marker`]"></div>
|
||||
<div class="timeline-content">
|
||||
<div v-if="step.type === 'start'" class="step-title">起点: {{ step.title }}</div>
|
||||
<div v-else-if="step.type === 'end'" class="step-title">终点: {{ step.title }}</div>
|
||||
<div v-else class="step-title">第{{ step.step }}步: {{ step.title }}</div>
|
||||
<div class="skill-tags">
|
||||
<div v-for="(skill, sIndex) in step.tags" :key="sIndex" class="skill-tag">{{ skill }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.career-path {
|
||||
padding: 10rpx 28rpx 20rpx;
|
||||
}
|
||||
|
||||
.card-content {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.label {
|
||||
font-size: 24rpx;
|
||||
line-height: 34rpx;
|
||||
color: rgba(154, 154, 154, 1);
|
||||
text-align: left;
|
||||
font-family: 'PingFangSC-Bold', 'PingFang SC', 'Helvetica Neue', Helvetica, Arial, 'Microsoft YaHei', sans-serif;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.value {
|
||||
font-size: 32rpx;
|
||||
line-height: 46rpx;
|
||||
color: rgb(16, 16, 16);
|
||||
font-weight: 600;
|
||||
text-align: left;
|
||||
font-family: 'PingFangSC-Bold', 'PingFang SC', 'Helvetica Neue', Helvetica, Arial, 'Microsoft YaHei', sans-serif;
|
||||
|
||||
&.placeholder {
|
||||
font-weight: 500;
|
||||
color: #ccc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.query-section {
|
||||
background-color: #FFFFFF;
|
||||
border-radius: 16rpx;
|
||||
padding: 28rpx;
|
||||
margin-bottom: 20rpx;
|
||||
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 32rpx;
|
||||
color: #000000;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12rpx;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.title-text {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #157DF0;
|
||||
}
|
||||
|
||||
.input-label {
|
||||
font-size: 28rpx;
|
||||
color: #000000;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.input-field {
|
||||
background-color: #F5F5F5;
|
||||
border: 1rpx solid #E0E0E0;
|
||||
border-radius: 12rpx;
|
||||
padding: 20rpx 24rpx;
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.path-summary {
|
||||
margin-top: 16rpx;
|
||||
font-size: 24rpx;
|
||||
color: #666666;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.path-section {
|
||||
background-color: #FFFFFF;
|
||||
border-radius: 16rpx;
|
||||
padding: 28rpx;
|
||||
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.timeline {
|
||||
position: relative;
|
||||
padding-left: 40rpx;
|
||||
}
|
||||
|
||||
.timeline-item {
|
||||
position: relative;
|
||||
margin-bottom: 32rpx;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
&:not(:last-child)::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: -32rpx;
|
||||
top: 0;
|
||||
width: 2rpx;
|
||||
height: 100%;
|
||||
background: repeating-linear-gradient(
|
||||
to bottom,
|
||||
#E0E0E0 0,
|
||||
#E0E0E0 6rpx,
|
||||
transparent 6rpx,
|
||||
transparent 12rpx
|
||||
);
|
||||
transform: translateX(-50%);
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.timeline-marker {
|
||||
position: absolute;
|
||||
left: -32rpx;
|
||||
top: 0;
|
||||
transform: translateX(-50%);
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
border-radius: 50%;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.start-marker {
|
||||
background-color: #FF4444;
|
||||
border: 4rpx solid #FFFFFF;
|
||||
box-shadow: 0 0 0 2rpx #FF4444;
|
||||
}
|
||||
|
||||
.step-marker {
|
||||
background-color: #286BFA;
|
||||
border: 4rpx solid #FFFFFF;
|
||||
box-shadow: 0 0 0 2rpx #286BFA;
|
||||
}
|
||||
|
||||
.end-marker {
|
||||
background-color: #52C41A;
|
||||
border: 4rpx solid #FFFFFF;
|
||||
box-shadow: 0 0 0 2rpx #52C41A;
|
||||
}
|
||||
|
||||
.timeline-content {
|
||||
background-color: #F5F5F5;
|
||||
border-radius: 12rpx;
|
||||
padding: 24rpx;
|
||||
margin-left: 20rpx;
|
||||
}
|
||||
|
||||
.step-title {
|
||||
font-size: 30rpx;
|
||||
font-weight: 600;
|
||||
color: #000000;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.skill-tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 12rpx;
|
||||
}
|
||||
|
||||
.skill-tag {
|
||||
background-color: #F0F0F0;
|
||||
color: #286BFA;
|
||||
padding: 8rpx 16rpx;
|
||||
border-radius: 8rpx;
|
||||
font-size: 24rpx;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
button::after {
|
||||
border: none;
|
||||
}
|
||||
</style>
|
||||
200
packageA/pages/service/components/CareerRecommend.vue
Normal file
200
packageA/pages/service/components/CareerRecommend.vue
Normal file
@@ -0,0 +1,200 @@
|
||||
<!--suppress JSFileReferences, NpmUsedModulesInstalled, VueMissingComponentImportInspection, HtmlUnknownTag -->
|
||||
<script setup>
|
||||
import { useCareerRecommendationStore } from '@/stores/useCareerRecommendationStore';
|
||||
|
||||
|
||||
const store = useCareerRecommendationStore();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="career-recommend">
|
||||
<div class="info-card">
|
||||
<div class="section-title">
|
||||
<uni-icons color="#286BFA" size="18" type="search"></uni-icons>
|
||||
<span class="title-text">我的职业</span>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<div class="input-item">
|
||||
<picker @change="store.eventProfession" :value="store.professionIndex" :range="store.professionsRef" range-key="label">
|
||||
<div class="picker-field">
|
||||
<span :class="store.professionLabel ? 'picker-text' : 'picker-placeholder'">
|
||||
{{ store.professionLabel || '请选择职业' }}
|
||||
</span>
|
||||
<uni-icons color="#999999" size="16" type="down"></uni-icons>
|
||||
</div>
|
||||
</picker>
|
||||
</div>
|
||||
<button class="query-btn" @click="store.eventSearch">
|
||||
<span>搜索</span>
|
||||
<uni-icons type="search" size="18" color="#FFFFFF"></uni-icons>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="info-card">
|
||||
<div class="card-title">我的技能标签</div>
|
||||
<div class="skill-tags">
|
||||
<div v-for="(skill, index) in store.skillTags" :key="index" class="skill-tag">
|
||||
{{ skill }}
|
||||
</div>
|
||||
<span v-if="!store.skillTags.length" class="empty-text">暂无技能数据</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section-title">
|
||||
相似推荐职位
|
||||
</div>
|
||||
<div v-if="!store.result && store.result.length === 0" class="empty-text">暂无推荐职位</div>
|
||||
<div v-for="(job, index) in store.result" :key="index" class="job-item-card">
|
||||
<div class="job-header">
|
||||
<span class="job-title">{{ job.title }}</span>
|
||||
</div>
|
||||
<div class="job-header">
|
||||
<span>职业相似度:{{ job.percentage }}%</span>
|
||||
</div>
|
||||
<div class="job-skills">
|
||||
<div v-for="tag in job.tags" :key="tag" class="job-skill-tag">
|
||||
{{ tag }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.career-recommend {
|
||||
padding: 10rpx 28rpx 20rpx;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 32rpx;
|
||||
color: #000000;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12rpx;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.title-text {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #157DF0;
|
||||
}
|
||||
|
||||
.info-card {
|
||||
background-color: #FFFFFF;
|
||||
border-radius: 16rpx;
|
||||
padding: 28rpx;
|
||||
margin-bottom: 20rpx;
|
||||
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.card-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #000000;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.card-content {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.label {
|
||||
font-size: 24rpx;
|
||||
line-height: 34rpx;
|
||||
color: rgba(154, 154, 154, 1);
|
||||
text-align: left;
|
||||
font-family: 'PingFangSC-Bold', 'PingFang SC', 'Helvetica Neue', Helvetica, Arial, 'Microsoft YaHei', sans-serif;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.value {
|
||||
font-size: 32rpx;
|
||||
line-height: 46rpx;
|
||||
color: rgb(16, 16, 16);
|
||||
font-weight: 600;
|
||||
text-align: left;
|
||||
font-family: 'PingFangSC-Bold', 'PingFang SC', 'Helvetica Neue', Helvetica, Arial, 'Microsoft YaHei', sans-serif;
|
||||
}
|
||||
}
|
||||
|
||||
.skill-tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.skill-tag {
|
||||
background-color: #EAEFFE;
|
||||
color: rgba(44, 101, 247, 1);
|
||||
padding: 8rpx 20rpx;
|
||||
border-radius: 0;
|
||||
font-size: 24rpx;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.job-item-card {
|
||||
background-color: #FFFFFF;
|
||||
border-radius: 16rpx;
|
||||
padding: 28rpx;
|
||||
margin-bottom: 20rpx;
|
||||
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);
|
||||
border-left: 6rpx solid #409EFF;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.job-header {
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.job-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: rgb(16, 16, 16);
|
||||
text-align: left;
|
||||
font-family: 'PingFangSC-Bold', 'PingFang SC', 'Helvetica Neue', Helvetica, Arial, 'Microsoft YaHei', sans-serif;
|
||||
line-height: 46rpx;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.job-skills {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 12rpx;
|
||||
}
|
||||
|
||||
.job-skill-tag {
|
||||
width: 130rpx;
|
||||
height: 36rpx;
|
||||
line-height: 34rpx;
|
||||
background-color: rgba(49, 100, 239, 0.1);
|
||||
color: rgba(44, 101, 247, 1);
|
||||
font-size: 24rpx;
|
||||
text-align: center;
|
||||
font-family: 'PingFang SC', 'Helvetica Neue', Helvetica, Arial, 'Microsoft YaHei', sans-serif;
|
||||
border-radius: 8rpx;
|
||||
white-space: nowrap;
|
||||
border: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
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 {
|
||||
border: none;
|
||||
}
|
||||
</style>
|
||||
236
packageA/pages/service/components/PageHeader.vue
Normal file
236
packageA/pages/service/components/PageHeader.vue
Normal file
@@ -0,0 +1,236 @@
|
||||
<template>
|
||||
<view class="page-header" :style="{ paddingTop: statusBarHeight > 0 ? `calc(40rpx + ${statusBarHeight * 2}rpx)` : '40rpx' }">
|
||||
<view class="header-top">
|
||||
<view class="title-section">
|
||||
<text class="main-title">职业规划推荐指导平台</text>
|
||||
<text class="sub-title">智能匹配·精准推荐·职业发展</text>
|
||||
</view>
|
||||
<view class="header-icons">
|
||||
<view class="icon-dot" @click="handleMenuClick">
|
||||
<view class="dot"></view>
|
||||
<view class="dot"></view>
|
||||
<view class="dot"></view>
|
||||
</view>
|
||||
<view class="icon-single-dot" @click="handleMoreClick"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 搜索栏 -->
|
||||
<view class="search-bar" @click.stop="handleSearchClick" @tap.stop="handleSearchClick">
|
||||
<uni-icons class="search-icon" type="search" size="18" color="#999999"></uni-icons>
|
||||
<text class="search-placeholder">职位名称、薪资要求等</text>
|
||||
</view>
|
||||
|
||||
<!-- Tab导航 -->
|
||||
<view class="tab-nav-wrapper">
|
||||
<view class="tab-nav">
|
||||
<view
|
||||
class="tab-item"
|
||||
:class="{ 'active': activeTab === 0 }"
|
||||
@click.stop="handleTabClick(0)"
|
||||
@tap.stop="handleTabClick(0)"
|
||||
>
|
||||
职业推荐
|
||||
</view>
|
||||
<view
|
||||
class="tab-item"
|
||||
:class="{ 'active': activeTab === 1 }"
|
||||
@click.stop="handleTabClick(1)"
|
||||
@tap.stop="handleTabClick(1)"
|
||||
>
|
||||
职业路径
|
||||
</view>
|
||||
<view
|
||||
class="tab-item"
|
||||
:class="{ 'active': activeTab === 2 }"
|
||||
@click.stop="handleTabClick(2)"
|
||||
@tap.stop="handleTabClick(2)"
|
||||
>
|
||||
技能发展
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { defineProps, defineEmits, ref, onMounted } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
activeTab: {
|
||||
type: Number,
|
||||
default: 0
|
||||
}
|
||||
});
|
||||
|
||||
const emit = defineEmits(['tab-change', 'search-click', 'menu-click', 'more-click']);
|
||||
|
||||
// 状态栏高度
|
||||
const statusBarHeight = ref(0);
|
||||
|
||||
onMounted(() => {
|
||||
try {
|
||||
const systemInfo = uni.getSystemInfoSync();
|
||||
statusBarHeight.value = systemInfo.statusBarHeight || 0;
|
||||
} catch (error) {
|
||||
statusBarHeight.value = 0;
|
||||
}
|
||||
});
|
||||
|
||||
function handleTabClick(index) {
|
||||
emit('tab-change', index);
|
||||
}
|
||||
|
||||
function handleSearchClick() {
|
||||
emit('search-click');
|
||||
}
|
||||
|
||||
function handleMenuClick() {
|
||||
emit('menu-click');
|
||||
}
|
||||
|
||||
function handleMoreClick() {
|
||||
emit('more-click');
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page-header {
|
||||
padding: 40rpx 28rpx 0;
|
||||
flex-shrink: 0;
|
||||
/* #ifdef MP-WEIXIN */
|
||||
padding-top: calc(40rpx + env(safe-area-inset-top));
|
||||
/* #endif */
|
||||
/* #ifdef H5 */
|
||||
padding-top: calc(40rpx + var(--status-bar-height, 0px));
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.header-top {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 15rpx;
|
||||
}
|
||||
|
||||
.title-section {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.main-title {
|
||||
font-size: 40rpx;
|
||||
font-weight: 600;
|
||||
color: #000000;
|
||||
margin-bottom: 8rpx;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.sub-title {
|
||||
font-size: 24rpx;
|
||||
line-height: 28rpx;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
text-align: left;
|
||||
font-family: 'PingFangSC-Bold', 'PingFang SC', 'Helvetica Neue', Helvetica, Arial, 'Microsoft YaHei', sans-serif;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.header-icons {
|
||||
display: flex;
|
||||
gap: 16rpx;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.icon-dot {
|
||||
width: 44rpx;
|
||||
height: 44rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 4rpx;
|
||||
|
||||
.dot {
|
||||
width: 6rpx;
|
||||
height: 6rpx;
|
||||
background-color: #666666;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.icon-single-dot {
|
||||
width: 44rpx;
|
||||
height: 44rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #666666;
|
||||
}
|
||||
|
||||
.search-bar {
|
||||
background-color: #EBF1FF;
|
||||
border-radius: 40rpx;
|
||||
padding: 0 28rpx;
|
||||
margin-bottom: 16rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 16rpx;
|
||||
height: 88rpx;
|
||||
box-shadow: none;
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
pointer-events: auto;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.search-icon {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.search-placeholder {
|
||||
flex: 1;
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tab-nav-wrapper {
|
||||
background-color: #FFFFFF;
|
||||
border-radius: 16rpx;
|
||||
padding: 6rpx 20rpx;
|
||||
margin-bottom: 10rpx;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.tab-nav {
|
||||
display: flex;
|
||||
gap: 8rpx;
|
||||
}
|
||||
|
||||
.tab-item {
|
||||
flex: 1;
|
||||
padding: 12rpx 24rpx;
|
||||
border-radius: 20rpx;
|
||||
font-size: 28rpx;
|
||||
color: #000000;
|
||||
background-color: transparent;
|
||||
text-align: center;
|
||||
transition: all 0.3s;
|
||||
position: relative;
|
||||
pointer-events: auto;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.tab-item.active {
|
||||
background: linear-gradient(135deg, #9974FD 0%, #286BFA 100%);
|
||||
color: #FFFFFF;
|
||||
font-weight: 500;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
</style>
|
||||
|
||||
144
packageA/pages/service/components/RemindPopup.vue
Normal file
144
packageA/pages/service/components/RemindPopup.vue
Normal file
@@ -0,0 +1,144 @@
|
||||
<template>
|
||||
<uni-popup
|
||||
ref="popupRef"
|
||||
type="center"
|
||||
borderRadius="10px 10px 10px 10px"
|
||||
background-color="#FFFFFF"
|
||||
:mask-click="false"
|
||||
>
|
||||
<view class="remind-popup-content">
|
||||
<view class="remind-title">提醒</view>
|
||||
<view class="remind-message">请先完善您的个人信息:</view>
|
||||
<view class="remind-list">
|
||||
<view
|
||||
class="remind-item"
|
||||
v-for="(item, index) in remindList"
|
||||
:key="index"
|
||||
>
|
||||
{{ index + 1 }}、{{ item }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="remind-btns">
|
||||
<button class="remind-btn cancel-btn" @click="handleCancel">取消</button>
|
||||
<button class="remind-btn confirm-btn" @click="handleConfirm">确认</button>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, defineExpose } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
remindList: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
});
|
||||
|
||||
const emit = defineEmits(['cancel', 'confirm']);
|
||||
|
||||
const popupRef = ref(null);
|
||||
|
||||
// 打开弹窗
|
||||
function open() {
|
||||
if (popupRef.value) {
|
||||
try {
|
||||
popupRef.value.open();
|
||||
} catch (error) {
|
||||
// 静默处理错误
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 关闭弹窗
|
||||
function close() {
|
||||
popupRef.value?.close();
|
||||
}
|
||||
|
||||
// 取消按钮
|
||||
function handleCancel() {
|
||||
emit('cancel');
|
||||
}
|
||||
|
||||
// 确认按钮
|
||||
function handleConfirm() {
|
||||
emit('confirm');
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
close
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.remind-popup-content {
|
||||
padding: 40rpx;
|
||||
width: 630rpx;
|
||||
background-color: #FFFFFF;
|
||||
border-radius: 20rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.remind-title {
|
||||
font-weight: 600;
|
||||
font-size: 32rpx;
|
||||
color: #000000;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.remind-message {
|
||||
font-size: 28rpx;
|
||||
color: #000000;
|
||||
margin-bottom: 20rpx;
|
||||
line-height: 40rpx;
|
||||
}
|
||||
|
||||
.remind-list {
|
||||
margin-bottom: 32rpx;
|
||||
min-height: 40rpx;
|
||||
}
|
||||
|
||||
.remind-item {
|
||||
font-size: 28rpx;
|
||||
color: #000000;
|
||||
line-height: 40rpx;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.remind-btns {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.remind-btn {
|
||||
flex: 1;
|
||||
height: 88rpx;
|
||||
line-height: 88rpx;
|
||||
text-align: center;
|
||||
border-radius: 8rpx;
|
||||
font-size: 28rpx;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.cancel-btn {
|
||||
background-color: #FFFFFF;
|
||||
color: #666666;
|
||||
border: 1rpx solid #E5E7EB;
|
||||
}
|
||||
|
||||
.confirm-btn {
|
||||
background-color: #256BFA;
|
||||
color: #FFFFFF;
|
||||
border: none;
|
||||
}
|
||||
|
||||
button::after {
|
||||
border: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
223
packageA/pages/service/components/SkillDetailPopup.vue
Normal file
223
packageA/pages/service/components/SkillDetailPopup.vue
Normal file
@@ -0,0 +1,223 @@
|
||||
<template>
|
||||
<uni-popup
|
||||
ref="popupRef"
|
||||
type="bottom"
|
||||
:borderRadius="'20rpx 20rpx 0 0'"
|
||||
background-color="#FFFFFF"
|
||||
maskBackgroundColor="rgba(255, 255, 255, 0.6)"
|
||||
:isMaskClick="true"
|
||||
@maskClick="handleClose"
|
||||
>
|
||||
<view class="skill-popup-content">
|
||||
<!-- 头部:标题和关闭按钮 -->
|
||||
<view class="popup-header">
|
||||
<text class="popup-title">{{ jobTitle }}</text>
|
||||
<view class="close-btn" @click="handleClose">
|
||||
<uni-icons type="closeempty" size="20" color="#000000"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 内容区域 -->
|
||||
<scroll-view scroll-y class="popup-body" :show-scrollbar="false">
|
||||
<view
|
||||
class="skill-section"
|
||||
v-for="(section, sIndex) in skillSections"
|
||||
:key="sIndex"
|
||||
>
|
||||
<view class="section-header">
|
||||
<view class="section-icon"></view>
|
||||
<text class="section-title">{{ section.title }}</text>
|
||||
</view>
|
||||
<view class="skill-list">
|
||||
<view
|
||||
class="skill-item"
|
||||
v-for="(skill, index) in section.skills"
|
||||
:key="index"
|
||||
>
|
||||
<text class="skill-name">{{ skill.name }}</text>
|
||||
<view class="skill-dots">
|
||||
<view
|
||||
class="dot"
|
||||
:class="{ 'active': i - 1 < skill.level }"
|
||||
v-for="i in 6"
|
||||
:key="i"
|
||||
></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, defineExpose } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
jobTitle: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
possessedSkills: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
improvementSkills: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
});
|
||||
|
||||
const emit = defineEmits(['close']);
|
||||
|
||||
const popupRef = ref(null);
|
||||
|
||||
// 技能区块数据
|
||||
const skillSections = computed(() => [
|
||||
{ title: '已具备技能', skills: props.possessedSkills },
|
||||
{ title: '需要提升的技能', skills: props.improvementSkills }
|
||||
]);
|
||||
|
||||
function open() {
|
||||
popupRef.value?.open('bottom');
|
||||
}
|
||||
|
||||
function close() {
|
||||
popupRef.value?.close('bottom');
|
||||
}
|
||||
|
||||
function handleClose() {
|
||||
close();
|
||||
emit('close');
|
||||
}
|
||||
|
||||
defineExpose({ open, close });
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.skill-popup-content {
|
||||
height: calc(100vh - 330rpx);
|
||||
background-color: #FFFFFF;
|
||||
border-radius: 20rpx 20rpx 0 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.popup-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 32rpx 28rpx;
|
||||
border-bottom: 1rpx solid #F0F0F0;
|
||||
flex-shrink: 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.popup-title {
|
||||
font-size: 36rpx;
|
||||
font-weight: 600;
|
||||
color: #000000;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.close-btn {
|
||||
width: 44rpx;
|
||||
height: 44rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 50%;
|
||||
background-color: #F5F5F5;
|
||||
position: absolute;
|
||||
right: 28rpx;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
.popup-body {
|
||||
flex: 1;
|
||||
padding: 0 28rpx 28rpx;
|
||||
overflow-y: auto;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.skill-section {
|
||||
margin-bottom: 40rpx;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.section-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 24rpx;
|
||||
gap: 12rpx;
|
||||
}
|
||||
|
||||
.section-icon {
|
||||
width: 24rpx;
|
||||
height: 24rpx;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(135deg, #9974FD 0%, #286BFA 100%);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #286BFA;
|
||||
}
|
||||
|
||||
.skill-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12rpx;
|
||||
}
|
||||
|
||||
.skill-item {
|
||||
background-color: #F5F5F5;
|
||||
border-radius: 12rpx;
|
||||
padding: 20rpx 24rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
min-height: 64rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.skill-name {
|
||||
font-size: 28rpx;
|
||||
color: #000000;
|
||||
flex: 1;
|
||||
margin-right: 20rpx;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.skill-dots {
|
||||
display: flex;
|
||||
gap: 8rpx;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
width: 112rpx;
|
||||
}
|
||||
|
||||
.dot {
|
||||
width: 12rpx;
|
||||
height: 12rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #E0E0E0;
|
||||
|
||||
&.active {
|
||||
background-color: #286BFA;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
355
packageA/pages/service/components/SkillDevelopment.vue
Normal file
355
packageA/pages/service/components/SkillDevelopment.vue
Normal file
@@ -0,0 +1,355 @@
|
||||
<!--suppress JSFileReferences, NpmUsedModulesInstalled, VueMissingComponentImportInspection, HtmlUnknownTag -->
|
||||
<script setup>
|
||||
import { useSkillDevelopmentStore } from '@/stores/useSkillDevelopmentStore';
|
||||
|
||||
|
||||
const store = useSkillDevelopmentStore();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="skill-development">
|
||||
<!-- 职业技能查询区域 -->
|
||||
<div class="query-section">
|
||||
<div class="section-title">
|
||||
<uni-icons color="#286BFA" size="18" type="search"></uni-icons>
|
||||
<span class="title-text">技能发展路径查询</span>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<div class="input-item">
|
||||
<span class="input-label">当前职位</span>
|
||||
<picker @change="store.eventProfession" :value="store.professionIndex" :range="store.professionsRef" range-key="label">
|
||||
<div class="picker-field">
|
||||
<span :class="store.professionLabel ? 'picker-text' : 'picker-placeholder'">
|
||||
{{ store.professionLabel || '请选择目标职业' }}
|
||||
</span>
|
||||
<uni-icons color="#999999" size="16" type="down"></uni-icons>
|
||||
</div>
|
||||
</picker>
|
||||
</div>
|
||||
<div class="input-item">
|
||||
<span class="input-label">目标职业</span>
|
||||
<picker :range="store.pathsRef" :value="store.targetCareerIndex" range-key="label" @change="store.eventTargetCareer">
|
||||
<div class="picker-field">
|
||||
<span :class="store.targetCareerLabel ? 'picker-text' : 'picker-placeholder'">
|
||||
{{ store.targetCareerLabel || '请选择目标职业' }}
|
||||
</span>
|
||||
<uni-icons color="#999999" size="16" type="down"></uni-icons>
|
||||
</div>
|
||||
</picker>
|
||||
</div>
|
||||
<button class="query-btn" @click="store.eventSearch">
|
||||
<span>查询技能发展路径</span>
|
||||
<uni-icons color="#FFFFFF" size="18" type="search"></uni-icons>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="store.careerPaths.length" class="content-section career-section">
|
||||
<div class="section-title">
|
||||
<span class="title-text">职业路径</span>
|
||||
</div>
|
||||
<div class="">
|
||||
<scroll-view scroll-x>
|
||||
<div class="career-paths">
|
||||
<template v-for="(item, index) in store.careerPaths" :key="item.label">
|
||||
<div
|
||||
:class="{ 'career-active': store.currentCareer && store.currentCareer.value === item.value }"
|
||||
class="career-path-item"
|
||||
@click="store.eventResult(index)"
|
||||
>
|
||||
<div
|
||||
class="career-index"
|
||||
>
|
||||
<span class="index">{{ item.index }}</span>
|
||||
</div>
|
||||
<div class="career-label">{{ item.label }}</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</scroll-view>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="store.careerPaths.length" class="content-section">
|
||||
<div class="section-title">
|
||||
<uni-icons color="#000000" size="18" type="person-filled"></uni-icons>
|
||||
<span class="title-text">{{ store.currentCareerLabel }}技能</span>
|
||||
</div>
|
||||
<div class="skill-list">
|
||||
<div v-if="store.result.length === 0" class="empty-text">暂无数据</div>
|
||||
<div v-for="(item, index) in store.result" :key="index" class="skill-card">
|
||||
<div class="skill-label">{{ item.label }}</div>
|
||||
<div class="skill-detail">
|
||||
<div v-for="d in item.children" :key="d.label" class="skill-detail-item">
|
||||
<div class="skill-detail-item-label">{{ d.label }}</div>
|
||||
<div class="skill-detail-item-value">
|
||||
<div class="value-item">技能得分:{{ d.value }}</div>
|
||||
<div class="value-item">权重:{{ d.weight }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.skill-development {
|
||||
padding: 10rpx 28rpx 20rpx;
|
||||
background-color: #EBF4FF;
|
||||
min-height: 95%;
|
||||
}
|
||||
|
||||
.query-section {
|
||||
background-color: #FFFFFF;
|
||||
border-radius: 16rpx;
|
||||
padding: 28rpx;
|
||||
margin-bottom: 20rpx;
|
||||
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);
|
||||
|
||||
.section-title {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.content-section {
|
||||
background-color: #FFFFFF;
|
||||
border-radius: 16rpx;
|
||||
padding: 28rpx;
|
||||
margin-bottom: 20rpx;
|
||||
box-sizing: border-box;
|
||||
overflow: visible;
|
||||
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.input-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20rpx;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.input-label {
|
||||
font-size: 28rpx;
|
||||
color: #000000;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.input-field {
|
||||
background-color: #F5F5F5;
|
||||
border: 1rpx solid #E0E0E0;
|
||||
border-radius: 12rpx;
|
||||
padding: 20rpx 24rpx;
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.path-summary {
|
||||
margin-top: 16rpx;
|
||||
font-size: 24rpx;
|
||||
color: #666666;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
button::after {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 32rpx;
|
||||
color: #000000;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12rpx;
|
||||
margin-bottom: 24rpx;
|
||||
|
||||
.content-section & {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.career-paths {
|
||||
display: grid;
|
||||
grid-auto-flow: column;
|
||||
gap: 20px;
|
||||
padding-bottom: 10px;
|
||||
|
||||
.career-path-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
width: 80px;
|
||||
padding: 5px;
|
||||
font-weight: 700;
|
||||
cursor: pointer;
|
||||
|
||||
.career-index {
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
font-size: 20px;
|
||||
color: #fff;
|
||||
border-radius: 50%;
|
||||
|
||||
.index {
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
&:before,
|
||||
&:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
&:before {
|
||||
inset: 0;
|
||||
z-index: 1;
|
||||
background: #6c64e7;
|
||||
border: 3px solid #fff;
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 1px 5px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
&:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 50%;
|
||||
z-index: 0;
|
||||
width: 100px;
|
||||
border-bottom: 4px solid #ccc;
|
||||
}
|
||||
}
|
||||
|
||||
.career-label {
|
||||
margin-top: 10px;
|
||||
font-size: 16px;
|
||||
text-align: center;
|
||||
color: #6c64e7;
|
||||
}
|
||||
|
||||
&.career-active {
|
||||
.career-index {
|
||||
&:before {
|
||||
background: #22c55e;
|
||||
}
|
||||
&:after {
|
||||
border-color: #22c55e;
|
||||
}
|
||||
}
|
||||
|
||||
.career-label {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
& + .career-path-item {
|
||||
.career-index {
|
||||
&:after {
|
||||
border-color: #22c55e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
.career-index {
|
||||
font-size: 16px;
|
||||
|
||||
&:after {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
.career-index {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.title-text {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #167CF1;
|
||||
}
|
||||
|
||||
.skill-card {
|
||||
margin-bottom: 14px;
|
||||
box-sizing: border-box;
|
||||
font-weight: 700;
|
||||
|
||||
.skill-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.skill-item {
|
||||
width: 100%;
|
||||
max-width: 796rpx;
|
||||
min-height: 162rpx;
|
||||
line-height: 40rpx;
|
||||
border-radius: 20rpx;
|
||||
background-color: rgba(239, 239, 239, 1);
|
||||
color: rgba(16, 16, 16, 1);
|
||||
font-size: 28rpx;
|
||||
text-align: center;
|
||||
padding: 24rpx;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
overflow: visible;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.skill-label {
|
||||
margin-bottom: 10px;
|
||||
font-size: 16px;
|
||||
color: #94a3b8;
|
||||
}
|
||||
|
||||
.skill-detail {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
|
||||
.skill-detail-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 8px;
|
||||
border-radius: 3px;
|
||||
background: #c1d2ea;
|
||||
}
|
||||
|
||||
.skill-detail-item-label {
|
||||
width: 55%;
|
||||
word-wrap: break-word;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
color: #334155;
|
||||
}
|
||||
|
||||
.skill-detail-item-value {
|
||||
width: 45%;
|
||||
padding-left: 6px;
|
||||
color: #4f46e5;
|
||||
box-sizing: border-box;
|
||||
|
||||
.value-item {
|
||||
text-wrap: nowrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
212
packageA/pages/service/components/SkillWeightPopup.vue
Normal file
212
packageA/pages/service/components/SkillWeightPopup.vue
Normal file
@@ -0,0 +1,212 @@
|
||||
<template>
|
||||
<uni-popup
|
||||
ref="popupRef"
|
||||
type="bottom"
|
||||
:borderRadius="'20rpx 20rpx 0 0'"
|
||||
background-color="#FFFFFF"
|
||||
maskBackgroundColor="rgba(255, 255, 255, 0.6)"
|
||||
:isMaskClick="true"
|
||||
@maskClick="handleClose"
|
||||
>
|
||||
<view class="skill-weight-popup-content">
|
||||
<!-- 头部:标题和关闭按钮 -->
|
||||
<view class="popup-header">
|
||||
<text class="popup-title">{{ skillName }}</text>
|
||||
<view class="close-btn" @click="handleClose">
|
||||
<uni-icons type="closeempty" size="20" color="#000000"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 内容区域 -->
|
||||
<scroll-view scroll-y class="popup-body" :show-scrollbar="false">
|
||||
<!-- 技能权重 -->
|
||||
<view class="info-section">
|
||||
<view class="section-header">
|
||||
<view class="section-icon"></view>
|
||||
<text class="section-title">技能权重</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">{{ skillName }}</text>
|
||||
<text class="info-value">{{ weight }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 当前水平 -->
|
||||
<view class="info-section">
|
||||
<view class="section-header">
|
||||
<view class="section-icon"></view>
|
||||
<text class="section-title">当前水平</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">能力等级</text>
|
||||
<view class="level-dots">
|
||||
<view
|
||||
class="dot"
|
||||
:class="{ 'active': i - 1 < currentLevel }"
|
||||
v-for="i in 5"
|
||||
:key="i"
|
||||
></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, defineExpose } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
skillName: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
weight: {
|
||||
type: String,
|
||||
default: '0'
|
||||
},
|
||||
currentLevel: {
|
||||
type: Number,
|
||||
default: 0
|
||||
}
|
||||
});
|
||||
|
||||
const emit = defineEmits(['close']);
|
||||
|
||||
const popupRef = ref(null);
|
||||
|
||||
function open() {
|
||||
popupRef.value?.open('bottom');
|
||||
}
|
||||
|
||||
function close() {
|
||||
popupRef.value?.close('bottom');
|
||||
}
|
||||
|
||||
function handleClose() {
|
||||
close();
|
||||
emit('close');
|
||||
}
|
||||
|
||||
defineExpose({ open, close });
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.skill-weight-popup-content {
|
||||
height: calc(100vh - 330rpx);
|
||||
background-color: #FFFFFF;
|
||||
border-radius: 20rpx 20rpx 0 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.popup-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 32rpx 28rpx;
|
||||
border-bottom: 1rpx solid #F0F0F0;
|
||||
flex-shrink: 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.popup-title {
|
||||
font-size: 36rpx;
|
||||
font-weight: 600;
|
||||
color: #000000;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.close-btn {
|
||||
width: 44rpx;
|
||||
height: 44rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 50%;
|
||||
background-color: #F5F5F5;
|
||||
position: absolute;
|
||||
right: 28rpx;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
.popup-body {
|
||||
flex: 1;
|
||||
padding: 0 28rpx 28rpx;
|
||||
overflow-y: auto;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.info-section {
|
||||
margin-bottom: 40rpx;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.section-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 24rpx;
|
||||
gap: 12rpx;
|
||||
}
|
||||
|
||||
.section-icon {
|
||||
width: 24rpx;
|
||||
height: 24rpx;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(135deg, #9974FD 0%, #286BFA 100%);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #286BFA;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
background-color: #F5F5F5;
|
||||
border-radius: 12rpx;
|
||||
padding: 20rpx 24rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.info-label {
|
||||
font-size: 28rpx;
|
||||
color: #000000;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.info-value {
|
||||
font-size: 28rpx;
|
||||
color: #286BFA;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.level-dots {
|
||||
display: flex;
|
||||
gap: 8rpx;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.dot {
|
||||
width: 12rpx;
|
||||
height: 12rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #E0E0E0;
|
||||
|
||||
&.active {
|
||||
background-color: #286BFA;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
456
packageA/pages/service/guidance.vue
Normal file
456
packageA/pages/service/guidance.vue
Normal file
@@ -0,0 +1,456 @@
|
||||
<template>
|
||||
<view class="service-guidance-container">
|
||||
<view class="guidance-header">
|
||||
<text class="header-title">服务指导</text>
|
||||
<text class="header-subtitle">如何使用喀什智慧就业平台</text>
|
||||
</view>
|
||||
|
||||
<scroll-view class="guidance-content" scroll-y="true">
|
||||
<!-- 欢迎介绍 -->
|
||||
<view class="guidance-section">
|
||||
<view class="section-title">
|
||||
<uni-icons type="info-filled" size="24" color="#256BFA"></uni-icons>
|
||||
<text class="title-text">欢迎使用</text>
|
||||
</view>
|
||||
<view class="section-content">
|
||||
<text class="content-text">喀什智慧就业平台是为您提供全方位就业服务的小程序,包括职位搜索、简历创建、职业规划等功能。</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 使用步骤 -->
|
||||
<view class="guidance-section">
|
||||
<view class="section-title">
|
||||
<uni-icons type="steps-filled" size="24" color="#256BFA"></uni-icons>
|
||||
<text class="title-text">使用步骤</text>
|
||||
</view>
|
||||
<view class="section-content">
|
||||
<view class="step-item">
|
||||
<view class="step-number">1</view>
|
||||
<view class="step-content">
|
||||
<text class="step-title">登录/注册</text>
|
||||
<text class="step-desc">首次使用请先完成登录或注册,完善个人信息以便获取更好的服务。</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="step-item">
|
||||
<view class="step-number">2</view>
|
||||
<view class="step-content">
|
||||
<text class="step-title">浏览首页</text>
|
||||
<text class="step-desc">首页展示了推荐职位、附近工作和各种服务功能,您可以根据需求选择。</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="step-item">
|
||||
<view class="step-number">3</view>
|
||||
<view class="step-content">
|
||||
<text class="step-title">搜索职位</text>
|
||||
<text class="step-desc">使用顶部搜索框输入职位名称、关键词等,快速找到您感兴趣的职位。</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="step-item">
|
||||
<view class="step-number">4</view>
|
||||
<view class="step-content">
|
||||
<text class="step-title">查看职位详情</text>
|
||||
<text class="step-desc">点击职位卡片查看详细信息,包括薪资待遇、工作地点、任职要求等。</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="step-item">
|
||||
<view class="step-number">5</view>
|
||||
<view class="step-content">
|
||||
<text class="step-title">投递简历</text>
|
||||
<text class="step-desc">如果您对某个职位感兴趣,可以直接投递简历,等待企业联系。</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="step-item">
|
||||
<view class="step-number">6</view>
|
||||
<view class="step-content">
|
||||
<text class="step-title">使用服务功能</text>
|
||||
<text class="step-desc">首页九宫格提供了多种服务,包括简历指导、劳动政策指引、技能培训等,您可以根据需要使用。</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 功能介绍 -->
|
||||
<view class="guidance-section">
|
||||
<view class="section-title">
|
||||
<uni-icons type="grid-filled" size="24" color="#256BFA"></uni-icons>
|
||||
<text class="title-text">主要功能</text>
|
||||
</view>
|
||||
<view class="section-content">
|
||||
<view class="feature-grid">
|
||||
<view class="feature-item">
|
||||
<view class="feature-icon">
|
||||
<uni-icons type="search" size="36" color="#256BFA"></uni-icons>
|
||||
</view>
|
||||
<text class="feature-title">职位搜索</text>
|
||||
<text class="feature-desc">智能匹配,精准推荐</text>
|
||||
</view>
|
||||
<view class="feature-item">
|
||||
<view class="feature-icon">
|
||||
<uni-icons type="person-filled" size="36" color="#256BFA"></uni-icons>
|
||||
</view>
|
||||
<text class="feature-title">简历管理</text>
|
||||
<text class="feature-desc">在线创建,一键投递</text>
|
||||
</view>
|
||||
<view class="feature-item">
|
||||
<view class="feature-icon">
|
||||
<uni-icons type="map-pin" size="36" color="#256BFA"></uni-icons>
|
||||
</view>
|
||||
<text class="feature-title">附近工作</text>
|
||||
<text class="feature-desc">基于位置,就近推荐</text>
|
||||
</view>
|
||||
<view class="feature-item">
|
||||
<view class="feature-icon">
|
||||
<uni-icons type="document" size="36" color="#256BFA"></uni-icons>
|
||||
</view>
|
||||
<text class="feature-title">简历指导</text>
|
||||
<text class="feature-desc">专业建议,优化简历</text>
|
||||
</view>
|
||||
<view class="feature-item">
|
||||
<view class="feature-icon">
|
||||
<uni-icons type="book-filled" size="36" color="#256BFA"></uni-icons>
|
||||
</view>
|
||||
<text class="feature-title">政策指引</text>
|
||||
<text class="feature-desc">最新政策,实时更新</text>
|
||||
</view>
|
||||
<view class="feature-item">
|
||||
<view class="feature-icon">
|
||||
<uni-icons type="videocam-filled" size="36" color="#256BFA"></uni-icons>
|
||||
</view>
|
||||
<text class="feature-title">技能培训</text>
|
||||
<text class="feature-desc">线上学习,提升技能</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 常见问题 -->
|
||||
<view class="guidance-section">
|
||||
<view class="section-title">
|
||||
<uni-icons type="help-filled" size="24" color="#256BFA"></uni-icons>
|
||||
<text class="title-text">常见问题</text>
|
||||
</view>
|
||||
<view class="section-content">
|
||||
<view class="faq-item">
|
||||
<view class="faq-question">
|
||||
<uni-icons type="right" size="18" color="#256BFA"></uni-icons>
|
||||
<text>如何修改个人信息?</text>
|
||||
</view>
|
||||
<view class="faq-answer">
|
||||
<text>在"我的"页面点击个人信息,进入编辑页面即可修改基本信息、求职意向等。</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="faq-item">
|
||||
<view class="faq-question">
|
||||
<uni-icons type="right" size="18" color="#256BFA"></uni-icons>
|
||||
<text>如何查看投递记录?</text>
|
||||
</view>
|
||||
<view class="faq-answer">
|
||||
<text>在"我的"页面点击"投递记录",即可查看所有已投递的职位和状态。</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="faq-item">
|
||||
<view class="faq-question">
|
||||
<uni-icons type="right" size="18" color="#256BFA"></uni-icons>
|
||||
<text>如何收藏职位?</text>
|
||||
</view>
|
||||
<view class="faq-answer">
|
||||
<text>在职位详情页面点击右上角的收藏按钮,即可将职位添加到收藏夹。</text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- <view class="faq-item">
|
||||
<view class="faq-question">
|
||||
<uni-icons type="right" size="18" color="#256BFA"></uni-icons>
|
||||
<text>如何联系客服?</text>
|
||||
</view>
|
||||
<view class="faq-answer">
|
||||
<text>如果您在使用过程中遇到问题,可以在"我的"页面找到"联系客服"入口,或拨打客服热线。</text>
|
||||
</view>
|
||||
</view> -->
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 温馨提示 -->
|
||||
<view class="guidance-section">
|
||||
<view class="section-title">
|
||||
<uni-icons type="warning-filled" size="24" color="#256BFA"></uni-icons>
|
||||
<text class="title-text">温馨提示</text>
|
||||
</view>
|
||||
<view class="section-content">
|
||||
<view class="tips-list">
|
||||
<view class="tip-item">
|
||||
<uni-icons type="circle" size="12" color="#256BFA" class="tip-icon"></uni-icons>
|
||||
<text class="tip-text">请确保填写的个人信息真实有效,这有助于企业更好地了解您。</text>
|
||||
</view>
|
||||
<view class="tip-item">
|
||||
<uni-icons type="circle" size="12" color="#256BFA" class="tip-icon"></uni-icons>
|
||||
<text class="tip-text">定期更新简历,保持简历内容的时效性。</text>
|
||||
</view>
|
||||
<view class="tip-item">
|
||||
<uni-icons type="circle" size="12" color="#256BFA" class="tip-icon"></uni-icons>
|
||||
<text class="tip-text">多关注"附近工作"和"推荐职位",不错过好机会。</text>
|
||||
</view>
|
||||
<view class="tip-item">
|
||||
<uni-icons type="circle" size="12" color="#256BFA" class="tip-icon"></uni-icons>
|
||||
<text class="tip-text">如有任何疑问,欢迎随时联系我们的客服团队。</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 结尾鼓励 -->
|
||||
<view class="guidance-section end-section">
|
||||
<view class="encourage-content">
|
||||
<uni-icons type="thumbsup-filled" size="48" color="#256BFA"></uni-icons>
|
||||
<text class="encourage-text">祝您早日找到理想的工作!</text>
|
||||
<text class="encourage-subtext">喀什智慧就业平台与您同行</text>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
|
||||
onLoad(() => {
|
||||
// 页面加载时的逻辑
|
||||
console.log('服务指导页面加载');
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
.service-guidance-container {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
background-color: #F5F7FA;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.guidance-header {
|
||||
padding: 32rpx 24rpx;
|
||||
background-color: #FFFFFF;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.05);
|
||||
text-align: center;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
display: block;
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.header-subtitle {
|
||||
display: block;
|
||||
font-size: 24rpx;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.guidance-content {
|
||||
flex: 1;
|
||||
padding: 24rpx;
|
||||
overflow-y: scroll;
|
||||
box-sizing: border-box;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
.guidance-section {
|
||||
background-color: #FFFFFF;
|
||||
border-radius: 16rpx;
|
||||
padding: 32rpx;
|
||||
margin-bottom: 24rpx;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.section-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.title-text {
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
margin-left: 12rpx;
|
||||
}
|
||||
|
||||
.section-content {
|
||||
font-size: 24rpx;
|
||||
color: #666666;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* 步骤样式 */
|
||||
.step-item {
|
||||
display: flex;
|
||||
margin-bottom: 32rpx;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.step-number {
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #256BFA;
|
||||
color: #FFFFFF;
|
||||
font-size: 24rpx;
|
||||
font-weight: bold;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 20rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.step-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.step-title {
|
||||
display: block;
|
||||
font-size: 26rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.step-desc {
|
||||
display: block;
|
||||
font-size: 24rpx;
|
||||
color: #666666;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* 功能网格样式 */
|
||||
.feature-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 24rpx;
|
||||
margin-top: 16rpx;
|
||||
}
|
||||
|
||||
.feature-item {
|
||||
text-align: center;
|
||||
padding: 24rpx;
|
||||
background-color: #F8FAFC;
|
||||
border-radius: 12rpx;
|
||||
}
|
||||
|
||||
.feature-icon {
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.feature-title {
|
||||
display: block;
|
||||
font-size: 24rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.feature-desc {
|
||||
display: block;
|
||||
font-size: 20rpx;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
/* 常见问题样式 */
|
||||
.faq-item {
|
||||
margin-bottom: 24rpx;
|
||||
padding-bottom: 24rpx;
|
||||
border-bottom: 1rpx solid #F0F0F0;
|
||||
}
|
||||
|
||||
.faq-item:last-child {
|
||||
border-bottom: none;
|
||||
margin-bottom: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.faq-question {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 26rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
|
||||
.faq-question uni-icons {
|
||||
margin-right: 12rpx;
|
||||
}
|
||||
|
||||
.faq-answer {
|
||||
font-size: 24rpx;
|
||||
color: #666666;
|
||||
line-height: 1.6;
|
||||
padding-left: 40rpx;
|
||||
}
|
||||
|
||||
/* 温馨提示样式 */
|
||||
.tips-list {
|
||||
margin-top: 16rpx;
|
||||
}
|
||||
|
||||
.tip-item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 16rpx;
|
||||
font-size: 24rpx;
|
||||
color: #666666;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.tip-icon {
|
||||
margin-right: 12rpx;
|
||||
margin-top: 8rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.tip-text {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
/* 结尾鼓励样式 */
|
||||
.end-section {
|
||||
text-align: center;
|
||||
background: linear-gradient(135deg, #256BFA 0%, #6A8FFF 100%);
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.end-section .section-title {
|
||||
color: #FFFFFF;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.end-section .title-text {
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.encourage-content {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.encourage-content uni-icons {
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.encourage-text {
|
||||
display: block;
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #FFFFFF;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.encourage-subtext {
|
||||
display: block;
|
||||
font-size: 24rpx;
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
}
|
||||
</style>
|
||||
12
packageA/pages/service/salary-info.vue
Normal file
12
packageA/pages/service/salary-info.vue
Normal file
@@ -0,0 +1,12 @@
|
||||
<template>
|
||||
<web-view class="salary-info-container" src="https://www.mohrss.gov.cn/SYrlzyhshbzb/laodongguanxi_/fwyd/202506/t20250627_544623.html"></web-view>
|
||||
</template>
|
||||
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.salary-info-container {
|
||||
padding: 30rpx;
|
||||
background: #F5F5F5;
|
||||
min-height: 100vh;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user