775 lines
19 KiB
Vue
775 lines
19 KiB
Vue
<template>
|
|
<scroll-view class="mine-page" scroll-y :scroll-with-animation="true"
|
|
:style="{ paddingBottom: safeAreaBottom + 'px' }">
|
|
<view class="mine-container">
|
|
<!-- 用户信息头部 -->
|
|
<view class="profile-card">
|
|
<view class="profile-bg" />
|
|
<view class="profile-content">
|
|
<view class="profile-avatar-wrap" @click="handleEditProfile">
|
|
<image v-if="displayAvatarUrl" class="avatar-img" :src="displayAvatarUrl" mode="aspectFill" />
|
|
<view v-else class="avatar-placeholder">
|
|
<TnIcon name="my-circle" :size="80" color="#FFFFFF" />
|
|
</view>
|
|
<view class="avatar-edit-badge">
|
|
<TnIcon name="edit-write-fill" :size="24" color="#fff" />
|
|
</view>
|
|
</view>
|
|
<text class="profile-name" @click="handleEditProfile">
|
|
{{ userInfo.nickName || '铲屎官' }}
|
|
</text>
|
|
<view class="profile-member-row">
|
|
<view class="member-type-card" @click="handleGoMember">
|
|
<TnIcon :name="userInfo.membershipType === 'premium' ? 'vip-fill' : 'vip'" :size="36"
|
|
:color="userInfo.membershipType === 'premium' ? '#F59E0B' : '#94A3B8'" />
|
|
<view class="member-type-info">
|
|
<text class="member-type-name">
|
|
{{ userInfo.membershipType === 'premium' ? '高级会员' : '免费用户' }}
|
|
</text>
|
|
<text class="member-type-hint">
|
|
{{ userInfo.membershipType === 'premium'
|
|
? (userInfo.memberExpireAt ? '有效期至 ' + formatDate(userInfo.memberExpireAt) : '')
|
|
: '立即升级享更多权益' }}
|
|
</text>
|
|
</view>
|
|
<TnIcon name="right" :size="28" color="rgba(255,255,255,0.6)" />
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 数据统计卡片 -->
|
|
<view class="stats-section">
|
|
<view class="stats-card" @click="handleGoMyPets">
|
|
<view class="stats-icon-wrap">
|
|
<TnIcon name="floral" :size="36" color="#F97316" />
|
|
</view>
|
|
<text class="stats-value">{{ statsData.petCount }}</text>
|
|
<text class="stats-label">我的萌宠</text>
|
|
</view>
|
|
<view class="stats-card" @click="handleGoRecords">
|
|
<view class="stats-icon-wrap">
|
|
<TnIcon name="write" :size="36" color="#14B8A6" />
|
|
</view>
|
|
<text class="stats-value">{{ statsData.recordCount }}</text>
|
|
<text class="stats-label">健康记录</text>
|
|
</view>
|
|
<view class="stats-card" @click="handleGoSchedules">
|
|
<view class="stats-icon-wrap">
|
|
<TnIcon name="calendar" :size="36" color="#8B5CF6" />
|
|
</view>
|
|
<text class="stats-value">{{ statsData.scheduleCount }}</text>
|
|
<text class="stats-label">待办提醒</text>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 快捷操作 -->
|
|
<view class="section-block">
|
|
<text class="section-title">快捷操作</text>
|
|
<view class="quick-grid">
|
|
<view class="quick-item" @click="handleAddPet">
|
|
<view class="quick-icon" style="background: linear-gradient(135deg, #F97316, #FB923C)">
|
|
<TnIcon name="add-lack" :size="44" color="#FFFFFF" />
|
|
</view>
|
|
<text class="quick-label">添加宠物</text>
|
|
</view>
|
|
<view class="quick-item" @click="handleAddRecord">
|
|
<view class="quick-icon" style="background: linear-gradient(135deg, #2DD4BF, #0D9488)">
|
|
<TnIcon name="write-feather" :size="44" color="#FFFFFF" />
|
|
</view>
|
|
<text class="quick-label">健康记录</text>
|
|
</view>
|
|
<view class="quick-item" @click="handleAddSchedule">
|
|
<view class="quick-icon" style="background: linear-gradient(135deg, #8B5CF6, #7C3AED)">
|
|
<TnIcon name="notice-fill" :size="44" color="#FFFFFF" />
|
|
</view>
|
|
<text class="quick-label">添加提醒</text>
|
|
</view>
|
|
<view class="quick-item" @click="handleNearbyHospital">
|
|
<view class="quick-icon" style="background: linear-gradient(135deg, #EC4899, #DB2777)">
|
|
<TnIcon name="safe-fill" :size="44" color="#FFFFFF" />
|
|
</view>
|
|
<text class="quick-label">附近医院</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 宠物管理 -->
|
|
<view class="section-block">
|
|
<text class="section-title">宠物管理</text>
|
|
<view class="menu-card">
|
|
<view class="menu-row" @click="handleGoMyPets">
|
|
<view class="menu-icon-wrap" style="background: #FFF7ED">
|
|
<TnIcon name="floral" :size="38" color="#F97316" />
|
|
</view>
|
|
<text class="menu-text">我的宠物</text>
|
|
<TnIcon name="right" :size="28" color="#CBD5E1" />
|
|
</view>
|
|
<view class="menu-divider" />
|
|
<view class="menu-row" @click="handleGoPetAlbum">
|
|
<view class="menu-icon-wrap" style="background: #FFF7ED">
|
|
<TnIcon name="eye-fill" :size="38" color="#FB923C" />
|
|
</view>
|
|
<text class="menu-text">宠物相册</text>
|
|
<TnIcon name="right" :size="28" color="#CBD5E1" />
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 数据服务 -->
|
|
<view class="section-block">
|
|
<text class="section-title">数据服务</text>
|
|
<view class="menu-card">
|
|
<view class="menu-row" @click="handleGoHealthData">
|
|
<view class="menu-icon-wrap" style="background: #F0FDFA">
|
|
<TnIcon name="data-fill" :size="38" color="#14B8A6" />
|
|
</view>
|
|
<text class="menu-text">健康数据总览</text>
|
|
<text class="menu-badge">NEW</text>
|
|
<TnIcon name="right" :size="28" color="#CBD5E1" />
|
|
</view>
|
|
<view class="menu-divider" />
|
|
<view class="menu-row" @click="handleExportData">
|
|
<view class="menu-icon-wrap" style="background: #ECFEFF">
|
|
<TnIcon name="folder-upload" :size="38" color="#06B6D4" />
|
|
</view>
|
|
<text class="menu-text">数据导出</text>
|
|
<TnTag type="warning" size="sm" shape="round">会员</TnTag>
|
|
<TnIcon name="right" :size="28" color="#CBD5E1" />
|
|
</view>
|
|
<view class="menu-divider" />
|
|
<view class="menu-row" @click="handleCloudBackup">
|
|
<view class="menu-icon-wrap" style="background: #EFF6FF">
|
|
<TnIcon name="cloud-fill" :size="38" color="#3B82F6" />
|
|
</view>
|
|
<text class="menu-text">云端备份</text>
|
|
<text class="menu-extra">已备份</text>
|
|
<TnIcon name="right" :size="28" color="#CBD5E1" />
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 会员服务 -->
|
|
<view class="section-block">
|
|
<text class="section-title">会员服务</text>
|
|
<view class="menu-card">
|
|
<view class="menu-row" @click="handleGoMember">
|
|
<view class="menu-icon-wrap" style="background: #FFFBEB">
|
|
<TnIcon name="vip-fill" :size="38" color="#F59E0B" />
|
|
</view>
|
|
<text class="menu-text">会员中心</text>
|
|
<TnTag type="danger" size="sm" shape="round">限时优惠</TnTag>
|
|
<TnIcon name="right" :size="28" color="#CBD5E1" />
|
|
</view>
|
|
<view class="menu-divider" />
|
|
<view class="menu-row" @click="handleShare">
|
|
<view class="menu-icon-wrap" style="background: #F5F3FF">
|
|
<TnIcon name="share" :size="38" color="#8B5CF6" />
|
|
</view>
|
|
<text class="menu-text">推荐给朋友</text>
|
|
<TnIcon name="right" :size="28" color="#CBD5E1" />
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 其他 -->
|
|
<view class="section-block">
|
|
<text class="section-title">其他</text>
|
|
<view class="menu-card">
|
|
<view class="menu-row" @click="handleGoSettings">
|
|
<view class="menu-icon-wrap" style="background: #F8FAFC">
|
|
<TnIcon name="menu-set" :size="38" color="#475569" />
|
|
</view>
|
|
<text class="menu-text">设置</text>
|
|
<TnIcon name="right" :size="28" color="#CBD5E1" />
|
|
</view>
|
|
<view class="menu-divider" />
|
|
<view class="menu-row" @click="handleGoAbout">
|
|
<view class="menu-icon-wrap" style="background: #F8FAFC">
|
|
<TnIcon name="copyright" :size="38" color="#64748B" />
|
|
</view>
|
|
<text class="menu-text">关于毛球</text>
|
|
<TnIcon name="right" :size="28" color="#CBD5E1" />
|
|
</view>
|
|
<view class="menu-divider" />
|
|
<view class="menu-row" @click="handleFeedback">
|
|
<view class="menu-icon-wrap" style="background: #F8FAFC">
|
|
<TnIcon name="service" :size="38" color="#64748B" />
|
|
</view>
|
|
<text class="menu-text">帮助与反馈</text>
|
|
<TnIcon name="right" :size="28" color="#CBD5E1" />
|
|
</view>
|
|
<view class="menu-divider" />
|
|
<view class="menu-row" @click="handleGoLogin">
|
|
<view class="menu-icon-wrap" style="background: #FFF7ED">
|
|
<TnIcon name="my-circle" :size="38" color="#F97316" />
|
|
</view>
|
|
<text class="menu-text">登录 / 退出登录</text>
|
|
<TnIcon name="right" :size="28" color="#CBD5E1" />
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 底部版权 -->
|
|
<view class="footer-section">
|
|
<TnIcon name="floral" :size="44" color="#F97316" />
|
|
<text class="footer-name">毛球手账 v1.0.0</text>
|
|
<text class="footer-slogan">让宠物健康管理像记账一样简单</text>
|
|
</view>
|
|
</view>
|
|
</scroll-view>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, reactive, onMounted } from 'vue'
|
|
import { onShow } from '@dcloudio/uni-app'
|
|
import TnIcon from '@/uni_modules/tuniaoui-vue3/components/icon/src/icon.vue'
|
|
|
|
interface UserInfo {
|
|
avatarUrl: string
|
|
nickName: string
|
|
membershipType: 'free' | 'premium'
|
|
memberExpireAt: string
|
|
}
|
|
|
|
const safeAreaBottom = ref(0)
|
|
const displayAvatarUrl = ref('')
|
|
|
|
const userInfo = reactive<UserInfo>({
|
|
avatarUrl: '',
|
|
nickName: '',
|
|
membershipType: 'free',
|
|
memberExpireAt: '',
|
|
})
|
|
|
|
const statsData = reactive({
|
|
petCount: 0,
|
|
recordCount: 0,
|
|
scheduleCount: 0,
|
|
})
|
|
|
|
onMounted(() => {
|
|
loadUserInfo()
|
|
loadStats()
|
|
calcSafeArea()
|
|
})
|
|
|
|
onShow(() => {
|
|
loadUserInfo()
|
|
loadStats()
|
|
})
|
|
|
|
function calcSafeArea() {
|
|
const systemInfo = uni.getSystemInfoSync()
|
|
safeAreaBottom.value = (systemInfo.safeAreaInsets?.bottom || 0) + 78
|
|
}
|
|
|
|
function formatDate(dateStr: string) {
|
|
if (!dateStr) return ''
|
|
const d = new Date(dateStr)
|
|
if (Number.isNaN(d.getTime())) return dateStr
|
|
const y = d.getFullYear()
|
|
const m = String(d.getMonth() + 1).padStart(2, '0')
|
|
const day = String(d.getDate()).padStart(2, '0')
|
|
return `${y}-${m}-${day}`
|
|
}
|
|
|
|
async function loadUserInfo() {
|
|
try {
|
|
const uid = uni.getStorageSync('uid')
|
|
const res = await uniCloud.callFunction({
|
|
name: 'userManager',
|
|
data: { action: 'profile', uid },
|
|
})
|
|
if (res.result?.code === 0 && res.result.data) {
|
|
const data = res.result.data
|
|
userInfo.avatarUrl = data.avatarUrl || ''
|
|
userInfo.nickName = data.nickName || ''
|
|
userInfo.membershipType = data.membership?.type || 'free'
|
|
userInfo.memberExpireAt = data.membership?.expireAt || ''
|
|
await resolveMineAvatar()
|
|
return
|
|
}
|
|
} catch (e) {
|
|
console.warn('云函数加载用户信息失败,使用本地缓存', e)
|
|
}
|
|
const cached = uni.getStorageSync('userInfo')
|
|
if (cached) {
|
|
userInfo.avatarUrl = cached.avatarUrl || ''
|
|
userInfo.nickName = cached.nickName || '铲屎官'
|
|
userInfo.membershipType = cached.membership?.type || 'free'
|
|
userInfo.memberExpireAt = cached.membership?.expireAt || ''
|
|
await resolveMineAvatar()
|
|
}
|
|
}
|
|
|
|
async function resolveMineAvatar() {
|
|
const url = userInfo.avatarUrl
|
|
if (!url) {
|
|
displayAvatarUrl.value = ''
|
|
return
|
|
}
|
|
if (url.startsWith('cloud://')) {
|
|
try {
|
|
const res = await uniCloud.getTempFileURL({ fileList: [url] })
|
|
if (res.fileList && res.fileList[0]?.tempFileURL) {
|
|
displayAvatarUrl.value = res.fileList[0].tempFileURL
|
|
}
|
|
} catch (e) {
|
|
console.warn('获取头像临时URL失败', e)
|
|
displayAvatarUrl.value = ''
|
|
}
|
|
} else {
|
|
displayAvatarUrl.value = url
|
|
}
|
|
}
|
|
|
|
async function loadStats() {
|
|
try {
|
|
const uid = uni.getStorageSync('uid')
|
|
const res = await uniCloud.callFunction({
|
|
name: 'userManager',
|
|
data: { action: 'stats', uid },
|
|
})
|
|
if (res.result?.code === 0 && res.result.data) {
|
|
const data = res.result.data
|
|
statsData.petCount = data.petCount ?? 0
|
|
statsData.recordCount = data.recordCount ?? 0
|
|
statsData.scheduleCount = data.pendingScheduleCount ?? 0
|
|
}
|
|
} catch (e) {
|
|
console.warn('加载统计数据失败,使用默认值', e)
|
|
}
|
|
}
|
|
|
|
function handleEditProfile() {
|
|
uni.navigateTo({ url: '/pages/mine/profile-edit' })
|
|
}
|
|
|
|
function handleGoMember() {
|
|
uni.navigateTo({ url: '/pages/mine/member' })
|
|
}
|
|
|
|
function handleGoMyPets() {
|
|
uni.switchTab({ url: '/pages/index/index' })
|
|
}
|
|
|
|
function handleGoRecords() {
|
|
uni.switchTab({ url: '/pages/index/index' })
|
|
}
|
|
|
|
function handleGoSchedules() {
|
|
uni.switchTab({ url: '/pages/index/index' })
|
|
}
|
|
|
|
function handleAddPet() {
|
|
uni.navigateTo({ url: '/pages/pet/edit' })
|
|
}
|
|
|
|
function handleAddRecord() {
|
|
uni.navigateTo({ url: '/pages/record/type-select' })
|
|
}
|
|
|
|
function handleAddSchedule() {
|
|
uni.navigateTo({ url: '/pages/schedule/edit' })
|
|
}
|
|
|
|
function handleNearbyHospital() {
|
|
uni.navigateTo({ url: '/pages/discovery/hospital-list' })
|
|
}
|
|
|
|
function handleGoPetAlbum() {
|
|
uni.showToast({ title: '即将上线,敬请期待', icon: 'none' })
|
|
}
|
|
|
|
function handleGoHealthData() {
|
|
uni.showToast({ title: '即将上线,敬请期待', icon: 'none' })
|
|
}
|
|
|
|
function handleExportData() {
|
|
if (userInfo.membershipType !== 'premium') {
|
|
uni.showModal({
|
|
title: '会员功能',
|
|
content: '数据导出为高级会员专属功能,是否前往开通?',
|
|
success: (res) => {
|
|
if (res.confirm) {
|
|
handleGoMember()
|
|
}
|
|
},
|
|
})
|
|
return
|
|
}
|
|
uni.showToast({ title: '即将上线,敬请期待', icon: 'none' })
|
|
}
|
|
|
|
function handleCloudBackup() {
|
|
uni.showToast({ title: '数据已自动备份至云端', icon: 'none' })
|
|
}
|
|
|
|
function handleShare() {
|
|
uni.showToast({ title: '即将上线,敬请期待', icon: 'none' })
|
|
}
|
|
|
|
function handleGoSettings() {
|
|
uni.navigateTo({ url: '/pages/mine/settings' })
|
|
}
|
|
|
|
function handleGoAbout() {
|
|
uni.navigateTo({ url: '/pages/mine/about' })
|
|
}
|
|
|
|
function handleFeedback() {
|
|
uni.navigateTo({ url: '/pages/mine/feedback' })
|
|
}
|
|
|
|
function handleGoLogin() {
|
|
const token = uni.getStorageSync('token')
|
|
if (token) {
|
|
uni.showModal({
|
|
title: '提示',
|
|
content: '确定要退出当前账号吗?',
|
|
success: (res) => {
|
|
if (res.confirm) {
|
|
uni.removeStorageSync('token')
|
|
uni.removeStorageSync('uid')
|
|
uni.removeStorageSync('userInfo')
|
|
uni.reLaunch({ url: '/pages/login/login' })
|
|
}
|
|
},
|
|
})
|
|
} else {
|
|
uni.reLaunch({ url: '/pages/login/login' })
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
$primary: #F97316;
|
|
$primary-light: #FB923C;
|
|
$primary-bg: #FFF7ED;
|
|
$text-dark: #1E293B;
|
|
$text-body: #475569;
|
|
$text-muted: #94A3B8;
|
|
$card-bg: #FFFFFF;
|
|
$border-color: #F1F5F9;
|
|
$shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.04);
|
|
$radius-xl: 32rpx;
|
|
$radius-lg: 24rpx;
|
|
|
|
.mine-page {
|
|
height: 100vh;
|
|
background-color: #F8FAFC;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.mine-container {
|
|
padding: 0 28rpx 28rpx;
|
|
}
|
|
|
|
// === 个人资料卡 ===
|
|
.profile-card {
|
|
position: relative;
|
|
margin-top: 24rpx;
|
|
border-radius: $radius-xl;
|
|
overflow: hidden;
|
|
box-shadow: 0 8rpx 32rpx rgba(249, 115, 22, 0.12);
|
|
}
|
|
|
|
.profile-bg {
|
|
position: absolute;
|
|
inset: 0;
|
|
background: linear-gradient(145deg, #F97316 0%, #FB923C 60%, #FDBA74 100%);
|
|
|
|
&::after {
|
|
content: '';
|
|
position: absolute;
|
|
top: -40rpx;
|
|
right: -60rpx;
|
|
width: 260rpx;
|
|
height: 260rpx;
|
|
border-radius: 50%;
|
|
background: rgba(255, 255, 255, 0.1);
|
|
}
|
|
|
|
&::before {
|
|
content: '';
|
|
position: absolute;
|
|
bottom: -30rpx;
|
|
left: -30rpx;
|
|
width: 160rpx;
|
|
height: 160rpx;
|
|
border-radius: 50%;
|
|
background: rgba(255, 255, 255, 0.06);
|
|
}
|
|
}
|
|
|
|
.profile-content {
|
|
position: relative;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
padding: 48rpx 32rpx 40rpx;
|
|
gap: 16rpx;
|
|
}
|
|
|
|
.profile-avatar-wrap {
|
|
position: relative;
|
|
width: 160rpx;
|
|
height: 160rpx;
|
|
}
|
|
|
|
.avatar-img {
|
|
width: 160rpx;
|
|
height: 160rpx;
|
|
border-radius: 50%;
|
|
border: 6rpx solid rgba(255, 255, 255, 0.6);
|
|
box-shadow: 0 8rpx 20rpx rgba(124, 45, 18, 0.2);
|
|
}
|
|
|
|
.avatar-placeholder {
|
|
width: 160rpx;
|
|
height: 160rpx;
|
|
border-radius: 50%;
|
|
border: 6rpx solid rgba(255, 255, 255, 0.6);
|
|
background: rgba(255, 255, 255, 0.15);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
.avatar-edit-badge {
|
|
position: absolute;
|
|
bottom: 0;
|
|
right: 0;
|
|
width: 44rpx;
|
|
height: 44rpx;
|
|
border-radius: 50%;
|
|
background: linear-gradient(135deg, #FB923C, #F97316);
|
|
border: 4rpx solid #FFFFFF;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
box-shadow: 0 4rpx 8rpx rgba(124, 45, 18, 0.2);
|
|
}
|
|
|
|
.profile-name {
|
|
font-size: 40rpx;
|
|
font-weight: 800;
|
|
color: #FFFFFF;
|
|
line-height: 1.3;
|
|
text-shadow: 0 2rpx 8rpx rgba(124, 45, 18, 0.15);
|
|
}
|
|
|
|
.profile-member-row {
|
|
width: 100%;
|
|
margin-top: 8rpx;
|
|
}
|
|
|
|
.member-type-card {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 16rpx;
|
|
padding: 18rpx 24rpx;
|
|
background: rgba(255, 255, 255, 0.18);
|
|
backdrop-filter: blur(10rpx);
|
|
border-radius: 20rpx;
|
|
border: 1rpx solid rgba(255, 255, 255, 0.25);
|
|
}
|
|
|
|
.member-type-info {
|
|
flex: 1;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 4rpx;
|
|
}
|
|
|
|
.member-type-name {
|
|
font-size: 26rpx;
|
|
font-weight: 700;
|
|
color: #FFFFFF;
|
|
}
|
|
|
|
.member-type-hint {
|
|
font-size: 20rpx;
|
|
color: rgba(255, 255, 255, 0.8);
|
|
}
|
|
|
|
// === 数据统计 ===
|
|
.stats-section {
|
|
display: flex;
|
|
gap: 16rpx;
|
|
margin-top: 24rpx;
|
|
}
|
|
|
|
.stats-card {
|
|
flex: 1;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
gap: 8rpx;
|
|
padding: 24rpx 12rpx;
|
|
background-color: $card-bg;
|
|
border-radius: $radius-lg;
|
|
box-shadow: $shadow;
|
|
transition: transform 0.2s ease;
|
|
|
|
&:active {
|
|
transform: scale(0.97);
|
|
}
|
|
}
|
|
|
|
.stats-icon-wrap {
|
|
width: 56rpx;
|
|
height: 56rpx;
|
|
border-radius: 50%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
background: $primary-bg;
|
|
}
|
|
|
|
.stats-value {
|
|
font-size: 40rpx;
|
|
font-weight: 800;
|
|
color: $text-dark;
|
|
line-height: 1;
|
|
}
|
|
|
|
.stats-label {
|
|
font-size: 22rpx;
|
|
font-weight: 500;
|
|
color: $text-muted;
|
|
}
|
|
|
|
// === 快捷操作 & 分区 ===
|
|
.section-block {
|
|
margin-top: 36rpx;
|
|
}
|
|
|
|
.section-title {
|
|
font-size: 30rpx;
|
|
font-weight: 800;
|
|
color: $text-dark;
|
|
margin-bottom: 16rpx;
|
|
padding-left: 4rpx;
|
|
}
|
|
|
|
.quick-grid {
|
|
display: flex;
|
|
gap: 16rpx;
|
|
}
|
|
|
|
.quick-item {
|
|
flex: 1;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
gap: 12rpx;
|
|
padding: 24rpx 8rpx;
|
|
background-color: $card-bg;
|
|
border-radius: $radius-lg;
|
|
box-shadow: $shadow;
|
|
transition: transform 0.2s ease;
|
|
|
|
&:active {
|
|
transform: scale(0.96);
|
|
}
|
|
}
|
|
|
|
.quick-icon {
|
|
width: 80rpx;
|
|
height: 80rpx;
|
|
border-radius: 22rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
box-shadow: 0 6rpx 16rpx rgba(0, 0, 0, 0.1);
|
|
}
|
|
|
|
.quick-label {
|
|
font-size: 22rpx;
|
|
font-weight: 600;
|
|
color: $text-body;
|
|
text-align: center;
|
|
}
|
|
|
|
// === 菜单卡片 ===
|
|
.menu-card {
|
|
background-color: $card-bg;
|
|
border-radius: $radius-lg;
|
|
box-shadow: $shadow;
|
|
overflow: hidden;
|
|
padding: 0 24rpx;
|
|
}
|
|
|
|
.menu-row {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 20rpx;
|
|
padding: 24rpx 0;
|
|
|
|
&:active {
|
|
opacity: 0.7;
|
|
}
|
|
}
|
|
|
|
.menu-divider {
|
|
height: 1rpx;
|
|
background: $border-color;
|
|
margin-left: 88rpx;
|
|
}
|
|
|
|
.menu-icon-wrap {
|
|
width: 64rpx;
|
|
height: 64rpx;
|
|
border-radius: 16rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.menu-text {
|
|
flex: 1;
|
|
font-size: 28rpx;
|
|
font-weight: 500;
|
|
color: $text-dark;
|
|
}
|
|
|
|
.menu-badge {
|
|
font-size: 18rpx;
|
|
font-weight: 700;
|
|
color: #FFFFFF;
|
|
background: linear-gradient(135deg, #F97316, #FB923C);
|
|
padding: 4rpx 12rpx;
|
|
border-radius: 12rpx;
|
|
}
|
|
|
|
.menu-extra {
|
|
font-size: 24rpx;
|
|
color: #22C55E;
|
|
font-weight: 500;
|
|
}
|
|
|
|
// === 底部 ===
|
|
.footer-section {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
gap: 8rpx;
|
|
margin-top: 40rpx;
|
|
padding-bottom: 20rpx;
|
|
}
|
|
|
|
.footer-name {
|
|
font-size: 22rpx;
|
|
font-weight: 600;
|
|
color: $text-muted;
|
|
}
|
|
|
|
.footer-slogan {
|
|
font-size: 20rpx;
|
|
color: #CBD5E1;
|
|
}
|
|
</style>
|