diff --git a/src/app.config.ts b/src/app.config.ts index 1abd25d..197be93 100644 --- a/src/app.config.ts +++ b/src/app.config.ts @@ -16,6 +16,7 @@ export default defineAppConfig({ 'mapStore/index', // 地图找店页面 'reservation/index', // 预定页面 'appointmentStart/index', // 预约开台页面 + 'storeDetail/index', // 门店详情页面 ] }, { diff --git a/src/pageStore/images/billiardtab.png b/src/pageStore/images/billiardtab.png new file mode 100644 index 0000000..9e1e41f Binary files /dev/null and b/src/pageStore/images/billiardtab.png differ diff --git a/src/pageStore/images/locationicon.png b/src/pageStore/images/locationicon.png new file mode 100644 index 0000000..1232641 Binary files /dev/null and b/src/pageStore/images/locationicon.png differ diff --git a/src/pageStore/images/paitab.png b/src/pageStore/images/paitab.png new file mode 100644 index 0000000..f61e184 Binary files /dev/null and b/src/pageStore/images/paitab.png differ diff --git a/src/pageStore/images/payVip.png b/src/pageStore/images/payVip.png new file mode 100644 index 0000000..5f36eef Binary files /dev/null and b/src/pageStore/images/payVip.png differ diff --git a/src/pageStore/images/phone.png b/src/pageStore/images/phone.png new file mode 100644 index 0000000..4a000ff Binary files /dev/null and b/src/pageStore/images/phone.png differ diff --git a/src/pageStore/images/share.png b/src/pageStore/images/share.png new file mode 100644 index 0000000..989827d Binary files /dev/null and b/src/pageStore/images/share.png differ diff --git a/src/pageStore/images/storeBox.png b/src/pageStore/images/storeBox.png new file mode 100644 index 0000000..726a5a6 Binary files /dev/null and b/src/pageStore/images/storeBox.png differ diff --git a/src/pageStore/storeDetail/index.scss b/src/pageStore/storeDetail/index.scss new file mode 100644 index 0000000..6683827 --- /dev/null +++ b/src/pageStore/storeDetail/index.scss @@ -0,0 +1,519 @@ +/** + * 门店详情页面样式 + */ +.store_detail_page { + min-height: 100vh; + background-color: #121212; + position: relative; + + // 自定义透明导航栏 + .custom_nav_bar { + position: fixed; + top: 0; + left: 0; + right: 0; + z-index: 100; + background-color: transparent; + + .nav_content { + display: flex; + align-items: center; + padding: 0 30px; + + .nav_buttons { + display: flex; + align-items: center; + background-color: rgba(0, 0, 0, 0.3); + border-radius: 32px; + overflow: hidden; + + .nav_btn { + display: flex; + align-items: center; + justify-content: center; + width: 66px; + height: 64px; + + .nav_icon { + width: 36px; + height: 36px; + color: #FFFFFF; + + &.back_icon { + transform: rotate(180deg); + } + + &.home_icon { + width: 36px; + height: 36px; + } + } + } + + .nav_divider { + width: 1px; + height: 36px; + background-color: rgba(255, 255, 255, 0.3); + } + } + } + } + + // 轮播图区域 + .swiper_container { + width: 100%; + height: 465px; + position: relative; + + .swiper { + width: 100%; + height: 100%; + } + + .swiper_image { + width: 100%; + height: 100%; + display: block; + } + + .swiper_indicator { + position: absolute; + bottom: 40px; + left: 50%; + transform: translateX(-50%); + } + } + + // 内容区域 + .content_area { + position: relative; + margin-top: -20px; + background-color: #121212; + border-top-left-radius: 25px; + border-top-right-radius: 25px; + padding: 30px; + padding-bottom: 50px; + + // 门店信息 + .store_info_section { + margin-bottom: 33px; + + .store_header { + display: flex; + align-items: center; + justify-content: space-between; + + .store_name { + font-size: 42px; + color: #FFFFFF; + font-weight: 500; + } + + .store_actions { + display: flex; + align-items: center; + gap: 30px; + + .action_icon { + width: 33px; + height: 33px; + + &.phone, + &.share { + width: 33px; + height: 33px; + } + } + } + } + + .store_location { + display: flex; + align-items: flex-start; + justify-content: space-between; + padding: 30px 0; + + .location_left { + display: flex; + align-items: flex-start; + gap: 10px; + flex: 1; + + .location_icon { + width: 16px; + height: 20px; + flex-shrink: 0; + margin-top: 5px; + } + + .location_text { + font-size: 25px; + color: #E5E5E5; + line-height: 1.5; + flex: 1; + } + } + + .distance_text { + font-size: 25px; + color: #E5E5E5; + flex-shrink: 0; + margin-left: 20px; + } + } + + .store_price { + display: flex; + gap: 30px; + + .price_text { + font-size: 25px; + color: #B8B8B8; + } + } + } + + // VIP 横幅 + .vip_banner { + width: 690px; + height: 83px; + position: relative; + margin-bottom: 30px; + + .vip_bg { + width: 100%; + height: 100%; + border-radius: 10px; + } + + .vip_btn { + position: absolute; + right: 30px; + top: 50%; + transform: translateY(-50%); + width: 158px; + height: 58px; + background: #614929; + border-radius: 29px; + display: flex; + align-items: center; + justify-content: center; + + .vip_btn_text { + font-size: 25px; + color: #E0C699; + } + } + } + + // Tab 导航 + .tab_container { + display: flex; + justify-content: space-around; + padding: 20px 0; + margin-bottom: 30px; + + .tab_item { + display: flex; + flex-direction: column; + align-items: center; + position: relative; + + .tab_count{ + display: flex; + align-items: center; + gap: 5px; + margin-bottom: 10px; + .count_label { + font-size: 26px; + color: #FFFFFF; + } + + .count_value { + font-size: 26px; + color: #01CA68; + } + + } + + .tab_name { + font-size: 36px; + color: #FFFFFF; + } + + .tab_indicator { + width: 29px; + height: 8px; + background: linear-gradient(-30deg, #0099E6, #33FF99); + border-radius: 4px; + margin-top: 10px; + } + } + } + + // 台球和棋牌区域 + .tables_section { + padding: 30px; + background: #202029; + border-radius: 13px; + + // 分类区块 + .category_block { + margin-bottom: 30px; + } + + // 分类头部 + .category_header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 20px; + + .category_name { + font-size: 33px; + color: #FFFFFF; + font-weight: 500; + } + + .category_price { + display: flex; + gap: 20px; + + .vip_price { + font-size: 23px; + color: #F5CFA9; + } + + .original_price, + .time_range, + .price_info { + font-size: 23px; + color: #999999; + } + } + } + + // 台球桌网格 + .tables_grid { + display: grid; + gap: 20px; + + &.billiard_grid { + grid-template-columns: repeat(2, 1fr); + } + + &.chess_grid { + grid-template-columns: repeat(2, 1fr); + } + } + + // 台球桌卡片 + .table_card { + position: relative; + border-radius: 12px; + overflow: hidden; + + &.billiard_card { + width: 100%; + height: 204px; + } + + &.chess_card { + width: 100%; + height: 300px; + } + + .table_bg { + width: 100%; + height: 100%; + position: absolute; + top: 0; + left: 0; + } + + // 蒙版 + .table_mask { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.4); + z-index: 1; + } + + // 状态标签(棋牌) + .status_tag { + position: absolute; + top: 15px; + left: 15px; + padding: 5px 12px; + border-radius: 4px; + z-index: 2; + + &.available { + background-color: #03C175; + } + + &.using { + background-color: #FF4D4F; + } + + .tag_text { + font-size: 21px; + color: #FFFFFF; + } + } + + // 内容区域 + .table_content { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + z-index: 2; + + .table_name { + font-size: 33px; + color: #FFFFFF; + font-weight: bold; + margin-bottom: 15px; + text-align: center; + } + + .table_buttons { + display: flex; + background-color: #00B05C; + border-radius: 33px; + overflow: hidden; + + .table_btn { + font-size: 27px; + color: #FFFFFF; + padding: 15px 30px; + background-color: transparent; + position: relative; + + // 中间分隔线 + &:not(:last-child)::after { + content: ''; + position: absolute; + right: 0; + top: 50%; + transform: translateY(-50%); + width: 1px; + height: 60%; + background-color: rgba(255, 255, 255, 0.3); + } + } + } + + // 单个按钮样式 + .table_btn_single { + font-size: 27px; + color: #FFFFFF; + padding: 15px 36px; + border-radius: 33px; + background-color: #00B05C; + } + + .table_status { + font-size: 25px; + color: #FFFFFF; + text-align: center; + white-space: pre-line; + line-height: 1.6; + } + } + } + + // 棋牌区域 + .chess_section { + margin-top: 40px; + } + } + + // 存杆柜区域 + .storage_section { + margin-top: 40px; + + .section_title { + font-size: 33px; + color: #FFFFFF; + font-weight: 500; + margin-bottom: 20px; + display: block; + } + + .storage_card { + width: 100%; + height: 255px; + position: relative; + border-radius: 12px; + overflow: hidden; + + .storage_bg { + width: 100%; + height: 100%; + position: absolute; + top: 0; + left: 0; + } + + .storage_content { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + padding: 30px; + display: flex; + flex-direction: column; + justify-content: flex-start; + z-index: 1; + + .storage_status { + font-size: 29px; + color: #FFFFFF; + margin-bottom: 10px; + } + + .storage_price { + font-size: 25px; + color: #03C175; + margin-bottom: 20px; + } + + .storage_btn { + width: 120px; + height: 50px; + background-color: #21212A; + border-radius: 25px; + display: flex; + align-items: center; + justify-content: center; + + .btn_text { + font-size: 27px; + color: #03C175; + } + } + } + } + } + + // 底部提示 + .end_tip { + display: block; + text-align: center; + font-size: 25px; + color: #666666; + margin-top: 40px; + } + } +} diff --git a/src/pageStore/storeDetail/index.tsx b/src/pageStore/storeDetail/index.tsx new file mode 100644 index 0000000..9dec202 --- /dev/null +++ b/src/pageStore/storeDetail/index.tsx @@ -0,0 +1,472 @@ +/** + * 门店详情页面 + */ +import { View, Text, Image } from '@tarojs/components' +import Taro, { useLoad } from '@tarojs/taro' +import { useState, useEffect } from 'react' +import { Swiper } from '@taroify/core' +import { Arrow, HomeOutlined } from '@taroify/icons' +import './index.scss' + +// 页面配置 - 隐藏导航栏 +definePageConfig({ + navigationStyle: 'custom', + navigationBarTitleText: '' +}) + +// 图片资源 +import phoneIcon from '../images/phone.png' +import locationIcon from '../images/locationicon.png' +import shareIcon from '../images/share.png' +import payVipBg from '../images/payVip.png' +import billiardTabBg from '../images/billiardtab.png' +import paiTabBg from '../images/paitab.png' +import storeBoxBg from '../images/storeBox.png' +import swBG from '../../assets/big/swBG.png' + +// 台球桌状态类型 +type TableStatus = 'available' | 'using' | 'waiting' | 'reserved' + +// 台球桌数据接口 +interface BilliardTable { + id: string + name: string + status: TableStatus + waitTime?: string + buttons: Array<{ + type: 'start' | 'reserve' + text: string + }> +} + +// 台球桌分类数据 +interface BilliardCategory { + name: string + vipPrice: string + originalPrice: string + tables: BilliardTable[] +} + +// 棋牌桌数据接口 +interface ChessTable { + id: string + name: string + status: TableStatus + statusText?: string + buttonText?: string + waitTime?: string +} + +// 存杆柜数据接口 +interface StorageCabinet { + id: string + status: 'available' | 'rented' + price: string +} + +const StoreDetail = () => { + const [activeTab, setActiveTab] = useState(0) // 0: 中式台球, 1: 棋牌, 2: 存杆柜 + const [statusBarHeight, setStatusBarHeight] = useState(20) // 状态栏高度 + const [navBarHeight, setNavBarHeight] = useState(44) // 导航栏内容高度 + + // 获取系统信息设置导航栏高度 + useEffect(() => { + const systemInfo = Taro.getSystemInfoSync() + setStatusBarHeight(systemInfo.statusBarHeight || 20) + // 微信小程序胶囊按钮信息 + if (process.env.TARO_ENV === 'weapp') { + const menuButtonInfo = Taro.getMenuButtonBoundingClientRect() + const navHeight = (menuButtonInfo.top - (systemInfo.statusBarHeight || 0)) * 2 + menuButtonInfo.height + setNavBarHeight(navHeight) + } + }, []) + + // 返回上一页 + const handleBack = () => { + const pages = Taro.getCurrentPages() + if (pages.length > 1) { + Taro.navigateBack() + } else { + Taro.switchTab({ url: '/pages/index/index' }) + } + } + + // 返回首页 + const handleGoHome = () => { + Taro.switchTab({ url: '/pages/index/index' }) + } + + // 门店信息 + const storeInfo = { + name: '北京黑八大师联盟球厅店', + address: '北京市XXX区XXX街道XXX路XXXXXX大厦101', + distance: '10.05km', + billiardPrice: '¥10.00起', + chessPrice: '¥20.00起' + } + + // Tab 数据 + const tabs = [ + { name: '中式台球', idleCount: 5 }, + { name: '棋牌', idleCount: 1 }, + { name: '存杆柜', idleCount: 0 } + ] + + // 台球桌分类数据 + const [billiardCategories] = useState([ + { + name: '独牙&来力.山岩', + vipPrice: '¥8.00/小时', + originalPrice: '¥10.00/小时', + tables: [ + { id: '1', name: '独牙01', status: 'available', buttons: [{ type: 'start', text: '立即开台' }] }, + { id: '2', name: '独牙02', status: 'waiting', waitTime: '00 时 15 分', buttons: [] }, + { id: '3', name: '来力黑金刚03', status: 'available', buttons: [{ type: 'start', text: '立即开台' }] }, + { id: '4', name: '来力黑金刚04', status: 'using', buttons: [] } + ] + }, + { + name: '乔氏赛台', + vipPrice: '¥16.00/小时', + originalPrice: '¥20.00/小时', + tables: [ + { id: '5', name: '乔氏01', status: 'available', buttons: [{ type: 'start', text: '立即开台' }] }, + { id: '6', name: '乔氏02', status: 'available', buttons: [{ type: 'reserve', text: '预定' }, { type: 'start', text: '立即开台' }] }, + { id: '7', name: '乔氏03', status: 'available', buttons: [{ type: 'start', text: '立即开台' }] } + ] + } + ]) + + // 棋牌数据 + const [chessTables] = useState([ + { id: '1', name: 'Q01号', status: 'available', buttonText: '立即开台' }, + { id: '2', name: 'Q02号', status: 'using', statusText: '预计 16:00 结束' }, + { id: '3', name: 'Q03号', status: 'waiting', statusText: '预计等待:', waitTime: '00 时 15 分' }, + { id: '4', name: 'Q04号', status: 'reserved', buttonText: '预约开台' } + ]) + + // 棋牌价格信息 + const chessInfo = { + timeRange: '00:00-24:00', + price: '¥60.00/小时' + } + + // 存杆柜数据 + const [storageCabinet] = useState({ + id: '1', + status: 'available', + price: '1元/天' + }) + + useLoad(() => { + console.log('门店详情页面加载') + }) + + // 拨打电话 + const handlePhoneCall = () => { + Taro.makePhoneCall({ + phoneNumber: '100-666-XXXX', + }).catch((err) => { + console.error('拨打电话失败:', err) + }) + } + + // 分享 + const handleShare = () => { + Taro.showToast({ + title: '分享功能开发中', + icon: 'none' + }) + } + + // 开通VIP + const handleOpenVip = () => { + Taro.navigateTo({ + url: '/pagesUser/vipBenefits/index' + }) + } + + // Tab 点击,滚动到对应位置 + const handleTabClick = (index: number) => { + setActiveTab(index) + // 获取对应区域的 ID + const sectionIds = ['billiard-section', 'chess-section', 'storage-section'] + const query = Taro.createSelectorQuery() + query.select(`#${sectionIds[index]}`).boundingClientRect() + query.select('#scroll-content').scrollOffset() + query.exec((res) => { + if (res[0] && res[1]) { + const targetTop = res[0].top + res[1].scrollTop - 150 // 减去 tab 高度 + Taro.pageScrollTo({ + scrollTop: targetTop, + duration: 300 + }) + } + }) + } + + // 进入预定页面 + const handleReserve = (tableId: string) => { + Taro.navigateTo({ + url: '/pageStore/reservation/index?tableId=' + tableId + }) + } + + // 进入开台页面 + const handleStartTable = (tableId: string) => { + Taro.navigateTo({ + url: '/pageScan/startTable/index?tableId=' + tableId + }) + } + + // 进入预约开台页面 + const handleAppointmentStart = (tableId: string) => { + Taro.navigateTo({ + url: '/pageStore/appointmentStart/index?tableId=' + tableId + }) + } + + // 进入存杆柜租赁页面 + const handleCabinetRental = () => { + Taro.navigateTo({ + url: '/pagesOrder/cabinetRental/index' + }) + } + + // 获取台球桌状态文本 + const getBilliardStatusText = (table: BilliardTable) => { + if (table.status === 'using') return '使用中' + if (table.status === 'waiting') return `预计等待:\n${table.waitTime}` + return '' + } + + // 获取棋牌状态标签 + const getChessStatusTag = (status: TableStatus) => { + if (status === 'available') return { text: '空闲中', class: 'available' } + if (status === 'using') return { text: '使用中', class: 'using' } + if (status === 'waiting') return { text: '使用中', class: 'using' } + if (status === 'reserved') return { text: '空闲中', class: 'available' } + return { text: '', class: '' } + } + + return ( + + {/* 自定义透明导航栏 */} + + + + + + + {/* + + + */} + + + + + {/* 轮播图区域 */} + + + + + + + + + + + + + {/* 内容区域 */} + + {/* 门店信息 */} + + + {storeInfo.name} + + + + + + + + + + {storeInfo.address} + + 距离{storeInfo.distance} + + + + 台球 {storeInfo.billiardPrice} + 棋牌 {storeInfo.chessPrice} + + + + {/* VIP 开通横幅 */} + + + + 立即开通 + + + + {/* Tab 导航 */} + + {tabs.map((tab, index) => ( + handleTabClick(index)} + > + + 空闲 + {tab.idleCount} + + {tab.name} + {activeTab === index && } + + ))} + + + {/* 台球和棋牌区域 */} + + {/* 台球区域 */} + + {billiardCategories.map((category, catIndex) => ( + + + {category.name} + + VIP: {category.vipPrice} + 原价: {category.originalPrice} + + + + + {category.tables.map((table) => ( + + + {table.status !== 'available' && } + + {table.name} + {table.status === 'available' && table.buttons.length > 0 ? ( + table.buttons.length === 1 ? ( + // 单个按钮 + table.buttons[0].type === 'reserve' ? handleReserve(table.id) : handleStartTable(table.id)} + > + {table.buttons[0].text} + + ) : ( + // 按钮组 + + {table.buttons.map((btn, btnIndex) => ( + btn.type === 'reserve' ? handleReserve(table.id) : handleStartTable(table.id)} + > + {btn.text} + + ))} + + ) + ) : ( + {getBilliardStatusText(table)} + )} + + + ))} + + + ))} + + + {/* 棋牌区域 */} + + + 棋牌 + + {chessInfo.timeRange} + 价格: {chessInfo.price} + + + + + {chessTables.map((table) => ( + + + {(table.status === 'using' || table.status === 'waiting') && } + + {/* 状态标签 */} + + {getChessStatusTag(table.status).text} + + + + {table.name} + {table.status === 'available' ? ( + handleStartTable(table.id)}>{table.buttonText} + ) : table.status === 'reserved' ? ( + handleAppointmentStart(table.id)}>{table.buttonText} + ) : ( + + {table.statusText} + {table.status === 'waiting' && `\n${table.waitTime}`} + + )} + + + ))} + + + + + {/* 存杆柜区域 */} + + 存杆柜 + + + + 暂未租赁/租赁中 + {storageCabinet.price} + + 租赁 + + + + + + {/* 底部提示 */} + 到底了~ + + + ) +} + +export default StoreDetail diff --git a/src/pages/store/index.tsx b/src/pages/store/index.tsx index 1a23bd2..9fa2803 100644 --- a/src/pages/store/index.tsx +++ b/src/pages/store/index.tsx @@ -216,6 +216,14 @@ const StoreIndex = observer(() => { }, 500) } + // 跳转到店铺详情 + const clickStoreItem = (store: any) => { + Taro.navigateTo({ + url: '/pageStore/storeDetail/index?id=' + store.id + }) + console.log('跳转到店铺详情', store) + } + // 跳转到地图找店页面(分包页面) const handleGoToMap = () => { Taro.navigateTo({ @@ -266,7 +274,7 @@ const StoreIndex = observer(() => { {/* 门店列表 */} {storeList.map((store) => ( - + clickStoreItem(store)}> {/* 标题和价格 */} {store.name}