feat: migrate comprehensive venue module

This commit is contained in:
gqt
2026-06-08 20:54:25 +08:00
parent c9650b0db1
commit 8e1443f7e5
43 changed files with 5017 additions and 0 deletions
@@ -0,0 +1,453 @@
<template>
<view class="profile-page container">
<view v-if="!session.isLoggedIn" class="unlogged">
<text class="brand">星河综合运动中心</text>
<text class="desc">登录后查看余额订单门票权益与个人资料</text>
<button class="primary-button login-btn" @tap="login">微信一键登录</button>
</view>
<block v-else>
<view class="user-profile-hero" @tap="go('/pages/comprehensive/profile/detail')">
<view class="hero-left">
<image v-if="session.member?.avatar_url" :src="session.member.avatar_url" mode="aspectFill" class="hero-avatar" />
<view v-else class="hero-avatar placeholder">
<text>{{ avatarInitial }}</text>
</view>
<view class="hero-meta">
<text class="hero-name">{{ session.member?.nickname }}</text>
<view v-if="session.member?.phone" class="hero-sub-row">
<text class="hero-phone">{{ session.member.phone }}</text>
</view>
</view>
</view>
<view class="hero-right">
<view class="hero-arrow" />
</view>
</view>
<view class="menu-group-card">
<view v-for="item in menuItems" :key="item.title" class="menu-item" @tap="go(item.url)">
<view class="item-left">
<view class="item-icon-container" :class="item.theme">
<view class="icon-order" v-if="item.icon === 'order'">
<view class="icon-order-line" />
<view class="icon-order-line short" />
</view>
<view class="icon-private" v-else-if="item.icon === 'private'">
<view class="icon-private-net" />
</view>
<view class="icon-ticket" v-else-if="item.icon === 'ticket'">
<view class="icon-ticket-dot" />
</view>
<view class="icon-profile" v-else>
<view class="icon-profile-head" />
<view class="icon-profile-body" />
</view>
</view>
<text class="menu-title">{{ item.title }}</text>
</view>
<view class="item-right">
<view class="menu-arrow" />
</view>
</view>
<view class="menu-item logout" @tap="logout">
<view class="item-left">
<view class="item-icon-container logout-theme">
<view class="icon-logout">
<view class="icon-logout-door" />
<view class="icon-logout-arrow" />
</view>
</view>
<text class="menu-title">退出登录</text>
</view>
<view class="item-right">
<view class="menu-arrow" />
</view>
</view>
</view>
</block>
</view>
</template>
<script setup>
import { computed, onMounted } from 'vue'
import { useComprehensiveSessionStore } from '@/modules/comprehensive/stores/session'
const session = useComprehensiveSessionStore()
const avatarInitial = computed(() => (session.member?.nickname || '用户').slice(0, 1))
const menuItems = [
{ title: '包场预约', url: '/pages/comprehensive/private/index', theme: 'private-theme', icon: 'private' },
{ title: '篮球门票', url: '/pages/comprehensive/tickets/index', theme: 'ticket-theme', icon: 'ticket' },
{ title: '我的订单', url: '/pages/comprehensive/profile/orders', theme: 'order-theme', icon: 'order' },
{ title: '个人信息', url: '/pages/comprehensive/profile/detail', theme: 'profile-theme', icon: 'profile' },
{ title: '切换场馆', url: '/pages/venue-select/index', theme: 'profile-theme', icon: 'profile' }
]
onMounted(async () => {
await session.init()
})
const login = async () => {
await session.login()
}
const logout = () => {
session.logout()
uni.showToast({ title: '已退出', icon: 'none' })
}
const go = (url) => {
uni.navigateTo({ url })
}
</script>
<style lang="scss" scoped>
.unlogged {
min-height: 80vh;
padding-top: 180rpx;
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
}
.brand {
color: $text-color-main;
font-size: 42rpx;
font-weight: 900;
letter-spacing: 2rpx;
}
.desc {
margin-top: $spacing-md;
color: $text-color-muted;
font-size: 26rpx;
}
.login-btn {
width: 520rpx;
margin-top: 100rpx;
}
.user-profile-hero {
display: flex;
align-items: center;
justify-content: space-between;
min-height: 160rpx;
padding: $spacing-lg;
border: 1rpx solid rgba(241, 245, 249, 0.9);
border-radius: $border-radius-lg;
background-color: $bg-color-main;
box-shadow: 0 10rpx 40rpx rgba(15, 23, 42, 0.02);
transition: all 0.2s ease;
}
.user-profile-hero:active {
opacity: 0.96;
transform: scale(0.99);
}
.hero-left {
display: flex;
align-items: center;
gap: $spacing-md;
min-width: 0;
}
.hero-avatar {
width: 104rpx;
height: 104rpx;
flex-shrink: 0;
border-radius: 50%;
background: $bg-color-hover;
}
.hero-avatar.placeholder {
display: flex;
align-items: center;
justify-content: center;
color: $text-color-main;
font-size: 36rpx;
font-weight: 900;
background: $color-primary-light;
}
.hero-meta {
display: flex;
flex-direction: column;
gap: 6rpx;
min-width: 0;
}
.hero-name,
.hero-phone,
.menu-title {
display: block;
}
.hero-name {
color: $text-color-main;
font-size: 34rpx;
font-weight: 700;
line-height: 1.3;
}
.hero-phone {
color: $text-color-muted;
font-size: 24rpx;
font-weight: 500;
}
.hero-arrow,
.menu-arrow {
width: 18rpx;
height: 18rpx;
border-top: 3rpx solid $text-color-light;
border-right: 3rpx solid $text-color-light;
transform: rotate(45deg);
}
.menu-group-card {
margin-top: $spacing-lg;
overflow: hidden;
border: 1rpx solid rgba(241, 245, 249, 0.9);
border-radius: $border-radius-lg;
background-color: $bg-color-main;
box-shadow: 0 10rpx 40rpx rgba(15, 23, 42, 0.02);
}
.menu-item {
min-height: 112rpx;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 $spacing-lg;
border-bottom: 1rpx solid rgba(241, 245, 249, 0.9);
}
.menu-item:last-child {
border-bottom: none;
}
.item-left,
.item-right {
display: flex;
align-items: center;
}
.item-left {
gap: $spacing-md;
}
.item-icon-container {
width: 58rpx;
height: 58rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: $border-radius-base;
background: $bg-color-soft;
color: $text-color-muted;
}
.item-icon-container.order-theme {
background: $color-primary-light;
color: $color-primary;
}
.item-icon-container.profile-theme {
background: $color-success-light;
color: $color-success;
}
.item-icon-container.private-theme {
background: rgba(14, 165, 233, 0.12);
color: #0284C7;
}
.item-icon-container.ticket-theme {
background: rgba(245, 158, 11, 0.14);
color: #D97706;
}
.item-icon-container.logout-theme {
background: $color-danger-light;
color: $color-danger;
}
.icon-order,
.icon-private,
.icon-ticket,
.icon-profile,
.icon-logout {
position: relative;
width: 32rpx;
height: 32rpx;
}
.icon-order {
border: 3rpx solid currentColor;
border-radius: 4rpx;
}
.icon-order::before {
content: '';
position: absolute;
top: -8rpx;
left: 7rpx;
width: 14rpx;
height: 10rpx;
border: 3rpx solid currentColor;
border-bottom: none;
border-radius: 4rpx 4rpx 0 0;
background: inherit;
}
.icon-order-line {
position: absolute;
left: 7rpx;
right: 7rpx;
top: 10rpx;
height: 3rpx;
border-radius: 2rpx;
background: currentColor;
}
.icon-order-line.short {
top: 19rpx;
right: 12rpx;
}
.icon-private {
border: 3rpx solid currentColor;
border-radius: 50%;
}
.icon-private::before,
.icon-private::after {
content: '';
position: absolute;
left: 5rpx;
right: 5rpx;
height: 3rpx;
border-radius: 2rpx;
background: currentColor;
}
.icon-private::before {
top: 9rpx;
}
.icon-private::after {
bottom: 9rpx;
}
.icon-private-net {
position: absolute;
top: 3rpx;
bottom: 3rpx;
left: 12rpx;
width: 4rpx;
border-radius: 2rpx;
background: currentColor;
}
.icon-ticket {
border: 3rpx solid currentColor;
border-radius: 6rpx;
transform: rotate(-8deg);
}
.icon-ticket::before,
.icon-ticket::after {
content: '';
position: absolute;
top: 9rpx;
bottom: 9rpx;
width: 3rpx;
border-radius: 2rpx;
background: currentColor;
}
.icon-ticket::before {
left: 8rpx;
}
.icon-ticket::after {
right: 8rpx;
}
.icon-ticket-dot {
position: absolute;
top: 12rpx;
left: 13rpx;
width: 6rpx;
height: 6rpx;
border-radius: 50%;
background: currentColor;
}
.icon-profile-head {
position: absolute;
top: 3rpx;
left: 10rpx;
width: 12rpx;
height: 12rpx;
border: 3rpx solid currentColor;
border-radius: 50%;
}
.icon-profile-body {
position: absolute;
left: 5rpx;
right: 5rpx;
bottom: 3rpx;
height: 12rpx;
border: 3rpx solid currentColor;
border-radius: 16rpx 16rpx 4rpx 4rpx;
}
.icon-logout-door {
position: absolute;
left: 4rpx;
top: 4rpx;
width: 15rpx;
height: 24rpx;
border: 3rpx solid currentColor;
border-right: none;
border-radius: 4rpx 0 0 4rpx;
}
.icon-logout-arrow {
position: absolute;
right: 2rpx;
top: 14rpx;
width: 20rpx;
height: 3rpx;
border-radius: 2rpx;
background: currentColor;
}
.icon-logout-arrow::after {
content: '';
position: absolute;
right: 0;
top: -6rpx;
width: 10rpx;
height: 10rpx;
border-top: 3rpx solid currentColor;
border-right: 3rpx solid currentColor;
transform: rotate(45deg);
}
.menu-title {
color: $text-color-main;
font-size: 28rpx;
font-weight: 700;
}
.logout .menu-title {
color: $color-danger;
}
</style>