feat: add venue selection shell
This commit is contained in:
@@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"easycom": {
|
||||||
|
"autoscan": true,
|
||||||
|
"custom": {
|
||||||
|
"^u--(.*)": "uview-plus/components/u-$1/u-$1.vue",
|
||||||
|
"^up-(.*)": "uview-plus/components/u-$1/u-$1.vue",
|
||||||
|
"^u-([^-].*)": "uview-plus/components/u-$1/u-$1.vue"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pages": [
|
||||||
|
{
|
||||||
|
"path": "pages/venue-select/index",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "选择场馆",
|
||||||
|
"navigationBarBackgroundColor": "#FFFFFF",
|
||||||
|
"navigationBarTextStyle": "black"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"globalStyle": {
|
||||||
|
"navigationBarTextStyle": "black",
|
||||||
|
"navigationBarBackgroundColor": "#FFFFFF",
|
||||||
|
"backgroundColor": "#F8FAFC",
|
||||||
|
"backgroundColorBottom": "#F8FAFC",
|
||||||
|
"backgroundColorTop": "#FFFFFF"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,130 @@
|
|||||||
|
<template>
|
||||||
|
<view class="venue-select-page">
|
||||||
|
<view class="header">
|
||||||
|
<text class="title">选择场馆</text>
|
||||||
|
<text class="subtitle">进入对应场馆后,会员、预约、订单和支付数据彼此独立。</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="venue-list">
|
||||||
|
<view
|
||||||
|
v-for="venue in venues"
|
||||||
|
:key="venue.key"
|
||||||
|
class="venue-card"
|
||||||
|
:class="{ active: venue.key === currentVenue }"
|
||||||
|
@tap="selectVenue(venue.key)"
|
||||||
|
>
|
||||||
|
<view class="venue-main">
|
||||||
|
<text class="venue-name">{{ venue.name }}</text>
|
||||||
|
<text class="venue-desc">{{ venue.description }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="venue-action">
|
||||||
|
<text>{{ venue.key === currentVenue ? '当前' : '进入' }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { computed, onMounted } from 'vue'
|
||||||
|
import { useVenueStore } from '@/stores/venue'
|
||||||
|
import { VENUE_OPTIONS } from '@/utils/venue'
|
||||||
|
|
||||||
|
const venueStore = useVenueStore()
|
||||||
|
const venues = VENUE_OPTIONS
|
||||||
|
const currentVenue = computed(() => venueStore.currentVenue)
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
venueStore.init()
|
||||||
|
})
|
||||||
|
|
||||||
|
const selectVenue = (venueKey) => {
|
||||||
|
venueStore.enterVenue(venueKey)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.venue-select-page {
|
||||||
|
min-height: 100vh;
|
||||||
|
padding: 96rpx 32rpx 48rpx;
|
||||||
|
background: $bg-color-soft;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 18rpx;
|
||||||
|
margin-bottom: 56rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
color: $text-color-main;
|
||||||
|
font-size: 48rpx;
|
||||||
|
font-weight: 900;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subtitle {
|
||||||
|
color: $text-color-muted;
|
||||||
|
font-size: 26rpx;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.venue-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.venue-card {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 24rpx;
|
||||||
|
padding: 32rpx;
|
||||||
|
border: 1rpx solid $border-color;
|
||||||
|
border-radius: $border-radius-lg;
|
||||||
|
background: $bg-color-main;
|
||||||
|
}
|
||||||
|
|
||||||
|
.venue-card.active {
|
||||||
|
border-color: $color-primary;
|
||||||
|
background: $color-primary-light;
|
||||||
|
}
|
||||||
|
|
||||||
|
.venue-main {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.venue-name {
|
||||||
|
color: $text-color-main;
|
||||||
|
font-size: 34rpx;
|
||||||
|
font-weight: 900;
|
||||||
|
}
|
||||||
|
|
||||||
|
.venue-desc {
|
||||||
|
color: $text-color-muted;
|
||||||
|
font-size: 24rpx;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.venue-action {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
min-width: 96rpx;
|
||||||
|
height: 56rpx;
|
||||||
|
border-radius: $border-radius-sm;
|
||||||
|
background: $text-color-main;
|
||||||
|
color: #FFFFFF;
|
||||||
|
font-size: 24rpx;
|
||||||
|
font-weight: 800;
|
||||||
|
}
|
||||||
|
|
||||||
|
.venue-card.active .venue-action {
|
||||||
|
background: $color-primary;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
import { defineStore } from 'pinia'
|
||||||
|
import { getStoredVenue, getVenueOption, navigateToVenueHome, setStoredVenue } from '@/utils/venue'
|
||||||
|
|
||||||
|
export const useVenueStore = defineStore('currentVenue', {
|
||||||
|
state: () => ({
|
||||||
|
currentVenue: ''
|
||||||
|
}),
|
||||||
|
getters: {
|
||||||
|
currentVenueOption: (state) => getVenueOption(state.currentVenue),
|
||||||
|
hasSelectedVenue: (state) => Boolean(getVenueOption(state.currentVenue))
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
init() {
|
||||||
|
this.currentVenue = getStoredVenue()
|
||||||
|
return this.currentVenue
|
||||||
|
},
|
||||||
|
selectVenue(venueKey) {
|
||||||
|
this.currentVenue = setStoredVenue(venueKey)
|
||||||
|
return this.currentVenue
|
||||||
|
},
|
||||||
|
enterVenue(venueKey) {
|
||||||
|
const selectedVenue = this.selectVenue(venueKey)
|
||||||
|
navigateToVenueHome(selectedVenue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
export const CURRENT_VENUE_KEY = 'CURRENT_VENUE'
|
||||||
|
|
||||||
|
export const VENUE_KEYS = Object.freeze({
|
||||||
|
ICE: 'ice',
|
||||||
|
COMPREHENSIVE: 'comprehensive'
|
||||||
|
})
|
||||||
|
|
||||||
|
export const VENUE_OPTIONS = Object.freeze([
|
||||||
|
{
|
||||||
|
key: VENUE_KEYS.ICE,
|
||||||
|
name: '冰场馆',
|
||||||
|
description: '课程预约、会员卡与滑冰服务',
|
||||||
|
homePath: '/pages/ice/home/index'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: VENUE_KEYS.COMPREHENSIVE,
|
||||||
|
name: '综合场馆',
|
||||||
|
description: '课程、包场、门票、订单与余额',
|
||||||
|
homePath: '/pages/comprehensive/home/index'
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
export const isVenueKey = (value) => {
|
||||||
|
return value === VENUE_KEYS.ICE || value === VENUE_KEYS.COMPREHENSIVE
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getVenueOption = (venueKey) => {
|
||||||
|
return VENUE_OPTIONS.find((item) => item.key === venueKey) || null
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getStoredVenue = () => {
|
||||||
|
const venue = uni.getStorageSync(CURRENT_VENUE_KEY)
|
||||||
|
return isVenueKey(venue) ? venue : ''
|
||||||
|
}
|
||||||
|
|
||||||
|
export const setStoredVenue = (venueKey) => {
|
||||||
|
if (!isVenueKey(venueKey)) {
|
||||||
|
uni.removeStorageSync(CURRENT_VENUE_KEY)
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
|
||||||
|
uni.setStorageSync(CURRENT_VENUE_KEY, venueKey)
|
||||||
|
return venueKey
|
||||||
|
}
|
||||||
|
|
||||||
|
export const navigateToVenueHome = (venueKey, options = {}) => {
|
||||||
|
const venue = getVenueOption(venueKey)
|
||||||
|
if (!venue) {
|
||||||
|
uni.reLaunch({ url: '/pages/venue-select/index' })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const navigate = options.redirect === true ? uni.redirectTo : uni.reLaunch
|
||||||
|
navigate({ url: venue.homePath })
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user