Przeglądaj źródła

场地预览页

学习?学个屁 1 tydzień temu
rodzic
commit
8761d25ed3

+ 6 - 0
src/pages.json

@@ -205,6 +205,12 @@
 				"navigationBarBackgroundColor": "#fff",
 				"navigationBarTitleText": "场馆全景"
 			}
+		},{
+			"path": "pages/index/mapPage/index",
+			"style": {
+				"navigationBarBackgroundColor": "#fff",
+				"navigationBarTitleText": "导航"
+			}
 		},{
 			"path": "pages/mine/index",
 			"style": {

+ 20 - 6
src/pages/index/allInstructor/index.vue

@@ -1,19 +1,33 @@
 <template>
 	<view class="content">
-		<view class="a-instructor-card" v-for="item in 4" @click="to_instructor">
-			<image class="instructor-img" src="https://img.keaitupian.cn/newupload/08/1629449018344288.jpg" mode=""></image>
+		<view class="a-instructor-card" v-for="item in instructorList" :key="item.id" @click="to_instructor(item)">
+			<image class="instructor-img" :src="item.avatar" mode=""></image>
 			<view class="a-instructor-name">
-				<view class="name">詹姆四</view>
-				<view class="type">篮球</view>
+				<view class="name">{{item.realname}}</view>
+				<view class="type">{{item.trainingProgramsName}}</view>
 			</view>
 		</view>
 	</view>
 </template>
 
 <script lang="ts" setup>
-	const to_instructor=()=>{
+	import { ref, onMounted, computed } from 'vue'
+	import { onLoad, onReachBottom } from '@dcloudio/uni-app'
+	import { http } from '@/utils/http'
+	import zsEmpty from '@/components/zs-empty/index.vue'
+	onMounted(()=>{
+		get_findCoachList()
+	})
+	const to_instructor=(e)=>{
 		uni.navigateTo({
-			url:'/pages/index/instructorDetail/index'
+			url:`/pages/index/instructorDetail/index?id=${e.id}`
+		})
+	}
+	
+	const instructorList=ref()
+	const get_findCoachList=()=>{
+		http.get('/coachC/findCoachList',{loading:true}).then((res)=>{
+			instructorList.value=res.result
 		})
 	}
 </script>

+ 25 - 12
src/pages/index/certifyingDetail/index.vue

@@ -9,13 +9,13 @@
 			<view class="item-list">
 				<view class="item-text">无犯罪记录</view>
 				<view class="item-img">
-					<image src="https://img.keaitupian.cn/newupload/08/1629449018344288.jpg" mode="widthFix"></image>
+					<image :src="detailObj.certificateInnocence" mode="widthFix"></image>
 				</view>
 			</view>
 			<view class="item-list">
 				<view class="item-text">健康证</view>
 				<view class="item-img">
-					<image src="https://img.keaitupian.cn/newupload/08/1629449018344288.jpg" mode="widthFix"></image>
+					<image :src="detailObj.healthy" mode="widthFix"></image>
 				</view>
 			</view>
 		</view>
@@ -24,23 +24,36 @@
 				<zzx-icon name="idcard"></zzx-icon>
 				<view class="text">荣誉认证</view>
 			</view>
-			<view class="item-list">
-				<view class="item-text">篮球裁判三级</view>
-				<view class="item-img">
-					<image src="https://img.keaitupian.cn/newupload/08/1629449018344288.jpg" mode="widthFix"></image>
-				</view>
-			</view>
-			<view class="item-list">
-				<view class="item-text">优秀教师</view>
+			<view class="item-list" v-for="(item,index) in detailObj.honorImgList" :key="index">
+				<!-- <view class="item-text">篮球裁判三级</view> -->
 				<view class="item-img">
-					<image src="https://img.keaitupian.cn/newupload/08/1629449018344288.jpg" mode="widthFix"></image>
+					<image :src="item" mode="widthFix"></image>
 				</view>
 			</view>
 		</view>
 	</view>
 </template>
 
-<script>
+<script lang="ts" setup>
+	import { ref, onMounted } from 'vue';
+	import { onLoad, onPageScroll } from '@dcloudio/uni-app';
+	import { http } from '@/utils/http'
+	import { useCacheStore } from '@/stores/cache'
+	const cache = useCacheStore()
+	onLoad((option)=>{
+		detailId.value=option.id
+	})
+	onMounted(()=>{
+		get_findByCoachId()
+	})
+	
+	const detailId=ref()
+	const detailObj=ref()
+	const get_findByCoachId=()=>{
+		http.get('/coachC/findByCoachId',{data:{id:detailId.value,longitude:cache.get('LON'),latitude:cache.get('LAT')},loading:true}).then((res)=>{
+			detailObj.value=res.result
+		})
+	}
 </script>
 <style>
 	page{

+ 91 - 41
src/pages/index/courseDetail/index.vue

@@ -1,19 +1,17 @@
 <template>
 	<zzx-navbar :scrollable="true" :back="true" title="详情"></zzx-navbar>
 	<view class="detail-header">
-		<image class="header-bg"
-			src="https://ts1.tc.mm.bing.net/th/id/R-C.a8553f142638e741396e386b43c2bca7?rik=dzSGk6XRsxAAsQ&riu=http%3a%2f%2fseopic.699pic.com%2fphoto%2f50062%2f5890.jpg_wh1200.jpg&ehk=BgxiqxvzoNQd0pZHWV4VPOMbYgqM76WDMt8RDzCjoYY%3d&risl=&pid=ImgRaw&r=0"
-			mode="widthFix"></image>
+		<image class="header-bg" :src="bannerList[0]" mode=""></image>
 		<view class="back-icon" :style="{paddingTop:(statusBarHeight+10)+'px'}" @click="RouterUtils.back()">
 			<zzx-icon name="back"></zzx-icon>
 		</view>
 		<view :style="{height:(statusBarHeight+70)+'px'}"></view>
 		<scroll-view class="header-swiper content" scroll-x="true" :show-scrollbar="false">
 			<view class="swiper-inner">
-				<video src="https://vod.v.jstv.com/2025/05/09/JSTV_JSGGNEW_1746791056693_2lBi96K_114.mp4"></video>
-				<image v-for="item in 4"
-					src="https://bpic.588ku.com/element_origin_min_pic/23/07/11/d32dabe266d10da8b21bd640a2e9b611.jpg!r650"
-					mode=""></image>
+				<block  v-if="courseDetailInfo.video">
+					<video v-for="(item,index) in videoList" :key="index" :src="item"></video>
+				</block>
+				<image @click="_previewImage(bannerList)" v-for="(item,index) in bannerList" :key="index" :src="item" mode=""></image>
 			</view>
 		</scroll-view>
 	</view>
@@ -21,22 +19,27 @@
 	<view class="header-info">
 		<view class="c-price-info">
 			<view class="price-info">
-				<view class="new-price">¥25.9</view>
-				<view class="old-price">¥80.9</view>
+				<view class="new-price">¥{{courseDetailInfo.sellingPrice}}</view>
+				<view class="old-price">¥{{courseDetailInfo.originalPrice}}</view>
 			</view>
-			<view class="sales">年售150</view>
+			<view class="sales">年售{{courseDetailInfo.sales}}</view>
 		</view>
 		<view class="c-name">
-			一对一篮球30分钟室内精品课程,一对一篮球
-			30分钟室内精品课程
+			{{courseDetailInfo.name}}
 		</view>
 		<view class="c-detail-info">
-			<view class="c-time">课时:05.06-05.31</view>
+			<view class="c-time">课时:{{courseDetailInfo.startTime}}-{{courseDetailInfo.endTime}}</view>
 			<view class="c-address">
-				<view class="">上课地点:观山湖区第十二小学</view>
+				<view class="">上课地点:{{courseDetailInfo.address}} | {{courseDetailInfo.km}}</view>
 				<zzx-icon name="ashRight" size="10"></zzx-icon>
 			</view>
-			<view class="c-instructor">授课教练:杨锦新</view>
+			<view class="c-instructor">
+				<view class="c-instructor-title">授课教练:</view>
+				<view class="c-instructor-name">
+					<image :src="courseDetailInfo.instructorAvatar" mode=""></image>
+					<view class="">{{courseDetailInfo.instructorName}}</view>
+				</view>
+			</view>
 		</view>
 		<view class="c-line"></view>
 		<view class="c-rules">限制:每人限购一张</view>
@@ -52,17 +55,13 @@
 		</uv-sticky>
 		<view class="c-tabbar">
 			<view class="c-tabbar-detail" id="detail">
-				详情富文本内容详情富文本内容详情富文本内容详情富文本内容详情富文本内容详情富文本内容详情富文本内容详情富文本内容详情富文本内容详情富文本内容详情富文本内容详情富文本内容详情富文本内容详情富文本内容
-				详情富文本内容详情富文本内容详情富文本内容详情富文本内容详情富文本内容详情富文本内容详情富文本内容详情富文本内容详情富文本内容
-				详情富文本内容详情富文本内容详情富文本内容详情富文本内容
+				<rich-text :nodes="courseDetailInfo.details"></rich-text>
 			</view>
 			<view class="c-notice" id="notice">
 				<view class="title">购买须知</view>
 				<view class="tips-text">
 					<view class="text">
-						<view class="">1.购买后,需按照课表按时上课;</view>
-						<view class="">2.如有特殊情况,需上传相关证明;</view>
-						<view class="">3.由于特殊情况耽误了课程,后续会发布补课表,集中补课</view>
+						<rich-text :nodes="courseDetailInfo.reminder"></rich-text>
 					</view>
 					<view class="more">
 						<text>查看更多</text>
@@ -73,12 +72,12 @@
 			<view class="c-schedule" id="schedule">
 				<view class="title">课程表</view>
 				<view class="list-card">
-					<view class="card-title">总共6节</view>
-					<view class="schedule-list" v-for="item in 5">
+					<view class="card-title">总共{{courseDetailInfo.courseDetail.length}}节</view>
+					<view class="schedule-list" v-for="item in courseDetailInfo.courseDetail" :key="item.id">
 						<view class="time">
-							<text>05.06 17:00-19:00</text>
+							<text>{{item.startTime}}-{{item.endTime}}</text>
 						</view>
-						<view class="name">第一节:篮球热身运动</view>
+						<view class="name">{{item.name}}</view>
 					</view>
 					<view class="more">
 						<text>查看更多</text>
@@ -145,9 +144,11 @@
 
 <script lang="ts" setup>
 	import { ref, onMounted, getCurrentInstance, nextTick } from 'vue';
-	import { RouterUtils } from '@/utils/util';
+	import { RouterUtils,_previewImage } from '@/utils/util';
+	import { http } from '@/utils/http'
 	import zzxNavbar from '@/components/zzx-navbar/zzx-navbar.vue';
 	import { onLoad, onPageScroll } from '@dcloudio/uni-app';
+	import { useCacheStore } from '@/stores/cache'
 	const statusBarHeight = ref(0);
 	const sectionTops = ref<number[]>([]);
 	const isScrollingByTab = ref(false);
@@ -155,11 +156,16 @@
 	const sel_index = ref(0);
 	const selectList = ref(['详情', '须知', '课表', '评价']);
 	const instance = getCurrentInstance();
+	const cache = useCacheStore()
+	onLoad((option) => {
+		courseId.value = option.id
+	})
 	onMounted(() => {
 		get_navheight()
 		nextTick(() => {
 			setTimeout(() => getSectionsTop(), 300);
 		});
+		get_courseInfo()
 	})
 
 	// 获取所有模块的位置信息
@@ -171,7 +177,7 @@
 		});
 		query.exec((rects) => {
 			// 计算各模块相对于页面顶部的距离
-			sectionTops.value = rects.map((rect:any) => rect.top -130);
+			sectionTops.value = rects.map((rect : any) => rect.top - 130);
 		})
 	};
 
@@ -235,10 +241,26 @@
 			});
 		});
 	}
