14 Commits

Author SHA1 Message Date
francis-fh
3cce6621ad Merge branch 'master' of http://124.243.245.42:3000/sdz/ks-app-employment-service 2026-07-16 13:37:16 +08:00
francis-fh
5d08291ef6 Merge branch 'feature/filter-improvements' 2026-07-16 13:34:53 +08:00
francis-fh
9ce22a7949 一体机和小程序样式错乱问题修复。 2026-07-16 12:36:56 +08:00
francis-fh
76b1a65f9f bug修复 2026-07-16 12:10:52 +08:00
francis-fh
4e649401cd bug修复 2026-07-16 12:06:02 +08:00
francis-fh
a804e443f3 11 2026-07-16 01:06:02 +08:00
francis-fh
9a5ac849a0 搜索页面头部返回 2026-07-16 00:58:13 +08:00
francis-fh
d7b7f8d111 筛选条件功能开发 2026-07-16 00:54:56 +08:00
francis-fh
3980aecd56 11 2026-07-15 23:55:48 +08:00
francis-fh
805122c23f 地区跳转bug修复 2026-07-15 23:39:11 +08:00
francis-fh
ba9e1d279d 排除文件 2026-07-15 22:58:42 +08:00
francis-fh
4ea7b8abb4 feat: 筛选页面重构为侧边栏布局,地区改为多选,零工市场改为零工岗位
- 筛选页重构header和body布局,左侧tabs+右侧content
- 地区筛选从单选改为多选(checkbox-group)
- 零工市场文案改为零工岗位
- 新增area多选参数处理逻辑
2026-07-15 22:52:14 +08:00
Apcallover
43eb458c6a flat:1 2026-07-02 16:19:08 +08:00
Apcallover
809e57347a =【首页】岗位筛选 - 新增按薪资筛选条件(minSalary/maxSalary)
Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-01 14:57:27 +08:00
8 changed files with 623 additions and 329 deletions

16
.codegraph/.gitignore vendored Normal file
View File

@@ -0,0 +1,16 @@
# CodeGraph data files
# These are local to each machine and should not be committed
# Database
*.db
*.db-wal
*.db-shm
# Cache
cache/
# Logs
*.log
# Hook markers
.dirty

6
.codegraph/daemon.pid Normal file
View File

@@ -0,0 +1,6 @@
{
"pid": 37252,
"version": "0.9.9",
"socketPath": "\\\\.\\pipe\\codegraph-27b009ff71560217",
"startedAt": 1784169684502
}

3
.gitignore vendored
View File

@@ -23,4 +23,5 @@ pnpm-debug.log*
/output/
/hs_err_pid*
*.local
yarn.lock
yarn.lock
.codegraph

View File

