Merge remote-tracking branch 'origin/main'

# Conflicts:
#	packageB/login2.vue
This commit is contained in:
hanguangpu01
2026-04-24 14:35:44 +08:00
138 changed files with 29130 additions and 5130 deletions

View File

@@ -1,5 +1,5 @@
<template>
<view class="app-container">
<view class="app-container" @touchstart="handleTouchStart" @touchmove="handleTouchMove">
<!-- #ifdef MP-WEIXIN -->
<!-- 小程序背景图片 -->
<image class="mp-background" src="/static/icon/background2.png" mode="aspectFill"></image>
@@ -110,7 +110,7 @@
<view class="service-icon service-icon-5">
<IconfontIcon name="jinengpeixun" :size="48" color="#FFFFFF" />
</view>
<view class="service-title">技能培训</view>
<view class="service-title">技能课堂</view>
</view>
<view class="service-item press-button" @click="handleServiceClick('skill-evaluation')">
<view class="service-icon service-icon-6">
@@ -136,12 +136,7 @@
</view>
<view class="service-title">虚拟面试</view>
</view>
<view class="service-item press-button" style="justify-content:normal" @click="goRc()">
<view class="service-icon service-icon-9">
<IconfontIcon name="Graduation-simple-" :size="32" color="#FFFFFF" />
</view>
<view class="service-title" style="overflow:unset">高校毕业生<br/>智慧就业服务</view>
</view>
<view class="service-item press-button" @click="handleServiceClick('career-planning')">
<view class="service-icon service-icon-11">
<image class="service-icon-img" src="/static/icon/antOutline.png" mode="aspectFit"></image>
@@ -166,6 +161,12 @@
</view>
<view class="service-title">帮扶</view>
</view>
<!-- <view class="service-item press-button" v-if="isFourLevelLinkagePurview" @click="helpTaskClick">
<view class="service-icon service-icon-1">
<uni-icons type="shop" size="32" color="#FFFFFF"></uni-icons>
</view>
<view class="service-title">帮扶任务</view>
</view> -->
<view class="service-item press-button" @click="handleNoticeClick">
<view class="service-icon service-icon-10">
<uni-icons type="sound" size="32" color="#FFFFFF"></uni-icons>
@@ -185,6 +186,12 @@
</view>
<view class="service-title">评价机构信息</view>
</view>
<view class="service-item press-button" style="justify-content:normal" @click="goRc()">
<view class="service-icon service-icon-9">
<IconfontIcon name="Graduation-simple-" :size="32" color="#FFFFFF" />
</view>
<view class="service-title" style="overflow:unset">高校毕业生<br/>智慧就业服务</view>
</view>
</view>
<!-- #endif -->
</view>
@@ -197,7 +204,7 @@
</view>
<view class="company-grid">
<view class="company-item press-button" @click="navTo('/pages/job/publishJob')">
<view class="company-item press-button" @click="navTo('/packageA/pages/job/publishJob')">
<view class="company-icon company-icon-1">
<uni-icons type="plus-filled" size="32" color="#FFFFFF"></uni-icons>
</view>
@@ -229,7 +236,7 @@
<view class="nav-filter" :class="{ 'sticky-filter': shouldStickyFilter }" v-if="shouldShowJobSeekerContent">
<view class="filter-top" @touchmove.stop.prevent>
<view class="filter-top">
<scroll-view :scroll-x="true" :show-scrollbar="false" class="tab-scroll">
<view class="jobs-left">
<view
@@ -250,10 +257,15 @@
</view>
</view>
</scroll-view>
<view class="jobs-add button-click" @click="navTo('/packageA/pages/addPosition/addPosition')">
<uni-icons class="iconsearch" color="#666D7F" type="plusempty" size="18"></uni-icons>
<text>添加</text>
</view>
<view class="jobs-add button-click" @click="navTo('/pages/city-select/index')" style="padding-right:0;">
<text>{{ selectedCity.name || '地区' }}</text>
<image class="right-sx" :class="{ active: showFilter }" src="@/static/icon/shaixun.png"></image>
</view>
</view>
<view class="filter-bottom">
<view class="btm-left">
@@ -281,7 +293,6 @@
@scrolltolower="scrollBottom"
:enable-back-to-top="false"
:scroll-with-animation="false"
@touchmove.stop.prevent
>
<view class="falls" v-if="list.length">
<!-- #ifdef MP-WEIXIN -->
@@ -293,10 +304,17 @@
:value="list"
>
<view v-for="(job, index) in list" :key="index" :slot="`slot${index}`">
<view class="item btn-feel" v-if="!job.recommend">
<view class="falls-card" @click="nextDetail(job)">
<view class="item" v-if="!job.recommend">
<view
class="falls-card"
:class="{
'disabled-card': Number(job.isPublish) === 0
}"
@click="Number(job.isPublish) === 1 ? nextDetail(job) : null"
>
<view class="falls-card-pay">
<view class="pay-text">
<view class="fl_1 falls-card-title">{{ job.jobTitle }}</view>
<view class="fr_1 pay-text">
<Salary-Expectation
:max-salary="job.maxSalary"
:min-salary="job.minSalary"
@@ -305,31 +323,35 @@
</view>
<image v-if="job.isHot" class="flame" src="/static/icon/flame.png"></image>
</view>
<view class="falls-card-title">{{ job.jobTitle }}</view>
<view class="fl_box fl_warp">
<view class="falls-card-education mar_ri10" v-if="job.education">
<dict-Label dictType="education" :value="job.education"></dict-Label>
</view>
<view class="falls-card-experience" v-if="job.experience">
<dict-Label dictType="experience" :value="job.experience"></dict-Label>
<view>
<!-- <view class="fl_1 falls-card-title">{{ job.jobTitle }}</view> -->
<view class="fr_1 fl_box fl_warp">
<view class="falls-card-education mar_ri10" v-if="job.education">
<dict-Label dictType="education" :value="job.education"></dict-Label>
</view>
<view class="falls-card-experience" v-if="job.experience">
<dict-Label dictType="experience" :value="job.experience"></dict-Label>
</view>
</view>
</view>
<view class="falls-card-company" v-show="isShowJw !== 3">
<!-- <view class="falls-card-company" v-show="isShowJw !== 3">
{{ config.appInfo.areaName }}
<!-- {{ job.jobLocation }} -->
<dict-Label dictType="area" :value="job.jobLocationAreaCode"></dict-Label>
</view>
{{ job.jobLocation }}
<dict-Label dictType="jobLocationAreaCode" :value="job.jobLocationAreaCode"></dict-Label>
</view> -->
<view class="falls-card-pepleNumber">
<view>
<image class="point2" src="/static/icon/pintDate.png"></image>
<image class="point2" src="/static/icon/pintDate.png"></image>
<view class="fl_1">
{{ job.postingDate || '发布日期' }}
发布日期{{ job.postingDate || '暂无数据' }}
</view>
</view>
<view>
<image class="point3" src="/static/icon/pointpeople.png"></image>
<view class="fl_1">
{{ vacanciesTo(job.vacancies) }}
招聘人数{{ vacanciesTo(job.vacancies) }}
</view>
</view>
</view>
@@ -338,6 +360,24 @@
<view class="fl_1">
{{ job.companyName }}
</view>
<view class="fr-1" v-if="job.regionName">
地区{{ job.regionName }}
</view>
</view>
<!-- 未通过审核状态显示 -->
<view class="unpublished-badge" v-if="Number(job.isPublish) === 0">
未通过审核
</view>
<!-- 招聘者显示上下架开关 -->
<view class="falls-card-actions" v-if="isRecruiter && Number(job.isPublish) === 1">
<view class="job-status-switch" @click.stop="toggleJobStatus(job)">
<view class="switch-track" :class="{ 'active': Number(job.jobStatus) === 0 }">
<view class="switch-thumb" :class="{ 'active': Number(job.jobStatus) === 0 }"></view>
</view>
<view class="switch-label">
{{ Number(job.jobStatus) === 0 ? '已上架' : '已下架' }}
</view>
</view>
</view>
<!-- <view class="falls-card-matchingrate">
<view class=""><matchingDegree :job="job"></matchingDegree></view>
@@ -370,10 +410,17 @@
:value="list"
>
<template v-slot:default="job">
<view class="item btn-feel" v-if="!job.recommend">
<view class="falls-card" @click="nextDetail(job)">
<view class="item" v-if="!job.recommend">
<view
class="falls-card"
:class="{
'disabled-card': (Number(job.jobStatus) === 1 || Number(job.isPublish) === 0) && currentUserType !== 0
}"
@click="Number(job.isPublish) === 1 ? nextDetail(job) : null"
>
<view class="falls-card-pay">
<view class="pay-text">
<view class="fl_1 falls-card-title">{{ job.jobTitle }}</view>
<view class="fr_1 pay-text">
<Salary-Expectation
:max-salary="job.maxSalary"
:min-salary="job.minSalary"
@@ -382,7 +429,7 @@
</view>
<image v-if="job.isHot" class="flame" src="/static/icon/flame.png"></image>
</view>
<view class="falls-card-title">{{ job.jobTitle }}</view>
<view class="fl_box fl_warp">
<view class="falls-card-education mar_ri10" v-if="job.education">
<dict-Label dictType="education" :value="job.education"></dict-Label>
@@ -391,16 +438,16 @@
<dict-Label dictType="experience" :value="job.experience"></dict-Label>
</view>
</view>
<view class="falls-card-company" v-show="isShowJw !== 3">
{{ config.appInfo.areaName }}
<!-- {{ job.jobLocation }} -->
<dict-Label dictType="area" :value="job.jobLocationAreaCode"></dict-Label>
</view>
<!-- <view class="falls-card-company" v-show="isShowJw !== 3">
地区{{ config.appInfo.areaName }}
地址{{ job.jobLocation }}
<dict-Label dictType="jobLocationAreaCode" :value="job.jobLocationAreaCode"></dict-Label>
</view> -->
<view class="falls-card-pepleNumber">
<view>
<image class="point2" src="/static/icon/pintDate.png"></image>
<view class="fl_1">
{{ job.postingDate || '发布日期' }}
发布日期{{ job.postingDate || '暂无数据' }}
</view>
</view>
<view>
@@ -415,6 +462,24 @@
<view class="fl_1">
{{ job.companyName }}
</view>
<view class="fr-1" v-if="job.regionName">
地区{{ job.regionName }}
</view>
</view>
<!-- 未通过审核状态显示 -->
<view class="unpublished-badge" v-if="Number(job.isPublish) === 0">
未通过审核
</view>
<!-- 招聘者显示上下架开关 -->
<view class="falls-card-actions" v-if="isRecruiter && Number(job.isPublish) === 1">
<view class="job-status-switch" @click.stop="toggleJobStatus(job)">
<view class="switch-track" :class="{ 'active': Number(job.jobStatus) === 0 }">
<view class="switch-thumb" :class="{ 'active': Number(job.jobStatus) === 0 }"></view>
</view>
<view class="switch-label">
{{ Number(job.jobStatus) === 0 ? '已上架' : '已下架' }}
</view>
</view>
</view>
<!-- <view class="falls-card-matchingrate">
<view class=""><matchingDegree :job="job"></matchingDegree></view>
@@ -445,9 +510,15 @@
</view>
<!-- 筛选 -->
<select-filter ref="selectFilterModel" />
<!-- 新筛选页面 -->
<new-filter-page
:show="showNewFilter"
@confirm="handleNewFilterConfirm"
@close="handleNewFilterClose"
@update:show="(value) => showNewFilter = value"
/>
<!-- 微信授权登录弹窗 -->
<WxAuthLogin ref="wxAuthLoginRef" @success="handleLoginSuccess" />
<!-- <view class="maskFristEntry" v-if="maskFristEntry">
<view class="entry-content">
@@ -525,6 +596,15 @@ const shouldShowCompanyCard = computed(() => {
return companyInfo.name && companyInfo.name.trim() !== '';
});
// 计算当前用户类型
const currentUserType = computed(() => {
// 优先从store获取如果为空则从缓存获取
const storeIsCompanyUser = userInfo.value?.isCompanyUser;
const cachedUserInfo = uni.getStorageSync('userInfo') || {};
const cachedIsCompanyUser = cachedUserInfo.isCompanyUser;
return storeIsCompanyUser !== undefined ? Number(storeIsCompanyUser) : Number(cachedIsCompanyUser);
});
// 计算是否显示企业用户内容
const shouldShowCompanyContent = computed(() => {
// 未登录时不显示企业内容
@@ -545,14 +625,34 @@ const shouldShowCompanyContent = computed(() => {
return userType === 0;
});
// 判断当前用户是否为招聘者(企业用户)
const isRecruiter = computed(() => {
if (!hasLogin.value) {
return false;
}
// 优先从store获取如果为空则从缓存获取
const storeIsCompanyUser = userInfo.value?.isCompanyUser;
const cachedUserInfo = uni.getStorageSync('userInfo') || {};
const cachedIsCompanyUser = cachedUserInfo.isCompanyUser;
// 获取用户类型优先使用store中的isCompanyUser如果store中没有使用缓存中的isCompanyUser
// 缓存中的值可能是字符串,需要转换为数值类型
const userType = storeIsCompanyUser !== undefined ? Number(storeIsCompanyUser) : Number(cachedIsCompanyUser);
// 企业用户(isCompanyUser=0)是招聘者
return userType === 0;
});
import useDictStore from '@/stores/useDictStore';
const { getTransformChildren, oneDictData, dictLabel: getDictLabel, industryLabel } = useDictStore();
import useLocationStore from '@/stores/useLocationStore';
import selectFilter from '@/components/selectFilter/selectFilter.vue';
import newFilterPage from '@/components/new-filter-page/new-filter-page.vue';
import { useRecommedIndexedDBStore, jobRecommender } from '@/stores/useRecommedIndexedDBStore.js';
import { useScrollDirection } from '@/hook/useScrollDirection';
import { useColumnCount } from '@/hook/useColumnCount';
import WxAuthLogin from '@/components/WxAuthLogin/WxAuthLogin.vue';
import IconfontIcon from '@/components/IconfontIcon/IconfontIcon.vue'
// 企业卡片组件已内联到模板中
// 滚动状态管理
@@ -562,10 +662,48 @@ const lastScrollTop = ref(0);
const scrollTop = ref(0);
// 当用户与筛选/导航交互时,临时锁定头部显示状态,避免因数据刷新导致回弹显示
const isInteractingWithFilter = ref(false);
// 触摸事件状态
const touchStartY = ref(0);
const touchMoveY = ref(0);
// 滚动阈值配置
const HIDE_THRESHOLD = 50; // 隐藏顶部区域的滚动阈值(降低阈值,更容易触发)
const SHOW_THRESHOLD = 5; // 显示顶部区域的滚动阈值(接近顶部)
const STICKY_THRESHOLD = 80; // 筛选区域吸顶的滚动阈值
const TOUCH_MOVE_THRESHOLD = 30; // 触摸滑动阈值,用于判断是否为有效滑动
// 处理触摸开始事件
function handleTouchStart(e) {
// 记录触摸起始位置
touchStartY.value = e.touches[0].clientY;
}
// 处理触摸移动事件
function handleTouchMove(e) {
// 记录触摸移动位置
touchMoveY.value = e.touches[0].clientY;
// 计算滑动距离
const diffY = touchStartY.value - touchMoveY.value;
// 当向上滑动超过阈值时,隐藏顶部区域
if (diffY > TOUCH_MOVE_THRESHOLD) {
if (!shouldHideTop.value) {
shouldHideTop.value = true;
}
if (!shouldStickyFilter.value) {
shouldStickyFilter.value = true;
}
}
// 当向下滑动超过阈值且在顶部附近时,显示顶部区域
else if (diffY < -TOUCH_MOVE_THRESHOLD && scrollTop.value <= SHOW_THRESHOLD) {
if (shouldHideTop.value && !isInteractingWithFilter.value) {
shouldHideTop.value = false;
}
if (shouldStickyFilter.value) {
shouldStickyFilter.value = false;
}
}
}
// 简化的滚动处理函数
function handleScroll(e) {
@@ -605,7 +743,7 @@ const loadmoreRef = ref(null);
const conditionSearch = ref({});
const waterfallcolumn = ref(2);
const maskFristEntry = ref(false);
const wxAuthLoginRef = ref(null);
const state = reactive({
tabIndex: 'all',
});
@@ -613,6 +751,9 @@ const state = reactive({
const helpClick = () => {
navTo('/packageB/priority/helpFilter');
};
const helpTaskClick = () =>{
navTo('/packageB/priority/index');
}
//招聘会模块跳转
const handleJobFairClick = () => {
navTo('/pages/careerfair/careerfair');
@@ -631,11 +772,14 @@ const inputText = ref('');
const showFilter = ref(false);
const selectFilterModel = ref(null);
const showModel = ref(false);
const showNewFilter = ref(false);
// 选中的城市
const selectedCity = ref({ code: '', name: '' });
const rangeOptions = ref([
{ value: 0, text: '推荐' },
{ value: 1, text: '最热' },
{ value: 2, text: '最新发布' },
{ value: 3, text: '疆外' },
// { value: 3, text: '疆外' },
{ value: 4, text: '零工市场' }
]);
const isLoaded = ref(false);
@@ -714,7 +858,7 @@ onMounted(() => {
getCompanyInfo();
// pageNull.value = 0;
uni.$on('showLoginModal', () => {
wxAuthLoginRef.value?.open();
uni.navigateTo({ url: '/pages/login/wx-login' });
pageNull.value = 0;
});
});
@@ -723,14 +867,24 @@ onMounted(() => {
// 在组件挂载时绑定事件监听,确保只绑定一次
// 先移除可能存在的旧监听,避免重复绑定
uni.$off('showLoginModal');
uni.$off('citySelected');
// 绑定新的监听
uni.$on('showLoginModal', () => {
console.log('收到showLoginModal事件打开登录弹窗');
wxAuthLoginRef.value?.open();
uni.navigateTo({ url: '/pages/login/wx-login' });
pageNull.value = 0;
});
// 监听城市选择事件
uni.$on('citySelected', (city) => {
console.log('收到citySelected事件选择的城市:', city);
selectedCity.value = city;
// 可以在这里添加根据城市筛选职位的逻辑
conditionSearch.value.regionCode = city.code;
getJobRecommend('refresh');
});
// 获取企业信息
getCompanyInfo();
});
@@ -738,6 +892,7 @@ onMounted(() => {
onUnmounted(() => {
// 组件销毁时移除事件监听
uni.$off('showLoginModal');
uni.$off('citySelected');
});
onShow(() => {
@@ -776,26 +931,19 @@ const handleLoginSuccess = () => {
getIsFourLevelLinkagePurview()
};
// H5环境下从URL获取token并自动登录
onLoad(() => {
// #ifdef H5
const token = uni.getStorageSync('zkr-token');
if (token) {
useUserStore().loginSetToken(token);
}
// #endif
});
// onLoad 函数已移至下方,包含筛选参数处理
// 处理附近工作点击
const handleNearbyClick = (options ) => {
// #ifdef MP-WEIXIN
if (checkLogin()) {
navTo('/pages/nearby/nearby');
navTo('/packageA/pages/nearby/nearby');
}
// #endif
// #ifdef H5
const token = options.token || uni.getStorageSync('zkr-token');
if (token) {
navTo('/pages/nearby/nearby');
navTo('/packageA/pages/nearby/nearby');
}
// #endif
};
@@ -944,7 +1092,7 @@ function clearfindJob(job) {
}
function nextDetail(job) {
navTo(`/packageA/pages/post/post?jobId=${encodeURIComponent(job.jobId)}`);
navTo(`/packageA/pages/post/post?jobId=${encodeURIComponent(job.jobId)}&encryptJobId=${encodeURIComponent(job.encryptJobId)}`);
}
function navToService(serviceType) {
@@ -959,7 +1107,7 @@ function navToService(serviceType) {
// 'skill-evaluation': '/pages/service/skill-evaluation',
'question-bank': '/pages/service/question-bank',
// 'quality-assessment': '/packageCa/search/search',
// 'ai-interview': '/pages/chat/chat',
// 'ai-interview': '/packageA/pages/chat/chat',
'job-search': '/pages/search/search',
'career-planning': '/pages/service/career-planning',
'salary-query': '/pages/service/salary-query',
@@ -982,34 +1130,65 @@ function navToService(serviceType) {
function openFilter() {
isInteractingWithFilter.value = true;
showFilter.value = true;
showNewFilter.value = true;
emits('onShowTabbar', false);
selectFilterModel.value?.open({
title: '筛选',
maskClick: true,
success: (values) => {
pageState.search = {
...pageState.search,
};
for (const [key, value] of Object.entries(values)) {
// 特殊处理岗位类型,直接传递数字值
}
function handleNewFilterConfirm(values) {
pageState.search = {
...pageState.search,
};
for (const [key, value] of Object.entries(values)) {
// 特殊处理岗位类型,直接传递数字值
if (key === 'jobType') {
pageState.search.type = value;
} else if (value) {
pageState.search[key] = value;
} else {
// 如果值为空,删除该搜索条件
delete pageState.search[key];
}
}
showNewFilter.value = false;
getJobList('refresh');
// 短暂延迟后解除交互锁,避免数据刷新导致顶部区域回弹
setTimeout(() => { isInteractingWithFilter.value = false; }, 400);
emits('onShowTabbar', true);
}
// 监听页面加载,接收筛选参数
onLoad((options) => {
// #ifdef H5
const token = uni.getStorageSync('zkr-token');
if (token) {
useUserStore().loginSetToken(token);
}
// #endif
// 接收从筛选页面传递过来的参数
if (options.filterParams) {
try {
const filterParams = JSON.parse(options.filterParams);
console.log('filterParams:', filterParams);
for (const [key, value] of Object.entries(filterParams)) {
if (key === 'jobType') {
pageState.search.type = value.join(',');
} else {
pageState.search[key] = value.join(',');
pageState.search.type = value;
} else if (value) {
pageState.search[key] = value;
}
}
showFilter.value = false;
console.log('pageState.search:', pageState.search);
getJobList('refresh');
// 短暂延迟后解除交互锁,避免数据刷新导致顶部区域回弹
setTimeout(() => { isInteractingWithFilter.value = false; }, 400);
},
cancel: () => {
showFilter.value = false;
emits('onShowTabbar', true);
setTimeout(() => { isInteractingWithFilter.value = false; }, 200);
},
});
} catch (error) {
console.error('解析筛选参数失败:', error);
}
}
});
function handleNewFilterClose() {
showNewFilter.value = false;
emits('onShowTabbar', true);
setTimeout(() => { isInteractingWithFilter.value = false; }, 200);
}
function handleFilterConfirm(e) {
@@ -1064,7 +1243,6 @@ function getJobRecommend(type = 'add') {
sessionId: useUserStore().seesionId,
...pageState.search,
...conditionSearch.value,
isPublish: 1,
};
// 当选中零工市场(4)或疆外(3)时order参数传递0
if (pageState.search.order === 3 || pageState.search.order === 4) {
@@ -1079,6 +1257,11 @@ function getJobRecommend(type = 'add') {
// 只有企业用户(isCompanyUser=0)才添加current字段
if (userType === 0) {
params.current = pageNull.value;
// 企业用户不传递isPublish字段
} else {
// 求职者只显示已上架且通过审核的岗位jobStatus=0, isPublish=1
params.jobStatus = 0;
params.isPublish = 1;
}
let comd = { recommend: true, jobCategory: '', tip: '确认你的兴趣,为您推荐更多合适的岗位' };
$api.createRequest('/app/job/recommend', params).then((resData) => {
@@ -1152,6 +1335,19 @@ function getJobList(type = 'add') {
if (pageState.search.order === 3 || pageState.search.order === 4) {
params.order = 0;
}
// 判断用户类型求职者只显示已上架的岗位jobStatus=0
// 优先从store获取如果为空则从缓存获取
const storeIsCompanyUser = userInfo.value?.isCompanyUser;
const cachedUserInfo = uni.getStorageSync('userInfo') || {};
const cachedIsCompanyUser = cachedUserInfo.isCompanyUser;
const userType = storeIsCompanyUser !== undefined ? Number(storeIsCompanyUser) : Number(cachedIsCompanyUser);
// 如果不是企业用户(求职者),只显示已上架且通过审核的岗位
if (userType !== 0) {
params.jobStatus = 0;
params.isPublish = 1;
}
$api.createRequest('/app/job/list', params).then((resData) => {
const { rows, total } = resData;
@@ -1175,6 +1371,93 @@ function getJobList(type = 'add') {
}
});
}
// 上架岗位
const jobUp = (encryptJobId) => {
if (!checkLogin()) return;
uni.showLoading({
title: '处理中...',
mask: true
});
$api.createRequest(`/app/job/jobUp/${encryptJobId}`, {}, 'PUT', true).then((res) => {
uni.hideLoading();
$api.msg('上架成功');
// 刷新数据
if (state.tabIndex === 'all') {
getJobRecommend('refresh');
} else {
getJobList('refresh');
}
}).catch((err) => {
uni.hideLoading();
console.error('上架失败:', err);
$api.msg('上架失败,请重试');
});
};
// 下架岗位
const jobDown = (encryptJobId) => {
if (!checkLogin()) return;
uni.showLoading({
title: '处理中...',
mask: true
});
$api.createRequest(`/app/job/jobDown/${encryptJobId}`, {}, 'PUT', true).then((res) => {
uni.hideLoading();
$api.msg('下架成功');
// 刷新数据
if (state.tabIndex === 'all') {
getJobRecommend('refresh');
} else {
getJobList('refresh');
}
}).catch((err) => {
uni.hideLoading();
console.error('下架失败:', err);
$api.msg('下架失败,请重试');
});
};
// 切换岗位状态(上架/下架)
const toggleJobStatus = (job) => {
if (!checkLogin()) return;
uni.showLoading({
title: '处理中...',
mask: true
});
// 根据当前状态决定调用哪个接口
const isCurrentlyUp = Number(job.jobStatus) === 0; // 0: 已上架, 1: 已下架
const apiUrl = isCurrentlyUp ? `/app/job/jobDown/${job.encryptJobId}` : `/app/job/jobUp/${job.encryptJobId}`;
$api.createRequest(apiUrl, {}, 'PUT', true).then((res) => {
uni.hideLoading();
$api.msg(isCurrentlyUp ? '下架成功' : '上架成功');
// 更新本地数据状态,避免立即刷新整个列表
const jobIndex = list.value.findIndex(item => item.encryptJobId === job.encryptJobId);
if (jobIndex !== -1) {
// 更新状态
list.value[jobIndex].jobStatus = isCurrentlyUp ? 1 : 0;
}
// 也可以选择刷新数据
// if (state.tabIndex === 'all') {
// getJobRecommend('refresh');
// } else {
// getJobList('refresh');
// }
}).catch((err) => {
uni.hideLoading();
console.error('操作失败:', err);
$api.msg(isCurrentlyUp ? '下架失败,请重试' : '上架失败,请重试');
});
};
const isFourLevelLinkagePurview=ref(false)
const getIsFourLevelLinkagePurview=()=>{
let userInfo = uni.getStorageSync('userInfo')
@@ -1493,10 +1776,10 @@ defineExpose({ loadData });
color: #256BFA
// 服务功能网格样式
.service-grid
padding: 20rpx 28rpx
padding: 10rpx 28rpx
display: grid
grid-template-columns: 1fr 1fr 1fr 1fr
grid-gap: 20rpx
grid-gap: 10rpx
.service-item
display: flex
flex-direction: column
@@ -1504,12 +1787,12 @@ defineExpose({ loadData });
justify-content: center
height: 120rpx
background: transparent
padding: 10px 0px
padding: 2rpx 0px
.service-icon
width: 88rpx
height: 88rpx
border-radius: 12rpx
margin-bottom: 8rpx
width: 62rpx
height: 62rpx
border-radius: 10rpx
margin-bottom: 14rpx
flex-shrink: 0
.service-icon-1
background: linear-gradient(180deg, #FF8E8E 0%, #E53E3E 100%)
@@ -1728,6 +2011,9 @@ defineExpose({ loadData });
min-width: 80rpx;
padding: 8rpx 12rpx;
white-space: nowrap;
.right-sx
width: 28rpx;
height: 28rpx;
.filter-bottom
display: flex
justify-content: space-between
@@ -1876,6 +2162,17 @@ defineExpose({ loadData });
margin: 4rpx 4rpx 0 0
height: 26rpx
width: 26rpx
// 未通过审核状态样式
.unpublished-badge
position: absolute
top: 0
right: 0
background-color: #FF4D4F
color: #FFFFFF
font-size: 20rpx
padding: 6rpx 12rpx
border-bottom-left-radius: 16rpx
z-index: 10
// 推荐卡片
.recommend-card::before
position: absolute
@@ -2205,4 +2502,54 @@ defineExpose({ loadData });
color: #FFFFFF
text-align: center
white-space: nowrap
// 上下架开关样式
.falls-card-actions
margin-top: 20rpx
.job-status-switch
display: flex
align-items: center
justify-content: space-between
padding: 8rpx 0
.switch-track
width: 80rpx
height: 40rpx
background: #e0e0e0
border-radius: 20rpx
position: relative
transition: all 0.3s ease
cursor: pointer
&.active
background: #52c41a
.switch-thumb
position: absolute
top: 4rpx
left: 4rpx
width: 32rpx
height: 32rpx
background: #ffffff
border-radius: 50%
box-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.2)
transition: all 0.3s ease
&.active
left: 44rpx
.switch-label
font-family: 'PingFangSC-Medium', 'PingFang SC', 'Helvetica Neue', Helvetica, Arial, 'Microsoft YaHei', sans-serif
font-weight: 500
font-size: 24rpx
color: #666666
margin-left: 16rpx
min-width: 80rpx
text-align: center
// 下架后卡片置灰样式
.disabled-card
opacity: 0.6
filter: grayscale(50%)
background: #f8f8f8 !important
.falls-card-title,
.falls-card-company,
.falls-card-pepleNumber,
.falls-card-company2
color: #999999 !important
</style>

View File

@@ -1,6 +1,16 @@
<template>
<view class="app-custom-root">
<view class="app-container">
<!-- #ifdef H5 -->
<!-- 自定义导航栏 -->
<view class="custom-nav" :style="{paddingTop: statusBarHeight + 'px'}">
<view class="nav-content">
<view class="nav-back" @click="back"><text class="nav-back-text"></text></view>
<view class="nav-title">喀什智慧就业平台</view>
<view class="nav-placeholder"></view>
</view>
</view>
<!-- #endif -->
<!-- 主体内容区域 -->
<view class="container-main">
<IndexOne @onShowTabbar="changeShowTabbar" />
@@ -26,7 +36,13 @@ const userStore = useUserStore();
onLoad((options) => {
// useReadMsg().fetchMessages();
});
// 返回按钮功能
function back() {
// uni.navigateBack({
// delta: 1
// });
window.location.href = 'https://www.xjksly.cn/mechine-single-vue/';
}
onShow(() => {
// 更新自定义tabbar选中状态
tabbarManager.updateSelected(0);
@@ -191,4 +207,39 @@ onShow(() => {
background: #FFFFFF
width: 4rpx
height: 20rpx
/* 自定义导航栏样式 */
.custom-nav
background: linear-gradient(135deg, #8a9bf0, #c3cafa, #e7ebfe)
width: 100%
box-shadow: 0 2rpx 10rpx rgba(138, 155, 240, 0.2)
border-radius: 0
.nav-content
height: 80rpx
display: flex
align-items: center
justify-content: space-between
padding: 0 40rpx
.nav-back
width: 120rpx
height: 80rpx
display: flex
align-items: center
justify-content: flex-start
color: #2f56e8
font-weight: 400
transition: all 0.3s ease
&:hover
transform: translateX(-5rpx)
.nav-back-text
font-size: 56rpx
line-height: 1
text-shadow: 1rpx 1rpx 2rpx rgba(0, 0, 0, 0.1)
.nav-title
color: #4a55b0
font-size: 36rpx
font-weight: 600
text-shadow: 1rpx 1rpx 2rpx rgba(255, 255, 255, 0.8)
letter-spacing: 2rpx
.nav-placeholder
width: 120rpx
</style>