flat: 缓动

This commit is contained in:
Apcallover
2025-12-08 21:46:55 +08:00
parent c173fdd6a8
commit f24d95cedf
25 changed files with 642 additions and 353 deletions

View File

@@ -14,8 +14,10 @@ onLaunch((options) => {
useDictStore().getDictData();
try {
getUserInfo();
useUserStore().changMiniProgramAppStatus(false);
} catch {
console.log('不是爱山东平台,使用测试登陆');
useUserStore().changMiniProgramAppStatus(true);
useUserStore().initSeesionId(); //更新
let token = uni.getStorageSync('token') || ''; // 同步获取 缓存信息
if (token) {

View File

@@ -33,12 +33,17 @@ html {
overflow-x: hidden;
}
li {
list-style: none;
}
/* 布局调整 */
/* 点击动效 */
/* 缩小 */
.button-click {
transition: transform 0.1s ease;
/* transition: transform 0.1s ease; */
transition: transform 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}
.button-click:active {
@@ -67,7 +72,8 @@ html {
}
.btn-feel {
transition: transform 0.15s ease;
transition: transform 0.5s ease;
/* transition: transform 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275); */
transform-style: preserve-3d;
}
@@ -84,7 +90,8 @@ html {
border: none;
border-radius: 6px;
cursor: pointer;
transition: transform 0.1s ease, box-shadow 0.1s ease;
/* transition: transform 0.4s ease, box-shadow 0.1s ease; */
transition: transform 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275);
/* box-shadow: 0 4px 0 #2C3E50; */
}
@@ -477,4 +484,154 @@ html {
.pointEveNone {
pointer-events: none;
}
/*
*
* TransitionGroup 动画
* stagger 错峰
* fade-up-stagger --i 淡入上滑(经典错峰)
* pop-in-stagger --i 旋转缩放弹入(活泼)
* slide-left-stagger 从左侧滑入(消息流风格)
* blur-fade-stagger --i 渐显 + 模糊(毛玻璃感)
* bounce-up-stagger 从底部弹跳入场(物理感)
*
*/
/* 淡入上滑(经典错峰) */
.fade-up-stagger-enter-active {
transition: all 0.4s cubic-bezier(0.18, 0.89, 0.32, 1.28);
transition-delay: calc(var(--i) * 0.1s);
}
.fade-up-stagger-enter-from {
opacity: 0;
transform: translateY(20px);
}
.fade-up-stagger-leave-active {
transition: opacity 0.25s ease;
}
.fade-up-stagger-leave-to {
opacity: 0;
}
/* */
.pop-in-stagger-enter-active {
transition: all 0.45s cubic-bezier(0.68, -0.55, 0.27, 1.55);
transition-delay: calc(var(--i) * 0.08s);
}
.pop-in-stagger-enter-from {
opacity: 0;
transform: scale(0.7) rotate(-10deg);
}
.pop-in-stagger-leave-active {
transition: all 0.2s ease;
}
.pop-in-stagger-leave-to {
opacity: 0;
transform: scale(0.9) rotate(5deg);
}
.slide-left-stagger-enter-active {
transition: all 0.35s ease-out;
transition-delay: calc(var(--i) * 0.07s);
}
.slide-left-stagger-enter-from {
opacity: 0;
transform: translateX(-100%);
}
.slide-left-stagger-leave-active {
transition: all 0.25s ease;
}
.slide-left-stagger-leave-to {
opacity: 0;
transform: translateX(50%);
}
/* 错峰动画 */
.stagger-enter-active {
transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
transition-delay: calc(var(--i) * 0.42s);
/* 关键120ms 间隔 */
}
.stagger-enter-from {
opacity: 0;
transform: translateY(30px) scale(0.95);
/* 更大位移 + 轻微缩放 */
}
.stagger-leave-active {
transition: all 0.25s ease;
}
.stagger-leave-to {
opacity: 0;
transform: translateX(20px);
}
.stagger-move {
transition: transform 0.4s ease;
}
.blur-fade-stagger-enter-active {
transition: all 0.5s ease;
transition-delay: calc(var(--i) * 0.09s);
}
.blur-fade-stagger-enter-from {
opacity: 0;
filter: blur(8px);
transform: scale(1.02);
}
.blur-fade-stagger-leave-active {
transition: all 0.2s ease;
}
.blur-fade-stagger-leave-to {
opacity: 0;
filter: blur(4px);
}
.bounce-up-stagger-enter-active {
animation: stagger-bounce 0.6s forwards;
animation-delay: calc(var(--i) * 0.12s);
}
.bounce-up-stagger-leave-active {
transition: all 0.25s ease;
}
.bounce-up-stagger-leave-to {
opacity: 0;
transform: translateY(30px);
}
@keyframes stagger-bounce {
0% {
opacity: 0;
transform: translateY(100px) scale(0.8);
}
60% {
transform: translateY(-10px) scale(1.05);
}
80% {
transform: translateY(5px) scale(0.98);
}
100% {
opacity: 1;
transform: translateY(0) scale(1);
}
}

View File

@@ -1,48 +1,52 @@
<template>
<view v-for="job in listData" :key="job.id">
<view class="cards" @click="nextDetail(job)">
<view class="card-company">
<text class="company line_1">{{ job.gsmc }}</text>
</view>
<view class="card-bottom" >
<view class="fl_box fs_14" >
<!-- <dict-tree-Label class="mar_ri10" dictType="industry" :value="job.industry"></dict-tree-Label>
<transition-group name="blur-fade-stagger" tag="view">
<view v-for="(job, index) in dataSource" :key="job.id" :style="{ '--i': 2 }">
<view class="cards" @click="nextDetail(job)">
<view class="card-company">
<text class="company line_1">{{ job.gsmc }}</text>
</view>
<view class="card-bottom">
<view class="fl_box fs_14">
<!-- <dict-tree-Label class="mar_ri10" dictType="industry" :value="job.industry"></dict-tree-Label>
<dict-Label dictType="scale" :value="job.scale"></dict-Label> -->
<view>{{job.gsxy}}</view>
<view>{{ job.gsxy }}</view>
</view>
<view class="ris">
<text class="fs_14">
在招职位·
<text class="color_256BFA">{{ job.zzgwsl || '-' }}</text>
</text>
</view>
</view>
<view class="ris" >
<text class="fs_14">
在招职位·
<text class="color_256BFA">{{ job.zzgwsl || '-' }}</text>
</text>
</view>
</view>
<view class="card-tags">
<view class="tag" v-if="job.nature">
<dict-Label dictType="nature" :value="job.nature"></dict-Label>
<dict-Label dictType="nature" :value="job.nature"></dict-Label>
</view>
<view class="tag">
{{ vacanciesTo(job.vacancies) }}
</view>
<view class="tag" v-if="job.qyxz">
{{job.qyxz}}
<view class="card-tags">
<view class="tag" v-if="job.nature">
<dict-Label dictType="nature" :value="job.nature"></dict-Label>
<dict-Label dictType="nature" :value="job.nature"></dict-Label>
</view>
<view class="tag">
{{ vacanciesTo(job.vacancies) }}
</view>
<view class="tag" v-if="job.qyxz">
{{ job.qyxz }}
</view>
</view>
</view>
</view>
</view>
</transition-group>
</template>
<script setup>
import { inject, computed, toRaw } from 'vue';
import { inject, computed, toRaw, watch, ref, nextTick } from 'vue';
const { insertSortData, navTo, vacanciesTo } = inject('globalFunction');
import { useRecommedIndexedDBStore } from '@/stores/useRecommedIndexedDBStore.js';
const recommedIndexDb = useRecommedIndexedDBStore();
const dataSource = ref([]);
const props = defineProps({
list: {
type: Array,
default: '标题',
default: () => [],
},
longitude: {
type: Number,
@@ -61,13 +65,28 @@ const props = defineProps({
default: '',
},
});
const listData = computed(() => {
return props.list;
});
const processedIds = new Set();
watch(
() => props.list,
(newList) => {
if (!Array.isArray(newList)) return;
const newItems = newList.filter((item) => !processedIds.has(item.id));
if (newItems.length === 0) return;
newItems.forEach((item) => processedIds.add(item.id));
const delay = 50;
newItems.forEach((item, index) => {
setTimeout(() => {
dataSource.value.push(item);
}, index * delay);
});
},
{ immediate: true }
);
function nextDetail(company) {
navTo(`/packageA/pages/UnitDetails/UnitDetails?companyId=${company.gsID}&companyName=${company.gsmc}&zphId=${props.zphId}&dataType=2`);
navTo(
`/packageA/pages/UnitDetails/UnitDetails?companyId=${company.gsID}&companyName=${company.gsmc}&zphId=${props.zphId}&dataType=2`
);
}
</script>

View File

@@ -1,48 +1,54 @@
<template>
<view v-for="job in listData" :key="job.id">
<view v-if="!job.isTitle" class="cards" @click="nextDetail(job)">
<view class="card-company">
<text class="company">{{ job.jobTitle }}</text>
<view class="salary">
<Salary-Expectation :max-salary="job.maxSalary" :min-salary="job.minSalary"></Salary-Expectation>
<transition-group name="blur-fade-stagger" tag="view">
<view v-for="job in dataSource" :key="job.id || job.jobId" :style="{ '--i': 2 }">
<view v-if="!job.isTitle" class="cards" @click="nextDetail(job)">
<view class="card-company">
<text class="company">{{ job.jobTitle }}</text>
<view class="salary">
<Salary-Expectation
:max-salary="job.maxSalary"
:min-salary="job.minSalary"
></Salary-Expectation>
</view>
</view>
<view class="card-companyName">{{ job.gwmc }}</view>
<view class="card-tags">
<view class="tag">
<dict-Label dictType="education" :value="job.education"></dict-Label>
</view>
<view class="tag">
<dict-Label dictType="experience" :value="job.experience"></dict-Label>
</view>
<view class="tag">
{{ vacanciesTo(job.vacancies) }}
</view>
</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>
</view>
</view>
<view class="card-companyName">{{ job.gwmc }}</view>
<view class="card-tags">
<view class="tag">
<dict-Label dictType="education" :value="job.education"></dict-Label>
</view>
<view class="tag">
<dict-Label dictType="experience" :value="job.experience"></dict-Label>
</view>
<view class="tag">
{{ vacanciesTo(job.vacancies) }}
</view>
</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>
<view class="date-jobTitle" v-else>
{{ job.title }}
</view>
</view>
<view class="date-jobTitle" v-else>
{{ job.title }}
</view>
</view>
</transition-group>
</template>
<script setup>
import { inject, computed, toRaw } from 'vue';
import { inject, computed, toRaw, ref, watch } from 'vue';
const { insertSortData, navTo, vacanciesTo } = inject('globalFunction');
import { useRecommedIndexedDBStore } from '@/stores/useRecommedIndexedDBStore.js';
const recommedIndexDb = useRecommedIndexedDBStore();
const dataSource = ref([]);
const props = defineProps({
list: {
type: Array,
@@ -71,6 +77,24 @@ const listData = computed(() => {
return props.list;
});
const processedIds = new Set();
watch(
() => props.list,
(newList) => {
if (!Array.isArray(newList)) return;
const newItems = newList.filter((item) => !processedIds.has(item.id));
if (newItems.length === 0) return;
newItems.forEach((item) => processedIds.add(item.id));
const delay = 50;
newItems.forEach((item, index) => {
setTimeout(() => {
dataSource.value.push(item);
}, index * delay);
});
},
{ immediate: true }
);
function nextDetail(job) {
// 记录岗位类型,用作数据分析
if (job.jobCategory) {

View File

@@ -1,48 +1,54 @@
<template>
<view v-for="job in listData" :key="job.id">
<view v-if="!job.isTitle" class="cards" @click="nextDetail(job)">
<view class="card-company">
<text class="company">{{ job.gwmc }}</text>
<view class="salary">
<Salary-Expectation :max-salary="job.maxSalary" :min-salary="job.minSalary"></Salary-Expectation>
<transition-group name="blur-fade-stagger" tag="view">
<view v-for="job in dataSource" :key="job.id" :style="{ '--i': 2 }">
<view v-if="!job.isTitle" class="cards" @click="nextDetail(job)">
<view class="card-company">
<text class="company">{{ job.gwmc }}</text>
<view class="salary">
<Salary-Expectation
:max-salary="job.maxSalary"
:min-salary="job.minSalary"
></Salary-Expectation>
</view>
</view>
</view>
<view class="card-companyName">{{ job.gsmc }}</view>
<view class="card-tags">
<view class="tag">
{{job.xlyq == '不限' ? '学历不限' : job.xlyq}}
<view class="card-companyName">{{ job.gsmc }}</view>
<view class="card-tags">
<view class="tag">
{{ job.xlyq == '不限' ? '学历不限' : job.xlyq }}
</view>
<view class="tag">
{{ job.gwgzjy == '不限' ? '经验不限' : job.gwgzjy }}
</view>
<view class="tag">
{{ vacanciesTo(job.zprs) }}
</view>
</view>
<view class="tag">
{{job.gwgzjy == '不限' ? '经验不限' : job.gwgzjy}}
</view>
<view class="tag">
{{ vacanciesTo(job.zprs) }}
</view>
</view>
<view class="card-bottom">
<view>{{ parseDateTime(job.createTime).date }}</view>
<view>
<!-- <convert-distance
<view class="card-bottom">
<view>{{ parseDateTime(job.createTime).date }}</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>
</view>
</view>
<view class="date-jobTitle" v-else>
{{ job.title }}
</view>
</view>
<view class="date-jobTitle" v-else>
{{ job.title }}
</view>
</view>
</transition-group>
</template>
<script setup>
import { inject, computed, toRaw } from 'vue';
import { inject, computed, toRaw, ref, watch } from 'vue';
const { insertSortData, navTo, vacanciesTo } = inject('globalFunction');
import { useRecommedIndexedDBStore } from '@/stores/useRecommedIndexedDBStore.js';
const recommedIndexDb = useRecommedIndexedDBStore();
const dataSource = ref([]);
const props = defineProps({
list: {
type: Array,
@@ -71,6 +77,24 @@ const listData = computed(() => {
return props.list;
});
const processedIds = new Set();
watch(
() => props.list,
(newList) => {
if (!Array.isArray(newList)) return;
const newItems = newList.filter((item) => !processedIds.has(item.id));
if (newItems.length === 0) return;
newItems.forEach((item) => processedIds.add(item.id));
const delay = 50;
newItems.forEach((item, index) => {
setTimeout(() => {
dataSource.value.push(item);
}, index * delay);
});
},
{ immediate: true }
);
function nextDetail(job) {
// 记录岗位类型,用作数据分析
if (job.jobCategory) {

View File

@@ -10,7 +10,7 @@ export default {
speechSynthesis: 'wss://qd.zhaopinzao8dian.com/api/speech-synthesis',
speechSynthesis2: 'wss://resource.zhuoson.com/synthesis/', //直接替换即可
// indexedDB
DBversion: 2,
DBversion: 3,
// 只使用本地缓寸的数据
OnlyUseCachedDB: false,
// 素质测评URL
@@ -84,5 +84,12 @@ export default {
mode: 'ECB', // default
iv: 'UISwD9fW6cFh9SNS', // default is null
cipherType: 'base64' // default is base64
}
},
animations: [ //动画
'fade-up-stagger',
'pop-in-stagger',
'slide-left-stagger',
'blur-fade-stagger',
'bounce-up-stagger'
]
}

View File

@@ -21,6 +21,7 @@ import { storeToRefs } from 'pinia';
import useLocationStore from '@/stores/useLocationStore';
const { longitudeVal, latitudeVal } = storeToRefs(useLocationStore());
const userStore = useUserStore();
const { isMiniProgram } = storeToRefs(useUserStore());
const state = reactive({});
const pageState = reactive({
page: 0,
@@ -37,6 +38,15 @@ onLoad(() => {
getJobList();
});
onMounted(() => {
// #ifdef H5
if (!isMiniProgram.value) {
const a = document.getElementsByClassName('uni-page-head-hd')[0];
a.style.display = 'none';
}
// #endif
});
onReachBottom(() => {
getJobList();
});

View File

@@ -1,6 +1,6 @@
<template>
<AppLayout title="" :use-scroll-view="false">
<template #headerleft>
<template #headerleft v-if="isMiniProgram">
<view class="btnback">
<image src="@/static/icon/back.png" @click="navBack"></image>
</view>
@@ -75,6 +75,8 @@ import { reactive, inject, watch, ref, onMounted, computed } from 'vue';
import { onLoad, onShow } from '@dcloudio/uni-app';
import dictLabel from '@/components/dict-Label/dict-Label.vue';
import { storeToRefs } from 'pinia';
const { isMiniProgram } = storeToRefs(useUserStore());
import useUserStore from '@/stores/useUserStore';
import useLocationStore from '@/stores/useLocationStore';
const { longitudeVal, latitudeVal } = storeToRefs(useLocationStore());
const { $api, navTo, vacanciesTo, navBack } = inject('globalFunction');
@@ -220,7 +222,8 @@ function handleJobsListResponse(type, rows, total, pageKey) {
const str = pageState.pageSize * (pageState[pageKey] - 1);
const end = pageState.list.length;
const reslist = rows;
pageState.list.splice(str, end, ...reslist);
pageState.list = [...pageState.list, ...rows];
// pageState.list.splice(str, end, ...reslist);
} else {
pageState.list = rows;
}

View File

@@ -1,6 +1,6 @@
<template>
<AppLayout title="添加岗位">
<template #headerleft>
<template #headerleft v-if="isMiniProgram">
<view class="btn">
<image src="@/static/icon/back.png" @click="navBack"></image>
</view>
@@ -74,7 +74,7 @@ const { $api, navBack } = inject('globalFunction');
import { storeToRefs } from 'pinia';
import useUserStore from '@/stores/useUserStore';
const { getUserResume } = useUserStore();
const { userInfo } = storeToRefs(useUserStore());
const { userInfo, isMiniProgram } = storeToRefs(useUserStore());
const popup = ref(null);
const selectJobsModel = ref(null);

View File

@@ -1,6 +1,6 @@
<template>
<AppLayout title="我的浏览" :show-bg-image="false" :use-scroll-view="false">
<template #headerleft>
<template #headerleft v-if="isMiniProgram">
<view class="btnback">
<image src="@/static/icon/back.png" @click="navBack"></image>
</view>
@@ -46,7 +46,7 @@ import { onLoad, onShow } from '@dcloudio/uni-app';
import useUserStore from '@/stores/useUserStore';
const { $api, navTo, navBack } = inject('globalFunction');
import useLocationStore from '@/stores/useLocationStore';
const { userInfo } = storeToRefs(useUserStore());
const { userInfo, isMiniProgram } = storeToRefs(useUserStore());
const { longitudeVal, latitudeVal } = storeToRefs(useLocationStore());
const userStore = useUserStore();
const browseDate = ref('');
@@ -123,6 +123,7 @@ function getJobList(type = 'add', loading = true) {
reslist.shift();
}
}
// pageState.list = [...pageState.list, ...rows];
pageState.list.splice(str, end, ...reslist);
pageState.lastDate = lastDate;
} else {

View File

@@ -1,6 +1,6 @@
<template>
<AppLayout title="精选企业">
<template #headerleft>
<template #headerleft v-if="isMiniProgram">
<view class="btn">
<image src="@/static/icon/back.png" @click="navBack"></image>
</view>
@@ -28,7 +28,7 @@ const { $api, navBack, navTo } = inject('globalFunction');
import { storeToRefs } from 'pinia';
import useUserStore from '@/stores/useUserStore';
const { getUserResume } = useUserStore();
const { userInfo } = storeToRefs(useUserStore());
const { userInfo, isMiniProgram } = storeToRefs(useUserStore());
const list = ref([]);
onLoad(() => {

View File

@@ -1,6 +1,6 @@
<template>
<AppLayout :title="title" :show-bg-image="false" @onScrollBottom="getDataList('add')">
<template #headerleft>
<template #headerleft v-if="isMiniProgram">
<view class="btnback">
<image src="@/static/icon/back.png" @click="navBack"></image>
</view>
@@ -39,6 +39,8 @@ import { storeToRefs } from 'pinia';
const { $api, navTo, navBack } = inject('globalFunction');
import useLocationStore from '@/stores/useLocationStore';
const { longitudeVal, latitudeVal } = storeToRefs(useLocationStore());
import useUserStore from '@/stores/useUserStore';
const { isMiniProgram } = storeToRefs(useUserStore());
// state
const title = ref('事业单位');
const cardInfo = ref({});

View File

@@ -1,6 +1,6 @@
<template>
<AppLayout title="我的收藏" :show-bg-image="false" :use-scroll-view="false">
<template #headerleft>
<template #headerleft v-if="isMiniProgram">
<view class="btn">
<image src="@/static/icon/back.png" @click="navBack"></image>
</view>
@@ -61,6 +61,8 @@ import { storeToRefs } from 'pinia';
import useLocationStore from '@/stores/useLocationStore';
const { longitudeVal, latitudeVal } = storeToRefs(useLocationStore());
const { $api, navBack } = inject('globalFunction');
import useUserStore from '@/stores/useUserStore';
const { isMiniProgram } = storeToRefs(useUserStore());
const type = ref(0);
const pageState = reactive({

View File

@@ -1,6 +1,6 @@
<template>
<AppLayout title="" :use-scroll-view="false">
<template #headerleft>
<template #headerleft v-if="isMiniProgram">
<view class="btnback">
<image src="@/static/icon/back.png" @click="navBack"></image>
</view>
@@ -83,7 +83,7 @@
:longitude="longitudeVal"
:latitude="latitudeVal"
></renderCompanysOutData>
<empty v-else is-position></empty>
<empty v-if="!pageState.list.length" is-position></empty>
</view>
</scroll-view>
</view>
@@ -110,6 +110,8 @@ import useLocationStore from '@/stores/useLocationStore';
const { $api, navTo, vacanciesTo, navBack } = inject('globalFunction');
import { storeToRefs } from 'pinia';
const { longitudeVal, latitudeVal } = storeToRefs(useLocationStore());
import useUserStore from '@/stores/useUserStore';
const { isMiniProgram } = storeToRefs(useUserStore());
const isExpanded = ref(false);
const fairInfo = ref({});
@@ -163,7 +165,8 @@ function getCompanyList(type = 'add') {
const str = pageState.pageSize * (pageState.current - 1);
const end = pageState.list.length;
const reslist = rows;
pageState.list.splice(str, end, ...reslist);
pageState.list = [...pageState.list, ...rows];
// pageState.list.splice(str, end, ...reslist);
} else {
pageState.list = rows;
}

View File

@@ -1,6 +1,6 @@
<template>
<AppLayout title="我的简历" title-color="#FFFFFF" back-gorund-color="#F4F4F4">
<template #headerleft>
<template #headerleft v-if="isMiniProgram">
<view class="btn">
<image src="@/static/icon/back-white.png" @click="navBack"></image>
</view>
@@ -137,7 +137,7 @@ import { onLoad, onShow } from '@dcloudio/uni-app';
import { storeToRefs } from 'pinia';
import useUserStore from '@/stores/useUserStore';
import useDictStore from '@/stores/useDictStore';
const { userInfo } = storeToRefs(useUserStore());
const { userInfo, isMiniProgram } = storeToRefs(useUserStore());
const { getUserResume } = useUserStore();
const { getDictData, oneDictData } = useDictStore();
import config from '@/config.js';

View File

@@ -1,6 +1,6 @@
<template>
<AppLayout title="" backGorundColor="#F4F4F4">
<template #headerleft>
<template #headerleft v-if="isMiniProgram">
<view class="btnback">
<image src="@/static/icon/back.png" @click="navBack"></image>
</view>
@@ -183,6 +183,9 @@ import { reactive, inject, watch, ref, onMounted, computed } from 'vue';
import { onLoad, onShow, onHide } from '@dcloudio/uni-app';
import dictLabel from '@/components/dict-Label/dict-Label.vue';
import RadarMap from './component/radarMap.vue';
import { storeToRefs } from 'pinia';
import useUserStore from '@/stores/useUserStore';
const { isMiniProgram } = storeToRefs(useUserStore());
const { $api, navTo, getLenPx, parseQueryParams, navBack, isEmptyObject } = inject('globalFunction');
import config from '@/config.js';

View File

@@ -60,7 +60,7 @@ import Countdown from './component/countdown.vue';
import { storeToRefs } from 'pinia';
import useLocationStore from '@/stores/useLocationStore';
import useUserStore from '@/stores/useUserStore';
const { userInfo } = storeToRefs(useUserStore());
const { userInfo, isMiniProgram } = storeToRefs(useUserStore());
const { longitudeVal, latitudeVal } = storeToRefs(useLocationStore());
const pageState = reactive({
@@ -92,6 +92,15 @@ onLoad(() => {
getList();
});
onMounted(() => {
// #ifdef H5
if (!isMiniProgram.value) {
const a = document.getElementsByClassName('uni-page-head-hd')[0];
a.style.display = 'none';
}
// #endif
});
function chnageRanOption(item) {
ranItem.value = item;
getList();

View File

@@ -1,7 +1,7 @@
<template>
<AppLayout title="选择日期" :use-scroll-view="false" back-gorund-color="#FAFAFA">
<template #headerleft>
<view class="btn">
<view class="btn" v-if="isMiniProgram">
<image src="@/static/icon/back.png" @click="navBack"></image>
</view>
</template>
@@ -51,6 +51,9 @@ const { $api, navTo, navBack } = inject('globalFunction');
const weekMap = ['日', '一', '二', '三', '四', '五', '六'];
const calendarData = ref([]);
const current = ref({});
import { storeToRefs } from 'pinia';
import useUserStore from '@/stores/useUserStore';
const { isMiniProgram } = storeToRefs(useUserStore());
import { Solar, Lunar } from '@/lib/lunar-javascript@1.7.2.js';
const isRecord = ref(false);

View File

@@ -1,6 +1,6 @@
<template>
<AppLayout title="电子名片" title-color="#FFFFFF" back-gorund-color="#F4F4F4">
<template #headerleft>
<template #headerleft v-if="isMiniProgram">
<view class="btn">
<image src="@/static/icon/back-white.png" @click="navBack"></image>
</view>
@@ -112,7 +112,7 @@ import { onLoad, onShow } from '@dcloudio/uni-app';
import { storeToRefs } from 'pinia';
import useUserStore from '@/stores/useUserStore';
import useDictStore from '@/stores/useDictStore';
const { userInfo } = storeToRefs(useUserStore());
const { userInfo, isMiniProgram } = storeToRefs(useUserStore());
const { getUserResume } = useUserStore();
const { getDictData, oneDictData } = useDictStore();
</script>

View File

@@ -1,245 +1,249 @@
<template>
<AppLayout title="工作经历" border back-gorund-color="#ffffff" :show-bg-image="false">
<template #headerleft>
<view class="btn mar_le20 button-click" @click="navBack">取消</view>
</template>
<template #headerright>
<view class="btn mar_ri20 button-click blue" @click="confirm">确认</view>
</template>
<view class="content">
<view class="content-input">
<view class="input-titile">公司</view>
<input class="input-con" v-model="fromValue.company" placeholder="请输入公司名称" />
</view>
<view class="content-input">
<view class="input-titile">岗位</view>
<input class="input-con" v-model="fromValue.position" placeholder="请输入岗位" />
</view>
<view class="content-input">
<view class="input-titile">时间</view>
<view class="flex-box">
<view class="input-box btn-feel" @click="changestartTime">
<input v-model="fromValue.startTime" class="input-con triangle" disabled placeholder="开始时间" />
<image class="icon" src="@/static/icon/arrow-down.png" />
</view>
<view class="gap">-</view>
<view class="input-box btn-feel" @click="changeendTime">
<input v-model="fromValue.endTime" class="input-con triangle" disabled placeholder="至今" />
<image class="icon" src="@/static/icon/arrow-down.png" />
</view>
<AppLayout title="工作经历" border back-gorund-color="#ffffff" :show-bg-image="false">
<template #headerleft>
<view class="btn mar_le20 button-click" @click="navBack">取消</view>
</template>
<template #headerright>
<view class="btn mar_ri20 button-click blue" @click="confirm">确认</view>
</template>
<view class="content">
<view class="content-input">
<view class="input-titile">公司</view>
<input class="input-con" v-model="fromValue.company" placeholder="请输入公司名称" />
</view>
<view class="content-input">
<view class="input-titile">岗位</view>
<input class="input-con" v-model="fromValue.position" placeholder="请输入岗位" />
</view>
<view class="content-input">
<view class="input-titile">时间</view>
<view class="flex-box">
<view class="input-box btn-feel" @click="changestartTime">
<input
v-model="fromValue.startTime"
class="input-con triangle"
disabled
placeholder="开始时间"
/>
<image class="icon" src="@/static/icon/arrow-down.png" />
</view>
<view class="gap">-</view>
<view class="input-box btn-feel" @click="changeendTime">
<input v-model="fromValue.endTime" class="input-con triangle" disabled placeholder="至今" />
<image class="icon" src="@/static/icon/arrow-down.png" />
</view>
</view>
</view>
<view class="content-input">
<view class="input-titile">工作内容</view>
<textarea class="text-area" placeholder="请输入工作内容" v-model="fromValue.duty"></textarea>
</view>
</view>
</view>
<view class="content-input">
<view class="input-titile">工作内容</view>
<textarea class="text-area" placeholder="请输入工作内容" v-model="fromValue.duty"></textarea>
</view>
</view>
<!-- 时间选择器组件 -->
<DatePicker ref="datePicker" />
<template #footer v-if="fromValue.id">
<view class="footer-container">
<view class="footer-button btn-feel" @click="delCurrent">删除该工作经历</view>
</view>
</template>
</AppLayout>
<!-- 时间选择器组件 -->
<DatePicker ref="datePicker" />
<template #footer v-if="fromValue.id">
<view class="footer-container">
<view class="footer-button btn-feel" @click="delCurrent">删除该工作经历</view>
</view>
</template>
</AppLayout>
</template>
<script setup>
import { reactive, inject, watch, ref, onMounted, computed } from "vue";
import { onLoad, onShow } from "@dcloudio/uni-app";
const { $api, navTo, navBack } = inject("globalFunction");
import { storeToRefs } from "pinia";
import useUserStore from "@/stores/useUserStore";
import useDictStore from "@/stores/useDictStore";
import DatePicker from "@/components/DatePicker/DatePicker.vue";
import { reactive, inject, watch, ref, onMounted, computed } from 'vue';
import { onLoad, onShow } from '@dcloudio/uni-app';
const { $api, navTo, navBack } = inject('globalFunction');
import { storeToRefs } from 'pinia';
import useUserStore from '@/stores/useUserStore';
import useDictStore from '@/stores/useDictStore';
import DatePicker from '@/components/DatePicker/DatePicker.vue';
const { userInfo } = storeToRefs(useUserStore());
const { getUserResume } = useUserStore();
const { dictLabel, oneDictData } = useDictStore();
// 初始化数据
const fromValue = reactive({
position: "",
company: "",
startTime: "",
endTime: "",
duty: "",
id: undefined,
position: '',
company: '',
startTime: '',
endTime: '',
duty: '',
id: undefined,
});
// 获取时间选择器组件的引用
const datePicker = ref();
onLoad((e) => {
initLoad(e?.id);
initLoad(e?.id);
});
const confirm = async () => {
// 验证必填字段
if (!fromValue.company) {
return $api.msg("请输入公司名称");
}
if (!fromValue.position) {
return $api.msg("请输入岗位");
}
if (!fromValue.startTime) {
return $api.msg("请选择开始时间");
}
// 验证时间逻辑:结束时间不能早于开始时间
if (fromValue.endTime && new Date(fromValue.endTime) < new Date(fromValue.startTime)) {
return $api.msg("结束时间不能早于开始时间");
}
let res;
try {
if (fromValue.id) {
res = await $api.createRequest("/app/user/experience/edit", fromValue, "post");
} else {
res = await $api.createRequest("/app/user/experience/save", fromValue, "post");
// 验证必填字段
if (!fromValue.company) {
return $api.msg('请输入公司名称');
}
if (!fromValue.position) {
return $api.msg('请输入岗位');
}
if (!fromValue.startTime) {
return $api.msg('请选择开始时间');
}
// 验证时间逻辑:结束时间不能早于开始时间
if (fromValue.endTime && new Date(fromValue.endTime) < new Date(fromValue.startTime)) {
return $api.msg('结束时间不能早于开始时间');
}
let res;
try {
if (fromValue.id) {
res = await $api.createRequest('/app/user/experience/edit', fromValue, 'post');
} else {
res = await $api.createRequest('/app/user/experience/save', fromValue, 'post');
}
$api.msg('保存成功');
getUserResume().then(() => {
navBack();
});
} catch (error) {
$api.msg('保存失败');
}
$api.msg("保存成功");
getUserResume().then(() => {
navBack();
});
} catch (error) {
$api.msg("保存失败");
}
};
function delCurrent() {
uni.showModal({
title: "提示",
content: "确认要删除此条工作经历吗?",
showCancel: true,
success: async ({ confirm, cancel }) => {
if (confirm) {
await $api.createRequest("/app/user/experience/delete", { id: fromValue.id }, "post");
$api.msg("删除成功");
getUserResume().then(() => {
navBack();
});
}
},
});
uni.showModal({
title: '提示',
content: '确认要删除此条工作经历吗?',
showCancel: true,
success: async ({ confirm, cancel }) => {
if (confirm) {
await $api.createRequest('/app/user/experience/delete', { id: fromValue.id }, 'post');
$api.msg('删除成功');
getUserResume().then(() => {
navBack();
});
}
},
});
}
function initLoad(id) {
if (!id) return;
$api
.createRequest(`/app/user/experience/getSingle/${id}`, {}, "get")
.then((res) => {
Object.assign(fromValue, res.data);
})
.catch((err) => {
console.error("获取工作经历失败:", err);
});
if (!id) return;
$api.createRequest(`/app/user/experience/getSingle/${id}`, {}, 'get')
.then((res) => {
Object.assign(fromValue, res.data);
})
.catch((err) => {
console.error('获取工作经历失败:', err);
});
}
// 选择开始时间
const changestartTime = () => {
console.log(1);
datePicker.value.open({
title: "选择开始时间",
defaultDate: fromValue.startTime,
success: (selectedDate) => {
fromValue.startTime = selectedDate;
},
});
console.log(1);
datePicker.value.open({
title: '选择开始时间',
defaultDate: fromValue.startTime,
success: (selectedDate) => {
fromValue.startTime = selectedDate;
},
});
};
// 选择结束时间
const changeendTime = () => {
datePicker.value.open({
title: "选择结束时间",
defaultDate: fromValue.endTime,
success: (selectedDate) => {
fromValue.endTime = selectedDate;
// 如果结束时间早于新的开始时间,清空结束时间
if (fromValue.startTime && new Date(fromValue.startTime) > new Date(selectedDate)) {
fromValue.endTime = "";
$api.msg("结束时间不能小于开始时间!");
}
},
});
datePicker.value.open({
title: '选择结束时间',
defaultDate: fromValue.endTime,
success: (selectedDate) => {
fromValue.endTime = selectedDate;
// 如果结束时间早于新的开始时间,清空结束时间
if (fromValue.startTime && new Date(fromValue.startTime) > new Date(selectedDate)) {
fromValue.endTime = '';
$api.msg('结束时间不能小于开始时间!');
}
},
});
};
</script>
<style lang="scss" scoped>
.btn.blue {
color: #1677ff;
color: #1677ff;
}
.content {
padding: 28rpx;
display: flex;
flex-direction: column;
justify-content: flex-start;
height: calc(100% - 120rpx);
padding: 28rpx;
display: flex;
flex-direction: column;
justify-content: flex-start;
height: calc(100% - 120rpx);
}
.flex-box {
display: flex;
align-items: center;
.gap {
font-size: 40rpx;
font-weight: bold;
flex: 0.25;
text-align: center;
}
.icon {
width: 75rpx;
height: 50rpx;
}
.input-box {
flex: 0.375;
display: flex;
align-items: center;
}
.gap {
font-size: 40rpx;
font-weight: bold;
flex: 0.25;
text-align: center;
}
.icon {
width: 75rpx;
height: 50rpx;
}
.input-box {
flex: 0.375;
display: flex;
align-items: center;
}
}
.content-input {
margin-bottom: 48rpx;
padding-bottom: 20rpx;
border-bottom: 2rpx solid #ebebeb;
&:nth-last-of-type(1) {
border-bottom: none;
}
.input-titile {
font-weight: 400;
font-size: 28rpx;
color: #6a6a6a;
margin-bottom: 10rpx;
}
.input-con {
font-weight: 400;
font-size: 32rpx;
color: #333333;
line-height: 80rpx;
height: 80rpx;
position: relative;
}
.triangle {
pointer-events: none;
}
.text-area {
width: 100%;
height: 700rpx;
background: #f5f5f5;
padding: 20rpx;
box-sizing: border-box;
}
margin-bottom: 48rpx;
padding-bottom: 20rpx;
border-bottom: 2rpx solid #ebebeb;
&:nth-last-of-type(1) {
border-bottom: none;
}
.input-titile {
font-weight: 400;
font-size: 28rpx;
color: #6a6a6a;
margin-bottom: 10rpx;
}
.input-con {
font-weight: 400;
font-size: 32rpx;
color: #333333;
line-height: 80rpx;
height: 80rpx;
position: relative;
}
.triangle {
pointer-events: none;
}
.text-area {
width: 100%;
height: 700rpx;
background: #f5f5f5;
padding: 20rpx;
box-sizing: border-box;
}
}
.footer-container {
background: #ffffff;
box-shadow: 0rpx -4rpx 24rpx 0rpx rgba(11, 44, 112, 0.12);
border-radius: 0rpx 0rpx 0rpx 0rpx;
padding: 40rpx 28rpx 20rpx 28rpx;
.footer-button {
width: 100%;
height: 90rpx;
background: #f93a4a;
border-radius: 8rpx;
color: #ffffff;
line-height: 90rpx;
text-align: center;
}
background: #ffffff;
box-shadow: 0rpx -4rpx 24rpx 0rpx rgba(11, 44, 112, 0.12);
border-radius: 0rpx 0rpx 0rpx 0rpx;
padding: 40rpx 28rpx 20rpx 28rpx;
.footer-button {
width: 100%;
height: 90rpx;
background: #f93a4a;
border-radius: 8rpx;
color: #ffffff;
line-height: 90rpx;
text-align: center;
}
}
</style>

View File

@@ -45,54 +45,57 @@
<view class="container-main">
<scroll-view scroll-y class="main-scroll" @scrolltolower="handleScrollToLower">
<view class="cards">
<view
class="card press-button"
v-for="(item, index) in fairList"
:key="index"
@click="
navTo(
'/packageA/pages/exhibitors/exhibitors?jobFairId=' +
item.zphID +
'&jobFairName=' +
item.zphmc
)
"
>
<view class="card-title">{{ item.zphmc }}</view>
<view class="card-row">
<text class="">{{ item.jbf }}</text>
<text class="">
<!-- <convert-distance
<transition-group name="stagger" tag="view" :css="true">
<view
class="card press-button"
v-for="(item, index) in fairList"
:key="item.zphID"
:style="{ '--i': index }"
@click="
navTo(
'/packageA/pages/exhibitors/exhibitors?jobFairId=' +
item.zphID +
'&jobFairName=' +
item.zphmc
)
"
>
<view class="card-title">{{ item.zphmc }}</view>
<view class="card-row">
<text class="">{{ item.jbf }}</text>
<text class="">
<!-- <convert-distance
:alat="item.latitude"
:along="item.longitude"
:blat="latitudeVal"
:blong="longitudeVal"
></convert-distance> -->
</text>
</view>
<view class="card-times">
<view class="time-left">
<view class="left-date">{{ parseDateTime(item.zphjbsj).time }}</view>
<view class="left-dateDay">{{ parseDateTime(item.zphjbsj).date }}</view>
</text>
</view>
<view class="line"></view>
<view class="time-center">
<view class="center-date">
{{ getTimeStatus(item.zphjbsj, item.zphjzsj).statusText }}
<view class="card-times">
<view class="time-left">
<view class="left-date">{{ parseDateTime(item.zphjbsj).time }}</view>
<view class="left-dateDay">{{ parseDateTime(item.zphjbsj).date }}</view>
</view>
<view class="center-dateDay">
{{ getHoursBetween(item.zphjbsj, item.zphjzsj) }}小时
<view class="line"></view>
<view class="time-center">
<view class="center-date">
{{ getTimeStatus(item.zphjbsj, item.zphjzsj).statusText }}
</view>
<view class="center-dateDay">
{{ getHoursBetween(item.zphjbsj, item.zphjzsj) }}小时
</view>
</view>
<view class="line"></view>
<view class="time-right">
<view class="left-date">{{ parseDateTime(item.zphjzsj).time }}</view>
<view class="left-dateDay">{{ parseDateTime(item.zphjzsj).date }}</view>
</view>
</view>
<view class="line"></view>
<view class="time-right">
<view class="left-date">{{ parseDateTime(item.zphjzsj).time }}</view>
<view class="left-dateDay">{{ parseDateTime(item.zphjzsj).date }}</view>
</view>
<view class="recommend-card-line"></view>
<view class="card-footer">内容简介{{ item.zphjj }}</view>
</view>
<view class="recommend-card-line"></view>
<view class="card-footer">内容简介{{ item.zphjj }}</view>
</view>
</transition-group>
</view>
<empty v-if="!fairList.length" content="暂时没有结果,下一天也许就有惊喜"></empty>
</scroll-view>

View File

@@ -49,7 +49,7 @@
</view>
</view>
</view>
<view class="tip" @click="navTo('/packageA/pages/myResume/myResume')">
<view class="tip button-click" @click="navTo('/packageA/pages/myResume/myResume')">
<image class="icon" src="@/static/icon/leart-gold.png" />
<view class="text">使用人工智能需要先完成素质测评完善简历 ></view>
</view>

View File

@@ -91,7 +91,9 @@ onLoad(() => {
uni.preloadPage({ url: '/pages/nearby/nearby' });
uni.preloadPage({ url: '/pages/chat/chat' });
uni.preloadPage({ url: '/packageA/pages/choiceness/choiceness' });
}, 3000);
uni.preloadPage({ url: '/packageA/pages/reservation/reservation' });
uni.preloadPage({ url: '/packageA/pages/Intendedposition/Intendedposition' });
}, 1000);
});
onShow(() => {

View File

@@ -1,6 +1,6 @@
<template>
<AppLayout title="附近" :use-scroll-view="false" :show-bg-image="false">
<template #headerleft>
<template #headerleft v-if="isMiniProgram">
<view class="btnback">
<image src="@/static/icon/back.png" @click="navBack"></image>
</view>
@@ -50,6 +50,9 @@ import threeComponent from './components/three.vue';
import fourComponent from './components/four.vue';
import { reactive, inject, watch, ref, onMounted } from 'vue';
import { onLoad, onShow } from '@dcloudio/uni-app';
import { storeToRefs } from 'pinia';
import useUserStore from '@/stores/useUserStore';
const { isMiniProgram } = storeToRefs(useUserStore());
const { $api, debounce, throttle, navBack } = inject('globalFunction');
const loadedMap = reactive([false, false, false, false]);
const swiperRefs = [ref(null), ref(null), ref(null), ref(null)];

View File

@@ -58,6 +58,7 @@ const useUserStore = defineStore("user", () => {
const Completion = ref('0%')
const seesionId = ref('')
const counts = ref({})
const isMiniProgram = ref(false)
const login = (value) => {
hasLogin.value = true;
@@ -139,6 +140,11 @@ const useUserStore = defineStore("user", () => {
});
}
function changMiniProgramAppStatus(val) {
// 是否是小程序内
isMiniProgram.value = val
}
// 导入
return {
@@ -154,7 +160,9 @@ const useUserStore = defineStore("user", () => {
seesionId,
Completion,
getUserstatistics,
counts
counts,
isMiniProgram,
changMiniProgramAppStatus
}
}, {
unistorage: true,