@@ -1,5 +1,14 @@
<template>
<view v-if="show" class="filter-container">
<!-- 头部 -->
<view class="filter-header">
<view class="header-title">筛选</view>
<view class="header-close" @click="handleClose">
<view class="close-icon"></view>
</view>
</view>
<!-- 主体内容 -->
<view class="filter-body">
<!-- 左侧标签页 -->
<view class="filter-tabs">
<view
@@ -53,6 +62,24 @@
</radio-group>
</view>
<!-- 薪资 -->
<view v-if="activeTab === 'salary'" class="content-section">
<radio-group @change="(e) => handleSelect('salary', e)">
<label
v-for="option in salaryOptions"
:key="option.value"
class="radio-item"
:class="{ checked: selectedValues['salary'] === String(option.value) }"
>
<radio
:value="String(option.value)"
:checked="selectedValues['salary'] === String(option.value)"
/>
<text class="option-label">{{ option.label }}</text>
</label>
</radio-group>
</view>
<!-- 公司规模 -->
<view v-if="activeTab === 'scale'" class="content-section">
<radio-group @change="(e) => handleSelect('scale', e)">
@@ -71,22 +98,22 @@
</radio-group>
</view>
<!-- 地区 -->
<!-- 地区多选 -->
<view v-if="activeTab === 'area'" class="content-section">
<radio-group @change="(e) => handleSelect('area', e)">
<checkbox-group @change="(e) => handleCheckboxSelect('area', e)">
<label
v-for="option in areaOptions"
:key="option.value"
class="radio-item"
:class="{ checked: selectedValues['area'] === String(option.value) }"
:class="{ checked: isAreaSelected(String(option.value)) }"
>
<radio
<checkbox
:value="String(option.value)"
:checked="selectedValues['area'] === String(option.value)"
:checked="isAreaSelected(String(option.value))"
/>
<text class="option-label">{{ option.label }}</text>
</label>
</radio-group>
</checkbox-group>
</view>
<!-- 岗位类型 -->
@@ -108,20 +135,111 @@
</view>
</view>
<!-- 内容区域 -->
<view class="filter-content">
<!-- 学历要求 -->
<view v-if="activeTab === 'education'" class="content-section">
<radio-group @change="(e) => handleSelect('education', e)">
<label
v-for="option in educationOptions"
:key="option.value"
class="radio-item"
:class="{ checked: selectedValues['education'] === String(option.value) }"
>
<radio
:value="String(option.value)"
:checked="selectedValues['education'] === String(option.value)"
/>
<text class="option-label">{{ option.label }}</text>
</label>
</radio-group>
</view>
<!-- 工作经验 -->
<view v-if="activeTab === 'experience'" class="content-section">
<radio-group @change="(e) => handleSelect('experience', e)">
<label
v-for="option in experienceOptions"
:key="option.value"
class="radio-item"
:class="{ checked: selectedValues['experience'] === String(option.value) }"
>
<radio
:value="String(option.value)"
:checked="selectedValues['experience'] === String(option.value)"
/>
<text class="option-label">{{ option.label }}</text>
</label>
</radio-group>
</view>
<!-- 公司规模 -->
<view v-if="activeTab === 'scale'" class="content-section">
<radio-group @change="(e) => handleSelect('scale', e)">
<label
v-for="option in scaleOptions"
:key="option.value"
class="radio-item"
:class="{ checked: selectedValues['scale'] === String(option.value) }"
>
<radio
:value="String(option.value)"
:checked="selectedValues['scale'] === String(option.value)"
/>
<text class="option-label">{{ option.label }}</text>
</label>
</radio-group>
</view>
<!-- 岗位类型 -->
<view v-if="activeTab === 'jobType'" class="content-section">
<radio-group @change="(e) => handleSelect('jobType', e)">
<label
v-for="option in jobTypeOptions"
:key="option.value"
class="radio-item"
:class="{ checked: selectedValues['jobType'] === String(option.value) }"
>
<radio
:value="String(option.value)"
:checked="selectedValues['jobType'] === String(option.value)"
/>
<text class="option-label">{{ option.label }}</text>
</label>
</radio-group>
</view>
<!-- 地区多选 -->
<view v-if="activeTab === 'area'" class="content-section">
<checkbox-group @change="(e) => handleAreaSelect(e)">
<label
v-for="option in areaOptions"
:key="option.value"
class="radio-item"
:class="{ checked: selectedValues['area'].includes(String(option.value)) }"
>
<checkbox
:value="String(option.value)"
:checked="selectedValues['area'].includes(String(option.value))"
/>
<text class="option-label">{{ option.label }}</text>
</label>
</checkbox-group>
</view>
<!-- 底部按钮 -->
<view class="filter-footer">
<button class="footer-btn clear-btn" @click="handleClear">清除</button>
<button class="footer-btn confirm-btn" @click="handleConfirm">确认</button>
</view>
</view>
</view><!-- end filter-body -->
</view>
</template>
<script setup>
import { ref, reactive, onBeforeMount } from 'vue';
import { ref, reactive, onBeforeMount, watch } from 'vue';
import useDictStore from '@/stores/useDictStore';
const dictStore = useDictStore();
const { getTransformChildren } = dictStore;
const { getTransformChildren } = useDictStore();
const props = defineProps({
show: Boolean,
@@ -156,54 +274,99 @@ const selectedValues = reactive({
education: '',
experience: '',
scale: '',
area: '',
jobType: ''
jobType: '',
area: []
});
// 从字典获取的选项数据
const educationOptions = ref([]);
const experienceOptions = ref([]);
const scaleOptions = ref([]);
const areaOptions = ref([]);
const jobTypeOptions = ref([]);
// 加载状态
const loading = ref(true);
const areaOptions = ref([]);
// 初始化获取数据
onBeforeMount(async () => {
try {
// 先获取字典数据
await dictStore.getDictData();
// 再初始化选项数据
educationOptions.value = getTransformChildren('education', '学历要求').options || [];
experienceOptions.value = getTransformChildren('experience', '工作经验').options || [];
scaleOptions.value = getTransformChildren('scale', '公司规模').options || [];
areaOptions.value = getTransformChildren('area', '地区').options || [];
jobTypeOptions.value = getJobTypeData();
} catch (error) {
console.error('获取字典数据失败:', error);
} finally {
loading.value = false;
const initData = () => {
educationOptions.value = getTransformChildren('education', '学历要求').options || [];
experienceOptions.value = getTransformChildren('experience', '工作经验').options || [];
scaleOptions.value = getTransformChildren('scale', '公司规模').options || [];
jobTypeOptions.value = getJobTypeData();
areaOptions.value = getTransformChildren('area', '地区').options || [];
};
// 组件挂载时初始化数据
onBeforeMount(() => {
initData();
});
// 监听组件显示状态,当显示时重新初始化数据
watch(() => props.show, (newVal) => {
if (newVal) {
initData();
}
});
// 处理选项选择
// 处理单选选项选择
const handleSelect = (key, e) => {
selectedValues[key] = e.detail.value;
};
// 处理多选选项选择(地区)
// 兼容不同平台H5 返回逗号分隔字符串,小程序返回数组,统一规范化为逗号分隔字符串
const handleCheckboxSelect = (key, e) => {
let val = e.detail.value;
if (typeof val === 'string') {
// H5 平台返回逗号分隔字符串,直接使用
selectedValues[key] = val || '';
} else if (Array.isArray(val)) {
// 小程序返回数组,转为逗号分隔字符串
selectedValues[key] = val ? val.join(',') : '';
} else {
selectedValues[key] = '';
}
};
// 判断地区选项是否被选中area 统一为逗号分隔字符串)
const isAreaSelected = (value) => {
const areaVal = selectedValues.area;
if (typeof areaVal === 'string' && areaVal) {
return areaVal.split(',').includes(value);
}
return false;
};
// 清除所有选择
const handleClear = () => {
Object.keys(selectedValues).forEach((key) => {
selectedValues[key] = '';
if (key === 'area') {
selectedValues[key] = '';
} else {
selectedValues[key] = '';
}
});
};
// 确认筛选
const handleConfirm = () => {
console.log('selectedValues:', selectedValues);
emit('confirm', selectedValues);
const payload = { ...selectedValues };
// area 已统一为逗号分隔字符串,无需额外转换
console.log('[new-filter-page] area value to emit:', payload.area);
// 将选中的薪资区间转换为 minSalary / maxSalary 参数
// 始终带上 minSalary / maxSalary含空值便于父组件在清除时移除旧值
let minSalary = '';
let maxSalary = '';
if (payload.salary) {
const selected = salaryOptions.value.find((item) => item.value === payload.salary);
if (selected) {
minSalary = selected.min;
maxSalary = selected.max;
}
}
payload.minSalary = minSalary;
payload.maxSalary = maxSalary;
delete payload.salary;
console.log('selectedValues:', payload);
emit('confirm', payload);
handleClose();
};
@@ -224,22 +387,33 @@ const handleClose = () => {
background-color: #fff;
z-index: 9999;
display: flex;
flex-direction: row;
flex-direction: column;
}
.filter-header {
height: 96rpx;
height: 88rpx;
display: flex;
align-items: center;
justify-content: space-between;
justify-content: center;
padding: 0 32rpx;
border-bottom: 1rpx solid #eee;
background-color: #fff;
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
flex-shrink: 0;
position: relative;
.back-btn {
font-size: 36rpx;
.header-title {
font-size: 34rpx;
font-weight: 600;
color: #333;
}
.header-close {
position: absolute;
right: 32rpx;
top: 50%;
transform: translateY(-50%);
width: 48rpx;
height: 48rpx;
display: flex;
align-items: center;
justify-content: center;
@@ -250,45 +424,104 @@ const handleClose = () => {
&:active {
background-color: rgba(37, 107, 250, 0.1);
}
.close-icon {
position: relative;
width: 28rpx;
height: 28rpx;
&::before,
&::after {
content: '';
position: absolute;
left: 50%;
top: 50%;
width: 4rpx;
height: 28rpx;
border-radius: 2rpx;
background: #5A5A68;
}
&::before {
transform: translate(-50%, -50%) rotate(45deg);
}
&::after {
transform: translate(-50%, -50%) rotate(-45deg);
}
}
}
.filter-title {
font-size: 34rpx;
font-weight: 600;
color: #333;
.header-close-btn {
display: flex;
align-items: center;
gap: 8rpx;
padding: 12rpx 24rpx;
border-radius: 8rpx;
border: 1rpx solid #256BFA;
background: rgba(37, 107, 250, 0.08);
.close-text {
font-size: 39rpx;
color: #256BFA;
}
&:active {
background: rgba(37, 107, 250, 0.18);
transform: scale(0.96);
}
}
}
.filter-body {
flex: 1;
display: flex;
flex-direction: row;
overflow: hidden;
}
.filter-body {
flex: 1;
display: flex;
flex-direction: row;
overflow: hidden;
}
.filter-tabs {
width: 200rpx;
border-right: 1rpx solid #eee;
background-color: #f8f8f8;
display: flex;
flex-direction: column;
width: 250rpx;
border-right: 1rpx solid #eee;
background-color: #f9f9f9;
box-shadow: 3rpx 0 15rpx rgba(0, 0, 0, 0.05);
height: 100%;
box-sizing: border-box;
.tab-item {
height: 100rpx;
line-height: 100rpx;
height: 130rpx;
line-height: 130rpx;
text-align: center;
font-size: 28rpx;
font-size: 42rpx;
color: #666;
position: relative;
transition: all 0.3s ease;
border-bottom: 1rpx solid #f0f0f0;
&.active {
color: #256BFA;
font-weight: 600;
background-color: #fff;
box-shadow: 3rpx 0 10rpx rgba(37, 107, 250, 0.1);
&::after {
content: '';
position: absolute;
left: 0;
right: 0;
top: 25%;
width: 4rpx;
width: 6rpx;
height: 50%;
background-color: #256BFA;
border-radius: 2rpx;
border-radius: 3rpx 0 0 3rpx;
}
}
@@ -298,24 +531,23 @@ const handleClose = () => {
}
}
.filter-right {
flex: 1;
display: flex;
flex-direction: column;
position: relative;
}
.filter-content {
flex: 1;
padding: 40rpx 32rpx;
overflow-y: auto;
padding: 30rpx 0rpx;
display: flex;
flex-direction: column;
padding-bottom: 160rpx;
box-sizing: border-box;
}
.content-section {
padding: 0 4%;
overflow-y: auto;
flex: 12;
.radio-item {
display: flex;
align-items: center;
padding: 30rpx 0;
padding: 45rpx 0;
border-bottom: 1rpx solid #f0f0f0;
transition: all 0.3s ease;
position: relative;
@@ -329,9 +561,9 @@ const handleClose = () => {
}
radio {
width: 28rpx;
height: 28rpx;
margin-right: 24rpx;
width: 42rpx;
height: 42rpx;
margin-right: 36rpx;
transform: scale(1);
display: flex;
align-items: center;
@@ -339,10 +571,10 @@ const handleClose = () => {
}
radio .wx-radio-input {
width: 28rpx;
height: 28rpx;
width: 42rpx;
height: 42rpx;
border-radius: 50%;
border: 2rpx solid #ccc;
border: 3rpx solid #ccc;
background: transparent;
}
@@ -352,11 +584,11 @@ const handleClose = () => {
}
radio .wx-radio-input::before {
width: 16rpx;
height: 16rpx;
line-height: 16rpx;
width: 24rpx;
height: 24rpx;
line-height: 24rpx;
text-align: center;
font-size: 12rpx;
font-size: 18rpx;
color: #fff;
background: transparent;
transform: translate(-50%, -50%) scale(0);
@@ -369,38 +601,40 @@ const handleClose = () => {
}
.option-label {
font-size: 30rpx;
font-size: 45rpx;
color: #333;
flex: 1;
font-weight: 400;
line-height: 40rpx;
line-height: 60rpx;
}
}
}
.filter-footer {
height: 160rpx;
height: 200rpx;
flex: 1;
display: flex;
border-top: 1rpx solid #eee;
background-color: #fff;
box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05);
padding: 20rpx 32rpx 100rpx;
box-shadow: 0 -3rpx 15rpx rgba(0, 0, 0, 0.05);
padding: 30rpx 0;
flex-shrink: 0;
position: relative;
z-index: 10;
margin-top: auto;
box-sizing: border-box;
.footer-btn {
flex: 1;
margin: 0;
border-radius: 16rpx;
height: 80rpx;
line-height: 80rpx;
font-size: 32rpx;
margin: 0 40rpx;
border-radius: 24rpx;
height: 100rpx;
line-height: 100rpx;
font-size: 45rpx;
transition: all 0.3s ease;
font-weight: 500;
&:first-child {
margin-right: 20rpx;
margin-right: 30rpx;
background-color: #f5f5f5;
color: #666;
border: 1rpx solid #e0e0e0;

View File

@@ -21,14 +21,8 @@
</view>
<view class="card-bottom">
<view>{{ job.postingDate }}</view>
<view>
<convert-distance
:alat="job.latitude"
:along="job.longitude"
:blat="latitude"
:blong="longitude"
></convert-distance>
<dict-Label class="mar_le10" dictType="area" :value="job.jobLocationAreaCode"></dict-Label>
<view class="card-bottom-right">
<text v-if="job.regionName">地区{{ job.regionName }}</text>
</view>
</view>
</view>

50
package-lock.json generated
View File

@@ -1,11 +1,13 @@
{
"name": "ks-app-employment-service",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"dependencies": {
"@dcloudio/uni-ui": "^1.5.11",
"crypto-js": "^3.3.0",
"dayjs": "^1.11.19",
"mp-html": "^2.5.2",
"sm-crypto": "^0.3.13"
},
"devDependencies": {
@@ -13,40 +15,36 @@
}
},
"node_modules/@dcloudio/uni-ui": {
"lockfileVersion": 1,
"dependencies": {
"@dcloudio/uni-ui": {
"version": "1.5.11",
"resolved": "https://registry.npmmirror.com/@dcloudio/uni-ui/-/uni-ui-1.5.11.tgz",
"integrity": "sha512-DBtk046ofmeFd82zRI7d89SoEwrAxYzUN3WVPm1DIBkpLPG5F5QDNkHMnZGu2wNrMEmGBjBpUh3vqEY1L3jaMw=="
"version": "1.5.12",
"resolved": "https://registry.npmjs.org/@dcloudio/uni-ui/-/uni-ui-1.5.12.tgz",
"integrity": "sha512-mGDl2OZSz7D8xcUAzJegWDHOqB4MEFBSW9Esb/oJiu2/3Gk9+P/Z4bA4JZ9jv9VWBYbMrYwaTfK1Z728kABdYg==",
"license": "Apache-2.0"
},
"node_modules/crypto-js": {
"version": "4.2.0",
"resolved": "https://registry.npmmirror.com/crypto-js/-/crypto-js-4.2.0.tgz",
"resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz",
"integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==",
"dev": true
"dev": true,
"license": "MIT"
},
"node_modules/dayjs": {
"crypto-js": {
"version": "3.3.0",
"resolved": "https://registry.npmmirror.com/crypto-js/-/crypto-js-3.3.0.tgz",
"integrity": "sha512-DIT51nX0dCfKltpRiXV+/TVZq+Qq2NgF4644+K7Ttnla7zEzqc+kjJyiB96BHNyUTBxyjzRcZYpUdZa+QAqi6Q=="
"version": "1.11.21",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.21.tgz",
"integrity": "sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA==",
"license": "MIT"
},
"dayjs": {
"version": "1.11.19",
"resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.19.tgz",
"integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw=="
},
"jsbn": {
"node_modules/jsbn": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/jsbn/-/jsbn-1.1.0.tgz",
"integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A=="
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz",
"integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==",
"license": "MIT"
},
"sm-crypto": {
"version": "0.3.13",
"resolved": "https://registry.npmmirror.com/sm-crypto/-/sm-crypto-0.3.13.tgz",
"integrity": "sha512-ztNF+pZq6viCPMA1A6KKu3bgpkmYti5avykRHbcFIdSipFdkVmfUw2CnpM2kBJyppIalqvczLNM3wR8OQ0pT5w==",
"requires": {
"node_modules/sm-crypto": {
"version": "0.3.14",
"resolved": "https://registry.npmjs.org/sm-crypto/-/sm-crypto-0.3.14.tgz",
"integrity": "sha512-sR7NuGAJH93Om8keAF2/rj1EqFzEiUey4aKGyDo3nQ2BiVqhgq8UkiIoIp5qhV9w4pG7qArhfqyewcG8AbhXbg==",
"license": "MIT",
"dependencies": {
"jsbn": "^1.1.0"
}
}

View File

@@ -46,7 +46,7 @@
:class="{ 'hidden-height': shouldHideTop }"
>
<view class="container-search" v-if="shouldShowJobSeekerContent">
<view class="search-input button-click" @click="navTo('/pages/search/search')">
<view class="search-input button-click" @click="navToSearch">
<uni-icons class="iconsearch" color="#666666" type="search" size="18"></uni-icons>
<text class="inpute">职位名称薪资要求等</text>
</view>
@@ -78,7 +78,7 @@
<!-- <view class="h5-action-btn press-button" @click="handleH5SalaryClick">
<view class="btn-text">薪酬信息</view>
</view> -->
<view class="h5-action-btn press-button" @click="handleServiceClick('resume-creation')">
<view class="h5-action-btn press-button" @click="handelGoResumeGuide()">
<view class="btn-text">简历指导</view>
</view>
@@ -161,12 +161,12 @@
</view>
<view class="service-title">帮扶</view>
</view>
<!-- <view class="service-item press-button" v-if="isFourLevelLinkagePurview" @click="helpTaskClick">
<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>
<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>
@@ -279,9 +279,14 @@
{{ item.text }}
</view>
</view>
<view class="btm-right button-click" @click="openFilter">
筛选
<image class="right-sx" :class="{ active: showFilter }" src="@/static/icon/shaixun.png"></image>
<view class="btm-right-wrap">
<view class="button-click clear-btn" v-if="hasFilterConditions" @click="clearFilter">
清除筛选
</view>
<view class="btm-right button-click" @click="openFilter">
筛选
<image class="right-sx" :class="{ active: showFilter }" src="@/static/icon/shaixun.png"></image>
</view>
</view>
</view>
</view>
@@ -304,17 +309,10 @@
:value="list"
>
<view v-for="(job, index) in list" :key="index" :slot="`slot${index}`">
<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="item btn-feel" v-if="!job.recommend">
<view class="falls-card" :class="{ 'disabled-card': Number(job.jobStatus) === 1 }" @click="nextDetail(job)">
<view class="falls-card-pay">
<view class="fl_1 falls-card-title">{{ job.jobTitle }}</view>
<view class="fr_1 pay-text">
<view class="pay-text">
<Salary-Expectation
:max-salary="job.maxSalary"
:min-salary="job.minSalary"
@@ -323,53 +321,39 @@
</view>
<image v-if="job.isHot" class="flame" src="/static/icon/flame.png"></image>
</view>
<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 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>
<!-- <view class="falls-card-company" v-show="isShowJw !== 3">
<view class="falls-card-company" v-show="isShowJw !== 3">
{{ config.appInfo.areaName }}
{{ job.jobLocation }}
<!-- {{ job.jobLocation }} -->
<dict-Label dictType="jobLocationAreaCode" :value="job.jobLocationAreaCode"></dict-Label>
</view> -->
</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>
<view class="falls-card-company2">
<image class="point3" src="/static/icon/point3.png"></image>
<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">
未通过审核
{{ job.companyName }}
</view>
<!-- 招聘者显示上下架开关 -->
<view class="falls-card-actions" v-if="isRecruiter && Number(job.isPublish) === 1">
<view class="falls-card-actions" v-if="isRecruiter">
<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>
@@ -410,17 +394,10 @@
:value="list"
>
<template v-slot:default="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="item btn-feel" v-if="!job.recommend">
<view class="falls-card" :class="{ 'disabled-card': Number(job.jobStatus) === 1 }" @click="nextDetail(job)">
<view class="falls-card-pay">
<view class="fl_1 falls-card-title">{{ job.jobTitle }}</view>
<view class="fr_1 pay-text">
<view class="pay-text">
<Salary-Expectation
:max-salary="job.maxSalary"
:min-salary="job.minSalary"
@@ -429,7 +406,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>
@@ -438,16 +415,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 }}
<view class="falls-card-company" v-show="isShowJw !== 3">
{{ job.regionName }}
<!-- {{ job.jobLocation }} -->
<dict-Label dictType="jobLocationAreaCode" :value="job.jobLocationAreaCode"></dict-Label>
</view> -->
</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>
@@ -458,20 +435,10 @@
</view>
</view>
<view class="falls-card-company2">
<image class="point3" src="/static/icon/point3.png"></image>
<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">
未通过审核
{{ job.companyName }}
</view>
<!-- 招聘者显示上下架开关 -->
<view class="falls-card-actions" v-if="isRecruiter && Number(job.isPublish) === 1">
<view class="falls-card-actions" v-if="isRecruiter">
<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>
@@ -518,7 +485,8 @@
@update:show="(value) => showNewFilter = value"
/>
<!-- 微信授权登录弹窗 -->
<WxAuthLogin ref="wxAuthLoginRef" @success="handleLoginSuccess" />
<!-- <view class="maskFristEntry" v-if="maskFristEntry">
<view class="entry-content">
@@ -596,15 +564,6 @@ 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(() => {
// 未登录时不显示企业内容
@@ -625,6 +584,12 @@ const shouldShowCompanyContent = computed(() => {
return userType === 0;
});
// 判断是否有筛选条件(用于显示/隐藏清除按钮)
const hasFilterConditions = computed(() => {
const searchKeys = Object.keys(pageState.search).filter((k) => k !== 'order' && pageState.search[k]);
return searchKeys.length > 0 || Object.keys(conditionSearch.value).length > 0 || Boolean(selectedCity.value.code);
});
// 判断当前用户是否为招聘者(企业用户)
const isRecruiter = computed(() => {
if (!hasLogin.value) {
@@ -652,7 +617,7 @@ 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'
// 企业卡片组件已内联到模板中
// 滚动状态管理
@@ -743,7 +708,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',
});
@@ -756,9 +721,7 @@ const helpTaskClick = () =>{
}
//招聘会模块跳转
const handleJobFairClick = () => {
if (checkLogin()) {
navTo('/packageA/pages/careerfair/careerfair');
}
navTo('/pages/careerfair/careerfair');
};
const list = ref([]);
const pageState = reactive({
@@ -775,6 +738,15 @@ const showFilter = ref(false);
const selectFilterModel = ref(null);
const showModel = ref(false);
const showNewFilter = ref(false);
// 判断是否有活跃的筛选条件
const hasActiveFilters = computed(() => {
// 城市选择
if (selectedCity.value.code) return true;
// 筛选弹窗的条件(除了 order 之外还有其他字段)
const searchKeys = Object.keys(pageState.search).filter(k => k !== 'order');
if (searchKeys.length > 0) return true;
return false;
});
// 选中的城市
const selectedCity = ref({ code: '', name: '' });
const rangeOptions = ref([
@@ -782,11 +754,10 @@ const rangeOptions = ref([
{ value: 1, text: '最热' },
{ value: 2, text: '最新发布' },
// { value: 3, text: '疆外' },
{ value: 4, text: '零工市场' }
{ value: 4, text: '零工岗位' }
]);
const isLoaded = ref(false);
const isInitialized = ref(false); // 添加初始化标志
const isRecommendLoading = ref(false); // 请求锁,防止重复调用
const { columnCount, columnSpace } = useColumnCount(() => {
pageState.pageSize = 10 * (columnCount.value - 1) + 10;
@@ -807,7 +778,7 @@ const { columnCount, columnSpace } = useColumnCount(() => {
const getCompanyInfo = () => {
try {
const cachedUserInfo = uni.getStorageSync('userInfo') || {};
// console.log('缓存中的userInfo:', cachedUserInfo);
console.log('缓存中的userInfo:', cachedUserInfo);
// 重置企业信息
companyInfo.name = '';
@@ -851,7 +822,7 @@ const getCompanyInfo = () => {
// 跳转到企业信息详情页面
const goToCompanyInfo = () => {
navTo('/packageA/pages/company-mine/company-info');
navTo('/pages/mine/company-info');
};
@@ -861,7 +832,7 @@ onMounted(() => {
getCompanyInfo();
// pageNull.value = 0;
uni.$on('showLoginModal', () => {
uni.navigateTo({ url: '/packageA/pages/login/wx-login' });
wxAuthLoginRef.value?.open();
pageNull.value = 0;
});
});
@@ -875,7 +846,7 @@ onMounted(() => {
// 绑定新的监听
uni.$on('showLoginModal', () => {
console.log('收到showLoginModal事件打开登录弹窗');
uni.navigateTo({ url: '/packageA/pages/login/wx-login' });
wxAuthLoginRef.value?.open();
pageNull.value = 0;
});
@@ -936,42 +907,66 @@ const handleLoginSuccess = () => {
// H5环境下从URL获取token并自动登录
// onLoad 函数已移至下方,包含筛选参数处理
// 跳转到搜索页面,筛选弹窗的地区用 area添加旁地区的城市用 regionCode
const goToSearch = () => {
const query = {
regionCode: selectedCity.value.code,
regionName: selectedCity.value.name,
};
// area 只有在筛选弹窗选了地区时才传
if (pageState.search.area) {
query.area = pageState.search.area;
}
navTo('/pages/search/search', { query });
};
// 处理附近工作点击
const handleNearbyClick = () => {
navTo('/packageA/pages/nearby/nearby');
const handleNearbyClick = (options ) => {
// #ifdef MP-WEIXIN
if (checkLogin()) {
navTo('/packageA/pages/nearby/nearby');
}
// #endif
// #ifdef H5
const token = options.token || uni.getStorageSync('zkr-token');
if (token) {
navTo('/packageA/pages/nearby/nearby');
}
// #endif
};
const handleNoticeClick = () =>{
if (checkLogin()) {
uni.navigateTo({
url:'/packageB/notice/index'
})
}
function handleInstitutionClick(type){
if(type=='evaluate'){
uni.navigateTo({
url:'/packageB/notice/index'
url:'/packageB/institution/evaluationAgency'
})
}else if (type=='training'){
uni.navigateTo({
url:'/packageB/institution/trainingInstitution'
})
}
}
function handleInstitutionClick(type){
if (checkLogin()) {
if(type=='evaluate'){
uni.navigateTo({
url:'/packageB/institution/evaluationAgency'
})
}else if (type=='training'){
uni.navigateTo({
url:'/packageB/institution/trainingInstitution'
})
}
}
}
// 处理服务功能点击
const handleServiceClick = (serviceType) => {
const noLoginRequired = ['resume-creation'];
if (noLoginRequired.includes(serviceType) || checkLogin()) {
if (checkLogin()) {
navToService(serviceType);
}
};
// H5的简历指导跳转
const handelGoResumeGuide = () => {
const token = uni.getStorageSync('zkr-token');
// myToken.value = token;
if (token) {
// navTo()
navTo('/pages/resume-guide/resume-guide');
}
}
// 处理直播按钮点击
const handleLiveClick = () => {
// #ifdef MP-WEIXIN
@@ -1003,7 +998,7 @@ const handleLiveClick = () => {
// 处理薪酬信息点击
const handleSalaryInfoClick = () => {
navTo('/packageA/pages/service/salary-info');
navTo('/pages/service/salary-info');
};
const handleH5SalaryClick = () => {
@@ -1084,29 +1079,29 @@ function clearfindJob(job) {
}
function nextDetail(job) {
navTo(`/packageA/pages/post/post?encryptJobId=${encodeURIComponent(job.encryptJobId)}`);
navTo(`/packageA/pages/post/post?jobId=${encodeURIComponent(job.jobId)}`);
}
function navToService(serviceType) {
// 根据服务类型跳转到不同页面
const serviceRoutes = {
'service-guidance': '/packageA/pages/service/guidance',
'public-recruitment': '/packageA/pages/service/public-recruitment',
'resume-creation': '/packageA/pages/resume-guide/resume-guide',
'service-guidance': '/pages/service/guidance',
'public-recruitment': '/pages/service/public-recruitment',
'resume-creation': '/pages/resume-guide/resume-guide',
'labor-policy': '/packageRc/pages/policy/policyList',
'skill-training': '/packageB/train/video/videoList',
'skill-evaluation': '/packageB/train/index',
// 'skill-evaluation': '/packageA/pages/service/skill-evaluation',
'question-bank': '/packageA/pages/service/question-bank',
// 'skill-evaluation': '/pages/service/skill-evaluation',
'question-bank': '/pages/service/question-bank',
// 'quality-assessment': '/packageCa/search/search',
// 'ai-interview': '/packageA/pages/chat/chat',
'job-search': '/pages/search/search',
'career-planning': '/packageA/pages/service/career-planning',
'salary-query': '/packageA/pages/service/salary-query',
'company-info': '/packageA/pages/service/company-info',
'interview-tips': '/packageA/pages/service/interview-tips',
'employment-news': '/packageA/pages/service/employment-news',
'more-services': '/packageA/pages/service/more-services',
'career-planning': '/pages/service/career-planning',
'salary-query': '/pages/service/salary-query',
'company-info': '/pages/service/company-info',
'interview-tips': '/pages/service/interview-tips',
'employment-news': '/pages/service/employment-news',
'more-services': '/pages/service/more-services',
};
if((serviceType=='skill-training'||serviceType=='skill-evaluation')&&!uni.getStorageSync('userInfo').idCard){
$api.msg('请先完善信息');
@@ -1126,6 +1121,38 @@ function openFilter() {
emits('onShowTabbar', false);
}
// 跳转到搜索页,并携带筛选条件
function navToSearch() {
const query = {};
// 携带筛选弹窗中选择的地区(确保是逗号分隔字符串)
const areaVal = pageState.search.area;
if (areaVal && String(areaVal)) {
query.area = String(areaVal);
}
// 携带城市选择器中选择的regionCode
if (conditionSearch.value.regionCode) {
query.regionCode = String(conditionSearch.value.regionCode);
}
console.log('[navToSearch] query params:', query);
navTo('/pages/search/search', { query });
}
// 清除所有筛选条件
function clearFilter() {
// 保留 order 排序方式
const currentOrder = pageState.search.order;
pageState.search = { order: currentOrder };
// 清除城市选择
conditionSearch.value = {};
selectedCity.value = { code: '', name: '' };
// 刷新列表
if (state.tabIndex === 'all') {
getJobRecommend('refresh');
} else {
getJobList('refresh');
}
}
function handleNewFilterConfirm(values) {
pageState.search = {
...pageState.search,
@@ -1134,6 +1161,13 @@ function handleNewFilterConfirm(values) {
// 特殊处理岗位类型,直接传递数字值
if (key === 'jobType') {
pageState.search.type = value;
} else if (key === 'area') {
// 地区多选,转为逗号分隔字符串;未选择时设为空字符串
if (Array.isArray(value) && value.length > 0) {
pageState.search[key] = value.join(',');
} else {
pageState.search[key] = '';
}
} else if (value) {
pageState.search[key] = value;
} else {
@@ -1226,17 +1260,16 @@ function handelHostestSearch(val) {
}
function getJobRecommend(type = 'add') {
if (isRecommendLoading.value) return;
if (type === 'refresh') {
list.value = [];
if (waterfallsFlowRef.value) waterfallsFlowRef.value.refresh();
}
isRecommendLoading.value = true;
let params = {
pageSize: pageState.pageSize + 10,
sessionId: useUserStore().seesionId,
...pageState.search,
...conditionSearch.value,
isPublish: 1,
};
// 当选中零工市场(4)或疆外(3)时order参数传递0
if (pageState.search.order === 3 || pageState.search.order === 4) {
@@ -1251,14 +1284,14 @@ function getJobRecommend(type = 'add') {
// 只有企业用户(isCompanyUser=0)才添加current字段
if (userType === 0) {
params.current = pageNull.value;
// 企业用户不传递isPublish字段
} else {
// 求职者只显示已上架且通过审核的岗位jobStatus=0, isPublish=1
// 求职者只显示已上架的岗位jobStatus=0
params.jobStatus = 0;
params.isPublish = 1;
}
let comd = { recommend: true, jobCategory: '', tip: '确认你的兴趣,为您推荐更多合适的岗位' };
$api.createRequest('/app/job/recommend', params).then((resData) => {
console.log('=== /app/job/recommend 解密后的数据 ===', resData);
console.log('=== 岗位列表 data ===', resData.data);
const { data, total } = resData;
pageState.total = 0;
if (type === 'add') {
@@ -1305,8 +1338,6 @@ function getJobRecommend(type = 'add') {
if (!data.length) {
useUserStore().initSeesionId();
}
}).finally(() => {
isRecommendLoading.value = false;
});
}
@@ -1339,10 +1370,9 @@ function getJobList(type = 'add') {
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) => {
@@ -1369,7 +1399,7 @@ function getJobList(type = 'add') {
}
// 上架岗位
const jobUp = (encryptJobId) => {
const jobUp = (jobId) => {
if (!checkLogin()) return;
uni.showLoading({
@@ -1377,7 +1407,7 @@ const jobUp = (encryptJobId) => {
mask: true
});
$api.createRequest(`/app/job/jobUp/${encryptJobId}`, {}, 'PUT', true).then((res) => {
$api.createRequest(`/app/job/jobUp/${jobId}`, {}, 'PUT', true).then((res) => {
uni.hideLoading();
$api.msg('上架成功');
// 刷新数据
@@ -1394,7 +1424,7 @@ const jobUp = (encryptJobId) => {
};
// 下架岗位
const jobDown = (encryptJobId) => {
const jobDown = (jobId) => {
if (!checkLogin()) return;
uni.showLoading({
@@ -1402,7 +1432,7 @@ const jobDown = (encryptJobId) => {
mask: true
});
$api.createRequest(`/app/job/jobDown/${encryptJobId}`, {}, 'PUT', true).then((res) => {
$api.createRequest(`/app/job/jobDown/${jobId}`, {}, 'PUT', true).then((res) => {
uni.hideLoading();
$api.msg('下架成功');
// 刷新数据
@@ -1429,14 +1459,14 @@ const toggleJobStatus = (job) => {
// 根据当前状态决定调用哪个接口
const isCurrentlyUp = Number(job.jobStatus) === 0; // 0: 已上架, 1: 已下架
const apiUrl = isCurrentlyUp ? `/app/job/jobDown/${job.encryptJobId}` : `/app/job/jobUp/${job.encryptJobId}`;
const apiUrl = isCurrentlyUp ? `/app/job/jobDown/${job.jobId}` : `/app/job/jobUp/${job.jobId}`;
$api.createRequest(apiUrl, {}, 'PUT', true).then((res) => {
uni.hideLoading();
$api.msg(isCurrentlyUp ? '下架成功' : '上架成功');
// 更新本地数据状态,避免立即刷新整个列表
const jobIndex = list.value.findIndex(item => item.encryptJobId === job.encryptJobId);
const jobIndex = list.value.findIndex(item => item.jobId === job.jobId);
if (jobIndex !== -1) {
// 更新状态
list.value[jobIndex].jobStatus = isCurrentlyUp ? 1 : 0;
@@ -1668,9 +1698,9 @@ defineExpose({ loadData });
.iconsearch
padding-left: 36rpx
.inpute
margin-left: 20rpx
margin-left: 30rpx
font-weight: 400;
font-size: 28rpx;
font-size: 63rpx;
color: #B5B5B5;
width: 100%
.live-button
@@ -1698,7 +1728,7 @@ defineExpose({ loadData });
.live-text
font-family: 'PingFangSC-Medium', 'PingFang SC', 'Helvetica Neue', Helvetica, Arial, 'Microsoft YaHei', sans-serif
font-weight: 500
font-size: 24rpx
font-size: 36rpx
color: #FFFFFF
text-align: center
white-space: nowrap
@@ -1711,8 +1741,8 @@ defineExpose({ loadData });
border: 2rpx solid #FFFFFF;
text-align: center
font-weight: 500;
font-size: 28rpx;
height: 36rpx;
font-size: 42rpx;
height: 54rpx;
color: #000000;
padding: 20rpx 30rpx
.cards
@@ -1721,7 +1751,6 @@ defineExpose({ loadData });
grid-gap: 38rpx;
grid-template-columns: 1fr;
.card
height: calc(158rpx - 40rpx);
padding: 22rpx 26rpx
box-shadow: 0rpx 8rpx 40rpx 0rpx rgba(210,210,210,0.14);
border-radius: 16rpx 16rpx 16rpx 16rpx;
@@ -1729,11 +1758,11 @@ defineExpose({ loadData });
.card-title
font-family: 'PingFangSC-Medium', 'PingFang SC', 'Helvetica Neue', Helvetica, Arial, 'Microsoft YaHei', sans-serif;
font-weight: 600;
font-size: 32rpx;
font-size: 96rpx;
color: #000000;
.card-text
font-weight: 400;
font-size: 24rpx;
font-size: 48rpx;
color: #9E9E9E;
margin-top: 4rpx
.card:first-child
@@ -1754,7 +1783,7 @@ defineExpose({ loadData });
gap: 16rpx
.h5-action-btn
flex: 1
height: 60rpx
height: 90rpx
background:#FFFFFF
border-radius: 8rpx
display: flex
@@ -1768,7 +1797,7 @@ defineExpose({ loadData });
.btn-text
font-family: 'PingFangSC-Regular', 'PingFang SC', 'Helvetica Neue', Helvetica, Arial, 'Microsoft YaHei', sans-serif
font-weight: 400
font-size: 26rpx
font-size: 66rpx
color: #256BFA
// 服务功能网格样式
.service-grid
@@ -1911,7 +1940,7 @@ defineExpose({ loadData });
.service-title
font-family: 'PingFangSC-Medium', 'PingFang SC', 'Helvetica Neue', Helvetica, Arial, 'Microsoft YaHei', sans-serif
font-weight: 500
font-size: 24rpx
font-size: 36rpx
color: #333333
text-align: center
line-height: 1.2
@@ -1987,13 +2016,13 @@ defineExpose({ loadData });
flex-wrap: nowrap
.job
font-weight: 400;
font-size: 36rpx;
font-size: 66rpx;
color: #666D7F;
margin-right: 32rpx;
white-space: nowrap
.active
font-weight: 500;
font-size: 36rpx;
font-size: 66rpx;
color: #000000;
.jobs-add
font-family: 'PingFangSC-Regular', 'PingFang SC', 'Microsoft YaHei', 'Helvetica Neue', Helvetica, Arial, sans-serif;
@@ -2001,9 +2030,9 @@ defineExpose({ loadData });
align-items: center;
justify-content: center;
font-weight: 400;
font-size: 32rpx;
font-size: 66rpx;
color: #666D7F;
line-height: 38rpx;
line-height: 57rpx;
min-width: 80rpx;
padding: 8rpx 12rpx;
white-space: nowrap;
@@ -2019,24 +2048,34 @@ defineExpose({ loadData });
font-family: 'PingFangSC-Regular', 'PingFang SC', 'Microsoft YaHei', 'Helvetica Neue', Helvetica, Arial, sans-serif;
.filterbtm
font-weight: 400;
font-size: 32rpx;
font-size: 66rpx;
color: #666D7F;
margin-right: 8rpx
padding: 0rpx 6rpx
.active
font-weight: 500;
font-size: 32rpx;
font-size: 66rpx;
color: #256BFA;
.btm-right
font-family: 'PingFangSC-Regular', 'PingFang SC', 'Microsoft YaHei', 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-weight: 400;
font-size: 32rpx;
color: #6C7282;
.right-sx
width: 26rpx;
height: 26rpx;
.active
transform: rotate(180deg)
.btm-right-wrap
display: flex
align-items: center
.clear-btn
font-family: 'PingFangSC-Regular', 'PingFang SC', 'Microsoft YaHei', 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-weight: 400;
font-size: 28rpx;
color: #999;
margin-right: 20rpx;
white-space: nowrap;
.btm-right
font-family: 'PingFangSC-Regular', 'PingFang SC', 'Microsoft YaHei', 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-weight: 400;
font-size: 32rpx;
color: #6C7282;
.right-sx
width: 26rpx;
height: 26rpx;
.active
transform: rotate(180deg)
.table-list
background: #F4F4F4
flex: 1
@@ -2072,7 +2111,7 @@ defineExpose({ loadData });
text-align: left;
word-break:break-all
font-weight: 500;
font-size: 32rpx;
font-size: 57rpx;
color: #333333;
margin-top: 10rpx
.falls-card-pay
@@ -2088,9 +2127,9 @@ defineExpose({ loadData });
color: #4C6EFB;
padding-right: 10rpx
font-weight: 500;
font-size: 28rpx;
font-size: 66rpx;
color: #4C6EFB;
line-height: 45rpx;
line-height: 67.5rpx;
text-align: left;
.flame
position: absolute
@@ -2101,13 +2140,13 @@ defineExpose({ loadData });
height: 31rpx
.falls-card-education,.falls-card-experience
width: fit-content;
height: 30rpx;
height: 45rpx;
background: #F4F4F4;
border-radius: 4rpx;
padding: 6rpx 20rpx;
line-height: 30rpx;
padding: 12rpx 20rpx;
line-height: 45rpx;
font-weight: 400;
font-size: 24rpx;
font-size: 48rpx;
color: #6C7282;
text-align: center;
margin-top: 20rpx;
@@ -2115,9 +2154,9 @@ defineExpose({ loadData });
.falls-card-company,.falls-card-pepleNumber
margin-top: 20rpx;
font-size: 24rpx;
font-size: 48rpx;
color: #999999;
line-height: 25rpx;
line-height: 37.5rpx;
text-align: left;
.falls-card-pepleNumber
display: flex;
@@ -2125,9 +2164,9 @@ defineExpose({ loadData });
flex-wrap: wrap
margin-top: 10rpx;
font-weight: 400;
font-size: 24rpx;
font-size: 48rpx;
color: #999999;
line-height: 46rpx
line-height: 69rpx
view
display:flex
align-items: center
@@ -2145,30 +2184,19 @@ defineExpose({ loadData });
display: flex;
justify-content: space-between;
align-items: center;
font-size: 21rpx;
font-size: 48rpx;
color: #4778EC;
text-align: left;
.falls-card-company2
margin-top: 4rpx;
font-size: 24rpx;
font-size: 48rpx;
color: #999999;
text-align: left;
display: flex
.point3
margin: 4rpx 4rpx 0 0
margin: 16rpx 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
@@ -2207,14 +2235,14 @@ defineExpose({ loadData });
margin-bottom: 40rpx
.company-title
font-size: 36rpx
font-size: 54rpx
font-weight: bold
color: #333333
display: block
margin-bottom: 10rpx
.company-subtitle
font-size: 24rpx
font-size: 36rpx
color: #666666
display: block
@@ -2255,7 +2283,7 @@ defineExpose({ loadData });
background: #eb2f96
.company-title
font-size: 24rpx
font-size: 36rpx
color: #333333
font-weight: 500
@@ -2270,11 +2298,11 @@ defineExpose({ loadData });
z-index: 2;
.recommend-card-title
font-weight: 500;
font-size: 28rpx;
font-size: 42rpx;
color: #333333;
.recommend-card-tip
font-weight: 400;
font-size: 28rpx;
font-size: 42rpx;
color: #6C7282;
margin-top: 28rpx
.recommend-card-line
@@ -2318,6 +2346,8 @@ defineExpose({ loadData });
text-align: center;
line-height: 60rpx
color: #256BFA
font-weight: 400;
font-size: 42rpx;
.controll-no
width: 124rpx;
height: 56rpx;
@@ -2325,7 +2355,7 @@ defineExpose({ loadData });
border-radius: 12rpx 12rpx 12rpx 12rpx;
border: 2rpx solid #DEDEDE;
font-weight: 400;
font-size: 28rpx;
font-size: 42rpx;
color: #333333;
text-align: center;
.controll-yes:active, .controll-no:active
@@ -2437,7 +2467,7 @@ defineExpose({ loadData });
position: relative
.company-name
font-size: 34rpx
font-size: 51rpx
font-weight: 600
color: #000000
line-height: 1.3
@@ -2450,7 +2480,7 @@ defineExpose({ loadData });
.company-details
display: flex
align-items: center
font-size: 26rpx
font-size: 39rpx
color: #666666
line-height: 1.2
@@ -2494,7 +2524,7 @@ defineExpose({ loadData });
.live-text
font-family: 'PingFangSC-Medium', 'PingFang SC', 'Helvetica Neue', Helvetica, Arial, 'Microsoft YaHei', sans-serif
font-weight: 500
font-size: 24rpx
font-size: 36rpx
color: #FFFFFF
text-align: center
white-space: nowrap

View File

@@ -1,9 +1,9 @@
<template>
<view class="container safe-area-top">
<!-- 自定义头部搜索框 -->
<view class="custom-header">
<view class="custom-header" :style="{ paddingTop: statusBarHeight + 'px' }">
<view class="top">
<!-- <image class="btnback button-click" src="@/static/icon/back.png" @click="navBack"></image> -->
<image class="btnback button-click" src="@/static/icon/back.png" @click="navBack"></image>
<view class="search-box">
<uni-icons
class="iconsearch"
@@ -55,6 +55,11 @@ import { storeToRefs } from 'pinia';
import { useColumnCount } from '@/hook/useColumnCount';
import img from '@/static/icon/filter.png';
const { longitudeVal, latitudeVal } = storeToRefs(useLocationStore());
const statusBarHeight = ref(0);
// #ifdef H5
const sysInfo = uni.getSystemInfoSync();
statusBarHeight.value = sysInfo.statusBarHeight || 0;
// #endif
const searchValue = ref('');
const historyList = ref([]);
const searchParams = ref({});
@@ -79,7 +84,16 @@ onLoad((query) => {
if (arr) {
historyList.value = uni.getStorageSync('searchList');
}
const {job} = query;
const {job, area, regionCode} = query;
// 从首页筛选条件传入的地区和区域编码
console.log('[search-page] onLoad query:', JSON.stringify(query));
if (area) {
pageState.search.area = String(area);
console.log('[search-page] set area:', pageState.search.area);
}
if (regionCode) {
pageState.search.regionCode = String(regionCode);
}
if (job) {
searchValue.value = job;
searchBtn();
@@ -161,6 +175,7 @@ function getJobList(type = 'add') {
...pageState.search,
jobTitle: searchValue.value,
};
console.log('[search-page] getJobList params:', JSON.stringify(params));
$api.createRequest('/app/job/list', params, 'GET', true).then((resData) => {
const { rows, total } = resData;