274 lines
5.7 KiB
Vue
274 lines
5.7 KiB
Vue
<template>
|
|
<view class="quick-entry">
|
|
<view
|
|
v-for="(item, index) in entries"
|
|
:key="index"
|
|
class="entry-item"
|
|
@tap="handleEntryClick(item)"
|
|
>
|
|
<view :class="['entry-icon', { accent: item.accent }]">
|
|
<image :src="item.icon" mode="aspectFit" class="icon-img" />
|
|
</view>
|
|
<text class="entry-title">{{ item.title }}</text>
|
|
<text class="entry-desc">{{ item.desc }}</text>
|
|
</view>
|
|
|
|
<view v-if="showCheckInMenu" class="checkin-menu-overlay" @tap="showCheckInMenu = false">
|
|
<view class="checkin-menu" @tap.stop>
|
|
<view class="menu-item" @tap="handleStoreCheckIn">
|
|
<image src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/icons/checkIn.png" mode="aspectFit" class="menu-icon" />
|
|
<text class="menu-text">到店签到</text>
|
|
</view>
|
|
<view class="menu-item" @tap="handleGroupCourseCheckIn">
|
|
<image src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/icons/course.png" mode="aspectFit" class="menu-icon" />
|
|
<text class="menu-text">团课签到</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref } from 'vue'
|
|
|
|
const showCheckInMenu = ref(false)
|
|
|
|
const handleEntryClick = (item) => {
|
|
if (item.title === '签到') {
|
|
const token = uni.getStorageSync('token')
|
|
if (!token) {
|
|
uni.showModal({
|
|
title: '请登录',
|
|
content: '是否跳转到登录页面?',
|
|
confirmText: '确定',
|
|
cancelText: '取消',
|
|
confirmColor: '#FF6B35',
|
|
success: (res) => {
|
|
if (res.confirm) {
|
|
uni.navigateTo({
|
|
url: '/pages/login/login'
|
|
})
|
|
}
|
|
}
|
|
})
|
|
return
|
|
}
|
|
showCheckInMenu.value = !showCheckInMenu.value
|
|
} else if (item.path) {
|
|
if (item.isTabBar) {
|
|
uni.switchTab({
|
|
url: item.path
|
|
})
|
|
} else {
|
|
uni.navigateTo({
|
|
url: item.path
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
const handleStoreCheckIn = () => {
|
|
showCheckInMenu.value = false
|
|
uni.navigateTo({
|
|
url: '/pages/checkIn/checkIn'
|
|
})
|
|
}
|
|
|
|
const handleGroupCourseCheckIn = () => {
|
|
showCheckInMenu.value = false
|
|
uni.scanCode({
|
|
onlyFromCamera: true,
|
|
success: (res) => {
|
|
console.log('扫码结果:', res)
|
|
uni.showToast({
|
|
title: '扫码成功',
|
|
icon: 'success'
|
|
})
|
|
},
|
|
fail: (err) => {
|
|
console.error('扫码失败:', err)
|
|
uni.showToast({
|
|
title: '扫码失败',
|
|
icon: 'none'
|
|
})
|
|
}
|
|
})
|
|
}
|
|
|
|
const entries = [
|
|
{
|
|
icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/icons/course.png',
|
|
title: '找课程',
|
|
desc: '精品课程',
|
|
accent: false,
|
|
path: "/pages/groupCourse/list"
|
|
},
|
|
{
|
|
icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/icons/checkIn.png',
|
|
title: '签到',
|
|
desc: '打卡签到',
|
|
accent: false,
|
|
path: "/pages/checkIn/checkIn"
|
|
}
|
|
]
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.quick-entry {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
padding: 32rpx 24rpx;
|
|
background: rgba(255, 255, 255, 0.55);
|
|
backdrop-filter: blur(24px);
|
|
-webkit-backdrop-filter: blur(24px);
|
|
margin: 24rpx;
|
|
border-radius: 28rpx;
|
|
box-shadow: 0 8rpx 32rpx var(--shadow-blue-light);
|
|
border: 1rpx solid rgba(255, 255, 255, 0.7);
|
|
position: relative;
|
|
z-index: 3;
|
|
}
|
|
|
|
.entry-item {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
flex: 1;
|
|
}
|
|
|
|
.entry-icon {
|
|
width: 104rpx;
|
|
height: 104rpx;
|
|
border-radius: 24rpx;
|
|
background: rgba(130, 220, 130, 0.9);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
margin-bottom: 16rpx;
|
|
box-shadow: 0 6rpx 20rpx rgba(130, 220, 130, 0.35);
|
|
position: relative;
|
|
}
|
|
|
|
.badge-dot {
|
|
position: absolute;
|
|
top: 8rpx;
|
|
right: 8rpx;
|
|
width: 16rpx;
|
|
height: 16rpx;
|
|
background: linear-gradient(135deg, #FF4757, #FF2D55);
|
|
border-radius: 50%;
|
|
box-shadow: 0 2rpx 8rpx rgba(255, 71, 87, 0.5);
|
|
z-index: 99;
|
|
animation: pulse 2s infinite;
|
|
}
|
|
|
|
.icon-img {
|
|
width: 52rpx;
|
|
height: 52rpx;
|
|
}
|
|
|
|
.entry-icon.accent {
|
|
background: rgba(130, 220, 130, 0.9);
|
|
}
|
|
|
|
.entry-title {
|
|
font-size: 26rpx;
|
|
font-weight: 600;
|
|
color: #2D4A5A;
|
|
margin-bottom: 4rpx;
|
|
}
|
|
|
|
.entry-desc {
|
|
font-size: 22rpx;
|
|
color: var(--tabbar-text-inactive);
|
|
}
|
|
|
|
.checkin-menu-overlay {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
z-index: 1000;
|
|
display: flex;
|
|
align-items: flex-start;
|
|
justify-content: flex-end;
|
|
padding-top: 280rpx;
|
|
padding-right: 60rpx;
|
|
animation: fadeIn 0.2s ease;
|
|
}
|
|
|
|
@keyframes fadeIn {
|
|
from { opacity: 0; }
|
|
to { opacity: 1; }
|
|
}
|
|
|
|
@keyframes pulse {
|
|
0%, 100% { opacity: 1; }
|
|
50% { opacity: 0.5; }
|
|
}
|
|
|
|
.checkin-menu {
|
|
position: absolute;
|
|
right: 0;
|
|
top: 140rpx;
|
|
background: white;
|
|
border-radius: 24rpx;
|
|
box-shadow: 0 16rpx 48rpx rgba(0, 0, 0, 0.15);
|
|
padding: 16rpx;
|
|
min-width: 320rpx;
|
|
animation: slideDown 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
|
|
&::before {
|
|
content: '';
|
|
position: absolute;
|
|
top: -24rpx;
|
|
right: 60rpx;
|
|
width: 0;
|
|
height: 0;
|
|
border-left: 24rpx solid transparent;
|
|
border-right: 24rpx solid transparent;
|
|
border-bottom: 24rpx solid white;
|
|
}
|
|
}
|
|
|
|
@keyframes slideDown {
|
|
from {
|
|
opacity: 0;
|
|
transform: translateY(-40rpx) scale(0.95);
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
transform: translateY(0) scale(1);
|
|
}
|
|
}
|
|
|
|
.menu-item {
|
|
display: flex;
|
|
align-items: center;
|
|
padding: 24rpx 32rpx;
|
|
border-radius: 16rpx;
|
|
transition: all 0.2s ease;
|
|
|
|
&:active {
|
|
background: rgba(0, 0, 0, 0.04);
|
|
transform: scale(0.98);
|
|
}
|
|
|
|
& + .menu-item {
|
|
margin-top: 8rpx;
|
|
}
|
|
}
|
|
|
|
.menu-icon {
|
|
width: 48rpx;
|
|
height: 48rpx;
|
|
margin-right: 20rpx;
|
|
}
|
|
|
|
.menu-text {
|
|
font-size: 30rpx;
|
|
font-weight: 600;
|
|
color: #2D4A5A;
|
|
}
|
|
</style> |