-	
-	const toOrderPage=()=>{
+
+	const toOrderPage = () => {
 		RouterUtils.to_page('/pages/index/submitOrder/index')
 	}
+
+	const courseId = ref()
+	const courseDetailInfo=ref()
+	const bannerList = ref([])
+	const videoList = ref([])
+	const get_courseInfo = () => {
+		http.get('/detail/getCourseInfo', { data: { id: courseId.value || '22222', latitude: cache.get('LAT'), longitude: cache.get('LON') }, loading: true }).then((res) => {
+			const startIndex = res.result.cover.indexOf('"') + 1;
+			const endIndex = res.result.cover.lastIndexOf('');
+			bannerList.value = res.result.cover.slice(startIndex, endIndex).split(',');
+			let videoIndex = res.result.video.indexOf('"') + 1;
+			let videoEndIndex = res.result.video.lastIndexOf('');
+			videoList.value = res.result.video.slice(videoIndex, videoEndIndex).split(',');
+			courseDetailInfo.value=res.result
+		})
+	}
 </script>
 
 <style lang="less" scoped>
@@ -248,6 +270,7 @@
 		.header-bg {
 			position: absolute;
 			width: 100%;
+			height: 432rpx;
 			z-index: -100;
 		}
 
@@ -346,6 +369,22 @@
 
 			.c-instructor {
 				margin-top: 20rpx;
+				display: flex;
+				align-items: center;
+				gap: 20rpx;
+				font-size: 24rpx;
+				color: #AAAAAA;
+				.c-instructor-title{
+					
+				}
+				.c-instructor-name{
+					text-align: center;
+					&>image{
+						width: 60rpx;
+						height: 60rpx;
+						border-radius: 50%;
+					}
+				}
 			}
 		}
 
@@ -423,6 +462,8 @@
 			background: #FFFFFF;
 			border-radius: 32rpx;
 			padding: 20rpx;
+			font-size: 24rpx;
+			color: #222222;
 		}
 
 		.c-notice {
@@ -611,52 +652,61 @@
 			}
 		}
 	}
