This commit is contained in:
2025-12-05 18:09:45 +08:00
parent 0d5e3024bc
commit 1ba45fdf93
48 changed files with 2702 additions and 1047 deletions

View File

@@ -1,84 +1,63 @@
<template>
<view class="app-container">
<view class="nav-filter">
<view class="filter-top" @touchmove.stop.prevent>
<scroll-view :scroll-x="true" :show-scrollbar="false" class="tab-scroll">
<view class="jobs-left">
<view
class="job button-click"
:class="{ active: state.tabIndex === 'all' }"
@click="choosePosition('all')"
>
全部
</view>
<view
class="job button-click"
:class="{ active: state.tabIndex === index }"
v-for="(item, index) in userInfo.jobTitle"
:key="index"
@click="choosePosition(index)"
>
{{ item }}
</view>
</view>
</scroll-view>
<view class="jobs-add button-click" @click="navTo('/pages/search/search')">
<uni-icons class="iconsearch" color="#666D7F" type="search" size="18"></uni-icons>
<text>搜索</text>
</view>
<view class="app-container">
<view class="nav-filter">
<view class="filter-top" @touchmove.stop.prevent>
<scroll-view :scroll-x="true" :show-scrollbar="false" class="tab-scroll">
<view class="jobs-left">
<view class="job button-click" :class="{ active: state.tabIndex === 'all' }" @click="choosePosition('all')"> 全部 </view>
<view class="job button-click" :class="{ active: state.tabIndex === index }" v-for="(item, index) in userInfo.jobTitle" :key="index" @click="choosePosition(index)">
{{ item }}
</view>
</view>
</scroll-view>
<view class="jobs-add button-click" @click="navTo('/pages/search/search')">
<uni-icons class="iconsearch" color="#666D7F" type="search" size="18"></uni-icons>
<text>搜索</text>
</view>
<view class="cards">
<scroll-view :scroll-y="true" class="tab-scroll" @scrolltolower="scrollBottom">
<view class="scroll-content">
<custom-waterfalls-flow
ref="waterfallsFlowRef"
:column="columnCount"
:columnSpace="columnSpace"
:value="list"
>
<template v-slot:default="job">
<view class="slot-item">
<view class="job-image btn-feel" @click="nextVideo(job)">
<image class="cover-image" :src="job.cover" mode="aspectFill"></image>
<view class="cover-triangle"></view>
</view>
<view class="job-info" @click="nextDetail(job)">
<view class="salary">
<Salary-Expectation
:max-salary="job.maxSalary"
:min-salary="job.minSalary"
:is-month="true"
></Salary-Expectation>
<image v-if="job.isHot" class="flame" src="/static/icon/flame.png"></image>
</view>
<view class="title">{{ job.jobTitle }}</view>
<view class="desc">
<image class="point3" src="/static/icon/point3.png"></image>
<!-- <uni-icons type="location" size="14"></uni-icons> -->
<view class="descText">{{ job.companyName }}</view>
</view>
</view>
</view>
</template>
</custom-waterfalls-flow>
<loadmore ref="loadmoreRef"></loadmore>
</view>
</scroll-view>
</view>
</view>
</view>
<view class="cards">
<scroll-view :scroll-y="true" class="tab-scroll" @scrolltolower="scrollBottom">
<view class="scroll-content">
<custom-waterfalls-flow ref="waterfallsFlowRef" :column="columnCount" :columnSpace="columnSpace" :value="list">
<template v-slot:default="job">
<view class="slot-item">
<view class="job-image btn-feel" @click="nextVideo(job)">
<image class="cover-image" :src="job.cover" mode="aspectFill"></image>
<view class="cover-triangle"></view>
</view>
<view class="job-info" @click="nextDetail(job)">
<view class="salary">
<Salary-Expectation :max-salary="job.maxSalary" :min-salary="job.minSalary" :is-month="true"></Salary-Expectation>
<image v-if="job.isHot" class="flame" src="/static/icon/flame.png"></image>
</view>
<view class="title">{{ job.jobTitle }}</view>
<view class="desc">
<image class="point3" src="/static/icon/point3.png"></image>
<!-- <uni-icons type="location" size="14"></uni-icons> -->
<view class="descText">{{ job.companyName }}</view>
</view>
</view>
</view>
</template>
</custom-waterfalls-flow>
<loadmore ref="loadmoreRef"></loadmore>
</view>
</scroll-view>
</view>
</view>
</template>
<script setup>
import { reactive, inject, watch, ref, onMounted, watchEffect, nextTick } from 'vue';
import { usePagination } from '@/hook/usePagination';
const { $api, navTo } = inject('globalFunction');
import { storeToRefs } from 'pinia';
import useUserStore from '@/stores/useUserStore';
import img from '@/static/icon/filter.png';
import useLocationStore from '@/stores/useLocationStore';
import { useColumnCount } from '@/hook/useColumnCount';
import { useRecommedIndexedDBStore, jobRecommender } from '@/stores/useRecommedIndexedDBStore.js';
import { reactive, inject, watch, ref, onMounted, watchEffect, nextTick } from "vue";
import { usePagination } from "@/hook/usePagination";
const { $api, navTo } = inject("globalFunction");
import { storeToRefs } from "pinia";
import useUserStore from "@/stores/useUserStore";
import img from "@/static/icon/filter.png";
import useLocationStore from "@/stores/useLocationStore";
import { useColumnCount } from "@/hook/useColumnCount";
import { useRecommedIndexedDBStore, jobRecommender } from "@/stores/useRecommedIndexedDBStore.js";
const recommedIndexDb = useRecommedIndexedDBStore();
// status
const { userInfo } = storeToRefs(useUserStore());
@@ -86,32 +65,38 @@ const isLoaded = ref(false);
const waterfallsFlowRef = ref(null);
const loadmoreRef = ref(null);
const state = reactive({
tabIndex: 'all',
tabIndex: "all",
});
// 响应式搜索条件(可以被修改)
const searchParams = ref({});
const pageSize = ref(10);
const { list, loading, refresh, loadMore,finished } = usePagination(
(params) => $api.createRequest('/app/job/littleVideo', params),
dataToImg, // 转换函数
{
pageSize: pageSize,
search: searchParams,
dataKey: 'data',
onBeforeRequest: () => {
loadmoreRef.value?.change('loading');
},
}
);
watch(()=>finished.value, (newVal) => {
if (newVal) {
// 确保瀑布流组件知道数据已加载完成
loadmoreRef.value?.change('noMore')
}else{
loadmoreRef.value?.change('more')
const { list, loading, refresh, loadMore, finished } = usePagination(
(params) => $api.createRequest("/app/job/littleVideo", params),
dataToImg, // 转换函数
{
pageSize: pageSize,
search: searchParams,
dataKey: "data",
onBeforeRequest: () => {
if (!finished) {
loadmoreRef.value?.change("loading");
}
},
}
})
);
watch(
() => finished.value,
(newVal) => {
console.log(newVal,'+++++')
if (newVal) {
// 确保瀑布流组件知道数据已加载完成
loadmoreRef.value?.change("noMore");
} else {
loadmoreRef.value?.change("more");
}
}
);
// function imageloaded() {
// nextTick(() => {
@@ -125,61 +110,61 @@ watch(()=>finished.value, (newVal) => {
// }
const { columnCount, columnSpace } = useColumnCount(() => {
pageSize.value = 10 * (columnCount.value - 1);
nextTick(() => {
waterfallsFlowRef.value?.refresh?.();
useLocationStore().getLocation();
});
pageSize.value = 10 * (columnCount.value - 1);
nextTick(() => {
waterfallsFlowRef.value?.refresh?.();
useLocationStore().getLocation();
});
});
async function loadData() {
try {
if (isLoaded.value) return;
isLoaded.value = true;
refresh();
} catch (err) {
isLoaded.value = false; // 重置状态允许重试
throw err;
}
try {
if (isLoaded.value) return;
isLoaded.value = true;
refresh();
} catch (err) {
isLoaded.value = false; // 重置状态允许重试
throw err;
}
}
async function choosePosition(index) {
state.tabIndex = index;
if (index === 'all') {
searchParams.value.jobTitle = '';
} else {
searchParams.value.jobTitle = userInfo.value.jobTitle[index];
}
console.log(searchParams.value);
refresh('refresh');
waterfallsFlowRef.value.refresh();
state.tabIndex = index;
if (index === "all") {
searchParams.value.jobTitle = "";
} else {
searchParams.value.jobTitle = userInfo.value.jobTitle[index];
}
console.log(searchParams.value);
refresh("refresh");
waterfallsFlowRef.value.refresh();
}
function scrollBottom() {
loadMore();
loadMore();
}
function nextDetail(job) {
// 记录岗位类型,用作数据分析
if (job.jobCategory) {
const recordData = recommedIndexDb.JobParameter(job);
recommedIndexDb.addRecord(recordData);
}
navTo(`/packageA/pages/post/post?jobId=${btoa(job.jobId)}`);
// 记录岗位类型,用作数据分析
if (job.jobCategory) {
const recordData = recommedIndexDb.JobParameter(job);
recommedIndexDb.addRecord(recordData);
}
navTo(`/packageA/pages/post/post?jobId=${btoa(job.jobId)}`);
}
function nextVideo(job) {
uni.setStorageSync(`job-Info`, job);
navTo(`/packageA/pages/tiktok/tiktok`);
uni.setStorageSync(`job-Info`, job);
navTo(`/packageA/pages/tiktok/tiktok`);
}
function dataToImg(data) {
return data.map((item) => ({
...item,
// image: item.cover,
image: img,
hide: true,
}));
return data.map((item) => ({
...item,
// image: item.cover,
image: img,
hide: true,
}));
}
defineExpose({ loadData });
@@ -345,3 +330,49 @@ defineExpose({ loadData });
width: 26rpx
}
</style>
<style lang="scss" scoped>
@media (min-width: 800px) {
.nav-filter {
padding: 30rpx 40rpx;
.filter-top {
.tab-scroll {
.jobs-left {
.job {
font-size: 36rpx;
}
.active {
font-size: 42rpx;
}
}
}
.jobs-add {
font-size: 36rpx;
.iconsearch {
font-size: 50rpx !important;
}
}
}
}
.slot-item{
.job-image{
height: 500rpx;
}
.salary{
font-size: 38rpx;
}
.title{
font-size: 40rpx;
}
.desc{
.point3{
width: 40rpx;
height:40rpx ;
}
.descText{
font-size: 32rpx;
}
}
}
}
</style>