200 lines
4.7 KiB
Vue
200 lines
4.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>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { qrSignInGroupCourse } from '@/api/groupCourse.js'
|
|
import { getMemberId } from '@/utils/request.js'
|
|
|
|
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
|
|
}
|
|
// 直接调用扫码签到
|
|
qrScanSignIn()
|
|
} else if (item.path) {
|
|
if (item.isTabBar) {
|
|
uni.switchTab({
|
|
url: item.path
|
|
})
|
|
} else {
|
|
uni.navigateTo({
|
|
url: item.path
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
const qrScanSignIn = () => {
|
|
uni.scanCode({
|
|
onlyFromCamera: true,
|
|
success: async (res) => {
|
|
console.log('扫码结果:', res)
|
|
const qrContent = res.result
|
|
|
|
// 解析二维码内容获取 courseId 和课程名称
|
|
let courseId = null
|
|
let courseName = ''
|
|
try {
|
|
const parsed = JSON.parse(qrContent)
|
|
courseId = Number(parsed.id || parsed.courseId)
|
|
courseName = parsed.courseName || ''
|
|
} catch {
|
|
const num = Number(qrContent)
|
|
if (!isNaN(num)) {
|
|
courseId = num
|
|
}
|
|
}
|
|
|
|
if (!courseId) {
|
|
uni.showToast({ title: '无效的签到二维码', icon: 'none' })
|
|
return
|
|
}
|
|
|
|
const memberId = getMemberId()
|
|
if (!memberId) {
|
|
uni.showToast({ title: '请先登录', icon: 'none' })
|
|
return
|
|
}
|
|
|
|
uni.showLoading({ title: '签到中...' })
|
|
try {
|
|
const result = await qrSignInGroupCourse(courseId, memberId)
|
|
uni.hideLoading()
|
|
if (result.success) {
|
|
uni.showToast({ title: courseName ? `「${courseName}」签到成功` : '签到成功', icon: 'success' })
|
|
setTimeout(() => {
|
|
uni.navigateTo({ url: '/pages/memberInfo/myCourses' })
|
|
}, 1200)
|
|
} else {
|
|
uni.showToast({ title: result.message || '签到失败', icon: 'none', duration: 3000 })
|
|
}
|
|
} catch (e) {
|
|
uni.hideLoading()
|
|
console.error('团课签到失败:', e)
|
|
let errMsg = e?.message || e?.data?.message || '签到失败'
|
|
// 附加课程名称(如果已知)
|
|
if (courseName && !errMsg.includes(courseName)) {
|
|
errMsg = `「${courseName}」${errMsg}`
|
|
}
|
|
uni.showToast({ title: errMsg, icon: 'none', duration: 3000 })
|
|
}
|
|
},
|
|
fail: (err) => {
|
|
console.error('扫码失败:', err)
|
|
}
|
|
})
|
|
}
|
|
|
|
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: #FFFFFF;
|
|
margin: 24rpx;
|
|
border-radius: 28rpx;
|
|
box-shadow: 0 8rpx 32rpx rgba(45,74,90,0.08);
|
|
}
|
|
|
|
.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);
|
|
}
|
|
</style> |