-	.c-bottom{
+
+	.c-bottom {
 		display: flex;
 		align-items: center;
 		justify-content: space-between;
 		position: fixed;
 		bottom: 0;
-		width:95%;
+		width: 95%;
 		padding: 20rpx;
 		background: #fff;
-		box-shadow: 0rpx -6rpx 12rpx 2rpx rgba(0,0,0,0.09);
+		box-shadow: 0rpx -6rpx 12rpx 2rpx rgba(0, 0, 0, 0.09);
 		border-radius: 32rpx 32rpx 0rpx 0rpx;
-		.c-share{
+
+		.c-share {
 			font-weight: bold;
 			font-size: 28rpx;
 			color: #222222;
 			text-align: center;
 		}
-		.c-buy-btn{
+
+		.c-buy-btn {
 			display: flex;
 			align-items: center;
 			gap: 16rpx;
-			.buy{
+
+			.buy {
 				width: 226rpx;
 				height: 100rpx;
 				background: #222222;
 				border-radius: 60rpx;
 				text-align: center;
-				.buy-text{
+
+				.buy-text {
 					margin-top: 8rpx;
 					font-weight: bold;
 					font-size: 32rpx;
 					color: #D3FD76;
 				}
-				.buy-price{
+
+				.buy-price {
 					color: #D3FD76;
-					&>text:first-child{
+
+					&>text:first-child {
 						font-weight: bold;
 						font-size: 28rpx;
 					}
-					&>text:last-child{
+
+					&>text:last-child {
 						margin-left: 6rpx;
 						font-size: 22rpx;
 					}
 				}
 			}
-			.gratis{
+
+			.gratis {
 				width: 226rpx;
 				height: 100rpx;
 				background: #D3FD76;
@@ -665,7 +715,7 @@
 				font-size: 32rpx;
 				color: #222222;
 				text-align: center;
-				line-height: 100rpx ;
+				line-height: 100rpx;
 			}
 		}
 	}

+ 27 - 16
src/pages/index/detail/components/course.vue

@@ -6,47 +6,58 @@
 		</view>
 		<view class="select-btn">
 			<view :class="sel_btn===index?'distance':'score'" v-for="(item,index) in selectList" :key="index"
-				@click="select_btn(index)">{{item}}</view>
+				@click="select_btn(item,index)">{{item.name}}</view>
 		</view>
-		<view class="venue-card" v-for="item in 2" @click="toCOurseDetail">
-			<image src="https://img.keaitupian.cn/newupload/08/1629449018344288.jpg" mode=""></image>
+		<view class="venue-card" v-for="item in listData" :key="item.id" @click="toCourseDetail(item)">
+			<image :src="item.cover" mode=""></image>
 			<view class="venue-info">
 				<view class="info-title">
-					<view class="title textHidden">小班体适能+篮球衔接小班体适能+篮球衔接...</view>
-					<view class="sales">年售20</view>
+					<view class="title textHidden">{{item.name}}</view>
+					<view class="sales">年售{{item.salesYear}}</view>
 				</view>
 				<view class="type">
-					篮球、足球、羽毛球
+					上课地点:{{item.address}} | {{item.km||'--'}}km
+				</view>
+				<view class="type">
+					{{item.count||'0'}}课时 {{item.startTime}}-{{item.endTime}}
 				</view>
 				<view class="price">
-					<view class="">¥58.9</view>
-					<view class="">¥80.9</view>
+					<view class="">¥{{item.sellingPrice}}</view>
+					<view class="">¥{{item.originalPrice}}</view>
 				</view>
 				<view class="price-info">
 					<view class="sale">
-						已售33 98%好评
+						已售{{item.sales}} {{item.goodRate}}%好评
 					</view>
 					<view class="price-btn">免费试听</view>
 				</view>
 			</view>
 		</view>
-		<!-- <loading/> -->
+		<view class="not-data" v-if="listData.length<1">暂无数据</view>
 		<view class="more">查看更多</view>
 	</view>
 </template>
 
 <script lang="ts" setup>
 	import { ref } from 'vue';
-	import loading from '@/components/zzx-loading/zzx-loading.vue';
-	const selectList = ref(['篮球', '羽毛球','乒乓球','网球']);
+	interface Props {
+		listData ?: any;
+		selectList?:any;
+	}
+	const props = withDefaults(defineProps<Props>(), {
+		listData: [],
+		selectList:[],
+	});
+	const emit = defineEmits(['change']);
 	const sel_btn=ref(0);
-	const select_btn=(i)=>{
+	const select_btn=(e,i)=>{
 		sel_btn.value=i
+		emit('change', e, i);
 	}
 	
-	const toCOurseDetail=()=>{
+	const toCourseDetail=(e)=>{
 		uni.navigateTo({
-			url:'/pages/index/courseDetail/index'
+			url:`/pages/index/courseDetail/index?id=${e.id}`
 		})
 	}
 </script>
@@ -115,7 +126,7 @@
 			}
 			.venue-info{
 				width: 430rpx;
-				height: 200rpx;
+				height: 260rpx;
 				border-bottom: 1rpx solid #F0F0F0;
 				.info-title{
 					display: flex;

+ 16 - 6
src/pages/index/detail/components/instructor.vue

@@ -1,25 +1,35 @@
 <template>
 	<view class="instructor-card">
 		<view class="card-title">
-			<view class="">教练(9)</view>
+			<view class="">教练({{instrctorList.length}})</view>
 			<zzx-icon name="right" size="12"></zzx-icon>
 		</view>
 		<scroll-view class="header-swiper content" scroll-x="true" :show-scrollbar="false">
 			<view class="swiper-box">
-				<view class="swiper-inner" v-for="item in 12">
+				<view class="swiper-inner" v-for="item in instrctorList" :key="item.id">
 					<view class="header-img">
-						<image src="https://img.keaitupian.cn/newupload/08/1629449018344288.jpg" mode=""></image>
+						<image :src="item.avatar" mode=""></image>
 						<image src="/src/static/badge.png" mode=""></image>
 					</view>
-					<view class="instructor-name">詹姆斯</view>
-					<view class="instructor-specialty">篮球</view>
+					<view class="instructor-name">{{item.name}}</view>
+					<view class="instructor-specialty">
+						<text v-for="(category,index) in item.category" :key="index">{{category}}</text>
+					</view>
 				</view>
 			</view>
 		</scroll-view>
+		<zs-empty v-if="instrctorList.length<1"></zs-empty>
 	</view>
 </template>
 
-<script>
+<script lang="ts" setup>
+	import zsEmpty from '@/components/zs-empty/index.vue'
+	interface Props {
+		instrctorList ?: any;
+	}
+	const props = withDefaults(defineProps<Props>(), {
+		instrctorList: []
+	});
 </script>
 
 <style lang="less" scoped>

+ 19 - 7
src/pages/index/detail/components/venue.vue

@@ -1,18 +1,18 @@
 <template>
-	<view class="venue-card" v-for="item in 10">
-		<image src="https://img.shetu66.com/2023/06/13/1686646672844195.jpg" mode=""></image>
+	<view class="venue-card" v-for="(item,index) in listData" :key="index" @click="venuePreview(item)">
+		<image :src="item.cover" mode=""></image>
 		<view class="venue-info">
 			<view class="info-title">
-				<view class="title textHidden">指定时段免费畅玩</view>
-				<view class="sales">年售20</view>
+				<view class="title textHidden">{{item.name}}</view>
+				<view class="sales">年售{{item.sales}}</view>
 			</view>
 			<view class="type">
-				篮球、足球、羽毛球
+				<text v-for="(category,index) in item.category" :key="index">{{category}}</text>
 			</view>
 			<view class="price-info">
 				<view class="price">
-					<view class="">¥58.9</view>
-					<view class="">¥80.9</view>
+					<view class="">¥{{item.sellingPrice}}</view>
+					<view class="">¥{{item.originalPrice}}</view>
 				</view>
 				<view class="price-btn">免费预约</view>
 			</view>
@@ -21,6 +21,18 @@
 </template>
 
 <script lang="ts" setup>
+	interface Props {
+		listData ?: any;
+	}
+	const props = withDefaults(defineProps<Props>(), {
+		listData: []
+	});
+	
+	const venuePreview = (item: any) => {
+		uni.navigateTo({
+			url: '/pages/index/submitOrder/index?id=' + item.id
+		})
+	}
 </script>
 
 <style lang="less" scoped>

+ 118 - 50
src/pages/index/detail/index.vue

@@ -1,58 +1,60 @@
 <template>
 	<zzx-navbar :scrollable="true" :back="true" title="详情"></zzx-navbar>
 	<view class="detail-header">
-		<image class="header-bg"
-			src="https://ts1.tc.mm.bing.net/th/id/R-C.a8553f142638e741396e386b43c2bca7?rik=dzSGk6XRsxAAsQ&riu=http%3a%2f%2fseopic.699pic.com%2fphoto%2f50062%2f5890.jpg_wh1200.jpg&ehk=BgxiqxvzoNQd0pZHWV4VPOMbYgqM76WDMt8RDzCjoYY%3d&risl=&pid=ImgRaw&r=0"
-			mode="widthFix"></image>
+		<image class="header-bg" :src="bannerList[0]" mode=""></image>
 		<view class="back-icon" :style="{paddingTop:(statusBarHeight+10)+'px'}" @click="RouterUtils.back()">
 			<zzx-icon name="back"></zzx-icon>
 		</view>
 		<view :style="{height:(statusBarHeight+70)+'px'}"></view>
 		<scroll-view class="header-swiper content" scroll-x="true" :show-scrollbar="false">
 			<view class="swiper-inner">
-				<video src="https://vod.v.jstv.com/2025/05/09/JSTV_JSGGNEW_1746791056693_2lBi96K_114.mp4"></video>
-				<image v-for="item in 4"
-					src="https://bpic.588ku.com/element_origin_min_pic/23/07/11/d32dabe266d10da8b21bd640a2e9b611.jpg!r650"
-					mode=""></image>
+				<block  v-if="detailInfo.video">
+					<video v-for="(item,index) in videoList" :key="index" :src="item"></video>
+				</block>
+				<!-- <view class="swiper-image-box"> -->
+				<image @click="_previewImage(bannerList)" v-for="(item,index) in bannerList" :key="index" :src="item" mode=""></image>
+				<!-- </view> -->
 			</view>
 		</scroll-view>
 	</view>
 	<view :style="{height:(statusBarHeight+34)+'px'}"></view>
 	<view class="header-info">
 		<view class="venue-name">
-			<view class="name">观山湖区第十二小学</view>
+			<view style="display: flex;gap: 20rpx;align-items: center;">
+				<view class="name">{{detailInfo.name}}</view>
+				<view class="open-status">{{detailInfo.runStatus?'开放中':'歇业中'}}</view>
+			</view>
 			<view class="star">
 				<zzx-icon name="star" size="12"></zzx-icon>
-				<text>4.8</text>
+				<text>{{detailInfo.goodRate}}</text>
 			</view>
 		</view>
 		<view class="open-time">
-			<view class="open-status">开放中</view>
 			<view class="time">
-				<view class="">教学日 10:00-22:00</view>
-				<view class="">非教学日 10:00-22:00</view>
+				<view>教学日 <text style="margin-right: 14rpx;" v-for="(item,index) in teachingDay.data" :key="index">{{item.startTime+'-'+item.endTime||'--'}}</text></view>
+				<view class="">非教学日 <text style="margin-right: 14rpx;" v-for="(item,index) in noTeachingDay.data" :key="index">{{item.startTime+'-'+item.endTime||'--'}}</text></view>
 			</view>
 		</view>
 		<view class="venues-tags">
 			<view class="tags-box">
-				<view class="tags" v-for="item in 4">无烟环境</view>
+				<view class="tags" v-for="(item,index) in detailInfo.facilityInfo" :key="index">{{item}}</view>
 			</view>
-			<view class="more-info">
+<!-- 			<view class="more-info" @click="RouterUtils.to_page(`/pages/index/basisInfo/index`)">
 				<text>信息/设备设施</text>
 				<zzx-icon name="ashRight" size="10"></zzx-icon>
-			</view>
+			</view> -->
 		</view>
 		<view class="venues-address">
 			<view class="address">
 				<zzx-icon name="location" size="14"></zzx-icon>
-				<text>印象城购物中心6楼</text>
+				<text>{{detailInfo.address}}</text>
 			</view>
 			<view class="nav-phone">
-				<view class="nav">
+				<view class="nav" @click="openMap">
 					<zzx-icon name="navigation" size="14"></zzx-icon>
 					<view class="">导航</view>
 				</view>
-				<view class="phone">
+				<view class="phone" @click="openphone">
 					<zzx-icon name="phone" size="14"></zzx-icon>
 					<view class="">电话</view>
 				</view>
@@ -62,31 +64,34 @@
 	<view class="content">
 		<uv-sticky offset-top="74">
 			<view class="detail-select">
-				<view :class="sel_index===index?'select-text':'notsel-text'" v-for="(item,index) in selectList" :key="index"
-					@click="sel_tab(index)">
+				<view :class="sel_index===index?'select-text':'notsel-text'" v-for="(item,index) in selectList"
+					:key="index" @click="sel_tab(index)">
 					<text>{{item}}</text>
 				</view>
 			</view>
 		</uv-sticky>
-			<view class="toggle" v-if="sel_index===0">
-				<venue/>
-			</view>
-			<view class="toggle" v-else-if="sel_index===1">
-				<course/>
-			</view>
-			<view class="toggle" v-else-if="sel_index===2">
-				<instructor/>
-			</view>
-			<view class="toggle" v-else>
-				<appraise/>
-			</view>
+		<view class="toggle" v-if="sel_index===0">
+			<venue :listData="detailInfo.placeInfoMsgVO" />
+			<zs-empty v-if="detailInfo.placeInfoMsgVO.length<1"></zs-empty>
+		</view>
+		<view class="toggle" v-else-if="sel_index===1">
+			<course :selectList="allCategoryList" :listData="courseList" :laoding="courseLoading"  @change="onchange" />
+		</view>
+		<view class="toggle" v-else-if="sel_index===2">
+			<instructor :instrctorList="detailInfo.instructorVOList" />
+		</view>
+		<view class="toggle" v-else>
+			<appraise />
+		</view>
 	</view>
 </template>
 
 <script lang="ts" setup>
 	import { ref, onMounted } from 'vue';
-	import { RouterUtils } from '@/utils/util';
+	import { RouterUtils,_previewImage } from '@/utils/util';
+	import { http } from '@/utils/http'
 	import zzxNavbar from '@/components/zzx-navbar/zzx-navbar.vue';
+	import zsEmpty from '@/components/zs-empty/index.vue'
 	import venue from './components/venue.vue';
 	import course from './components/course.vue';
 	import instructor from './components/instructor.vue';
@@ -94,10 +99,15 @@
 	import { onLoad, onPageScroll } from '@dcloudio/uni-app';
 	const statusBarHeight = ref(0);
 	const selectList = ref(['场地', '课程', '教练', '评价']);
-	const sel_index = ref(0)
-	onMounted(() => {
+	const sel_index = ref(0);
+	onLoad((option) => {
+		listId.value = option.id
 		get_navheight()
 	})
+	onMounted(() => {
+		get_placeInfo()
+		get_allCategory()
+	})
 	const get_navheight = () => {
 		const systemInfo = uni.getSystemInfoSync();
 		statusBarHeight.value = systemInfo.statusBarHeight || 0;
@@ -106,6 +116,67 @@
 	const sel_tab = (i) => {
 		sel_index.value = i
 	}
+
+	const listId = ref(0);
+	const detailInfo = ref({})
+	const bannerList = ref([])
+	const videoList = ref([])
+	const noTeachingDay=ref()
+	const teachingDay=ref()
+	const get_placeInfo = () => {
+		http.get('/detail/getPlaceInfo', { data: { id: listId.value }, loading: true }).then((res) => {
+			const startIndex = res.result.cover.indexOf('"') + 1;
+			const endIndex = res.result.cover.lastIndexOf('');
+			bannerList.value = res.result.cover.slice(startIndex, endIndex).split(',');
+			let videoIndex = res.result.video.indexOf('"') + 1;
+			let videoEndIndex = res.result.video.lastIndexOf('');
+			videoList.value = res.result.video.slice(videoIndex, videoEndIndex).split(',');
+			detailInfo.value = res.result
+			noTeachingDay.value=JSON.parse(res.result.noTeachingDay)
+			teachingDay.value=JSON.parse(res.result.teachingDay)
+		})
+	}
+
+	const openphone = () => {
+		uni.makePhoneCall({
+			phoneNumber: detailInfo.value.phone
+		});
+	}
+	
+	const openMap=()=>{
+		uni.openLocation({
+			latitude: detailInfo.value.latitude,
+			longitude: detailInfo.value.longitude,
+			name: detailInfo.value.name,
+			address: detailInfo.value.address,
+			success: function () {
+				console.log('success');
+			}
+		});
+	}
+	
+	
+	// 课程分类
+	const allCategoryList=ref([])
+	const categoryId=ref()
+	const get_allCategory=()=>{
+		http.get('/detail/getAllCategory', { data: { id: listId.value}}).then((res)=>{
+			categoryId.value=res.result[0].id
+			allCategoryList.value=res.result
+			get_courseList(categoryId.value)
+		})
+	}
+	const onchange=(e)=>{
+		get_courseList(e.id)
+	}
+	// 课程列表
+	const courseList=ref([])
+	const get_courseList=(categoryId)=>{
+		http.get('/detail/courseInfoVOList',{data:{categoryId:categoryId,id:listId.value},loading:true}).then((res)=>{
+			courseList.value=res.result
+		})
+	}
+	
 </script>
 
 <style lang="less" scoped>
@@ -115,6 +186,7 @@
 		.header-bg {
 			position: absolute;
 			width: 100%;
+			height: 432rpx;
 			z-index: -100;
 		}
 
@@ -144,8 +216,7 @@
 				gap: 14rpx;
 				height: 100%;
 
-				&>video,
-				&>image {
+				&>video ,&>image {
 					width: 220rpx;
 					height: 126rpx;
 					border-radius: 16rpx;
@@ -165,6 +236,11 @@
 			align-items: center;
 			justify-content: space-between;
 
+			.open-status {
+				width: 100rpx;
+				font-size: 24rpx;
+				color: #4DD951;
+			}
 			.name {
 				font-weight: 800;
 				font-size: 32rpx;
@@ -181,22 +257,13 @@
 		}
 
 		.open-time {
-			display: flex;
-			align-items: center;
-			gap: 20rpx;
 			margin-top: 20rpx;
-
-			.open-status {
-				font-size: 24rpx;
-				color: #4DD951;
-			}
-
 			.time {
-				display: flex;
-				align-items: center;
-				gap: 20rpx;
 				font-size: 24rpx;
 				color: #AAAAAA;
+				&>view{
+					margin-top: 20rpx;
+				}
 			}
 		}
 
@@ -268,7 +335,8 @@
 		gap: 60rpx;
 		margin-top: 20rpx;
 		height: 80rpx;
-		background-color:#F6F6F6;
+		background-color: #F6F6F6;
+
 		.select-text,
 		.notsel-text {
 			position: relative;

+ 130 - 42
src/pages/index/gymDetail/components/popup.vue

@@ -1,43 +1,53 @@
 <template>
 	<uni-popup ref="selectPopup" :safe-area="false" type="bottom">
-		<view class="header-text">开场前60分钟随时退</view>
+		<view class="header-text">开场前{{listData.earlyRefundTime||'--'}}分钟随时退</view>
 		<view class="select-popup">
 			<view class="pop-title">选择场次</view>
 			<view class="pop-date-list">
 				<scroll-view scroll-x="true" class="scroll-view_H">
-					<view class="scroll-view-item" v-for="(item,index) in 7" @click="sel_tab(index)">
-						<view class="today-time">今天(06-09)</view>
-						<view class="num">5场可订</view>
-						<view class="line" v-if="sel_index===index"></view>
+					<view class="scroll-view-item" v-for="(item,index) in listData.stadiumConcertsVOList" :key="index"
+						@click="sel_tab(item,index)">
+						<view class="today-time">{{item.weekDayAndDate}}</view>
+						<view class="num">{{item.noDayConcertsReservationNum||'0'}}场可订</view>
+						<view class="line" v-if="deteObj==index"></view>
 					</view>
 				</scroll-view>
 			</view>
 			<view class="gym-list">
 				<view class="time-list">
-					<view style="height: 26rpx;"></view>
-					<view class="item-time" v-for="(item,index) in time_list" :key="index">{{item}}</view>
+					<view class="time-title">时间段</view>
+					<block
+						v-for="(concert,index) in listData.stadiumConcertsVOList[0].concertsVOList[0].concertsDetailsVOList"
+						:key="index">
+						<view class="item-time">{{concert.startTime}}-{{concert.endTime}}</view>
+					</block>
 				</view>
 				<view class="table-list">
 					<scroll-view scroll-x="true" class="table-scroll">
-						<view class="father-list" v-for="item in 7">
-							<view class="father-title">羽毛球1</view>
-							<view class="children-list" v-for="item in 13">
-								<view class="item-card">¥35</view>
+						<view class="father-list" v-for="(conc,index) in itemList" :key="index"
+							style="vertical-align: top;">
+							<view class="father-title">{{conc.sitePlaceName}}</view>
+							<view class="children-list" v-for="(concert,index) in conc.concertsDetailsVOList"
+								:key="index">
+								<view class="item-card" :class="{ selected: isSelected(concert) }"
+									@click="selectItem(conc, concert)">
+									¥{{concert.price}}
+								</view>
 							</view>
 						</view>
 					</scroll-view>
 				</view>
 			</view>
-			<view class="select-list">
+			<view class="select-list" v-if="selArr.length>0">
 				<view class="select-title">已选场次</view>
 				<scroll-view scroll-x="true" class="select-scroll">
-					<view class="item-list" v-for="item in 7">
+					<view class="item-list" v-for="(item,index) in selArr" :key="index">
 						<view class="list-box">
 							<view class="list-text">
-								<view class="">16:00-17:00</view>
-								<view class="">羽毛球1</view>
+								<view class="">{{item.time}}</view>
+								<view class="">{{item.name}}</view>
 							</view>
-							<zzx-icon name="cancel" size="12"></zzx-icon>
+							<view @click="deleteSelarr(item)"> <zzx-icon name="cancel" size="12"></zzx-icon></view>
 						</view>
 					</view>
 				</scroll-view>
@@ -46,7 +56,7 @@
 			<view class="footer-submit">
 				<view class="f-price">
 					<view class="">总价</view>
-					<view class="">¥50.59</view>
+					<view class="">¥{{priceTotal}}</view>
 				</view>
 				<view class="f-btn" @click="submit_order">
 					<button>提交订单</button>
@@ -54,44 +64,44 @@
 			</view>
 		</view>
 	</uni-popup>
-	<view>
+	<view v-if="isopenDetail">
 		<uni-popup ref="orderPopup" :safe-area="false" type="bottom">
-			<view class="header-text">开场前60分钟随时退</view>
+			<view class="header-text">开场前{{previewgymOrderDetail.earlyRefundTime||'--'}}分钟随时退</view>
 			<view class="order-popup">
 				<view class="p-header-card">
 					<view class="p-school-info">
 						<zzx-icon name="pay-icon1" size="16"></zzx-icon>
-						<view class="name">观山湖区第十二小学</view>
+						<view class="name">{{previewgymOrderDetail.storeName}}</view>
 					</view>
 					<view class="p-title">羽毛球场地预定</view>
 					<view class="p-preset">
-						<view class="preset-info" v-for="item in 3">06-11(周三)11:00-12:00|羽毛球1</view>
+						<view class="preset-info" v-for="item in previewgymOrderDetail.timePeriod" :key="item.id">{{item.name}}</view>
 					</view>
 				</view>
 				<view class="p-price-card">
 					<view class="p-price">
-						<view class="text">商品总价(共3场)</view>
-						<view class="price"><text class="mini-text">¥</text>50.59</view>
+						<view class="text">商品总价(共{{previewgymOrderDetail.timePeriod.length}}场)</view>
+						<view class="price"><text class="mini-text">¥</text>{{previewgymOrderDetail.subtotal}}</view>
 					</view>
 					<view class="p-subtotal">
 						<text>小计</text>
-						<view class="total-price"><text class="mini-text">¥</text>50.59</view>
+						<view class="total-price"><text class="mini-text">¥</text>{{previewgymOrderDetail.totalPrice}}</view>
 					</view>
 				</view>
 				<view class="p-phone-card">
 					<view class="p-phone">
 						<view class="text">手机号码</view>
-						<view class="phone">159****2066</view>
+						<view class="phone">{{phoneHide(previewgymOrderDetail.mobile)}}</view>
 					</view>
 					<view class="tips">请通话畅通,商家需要联系您确认到店时间</view>
 				</view>
 				<view class="p-rules-card">
 					<view class="p-title">退改规则</view>
-					<view class="p-text">每场开场前<text>60分钟</text>可随时退改,之后不可退款。如您有疑问,可联系场馆。</view>
+					<view class="p-text">每场开场前<text>{{previewgymOrderDetail.earlyRefundTime}}分钟</text>可随时退改,之后不可退款。如您有疑问,可联系场馆。</view>
 				</view>
 				<view class="p-rules-card">
 					<view class="p-title">温馨提示</view>
-					<view class="p-text">场地仅限个人使用,培训、比赛或者其他商业活动可能需要额外收费,如有需求请提前联系商家咨询收费标准。</view>
+					<view class="p-text">{{previewgymOrderDetail.reminder}}</view>
 				</view>
 				<view class="p-remark">
 					<view class="title">备注</view>
@@ -100,7 +110,7 @@
 				<view style="height: 200rpx;"></view>
 				<view class="footer-pay">
 					<button hover-class="hover-style">
-						<view class="btn-price"><text class="mini-text">¥</text>50.59</view>
+						<view class="btn-price"><text class="mini-text">¥</text>{{previewgymOrderDetail.totalPrice}}</view>
 						<view class="btn-text">立即支付</view>
 					</button>
 				</view>
@@ -110,28 +120,88 @@
 </template>
 
 <script lang="ts" setup>
-	import { ref } from 'vue';
+	import { ref,onMounted, computed } from 'vue';
+	import { http } from '@/utils/http'
+	import { TipsUtils,phoneHide } from '@/utils/util';
+	interface Props {
+		listData ?: any;
+		itemList ?: any;
+		deteObj?:any
+	}
+	const props = withDefaults(defineProps<Props>(), {
+		listData: [],
+		itemList: [],
+		deteObj:null
+	});
 	const selectPopup = ref();
 	const orderPopup = ref()
 	const sel_index = ref(0);
-	const time_list = ref(['09:00', '10:00', '11:00', '12:00', '13:00', '14:00', '15:00', '16:00', '17:00', '18:00', '19:00', '20:00', '21:00', '22:00'])
+	const time_list = ref([])
+	onMounted(()=>{
+		
+	})
 	const open = () => {
 		selectPopup.value.open()
 	}
 	defineExpose({
 		open
 	})
+	const emit = defineEmits(['change']);
+	const sel_tab = (e, i) => {
+		emit('change', e, i);
+	}
 
-	const sel_tab = (i) => {
-		sel_index.value = i
+	const selArr = ref([])
+	const selectItem = (item1, item2) => {
+		const existingIndex = selArr.value.findIndex(item => item.id === item2.id);
+		if (existingIndex !== -1) {
+			selArr.value.splice(existingIndex, 1);
+		} else {
+			selArr.value.push({
+				name: item1.sitePlaceName,
+				time: item2.startTime + '-' + item2.endTime,
+				price: item2.price,
+				id: item2.id
+			});
+		}
 	}
 
+	const isSelected = (concert) => {
+		return selArr.value.some(item => item.id === concert.id);
+	}
+
+	const priceTotal = computed(() => {
+		return selArr.value.reduce((total, item) => {
+			return total + item.price
+		}, 0)
+	})
+
+	const deleteSelarr = (item) => {
+		const index = selArr.value.findIndex(selItem => selItem.id === item.id);
+		if (index !== -1) {
+			selArr.value.splice(index, 1);
+		}
+	}
+	
 	const submit_order = () => {
-		selectPopup.value.close()
-		orderPopup.value.open()
-		// uni.navigateTo({
-		// 	url:'/pages/index/gymPay/index'
-		// })
+		if(selArr.value.length<1){
+			return TipsUtils.tips_toast('请选择场次')
+		}
+		get_previewOrderPlaceGymnasiumChartered()
+	}
+	
+	const previewgymOrderDetail=ref()
+	const isopenDetail = ref(false)
+	const get_previewOrderPlaceGymnasiumChartered=()=>{
+		const result = selArr.value.map(item => item.id).join(',')
+		http.get('/order/previewOrderPlaceGymnasiumChartered',{data:{rulesId:result},loading:true}).then((res)=>{
+			previewgymOrderDetail.value=res.result
+			isopenDetail.value=true
+			setTimeout(()=>{
+				selectPopup.value.close()
+				orderPopup.value.open()
+			},500)
+		})
 	}
 </script>
 
@@ -206,7 +276,16 @@
 			padding: 20rpx;
 
 			.time-list {
-				width: 100rpx;
+				width: 180rpx;
+
+				.time-title {
+					height: 60rpx;
+					line-height: 60rpx;
+					text-align: center;
+					font-weight: bold;
+					font-size: 24rpx;
+					color: #222222;
+				}
 
 				.item-time {
 					margin-bottom: 20rpx;
@@ -250,6 +329,10 @@
 								color: #222222;
 								text-align: center;
 								line-height: 54rpx;
+
+								&.selected {
+									background: #C8FF0C !important;
+								}
 							}
 						}
 					}
@@ -509,7 +592,8 @@
 			bottom: 0;
 			padding: 0 20rpx;
 			z-index: 9999;
-			&>button{
+
+			&>button {
 				width: 686rpx;
 				height: 100rpx;
 				background: #C8FF0C;
@@ -518,21 +602,25 @@
 				align-items: center;
 				justify-content: center;
 				gap: 10rpx;
+
 				&>button::after {
 					border: none;
 				}
-				.btn-price{
+
+				.btn-price {
 					font-weight: 800;
 					font-size: 48rpx;
 					color: #222222;
 				}
-				.btn-text{
+
+				.btn-text {
 					font-weight: bold;
 					font-size: 32rpx;
 					color: #222222;
 				}
 			}
-			.hover-style{
+
+			.hover-style {
 				color: #999999;
 			}
 		}

+ 202 - 77
src/pages/index/gymDetail/index.vue

@@ -1,51 +1,51 @@
 <template>
 	<zzx-navbar :scrollable="true" :back="true" title="详情"></zzx-navbar>
 	<view class="detail-header">
-		<image class="header-bg"
-			src="https://ts1.tc.mm.bing.net/th/id/R-C.a8553f142638e741396e386b43c2bca7?rik=dzSGk6XRsxAAsQ&riu=http%3a%2f%2fseopic.699pic.com%2fphoto%2f50062%2f5890.jpg_wh1200.jpg&ehk=BgxiqxvzoNQd0pZHWV4VPOMbYgqM76WDMt8RDzCjoYY%3d&risl=&pid=ImgRaw&r=0"
-			mode="widthFix"></image>
+		<image class="header-bg" :src="bannerList[0]" mode=""></image>
 		<view class="back-icon" :style="{paddingTop:(statusBarHeight+10)+'px'}" @click="RouterUtils.back()">
 			<zzx-icon name="back"></zzx-icon>
 		</view>
 		<view :style="{height:(statusBarHeight+70)+'px'}"></view>
 		<scroll-view class="header-swiper content" scroll-x="true" :show-scrollbar="false">
 			<view class="swiper-inner">
-				<video src="https://vod.v.jstv.com/2025/05/09/JSTV_JSGGNEW_1746791056693_2lBi96K_114.mp4"></video>
-				<image v-for="item in 4"
-					src="https://bpic.588ku.com/element_origin_min_pic/23/07/11/d32dabe266d10da8b21bd640a2e9b611.jpg!r650"
-					mode=""></image>
+				<block  v-if="detailInfo.video">
+					<video v-for="(item,index) in videoList" :key="index" :src="item"></video>
+				</block>
+				<image v-for="(item,index) in bannerList" :key="index" :src="item" mode=""></image>
 			</view>
 		</scroll-view>
 	</view>
 	<view :style="{height:(statusBarHeight+34)+'px'}"></view>
 	<view class="header-info">
 		<view class="venue-name">
-			<view class="name">观山湖区第十二小学</view>
+			<view style="display: flex;gap: 20rpx;align-items: center;">
+				<view class="name">{{detailInfo.name}}</view>
+				<view class="open-status">{{detailInfo.runStatus?'营业中':'歇业中'}}</view>
+			</view>
 			<view class="star">
 				<zzx-icon name="star" size="12"></zzx-icon>
-				<text>4.8</text>
+				<text>{{detailInfo.goodRate}}</text>
 			</view>
 		</view>
 		<view class="open-time">
-			<view class="open-status">开放中</view>
 			<view class="time">
-				<view class="">教学日 10:00-22:00</view>
-				<view class="">非教学日 10:00-22:00</view>
+				<view>教学日 <text style="margin-right: 14rpx;" v-for="(item,index) in teachingDay.data" :key="index">{{item.startTime+'-'+item.endTime||'--'}}</text></view>
+				<view class="">非教学日 <text style="margin-right: 14rpx;" v-for="(item,index) in noTeachingDay.data" :key="index">{{item.startTime+'-'+item.endTime||'--'}}</text></view>
 			</view>
 		</view>
 		<view class="venues-tags">
 			<view class="tags-box">
-				<view class="tags" v-for="item in 4">无烟环境</view>
+				<view class="tags" v-for="(item,index) in detailInfo.facilityInfo" :key="index">{{item}}</view>
 			</view>
-			<view class="more-info" @click="RouterUtils.to_page('/pages/index/basisInfo/index')">
+<!-- 			<view class="more-info" @click="RouterUtils.to_page('/pages/index/basisInfo/index')">
 				<text>信息/设备设施</text>
 				<zzx-icon name="ashRight" size="10"></zzx-icon>
-			</view>
+			</view> -->
 		</view>
 		<view class="venues-address">
 			<view class="address">
 				<zzx-icon name="location" size="14"></zzx-icon>
-				<text>印象城购物中心6楼</text>
+				<text>{{detailInfo.address}}</text>
 			</view>
 			<view class="nav-phone">
 				<view class="nav" @click="open_map">
@@ -76,7 +76,7 @@
 						<view style="margin-bottom: 10rpx;">包场</view>
 					</view>
 					<view class="">
-						开场前60分钟随时退
+						开场前{{charteredList.earlyRefundTime}}分钟随时退
 					</view>
 					<view class="v-left" @click="RouterUtils.to_page('/pages/index/vr/index')">
 						<zzx-icon name="venue-icon2" size="14"></zzx-icon>
@@ -85,16 +85,17 @@
 				</view>
 				<view class="v-select-infocard">
 					<view class="select-btn">
-						<view :class="sel_btn===index?'distance':'score'" v-for="(item,index) in selectList_btn"
-							:key="index" @click="select_btn(index)">{{item}}</view>
+				<view :class="selChartered===index?'distance':'score'" v-for="(item,index) in allCategoryList" :key="item.id"
+					@click="selectChartered(item,index)">{{item.name}}</view>
 					</view>
 					<view class="info-card-list">
 						<scroll-view scroll-x="true" class="scroll-view_H">
-							<view class="item-card scroll-view-item_H" v-for="item in 6" @click="open_popup">
-								<view class="today">今天(03-04)</view>
-								<view class="time">最早19:00可订</view>
-								<view class="price">¥58起</view>
+							<view class="item-card scroll-view-item_H" v-for="(item,index) in charteredList.timeSlot" :key="item.id" @click="open_popup(item,index)">
+								<view class="today">{{item.dateLabel}}</view>
+								<view class="time">最早{{item.startTime}}可订</view>
+								<view class="price">¥{{item.sellingPrice}}起</view>
 							</view>
+							<view class="not-data" v-if="charteredList.timeSlot.length<1">暂无可选时间</view>
 						</scroll-view>
 					</view>
 				</view>
@@ -104,27 +105,27 @@
 					<zzx-icon name="venue-icon3" size="14"></zzx-icon>
 					<view class="">无固定场</view>
 				</view>
-				<view class="item-card" v-for="item in 2">
-					<image src="https://img.shetu66.com/2023/06/13/1686646672844195.jpg" mode=""></image>
+				<view class="item-card" v-for="(item,index) in detailInfo.placeInfoMsgVO" :key="item.id">
+					<image :src="item.cover" mode=""></image>
 					<view class="venue-info">
 						<view class="info-title">
-							<view class="title textHidden">指定时段免费畅玩</view>
-							<view class="sales">年售20</view>
+							<view class="title textHidden">{{item.name}}</view>
+							<view class="sales">年售{{item.sales}}</view>
 						</view>
-						<view class="type">
+<!-- 						<view class="type">
 							篮球、足球、羽毛球
-						</view>
+						</view> -->
 						<view class="price-info">
 							<view class="price">
-								<view class="">¥58.9</view>
-								<view class="">¥80.9</view>
+								<view class="">¥{{item.sellingPrice}}</view>
+								<view class="">¥{{item.originalPrice}}</view>
 							</view>
 							<view class="price-btn" @click="RouterUtils.to_page('/pages/index/gymPay/index?type=1')">抢购
 							</view>
 						</view>
 					</view>
 					<view class="card-tips">
-						<view class="item-tips">
+						<view class="item-tips" @click="buyTips(item)">
 							<text>购买须知</text>
 							<zzx-icon name="ashRight" size="10"></zzx-icon>
 						</view>
@@ -132,10 +133,10 @@
 							<text>服务保障</text>
 							<zzx-icon name="ashRight" size="10"></zzx-icon>
 						</view>
-						<view class="item-tips">
+<!-- 						<view class="item-tips">
 							<text>用户评价</text>
 							<zzx-icon name="ashRight" size="10"></zzx-icon>
-						</view>
+						</view> -->
 					</view>
 				</view>
 			</view>
@@ -146,33 +147,39 @@
 				<view class="">全平台每种类型的运动课程只可免费试听一次</view>
 			</view>
 			<view class="select-btn">
-				<view :class="sel_btn===index?'distance':'score'" v-for="(item,index) in selectList_btn" :key="index"
-					@click="select_btn(index)">{{item}}</view>
+				<view :class="sel_btn===index?'distance':'score'" v-for="(item,index) in allCategoryList" :key="item.id"
+					@click="selectallCategory(item,index)">{{item.name}}</view>
 			</view>
-			<view class="venue-card" v-for="item in 2" @click="toCOurseDetail">
-				<image src="https://img.keaitupian.cn/newupload/08/1629449018344288.jpg" mode=""></image>
-				<view class="venue-info">
-					<view class="info-title">
-						<view class="title textHidden">小班体适能+篮球衔接小班体适能+篮球衔接...</view>
-						<view class="sales">年售20</view>
-					</view>
-					<view class="type">
-						篮球、足球、羽毛球
-					</view>
-					<view class="price">
-						<view class="">¥58.9</view>
-						<view class="">¥80.9</view>
-					</view>
-					<view class="price-info">
-						<view class="sale">
-							已售33 98%好评
+			<block v-if="!courseLoading">
+				<view class="venue-card" v-for="item in courseList" :key="item.id" @click="toCOurseDetail">
+					<image :src="item.cover" mode=""></image>
+					<view class="venue-info">
+						<view class="info-title">
+							<view class="title textHidden">{{item.name}}</view>
+							<view class="sales">年售{{item.salesYear}}</view>
+						</view>
+						<view class="type">
+							{{item.address}} {{item.km||'--'}}km
+						</view>
+						<view class="price">
+							<view class="">¥{{item.sellingPrice}}</view>
+							<view class="">¥{{item.originalPrice}}</view>
 						</view>
-						<view class="price-btn" @click="RouterUtils.to_page('/pages/index/courseDetail/index?type=2')">免费试听
+						<view class="course-count">
+							{{item.period}}课时 {{item.startTime}}-{{item.endTime}}
+						</view>
+						<view class="price-info">
+							<view class="sale">
+								已售{{item.sales}} {{item.goodRate}}%好评
+							</view>
+							<view class="price-btn" @click="RouterUtils.to_page('/pages/index/courseDetail/index?type=2')">免费试听
+							</view>
 						</view>
 					</view>
 				</view>
-			</view>
-			<!-- <loading/> -->
+			</block>
+			<loading v-else/>
+			<view class="not-data" v-if="courseList.length<1&&!courseLoading">暂无数据</view>
 			<view class="more">查看更多</view>
 		</view>
 		<view class="instructor-card" id="schedule">
@@ -182,12 +189,12 @@
 			</view>
 			<scroll-view class="header-swiper content" scroll-x="true" :show-scrollbar="false">
 				<view class="swiper-box">
-					<view class="swiper-inner" v-for="item in 12">
+					<view class="swiper-inner" v-for="item in detailInfo.instructorVOList" :key="item.id">
 						<view class="header-img">
-							<image src="https://img.keaitupian.cn/newupload/08/1629449018344288.jpg" mode=""></image>
+							<image :src="item.avatar" mode=""></image>
 							<image src="/src/static/badge.png" mode=""></image>
 						</view>
-						<view class="instructor-name">詹姆斯</view>
+						<view class="instructor-name">{{item.name}}</view>
 						<view class="instructor-specialty">篮球</view>
 					</view>
 				</view>
@@ -229,32 +236,46 @@
 		</view>
 	</view>
 	<view style="position: relative;z-index: 99999;">
-		<selPopup ref="openPopup" />
+		<selPopup :listData="placedata" :itemList="selItems" :deteObj="dateIndex" @change="onchange" ref="openPopup" />
 	</view>
+	<uni-popup ref="placeInfoPopup" :safe-area="false" type="bottom">
+		<view class="buyTips-box">
+			<view class="buyTips-title">购买须知</view>
+			<view class="rich-box" v-if="buyTipsObj">
+				<rich-text :nodes="buyTipsObj.reminder"></rich-text>
+			</view>
+		</view>
+	</uni-popup>
 </template>
 
 <script lang="ts" setup>
-	import { ref, onMounted, getCurrentInstance, nextTick } from 'vue';
+	import { ref, onMounted, getCurrentInstance, nextTick,computed } from 'vue';
 	import { RouterUtils } from '@/utils/util';
+	import { http } from '@/utils/http'
 	import zzxNavbar from '@/components/zzx-navbar/zzx-navbar.vue';
 	import { onLoad, onPageScroll } from '@dcloudio/uni-app';
 	import loading from '@/components/zzx-loading/zzx-loading.vue';
 	import selPopup from './components/popup.vue';
 	const openPopup = ref(null);
+	const placeInfoPopup=ref()
 	const statusBarHeight = ref(0);
 	const sectionTops = ref<number[]>([]);
 	const isScrollingByTab = ref(false);
 	const scrollTimer = ref<any>(null);
 	const selectList = ref(['场地', '课程', '教练', '评价']);
 	const sel_index = ref(0);
-	const selectList_btn = ref(['篮球', '羽毛球', '乒乓球', '网球']);
 	const sel_btn = ref(0);
 	const instance = getCurrentInstance();
+	onLoad((option)=>{
+		listId.value = option.id
+	})
 	onMounted(() => {
 		get_navheight()
 		nextTick(() => {
 			setTimeout(() => getSectionsTop(), 300);
 		});
+		get_placeInfo()
+		get_allCategory()
 	})
 	const get_navheight = () => {
 		const systemInfo = uni.getSystemInfoSync();
@@ -262,7 +283,10 @@
 	}
 
 	// 打开选场弹窗
-	const open_popup = () => {
+	const dateIndex=ref()
+	const open_popup = (e,i) => {
+		dateIndex.value=i
+		get_placeInfoDetail(categoryId.value,i)
 		openPopup.value?.open()
 	}
 
@@ -354,9 +378,96 @@
 	// 拨打电话
 	const open_phone = () => {
 		uni.makePhoneCall({
-			phoneNumber: '028-87776666' //仅为示例
+			phoneNumber: detailInfo.value.phone
+		});
+	}
+	
+	// 详情信息
+	const listId = ref(0);
+	const detailInfo = ref({})
+	const bannerList = ref([])
+	const videoList = ref([])
+	const noTeachingDay=ref()
+	const teachingDay=ref()
+	const get_placeInfo = () => {
+		http.get('/detail/getPlaceInfo', { data: { id: listId.value }, loading: true }).then((res) => {
+			const startIndex = res.result.cover.indexOf('"') + 1;
+			const endIndex = res.result.cover.lastIndexOf('');
+			bannerList.value = res.result.cover.slice(startIndex, endIndex).split(',');
+			let videoIndex = res.result.video.indexOf('"') + 1;
+			let videoEndIndex = res.result.video.lastIndexOf('');
+			videoList.value = res.result.video.slice(videoIndex, videoEndIndex).split(',');
+			detailInfo.value = res.result
+			noTeachingDay.value=JSON.parse(res.result.noTeachingDay)
+			teachingDay.value=JSON.parse(res.result.teachingDay)
 		})
 	}
+	
+	// 课程分类
+	const allCategoryList=ref([])
+	const categoryId=ref()
+	const get_allCategory=()=>{
+		http.get('/detail/getAllCategory', { data: { id: listId.value}}).then((res)=>{
+			categoryId.value=res.result[0].id
+			allCategoryList.value=res.result
+			get_courseList(categoryId.value)
+			get_placeInfoNoFixation(categoryId.value)
+			get_placeInfoDetail(categoryId.value,'')
+		})
+	}
+	
+	// 课程列表
+	const courseList=ref([])
+	const courseLoading=ref(false)
+	const get_courseList=(categoryId)=>{
+		courseLoading.value=true
+		http.get('/detail/courseInfoVOList',{data:{categoryId:categoryId,id:listId.value}}).then((res)=>{
+			courseList.value=res.result
+			courseLoading.value=false
+		})
+	}
+	
+	// 课程切换
+	const selectallCategory=(e,i)=>{
+		sel_btn.value = i
+		get_courseList(e.id)
+	}
+	
+	// 包场切换
+	const selChartered=ref(0)
+	const selectChartered=(e,i)=>{
+		selChartered.value = i
+		get_placeInfoNoFixation(e.id)
+		get_placeInfoDetail(e.id,'')
+	}
+	
+	// 包场信息
+	const charteredList=ref()
+	const get_placeInfoNoFixation=(categoryId)=>{
+		http.get('/detail/getPlaceInfoNoFixation',{data:{categoryId:categoryId,id:listId.value},loading:true}).then((res)=>{
+			charteredList.value=res.result
+		})
+	}
+	
+	const buyTipsObj=ref()
+	const buyTips=(e)=>{
+		placeInfoPopup.value.open()
+		buyTipsObj.value=e
+	}
+	
+	const placedata=ref()
+	const selItems=ref()
+	const get_placeInfoDetail=(catId,dateIndex)=>{
+		http.get('/stadium/getPlaceInfo',{data:{siteId:listId.value ,categoryId:catId}}).then((res)=>{
+			placedata.value=res.result
+			selItems.value=res.result.stadiumConcertsVOList[dateIndex||0].concertsVOList
+		})
+	}
+	
+	const onchange=(e,i)=>{
+		selItems.value=e.concertsVOList
+		dateIndex.value=i
+	}
 </script>
 
 <style lang="less" scoped>
@@ -366,6 +477,7 @@
 		.header-bg {
 			position: absolute;
 			width: 100%;
+			height: 432rpx;
 			z-index: -100;
 		}
 
@@ -415,7 +527,10 @@
 			display: flex;
 			align-items: center;
 			justify-content: space-between;
-
+			.open-status {
+				font-size: 24rpx;
+				color: #4DD951;
+			}
 			.name {
 				font-weight: 800;
 				font-size: 32rpx;
@@ -432,22 +547,13 @@
 		}
 
 		.open-time {
-			display: flex;
-			align-items: center;
-			gap: 20rpx;
 			margin-top: 20rpx;
-
-			.open-status {
-				font-size: 24rpx;
-				color: #4DD951;
-			}
-
 			.time {
-				display: flex;
-				align-items: center;
-				gap: 20rpx;
 				font-size: 24rpx;
 				color: #AAAAAA;
+				&>view{
+					margin-top: 20rpx;
+				}
 			}
 		}
 
@@ -887,6 +993,10 @@
 						text-decoration: line-through;
 					}
 				}
+				.course-count{
+					font-size: 22rpx;
+					color: #AAAAAA;
+				}
 
 				.price-info {
 					display: flex;
@@ -1110,4 +1220,19 @@
 			}
 		}
 	}
+	.buyTips-box{
+		background: #F6F6F6;
+		border-radius: 32rpx 32rpx 0rpx 0rpx;
+		max-height: 1200rpx;
+		overflow: auto;
+		padding: 20rpx;
+		.buyTips-title{
+			text-align: center;
+			font-size: 28rpx;
+			font-weight: bold;
+		}
+		.rich-box{
+			margin-top: 20rpx;
+		}
+	}
 </style>

+ 34 - 20
src/pages/index/instructorDetail/index.vue

@@ -13,40 +13,39 @@
 		<view class="i-info-card">
 			<view class="i-userinfo">
 				<view class="user-header">
-					<image class="header-img" src="https://img.keaitupian.cn/newupload/08/1629449018344288.jpg" mode=""></image>
+					<image class="header-img" :src="detailObj.avatar" mode=""></image>
 					<image class="header-badge" src="/src/static/badge.png" mode=""></image>
 				</view>
 				<view style="width: 220rpx;"></view>
 				<view class="user-name">
 					<view class="name-box">
-						<view class="name">詹姆四</view>
-						<view class="type">篮球</view>
+						<view class="name">{{detailObj.realname}}</view>
+						<view class="type">{{detailObj.trainingProgramsName}}</view>
 					</view>
 					<view class="sign" @click="to_certifying">
-						<text class="textHidden">已实名,无犯罪记录,健康证,足球裁判...</text>
+						<text class="textHidden">{{detailObj.headDisplay}}</text>
 						<zzx-icon name="ashRight" size="12"></zzx-icon>
 					</view>
 				</view>
 			</view>
 			<view class="i-sign">
-				运动执教,点燃每一个篮球梦
+				{{detailObj.teachingPhilosophy}}
 			</view>
 			<view class="i-skill">
-				擅长:体适能、足球、其他运动培训。体适能、足球、其他
-				运动培训。体适能、足球、其他运动培训。
+				{{detailObj.excelMsg}}
 			</view>
 			<view class="i-data-card">
 				<view class="item-data">
 					<view class="text">好评率</view>
-					<view class="num">99%</view>
+					<view class="num">{{detailObj.goodRate}}%</view>
 				</view>
 				<view class="item-data">
-					<view class="text">订单</view>
+					<view class="text">订单</view>
 					<view class="num">1659</view>
 				</view>
 				<view class="item-data">
 					<view class="text">授课人数</view>
-					<view class="num">9568</view>
+					<view class="num">{{detailObj.classesNumber||'0'}}</view>
 				</view>
 			</view>
 		</view>
@@ -57,21 +56,21 @@
 					<view class="tips-icon">!</view>
 					<view class="tips-text">全平台每种类型的运动课程只可免费试听一次</view>
 				</view>
-				<view class="card-list" v-for="item in 4">
-					<image class="card-img" src="https://img.keaitupian.cn/newupload/08/1629449018344288.jpg" mode=""></image>
+				<view class="card-list" v-for="item in detailObj.courseInfoVOList" :key="item.id">
+					<image class="card-img" :src="item.cover" mode=""></image>
 					<view class="i-list">
 						<view class="list-name">
-							<view class="name textHidden">1对1篮球30分钟室内钟室内</view>
-							<view class="num">年售20</view>
+							<view class="name textHidden">{{item.name}}</view>
+							<view class="num">年售{{item.annualSalesNum}}</view>
 						</view>
-						<view class="address">上课地点:观山湖区第十二小学 | 2.2km</view>
+						<view class="address">上课地点:{{item.address}} | {{item.km}}km</view>
 						<view class="list-price">
-							<view class="left-price">¥58.9</view>
-							<view class="right-price">¥80.9</view>
+							<view class="left-price">¥{{item.sellingPrice}}</view>
+							<view class="right-price">¥{{item.originalPrice}}</view>
 						</view>
-						<view class="sale-data">已售33 98%好评</view>
+						<view class="sale-data">已售{{item.saleNum}} {{item.goodRate}}%好评</view>
 						<view class="course-num">
-							<view class="number">6课时 05.28-08.18</view>
+							<view class="number">{{item.coursesNum}}课时 {{item.startTime}}-{{item.endTime}}</view>
 							<view class="i-btn">抢购</view>
 						</view>
 						<view style="height: 24rpx;"></view>
@@ -119,11 +118,18 @@
 <script lang="ts" setup>
 	import { ref, onMounted } from 'vue';
 	import { onLoad, onPageScroll } from '@dcloudio/uni-app';
+	import { http } from '@/utils/http'
+	import { useCacheStore } from '@/stores/cache'
 	import { RouterUtils } from '@/utils/util';
 	import zzxNavbar from '@/components/zzx-navbar/zzx-navbar.vue';
+	const cache = useCacheStore()
 	const statusBarHeight = ref(0);
+	onLoad((option)=>{
+		detailId.value=option.id
+	})
 	onMounted(() => {
 		get_navheight()
+		get_findByCoachId()
 	})
 	const get_navheight = () => {
 		const systemInfo = uni.getSystemInfoSync();
@@ -132,7 +138,15 @@
 	
 	const to_certifying=()=>{
 		uni.navigateTo({
-			url:'/pages/index/certifyingDetail/index'
+			url:`/pages/index/certifyingDetail/index?id=${detailId.value}`
+		})
+	}
+	
+	const detailId=ref()
+	const detailObj=ref()
+	const get_findByCoachId=()=>{
+		http.get('/coachC/findByCoachId',{data:{id:detailId.value,longitude:cache.get('LON'),latitude:cache.get('LAT')},loading:true}).then((res)=>{
+			detailObj.value=res.result
 		})
 	}
 </script>

+ 23 - 0
src/pages/index/mapPage/index.vue

@@ -0,0 +1,23 @@
+<template>
+	<view class="map-box">
+		<map @click="openMap"></map>
+	</view>
+</template>
+
+<script lang="ts" setup>
+	import { ref, onMounted } from 'vue';
+	const openMap=()=>{
+		uni.openLocation({
+			latitude: 39.909,
+			longitude: 116.39742,
+			name: 'Tencent Building',
+			address: '北京市海淀区西二旗大街27号',
+			success: function () {
+				console.log('success');
+			}
+		});
+	}
+</script>
+
+<style>
+</style>

+ 1 - 1
src/pages/index/searchPage/components/events.vue

@@ -1,5 +1,5 @@
 <template>
-	<view class="e-card-list" v-for="item in listData" :key="item.id	">
+	<view class="e-card-list" v-for="item in listData" :key="item.id">
 		<view class="e-events-info">
 			<view class="e-picture">
 				<image class="pic" :src="item.cover" mode=""></image>

+ 5 - 3
src/pages/index/searchPage/index.vue

@@ -22,7 +22,8 @@
 		<view class="s-search-list"  v-if="!searchLoading">
 			<!-- 场地 -->
 			<view v-if="sel_index==0">
-				<view class="s-venue-card" v-for="(venue,index) in searchList" :key="venue.id">
+				<!-- pages/index/gymDetail/index -->
+				<view class="s-venue-card" v-for="(venue,index) in searchList" :key="venue.id" @click="RouterUtils.to_page(`/pages/index/gymDetail/index`)">
 					<view class="s-venue-info">
 						<view class="venue-img">
 							<image :src="venue.cover" mode=""></image>
@@ -93,13 +94,14 @@
 	import { ref, onMounted } from 'vue';
 	import { onLoad,onReachBottom } from '@dcloudio/uni-app';
 	import { http } from '@/utils/http'
+	import {RouterUtils} from '@/utils/util'
 	import { useCacheStore } from '@/stores/cache'
 	import events from './components/events.vue'
 	import instructor from './components/instructor.vue'
 	import zsEmpty from '@/components/zs-empty/index.vue'
 	import zsLoading from '@/components/zzx-loading/zzx-loading.vue'
 	const cache = useCacheStore()
-	const selectList = ref(['距离', '好评'])
+	const selectList = ref()
 	const sel_index = ref(0);
 	const sel_btn = ref(0);
 	const keyword = ref();
@@ -160,7 +162,7 @@
 	
 	const searchLoading=ref(true)
 	const current=ref(1)
-	const get_searchInfo = (tagsVal=ref()) => {
+	const get_searchInfo = (tagsVal) => {
 		http.post('/home/search', { keyword: keyword.value, size: 10, current:current.value, venueType:String(tagsVal), longitude: cache.get('LON'), latitude: cache.get('LAT') }).then((res) => {
 			searchLoading.value=false
 			if(current.value==1){

+ 99 - 26
src/pages/index/submitOrder/index.vue

@@ -1,30 +1,34 @@
 <template>
 	<view class="s-header-card">
 		<zzx-icon name="location" size="14"></zzx-icon>
-		<text>观山湖区第十二小学</text>
+		<text>{{timeList.name}}</text>
 	</view>
 	<view class="content">
 		<view class="s-selectdate-card">
 			<view class="s-title">选择日期</view>
 			<view class="select-card-list">
 				<scroll-view class="scroll-view_H" scroll-x="true">
-					<view class="item-card" v-for="item in 3" @click="open_calendar">
-						<view class="day">今天</view>
-						<view class="date">04.23</view>
+					<view :class="selIndex===index?'item-card-select':'item-card'" :style="{backgroundColor:item.inventory<1?'#fefefe':'',color:item.inventory<1?'#dddddd':''}" v-for="(item,index) in dateList" @click="open_calendar(item,index)">
+						<view class="day">{{item.namedDay}}</view>
+						<view class="date">{{item.day.slice(5)}}</view>
 					</view>
 				</scroll-view>
+				<view class="more-date" @click="calendar.open()">
+					更多日期
+				</view>
 			</view>
 		</view>
 		<view class="s-selecttime-card">
 			<view class="s-title">选择时段</view>
 			<view class="select-card-list">
 				<scroll-view class="scroll-view_H" scroll-x="true">
-					<view class="item-card" :style="{background: `${check_index==index?'#F0FFBB':'#F6F6F6'}`}" v-for="(item,index) in 8" @click="check_item(index)">
-						<view class="time">06:00-08:00</view>
-						<view class="allowance">余82</view>
-						<view class="price">¥95</view>
+					<view class="item-card" :style="{background: `${check_index==index?'#F0FFBB':'#F6F6F6'}`}" v-for="(item,index) in timeList.timeSlot" @click="check_item(item,index)">
+						<view class="time">{{item.name}}</view>
+						<view class="allowance">余{{item.inventory}}</view>
+						<view class="price">¥{{item.price}}</view>
 					</view>
 				</scroll-view>
+				<view class="not-data" v-if="timeList.timeSlot.length<1">暂无可选时段</view>
 			</view>
 		</view>
 		<view class="g-insurance-card">
@@ -58,12 +62,12 @@
 					<zzx-icon name="ashRight" size="12"></zzx-icon>
 				</view>
 			</view>
-			<view class="user-tags">张三</view>
-			<view class="r-user-list" v-for="item in 2">
-				<view class="minus-user">-</view>
+			<!-- <view class="user-tags">张三</view> -->
+			<view class="r-user-list" v-for="item in userData" :key="item.id">
+				<view class="minus-user" @click="deleteUser(item)">-</view>
 				<view class="r-list">
-					<view class="name">张三</view>
-					<view class="id-num">身份证 51**************10</view>
+					<view class="name">{{item.fullName}}</view>
+					<view class="id-num">身份证 {{idCardHide(item.identityCard)}}</view>
 				</view>
 			</view>
 			<view class="g-adduser-btn" @click="toUserList">
@@ -73,29 +77,74 @@
 		</view>
 		<view class="submit-btn">免费 立即预约</view>
 	</view>
-	<uni-calendar ref="calendar" :insert="false" @confirm="confirm" />
+	<uni-calendar ref="calendar" :insert="false" :date="selectInsurance" @confirm="confirm" />
 </template>
 
 <script lang="ts" setup>
-	import { ref } from 'vue';
-	import { RouterUtils } from '@/utils/util';
+	import { ref,onMounted } from 'vue';
+	import { RouterUtils,TipsUtils,idCardHide } from '@/utils/util';
+	import { onLoad, onPageScroll } from '@dcloudio/uni-app';
+	import { http } from '@/utils/http'
 	const calendar=ref();
-	const check_index=ref(0)
+	const check_index=ref(0);
+	onLoad((option)=>{
+		placeId.value=option.id
+	})
+	onMounted(()=>{
+		get_previewTIme()
+		get_userData()
+	})
 	const toUserList = () => {
 		RouterUtils.to_page('/pages/index/userList/index')
 	}
 	
-	const open_calendar=()=>{
-		calendar.value.open()
+	const selIndex=ref(0)
+	const selectInsurance=ref()
+	const open_calendar=(e,i)=>{
+		if(e.inventory<1) return TipsUtils.tips_toast('该天暂无库存')
+		selectInsurance.value=e.day
+		selIndex.value=i
+		get_previewOrderPlaceSchool(e.day)
 	}
 	// 日历回调确认
 	const confirm=(e)=>{
-		console.log(e);
+		get_previewOrderPlaceSchool(e.fulldate)
 	}
-	
-	const check_item=(i)=>{
+	const check_item=(e,i)=>{
 		check_index.value=i
 	}
+	
+	// 预览时间选项
+	const dateList=ref()
+	const get_previewTIme=()=>{
+		http.get('/order/previewOrderPlaceSchoolTime',{data:{placeId:placeId.value},loading:true}).then((res)=>{
+			dateList.value=res.result
+			get_previewOrderPlaceSchool(res.result[0].day)
+		})
+	}
+	
+	// 场地信息预览
+	const placeId=ref()
+	const timeList=ref()
+	const get_previewOrderPlaceSchool=(startTime)=>{
+		http.get('/order/previewOrderPlaceSchool',{data:{placeId:placeId.value,startTime:startTime},loading:true}).then((res)=>{
+			timeList.value=res.result
+		})
+	}
+	
+	const userData=ref()
+	const get_userData=()=>{
+		uni.$on('userData',function(data){
+			userData.value=data
+		})
+	}
+	
+	const deleteUser=async(e)=>{
+		let res = await TipsUtils.tips_alert('确定删除该用户吗?',true)
+		if(res.confirm){
+			userData.value=userData.value.filter(user=>user.id!==e.id)
+		}
+	}
 </script>
 
 <style lang="less" scoped>
@@ -124,11 +173,30 @@
 
 		.select-card-list {
 			margin-top: 20rpx;
-
+			display: flex;
+			align-items: center;
 			.scroll-view_H {
 				white-space: nowrap;
-				width: 100%;
-
+				width: 90%;
+				.item-card-select{
+					margin-right: 16rpx;
+					display: inline-block;
+					width: 104rpx;
+					height: 120rpx;
+					background: #F0FFBB;
+					border-radius: 16rpx;
+					font-size: 24rpx;
+					color: #222222;
+					text-align: center;
+					
+					.day {
+						padding-top: 20rpx;
+					}
+					
+					.date {
+						margin-top: 12rpx;
+					}
+				}
 				.item-card {
 					margin-right: 16rpx;
 					display: inline-block;
@@ -139,7 +207,6 @@
 					font-size: 24rpx;
 					color: #222222;
 					text-align: center;
-
 					.day {
 						padding-top: 20rpx;
 					}
@@ -149,6 +216,12 @@
 					}
 				}
 			}
+			.more-date{
+				width: 200rpx;
+				font-size: 24rpx;
+				color: #FDD143;
+				text-align: center;
+			}
 		}
 	}
 

+ 135 - 43
src/pages/index/training/index.vue

@@ -8,44 +8,122 @@
 	<view style="height: 70rpx;"></view>
 	<view class="content">
 		<view class="select-btn">
-			<view :class="sel_btn===index?'distance':'score'" v-for="(item,index) in selectList" :key="index" @click="select_btn(index)">{{item}}</view>
+			<view :class="sel_btn===index?'distance':'score'" v-for="(item,index) in selectList" :key="index"
+				@click="select_btn(item,index)">{{item.text}}</view>
 		</view>
-		<view class="t-card-list" v-for="item in 3">
-			<view class="t-courseImg">
-				<image src="https://img95.699pic.com/photo/60010/7623.jpg_wh860.jpg" mode=""></image>
-			</view>
-			<view class="t-course">
-				<view class="c-title textHidden">1对1篮球30分钟室内精品30分钟室内精品</view>
-				<view class="c-address">上课地点观山湖区万达广场 | 2.2km</view>
-				<view class="c-price">¥25.9</view>
-				<view class="c-ratio">已售37  98%好评</view>
-				<view class="c-class">6课时 05.06-05.11</view>
-				<view class="c-icon">
-					<image src="/src/static/snapped.png" mode="widthFix"></image>
+		<block v-if="courseList.length>1">
+			<view class="t-card-list" v-for="item in courseList" :key="item.id">
+				<view class="t-courseImg">
+					<image :src="item.cover" mode=""></image>
+				</view>
+				<view class="t-course">
+					<view class="c-title textHidden">{{item.name}}</view>
+					<view class="c-address">{{item.address}} | {{item.km.toFixed(2)}}km</view>
+					<view class="c-price">¥25.9
+						<text v-if="item.priceType==0"
+							style="font-size: 22rpx;color: #AAAAAA;text-decoration: line-through;">¥23.2</text>
+					</view>
+					<view class="c-ratio">已售{{item.saleNum||'0'}} {{item.goodRate}}%好评</view>
+					<view class="c-class">{{item.coursesNum}}课时 {{item.startTime}}-{{item.endTime}}</view>
+					<view class="c-icon">
+						<image v-if="item.priceType==1" src="/src/static/snapped.png" mode="widthFix"></image>
+						<block v-else>
+							<image v-if="item.isOneBuy" src="/src/static/snapped1.png" mode="widthFix"></image>
+							<image v-else src="/src/static/qinggou.png" mode="widthFix"></image>
+						</block>
+					</view>
 				</view>
 			</view>
-		</view>
+		</block>
+		<zs-empty v-else></zs-empty>
 	</view>
 </template>
 
 <script lang="ts" setup>
-	import { ref } from 'vue'
+	import { ref, onMounted, computed } from 'vue'
+	import { onLoad, onReachBottom } from '@dcloudio/uni-app'
+	import { http } from '@/utils/http'
+	import { useCacheStore } from '@/stores/cache'
+	import zsEmpty from '@/components/zs-empty/index.vue'
+	const cache = useCacheStore()
 	const navbarList = ref([{
 		text: '全部'
 	}, {
-		text: '学校'
+		text: '免费课'
 	}, {
-		text: '体育馆'
+		text: '精品课'
 	}]);
-	const selectList=ref(['距离','好评','销量'])
+	// 132
+	const selectList = ref([{
+		text: '距离',
+		type: 1
+	}, {
+		text: '好评',
+		type: 3
+	}, {
+		text: '销量',
+		type: 2
+	}])
 	const sel_index = ref(0);
-	const sel_btn=ref(0);
-	
-	const select_btn=(i)=>{
-		sel_btn.value=i
+	const sel_btn = ref(0);
+	onReachBottom(() => {
+		pageNo.value++
+		if (sel_index.value === 0) {
+			get_findByCourseList('', selectType.value)
+		} else if (sel_index.value === 1) {
+			get_findByCourseList(1, selectType.value)
+		} else if (sel_index.value === 2) {
+			get_findByCourseList('0', selectType.value)
+		}
+	})
+	onMounted(() => {
+		get_findByCourseList('', 1)
+	})
+	const selectType = ref()
+	const select_btn = (e, i) => {
+		selectType.value = e.type
+		if (sel_index.value === 0) {
+			get_findByCourseList('', e.type)
+		} else if (sel_index.value === 1) {
+			get_findByCourseList(1, e.type)
+		} else if (sel_index.value === 2) {
+			get_findByCourseList('0', e.type)
+		}
+		sel_btn.value = i
 	}
 	const select_nav = (i) => {
 		sel_index.value = i
+		sel_btn.value = 0
+		if (i === 0) {
+			get_findByCourseList('', 1)
+		} else if (i === 1) {
+			get_findByCourseList(1, 1)
+		} else if (i === 2) {
+			get_findByCourseList('0', 1)
+		}
+	}
+
+	// 获取列表
+	const courseList = ref()
+	const pageNo = ref(1)
+	const get_findByCourseList = (priceType : any, orderByType : number) => {
+		http.get('/detail/findByCourseList', {
+			data: {
+				priceType: priceType || '',
+				longitude: cache.get('LON'),
+				latitude: cache.get('LAT'),
+				orderByType: orderByType,
+				pageNo: pageNo.value,
+				pageSize: 10
+
+			}, loading: true
+		}).then((res) => {
+			if (pageNo.value == 1) {
+				courseList.value = res.result.records
+			} else {
+				courseList.value = [...courseList.value, ...res.result.records]
+			}
+		})
 	}
 </script>
 
@@ -62,39 +140,43 @@
 		width: 100%;
 		top: 0;
 		z-index: 1000;
+
 		.navbar-list {
 			display: flex;
 			align-items: center;
 			gap: 10rpx;
-	
+
 			.list-text {
 				font-weight: bold;
 				font-size: 28rpx;
 				color: #222222;
 			}
-	
+
 			&>image {
 				width: 30rpx;
 				height: 30rpx;
 			}
 		}
 	}
-	.select-btn{
+
+	.select-btn {
 		display: flex;
 		align-items: center;
 		gap: 20rpx;
 		margin-top: 20rpx;
-		.distance{
+
+		.distance {
 			width: 92rpx;
 			height: 48rpx;
 			background: #222222;
 			border-radius: 8rpx;
 			font-size: 28rpx;
 			color: #C8FF0C;
-			line-height:48rpx;
+			line-height: 48rpx;
 			text-align: center;
 		}
-		.score{
+
+		.score {
 			width: 92rpx;
 			height: 48rpx;
 			background: #FFFFFF;
@@ -102,11 +184,12 @@
 			font-size: 28rpx;
 			color: #AAAAAA;
 			height: 48rpx;
-			line-height:48rpx;
+			line-height: 48rpx;
 			text-align: center;
 		}
 	}
-	.t-card-list{
+
+	.t-card-list {
 		padding: 20rpx;
 		background: #FFFFFF;
 		border-radius: 32rpx;
@@ -114,52 +197,61 @@
 		align-items: center;
 		gap: 20rpx;
 		margin-top: 20rpx;
-		.t-courseImg{
-			&>image{
+
+		.t-courseImg {
+			&>image {
 				width: 200rpx;
 				height: 200rpx;
 				border-radius: 32rpx;
 			}
 		}
-		.t-course{
+
+		.t-course {
 			position: relative;
-			.c-title{
+
+			.c-title {
 				width: 430rpx;
 				font-weight: 800;
 				font-size: 32rpx;
 				color: #222222;
 				line-height: 52rpx;
 			}
-			.c-address{
+
+			.c-address {
 				margin-top: 4rpx;
 				font-size: 22rpx;
 				color: #AAAAAA;
 			}
-			.c-price{
+
+			.c-price {
 				font-weight: 800;
 				font-size: 32rpx;
 				color: #FB5B5B;
 				height: 44rpx;
 				line-height: 44rpx;
 			}
-			.c-ratio{
+
+			.c-ratio {
 				font-size: 22rpx;
 				color: #222222;
 				height: 32rpx;
 				line-height: 32rpx;
 			}
-			.c-class{
+
+			.c-class {
 				font-size: 22rpx;
 				color: #AAAAAA;
 				height: 32rpx;
 				line-height: 32rpx;
 			}
-			.c-icon{
+
+			.c-icon {
 				position: absolute;
-				bottom:-30rpx;
-				right:-42rpx;
-				&>image{
-					width:161rpx;
+				bottom: -30rpx;
+				right: -42rpx;
+
+				&>image {
+					width: 161rpx;
 				}
 			}
 		}

+ 12 - 4
src/pages/index/userList/index.vue

@@ -25,7 +25,7 @@
 				</view>
 			</view>
 		</view>
-		<view class="u-select-btn">
+		<view class="u-select-btn" @click="confirmSelect">
 			<button hover-class="hover-btn">确认选择:{{selTotal}}人</button>
 		</view>
 	</view>
@@ -61,7 +61,7 @@
 	})
 
 	const get_userList = () => {
-		http.get('/my/familyMembers/findFamilyMembers', { data: { userId: userinfo.value.id, pageNo: pageNo.value, pageSize: 10 }, loading: true }).then((res) => {
+		http.get('/my/familyMembers/findFamilyMembers', { data: { userId: userinfo.value.id, pageNo: pageNo.value, pageSize:30 }, loading: true }).then((res) => {
 			res.result.records = res.result.records.map((item:any) => ({
 				...item,
 				selOut: false
@@ -73,19 +73,27 @@
 			}
 		})
 	}
-
+	
+	const selArr=ref([])
 	const selectUser = (item : any) => {
 		item.selOut = !item.selOut
 		if (item.selOut) {
 			selTotal.value++
+			selArr.value.push(item)
 		} else {
 			selTotal.value--
-		}
+			selArr.value = selArr.value.filter((i:any) => i.id != item.id)
+		} 
+		console.log(selArr.value,'---1');
 	}
 
 	const addUser = () => {
 		RouterUtils.to_page('/pages/index/attestation/index');
 	}
+	const confirmSelect=()=>{
+		uni.$emit('userData',selArr.value)
+		uni.navigateBack()
+	}
 </script>
 
 <style lang="less" scoped>

+ 96 - 38
src/pages/index/venue/index.vue

@@ -1,6 +1,6 @@
 <template>
 	<view class="venue-navbar">
-		<view class="navbar-list" v-for="(item,index) in navbarList" :key="index" @click="select_nav(index)">
+		<view class="navbar-list" v-for="(item,index) in navbarList" :key="index" @click="select_nav(item,index)">
 			<view class="list-text">{{item.text}}</view>
 			<image :src="sel_index==index?'/static/notsel-icon.png':'/static/select-icon.png'" mode=""></image>
 		</view>
@@ -8,73 +8,131 @@
 	<view style="height: 70rpx;"></view>
 	<view class="content">
 		<view class="select-btn">
-			<view :class="sel_btn===index?'distance':'score'" v-for="(item,index) in selectList" :key="index" @click="select_btn(index)">{{item}}</view>
+			<view :class="sel_btn===index?'distance':'score'" v-for="(item,index) in selectList" :key="index" @click="select_btn(item,index)">{{item.text}}</view>
 		</view>
-		<view class="venue-card" v-for="item in 10" @click="gotoDetail">
-			<view class="venues-image">
-				<image src="https://img.keaitupian.cn/newupload/08/1629449018344288.jpg" mode=""></image>
-				<view class="e-badge">
-					<image src="/src/static/events-icon1.png" mode="widthFix"></image>
-					<view class="text">今日有票</view>
+		<view v-if="!searchLoading">
+			<view class="venue-card" v-for="item in dataList" @click="gotoDetail(item)" :key="item.id">
+				<view class="venues-image">
+					<image :src="item.cover" mode=""></image>
+					<view class="e-badge">
+						<image src="/src/static/events-icon1.png" mode="widthFix"></image>
+						<view class="text">{{item.ticketWhether?'今日有票':'暂无余票'}}</view>
+					</view>
 				</view>
-			</view>
-			<view class="venues-info">
-				<view class="venues-name">体育综合训练馆(观山湖店)</view>
-				<view class="venues-comments">
-					<view class="star">
-						<zzx-icon name="star" size="12"></zzx-icon>
-						<text>4.8</text>
+				<view class="venues-info">
+					<view class="venues-name">{{item.name}}</view>
+					<view class="venues-comments">
+						<view class="star">
+							<zzx-icon name="star" size="12"></zzx-icon>
+							<text>{{item.goodRate}}</text>
+						</view>
+						<view class="comment">
+							{{item.comments}}条评论
+						</view>
 					</view>
-					<view class="comment">
-						37条评论
+					<view class="venues-address">
+						{{item.address}} | {{item.km}}km
 					</view>
-				</view>
-				<view class="venues-address">
-					观山湖区万达广场 | 2.2km
-				</view>
-				<view class="venues-type">
-					<view class="type-tags" v-for="item in 4">
-						羽毛球
+					<view class="venues-type">
+						<view class="type-tags" v-for="(tags,index) in item.category" :key="index">
+							{{tags}}
+						</view>
 					</view>
 				</view>
 			</view>
 		</view>
+		<zs-loading v-else></zs-loading>
+		<zs-empty v-if="dataList.length<1&&!searchLoading"></zs-empty>
 	</view>
 </template>
 
 <script lang="ts" setup>
-	import { ref } from 'vue'
+	import { ref, onMounted, computed } from 'vue'
+	import { onLoad,onReachBottom } from '@dcloudio/uni-app'
+	import { http } from '@/utils/http'
+	import {RouterUtils} from '@/utils/util'
+	import { useCacheStore } from '@/stores/cache'
+	import zsEmpty from '@/components/zs-empty/index.vue'
+	import zsLoading from '@/components/zzx-loading/zzx-loading.vue'
+	const cache = useCacheStore()
 	const navbarList = ref([{
-		text: '全部'
+		text: '全部',
+		tagsVal:'0-1',
+		value:0
 	}, {
-		text: '学校'
+		text: '学校',
+		tagsVal:'1-1',
+		value:1
 	}, {
-		text: '体育馆'
+		text: '体育馆',
+		tagsVal:'2-1',
+		value:2
 	}]);
-	const selectList=ref(['距离','评分'])
+	const selectList=ref()
 	const sel_index = ref(0);
 	const sel_btn=ref(0);
-	
-	const select_btn=(i)=>{
+	onMounted(()=>{
+		get_dictType(0)
+		get_placeList('0-1')
+	})
+	onReachBottom(()=>{
+		current.value++
+		get_placeList(tagsVal.value||'0-1')
+	})
+	const select_btn=(e,i)=>{
+		searchLoading.value=true
 		sel_btn.value=i
+		get_placeList(e.value)
 	}
-	const select_nav = (i) => {
+	const select_nav = (e,i) => {
+		searchLoading.value=true
 		sel_index.value = i
+		sel_btn.value=0
+		tagsVal.value=e.tagsVal
+		get_dictType(e.value || 0)
+		get_placeList(e.tagsVal)
 	}
 	
-	const gotoDetail=()=>{
-		if(sel_index.value===0||sel_index.value===1){
-			console.log(sel_index.value);
+	const gotoDetail=(item)=>{
+		if(item.type==0){
 			uni.navigateTo({
-				url:'/pages/index/detail/index'
+				url:`/pages/index/detail/index?id=${item.id}`
 			})
 		}else{
-			console.log(sel_index.value);
 			uni.navigateTo({
-				url:'/pages/index/gymDetail/index'
+				url:`/pages/index/gymDetail/index?id=${item.id}`
 			})
 		}
 	}
+	
+	// 查询分类
+	const get_dictType = (type : number) => {
+		http.get('/common/getDictItems', { data: { dictCode: 'venue_type' } }).then(res => {
+			let arr = []
+			res.result.forEach((item) => {
+				let value = parseInt(item.value.split('-')[0])
+				item.text=item.text.split('-')[1]
+				if (type == value){
+					return arr.push(item)
+				}
+			})
+			selectList.value=arr
+		})
+	}
+	const dataList=ref()
+	const current=ref(1)
+	const searchLoading=ref(true)
+	const tagsVal=ref()
+	const get_placeList=(tagsVal)=>{
+		http.post('/home/getPlaceList',{size: 10, current:current.value, venueType:String(tagsVal), longitude: cache.get('LON'), latitude: cache.get('LAT')}).then((res)=>{
+			searchLoading.value=false
+			if(current.value==1){
+				dataList.value=res.result.records
+			}else{
+				dataList.value=[...dataList.value,...res.result.records]
+			}
+		})
+	}
 </script>
 
 <style lang="less" scoped>

BIN
src/static/qinggou.png


BIN
src/static/snapped1.png


+ 8 - 0
src/styles/variables.less

@@ -29,4 +29,12 @@
  	}
 	.scroll-view-item_H {
 			display: inline-block;
+		}
+		
+		.not-data{
+			 height: 100rpx;
+			 text-align: center;
+			 font-size: 24rpx;
+			 color: #999999;
+			 line-height: 100rpx;
 		}

+ 1 - 0
src/utils/http/index.ts

@@ -176,6 +176,7 @@ export class HttpClient {
 // 创建实例
 export const http = new HttpClient({
   baseURL: 'http://192.168.1.34:8080/jeecg-boot/app',
+  // baseURL: 'http://192.168.1.253:8080/jeecg-boot/app',
   headers: {
     'Content-Type': 'application/json'
   }

+ 11 - 0
src/utils/util/index.ts

@@ -170,4 +170,15 @@ export const idCardHide = (card : any) => {
 	const reg = /^(.{2})(?:\d+)(.{2})$/;
 	const maskedIdCard = card.replace(reg, '$1***********$2');
 	return maskedIdCard;
+}
+
+/**
+ * 手机号脱敏
+ * @param phone - 手机号字符串
+ * @returns 脱敏后的手机号字符串
+ */
+export const phoneHide = (phone : any) => {
+	const reg = /^(\d{3})\d{4}(\d{4})$/;
+	const maskedPhone = phone.replace(reg, '$1****$2');
+	return maskedPhone;
 }