Files
ks-app-employment-service/packageB/pages/job/index.vue

566 lines
16 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="jobIndex">
<view class="searchbox">
<view class="input-wrap">
<view class="school-tip" @click="showTipLayer()">
<view class="txt">职业</view>
<view class="txt">1639</view>
<view class="icon"></view>
</view>
<text class="icon icon-search"></text>
<input type="search" v-model="kw" placeholder="请输入职业名称" @input="inputKeywrok"/>
<view class="list-wrap" v-show="kw != ''">
<navigator class="link" :url="'/packageB/pages/job/details?id='+item.Id" v-for="(item, index) in jobDataList" :key="index">{{item.Name}}</navigator>
</view>
</view>
</view>
<!-- :style="{height: winHeight - barHeight - loginHeight + 'px'}" -->
<view class="u-menu-wrap" >
<scroll-view scroll-y scroll-with-animation class="u-tab-view menu-scroll-view" :scroll-top="scrollTop" :scroll-into-view="itemId">
<view v-for="(item,index) in jobList" :key="index" class="u-tab-item"
:class="[current == index ? 'u-tab-item-active' : '']" @tap.stop="swichMenu(index)">
<text class="u-line-3">{{item.Name}}</text>
</view>
</scroll-view>
<scroll-view :scroll-top="scrollRightTop" scroll-y scroll-with-animation class="right-box" @scroll="rightScroll">
<view class="page-view">
<view class="class-item" :id="'item' + index" v-for="(item , index) in jobList" :key="index">
<view class="item-title">
<text>{{item.Name}}</text>
</view>
<view class="item-container">
<view class="thumb-box" v-for="(item1, index1) in item.SubList" :key="index1" >
<navigator class="item-menu-name" :url="`/packageB/pages/job/midList?code=${item1.Code}&name=${item1.Name}`" >{{item1.Name}}</navigator>
</view>
</view>
</view>
</view>
</scroll-view>
</view>
<view class="fiexd-visitor" v-if="isVisitor">
<navigator class="btn" url="/packageB/pagesUserInfo/binding/binding?routeType=6">请先登录</navigator>
</view>
<!-- <u-modal :show="showTip" @confirm="showTip=false" @cancel="showTip=false" confirmText="我明白了">
<view class="slot-content">
<view class="tip-layer">
<view class="title">{{layerTitile}}</view>
<view class="desc" v-html="layerDesc"></view>
</view>
</view>
</u-modal> -->
</view>
</template>
<script>
import api from "@/apiB/job.js"
import jobList from "@/dataB/jobList.json";
export default {
data() {
return {
kw: "", //搜索关键
user: uni.getStorageSync("userInfo").user,
isVisitor: false, //游客
barHeight: wx.getWindowInfo().statusBarHeight,
winHeight: wx.getWindowInfo().windowHeight,
jobDataList: [],
jobList,
scrollTop: 0, //tab标题的滚动条位置
oldScrollTop: 0, // tab标题的滚动条旧位置
current: 0, // 预设当前项的值
menuHeight: 0, // 左边菜单的高度
menuItemHeight: 0, // 左边菜单item的高度
itemId: '', // 栏目右边scroll-view用于滚动的id
arr: [], // 储存距离顶部高度的数组
scrollRightTop: 0, // 右边栏目scroll-view的滚动条高度
timer: null, // 定时器
showTip: false, //数据弹窗
layerTitile: "",
layerDesc: "",
loginHeight:99,
}
},
onLoad(e) {
if(this.user == undefined || this.user == null){
this.isVisitor = true;
this.loginHeight=99;
}else {
this.isVisitor = false;
this.loginHeight=0;
}
this.scrollRightTop = 1;
},
methods: {
showTipLayer(){
this.layerTitile = "数据说明";
this.layerDesc = "共1639个职业数据来源《中华人民共和国职业分类大典(2022年版)》如有变更以官方最新公布为准。部分职业详情页中提供与职业相关的3-5分钟介绍视频截至2025年10月职业介绍视频共计200个。";
uni.showModal({
title:this.layerTitile,
content:this.layerDesc,
confirmText:"我明白了",
confirmColor:"#1677ff",
showCancel:false
})
//this.showTip = true;
},
// 滚动新旧值
getElRect(elClass, dataVal) {
new Promise((resolve, reject) => {
const query = uni.createSelectorQuery().in(this);
query.select('.' + elClass).fields({
size: true
}, res => {
// 如果节点尚未生成res值为null循环调用执行
if (!res) {
setTimeout(() => {
this.getElRect(elClass);
}, 10);
return;
}
this[dataVal] = res.height;
resolve();
}).exec();
})
},
//滚动位置
getMenuItemTop() {
new Promise(resolve => {
let selectorQuery = uni.createSelectorQuery();
selectorQuery.selectAll('.class-item').boundingClientRect((rects) => {
// 如果节点尚未生成rects值为[](因为用selectAll所以返回的是数组),循环调用执行
if (!rects.length) {
setTimeout(() => {
this.getMenuItemTop();
}, 10);
return;
}
rects.forEach((rect) => {
// 视情况而定这里减去rects[0].top是因为第一项顶部可能不是贴到导航栏(比如有个搜索框的情况)
// this.arr.push(rect.top - rects[0].top);
this.arr.push(rect.top - rects[0].top)
resolve();
})
}).exec()
})
},
/**
* 观测元素相交状态
* 检测右边scroll-view的id为itemxx的元素与right-box的相交状态
* 如果跟.right-box底部相交就动态设置左边栏目的活动状态
*/
async observer() {
this.tabbar.map((val, index) => {
let observer = uni.createIntersectionObserver(this);
observer.relativeTo('.right-box', {
top: 0
}).observe('#item' + index, res => {
if (res.intersectionRatio > 0) {
let id = res.id.substring(4);
this.leftMenuStatus(id);
}
})
})
},
/**
* 设置左边菜单的滚动状态
* @index 传入的 ID
*/
async leftMenuStatus(index) {
this.current = index;
// 如果为0意味着尚未初始化
if (this.menuHeight == 0 || this.menuItemHeight == 0) {
await this.getElRect('menu-scroll-view', 'menuHeight');
await this.getElRect('u-tab-item', 'menuItemHeight');
}
// 将菜单活动item垂直居中
this.scrollTop = index * this.menuItemHeight + this.menuItemHeight / 2 - this.menuHeight / 2;
},
/**
* 点击左边的栏目切换
* @index 传入的 ID
*/
async swichMenu(index) {
if (this.arr.length == 0) {
await this.getMenuItemTop();
}
if (index == this.current) return;
this.scrollRightTop = this.oldScrollTop;
this.$nextTick(()=> {
this.scrollRightTop = this.arr[index];
this.current = index;
this.leftMenuStatus(index);
})
},
/**
* 右边菜单滚动
* 如果不存在height2意味着数据循环已经到了最后一个设置左边菜单为最后一项即可
*/
async rightScroll(e) {
this.oldScrollTop = e.detail.scrollTop;
if (this.arr.length == 0) {
await this.getMenuItemTop();
}
if (this.timer) return;
if (!this.menuHeight) {
await this.getElRect('menu-scroll-view', 'menuHeight');
}
setTimeout(() => { // 节流
this.timer = null;
// scrollHeight为右边菜单垂直中点位置
// let scrollHeight = e.detail.scrollTop + this.menuHeight / 2;
// scrollHeight为右边菜单头部位置
let scrollHeight = e.detail.scrollTop + 20;
for (let i = 0; i < this.arr.length; i++) {
let height1 = this.arr[i];
let height2 = this.arr[i + 1];
if (!height2 || scrollHeight >= height1 && scrollHeight < height2) {
this.leftMenuStatus(i);
return;
}
}
}, 10)
},
inputKeywrok(){
if(this.user == undefined || this.user == null){
return;
}
if(this.kw.trim() == ''){
return;
}
api.queryJobListByParentCode(this.kw.trim(),"").then((res) => {
if(res.Result == 1){
this.jobDataList = res.Data.List;
}
})
},
// 查询专业
bindSearchList() {
if(this.user == undefined || this.user == null){
return uni.showToast({
title: "请先登录",
icon: "none"
})
}
if(this.kw == ""){
return uni.showToast({
title: "请输入搜索内容",
icon: "none"
})
}
uni.navigateTo({
url: "/packageB/pages/job/smallList?name=" + this.kw.trim()
})
},
}
}
</script>
<style lang="scss" scoped>
.tip-layer {
.title {
font-size: 36rpx;
color: #333;
text-align: center;
font-weight: 600;
margin-bottom: 30rpx;
}
.desc {
font-size: 28rpx;
color: #666666;
margin-bottom: 20rpx;
&:last-child {
margin-bottom: 0;
}
}
}
.jobIndex {
position: relative;
padding-top: 0;
height: 100vh;
.u-menu-wrap {
display: flex;
height: calc(100vh - 100rpx);
overflow: auto;
padding-top: 100rpx;
.u-tab-view {
width: 350rpx;
height: 100%;
border-radius: 0rpx 40rpx 0rpx 0rpx;
background-color: #F7FAFF;
.u-tab-item {
padding-left: 34rpx;
padding-right: 10rpx;
height: 160rpx;
background: #F7FAFF;
box-sizing: border-box;
display: flex;
align-items: center;
font-size: 26rpx;
color: #444;
font-weight: 400;
}
.u-tab-item-active {
position: relative;
color: #fff;
font-size: 26rpx;
font-weight: 500;
background: #1677ff;
border-radius:5px;
}
.u-tab-item-active::before {
content: "";
position: absolute;
border-left: 6rpx solid #1677ff;
border-radius: 8rpx;
height: 28rpx;
left: 16rpx;
top: 50%;
transform: translateY(-50%);
}
}
.right-box {
.page-view {
padding: 24rpx 24rpx 1200rpx;
}
.class-item {
margin-bottom: 20rpx;
background-color: #fff;
.item-title {
font-size: 28rpx;
color: #333;
margin-bottom: 25rpx;
font-weight: 600;
}
.item-container {
display: flex;
flex-wrap: wrap;
}
.item-menu-name {
display: flex;
align-items: center;
justify-content: center;
width: 420rpx;
height: 80rpx;
padding: 0 20rpx;
line-height: 40rpx;
margin-bottom: 25rpx;
background: #FFF;
border-radius: 12rpx;
font-size: 24rpx;
color: #333;
&:nth-child(2n){
margin-right: 0;
}
&.sel {
background: #E7F1FF;
color: #1677ff;
}
}
.thumb-box {
display: flex;
justify-content: center;
flex-direction: column;
.row {
display: flex;
flex-wrap: wrap;
margin-bottom: 25rpx;
}
}
}
}
}
}
.searchbox {
position: absolute;
left: 0;
top: 0;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100rpx;
background-color: #fff;
.input-wrap {
position: relative;
width: 544rpx;
height: 76rpx;
background: #F8F8F8;
border-radius: 12rpx;
font-size: 28rpx;
margin-left: 130rpx;
.school-tip {
position: absolute;
left: -142rpx;
top: 0;
padding-left: 10rpx;
padding-top: 6rpx;
width: 110rpx;
height: 70rpx;
background: #E7F1FF;
border-radius: 8rpx 8rpx 8rpx 8rpx;
font-size: 24rpx;
color: #1677ff;
}
.icon {
position: absolute;
right: 12rpx;
top: 8rpx;
width: 29rpx;
height: 29rpx;
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARzQklUCAgICHwIZIgAAAKDSURBVEiJtZXBceJAEEVfDxyo4aIQ5AzYCAwZmAiML6hUPtiKwHYE8p5U8gUcgTeDZSMwGaAMrAsqDlbPHjyqpUDCXPZX6aCemf49Pd2/hRPIsiwExiJyLSIBEPqlElgDf6qqWiZJUnb5kC7HvV7vwTk386Y1UPgPEQmcc+OGUESW2+02aSM6Isjz/ApYAIGILOu6forjuOgKxBhzDdx7000URb86CfI8fwAegbWqTrscdxC9ASPgMYqipyMCH/mbiCzn8/nNOY73kaZpMBwOU5/WaXMTaRattRugqKpq0vVoaZoGg8Eg2O12ZdeePM/fgVBVf8RxXBiA4XCYAqjqtO1glmWzPM831toPY8zGWrvx6TyCqk6BoNfrPQCIj/7jMHd7zsfGmN++gn56852voNYzLy8vC+fcTFUvjLV25plf2yIyxtwBfH5+TqMoeo6i6FlVJ375qu1MXdcN6dgAl0DRVTEiEojI6vb2dt3Ydrtdk8aw7Yz3tRaR6z4wEpFV20aA+Xw+ObRZa+88+br10BcKEQkNEDjnOlv9EFmWjfnqlaKu61PlXABh/1zHfD3eyDn3BhSqOjmnEfsN0zkEzrkFEDQ1fmqv16vS+PScReD3dRbEQTBjYC1Zls2MMQtVvThXe76D16YNkPSBFYDvvM5H8w35LiJFW2XtwyssVVUtTRzHhYgsnXMzP2BaMRgMRkDonBunaRqcih64F5FlkiSl4V/nlV5yWxHH8QqYqupJMWx8bLfbhC657ppO36HRoCO53iP5fwPn4CYL//usqq+nRube7C6/HZkNDqYTXldWe5IS+m+EH/pds7uVYJ/Iy/mld9ZUT+GcK51zr8DqVCr/AulAaepbjIRGAAAAAElFTkSuQmCC") center no-repeat;
background-size: 100%;
}
input {
width: 400rpx;
height: 100%;
margin-left: 90rpx;
outline: none;
background: transparent;
border: none;
}
.icon-search {
position: absolute;
left: 30rpx;
top: 50%;
transform: translateY(-50%);
width: 30rpx;
height: 30rpx;
background-image: url("data:image/gif;base64,R0lGODlhHgAeAKIAAMfHx6WlpbS0tNPT0+Tk5J2dnZaWlvHx8SwAAAAAHgAeAAADv3i6SiChhCAGu5gRYbr3AZCNB/CdX0CQDOcVAiC778rSIeacdjZ4Ahah8CIRDUGWIuARYVwB5YJQu1A7Uoap41xsk1kF6OKyhBW03oFpMJ+3bcZRnf113AcPXWo3dA9HeFlweGyCUmktHWBhRwZWHQVnJUAYR4xKjod9fyRwmAtscSxwfiNXXKc0kYcKfQYwAAMDMyhNp462HzK7JKu2BWarrQ0CuR05DKKjJLMyA3sHQx/Ek9MekyTXj9mnEQAJADs=");
background-size: 100%;
}
.list-wrap {
position: absolute;
left: 0;
top: 70rpx;
width: 480rpx;
height: 350rpx;
background: #fff;
overflow: auto;
box-shadow: 0 0 4rpx 2rpx #f2f2f2;
border-radius: 8rpx;
z-index: 90;
.link {
display: flex;
align-items: center;
height: 60rpx;
border-bottom: 2rpx solid #f2f2f2;
padding-left: 20rpx;
color: #333;
font-size: 24rpx;
}
}
}
.icon-search {
position: absolute;
left: 30rpx;
top: 50%;
transform: translateY(-50%);
width: 30rpx;
height: 30rpx;
background-image: url("data:image/gif;base64,R0lGODlhHgAeAKIAAMfHx6WlpbS0tNPT0+Tk5J2dnZaWlvHx8SwAAAAAHgAeAAADv3i6SiChhCAGu5gRYbr3AZCNB/CdX0CQDOcVAiC778rSIeacdjZ4Ahah8CIRDUGWIuARYVwB5YJQu1A7Uoap41xsk1kF6OKyhBW03oFpMJ+3bcZRnf113AcPXWo3dA9HeFlweGyCUmktHWBhRwZWHQVnJUAYR4xKjod9fyRwmAtscSxwfiNXXKc0kYcKfQYwAAMDMyhNp462HzK7JKu2BWarrQ0CuR05DKKjJLMyA3sHQx/Ek9MekyTXj9mnEQAJADs=");
background-size: 100%;
}
input {
width: 70%;
height: 100%;
margin-left: 90rpx;
outline: none;
background: transparent;
border: none;
}
}
.specialty-index-main {
padding-top: 110rpx;
}
.specialty-index-con {
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
display: flex;
.specialty-index-left,
.specialty-index-right {
position: absolute;
bottom: 0;
overflow-y: auto;
top: 0;
-webkit-overflow-scrolling: touch;
}
.specialty-index-left {
left: 0;
width: 40%;
z-index: 2;
background: #fff;
border-right: 1px solid #ddd;
.ul {
.li {
position: relative;
padding: 35rpx 19rpx;
font-size: 26rpx;
line-height: 46rpx;
&.sel {
background: #fff;
box-shadow: 4rpx 0 6px #ccc;
&:before {
content: "";
display: block;
width: 8rpx;
height: 100%;
background: #1677ff;
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
}
}
}
}
}
.specialty-index-right {
right: 0;
width: 60%;
background: #fff;
padding-bottom: 30rpx;
background: #f6f6f6;
.link {
display: block;
font-size: 26rpx;
background-color: #ffff;
padding: 32rpx 25rpx;
border-bottom: 2rpx solid #f1f1f1;
text {
color: #333;
}
}
}
}
.fiexd-visitor {
position: fixed;
bottom: 0;
left: 0;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 150rpx;
background: rgba(255, 255, 255, 0.9);
z-index: 99;
border-top: 1px solid #eee;
.btn {
width: 300rpx;
height: 80rpx;
border-radius: 40rpx;
line-height: 80rpx;
background: #1677ff;
font-size: 28rpx;
text-align: center;
color: #fff;
}
}
</style>