flat: 视频版本0.1
This commit is contained in:
8
App.vue
8
App.vue
@@ -7,12 +7,9 @@ const { $api, navTo, appendScriptTagElement } = inject('globalFunction');
|
|||||||
|
|
||||||
onLaunch((options) => {
|
onLaunch((options) => {
|
||||||
useDictStore().getDictData();
|
useDictStore().getDictData();
|
||||||
// uni.onTabBarMidButtonTap(() => {
|
// uni.hideTabBar();
|
||||||
// uni.navigateTo({
|
|
||||||
// url: '/pages/chat/chat',
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
|
|
||||||
|
// 登录
|
||||||
let token = uni.getStorageSync('token') || ''; // 同步获取 缓存信息
|
let token = uni.getStorageSync('token') || ''; // 同步获取 缓存信息
|
||||||
if (token) {
|
if (token) {
|
||||||
useUserStore()
|
useUserStore()
|
||||||
@@ -52,6 +49,7 @@ onHide(() => {
|
|||||||
|
|
||||||
<style>
|
<style>
|
||||||
/*每个页面公共css */
|
/*每个页面公共css */
|
||||||
|
@import '@/common/animation.css';
|
||||||
@import '@/common/common.css';
|
@import '@/common/common.css';
|
||||||
/* 修改pages tabbar样式 H5有效 */
|
/* 修改pages tabbar样式 H5有效 */
|
||||||
.uni-tabbar .uni-tabbar__item:nth-child(4) .uni-tabbar__bd .uni-tabbar__icon {
|
.uni-tabbar .uni-tabbar__item:nth-child(4) .uni-tabbar__bd .uni-tabbar__icon {
|
||||||
|
193
common/animation.css
Normal file
193
common/animation.css
Normal file
@@ -0,0 +1,193 @@
|
|||||||
|
/*base code*/
|
||||||
|
.animated {
|
||||||
|
-webkit-animation-duration: 1s;
|
||||||
|
animation-duration: 1s;
|
||||||
|
-webkit-animation-fill-mode: both;
|
||||||
|
animation-fill-mode: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
.animated.infinite {
|
||||||
|
-webkit-animation-iteration-count: infinite;
|
||||||
|
animation-iteration-count: infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.animated.hinge {
|
||||||
|
-webkit-animation-duration: 2s;
|
||||||
|
animation-duration: 2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*the animation definition*/
|
||||||
|
@-webkit-keyframes tada {
|
||||||
|
0% {
|
||||||
|
-webkit-transform: scale3d(1, 1, 1);
|
||||||
|
transform: scale3d(1, 1, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
10%,
|
||||||
|
20% {
|
||||||
|
-webkit-transform: scale3d(.9, .9, .9) rotate3d(0, 0, 1, -3deg);
|
||||||
|
transform: scale3d(.9, .9, .9) rotate3d(0, 0, 1, -3deg)
|
||||||
|
}
|
||||||
|
|
||||||
|
30%,
|
||||||
|
50%,
|
||||||
|
70%,
|
||||||
|
90% {
|
||||||
|
-webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);
|
||||||
|
transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg)
|
||||||
|
}
|
||||||
|
|
||||||
|
40%,
|
||||||
|
60%,
|
||||||
|
80% {
|
||||||
|
-webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);
|
||||||
|
transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg)
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
-webkit-transform: scale3d(1, 1, 1);
|
||||||
|
transform: scale3d(1, 1, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes tada {
|
||||||
|
0% {
|
||||||
|
-webkit-transform: scale3d(1, 1, 1);
|
||||||
|
-ms-transform: scale3d(1, 1, 1);
|
||||||
|
transform: scale3d(1, 1, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
10%,
|
||||||
|
20% {
|
||||||
|
-webkit-transform: scale3d(.9, .9, .9) rotate3d(0, 0, 1, -3deg);
|
||||||
|
-ms-transform: scale3d(.9, .9, .9) rotate3d(0, 0, 1, -3deg);
|
||||||
|
transform: scale3d(.9, .9, .9) rotate3d(0, 0, 1, -3deg)
|
||||||
|
}
|
||||||
|
|
||||||
|
30%,
|
||||||
|
50%,
|
||||||
|
70%,
|
||||||
|
90% {
|
||||||
|
-webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);
|
||||||
|
-ms-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);
|
||||||
|
transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg)
|
||||||
|
}
|
||||||
|
|
||||||
|
40%,
|
||||||
|
60%,
|
||||||
|
80% {
|
||||||
|
-webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);
|
||||||
|
-ms-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);
|
||||||
|
transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg)
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
-webkit-transform: scale3d(1, 1, 1);
|
||||||
|
-ms-transform: scale3d(1, 1, 1);
|
||||||
|
transform: scale3d(1, 1, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tada {
|
||||||
|
-webkit-animation-name: tada;
|
||||||
|
animation-name: tada
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.btn-tada:active {
|
||||||
|
-webkit-animation-name: tada;
|
||||||
|
animation-name: tada
|
||||||
|
}
|
||||||
|
|
||||||
|
/*the animation definition*/
|
||||||
|
@-webkit-keyframes rubberBand {
|
||||||
|
0% {
|
||||||
|
-webkit-transform: scale3d(1, 1, 1);
|
||||||
|
transform: scale3d(1, 1, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
30% {
|
||||||
|
-webkit-transform: scale3d(1.25, .75, 1);
|
||||||
|
transform: scale3d(1.25, .75, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
40% {
|
||||||
|
-webkit-transform: scale3d(0.75, 1.25, 1);
|
||||||
|
transform: scale3d(0.75, 1.25, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
-webkit-transform: scale3d(1.15, .85, 1);
|
||||||
|
transform: scale3d(1.15, .85, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
65% {
|
||||||
|
-webkit-transform: scale3d(.95, 1.05, 1);
|
||||||
|
transform: scale3d(.95, 1.05, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
75% {
|
||||||
|
-webkit-transform: scale3d(1.05, .95, 1);
|
||||||
|
transform: scale3d(1.05, .95, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
-webkit-transform: scale3d(1, 1, 1);
|
||||||
|
transform: scale3d(1, 1, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes rubberBand {
|
||||||
|
0% {
|
||||||
|
-webkit-transform: scale3d(1, 1, 1);
|
||||||
|
-ms-transform: scale3d(1, 1, 1);
|
||||||
|
transform: scale3d(1, 1, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
30% {
|
||||||
|
-webkit-transform: scale3d(1.25, .75, 1);
|
||||||
|
-ms-transform: scale3d(1.25, .75, 1);
|
||||||
|
transform: scale3d(1.25, .75, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
40% {
|
||||||
|
-webkit-transform: scale3d(0.75, 1.25, 1);
|
||||||
|
-ms-transform: scale3d(0.75, 1.25, 1);
|
||||||
|
transform: scale3d(0.75, 1.25, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
-webkit-transform: scale3d(1.15, .85, 1);
|
||||||
|
-ms-transform: scale3d(1.15, .85, 1);
|
||||||
|
transform: scale3d(1.15, .85, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
65% {
|
||||||
|
-webkit-transform: scale3d(.95, 1.05, 1);
|
||||||
|
-ms-transform: scale3d(.95, 1.05, 1);
|
||||||
|
transform: scale3d(.95, 1.05, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
75% {
|
||||||
|
-webkit-transform: scale3d(1.05, .95, 1);
|
||||||
|
-ms-transform: scale3d(1.05, .95, 1);
|
||||||
|
transform: scale3d(1.05, .95, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
-webkit-transform: scale3d(1, 1, 1);
|
||||||
|
-ms-transform: scale3d(1, 1, 1);
|
||||||
|
transform: scale3d(1, 1, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.rubberBand {
|
||||||
|
-webkit-animation-name: rubberBand;
|
||||||
|
animation-name: rubberBand
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.btn-rubberBand:active {
|
||||||
|
-webkit-animation-name: tada;
|
||||||
|
animation-name: tada
|
||||||
|
}
|
@@ -56,6 +56,7 @@ html {
|
|||||||
background-color: rgba(189, 197, 254, 0.15);
|
background-color: rgba(189, 197, 254, 0.15);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.btn-incline {
|
.btn-incline {
|
||||||
transition: transform 0.2s ease;
|
transition: transform 0.2s ease;
|
||||||
transform-style: preserve-3d;
|
transform-style: preserve-3d;
|
||||||
@@ -74,6 +75,23 @@ html {
|
|||||||
transform: perspective(600px) rotateX(6deg) scale(0.98);
|
transform: perspective(600px) rotateX(6deg) scale(0.98);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.press-button {
|
||||||
|
padding: 10px 20px;
|
||||||
|
background: #3A4750;
|
||||||
|
/* 深灰蓝 */
|
||||||
|
color: #ffffff;
|
||||||
|
font-size: 16px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 6px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: transform 0.1s ease, box-shadow 0.1s ease;
|
||||||
|
/* box-shadow: 0 4px 0 #2C3E50; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.press-button:active {
|
||||||
|
transform: scale(0.95) translateY(2px);
|
||||||
|
/* box-shadow: 0 2px 0 #1C2833; */
|
||||||
|
}
|
||||||
|
|
||||||
/* 动画效果 */
|
/* 动画效果 */
|
||||||
.btn-shaky:active {
|
.btn-shaky:active {
|
||||||
|
312
components/TikTok/TikTok.vue
Normal file
312
components/TikTok/TikTok.vue
Normal file
@@ -0,0 +1,312 @@
|
|||||||
|
<template>
|
||||||
|
<swiper
|
||||||
|
class="m-tiktok-video-swiper"
|
||||||
|
circular
|
||||||
|
@change="swiperChange"
|
||||||
|
:current="state.current"
|
||||||
|
:vertical="true"
|
||||||
|
duration="300"
|
||||||
|
>
|
||||||
|
<swiper-item v-for="(item, index) in state.displaySwiperList" :key="index">
|
||||||
|
<view class="swiper-item" @click="(e) => handleClick(index, e)">
|
||||||
|
<video
|
||||||
|
:id="`video__${index}`"
|
||||||
|
:controls="controls"
|
||||||
|
:autoplay="false"
|
||||||
|
:loop="loop"
|
||||||
|
@ended="ended"
|
||||||
|
@controlstoggle="controlstoggle"
|
||||||
|
@play="onPlay"
|
||||||
|
@error="emits('error')"
|
||||||
|
class="m-tiktok-video-player"
|
||||||
|
:src="item.src || item.explainUrl"
|
||||||
|
v-if="index === 0 || !state.isFirstLoad"
|
||||||
|
></video>
|
||||||
|
<view class="cover-triangle" v-if="pause"></view>
|
||||||
|
<image
|
||||||
|
v-if="item.poster && state.displayIndex != index"
|
||||||
|
:src="item.poster"
|
||||||
|
class="m-tiktok-video-poster"
|
||||||
|
mode="aspectFit"
|
||||||
|
></image>
|
||||||
|
<slot :item="item"></slot>
|
||||||
|
</view>
|
||||||
|
</swiper-item>
|
||||||
|
</swiper>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, reactive, getCurrentInstance, watch, nextTick } from 'vue';
|
||||||
|
import { onLoad, onUnload } from '@dcloudio/uni-app';
|
||||||
|
const _this = getCurrentInstance();
|
||||||
|
const emits = defineEmits(['play', 'error', 'loadMore', 'change', 'controlstoggle', 'click', 'ended']);
|
||||||
|
|
||||||
|
const lastTapTime = ref(0);
|
||||||
|
const pause = ref(false);
|
||||||
|
const props = defineProps({
|
||||||
|
/**
|
||||||
|
* 视频列表
|
||||||
|
*/
|
||||||
|
videoList: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 是否循环播放一个视频
|
||||||
|
*/
|
||||||
|
loop: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 显示原生控制栏
|
||||||
|
*/
|
||||||
|
controls: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 是否自动播放
|
||||||
|
*/
|
||||||
|
autoplay: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 是否自动滚动播放
|
||||||
|
*/
|
||||||
|
autoChange: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 滚动加载阈值(即播放到剩余多少个之后触发加载更多
|
||||||
|
*/
|
||||||
|
loadMoreOffsetCount: {
|
||||||
|
type: Number,
|
||||||
|
default: 2,
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 暂停 1 单机暂停; 2 双击暂停; 0关闭
|
||||||
|
*/
|
||||||
|
pauseType: {
|
||||||
|
type: Number,
|
||||||
|
default: 2,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const state = reactive({
|
||||||
|
originList: [], // 源数据
|
||||||
|
displaySwiperList: [], // swiper需要的数据
|
||||||
|
displayIndex: 0, // 用于显示swiper的真正的下标数值只有:0,1,2。
|
||||||
|
originIndex: 0, // 记录源数据的下标
|
||||||
|
current: 0,
|
||||||
|
oid: 0,
|
||||||
|
showControls: '',
|
||||||
|
toggleShow: true, // 显示面板
|
||||||
|
videoContexts: [],
|
||||||
|
isFirstLoad: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const initVideoContexts = () => {
|
||||||
|
state.videoContexts = [
|
||||||
|
uni.createVideoContext('video__0', _this),
|
||||||
|
uni.createVideoContext('video__1', _this),
|
||||||
|
uni.createVideoContext('video__2', _this),
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
const onPlay = (e) => {
|
||||||
|
emits('play', e);
|
||||||
|
};
|
||||||
|
|
||||||
|
const setVideoRef = (el, index) => {
|
||||||
|
if (el) {
|
||||||
|
videoRefs.value[index] = el;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function handleClick(index, e) {
|
||||||
|
const now = Date.now();
|
||||||
|
switch (props.pauseType) {
|
||||||
|
case 1:
|
||||||
|
if (pause.value) {
|
||||||
|
state.videoContexts[index].play();
|
||||||
|
pause.value = false;
|
||||||
|
} else {
|
||||||
|
state.videoContexts[index].pause();
|
||||||
|
pause.value = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if (now - lastTapTime.value < 300) {
|
||||||
|
if (pause.value) {
|
||||||
|
state.videoContexts[index].play();
|
||||||
|
pause.value = false;
|
||||||
|
} else {
|
||||||
|
state.videoContexts[index].pause();
|
||||||
|
pause.value = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
lastTapTime.value = now;
|
||||||
|
state.toggleShow = !state.toggleShow;
|
||||||
|
emits('click', e);
|
||||||
|
}
|
||||||
|
function ended() {
|
||||||
|
// 自动切换下一个视频
|
||||||
|
if (props.autoChange) {
|
||||||
|
if (state.displayIndex < 2) {
|
||||||
|
state.current = state.displayIndex + 1;
|
||||||
|
} else {
|
||||||
|
state.current = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
emits('ended');
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 初始一个显示的swiper数据
|
||||||
|
* @originIndex 从源数据的哪个开始显示默认0,如从其他页面跳转进来,要显示第n个,这个参数就是他的下标
|
||||||
|
*/
|
||||||
|
function initSwiperData(originIndex = state.originIndex) {
|
||||||
|
const originListLength = state.originList.length; // 源数据长度
|
||||||
|
const displayList = [];
|
||||||
|
displayList[state.displayIndex] = state.originList[originIndex];
|
||||||
|
displayList[state.displayIndex - 1 == -1 ? 2 : state.displayIndex - 1] =
|
||||||
|
state.originList[originIndex - 1 == -1 ? originListLength - 1 : originIndex - 1];
|
||||||
|
displayList[state.displayIndex + 1 == 3 ? 0 : state.displayIndex + 1] =
|
||||||
|
state.originList[originIndex + 1 == originListLength ? 0 : originIndex + 1];
|
||||||
|
state.displaySwiperList = displayList;
|
||||||
|
|
||||||
|
if (state.oid >= state.originList.length) {
|
||||||
|
state.oid = 0;
|
||||||
|
}
|
||||||
|
if (state.oid < 0) {
|
||||||
|
state.oid = state.originList.length - 1;
|
||||||
|
}
|
||||||
|
// 暂停所有视频
|
||||||
|
state.videoContexts.map((item) => item?.stop());
|
||||||
|
setTimeout(() => {
|
||||||
|
// 当前视频
|
||||||
|
if (props.autoplay) {
|
||||||
|
uni.createVideoContext(`video__${state.displayIndex}`, _this).play();
|
||||||
|
}
|
||||||
|
}, 500);
|
||||||
|
// 数据改变
|
||||||
|
emits('change', {
|
||||||
|
index: originIndex,
|
||||||
|
detail: state.originList[originIndex],
|
||||||
|
});
|
||||||
|
// 加载更多
|
||||||
|
var pCount = state.originList.length - props.loadMoreOffsetCount;
|
||||||
|
if (originIndex == pCount) {
|
||||||
|
emits('loadMore');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* swiper滑动时候
|
||||||
|
*/
|
||||||
|
function swiperChange(event) {
|
||||||
|
const { current } = event.detail;
|
||||||
|
state.isFirstLoad = false;
|
||||||
|
const originListLength = state.originList.length; // 源数据长度
|
||||||
|
// 向后滚动
|
||||||
|
if (state.displayIndex - current == 2 || state.displayIndex - current == -1) {
|
||||||
|
state.originIndex = state.originIndex + 1 == originListLength ? 0 : state.originIndex + 1;
|
||||||
|
state.displayIndex = state.displayIndex + 1 == 3 ? 0 : state.displayIndex + 1;
|
||||||
|
state.oid = state.originIndex - 1;
|
||||||
|
initSwiperData(state.originIndex);
|
||||||
|
}
|
||||||
|
// 如果两者的差为-2或者1则是向前滑动
|
||||||
|
else if (state.displayIndex - current == -2 || state.displayIndex - current == 1) {
|
||||||
|
state.originIndex = state.originIndex - 1 == -1 ? originListLength - 1 : state.originIndex - 1;
|
||||||
|
state.displayIndex = state.displayIndex - 1 == -1 ? 2 : state.displayIndex - 1;
|
||||||
|
state.oid = state.originIndex + 1;
|
||||||
|
initSwiperData(state.originIndex);
|
||||||
|
}
|
||||||
|
state.toggleShow = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function controlstoggle(e) {
|
||||||
|
state.showControls = e.detail.show;
|
||||||
|
emits('controlstoggle', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.videoList,
|
||||||
|
() => {
|
||||||
|
if (props.videoList?.length) {
|
||||||
|
state.originList = props.videoList;
|
||||||
|
if (state.isFirstLoad || !state.videoContexts?.length) {
|
||||||
|
initSwiperData();
|
||||||
|
initVideoContexts();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
let loadTimer = null;
|
||||||
|
onLoad(() => {
|
||||||
|
// 为了首次只加载一条视频(提高首次加载性能),延迟加载后续视频
|
||||||
|
loadTimer = setTimeout(() => {
|
||||||
|
state.isFirstLoad = false;
|
||||||
|
clearTimeout(loadTimer);
|
||||||
|
}, 5000);
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnload(() => {
|
||||||
|
clearTimeout(loadTimer);
|
||||||
|
});
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
initSwiperData,
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="stylus" scoped>
|
||||||
|
.m-tiktok-video-swiper,
|
||||||
|
.m-tiktok-video-player {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: #000;
|
||||||
|
}
|
||||||
|
.m-tiktok-video-swiper {
|
||||||
|
.swiper-item {
|
||||||
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.m-tiktok-video-poster {
|
||||||
|
background-color: #000;
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cover-triangle{
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
transform: translate(-50%, -50%)
|
||||||
|
width: 132rpx
|
||||||
|
height: 132rpx
|
||||||
|
border-radius: 50%;
|
||||||
|
background: rgba(0,0,0,0.3)
|
||||||
|
}
|
||||||
|
.cover-triangle::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-40%, -50%) rotate(90deg);
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
border-left: 40rpx solid transparent;
|
||||||
|
border-right: 40rpx solid transparent;
|
||||||
|
border-bottom: 60rpx solid #fff;
|
||||||
|
}
|
||||||
|
</style>
|
@@ -6,6 +6,7 @@
|
|||||||
background-color="#FFFFFF"
|
background-color="#FFFFFF"
|
||||||
@maskClick="maskClickFn"
|
@maskClick="maskClickFn"
|
||||||
:mask-click="maskClick"
|
:mask-click="maskClick"
|
||||||
|
class="popup-fix"
|
||||||
>
|
>
|
||||||
<view class="popup-content">
|
<view class="popup-content">
|
||||||
<view class="popup-header">
|
<view class="popup-header">
|
||||||
@@ -183,6 +184,15 @@ defineExpose({
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
.popup-fix {
|
||||||
|
position: fixed !important;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
top: 0;
|
||||||
|
height: 100vh;
|
||||||
|
z-index: 9999;
|
||||||
|
}
|
||||||
.popup-content {
|
.popup-content {
|
||||||
color: #000000;
|
color: #000000;
|
||||||
height: 80vh;
|
height: 80vh;
|
||||||
@@ -353,7 +363,6 @@ defineExpose({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.checkedstyle {
|
.checkedstyle {
|
||||||
|
|
||||||
height: 76rpx;
|
height: 76rpx;
|
||||||
background: rgba(37, 107, 250, 0.06);
|
background: rgba(37, 107, 250, 0.06);
|
||||||
border-radius: 12rpx 12rpx 12rpx 12rpx;
|
border-radius: 12rpx 12rpx 12rpx 12rpx;
|
||||||
|
@@ -1,7 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="tabbar_container">
|
<view class="tabbar_container">
|
||||||
<view class="tabbar_item" v-for="(item, index) in tabbarList" :key="index" @click="changeItem(item)">
|
<view class="tabbar_item" v-for="(item, index) in tabbarList" :key="index" @click="changeItem(item)">
|
||||||
<view class="item-top" :class="[item.centerItem ? 'center-item-img' : '']">
|
<view
|
||||||
|
class="item-top"
|
||||||
|
:class="[
|
||||||
|
item.centerItem ? 'center-item-img ' : '',
|
||||||
|
item.centerItem && currentItem === item.id ? 'rubberBand animated' : '',
|
||||||
|
]"
|
||||||
|
>
|
||||||
<image :src="currentItem == item.id ? item.selectedIconPath : item.iconPath"></image>
|
<image :src="currentItem == item.id ? item.selectedIconPath : item.iconPath"></image>
|
||||||
</view>
|
</view>
|
||||||
<view class="item-bottom" :class="[currentItem == item.id ? 'item-active' : '']">
|
<view class="item-bottom" :class="[currentItem == item.id ? 'item-active' : '']">
|
||||||
@@ -37,8 +43,8 @@ export default {
|
|||||||
id: 2,
|
id: 2,
|
||||||
text: '',
|
text: '',
|
||||||
path: '/pages/chat/chat',
|
path: '/pages/chat/chat',
|
||||||
iconPath: '../../static/tabbar/logo2copy.png',
|
iconPath: '../../static/tabbar/logo3.png',
|
||||||
selectedIconPath: '../../static/tabbar/logo2copy.png',
|
selectedIconPath: '../../static/tabbar/logo3.png',
|
||||||
centerItem: true,
|
centerItem: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -84,17 +90,18 @@ export default {
|
|||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.tabbar_container {
|
.tabbar_container {
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
position: fixed;
|
|
||||||
bottom: 0rpx;
|
|
||||||
left: 0rpx;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 126rpx;
|
height: 88rpx;
|
||||||
// box-shadow: 0 0 5px #999;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 5rpx 0;
|
padding: 5rpx 0;
|
||||||
padding-bottom: env(safe-area-inset-bottom);
|
overflow: hidden;
|
||||||
z-index: 998;
|
// position: fixed;
|
||||||
|
// bottom: 0rpx;
|
||||||
|
// left: 0rpx;
|
||||||
|
// box-shadow: 0 0 5px #999;
|
||||||
|
// padding-bottom: env(safe-area-inset-bottom);
|
||||||
|
// z-index: 998;
|
||||||
.tabbar_item {
|
.tabbar_item {
|
||||||
width: 33.33%;
|
width: 33.33%;
|
||||||
height: 100rpx;
|
height: 100rpx;
|
||||||
@@ -120,12 +127,12 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.center-item-img {
|
.center-item-img {
|
||||||
position: absolute;
|
// position: absolute;
|
||||||
top: 0rpx;
|
// top: 0rpx;
|
||||||
left: 50%;
|
// left: 50%;
|
||||||
transform: translate(-50%, 0);
|
// transform: translate(-50%, 0);
|
||||||
width: 96rpx !important;
|
width: 108rpx !important;
|
||||||
height: 96rpx !important;
|
height: 98rpx !important;
|
||||||
}
|
}
|
||||||
.item-active {
|
.item-active {
|
||||||
color: #256bfa;
|
color: #256bfa;
|
||||||
|
173
hook/usePagination.js
Normal file
173
hook/usePagination.js
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
import {
|
||||||
|
ref,
|
||||||
|
reactive,
|
||||||
|
watch,
|
||||||
|
isRef,
|
||||||
|
nextTick
|
||||||
|
} from 'vue'
|
||||||
|
|
||||||
|
export function usePagination(
|
||||||
|
requestFn,
|
||||||
|
transformFn,
|
||||||
|
options = {}
|
||||||
|
) {
|
||||||
|
const list = ref([])
|
||||||
|
const loading = ref(false)
|
||||||
|
const error = ref(false)
|
||||||
|
const finished = ref(false)
|
||||||
|
const firstLoading = ref(true)
|
||||||
|
const empty = ref(false)
|
||||||
|
|
||||||
|
const {
|
||||||
|
pageSize = 10,
|
||||||
|
search = {},
|
||||||
|
autoWatchSearch = false,
|
||||||
|
debounceTime = 300,
|
||||||
|
autoFetch = false,
|
||||||
|
|
||||||
|
// 字段映射
|
||||||
|
dataKey = 'rows',
|
||||||
|
totalKey = 'total',
|
||||||
|
|
||||||
|
// 分页字段名映射
|
||||||
|
pageField = 'current',
|
||||||
|
sizeField = 'pageSize',
|
||||||
|
|
||||||
|
onBeforeRequest,
|
||||||
|
onAfterRequest
|
||||||
|
} = options
|
||||||
|
|
||||||
|
const pageState = reactive({
|
||||||
|
page: 1,
|
||||||
|
pageSize: isRef(pageSize) ? pageSize.value : pageSize,
|
||||||
|
total: 0,
|
||||||
|
maxPage: 1,
|
||||||
|
search: isRef(search) ? search.value : search
|
||||||
|
})
|
||||||
|
|
||||||
|
let debounceTimer = null
|
||||||
|
|
||||||
|
const fetchData = async (type = 'refresh') => {
|
||||||
|
if (loading.value) return Promise.resolve()
|
||||||
|
|
||||||
|
loading.value = true
|
||||||
|
error.value = false
|
||||||
|
|
||||||
|
if (typeof onBeforeRequest === 'function') {
|
||||||
|
try {
|
||||||
|
onBeforeRequest(type, pageState)
|
||||||
|
} catch (err) {
|
||||||
|
console.warn('onBeforeRequest 执行异常:', err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === 'refresh') {
|
||||||
|
pageState.page = 1
|
||||||
|
finished.value = false
|
||||||
|
if (list.value.length === 0) {
|
||||||
|
firstLoading.value = true
|
||||||
|
}
|
||||||
|
} else if (type === 'loadMore') {
|
||||||
|
if (pageState.page >= pageState.maxPage) {
|
||||||
|
loading.value = false
|
||||||
|
finished.value = true
|
||||||
|
return Promise.resolve('no more')
|
||||||
|
}
|
||||||
|
pageState.page += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
const params = {
|
||||||
|
[pageField]: pageState.page,
|
||||||
|
[sizeField]: pageState.pageSize,
|
||||||
|
...pageState.search
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await requestFn(params)
|
||||||
|
|
||||||
|
const rawData = res[dataKey]
|
||||||
|
const total = res[totalKey]
|
||||||
|
|
||||||
|
const data = typeof transformFn === 'function' ? transformFn(rawData) : rawData
|
||||||
|
|
||||||
|
if (type === 'refresh') {
|
||||||
|
list.value = data
|
||||||
|
} else {
|
||||||
|
list.value.push(...data)
|
||||||
|
}
|
||||||
|
|
||||||
|
pageState.total = total
|
||||||
|
pageState.maxPage = Math.ceil(total / pageState.pageSize)
|
||||||
|
|
||||||
|
finished.value = list.value.length >= total
|
||||||
|
empty.value = list.value.length === 0
|
||||||
|
} catch (err) {
|
||||||
|
console.error('分页请求失败:', err)
|
||||||
|
error.value = true
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
firstLoading.value = false
|
||||||
|
|
||||||
|
if (typeof onAfterRequest === 'function') {
|
||||||
|
try {
|
||||||
|
onAfterRequest(type, pageState, {
|
||||||
|
error: error.value
|
||||||
|
})
|
||||||
|
} catch (err) {
|
||||||
|
console.warn('onAfterRequest 执行异常:', err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const refresh = () => fetchData('refresh')
|
||||||
|
const loadMore = () => fetchData('loadMore')
|
||||||
|
|
||||||
|
const resetPagination = () => {
|
||||||
|
list.value = []
|
||||||
|
pageState.page = 1
|
||||||
|
pageState.total = 0
|
||||||
|
pageState.maxPage = 1
|
||||||
|
finished.value = false
|
||||||
|
error.value = false
|
||||||
|
firstLoading.value = true
|
||||||
|
empty.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (autoWatchSearch && isRef(search)) {
|
||||||
|
watch(search, (newVal) => {
|
||||||
|
pageState.search = newVal
|
||||||
|
// clearTimeout(debounceTimer)
|
||||||
|
// debounceTimer = setTimeout(() => {
|
||||||
|
// refresh()
|
||||||
|
// }, debounceTime)
|
||||||
|
}, {
|
||||||
|
deep: true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(pageSize, (newVal) => {
|
||||||
|
pageState.pageSize = newVal
|
||||||
|
}, {
|
||||||
|
deep: true
|
||||||
|
})
|
||||||
|
|
||||||
|
if (autoFetch) {
|
||||||
|
nextTick(() => {
|
||||||
|
refresh()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
list,
|
||||||
|
loading,
|
||||||
|
error,
|
||||||
|
finished,
|
||||||
|
firstLoading,
|
||||||
|
empty,
|
||||||
|
pageState,
|
||||||
|
refresh,
|
||||||
|
loadMore,
|
||||||
|
resetPagination
|
||||||
|
}
|
||||||
|
}
|
@@ -13,7 +13,13 @@
|
|||||||
</template>
|
</template>
|
||||||
<view class="content" v-show="!isEmptyObject(jobInfo)">
|
<view class="content" v-show="!isEmptyObject(jobInfo)">
|
||||||
<view class="content-top btn-feel">
|
<view class="content-top btn-feel">
|
||||||
<view class="top-salary">{{ jobInfo.minSalary }}-{{ jobInfo.maxSalary }}/月</view>
|
<view class="top-salary">
|
||||||
|
<Salary-Expectation
|
||||||
|
:max-salary="jobInfo.maxSalary"
|
||||||
|
:min-salary="jobInfo.minSalary"
|
||||||
|
:is-month="true"
|
||||||
|
></Salary-Expectation>
|
||||||
|
</view>
|
||||||
<view class="top-name">{{ jobInfo.jobTitle }}</view>
|
<view class="top-name">{{ jobInfo.jobTitle }}</view>
|
||||||
<view class="top-info">
|
<view class="top-info">
|
||||||
<view class="info-img"><image src="/static/icon/post12.png"></image></view>
|
<view class="info-img"><image src="/static/icon/post12.png"></image></view>
|
||||||
|
136
packageA/pages/tiktok/tiktok.vue
Normal file
136
packageA/pages/tiktok/tiktok.vue
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
<template>
|
||||||
|
<div class="video-container">
|
||||||
|
<view class="back-box">
|
||||||
|
<view class="btn">
|
||||||
|
<uni-icons type="left" size="26" color="#FFFFFF" @click="navBack"></uni-icons>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<mTikTok :video-list="state.videoList" :pause-type="1" :controls="false" @loadMore="loadMore" @change="change">
|
||||||
|
<template v-slot="data">
|
||||||
|
<view class="video-layer">
|
||||||
|
<view class="title line_1">{{ currentItem.companyName }}</view>
|
||||||
|
<view class="discription">
|
||||||
|
<text class="line_1">
|
||||||
|
{{ currentItem.jobTitle }}
|
||||||
|
</text>
|
||||||
|
<view class="seedetail" @click="nextDetail">
|
||||||
|
查看详情
|
||||||
|
<uni-icons type="right" color="#FFFFFF" size="14"></uni-icons>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
</mTikTok>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import { inject, ref, reactive } from 'vue';
|
||||||
|
import { onLoad, onShow } from '@dcloudio/uni-app';
|
||||||
|
const { $api, navBack, navTo } = inject('globalFunction');
|
||||||
|
import mTikTok from '@/components/TikTok/TikTok.vue';
|
||||||
|
import useUserStore from '@/stores/useUserStore';
|
||||||
|
import { useRecommedIndexedDBStore } from '@/stores/useRecommedIndexedDBStore.js';
|
||||||
|
const recommedIndexDb = useRecommedIndexedDBStore();
|
||||||
|
const state = reactive({
|
||||||
|
videoList: [],
|
||||||
|
});
|
||||||
|
const currentItem = ref(null);
|
||||||
|
|
||||||
|
onLoad(() => {
|
||||||
|
const jobInfo = uni.getStorageSync(`job-Info`);
|
||||||
|
if (jobInfo) {
|
||||||
|
currentItem.value = jobInfo;
|
||||||
|
state.videoList.push(jobInfo);
|
||||||
|
}
|
||||||
|
getNextVideoSrc(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
function nextDetail() {
|
||||||
|
const job = currentItem.value;
|
||||||
|
// 记录岗位类型,用作数据分析
|
||||||
|
if (job.jobCategory) {
|
||||||
|
const recordData = recommedIndexDb.JobParameter(job);
|
||||||
|
recommedIndexDb.addRecord(recordData);
|
||||||
|
}
|
||||||
|
console.log(job.jobId);
|
||||||
|
navTo(`/packageA/pages/post/post?jobId=${btoa(job.jobId)}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getNextVideoSrc(num) {
|
||||||
|
let params = {
|
||||||
|
uuid: useUserStore().seesionId,
|
||||||
|
count: num || 1,
|
||||||
|
};
|
||||||
|
$api.createRequest('/app/job/littleVideo/random', params).then((resData) => {
|
||||||
|
const { data, code } = resData;
|
||||||
|
state.videoList.push(...data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const loadMore = () => {
|
||||||
|
// 触发加载更多
|
||||||
|
console.log('加载更多');
|
||||||
|
getNextVideoSrc();
|
||||||
|
};
|
||||||
|
|
||||||
|
const change = (e) => {
|
||||||
|
currentItem.value = e.detail;
|
||||||
|
console.log('🚀 ~ file: index.vue:53 ~ change ~ data:', e);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style lang="stylus" scoped>
|
||||||
|
.video-container{
|
||||||
|
width: 100%;
|
||||||
|
height: 100vh;
|
||||||
|
position: relative
|
||||||
|
.back-box{
|
||||||
|
position: absolute;
|
||||||
|
left: 20rpx;
|
||||||
|
top: 20rpx
|
||||||
|
color: #FFFFFF
|
||||||
|
z-index: 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.video-layer {
|
||||||
|
position: absolute;
|
||||||
|
left: 24rpx;
|
||||||
|
right: 24rpx;
|
||||||
|
bottom: 30rpx;
|
||||||
|
color: #fff;
|
||||||
|
.title{
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 30rpx;
|
||||||
|
line-height: 100%;
|
||||||
|
letter-spacing: 0%;
|
||||||
|
}
|
||||||
|
.discription{
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 28rpx;
|
||||||
|
letter-spacing: 0%;
|
||||||
|
margin-top: 20rpx
|
||||||
|
display: flex
|
||||||
|
align-items: center
|
||||||
|
.seedetail{
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 32rpx;
|
||||||
|
line-height: 100%;
|
||||||
|
letter-spacing: 0%;
|
||||||
|
white-space: nowrap
|
||||||
|
padding-left: 20rpx
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
width: 60rpx;
|
||||||
|
height: 60rpx;
|
||||||
|
|
||||||
|
image {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
10
pages.json
10
pages.json
@@ -186,10 +186,20 @@
|
|||||||
"navigationBarTitleText": "系统通知",
|
"navigationBarTitleText": "系统通知",
|
||||||
"navigationBarBackgroundColor": "#FFFFFF"
|
"navigationBarBackgroundColor": "#FFFFFF"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/tiktok/tiktok",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "",
|
||||||
|
"navigationBarBackgroundColor": "#FFFFFF",
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}],
|
}],
|
||||||
"tabBar": {
|
"tabBar": {
|
||||||
|
"custom": true,
|
||||||
|
"display": "none",
|
||||||
"color": "#5E5F60",
|
"color": "#5E5F60",
|
||||||
"selectedColor": "#256BFA",
|
"selectedColor": "#256BFA",
|
||||||
"borderStyle": "black",
|
"borderStyle": "black",
|
||||||
|
@@ -39,7 +39,7 @@
|
|||||||
<scroll-view scroll-y class="main-scroll" @scrolltolower="handleScrollToLower">
|
<scroll-view scroll-y class="main-scroll" @scrolltolower="handleScrollToLower">
|
||||||
<view class="cards" v-if="fairList.length">
|
<view class="cards" v-if="fairList.length">
|
||||||
<view
|
<view
|
||||||
class="card btn-incline"
|
class="card press-button"
|
||||||
v-for="(item, index) in fairList"
|
v-for="(item, index) in fairList"
|
||||||
:key="index"
|
:key="index"
|
||||||
@click="navTo('/packageA/pages/exhibitors/exhibitors?jobFairId=' + item.jobFairId)"
|
@click="navTo('/packageA/pages/exhibitors/exhibitors?jobFairId=' + item.jobFairId)"
|
||||||
@@ -83,6 +83,7 @@
|
|||||||
<empty v-else pdTop="200"></empty>
|
<empty v-else pdTop="200"></empty>
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
</view>
|
</view>
|
||||||
|
<Tabbar :currentpage="1"></Tabbar>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
@@ -90,6 +91,7 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { reactive, inject, watch, ref, onMounted } from 'vue';
|
import { reactive, inject, watch, ref, onMounted } from 'vue';
|
||||||
import { onLoad, onShow } from '@dcloudio/uni-app';
|
import { onLoad, onShow } from '@dcloudio/uni-app';
|
||||||
|
import Tabbar from '@/components/tabbar/midell-box.vue';
|
||||||
import useLocationStore from '@/stores/useLocationStore';
|
import useLocationStore from '@/stores/useLocationStore';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
const { longitudeVal, latitudeVal } = storeToRefs(useLocationStore());
|
const { longitudeVal, latitudeVal } = storeToRefs(useLocationStore());
|
||||||
|
@@ -62,10 +62,11 @@
|
|||||||
<view class="chatmain-warpper">
|
<view class="chatmain-warpper">
|
||||||
<ai-paging ref="paging"></ai-paging>
|
<ai-paging ref="paging"></ai-paging>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 自定义tabbar -->
|
<!-- 自定义tabbar -->
|
||||||
<!-- <tabbar-custom :currentpage="2"></tabbar-custom> -->
|
<view class="chatmain-footer" v-show="!isDrawerOpen">
|
||||||
|
<Tabbar :currentpage="2"></Tabbar>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -73,6 +74,7 @@
|
|||||||
import { ref, inject, nextTick, computed } from 'vue';
|
import { ref, inject, nextTick, computed } from 'vue';
|
||||||
const { $api, navTo, insertSortData } = inject('globalFunction');
|
const { $api, navTo, insertSortData } = inject('globalFunction');
|
||||||
import { onLoad, onShow, onHide } from '@dcloudio/uni-app';
|
import { onLoad, onShow, onHide } from '@dcloudio/uni-app';
|
||||||
|
import Tabbar from '@/components/tabbar/midell-box.vue';
|
||||||
import useChatGroupDBStore from '@/stores/userChatGroupStore';
|
import useChatGroupDBStore from '@/stores/userChatGroupStore';
|
||||||
import useUserStore from '@/stores/useUserStore';
|
import useUserStore from '@/stores/useUserStore';
|
||||||
import aiPaging from './components/ai-paging.vue';
|
import aiPaging from './components/ai-paging.vue';
|
||||||
@@ -108,16 +110,16 @@ onHide(() => {
|
|||||||
paging.value?.handleTouchCancel();
|
paging.value?.handleTouchCancel();
|
||||||
if (isDrawerOpen.value) {
|
if (isDrawerOpen.value) {
|
||||||
isDrawerOpen.value = false;
|
isDrawerOpen.value = false;
|
||||||
uni.showTabBar();
|
// uni.showTabBar();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const toggleDrawer = () => {
|
const toggleDrawer = () => {
|
||||||
isDrawerOpen.value = !isDrawerOpen.value;
|
isDrawerOpen.value = !isDrawerOpen.value;
|
||||||
if (isDrawerOpen.value) {
|
if (isDrawerOpen.value) {
|
||||||
uni.hideTabBar();
|
// uni.hideTabBar();
|
||||||
} else {
|
} else {
|
||||||
uni.showTabBar();
|
// uni.showTabBar();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -144,6 +146,7 @@ function updateSetting() {
|
|||||||
|
|
||||||
<style lang="stylus" scoped>
|
<style lang="stylus" scoped>
|
||||||
header-height = 88rpx
|
header-height = 88rpx
|
||||||
|
footer-height = 98rpx
|
||||||
|
|
||||||
/* 页面容器 */
|
/* 页面容器 */
|
||||||
.container {
|
.container {
|
||||||
@@ -277,6 +280,8 @@ header-height = 88rpx
|
|||||||
transition: margin-left 0.3s ease-in-out;
|
transition: margin-left 0.3s ease-in-out;
|
||||||
position: relative
|
position: relative
|
||||||
background: #FFFFFF
|
background: #FFFFFF
|
||||||
|
display: flex
|
||||||
|
flex-direction: column
|
||||||
.head
|
.head
|
||||||
display: block;
|
display: block;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
@@ -304,15 +309,20 @@ header-height = 88rpx
|
|||||||
height: 37rpx;
|
height: 37rpx;
|
||||||
|
|
||||||
.chatmain-warpper
|
.chatmain-warpper
|
||||||
height: 'calc(100% - %s)' % header-height
|
height: 'calc(100% - %s)' %( header-height + footer-height)
|
||||||
position: relative;
|
position: relative;
|
||||||
display: block;
|
display: block;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-top: 2rpx solid #F4F4F4;
|
border-top: 2rpx solid #F4F4F4;
|
||||||
|
flex: 1
|
||||||
|
|
||||||
/* 页面被挤压时向右移动 */
|
/* 页面被挤压时向右移动 */
|
||||||
.main-content.shift {
|
.main-content.shift {
|
||||||
margin-left: 500rpx;
|
margin-left: 500rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.chatmain-footer{
|
||||||
|
height: footer-height;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
@@ -9,11 +9,11 @@
|
|||||||
<view class="chart button-click">职业图谱</view>
|
<view class="chart button-click">职业图谱</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="cards">
|
<view class="cards">
|
||||||
<view class="card btn-feel" @click="navTo('/pages/nearby/nearby')">
|
<view class="card press-button" @click="navTo('/pages/nearby/nearby')">
|
||||||
<view class="card-title">附近工作</view>
|
<view class="card-title">附近工作</view>
|
||||||
<view class="card-text">好岗职等你来</view>
|
<view class="card-text">好岗职等你来</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="card btn-feel" @click="navTo('/packageA/pages/choiceness/choiceness')">
|
<view class="card press-button" @click="navTo('/packageA/pages/choiceness/choiceness')">
|
||||||
<view class="card-title">精选企业</view>
|
<view class="card-title">精选企业</view>
|
||||||
<view class="card-text">优选职得信赖</view>
|
<view class="card-text">优选职得信赖</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -132,6 +132,14 @@
|
|||||||
</view>
|
</view>
|
||||||
<!-- 筛选 -->
|
<!-- 筛选 -->
|
||||||
<select-filter ref="selectFilterModel"></select-filter>
|
<select-filter ref="selectFilterModel"></select-filter>
|
||||||
|
|
||||||
|
<view class="maskFristEntry" v-if="maskFristEntry">
|
||||||
|
<view class="entry-content">
|
||||||
|
<text>左滑查看视频</text>
|
||||||
|
<image class="indicateArrow" src="/static/gif/indicateArrow.gif"></image>
|
||||||
|
</view>
|
||||||
|
<view class="maskFristEntry-Close" @click="closeFristEntry"></view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -153,11 +161,13 @@ import { useScrollDirection } from '@/hook/useScrollDirection';
|
|||||||
import { useColumnCount } from '@/hook/useColumnCount';
|
import { useColumnCount } from '@/hook/useColumnCount';
|
||||||
const { isScrollingDown, handleScroll } = useScrollDirection();
|
const { isScrollingDown, handleScroll } = useScrollDirection();
|
||||||
const recommedIndexDb = useRecommedIndexedDBStore();
|
const recommedIndexDb = useRecommedIndexedDBStore();
|
||||||
|
const emits = defineEmits(['onShowTabbar']);
|
||||||
|
|
||||||
const waterfallsFlowRef = ref(null);
|
const waterfallsFlowRef = ref(null);
|
||||||
const loadmoreRef = ref(null);
|
const loadmoreRef = ref(null);
|
||||||
const conditionSearch = ref({});
|
const conditionSearch = ref({});
|
||||||
const waterfallcolumn = ref(2);
|
const waterfallcolumn = ref(2);
|
||||||
|
const maskFristEntry = ref(false);
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
tabIndex: 'all',
|
tabIndex: 'all',
|
||||||
});
|
});
|
||||||
@@ -193,6 +203,12 @@ const isLoaded = ref(false);
|
|||||||
// { name: '创意总监', highlight: false },
|
// { name: '创意总监', highlight: false },
|
||||||
// ]);
|
// ]);
|
||||||
|
|
||||||
|
onLoad(() => {
|
||||||
|
// 判断浏览器是否有 fristEntry 第一次进入
|
||||||
|
let fristEntry = uni.getStorageSync('fristEntry') || true; // 默认未读
|
||||||
|
maskFristEntry.value = fristEntry;
|
||||||
|
});
|
||||||
|
|
||||||
const { columnCount, columnSpace } = useColumnCount(() => {
|
const { columnCount, columnSpace } = useColumnCount(() => {
|
||||||
pageState.pageSize = 10 * (columnCount.value - 1);
|
pageState.pageSize = 10 * (columnCount.value - 1);
|
||||||
getJobRecommend('refresh');
|
getJobRecommend('refresh');
|
||||||
@@ -202,6 +218,11 @@ const { columnCount, columnSpace } = useColumnCount(() => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function closeFristEntry() {
|
||||||
|
uni.setStorageSync('fristEntry', false);
|
||||||
|
maskFristEntry.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
// onLoad(() => {
|
// onLoad(() => {
|
||||||
// getJobRecommend('refresh');
|
// getJobRecommend('refresh');
|
||||||
// });
|
// });
|
||||||
@@ -286,6 +307,7 @@ function nextDetail(job) {
|
|||||||
|
|
||||||
function openFilter() {
|
function openFilter() {
|
||||||
showFilter.value = true;
|
showFilter.value = true;
|
||||||
|
emits('onShowTabbar', false);
|
||||||
selectFilterModel.value?.open({
|
selectFilterModel.value?.open({
|
||||||
title: '筛选',
|
title: '筛选',
|
||||||
maskClick: true,
|
maskClick: true,
|
||||||
@@ -301,6 +323,7 @@ function openFilter() {
|
|||||||
},
|
},
|
||||||
cancel: () => {
|
cancel: () => {
|
||||||
showFilter.value = false;
|
showFilter.value = false;
|
||||||
|
emits('onShowTabbar', true);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -438,6 +461,51 @@ defineExpose({ loadData });
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="stylus" scoped>
|
<style lang="stylus" scoped>
|
||||||
|
.maskFristEntry
|
||||||
|
position: fixed;
|
||||||
|
right: 20rpx;
|
||||||
|
bottom: calc(50% - 200rpx);
|
||||||
|
// background: rgba(0,0,0,0.3)
|
||||||
|
.entry-content
|
||||||
|
display: flex;
|
||||||
|
align-items: center
|
||||||
|
text
|
||||||
|
font-size: 36rpx
|
||||||
|
background: linear-gradient(273.34deg, #356CFA 3.58%, #A47FFD 85.84%);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
background-clip: text; /* 有些浏览器兼容用 */
|
||||||
|
text-fill-color: transparent;
|
||||||
|
.indicateArrow
|
||||||
|
height: 76rpx
|
||||||
|
width: 68rpx
|
||||||
|
.maskFristEntry-Close
|
||||||
|
position: absolute;
|
||||||
|
left: calc(50% - 10rpx);
|
||||||
|
top: 86rpx
|
||||||
|
width: 42rpx
|
||||||
|
height: 42rpx
|
||||||
|
background: linear-gradient(273.34deg, #356CFA 3.58%, #A47FFD 85.84%);
|
||||||
|
border-radius: 50%;
|
||||||
|
.maskFristEntry-Close::before
|
||||||
|
position: absolute;
|
||||||
|
left: calc( 50% - 2rpx)
|
||||||
|
top: calc( 50% - 10rpx)
|
||||||
|
transform: rotate(45deg);
|
||||||
|
content: ''
|
||||||
|
background: #FFFFFF
|
||||||
|
width: 4rpx
|
||||||
|
height: 20rpx
|
||||||
|
.maskFristEntry-Close::after
|
||||||
|
position: absolute;
|
||||||
|
left: calc( 50% - 2rpx)
|
||||||
|
top: calc( 50% - 10rpx)
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
content: ''
|
||||||
|
background: #FFFFFF
|
||||||
|
width: 4rpx
|
||||||
|
height: 20rpx
|
||||||
|
|
||||||
|
|
||||||
.app-container
|
.app-container
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@@ -29,16 +29,40 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="cards">
|
<view class="cards">
|
||||||
<scroll-view :scroll-y="true" class="tab-scroll">
|
<scroll-view :scroll-y="true" class="tab-scroll" @scrolltolower="scrollBottom">
|
||||||
<view class="scroll-content">
|
<view class="scroll-content">
|
||||||
<custom-waterfalls-flow ref="waterfallsFlowRef" :value="data.list">
|
<custom-waterfalls-flow
|
||||||
<template v-slot:default="item">
|
ref="waterfallsFlowRef"
|
||||||
<view class="item">
|
:column="columnCount"
|
||||||
<view class="title">{{ item.title }}</view>
|
:columnSpace="columnSpace"
|
||||||
<view class="desc">{{ item.desc }}</view>
|
@loaded="imageloaded"
|
||||||
|
: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">
|
||||||
|
<!-- <uni-icons type="location" size="14"></uni-icons> -->
|
||||||
|
<view class="descText">{{ job.companyName }}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
</custom-waterfalls-flow>
|
</custom-waterfalls-flow>
|
||||||
|
<loadmore ref="loadmoreRef"></loadmore>
|
||||||
</view>
|
</view>
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
</view>
|
</view>
|
||||||
@@ -47,77 +71,100 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { reactive, inject, watch, ref, onMounted, watchEffect, nextTick } from 'vue';
|
import { reactive, inject, watch, ref, onMounted, watchEffect, nextTick } from 'vue';
|
||||||
|
import { usePagination } from '@/hook/usePagination';
|
||||||
const { $api, navTo } = inject('globalFunction');
|
const { $api, navTo } = inject('globalFunction');
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import useUserStore from '@/stores/useUserStore';
|
import useUserStore from '@/stores/useUserStore';
|
||||||
|
import img from '@/static/icon/filter.png';
|
||||||
|
import { useColumnCount } from '@/hook/useColumnCount';
|
||||||
|
import { useRecommedIndexedDBStore, jobRecommender } from '@/stores/useRecommedIndexedDBStore.js';
|
||||||
|
const recommedIndexDb = useRecommedIndexedDBStore();
|
||||||
|
// status
|
||||||
const { userInfo } = storeToRefs(useUserStore());
|
const { userInfo } = storeToRefs(useUserStore());
|
||||||
const isLoaded = ref(false);
|
const isLoaded = ref(false);
|
||||||
const waterfallsFlowRef = ref(null);
|
const waterfallsFlowRef = ref(null);
|
||||||
|
const loadmoreRef = ref(null);
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
tabIndex: 'all',
|
tabIndex: 'all',
|
||||||
});
|
});
|
||||||
const data = reactive({
|
|
||||||
list: [
|
// 响应式搜索条件(可以被修改)
|
||||||
|
const searchParams = ref({});
|
||||||
|
const pageSize = ref(10);
|
||||||
|
const { list, loading, refresh, loadMore } = usePagination(
|
||||||
|
(params) => $api.createRequest('/app/job/littleVideo', params),
|
||||||
|
dataToImg, // 转换函数
|
||||||
{
|
{
|
||||||
image: 'https://via.placeholder.com/200x500.png/ff0000',
|
pageSize: pageSize,
|
||||||
title: '我是标题1',
|
search: searchParams,
|
||||||
desc: '描述描述描述描述描述描述描述描述1',
|
dataKey: 'data',
|
||||||
|
onBeforeRequest: () => {
|
||||||
|
loadmoreRef.value?.change('loading');
|
||||||
},
|
},
|
||||||
{
|
}
|
||||||
image: 'https://via.placeholder.com/200x200.png/2878ff',
|
);
|
||||||
title: '我是标题2',
|
|
||||||
desc: '描述描述描述描述描述描述描述描述2',
|
function imageloaded() {
|
||||||
},
|
loadmoreRef.value?.change('more');
|
||||||
{
|
}
|
||||||
image: 'https://via.placeholder.com/200x100.png/FFB6C1',
|
|
||||||
title: '我是标题3',
|
const { columnCount, columnSpace } = useColumnCount(() => {
|
||||||
desc: '描述描述描述描述描述描述描述描述3',
|
pageSize.value = 10 * (columnCount.value - 1);
|
||||||
},
|
nextTick(() => {
|
||||||
{
|
waterfallsFlowRef.value?.refresh?.();
|
||||||
image: 'https://via.placeholder.com/200x300.png/9400D3',
|
useLocationStore().getLocation();
|
||||||
title: '我是标题4',
|
});
|
||||||
desc: '描述描述描述描述描述描述描述描述4',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
image: 'https://via.placeholder.com/100x240.png/B0E0E6',
|
|
||||||
title: '我是标题5',
|
|
||||||
desc: '描述描述描述描述描述描述描述描述5',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
image: 'https://via.placeholder.com/140x280.png/7FFFAA',
|
|
||||||
title: '我是标题6',
|
|
||||||
desc: '描述描述描述描述描述描述描述描述6',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
image: 'https://via.placeholder.com/40x60.png/EEE8AA',
|
|
||||||
title: '我是标题7',
|
|
||||||
desc: '描述描述描述描述描述描述描述描述7',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
image: 'https://via.placeholder.com/140x280.png/7FFFAA',
|
|
||||||
title: '我是标题6',
|
|
||||||
desc: '描述描述描述描述描述描述描述描述6',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
image: 'https://via.placeholder.com/40x60.png/EEE8AA',
|
|
||||||
title: '我是标题7',
|
|
||||||
desc: '描述描述描述描述描述描述描述描述7',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
});
|
||||||
|
|
||||||
async function loadData() {
|
async function loadData() {
|
||||||
try {
|
try {
|
||||||
if (isLoaded.value) return;
|
if (isLoaded.value) return;
|
||||||
isLoaded.value = true;
|
isLoaded.value = true;
|
||||||
|
refresh();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
isLoaded.value = false; // 重置状态允许重试
|
isLoaded.value = false; // 重置状态允许重试
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function choosePosition() {}
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
function scrollBottom() {
|
||||||
|
loadMore();
|
||||||
|
}
|
||||||
|
|
||||||
|
function nextDetail(job) {
|
||||||
|
// 记录岗位类型,用作数据分析
|
||||||
|
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`);
|
||||||
|
}
|
||||||
|
|
||||||
|
function dataToImg(data) {
|
||||||
|
return data.map((item) => ({
|
||||||
|
...item,
|
||||||
|
// image: item.cover,
|
||||||
|
image: img,
|
||||||
|
hide: true,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
defineExpose({ loadData });
|
defineExpose({ loadData });
|
||||||
</script>
|
</script>
|
||||||
@@ -159,9 +206,10 @@ defineExpose({ loadData });
|
|||||||
.jobs-left
|
.jobs-left
|
||||||
display: flex
|
display: flex
|
||||||
flex-wrap: nowrap
|
flex-wrap: nowrap
|
||||||
|
align-items: center
|
||||||
.job
|
.job
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-size: 36rpx;
|
font-size: 28rpx;
|
||||||
color: #666D7F;
|
color: #666D7F;
|
||||||
margin-right: 32rpx;
|
margin-right: 32rpx;
|
||||||
white-space: nowrap
|
white-space: nowrap
|
||||||
@@ -174,9 +222,11 @@ defineExpose({ loadData });
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-size: 32rpx;
|
font-size: 28rpx;
|
||||||
color: #666D7F;
|
color: #666D7F;
|
||||||
line-height: 38rpx;
|
line-height: 38rpx;
|
||||||
|
.iconsearch
|
||||||
|
margin-right: 6rpx
|
||||||
.filter-bottom
|
.filter-bottom
|
||||||
display: flex
|
display: flex
|
||||||
justify-content: space-between
|
justify-content: space-between
|
||||||
@@ -202,4 +252,71 @@ defineExpose({ loadData });
|
|||||||
height: 26rpx;
|
height: 26rpx;
|
||||||
.active
|
.active
|
||||||
transform: rotate(180deg)
|
transform: rotate(180deg)
|
||||||
|
|
||||||
|
.slot-item
|
||||||
|
background: #f4f4f4;
|
||||||
|
// background: #f6f8fa;
|
||||||
|
.job-image{
|
||||||
|
width: 100%;
|
||||||
|
height: 280rpx;
|
||||||
|
position: relative;
|
||||||
|
.cover-image{
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.cover-triangle{
|
||||||
|
position: absolute;
|
||||||
|
right: 20rpx;
|
||||||
|
top: 20rpx
|
||||||
|
width: 36rpx
|
||||||
|
height: 36rpx
|
||||||
|
border-radius: 50%
|
||||||
|
background: rgba(0,0,0,0.3)
|
||||||
|
}
|
||||||
|
.cover-triangle::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-40%, -50%) rotate(90deg);
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
border-left: 8rpx solid transparent;
|
||||||
|
border-right: 8rpx solid transparent;
|
||||||
|
border-bottom: 12rpx solid #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.job-info{
|
||||||
|
padding: 10rpx 24rpx 24rpx 24rpx
|
||||||
|
}
|
||||||
|
.salary
|
||||||
|
color: #4C6EFB;
|
||||||
|
font-size: 28rpx
|
||||||
|
display: flex
|
||||||
|
align-items: flex-start
|
||||||
|
justify-content: space-between
|
||||||
|
.flame
|
||||||
|
margin-top: 4rpx
|
||||||
|
margin-right: 4rpx
|
||||||
|
width: 24rpx
|
||||||
|
height: 31rpx
|
||||||
|
.title
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 32rpx;
|
||||||
|
color: #333333;
|
||||||
|
margin-top: 6rpx;
|
||||||
|
white-space: pre-wrap
|
||||||
|
.desc
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #6C7282;
|
||||||
|
margin-top: 6rpx;
|
||||||
|
display: flex
|
||||||
|
.descText{
|
||||||
|
white-space: pre-wrap
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@@ -6,21 +6,35 @@
|
|||||||
<swiper class="swiper" :current="state.current" @change="changeSwiperType">
|
<swiper class="swiper" :current="state.current" @change="changeSwiperType">
|
||||||
<swiper-item class="swiper-item" v-for="(_, index) in 2" :key="index">
|
<swiper-item class="swiper-item" v-for="(_, index) in 2" :key="index">
|
||||||
<!-- #ifndef MP-WEIXIN -->
|
<!-- #ifndef MP-WEIXIN -->
|
||||||
<component :is="components[index]" :ref="(el) => handelComponentsRef(el, index)" />
|
<component
|
||||||
|
:is="components[index]"
|
||||||
|
@onShowTabbar="changeShowTabbar"
|
||||||
|
:ref="(el) => handelComponentsRef(el, index)"
|
||||||
|
/>
|
||||||
<!-- #endif -->
|
<!-- #endif -->
|
||||||
<!-- #ifdef MP-WEIXIN -->
|
<!-- #ifdef MP-WEIXIN -->
|
||||||
<IndexOne v-show="currentIndex === 0" :ref="(el) => handelComponentsRef(el, index)" />
|
<IndexOne
|
||||||
<IndexTwo v-show="currentIndex === 1" :ref="(el) => handelComponentsRef(el, index)" />
|
v-show="currentIndex === 0"
|
||||||
|
@onShowTabbar="changeShowTabbar"
|
||||||
|
:ref="(el) => handelComponentsRef(el, index)"
|
||||||
|
/>
|
||||||
|
<IndexTwo
|
||||||
|
v-show="currentIndex === 1"
|
||||||
|
@onShowTabbar="changeShowTabbar"
|
||||||
|
:ref="(el) => handelComponentsRef(el, index)"
|
||||||
|
/>
|
||||||
<!-- #endif -->
|
<!-- #endif -->
|
||||||
</swiper-item>
|
</swiper-item>
|
||||||
</swiper>
|
</swiper>
|
||||||
</view>
|
</view>
|
||||||
|
<Tabbar v-show="showTabbar" :currentpage="0"></Tabbar>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { reactive, inject, watch, ref, onMounted } from 'vue';
|
import { reactive, inject, watch, ref, onMounted } from 'vue';
|
||||||
|
import Tabbar from '@/components/tabbar/midell-box.vue';
|
||||||
import { onLoad, onShow } from '@dcloudio/uni-app';
|
import { onLoad, onShow } from '@dcloudio/uni-app';
|
||||||
import IndexOne from './components/index-one.vue';
|
import IndexOne from './components/index-one.vue';
|
||||||
import IndexTwo from './components/index-two.vue';
|
import IndexTwo from './components/index-two.vue';
|
||||||
@@ -30,6 +44,7 @@ const components = [IndexOne, IndexTwo];
|
|||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import { useReadMsg } from '@/stores/useReadMsg';
|
import { useReadMsg } from '@/stores/useReadMsg';
|
||||||
const { unreadCount } = storeToRefs(useReadMsg());
|
const { unreadCount } = storeToRefs(useReadMsg());
|
||||||
|
const showTabbar = ref(true);
|
||||||
|
|
||||||
onShow(() => {
|
onShow(() => {
|
||||||
// 获取消息列表
|
// 获取消息列表
|
||||||
@@ -49,6 +64,11 @@ const handelComponentsRef = (el, index) => {
|
|||||||
swiperRefs[index].value = el;
|
swiperRefs[index].value = el;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function changeShowTabbar(val) {
|
||||||
|
showTabbar.value = val;
|
||||||
|
}
|
||||||
|
|
||||||
// 查看消息类型
|
// 查看消息类型
|
||||||
function changeSwiperType(e) {
|
function changeSwiperType(e) {
|
||||||
const index = e.detail.current;
|
const index = e.detail.current;
|
||||||
|
@@ -96,12 +96,16 @@
|
|||||||
></uni-popup-dialog>
|
></uni-popup-dialog>
|
||||||
</uni-popup>
|
</uni-popup>
|
||||||
</view>
|
</view>
|
||||||
|
<template #footer>
|
||||||
|
<Tabbar :currentpage="4"></Tabbar>
|
||||||
|
</template>
|
||||||
</AppLayout>
|
</AppLayout>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { reactive, inject, watch, ref, onMounted } from 'vue';
|
import { reactive, inject, watch, ref, onMounted } from 'vue';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
|
import Tabbar from '@/components/tabbar/midell-box.vue';
|
||||||
import { onLoad, onShow } from '@dcloudio/uni-app';
|
import { onLoad, onShow } from '@dcloudio/uni-app';
|
||||||
const { $api, navTo } = inject('globalFunction');
|
const { $api, navTo } = inject('globalFunction');
|
||||||
import useUserStore from '@/stores/useUserStore';
|
import useUserStore from '@/stores/useUserStore';
|
||||||
|
@@ -27,6 +27,8 @@
|
|||||||
</swiper-item>
|
</swiper-item>
|
||||||
</swiper>
|
</swiper>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
<Tabbar :currentpage="3"></Tabbar>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
@@ -34,6 +36,7 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { reactive, inject, watch, ref, onMounted } from 'vue';
|
import { reactive, inject, watch, ref, onMounted } from 'vue';
|
||||||
import { onLoad, onShow } from '@dcloudio/uni-app';
|
import { onLoad, onShow } from '@dcloudio/uni-app';
|
||||||
|
import Tabbar from '@/components/tabbar/midell-box.vue';
|
||||||
import ReadComponent from './read.vue';
|
import ReadComponent from './read.vue';
|
||||||
import UnreadComponent from './unread.vue';
|
import UnreadComponent from './unread.vue';
|
||||||
const loadedMap = reactive([false, false]);
|
const loadedMap = reactive([false, false]);
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
<scroll-view scroll-y class="main-scroll">
|
<scroll-view scroll-y class="main-scroll">
|
||||||
<view class="scrollmain">
|
<view class="scrollmain">
|
||||||
<view
|
<view
|
||||||
class="list-card btn-feel"
|
class="list-card press-button"
|
||||||
v-for="(item, index) in msgList"
|
v-for="(item, index) in msgList"
|
||||||
:key="index"
|
:key="index"
|
||||||
@click="seeDetail(item, index)"
|
@click="seeDetail(item, index)"
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
<scroll-view scroll-y class="main-scroll">
|
<scroll-view scroll-y class="main-scroll">
|
||||||
<view class="scrollmain">
|
<view class="scrollmain">
|
||||||
<view
|
<view
|
||||||
class="list-card btn-feel"
|
class="list-card press-button"
|
||||||
v-for="(item, index) in unreadMsgList"
|
v-for="(item, index) in unreadMsgList"
|
||||||
:key="index"
|
:key="index"
|
||||||
@click="seeDetail(item)"
|
@click="seeDetail(item)"
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="container">
|
<view class="container">
|
||||||
|
<view>
|
||||||
<view class="top">
|
<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">
|
<view class="search-box">
|
||||||
@@ -22,12 +23,48 @@
|
|||||||
</view>
|
</view>
|
||||||
<view class="search-btn button-click" @click="searchBtn">搜索</view>
|
<view class="search-btn button-click" @click="searchBtn">搜索</view>
|
||||||
</view>
|
</view>
|
||||||
<scroll-view scroll-y class="Detailscroll-view" v-show="list.length" @scrolltolower="getJobList('add')">
|
<view class="view-top" v-show="listCom.length || list.length">
|
||||||
<view class="cards-box">
|
<view class="top-item" @click="changeType(0)" :class="{ active: currentTab === 0 }">综合</view>
|
||||||
<renderJobs :list="list" :longitude="longitudeVal" :latitude="latitudeVal"></renderJobs>
|
<view class="top-item" @click="changeType(1)" :class="{ active: currentTab === 1 }">视频</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<scroll-view scroll-y class="Detailscroll-view" v-show="listCom.length" @scrolltolower="choosePosition">
|
||||||
|
<view class="cards-box" v-show="currentTab === 0">
|
||||||
|
<renderJobs :list="listCom" :longitude="longitudeVal" :latitude="latitudeVal"></renderJobs>
|
||||||
|
</view>
|
||||||
|
<view class="cards-box" style="padding-top: 24rpx" v-show="currentTab === 1">
|
||||||
|
<custom-waterfalls-flow
|
||||||
|
ref="waterfallsFlowRef"
|
||||||
|
:column="columnCount"
|
||||||
|
:columnSpace="columnSpace"
|
||||||
|
@loaded="imageloaded"
|
||||||
|
: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">{{ job.companyName }}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
</custom-waterfalls-flow>
|
||||||
|
<loadmore ref="loadmoreRef"></loadmore>
|
||||||
</view>
|
</view>
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
<view class="main-content" v-show="!list.length">
|
<view class="main-content" v-show="!listCom.length">
|
||||||
<view class="content-top">
|
<view class="content-top">
|
||||||
<view class="top-left">历史搜索</view>
|
<view class="top-left">历史搜索</view>
|
||||||
<view class="top-right button-click" @click="remove">
|
<view class="top-right button-click" @click="remove">
|
||||||
@@ -44,16 +81,19 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { inject, ref, reactive } from 'vue';
|
import { inject, ref, reactive, nextTick } from 'vue';
|
||||||
import { onLoad, onShow } from '@dcloudio/uni-app';
|
import { onLoad, onShow } from '@dcloudio/uni-app';
|
||||||
import SelectJobs from '@/components/selectJobs/selectJobs.vue';
|
import SelectJobs from '@/components/selectJobs/selectJobs.vue';
|
||||||
const { $api, navBack } = inject('globalFunction');
|
const { $api, navBack, navTo } = inject('globalFunction');
|
||||||
import useLocationStore from '@/stores/useLocationStore';
|
import useLocationStore from '@/stores/useLocationStore';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
|
import { useColumnCount } from '@/hook/useColumnCount';
|
||||||
|
import { usePagination } from '@/hook/usePagination';
|
||||||
|
import img from '@/static/icon/filter.png';
|
||||||
const { longitudeVal, latitudeVal } = storeToRefs(useLocationStore());
|
const { longitudeVal, latitudeVal } = storeToRefs(useLocationStore());
|
||||||
const searchValue = ref('');
|
const searchValue = ref('');
|
||||||
const historyList = ref([]);
|
const historyList = ref([]);
|
||||||
const list = ref([]);
|
const listCom = ref([]);
|
||||||
const pageState = reactive({
|
const pageState = reactive({
|
||||||
page: 0,
|
page: 0,
|
||||||
total: 0,
|
total: 0,
|
||||||
@@ -63,6 +103,47 @@ const pageState = reactive({
|
|||||||
order: 0,
|
order: 0,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
const isLoaded = ref(false);
|
||||||
|
const waterfallsFlowRef = ref(null);
|
||||||
|
const loadmoreRef = ref(null);
|
||||||
|
const currentTab = ref(0);
|
||||||
|
// 响应式搜索条件(可以被修改)
|
||||||
|
const searchParams = ref({});
|
||||||
|
const pageSize = ref(10);
|
||||||
|
|
||||||
|
const { list, loading, refresh, loadMore } = usePagination(
|
||||||
|
(params) => $api.createRequest('/app/job/littleVideo', params),
|
||||||
|
dataToImg, // 转换函数
|
||||||
|
{
|
||||||
|
pageSize: pageSize,
|
||||||
|
search: searchParams,
|
||||||
|
dataKey: 'data',
|
||||||
|
autoWatchSearch: true,
|
||||||
|
onBeforeRequest: () => {
|
||||||
|
loadmoreRef.value?.change('loading');
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
async function choosePosition(index) {
|
||||||
|
if (currentTab.value === 0) {
|
||||||
|
getJobList('add');
|
||||||
|
} else {
|
||||||
|
loadMore();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function imageloaded() {
|
||||||
|
loadmoreRef.value?.change('more');
|
||||||
|
}
|
||||||
|
|
||||||
|
const { columnCount, columnSpace } = useColumnCount(() => {
|
||||||
|
pageSize.value = 10 * (columnCount.value - 1);
|
||||||
|
nextTick(() => {
|
||||||
|
waterfallsFlowRef.value?.refresh?.();
|
||||||
|
useLocationStore().getLocation();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
onLoad(() => {
|
onLoad(() => {
|
||||||
let arr = uni.getStorageSync('searchList');
|
let arr = uni.getStorageSync('searchList');
|
||||||
@@ -71,6 +152,20 @@ onLoad(() => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function changeType(type) {
|
||||||
|
if (currentTab.value === type) return;
|
||||||
|
switch (type) {
|
||||||
|
case 0:
|
||||||
|
currentTab.value = 0;
|
||||||
|
getJobList('refresh');
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
currentTab.value = 1;
|
||||||
|
refresh();
|
||||||
|
waterfallsFlowRef.value?.refresh?.();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
function searchFn(item) {
|
function searchFn(item) {
|
||||||
searchValue.value = item;
|
searchValue.value = item;
|
||||||
searchBtn();
|
searchBtn();
|
||||||
@@ -83,7 +178,15 @@ function searchBtn() {
|
|||||||
historyList.value.unshift(searchValue.value);
|
historyList.value.unshift(searchValue.value);
|
||||||
historyList.value = unique(historyList.value);
|
historyList.value = unique(historyList.value);
|
||||||
uni.setStorageSync('searchList', historyList.value);
|
uni.setStorageSync('searchList', historyList.value);
|
||||||
|
searchParams.value = {
|
||||||
|
jobTitle: searchValue,
|
||||||
|
};
|
||||||
|
if (currentTab.value === 0) {
|
||||||
getJobList('refresh');
|
getJobList('refresh');
|
||||||
|
} else {
|
||||||
|
refresh();
|
||||||
|
waterfallsFlowRef.value?.refresh?.();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function searchCollection(e) {
|
function searchCollection(e) {
|
||||||
@@ -112,12 +215,25 @@ function remove() {
|
|||||||
historyList.value = [];
|
historyList.value = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function nextDetail(job) {
|
||||||
|
// 记录岗位类型,用作数据分析
|
||||||
|
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`);
|
||||||
|
}
|
||||||
|
|
||||||
function getJobList(type = 'add') {
|
function getJobList(type = 'add') {
|
||||||
if (type === 'add' && pageState.page < pageState.maxPage) {
|
if (type === 'add' && pageState.page < pageState.maxPage) {
|
||||||
pageState.page += 1;
|
pageState.page += 1;
|
||||||
}
|
}
|
||||||
if (type === 'refresh') {
|
if (type === 'refresh') {
|
||||||
list.value = [];
|
|
||||||
pageState.page = 1;
|
pageState.page = 1;
|
||||||
pageState.maxPage = 2;
|
pageState.maxPage = 2;
|
||||||
}
|
}
|
||||||
@@ -132,11 +248,11 @@ function getJobList(type = 'add') {
|
|||||||
const { rows, total } = resData;
|
const { rows, total } = resData;
|
||||||
if (type === 'add') {
|
if (type === 'add') {
|
||||||
const str = pageState.pageSize * (pageState.page - 1);
|
const str = pageState.pageSize * (pageState.page - 1);
|
||||||
const end = list.value.length;
|
const end = listCom.value.length;
|
||||||
const reslist = rows;
|
const reslist = rows;
|
||||||
list.value.splice(str, end, ...reslist);
|
listCom.value.splice(str, end, ...reslist);
|
||||||
} else {
|
} else {
|
||||||
list.value = rows;
|
listCom.value = rows;
|
||||||
}
|
}
|
||||||
pageState.total = resData.total;
|
pageState.total = resData.total;
|
||||||
pageState.maxPage = Math.ceil(pageState.total / pageState.pageSize);
|
pageState.maxPage = Math.ceil(pageState.total / pageState.pageSize);
|
||||||
@@ -147,6 +263,15 @@ function getJobList(type = 'add') {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function dataToImg(data) {
|
||||||
|
return data.map((item) => ({
|
||||||
|
...item,
|
||||||
|
// image: item.cover,
|
||||||
|
image: img,
|
||||||
|
hide: true,
|
||||||
|
}));
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="stylus" scoped>
|
<style lang="stylus" scoped>
|
||||||
@@ -156,12 +281,35 @@ function getJobList(type = 'add') {
|
|||||||
.Detailscroll-view{
|
.Detailscroll-view{
|
||||||
flex: 1
|
flex: 1
|
||||||
overflow: hidden
|
overflow: hidden
|
||||||
|
|
||||||
}
|
}
|
||||||
.container{
|
.container{
|
||||||
display: flex
|
display: flex
|
||||||
flex-direction: column
|
flex-direction: column
|
||||||
background: #F4f4f4
|
background: #F4f4f4
|
||||||
height: calc(100vh - var(--window-top) - var(--status-bar-height) - var(--window-bottom));
|
height: calc(100vh - var(--window-top) - var(--status-bar-height) - var(--window-bottom));
|
||||||
|
.view-top{
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around
|
||||||
|
background: #FFFFFF;
|
||||||
|
.top-item{
|
||||||
|
padding: 6rpx 0 18rpx 0
|
||||||
|
}
|
||||||
|
.active{
|
||||||
|
color: #256BFA;
|
||||||
|
font-weight: 500;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.active::after{
|
||||||
|
position: absolute;
|
||||||
|
content: ''
|
||||||
|
left: calc(50% - 12rpx)
|
||||||
|
bottom: 10rpx
|
||||||
|
width: 24rpx
|
||||||
|
height: 6rpx
|
||||||
|
background: #256BFA
|
||||||
|
}
|
||||||
|
}
|
||||||
.main-content{
|
.main-content{
|
||||||
background: #FFFFFF
|
background: #FFFFFF
|
||||||
height: 100%
|
height: 100%
|
||||||
@@ -244,4 +392,67 @@ function getJobList(type = 'add') {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.slot-item
|
||||||
|
// background: #f4f4f4;
|
||||||
|
background: #FFFFFF;
|
||||||
|
.job-info{
|
||||||
|
padding: 10rpx 24rpx 24rpx 24rpx
|
||||||
|
}
|
||||||
|
.job-image{
|
||||||
|
width: 100%;
|
||||||
|
height: 280rpx;
|
||||||
|
position: relative;
|
||||||
|
.cover-image{
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.cover-triangle{
|
||||||
|
position: absolute;
|
||||||
|
right: 20rpx;
|
||||||
|
top: 20rpx
|
||||||
|
width: 36rpx
|
||||||
|
height: 36rpx
|
||||||
|
border-radius: 50%
|
||||||
|
background: rgba(0,0,0,0.3)
|
||||||
|
}
|
||||||
|
.cover-triangle::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-40%, -50%) rotate(90deg);
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
border-left: 8rpx solid transparent;
|
||||||
|
border-right: 8rpx solid transparent;
|
||||||
|
border-bottom: 12rpx solid #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.salary
|
||||||
|
color: #4C6EFB;
|
||||||
|
font-size: 28rpx
|
||||||
|
display: flex
|
||||||
|
align-items: flex-start
|
||||||
|
justify-content: space-between
|
||||||
|
.flame
|
||||||
|
margin-top: 4rpx
|
||||||
|
margin-right: 4rpx
|
||||||
|
width: 24rpx
|
||||||
|
height: 31rpx
|
||||||
|
.title
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 32rpx;
|
||||||
|
color: #333333;
|
||||||
|
margin-top: 6rpx;
|
||||||
|
white-space: pre-wrap
|
||||||
|
.desc
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #6C7282;
|
||||||
|
margin-top: 6rpx;
|
||||||
</style>
|
</style>
|
||||||
|
BIN
static/.DS_Store
vendored
BIN
static/.DS_Store
vendored
Binary file not shown.
BIN
static/gif/.DS_Store
vendored
Normal file
BIN
static/gif/.DS_Store
vendored
Normal file
Binary file not shown.
BIN
static/gif/indicateArrow.gif
Normal file
BIN
static/gif/indicateArrow.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.4 KiB |
BIN
static/gif/logo.gif
Normal file
BIN
static/gif/logo.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.4 KiB |
BIN
static/imgs/4501750561414_.pic.jpg
Normal file
BIN
static/imgs/4501750561414_.pic.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 248 KiB |
@@ -57,7 +57,7 @@ const useUserStore = defineStore("user", () => {
|
|||||||
hasLogin.value = true;
|
hasLogin.value = true;
|
||||||
userInfo.value = value;
|
userInfo.value = value;
|
||||||
openId.value = value.wxOpenId;
|
openId.value = value.wxOpenId;
|
||||||
token.value = value.token
|
token.value = value.token;
|
||||||
uni.setStorage({
|
uni.setStorage({
|
||||||
key: 'token',
|
key: 'token',
|
||||||
data: value.token
|
data: value.token
|
||||||
|
BIN
unpackage/dist/build/.DS_Store
vendored
BIN
unpackage/dist/build/.DS_Store
vendored
Binary file not shown.
Reference in New Issue
Block a user