Эх сурвалжийг харах

更换addid,修复若干bug

学习?学个屁 1 сар өмнө
parent
commit
8d151898d2
34 өөрчлөгдсөн 811 нэмэгдсэн , 325 устгасан
  1. 1 0
      .gitignore
  2. 29 2
      src/App.vue
  3. 2 2
      src/components/sunui-upimg/sunui-upimg.vue
  4. 1 0
      src/manifest.json
  5. 5 5
      src/pages/index/attestation/index.vue
  6. 8 7
      src/pages/index/certifyingDetail/index.vue
  7. 4 4
      src/pages/index/courseDetail/index.vue
  8. 3 3
      src/pages/index/detail/index.vue
  9. 2 2
      src/pages/index/events/index.vue
  10. 6 5
      src/pages/index/eventsDetail/index.vue
  11. 54 10
      src/pages/index/eventsRegister/index.vue
  12. 26 2
      src/pages/index/gymDetail/components/popup.vue
  13. 24 13
      src/pages/index/gymDetail/index.vue
  14. 42 15
      src/pages/index/gymPay/index.vue
  15. 13 10
      src/pages/index/index.vue
  16. 2 2
      src/pages/index/instructorDetail/index.vue
  17. 1 1
      src/pages/index/search/index.vue
  18. 6 4
      src/pages/index/searchPage/components/instructor.vue
  19. 1 1
      src/pages/index/searchPage/index.vue
  20. 36 5
      src/pages/index/submitOrder/index.vue
  21. 190 19
      src/pages/index/toBeUsed/index.vue
  22. 2 2
      src/pages/index/training/index.vue
  23. 100 56
      src/pages/index/tryUseRecord/index.vue
  24. 2 0
      src/pages/index/userList/index.vue
  25. 1 1
      src/pages/index/venue/index.vue
  26. 3 2
      src/pages/index/writeComments/index.vue
  27. 1 1
      src/pages/mine/accountSetting/index.vue
  28. 107 105
      src/pages/mine/feedbackRecord/index.vue
  29. 72 12
      src/pages/mine/orderInfo/index.vue
  30. BIN
      src/static/hot-icon2.png
  31. 17 4
      src/stores/cache.ts
  32. 1 1
      src/utils/common/upload.ts
  33. 13 5
      src/utils/http/index.ts
  34. 36 24
      src/utils/util/index.ts

+ 1 - 0
.gitignore

@@ -1,4 +1,5 @@
 # Logs
+node_modules/
 logs
 *.log
 npm-debug.log*

+ 29 - 2
src/App.vue

@@ -4,9 +4,34 @@ import { initEid } from '@/pages/mp_ecard_sdk/main';
 import { TipsUtils } from '@/utils/util';
 import { useCacheStore } from '@/stores/cache'
 const cache = useCacheStore()
-onLaunch(() => {
+onLaunch((options) => {
+	console.log(options.scene, '小程序打开的场景值')
+	//  =============判断是否扫码进入start============
+	if (options.scene === 1011 || options.scene === 1012 || options.scene === 1013) {
+		const decodedUrl = decodeURIComponent(options.query.q);
+		// console.log(decodedUrl);
+		const urlParts = decodedUrl.split('?');
+		if (urlParts.length > 1) {
+			const queryParams = urlParts[1];
+			const paramPairs = queryParams.split('&');
+			const resultObj = {};
+			paramPairs.forEach(pair => {
+				const [key, value] = pair.split('=');
+				resultObj[key] = value;
+			});
+			const gamesId = resultObj['id'];
+			const placeId = resultObj['placeId'];
+			console.log(gamesId, '----赛事id');
+			console.log(placeId, '----场地id');
+			cache.set('GAME_ID',gamesId)
+			cache.set('PLACE_ID',placeId)
+			console.info(cache.get('GAME_ID'), '---用户通过扫赛事码进入')
+			console.info(cache.get('PLACE_ID'), '---用户通过扫学校场地进入')
+		}
+	}
+	//  =============判断是否扫码进入end============
+	//  =============获取经纬度start============
 	initEid()
-	console.log("App Launch");
 	uni.authorize({
 		scope: 'scope.userLocation',
 		isHighAccuracy: true,
@@ -52,6 +77,8 @@ onLaunch(() => {
 			uni.openSetting()
 		}
 	}
+	//  =============获取经纬度end============
+
 });
 onShow(() => {
 	console.log("App Show");

+ 2 - 2
src/components/sunui-upimg/sunui-upimg.vue

@@ -36,7 +36,7 @@ export default {
 		// 服务器url
 		url: {
 			type: String,
-			default: 'http://192.168.0.11:8080/jeecg-boot/sys/common/upload'
+			default: 'https://api.qlapp.cn/jeecgboot/sys/common/upload'
 		},
 		// 上传样式宽高
 		upload_img_wh: {
@@ -122,7 +122,7 @@ export default {
 			let _self = this;
 			uni.chooseImage({
 				count: _self.upload_count - _self.upload_before_list.length,
-				sizeType: ['compressed', 'original'],
+				sizeType: ['compressed'],
 				sourceType: ['album', 'camera'],
 				success: function (res) {
 					for (let i = 0, len = res.tempFiles.length; i < len; i++) {

+ 1 - 0
src/manifest.json

@@ -51,6 +51,7 @@
     /* 小程序特有相关 */
     "mp-weixin" : {
         "appid" : "wx6260718c6fd46efb",
+        //  "appid" : "wxc032a09413289004",
         "setting" : {
             "urlCheck" : false,
             "minified" : true

+ 5 - 5
src/pages/index/attestation/index.vue

@@ -5,7 +5,7 @@
 			<view class="title">本人实名认证</view>
 			<view class="text">用于身份实名核验,反洗钱,资料将严格保密</view>
 		</view>
-		<view class="a-idcard-box">
+		<!-- <view class="a-idcard-box">
 			<view class="front" v-if="frontImg != ''" @click="chooseImage(1)">
 				<image :src="frontImg" mode=""></image>
 			</view>
@@ -20,7 +20,7 @@
 				<zzx-icon name="upload" size="30"></zzx-icon>
 				<view class="">上传国徽面</view>
 			</view>
-		</view>
+		</view> -->
 		<view class="a-form">
 			<view class="form-item">
 				<view class="">真实姓名</view>
@@ -72,7 +72,7 @@ const flipSideImg = ref('')
 const chooseImage = (e) => {
 	uni.chooseImage({
 		count: 1,
-		sizeType: ['original', 'compressed'],
+		sizeType: ['compressed'],
 		sourceType: ['album', 'camera'],
 		success: function (res) {
 			if (e == 1) {
@@ -126,8 +126,8 @@ const handleChange = async (e) => {
 
 const submit = () => {
 	console.log(formData.value.realNameImg, '本人图片');
-	if (!formData.value.idCardFrontImg) return TipsUtils.tips_toast('请上传人像面');
-	if (!formData.value.idCardBackImg) return TipsUtils.tips_toast('请上传国徽面');
+	// if (!formData.value.idCardFrontImg) return TipsUtils.tips_toast('请上传人像面');
+	// if (!formData.value.idCardBackImg) return TipsUtils.tips_toast('请上传国徽面');
 	if (!formData.value.fullName) return TipsUtils.tips_toast('请输入姓名');
 	if (!ValidateUtils.validateIdCard(formData.value.identityCard)) return TipsUtils.tips_toast('身份证号码格式不正确');
 	if (!ValidateUtils.validatePhone(formData.value.phone)) return TipsUtils.tips_toast('手机号格式不正确');

+ 8 - 7
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="detailObj.certificateInnocence" mode="widthFix"></image>
+					<image :src="detailObj?.certificateInnocence" @click="_previewImage(detailObj?.certificateInnocence)" mode="widthFix"></image>
 				</view>
 			</view>
 			<view class="item-list">
 				<view class="item-text">健康证</view>
 				<view class="item-img">
-					<image :src="detailObj.healthy" mode="widthFix"></image>
+					<image :src="detailObj?.healthy" @click="_previewImage(detailObj?.healthy)" mode="widthFix"></image>
 				</view>
 			</view>
 		</view>
@@ -24,10 +24,10 @@
 				<zzx-icon name="idcard"></zzx-icon>
 				<view class="text">荣誉认证</view>
 			</view>
-			<view class="item-list" v-for="(item,index) in detailObj.honorImgList" :key="index">
+			<view class="item-list" v-for="(item,index) in detailObj?.honorImgList" :key="index">
 				<!-- <view class="item-text">篮球裁判三级</view> -->
 				<view class="item-img">
-					<image :src="item" mode="widthFix"></image>
+					<image :src="item" @click="_previewImage(detailObj?.honorImgList,item)" mode="widthFix"></image>
 				</view>
 			</view>
 		</view>
@@ -36,8 +36,9 @@
 
 <script lang="ts" setup>
 	import { ref, onMounted } from 'vue';
-	import { onLoad, onPageScroll } from '@dcloudio/uni-app';
-	import { http } from '@/utils/http'
+	import { onLoad} from '@dcloudio/uni-app';
+	import { http } from '@/utils/http';
+	import { _previewImage } from "@/utils/util";
 	import { useCacheStore } from '@/stores/cache'
 	const cache = useCacheStore()
 	onLoad((option)=>{
@@ -50,7 +51,7 @@
 	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)=>{
+		http.get('/coachC/findByCoachId',{data:{id:detailId.value,longitude:cache.get('LON')||0,latitude:cache.get('LAT')||0},loading:true}).then((res)=>{
 			detailObj.value=res.result
 		})
 	}

+ 4 - 4
src/pages/index/courseDetail/index.vue

@@ -64,7 +64,7 @@
 				<view class="title">购买须知</view>
 				<view class="tips-text">
 					<view class="text">
-						<rich-text :nodes="courseDetailInfo?.reminder"></rich-text>
+						<rich-text :nodes="fixImgStyle(courseDetailInfo?.reminder)"></rich-text>
 					</view>
 					<!-- <view class="more">
 						<text>查看更多</text>
@@ -160,7 +160,7 @@
 
 <script lang="ts" setup>
 import { ref, onMounted, getCurrentInstance, nextTick } from 'vue';
-import { RouterUtils, _previewImage, TipsUtils } 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, onShareAppMessage } from '@dcloudio/uni-app';
@@ -207,8 +207,8 @@ onMounted(() => {
 
 const openMap = () => {
 	uni.openLocation({
-		latitude: courseDetailInfo.value.latitude,
-		longitude: courseDetailInfo.value.longitude,
+		latitude: courseDetailInfo.value.latitude||0,
+		longitude: courseDetailInfo.value.longitude||0,
 		name: courseDetailInfo.value.name,
 		address: courseDetailInfo.value.address,
 		success: function () {

+ 3 - 3
src/pages/index/detail/index.vue

@@ -156,8 +156,8 @@ const openphone = () => {
 
 const openMap = () => {
 	uni.openLocation({
-		latitude: detailInfo.value.latitude,
-		longitude: detailInfo.value.longitude,
+		latitude: detailInfo.value.latitude||0,
+		longitude: detailInfo.value.longitude||0,
 		name: detailInfo.value.name,
 		address: detailInfo.value.address,
 		success: function () {
@@ -183,7 +183,7 @@ const onchange = (e) => {
 // 课程列表
 const courseList = ref([])
 const get_courseList = (categoryId) => {
-	http.get('/detail/courseInfoVOList', { data: { categoryId: categoryId, id: listId.value, longitude: cache.get('LON'), latitude: cache.get('LAT') }, loading: true }).then((res) => {
+	http.get('/detail/courseInfoVOList', { data: { categoryId: categoryId, id: listId.value, longitude: cache.get('LON')||0, latitude: cache.get('LAT')||0 }, loading: true }).then((res) => {
 		courseList.value = res.result
 	})
 }

+ 2 - 2
src/pages/index/events/index.vue

@@ -60,8 +60,8 @@ const listData = ref<any[]>([]);
 const formData = ref({
 	pageNo: 1,
 	pageSize: 10,
-	latitude:cache.get('LAT'),
-	longitude:cache.get('LON'),
+	latitude:cache.get('LAT')||0,
+	longitude:cache.get('LON')||0,
 });
 const get_eventsList = () => {
 	http.get('/game/findByList', { data: {...formData.value}, loading: true }).then((res: any) => {

+ 6 - 5
src/pages/index/eventsDetail/index.vue

@@ -168,7 +168,7 @@ const sel_index = ref(0);
 const selectList = ref(['赛程安排', '图文说明']);
 const instance = getCurrentInstance();
 onLoad((option) => {
-	formData.value.id = option.id;
+	formData.value.id = option.id?option.id:cache.get('GAME_ID');
 	get_location()
 })
 onMounted(() => {
@@ -313,22 +313,23 @@ const updateCountdown = () => {
 const eventsInfoObj = ref({})
 const formData = ref({
 	id: 0,
-	latitude: cache.get('LAT'),
-	longitude: cache.get('LON'),
+	latitude: cache.get('LAT')||0,
+	longitude: cache.get('LON')||0,
 });
 const get_eventsInfo = () => {
 	http.get('/game/findById', { data: formData.value, loading: true }).then((res) => {
 		eventsInfoObj.value = res.result;
 		messages.value = res.result.gameOrderVoList;
 		endTime.value = res.result.applicationEndTime;
+		cache.remove('GAME_ID')
 	});
 }
 
 // 打开地图
 const open_map = () => {
 	uni.openLocation({
-		latitude: eventsInfoObj.value.latitude,
-		longitude: eventsInfoObj.value.longitude,
+		latitude: eventsInfoObj.value.latitude||0,
+		longitude: eventsInfoObj.value.longitude||0,
 		name: eventsInfoObj.value.name,
 		address: eventsInfoObj.value.address,
 		success: function () {

+ 54 - 10
src/pages/index/eventsRegister/index.vue

@@ -125,7 +125,8 @@
 						<view class="r-userinfo-item">
 							<view class="r-item-title">被保人</view>
 							<view class="r-item-info">{{ insureUser.userData.length }}人(<text
-									v-for="(user,index) in insureUser.userData" :key="user.id">{{ user.fullName }}{{ index < insureUser.userData.length - 1 ? ',' : '' }}</text>)
+									v-for="(user, index) in insureUser.userData" :key="user.id">{{ user.fullName }}{{
+										index < insureUser.userData.length - 1 ? ',' : '' }}</text>)
 							</view>
 						</view>
 						<view class="r-userinfo-item">
@@ -178,7 +179,7 @@
 import { ref, onMounted, computed } from 'vue';
 import { http } from '@/utils/http';
 import { RouterUtils, TipsUtils, idCardHide, debounce } from '@/utils/util';
-import { onLoad } from '@dcloudio/uni-app';
+import { onLoad,onShareAppMessage } from '@dcloudio/uni-app';
 import zsTabs from "@/components/zzx-tabs/zzx-tabs.vue";
 import { useCacheStore } from '@/stores/cache';
 const cache = useCacheStore()
@@ -194,6 +195,17 @@ onMounted(() => {
 	get_eventsInfoDetail()
 	getInsureData()
 })
+
+onShareAppMessage((res) => {
+	if (res.from === 'button') {// 来自页面内分享按钮
+		console.log(res.target)
+	}
+	return {
+		title: '邀请您加入',
+		path: `pages/index/userList/index?userId=${cache.get('USER_INFO').id}`
+	}
+})
+
 const totalPrice = computed(() => {
 	let projectPrice = 0;
 	if (selectTabs.value === 0 && individualEvents.value[0] && selectEvents.value != null) {
@@ -418,6 +430,8 @@ let orderFormData = ref({
 		certificationDTOS: []
 	}
 })
+const orderCode = ref(null)
+const orderId = ref(null)
 const submitOrderImpl = () => {
 	if (selectTabs.value == 0) {
 		orderFormData.value.orderType = 3
@@ -431,13 +445,15 @@ const submitOrderImpl = () => {
 		if (!orderFormData.value.gameCertificationForm.teamName) return TipsUtils.tips_toast('请输入队名')
 		// 校验资质证明图片
 		const certificationDTOS = orderFormData.value.gameCertificationForm.certificationDTOS
-		if (!certificationDTOS || certificationDTOS.length !== aptitudesList.value.length) {
-			return TipsUtils.tips_toast('请上传所有必传的资质证明图片')
-		}
-		// 校验每个资质证明是否都已上传图片
-		for (let i = 0; i < certificationDTOS.length; i++) {
-			if (!certificationDTOS[i].certificationImg) {
-				return TipsUtils.tips_toast(`请上传${certificationDTOS[i].name}的图片`)
+		if (aptitudesList.value) {
+			if (!certificationDTOS || certificationDTOS.length !== aptitudesList.value.length) {
+				return TipsUtils.tips_toast('请上传所有必传的资质证明图片')
+			}
+			// 校验每个资质证明是否都已上传图片
+			for (let i = 0; i < certificationDTOS.length; i++) {
+				if (!certificationDTOS[i].certificationImg) {
+					return TipsUtils.tips_toast(`请上传${certificationDTOS[i].name}的图片`)
+				}
 			}
 		}
 	}
@@ -454,9 +470,37 @@ const submitOrderImpl = () => {
 	}
 	// orPayOrder0-免费/试听 1-调起支付
 	http.post('/order/createOrder', data, { loading: true }).then((res) => {
-		getOrderQuery(res.result.orderCode, res.result.orderId)
+		orderCode.value = res.result.orderCode
+		orderId.value = res.result.orderId
+		if (res.result.orPayOrder == 1) {
+			paymentOrder(res.result.params)
+		} else {
+			getOrderQuery(res.result.orderCode, res.result.orderId)
+		}
 	})
 }
+
+const paymentOrder = (payInfo: object) => {
+	getOrderQuery(orderCode.value, orderId.value)
+	// console.log(payInfo, '支付参数');
+	// uni.requestPayment({
+	// 	provider: 'wxpay',
+	// 	...payInfo,
+	// 	success: function (res) {
+	// 		console.log('支付成功', res);
+	// 		getOrderQuery(orderCode.value, orderId.value)
+	// 	},
+	// 	fail: function (err) {
+	// 		console.log('支付失败', err);
+	// 		if (err.errMsg == 'requestPayment:fail cancel') {
+	// 			RouterUtils.to_page(`/pages/index/toBeUsed/index?orderId=${orderId.value}&orderType=${orderFormData.value.orderType}`)
+	// 			return
+	// 		}
+	// 		// TipsUtils.tips_toast('支付失败,请稍后重试');
+	// 	}
+	// });
+}
+
 const submitOrder = debounce(submitOrderImpl, 500)
 
 // code编码 "100001支付成功";"100002查询失败"; "100003查询中 "; "100004支付失败"

+ 26 - 2
src/pages/index/gymDetail/components/popup.vue

@@ -284,12 +284,36 @@ const orderFormData = ref({
 	productIds: null,
 	amount: null,
 })
+const orderCode = ref(null)
+const orderId = ref(null)
 const submitOrderImpl = () => {
 	http.post('/order/createOrder', orderFormData.value, { loading: true }).then((res) => {
-		getOrderQuery(res.result.orderCode, res.result.orderId)
+		orderCode.value = res.result.orderCode
+		orderId.value = res.result.orderId
+		paymentOrder(res.result.params)
+		// getOrderQuery(res.result.orderCode, res.result.orderId)
 	})
 }
-
+const paymentOrder = (payInfo: object) => {
+	getOrderQuery(orderCode.value, orderId.value)
+	// console.log(payInfo, '支付参数');
+	// uni.requestPayment({
+	// 	provider: 'wxpay',
+	// 	...payInfo,
+	// 	success: function (res) {
+	// 		console.log('支付成功', res);
+	// 		getOrderQuery(orderCode.value, orderId.value)
+	// 	},
+	// 	fail: function (err) {
+	// 		console.log('支付失败', err);
+	// 		if (err.errMsg == 'requestPayment:fail cancel') {
+	// 			RouterUtils.to_page(`/pages/index/toBeUsed/index?orderId=${orderId.value}&orderType=${orderFormData.value.orderType}`)
+	// 			return
+	// 		}
+	// 		// TipsUtils.tips_toast('支付失败,请稍后重试');
+	// 	}
+	// });
+}
 const submitOrder = debounce(submitOrderImpl, 500)
 
 // code编码 "100001支付成功";"100002查询失败"; "100003查询中 "; "100004支付失败"

+ 24 - 13
src/pages/index/gymDetail/index.vue

@@ -66,7 +66,7 @@
 			</view>
 		</view>
 	</view>
-	<view class="content" v-if="charteredList">
+	<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"
@@ -98,17 +98,18 @@
 					</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, index) in charteredList.timeSlot"
+							<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" v-if="item.sellingPrice">¥{{ item.sellingPrice?.toFixed(2) }}起
 								</view>
 							</view>
-							<view class="not-data" v-if="charteredList.timeSlot?.length < 1">暂无可选时间</view>
+							<view class="not-data" v-if="charteredList?.timeSlot?.length < 1">暂无可选时间</view>
 						</scroll-view>
 					</view>
 				</view>
+				<view class="not-data" v-if="charteredList?.length < 1">暂无场地数据</view>
 			</view>
 			<view class="venue-card">
 				<view class="card-title">
@@ -159,7 +160,7 @@
 				<view class="">全平台每种类型的运动课程只可免费试听一次</view>
 			</view>
 			<view class="select-btn">
-				<view :class="sel_btn === index ? 'distance' : 'score'" v-for="(item, index) in allCategoryList"
+				<view :class="sel_btn === index ? 'distance' : 'score'" v-for="(item, index) in allCourseCategoryList"
 					:key="item.id" @click="selectallCategory(item, index)">{{ item.name }}</view>
 			</view>
 			<block v-if="!courseLoading">
@@ -243,7 +244,7 @@
 				<view class="a-content">
 					{{ item.evaluateContent }}
 				</view>
-				<scroll-view class="scroll-view_H" scroll-x="true" :show-scrollbar="false">
+				<scroll-view class="scroll-view_H" scroll-x="true" :show-scrollbar="false" v-if="item.images != ''">
 					<view class="scroll-view-item_H uni-bg-red" v-for="(img, idx) in item.images.split(',')" :key="idx">
 						<image @click="_previewImage(item.images.split(','), img)" :src="img" mode=""></image>
 					</view>
@@ -305,8 +306,8 @@ onMounted(() => {
 	});
 	get_placeInfo()
 	get_allCategory()
+	get_allCourseCategory()
 	getFindByOrderPage()
-	console.log('组件已挂载:', openPopup.value)
 })
 const get_navheight = () => {
 	const systemInfo = uni.getSystemInfoSync();
@@ -414,8 +415,8 @@ const scrollToTop = () => {
 // 打开地图
 const open_map = () => {
 	uni.openLocation({
-		latitude: detailInfo.value.latitude,
-		longitude: detailInfo.value.longitude,
+		latitude: detailInfo.value.latitude || 0,
+		longitude: detailInfo.value.longitude || 0,
 		name: detailInfo.value.name,
 		address: detailInfo.value.address,
 		success: function () {
@@ -452,16 +453,26 @@ const get_placeInfo = () => {
 	})
 }
 
-// 课程分类
+// 场地分类
 const allCategoryList = ref([])
 const categoryId = ref()
 const get_allCategory = () => {
 	http.get('/detail/getAllCategory', { data: { id: listId.value } }).then((res) => {
+		if (!res.result || res.result.length == 0) return
 		categoryId.value = res.result[0].id
 		allCategoryList.value = res.result
-		get_courseList(categoryId.value)
 		get_placeInfoNoFixation(categoryId.value)
-		// get_placeInfoDetail(categoryId.value, '')
+	})
+}
+
+// 课程分类
+const allCourseCategoryList = ref([])
+const categoryCourseId = ref()
+const get_allCourseCategory = () => {
+	http.get('/detail/getAllCourseCategory', { data: { id: listId.value } }).then((res) => {
+		categoryCourseId.value = res.result[0].id
+		allCourseCategoryList.value = res.result
+		get_courseList(categoryCourseId.value)
 	})
 }
 
@@ -470,7 +481,7 @@ const courseList = ref([])
 const courseLoading = ref(false)
 const get_courseList = (categoryId: string) => {
 	courseLoading.value = true
-	http.get('/detail/courseInfoVOList', { data: { categoryId: categoryId, id: listId.value, longitude: cache.get('LON'), latitude: cache.get('LAT') } }).then((res) => {
+	http.get('/detail/courseInfoVOList', { data: { categoryId: categoryId, id: listId.value, longitude: cache.get('LON') || 0, latitude: cache.get('LAT') || 0 } }).then((res) => {
 		courseLoading.value = false
 		courseList.value = res.result
 	})
@@ -493,7 +504,7 @@ const selectChartered = (e, i) => {
 }
 
 // 包场信息
-const charteredList = ref()
+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

+ 42 - 15
src/pages/index/gymPay/index.vue

@@ -436,10 +436,21 @@ const orderCode = ref(null)
 const orderId = ref(null)
 const submitOrderImpl = () => {
 	orderFormData.value.amount = countTotal.value
+
+	// 计算总金额
+	let totalPrice = 0;
+	if (previewCourseInfo.value?.originalPrice) {
+		totalPrice = previewCourseInfo.value.originalPrice * countTotal.value;
+	} else {
+		const sellingPrice = previewCourseInfo.value?.sellingPrice || 0;
+		const totalPriceValue = previewCourseInfo.value?.totalPrice || 0;
+		totalPrice = ((sellingPrice - (sellingPrice - totalPriceValue)) * countTotal.value + totalInsurePrice.value);
+	}
+
 	if (!placeId.value) {
-		// if (!userData.value) return TipsUtils.tips_toast('请添加用户信息')
-		// if (userData.value.length < countTotal.value) return TipsUtils.tips_toast(`请至少选择${countTotal.value}人`)
-		// if (userData.value.length > countTotal.value) return TipsUtils.tips_toast(`最多选择${countTotal.value}人`)
+		if (!userData.value) return TipsUtils.tips_toast('请添加用户信息')
+		if (userData.value.length < countTotal.value) return TipsUtils.tips_toast(`请至少选择${countTotal.value}人`)
+		if (userData.value.length > countTotal.value) return TipsUtils.tips_toast(`最多选择${countTotal.value}人`)
 		orderFormData.value.orderType = 5
 		orderFormData.value.type = 2
 	} else {
@@ -453,6 +464,17 @@ const submitOrderImpl = () => {
 	if (!userData || userData.value.length === 0) {
 		delete data.familyIds
 	}
+
+	// 如果总金额为0,直接创建订单并跳转,不调用微信支付
+	if (totalPrice === 0 || buyType.value == 1) {
+		http.post('/order/createOrder', data, { loading: true }).then((res) => {
+			orderCode.value = res.result.orderCode
+			orderId.value = res.result.orderId
+			// 直接查询订单状态,模拟支付成功
+			getOrderQuery(orderCode.value, orderId.value)
+		})
+		return;
+	}
 	uni.requestSubscribeMessage({
 		tmplIds: ['Yi1Z1IKRwgF6-mpiFcOUTvavc4TUAsfsLynK_3Yu350', 'NPlIBEwBDPX23J3Jip0CwYUU4vF9ZlcK8U1d6Gs4yrM'],
 		success(res) {
@@ -475,19 +497,24 @@ const submitOrderImpl = () => {
 }
 
 const paymentOrder = (payInfo: object) => {
+	getOrderQuery(orderCode.value, orderId.value)
 	console.log(payInfo, '支付参数');
-	uni.requestPayment({
-		provider: 'wxpay',
-		...payInfo,
-		success: function (res) {
-			console.log('支付成功', res);
-			getOrderQuery(orderCode.value, orderId.value)
-		},
-		fail: function (err) {
-			console.log('支付失败', err);
-			// TipsUtils.tips_toast('支付失败,请稍后重试');
-		}
-	});
+	// uni.requestPayment({
+	// 	provider: 'wxpay',
+	// 	...payInfo,
+	// 	success: function (res) {
+	// 		console.log('支付成功', res);
+	// 		getOrderQuery(orderCode.value, orderId.value)
+	// 	},
+	// 	fail: function (err) {
+	// 		console.log('支付失败', err);
+	// 		if (err.errMsg == 'requestPayment:fail cancel') {
+	// 			RouterUtils.to_page(`/pages/index/toBeUsed/index?orderId=${orderId.value}&orderType=${orderFormData.value.orderType}`)
+	// 			return
+	// 		}
+	// 		// TipsUtils.tips_toast('支付失败,请稍后重试');
+	// 	}
+	// });
 }
 
 const submitOrder = debounce(submitOrderImpl, 500)

+ 13 - 10
src/pages/index/index.vue

@@ -91,7 +91,7 @@
 						<image :src="item.cover"></image>
 						<view class="detail-text">免费</view>
 					</view>
-					<view class="not-data" v-if="stCourseList.length == 0">暂无课程数据</view>
+					<view class="not-data" v-if="stCourseList.length == 0" style="color: #000;">暂无课程数据</view>
 				</view>
 			</view>
 			<view class="audition" @click="gotoPage(`/pages/index/training/index?priceType=0`)">
@@ -108,7 +108,7 @@
 						<view class="detail-text">¥{{ item.sellingPrice || '0' }}</view>
 					</view>
 				</view>
-				<view class="not-data" v-if="gyCourseList.length == 0">暂无课程数据</view>
+				<view class="not-data" v-if="gyCourseList.length == 0" style="color: #fff;">暂无课程数据</view>
 			</view>
 		</view>
 		<view class="hot-instructor" v-if="!indexLoading">
@@ -137,7 +137,7 @@
 							<view class="name-tag">
 								<view class="name">
 									<view>
-										<text class="textHidden" style="width: 130rpx;">{{ item.name }}</text>
+										<text class="textHidden" style="width: 130rpx;text-align: center;">{{ item.name }}</text>
 									</view>
 									<image v-if="index % 2 === 0" src="/src/static/name_bg.png" mode=""></image>
 									<image v-else src="/src/static/name_bg1.png" mode=""></image>
@@ -147,10 +147,12 @@
 								</view>
 							</view>
 							<view class="ascription textHidden">{{ item.orgName }}</view>
-							<view class="sign textHidden">教理念:{{ item.teachingPhilosophy||'暂无'}}</view>
+							<view class="sign textHidden">教理念:{{ item.teachingPhilosophy||'暂无'}}</view>
 						</view>
 						<view class="type-icon">
-							<image src="/src/static/hot-icon2.png" mode=""></image>
+							<!-- https://national-motion.oss-cn-beijing.aliyuncs.com/opt/upFiles/dxVfKxD7aH2397154f377d68fb59a71226c9c2f078a9_1758071827887.png -->
+							<!-- https://national-motion.oss-cn-beijing.aliyuncs.com/opt/upFiles/uv0VmclIvXiJc1081e0e33e281a8a436d24ec9ca87c3_1758071769194.png -->
+							<image :src="index % 2 === 0?hotInstructorImg1:hotInstructorImg2" mode=""></image>
 						</view>
 					</view>
 					<view class="i-data">
@@ -192,7 +194,7 @@
 
 <script setup lang="ts">
 import zsLoading from '@/components/zzx-loading/zzx-loading.vue'
-import { ref, onMounted, computed } from 'vue'
+import { ref, onMounted, computed} from 'vue'
 import { onLoad, onPageScroll, onPullDownRefresh } from '@dcloudio/uni-app';
 import zsEmpty from '@/components/zs-empty/index.vue'
 import { TipsUtils } from '@/utils/util';
@@ -200,18 +202,19 @@ import { http } from '@/utils/http'
 import { useCacheStore } from '@/stores/cache'
 const cache = useCacheStore()
 import QQMapWX from '@/libs/qqmap-wx-jssdk.js'
-const token = computed(() => {
-	return cache.get('TOKEN')
-})
+const token = computed(() => cache.token)
 const navBarHeight = ref(0);
 const statusBarHeight = ref(0);
 const titleBarHeight = ref(0);
 const navOpacity = ref(0);
 const backgroundColor = ref('#D2FD73');
 const instructorList = ref();
-const indexLoading = ref(true)
+const indexLoading = ref(true);
+const hotInstructorImg1 = ref('https://national-motion.oss-cn-beijing.aliyuncs.com/opt/upFiles/dxVfKxD7aH2397154f377d68fb59a71226c9c2f078a9_1758071827887.png')
+const hotInstructorImg2 = ref('https://national-motion.oss-cn-beijing.aliyuncs.com/opt/upFiles/uv0VmclIvXiJc1081e0e33e281a8a436d24ec9ca87c3_1758071769194.png')
 onLoad(() => {
 	get_location()
+	console.log(token.value, 'token是否刷新')
 })
 onPullDownRefresh(() => {
 	get_indexInfo()

+ 2 - 2
src/pages/index/instructorDetail/index.vue

@@ -106,7 +106,7 @@
 				<view class="a-content">
 					{{ item.evaluateContent }}
 				</view>
-				<scroll-view class="scroll-view_H" scroll-x="true" :show-scrollbar="false">
+				<scroll-view class="scroll-view_H" scroll-x="true" :show-scrollbar="false" v-if="item.images!=''">
 					<view class="scroll-view-item_H uni-bg-red" v-for="(img, idx) in item.images.split(',')" :key="idx">
 						<image @click="_previewImage(item.images.split(','), img)" :src="img" mode=""></image>
 					</view>
@@ -153,7 +153,7 @@ const to_certifying = () => {
 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) => {
+	http.get('/coachC/findByCoachId', { data: { id: detailId.value, longitude: cache.get('LON')||0, latitude: cache.get('LAT')||0 }, loading: true }).then((res) => {
 		detailObj.value = res.result
 	})
 }

+ 1 - 1
src/pages/index/search/index.vue

@@ -2,7 +2,7 @@
 	<view class="content">
 		<view class="header-search">
 			<zzx-icon name="search" size="18" style="margin-top: 2rpx;margin-left: 20rpx;"></zzx-icon>
-			<input type="text" v-model="searchText" placeholder="搜索俱乐部名称" />
+			<input type="text" v-model="searchText" placeholder="搜索名称" />
 			<view class="search-btn" @click="to_search">
 				搜索
 			</view>

+ 6 - 4
src/pages/index/searchPage/components/instructor.vue

@@ -14,18 +14,18 @@
 						<view class="name-tag">
 							<view class="name">
 								<view class="">
-									<text class="textHidden" style="width: 130rpx;">{{ item.name }}</text>
+									<text class="textHidden" style="width: 130rpx;text-align: center;">{{ item.name }}</text>
 								</view>
 								<image v-if="index % 2 === 0" src="/src/static/name_bg.png" mode=""></image>
 								<image v-else src="/src/static/name_bg1.png" mode=""></image>
 							</view>
-							<view class="tag" v-for="(tag,index) in item.list">{{tag}}</view>
+							<view class="tag" v-for="(tag, index) in item.list">{{ tag }}</view>
 						</view>
 						<view class="ascription textHidden">{{ item.orgName }}</view>
 						<view class="sign textHidden">{{ item.teachingPhilosophy }}</view>
 					</view>
 					<view class="type-icon">
-						<image src="/src/static/hot-icon2.png" mode=""></image>
+						<image :src="index % 2 === 0 ? hotInstructorImg1 : hotInstructorImg2" mode=""></image>
 					</view>
 				</view>
 				<view class="i-data">
@@ -62,8 +62,10 @@
 </template>
 
 <script lang="ts" setup>
+import { ref } from 'vue'
 import { RouterUtils } from '@/utils/util'
-
+const hotInstructorImg1 = ref('https://national-motion.oss-cn-beijing.aliyuncs.com/opt/upFiles/dxVfKxD7aH2397154f377d68fb59a71226c9c2f078a9_1758071827887.png')
+const hotInstructorImg2 = ref('https://national-motion.oss-cn-beijing.aliyuncs.com/opt/upFiles/uv0VmclIvXiJc1081e0e33e281a8a436d24ec9ca87c3_1758071769194.png')
 interface Props {
 	listData?: any;
 }

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

@@ -165,7 +165,7 @@
 	const searchLoading=ref(true)
 	const current=ref(1)
 	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) => {
+		http.post('/home/search', { keyword: keyword.value, size: 10, current:current.value, venueType:String(tagsVal), longitude: cache.get('LON')||0, latitude: cache.get('LAT')||0 }).then((res) => {
 			searchLoading.value=false
 			if(current.value==1){
 				searchList.value=res.result.records

+ 36 - 5
src/pages/index/submitOrder/index.vue

@@ -72,7 +72,8 @@
 						<view class="r-userinfo-item">
 							<view class="r-item-title">被保人</view>
 							<view class="r-item-info">{{ insureUser.userData.length }}人(<text
-									v-for="(user,index) in insureUser.userData" :key="user.id">{{ user.fullName }}{{ index < insureUser.userData.length - 1 ? ',' : '' }}</text>)
+									v-for="(user, index) in insureUser.userData" :key="user.id">{{ user.fullName }}{{
+										index < insureUser.userData.length - 1 ? ',' : '' }}</text>)
 							</view>
 						</view>
 						<view class="r-userinfo-item">
@@ -142,8 +143,8 @@ import { useCacheStore } from '@/stores/cache'
 const cache = useCacheStore()
 const calendar = ref();
 const check_index = ref(0);
-onLoad((option) => {
-	placeId.value = option.id
+onLoad((option:any) => {
+	placeId.value = option.id?option.id:cache.get('PLACE_ID')
 	orderFormData.value.productIds = option.id
 })
 
@@ -263,6 +264,7 @@ const get_previewOrderPlaceSchool = (startTime: string) => {
 			})
 		})
 		insureIdList.value = res.result.insureIdList
+		cache.remove('PLACE_ID')
 	})
 }
 
@@ -359,6 +361,9 @@ let orderFormData = ref({
 		familyMembersIds: '',
 	}
 })
+
+const orderCode = ref(null)
+const orderId = ref(null)
 const submitOrderImpl = () => {
 	if (userData.value.length === 0) return TipsUtils.tips_toast('请添加成员')
 	if (!rulesId.value) {
@@ -374,19 +379,45 @@ const submitOrderImpl = () => {
 		delete data.insureOrderInfoForm;
 	}
 	http.post('/order/createOrder', data, { loading: true }).then((res) => {
+		orderCode.value = res.result.orderCode
+		orderId.value = res.result.orderId
 		uni.requestSubscribeMessage({
 			tmplIds: ['WSJjc9I24ijtr3EyNVXjEvTQm0gIECW9ABYVFcegOwM'],
 			success(su) {
 				TipsUtils.tips_toast('订阅成功')
-				getOrderQuery(res.result.orderCode, res.result.orderId)
+				if (orderFormData.value.insureOrderInfoForm.insureId!='') {
+					paymentOrder(res.result.params)
+				} else {
+					getOrderQuery(res.result.orderCode, res.result.orderId)
+				}
 			},
 			fail(err) {
-				getOrderQuery(res.result.orderCode, res.result.orderId)
+				if (orderFormData.value.insureOrderInfoForm.insureId!='') {
+					paymentOrder(res.result.params)
+				} else {
+					getOrderQuery(res.result.orderCode, res.result.orderId)
+				}
 				console.log(err, '订阅消息失败')
 			}
 		})
 	})
 }
+const paymentOrder = (payInfo: object) => {
+	// getOrderQuery(orderCode.value, orderId.value)
+	console.log(payInfo, '支付参数');
+	uni.requestPayment({
+		provider: 'wxpay',
+		...payInfo,
+		success: function (res) {
+			console.log('支付成功', res);
+			getOrderQuery(orderCode.value, orderId.value)
+		},
+		fail: function (err) {
+			console.log('支付失败', err);
+			// TipsUtils.tips_toast('支付失败,请稍后重试');
+		}
+	});
+}
 
 const submitBooking = debounce(submitOrderImpl, 500)  //防抖
 

+ 190 - 19
src/pages/index/toBeUsed/index.vue

@@ -5,7 +5,7 @@
 			<view class="timer-text">请在<text style="color: #FB5B5B;">{{ downTime }}</text>内支付</view>
 			<view class="timer-btn">
 				<view class="cancel-btn" @click="cancelOrder(orderDetailInfo?.id)">取消订单</view>
-				<view class="pay-btn">立即支付¥119</view>
+				<view class="pay-btn" @click="submitPay(orderDetailInfo?.id)">立即支付¥{{ orderDetailInfo?.price }}</view>
 			</view>
 		</view>
 		<view class="t-header" v-else>
@@ -71,21 +71,21 @@
 							orderDetailInfo?.proInfoList?.length }}</text></view>
 					<!-- refundType:退款类型;0可退/到期自动退 1限时退 2不可退" -->
 					<view class="shoping-refund" v-if="orderDetailInfo?.runType == 0">全天</view>
-					<view class="shoping-refund" v-else>
-						<!-- {{ DateUtils.formatDateToHHmm(orderDetailInfo?.createTime) + '-' +DateUtils.formatDateToHHmm(orderDetailInfo?.endTime) }} -->
+					<view class="shoping-refund"
+						v-if="orderDetailInfo?.runType != null && orderDetailInfo?.runType != 0">
 						{{ orderDetailInfo?.startTime }}-{{ orderDetailInfo?.endTime }}
 					</view>
 					<view class="shoping-refund" style="display: flex;align-items: center;"
 						v-if="orderDetailInfo?.gameScheduleNum"
 						@click="RouterUtils.to_page(`/pages/index/gamePlan/index?orderId=${orderDetailInfo?.id}`)">
-						<text>篮球赛</text>
+						<text>{{ orderDetailInfo?.appGameScheduleVOList[0].name }}</text>
 						<text>{{ orderDetailInfo?.gameScheduleNum }}场</text>
 						<zzx-icon name="ashRight" size="10"></zzx-icon>
 					</view>
 					<view class="shoping-refund">
 						<!-- 退款类型;0可退/到期自动退 1限时退 2不可退-->
-						  <text v-if="orderDetailInfo?.refundType == 0|| orderDetailInfo?.refundType == 1">随时退·过期退</text>
-						  <text v-if="orderDetailInfo?.refundType == 2">不支持退款</text>
+						<text v-if="orderDetailInfo?.refundType == 0 || orderDetailInfo?.refundType == 1">随时退·过期退</text>
+						<text v-if="orderDetailInfo?.refundType == 2">不支持退款</text>
 					</view>
 					<view class="shoping-price" @click="pricePopup.open()">
 						<view class="price">¥{{ orderDetailInfo?.totalPrice.toFixed(2) }}</view>
@@ -113,11 +113,21 @@
 				<button class="g-share-btn" open-type="share"></button>
 				邀请好友报名
 			</view>
+			<view class="t-shoping-address-eventInfo" v-if="countdownVisible&&orderDetailInfo?.orderType==3||orderDetailInfo?.orderType==4">
+				<view class="time">{{ days }}</view>
+				<view class="unit">天</view>
+				<view class="time">{{ hours }}</view>
+				<view class="unit">:</view>
+				<view class="time">{{ minutes }}</view>
+				<view class="unit">:</view>
+				<view class="time">{{ seconds }}</view>
+				<view class="">后比赛开始</view>
+			</view>
 		</view>
 		<!-- 待使用展示 -->
 		<view class="t-qrcode-card"
-			v-if="orderPageInfo?.orderType == 2 || orderPageInfo?.orderType == 5 || orderPageInfo?.orderType == 1 || orderPageInfo?.orderType == 3 || orderPageInfo?.orderType == 4&&orderDetailInfo?.orderStatus!=0">
-			<block v-if="orderDetailInfo?.orSchoolCourse != 1">
+			v-if="orderPageInfo?.orderType == 0 || orderPageInfo?.orderType == 2 || orderPageInfo?.orderType == 5 || orderPageInfo?.orderType == 1 || orderPageInfo?.orderType == 3 || orderPageInfo?.orderType == 4 && orderDetailInfo?.orderStatus != 0">
+			<block v-if="orderDetailInfo?.orSchoolCourse != 1 && hasPendingUsageItems && orderPageInfo?.orderType != 0">
 				<view class="qrcode-box">
 					<view class="item-qrcode">
 						<uv-qrcode ref="qrcode" size="100px" :value="orderDetailInfo?.id"></uv-qrcode>
@@ -125,7 +135,7 @@
 				</view>
 				<view class="download-qrcode" @click="download_qrcode">下载到手机</view>
 			</block>
-			<view v-else style="color: #222;font-size: 26rpx;">通过学校门口闸机时,通过人脸自动核验</view>
+			<view v-if="orderDetailInfo?.orderType == 0" style="color: #222;font-size: 26rpx;">通过学校门口闸机时,通过人脸自动核验</view>
 			<view class="t-todeused">
 				<view class="todeused">
 					<view class="text">{{ orderDetailInfo?.orderStatus }}</view>
@@ -137,12 +147,12 @@
 				</view>
 				<!-- orderStatus:0-待付款 1-待使用 2-已使用 3-已到期 4-已取消 5-退款中 6已退款 -->
 				<!-- type:0-学校 1-包场 2-无固定场 3-个人赛 4-团队赛 5-课程 6-保险 -->
-				<view class="order-num" v-for="item in orderDetailInfo?.proInfoList" :key="item.id">
+				<view class="order-num" v-for="(item, index) in orderDetailInfo?.proInfoList" :key="item.id"
+					@click="RouterUtils.to_page(`/pages/index/tryUseRecord/index?ticketNo=${item.ticketNo}&proInfoList=${JSON.stringify(orderDetailInfo?.proInfoList)}&selectValue=${index}`)">
 					<text v-if="item.type != 6">{{ item.ticketNo }}&nbsp;&nbsp; {{ item.userName }}</text>
 					<zzx-icon v-if="item.type != 6" name="ashRight" size="12"></zzx-icon>
 					<!-- <view v-if="item.type != 6" class="t-use-status">{{ getStatusText(item.orderStatus) }}</view> -->
-					 <text v-if="item.type != 6&&orderPageInfo?.orderType == 1">{{ item.expireTime }}到期</text>
-					<!-- 体育馆包场和无固定场 -->
+					<text v-if="item.type != 6 && orderPageInfo?.orderType == 1">{{ item.expireTime }}到期</text>
 					<!-- <view>申请退款</view> -->
 				</view>
 			</view>
@@ -188,7 +198,8 @@
 		<view class="t-address-card">
 			<view class="address">
 				<zzx-icon name="location"></zzx-icon>
-				<view class="">{{ orderDetailInfo?.courseSiteAddress || orderDetailInfo?.schoolAddress||orderDetailInfo?.gameAddress }}</view>
+				<view class="">{{ orderDetailInfo?.courseSiteAddress ||
+					orderDetailInfo?.schoolAddress || orderDetailInfo?.gameAddress }}</view>
 			</view>
 			<view class="nav-info">
 				<view class="nav" @click="open_map">
@@ -224,7 +235,8 @@
 					<view class="insureOrder-title">被保人</view>
 					<view class="insureOrder-text" v-if="orderDetailInfo?.insureOrderInfoList">
 						{{ orderDetailInfo?.insureOrderInfoList.length }}人(<text
-							v-for="(name,index) in orderDetailInfo?.insureOrderInfoList" :key="name.id">{{ name.familyUserName
+							v-for="(name, index) in orderDetailInfo?.insureOrderInfoList" :key="name.id">{{
+								name.familyUserName
 							}}{{ index < orderDetailInfo?.insureOrderInfoList.length - 1 ? ',' : '' }}</text>)</view>
 				</view>
 				<view class="t-use-insureOrder">
@@ -242,7 +254,8 @@
 				</view>
 			</view>
 		</view>
-		<view class="t-use-card" v-if="orderPageInfo?.orderType == 5 && queryWaitSignList?.length > 0&&orderDetailInfo?.orderStatus!=0">
+		<view class="t-use-card"
+			v-if="orderPageInfo?.orderType == 5 && queryWaitSignList?.length > 0 && orderDetailInfo?.orderStatus != 0">
 			<view class="use-tips t-contract-list">
 				<view class="title">电子合同</view>
 				<view class="text contract-list">
@@ -315,8 +328,9 @@
 				@click="RouterUtils.to_page(`/pages/index/gameResult/index?orderId=${orderDetailInfo?.id}`)">查看成绩</view>
 		</view>
 		<!-- 已使用展示 -->
-		<view class="appraise-btn" v-if="orderPageInfo?.orderType != 3 && orderDetailInfo?.orderStatus == '已使用'"
-			@click="RouterUtils.to_page(`/pages/index/writeComments/index?siteId=${orderDetailInfo?.addressSiteId}&orderId=${orderDetailInfo?.id}`)">
+		<view class="appraise-btn"
+			v-if="orderPageInfo?.orderType != 3 && orderDetailInfo?.orderStatus == '已使用' && orderDetailInfo?.orEvaluate == 0 && orderDetailInfo?.type != 3 && orderDetailInfo?.type != 4"
+			@click="RouterUtils.to_page(`/pages/index/writeComments/index?siteId=${orderDetailInfo?.addressSiteId}&orderId=${orderDetailInfo?.id}&siteName=${orderDetailInfo?.siteName}`)">
 			写评价
 		</view>
 	</view>
@@ -406,9 +420,9 @@
 </template>
 
 <script lang="ts" setup>
-import { ref, onMounted } from 'vue';
+import { ref, onMounted, computed } from 'vue';
 import { TipsUtils, RouterUtils, DateUtils, _previewImage, fixImgStyle } from '@/utils/util'
-import { onLoad, onShow, onShareAppMessage } from '@dcloudio/uni-app';
+import { onLoad, onShow, onShareAppMessage, onUnload } from '@dcloudio/uni-app';
 import { http } from '@/utils/http'
 import zsLoading from '@/components/zzx-loading/zzx-loading.vue'
 const qrcode = ref();
@@ -423,6 +437,15 @@ onLoad((option) => {
 onShow(() => {
 	getOrderDetailInfo()
 })
+onUnload(() => {
+	console.log('点击了返回按钮');
+	if (orderPageInfo.value.isPayOrder != 1) {
+		uni.switchTab({
+			url: '/pages/index/index'
+		});
+		return true;
+	}
+});
 onShareAppMessage((res) => {
 	if (res.from === 'button') {// 来自页面内分享按钮
 		console.log(res.target)
@@ -447,6 +470,15 @@ const statusMap = {
 	5: '退款中'
 }
 
+// 判断是否有待使用的项目
+const hasPendingUsageItems = computed(() => {
+	if (!orderDetailInfo.value?.proInfoList || !Array.isArray(orderDetailInfo.value.proInfoList)) {
+		return false;
+	}
+	// 检查是否有任意一项的orderStatus为1(待使用)
+	return orderDetailInfo.value.proInfoList.some(item => item.orderStatus === 1);
+});
+
 // 获取状态文本的函数
 const getStatusText = (status: number): string => {
 	return statusMap[status as keyof typeof statusMap] || ''
@@ -565,6 +597,13 @@ const getOrderDetailInfo = (() => {
 		gameCertificationList.value = JSON.parse(res.result.gameCertification || '{}')
 		loading.value = false
 		getQueryWaitSignList(res.result.id)
+		// 初始化倒计时(如果订单类型是比赛相关)
+		if ((res.result.orderType == 3 || res.result.orderType == 4) && res.result.appGameScheduleVOList?.length > 0) {
+			const gameStartTime = res.result.gameStartTime;
+			if (gameStartTime) {
+				startCountdown(gameStartTime);
+			}
+		}
 	})
 })
 
@@ -602,6 +641,116 @@ const downTimeFun = () => {
 	}
 }
 
+// ==================赛事倒计时start==================
+// 添加倒计时相关响应式数据
+const countdownVisible = ref(false);
+const days = ref('00');
+const hours = ref('00');
+const minutes = ref('00');
+const seconds = ref('00');
+let countdownTimer: any = null;
+// 添加倒计时函数
+const startCountdown = (startTime: string) => {
+	const startDate = new Date(startTime);
+	startDate.setHours(0, 0, 0, 0);
+	const now = new Date();
+	let timeDifference = startDate.getTime() - now.getTime();
+	if (timeDifference <= 0) {
+		countdownVisible.value = false;
+		return;
+	}
+	countdownVisible.value = true;
+	// 清除之前的定时器
+	if (countdownTimer) {
+		clearInterval(countdownTimer);
+	}
+	// 立即更新一次显示
+	updateCountdown(timeDifference);
+	countdownTimer = setInterval(() => {
+		timeDifference = startDate.getTime() - new Date().getTime();
+
+		if (timeDifference <= 0) {
+			clearInterval(countdownTimer);
+			countdownVisible.value = false;
+			return;
+		}
+
+		updateCountdown(timeDifference);
+	}, 1000);
+};
+// ==================赛事倒计时end==================
+// 更新倒计时显示
+const updateCountdown = (timeDifference: number) => {
+	// 计算天、小时、分钟、秒
+	const totalSeconds = Math.floor(timeDifference / 1000);
+	const totalMinutes = Math.floor(totalSeconds / 60);
+	const totalHours = Math.floor(totalMinutes / 60);
+	const totalDays = Math.floor(totalHours / 24);
+
+	days.value = totalDays.toString().padStart(2, '0');
+	hours.value = (totalHours % 24).toString().padStart(2, '0');
+	minutes.value = (totalMinutes % 60).toString().padStart(2, '0');
+	seconds.value = (totalSeconds % 60).toString().padStart(2, '0');
+};
+
+
+// ==================提交支付start==================
+const orderCode = ref()
+const orderId = ref()
+const submitPay = (e: any) => {
+	http.put(`/order/payOrder?appOrderId=${e}`, {}, { loading: true }).then((res) => {
+		orderCode.value = res.result.orderCode
+		orderId.value = res.result.orderId
+		paymentOrder(res.result.params)
+	})
+}
+const paymentOrder = (payInfo: object) => {
+	// getOrderQuery(orderCode.value, orderId.value)
+	console.log(payInfo, '支付参数');
+	uni.requestPayment({
+		provider: 'wxpay',
+		...payInfo,
+		success: function (res) {
+			console.log('支付成功', res);
+			getOrderQuery(orderCode.value, orderId.value)
+		},
+		fail: function (err) {
+			console.log('支付失败', err);
+			// TipsUtils.tips_toast('支付失败,请稍后重试');
+		}
+	});
+}
+
+const getOrderQuery = (orderCode: string, orderId: string, retryCount = 0) => {
+	http.get('/order/orderQuery', { data: { orderCode: orderCode }, loading: true }).then((res) => {
+		if (res.result == '100001') {
+			TipsUtils.tips_toast('支付成功');
+			getOrderDetailInfo()
+		} else if (retryCount <= 3) {
+			setTimeout(() => {
+				getOrderQuery(orderCode, orderId, retryCount + 1)
+			}, 1000)
+		} else {
+			if (res.result == '100003') {
+				console.log('查询中,但已达到最大查询次数')
+			} else if (res.result == '100002') {
+				console.log('查询失败')
+			} else if (res.result == '100004') {
+				console.log('支付失败')
+				TipsUtils.tips_toast('支付失败')
+			}
+		}
+	}).catch((error) => {
+		console.error('查询订单失败:', error)
+		if (retryCount < 2) {
+			setTimeout(() => {
+				getOrderQuery(orderCode, orderId, retryCount + 1)
+			}, 1000)
+		}
+	})
+}
+// ==================提交支付end==================
+
 // 取消订单
 const cancelOrder = async (e: any) => {
 	let res: any = await TipsUtils.tips_alert('确定取消订单吗?', true)
@@ -980,6 +1129,28 @@ const getSignUrl = (signFlowId: string) => {
 		}
 	}
 
+	.t-shoping-address-eventInfo {
+		margin-top: 20rpx;
+		display: flex;
+		align-items: center;
+		justify-content: center;
+		gap: 8rpx;
+		font-weight: bold;
+		font-size: 28rpx;
+		color: #222222;
+		border-top: 1rpx solid #F0F0F0;
+		height: 80rpx;
+
+		.time {
+			width: 60rpx;
+			height: 60rpx;
+			background: rgba(200, 255, 12, 0.5);
+			border-radius: 16rpx;
+			text-align: center;
+			line-height: 60rpx;
+		}
+	}
+
 	.t-invite {
 		margin-top: 24rpx;
 		font-size: 28rpx;

+ 2 - 2
src/pages/index/training/index.vue

@@ -126,8 +126,8 @@
 		http.get('/detail/findByCourseList', {
 			data: {
 				priceType: priceType,
-				longitude: cache.get('LON'),
-				latitude: cache.get('LAT'),
+				longitude: cache.get('LON')||0,
+				latitude: cache.get('LAT')||0,
 				orderByType: orderByType,
 				pageNo: pageNo.value,
 				pageSize: 10

+ 100 - 56
src/pages/index/tryUseRecord/index.vue

@@ -1,91 +1,135 @@
 <template>
 	<view class="t-header-card">
-		<text>0017 1712 5994  杨锦新</text>
-		<view style="transform: rotate(180deg);">
-			<zzx-icon name="up" size="12"></zzx-icon>
-		</view>
+		<uni-data-select v-model="selectValue" :localdata="range" @change="selectChange"></uni-data-select>
 	</view>
 	<view class="content">
-		<view class="t-uselist-card" v-for="item in 2">
+		<view class="t-uselist-card" v-for="item in appGmtInfoList" :key="item.id">
 			<view class="t-use-address">
-				<view class="add-title">使用地点</view>
-				<view class="add-text">观山湖区第十二小学</view>
+				<view class="add-title">使用地点:</view>
+				<view class="add-text">{{ item.siteName }}</view>
 			</view>
 			<view class="t-use-picre">
-				<view class="pic-title">使用照片</view>
+				<view class="pic-title">使用照片:</view>
 				<view class="pic-img">
-					<image src="https://img.shetu66.com/2023/06/13/1686646672844195.jpg" mode=""></image>
+					<image :src="item.picUrl" mode=""></image>
 				</view>
 			</view>
 			<view class="t-use-address" style="margin-top: 20rpx;">
-				<view class="add-title">使用时间</view>
-				<view class="add-text">2025-05-02 16:14:56</view>
+				<view class="add-title">使用时间:</view>
+				<view class="add-text">{{ item.gmtCreate }}</view>
 			</view>
 		</view>
-		<view class="t-uselist-card" v-for="item in 2">
+		<view class="t-uselist-card" v-for="item in appIsinList" :key="item.id">
 			<view class="t-use-address">
-				<view class="add-title">核验场馆</view>
-				<view class="add-text">观山湖区第十二小学</view>
+				<view class="add-title">核验场馆:</view>
+				<view class="add-text">{{ item.useAddress }}</view>
 			</view>
 			<view class="t-use-address" style="margin-top: 20rpx;">
-				<view class="add-title">核验人</view>
-				<view class="add-text">张三</view>
+				<view class="add-title">核验人:</view>
+				<view class="add-text">{{ item.verifyUserName }}</view>
 			</view>
 			<view class="t-use-address" style="margin-top: 20rpx;">
-				<view class="add-title">核验时间</view>
-				<view class="add-text">2025-05-02 16:14:56</view>
+				<view class="add-title">核验时间:</view>
+				<view class="add-text">{{ item.useTime }}</view>
 			</view>
 		</view>
 	</view>
 </template>
 
-<script>
+<script lang="ts" setup>
+import { ref, onMounted } from 'vue';
+import { onLoad } from '@dcloudio/uni-app';
+import { http } from '@/utils/http';
+const proInfoList = ref([]);
+const range = ref([])
+const selectValue = ref(0)
+onLoad((option: any) => {
+	console.log(option, '路由参数');
+	ticketNo.value = option.ticketNo;
+	proInfoList.value = JSON.parse(option.proInfoList || '[]');
+	proInfoList.value = proInfoList.value.filter((item: any) => item.type == 5||item.type==4||item.type==3);
+	range.value = proInfoList.value.map((item: any, index: number) => ({
+		value: index,
+		text: `${item.ticketNo} ${item.userName}`
+	}))
+	console.log(range.value, 'range');
+	// 匹配对应项
+	const matchedIndex = proInfoList.value.findIndex((item: any) => item.ticketNo === ticketNo.value);
+	if (matchedIndex !== -1) {
+		selectValue.value = matchedIndex;
+	}
+})
+onMounted(() => {
+	getUseRecordList()
+})
+
+const selectChange = (e) => {
+	const value = e;
+	const item = range.value.find((item: any) => item.value === value);
+	const text = item ? item.text : '';
+	const number = text.split(' ')[0];
+	ticketNo.value = number;
+	getUseRecordList()
+}
+
+const ticketNo = ref();
+const appIsinList = ref([]);
+const appGmtInfoList = ref([]);
+const getUseRecordList = () => {
+	http.get('/order/queryOrderUseRecords', { data: { ticketNo: ticketNo.value }, loading: true }).then((res) => {
+		appGmtInfoList.value = res.result.appGmtInfoList
+		appIsinList.value=res.result.appIsinList
+	})
+}
 </script>
 
 <style lang="less" scoped>
-	.t-header-card{
+.t-header-card {
+	background: #fff;
+	padding: 20rpx;
+	font-weight: bold;
+	font-size: 28rpx;
+}
+
+.t-uselist-card {
+	margin-top: 20rpx;
+	padding: 20rpx;
+	background: #FFFFFF;
+	border-radius: 32rpx;
+
+	.t-use-address {
 		display: flex;
 		align-items: center;
-		gap: 12rpx;
-		background: #fff;
-		padding: 20rpx;
-		font-weight: bold;
-		font-size: 28rpx;
-		color: #222222;
+		gap: 20rpx;
+
+		.add-title {
+			font-size: 28rpx;
+			color: #AAAAAA;
+		}
+
+		.add-text {
+			font-size: 28rpx;
+			color: #222222;
+		}
 	}
-	.t-uselist-card{
+
+	.t-use-picre {
+		display: flex;
+		gap: 20rpx;
 		margin-top: 20rpx;
-		padding: 20rpx;
-		background: #FFFFFF;
-		border-radius: 32rpx;
-		.t-use-address{
-			display: flex;
-			align-items: center;
-			gap: 20rpx;
-			.add-title{
-				font-size: 28rpx;
-				color: #AAAAAA;
-			}
-			.add-text{
-				font-size: 28rpx;
-				color: #222222;
-			}
+
+		.pic-title {
+			font-size: 28rpx;
+			color: #AAAAAA;
 		}
-		.t-use-picre{
-			display: flex;
-			gap: 20rpx;
-			margin-top: 20rpx;
-			.pic-title{
-				font-size: 28rpx;
-				color: #AAAAAA;
-			}
-			.pic-img{
-				&>image{
-					width: 160rpx;
-					height: 160rpx;
-					border-radius: 8rpx;
-				}
+
+		.pic-img {
+			&>image {
+				width: 160rpx;
+				height: 160rpx;
+				border-radius: 8rpx;
 			}
 		}
 	}
+}
 </style>

+ 2 - 0
src/pages/index/userList/index.vue

@@ -25,6 +25,7 @@
 					<zzx-icon :name="item.selOut ? 'selected' : 'unchecked'" size="14"></zzx-icon>
 				</view>
 			</view>
+		<view class="not-data" v-if="!userList?.length">暂无家庭成员</view>
 		</view>
 		<view style="height: 160rpx;"></view>
 		<view class="u-select-btn" @click="confirmSelect" v-if="!nameText">
@@ -78,6 +79,7 @@ onShareAppMessage((res) => {
 		path: `pages/index/userList/index?userId=${cache.get('USER_INFO').id}`
 	}
 })
+
 onMounted(() => {
 })
 

+ 1 - 1
src/pages/index/venue/index.vue

@@ -124,7 +124,7 @@
 	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)=>{
+		http.post('/home/getPlaceList',{size: 10, current:current.value, venueType:String(tagsVal), longitude: cache.get('LON')||0, latitude: cache.get('LAT')||0}).then((res)=>{
 			searchLoading.value=false
 			if(current.value==1){
 				dataList.value=res.result.records

+ 3 - 2
src/pages/index/writeComments/index.vue

@@ -1,7 +1,7 @@
 <template>
 	<view class="content">
 		<view class="w-header-card">
-			<view class="w-title">观山湖区第十二小学</view>
+			<view class="w-title">{{ siteName }}</view>
 			<view class="w-star">
 				<view class="">综合评价</view>
 				<uni-rate size="16" :value="formData.score" @change="onRateChange" />
@@ -36,11 +36,12 @@ import { http } from '@/utils/http';
 import { useCacheStore } from '@/stores/cache';
 const cache = useCacheStore()
 const upPicUrl = ref('http://192.168.0.11:8080/jeecg-boot/sys/common/upload')
-
+const siteName= ref('')
 onLoad((options) => {
 	console.log(options);
 	formData.value.siteId = options.siteId
 	formData.value.orderId = options.orderId
+	siteName.value=options.siteName
 })
 const formData = ref({
 	score: 0,

+ 1 - 1
src/pages/mine/accountSetting/index.vue

@@ -36,7 +36,7 @@ const userName = computed(() => {
 const selectUpType = () => {
 	uni.chooseImage({
 		count: 1,
-		sizeType: ['original', 'compressed'],
+		sizeType: ['compressed'],
 		sourceType: ['album', 'camera'],
 		success: function (res) {
 			tempFilePaths.value = res.tempFilePaths

+ 107 - 105
src/pages/mine/feedbackRecord/index.vue

@@ -3,163 +3,165 @@
 		title="意见反馈"></zzx-navbar>
 	<view style="height:170rpx;"></view>
 	<view class="content">
-		<view class="f-record-card" v-for="(item,index) in recordList" :key="item.id">
+		<view class="f-record-card" v-for="(item, index) in recordList" :key="item.id">
 			<view class="f-user-info">
 				<view class="user-info">
 					<view class="user-header">
 						<image :src="item.avatar" mode=""></image>
 					</view>
-					<view class="user-name">{{item.userName}}</view>
+					<view class="user-name">{{ item.userName }}</view>
 				</view>
-				<view class="user-time">{{item.createTime}}</view>
+				<view class="user-time">{{ item.createTime }}</view>
 			</view>
-			<view class="user-tags">{{item.feedbackName}}</view>
+			<view class="user-tags">{{ item.feedbackName }}</view>
 			<view class="user-des">
-				{{item.feedbackDescribed}}
+				{{ item.feedbackDescribed }}
 			</view>
 			<view class="user-picture">
 				<scroll-view class="scroll-view_H" scroll-x="true">
-					<view class="scroll-view-item_H" v-for="(img,index) in item.feedbackImgList" :key="index">
-						<image @click="_previewImage(item.feedbackImgList,img)" :src="img" mode=""></image>
+					<view class="scroll-view-item_H" v-for="(img, index) in item.feedbackImgList" :key="index">
+						<image @click="_previewImage(item.feedbackImgList, img)" :src="img" mode=""></image>
 					</view>
 				</scroll-view>
 			</view>
 			<view class="f-merchants-reply" v-if="item.replyContent">
 				<view class="merchants">商家回复</view>
 				<view class="reply">
-					<text :class="[switchOpen?'':'textHidden']">{{item.replyContent}}</text>
-					<text class="open-colse" @click="switchOpen=!switchOpen">{{switchOpen?'收起':'展开'}}</text>
+					<text :class="[switchOpen ? '' : 'textHidden']">{{ item.replyContent }}</text>
+					<text class="open-colse" @click="switchOpen = !switchOpen">{{ switchOpen ? '收起' : '展开' }}</text>
 				</view>
 			</view>
 		</view>
+		<zs-empty v-if="recordList?.length === 0" />
 	</view>
 </template>
 
 <script lang="ts" setup>
-	import { ref, onMounted } from 'vue'
-	import zzxNavbar from '@/components/zzx-navbar/zzx-navbar.vue';
-	import { onLoad, onReachBottom } from '@dcloudio/uni-app';
-	import { _previewImage } from '@/utils/util'
-	import { http } from '@/utils/http'
-	const switchOpen = ref(false);
-	const recordList = ref();
-	const pageNo = ref(1)
-	onReachBottom(() => {
-		pageNo.value++
-		get_recordList()
-	})
-	onMounted(() => {
-		get_recordList()
+import { ref, onMounted } from 'vue'
+import zzxNavbar from '@/components/zzx-navbar/zzx-navbar.vue';
+import zsEmpty from '@/components/zs-empty/index.vue';
+import { onLoad, onReachBottom } from '@dcloudio/uni-app';
+import { _previewImage } from '@/utils/util'
+import { http } from '@/utils/http'
+const switchOpen = ref(false);
+const recordList = ref();
+const pageNo = ref(1)
+onReachBottom(() => {
+	pageNo.value++
+	get_recordList()
+})
+onMounted(() => {
+	get_recordList()
+})
+const get_recordList = () => {
+	http.get('/my/feedback/findByPage', { data: { pageNo: pageNo.value, pageSize: 10 }, loading: true }).then((res) => {
+		if (pageNo.value == 1) {
+			recordList.value = res.result.records
+		} else {
+			recordList.value = recordList.value.concat(res.result.records)
+		}
 	})
-	const get_recordList = () => {
-		http.get('/my/feedback/findByPage', { data: { pageNo: pageNo.value, pageSize: 10 }, loading: true }).then((res) => {
-			if (pageNo.value == 1) {
-				recordList.value = res.result.records
-			} else {
-				recordList.value = recordList.value.concat(res.result.records)
-			}
-		})
-	}
+}
 </script>
 
 <style lang="less">
-	.f-record-card {
-		background: #FFFFFF;
-		border-radius: 32rpx;
-		padding: 20rpx;
-		margin-top: 20rpx;
+.f-record-card {
+	background: #FFFFFF;
+	border-radius: 32rpx;
+	padding: 20rpx;
+	margin-top: 20rpx;
+
+	.f-user-info {
+		display: flex;
+		align-items: center;
+		justify-content: space-between;
 
-		.f-user-info {
+		.user-info {
 			display: flex;
 			align-items: center;
-			justify-content: space-between;
-
-			.user-info {
-				display: flex;
-				align-items: center;
-				gap: 16rpx;
-
-				.user-header {
-					&>image {
-						width: 60rpx;
-						height: 60rpx;
-						border-radius: 50%;
-					}
-				}
+			gap: 16rpx;
 
-				.user-name {
-					font-weight: bold;
-					font-size: 24rpx;
-					color: #222222;
+			.user-header {
+				&>image {
+					width: 60rpx;
+					height: 60rpx;
+					border-radius: 50%;
 				}
 			}
 
-			.user-time {
+			.user-name {
+				font-weight: bold;
 				font-size: 24rpx;
-				color: #AAAAAA;
+				color: #222222;
 			}
 		}
 
-		.user-tags {
-			background: #F5F5F5;
-			border-radius: 8rpx;
-			width: 152rpx;
-			height: 48rpx;
-			font-size: 28rpx;
+		.user-time {
+			font-size: 24rpx;
 			color: #AAAAAA;
-			text-align: center;
-			line-height: 48rpx;
-			margin-top: 20rpx;
 		}
+	}
 
-		.user-des {
-			margin-top: 16rpx;
-			font-size: 28rpx;
-			color: #222222;
-		}
+	.user-tags {
+		background: #F5F5F5;
+		border-radius: 8rpx;
+		width: 152rpx;
+		height: 48rpx;
+		font-size: 28rpx;
+		color: #AAAAAA;
+		text-align: center;
+		line-height: 48rpx;
+		margin-top: 20rpx;
+	}
 
-		.user-picture {
-			margin-top: 20rpx;
+	.user-des {
+		margin-top: 16rpx;
+		font-size: 28rpx;
+		color: #222222;
+	}
 
-			.scroll-view_H {
-				.scroll-view-item_H {
-					&>image {
-						width: 160rpx;
-						height: 160rpx;
-						border-radius: 8rpx;
-						margin-right: 20rpx;
-					}
+	.user-picture {
+		margin-top: 20rpx;
+
+		.scroll-view_H {
+			.scroll-view-item_H {
+				&>image {
+					width: 160rpx;
+					height: 160rpx;
+					border-radius: 8rpx;
+					margin-right: 20rpx;
 				}
 			}
 		}
+	}
 
-		.f-merchants-reply {
-			display: flex;
-			gap: 12rpx;
-			background: #F6F6F6;
-			border-radius: 16rpx;
-			padding: 20rpx;
-			margin-top: 20rpx;
-			transition: all .3s;
+	.f-merchants-reply {
+		display: flex;
+		gap: 12rpx;
+		background: #F6F6F6;
+		border-radius: 16rpx;
+		padding: 20rpx;
+		margin-top: 20rpx;
+		transition: all .3s;
 
-			.merchants {
-				width: 100rpx;
-				height: 40rpx;
-				font-size: 24rpx;
-				color: #AAAAAA;
-			}
+		.merchants {
+			width: 100rpx;
+			height: 40rpx;
+			font-size: 24rpx;
+			color: #AAAAAA;
+		}
 
-			.reply {
-				width: 520rpx;
-				font-size: 24rpx;
-				color: #222222;
-				display: flex;
+		.reply {
+			width: 520rpx;
+			font-size: 24rpx;
+			color: #222222;
+			display: flex;
 
-				.open-colse {
-					color: #AAAAAA;
-					width: 120rpx;
-				}
+			.open-colse {
+				color: #AAAAAA;
+				width: 120rpx;
 			}
 		}
 	}
+}
 </style>

+ 72 - 12
src/pages/mine/orderInfo/index.vue

@@ -6,9 +6,10 @@
 	<view style="height: 80rpx;"></view>
 	<view class="content">
 		<view class="o-orderlist-card" v-for="item in orderList" :key="item.orderId"
-			@click="RouterUtils.to_page(`/pages/index/toBeUsed/index?orderId=${item.orderId}&orderType=${item.orderType}`)">
+			@click="RouterUtils.to_page(`/pages/index/toBeUsed/index?orderId=${item.orderId}&orderType=${item.orderType}&isPayOrder=1`)">
 			<view class="o-order-name">
-				<view class="order-name">{{item.orderType==5?'上课地点':'场地'}}:{{ item.orderProInfoList[0].address || '--' }}</view>
+				<view class="order-name">{{ item.orderType == 5 ? '上课地点' : '场地' }}:{{ item.orderProInfoList[0].address || '--'
+					}}</view>
 				<!-- 待付款 -->
 				<view class="order-status" v-if="item.orderStatus == 0">待支付(剩余{{ item.downTime }})</view>
 				<view class="item-order-status" style="color:#FB5B5B;" v-if="item.orderStatus == 1">待使用</view>
@@ -36,7 +37,7 @@
 						<view class="scroll-view-item_H scroll-order-item">
 							<view class="item-order">
 								<view class="order-img">
-									<image :src="item.orderInsureList[0].productImage" mode="">
+									<image :src="item.orderInsureList[0].productImage.split(',')[0]" mode="">
 									</image>
 								</view>
 								<view class="order-name textHidden">{{ item.orderInsureList[0].productName }}</view>
@@ -46,13 +47,15 @@
 					<!-- 没保险 -->
 					<view class="item-order-single" v-else>
 						<view class="single-img">
-							<image :src="item.orderProInfoList[0].productImage" mode=""></image>
+							<image :src="item.orderProInfoList[0].productImage.split(',')[0]" mode=""></image>
 						</view>
 						<view class="single-name">
-							<view class="item-single-name textHidden" v-if="item.orderType!=1">{{ item.orderProInfoList[0].productName }}</view>
+							<view class="item-single-name textHidden" v-if="item.orderType != 1">{{
+								item.orderProInfoList[0].productName }}</view>
 							<view class="item-single-name" v-else>
 								<!-- {{ item.orderProInfoList[0].productName }} -->
-								  <view class="textHidden" v-for="name in item.orderProInfoList" :key="name.id">{{ name.productName }}</view>
+								<view class="textHidden" v-for="name in item.orderProInfoList" :key="name.id">{{
+									name.productName }}</view>
 							</view>
 						</view>
 					</view>
@@ -66,18 +69,19 @@
 			<!-- 待付款 -->
 			<view class="o-order-btn">
 				<view class="cancel-btn" v-if="item.orderStatus == 0" @click.stop="cancelOrder(item)">取消订单</view>
-				<view class="pay-btn" v-if="item.orderStatus == 0">付款</view>
+				<view class="pay-btn" v-if="item.orderStatus == 0" @click.stop="submitPay(item)">付款</view>
 				<!-- 售后/退款 -->
-				<view class="pay-btn" v-if="item.orderStatus == 2"
-					@click="RouterUtils.to_page(`/pages/index/writeComments/index?siteId=${item.addressSiteId}&orderId=${item.orderId}`)">
+				<view class="pay-btn" v-if="item.orderStatus == 2&&item.orEvaluate==0&&item.orderType!=3&&item.orderType!=4"
+					@click.stop="RouterUtils.to_page(`/pages/index/writeComments/index?siteId=${item.addressSiteId}&orderId=${item.orderId}&siteName=${item.orderProInfoList[0].address}`)">
 					评价</view>
 				<!-- 已使用 -->
 				<view class="cancel-btn" v-if="selected == 4">申请退款</view>
 				<view class="pay-btn" v-if="selected == 4">凭证</view>
 			</view>
 			<!-- 待使用 -->
-			<view class="o-order-tips" v-if="item.orderStatus == 1">
-				限{{ item.orderProInfoList[0].frameTimeStr }}使用,过期作废
+			<view class="o-order-tips" v-if="item.orderStatus == 1&&item.orderType != 3&&item.orderType != 4">
+				<text v-if="item.orderProInfoList[0].frameTimeStr&&item.orderProInfoList[0].frameTimeStr!='00:00-00:00'">限{{ item.orderProInfoList[0].frameTimeStr }}使用,过期作废</text>
+				<text v-if="item.earlyRefundTime">请按时到场,退款需提前{{ item.earlyRefundTime }}分钟</text>
 			</view>
 		</view>
 		<zs-empty v-if="orderList.length == 0"></zs-empty>
@@ -142,6 +146,63 @@ const selectedItem = (i) => {
 	getOrderList()
 }
 
+// 提交支付start
+const orderCode=ref()
+const orderId=ref()
+const submitPay = (e: any) => {
+	http.put(`/order/payOrder?appOrderId=${e.orderId}`, {}, { loading: true }).then((res) => {
+		orderCode.value=res.result.orderCode
+		orderId.value=res.result.orderId
+		paymentOrder(res.result.params)
+	})
+}
+const paymentOrder = (payInfo: object) => {
+	// getOrderQuery(orderCode.value, orderId.value)
+	console.log(payInfo, '支付参数');
+	uni.requestPayment({
+		provider: 'wxpay',
+		...payInfo,
+		success: function (res) {
+			console.log('支付成功', res);
+			getOrderQuery(orderCode.value, orderId.value)
+		},
+		fail: function (err) {
+			console.log('支付失败', err);
+			// TipsUtils.tips_toast('支付失败,请稍后重试');
+		}
+	});
+}
+
+const getOrderQuery = (orderCode: string, orderId: string, retryCount = 0) => {
+	http.get('/order/orderQuery', { data: { orderCode: orderCode }, loading: true }).then((res) => {
+		if (res.result == '100001') {
+			TipsUtils.tips_toast('支付成功');
+			getOrderList()
+		} else if (retryCount <= 3) {
+			setTimeout(() => {
+				getOrderQuery(orderCode, orderId, retryCount + 1)
+			}, 1000)
+		} else {
+			if (res.result == '100003') {
+				console.log('查询中,但已达到最大查询次数')
+			} else if (res.result == '100002') {
+				console.log('查询失败')
+			} else if (res.result == '100004') {
+				console.log('支付失败')
+				TipsUtils.tips_toast('支付失败')
+			}
+		}
+	}).catch((error) => {
+		console.error('查询订单失败:', error)
+		if (retryCount < 2) {
+			setTimeout(() => {
+				getOrderQuery(orderCode, orderId, retryCount + 1)
+			}, 1000)
+		}
+	})
+}
+// 提交支付end
+
 // 获取订单数据
 const orderFormData = ref({
 	pageNo: 1,
@@ -196,7 +257,6 @@ const startCountdown = (item) => {
 				}
 				return;
 			}
-
 			const newMinutes = Math.floor(newRemainingTime / (1000 * 60));
 			const newSeconds = Math.floor((newRemainingTime % (1000 * 60)) / 1000);
 			item.downTime = `${newMinutes.toString().padStart(2, '0')}分${newSeconds.toString().padStart(2, '0')}秒`;

BIN
src/static/hot-icon2.png


+ 17 - 4
src/stores/cache.ts

@@ -7,7 +7,17 @@ interface CacheItem {
 
 export const useCacheStore = defineStore('cache', {
 	state: () => ({
-		cache: {} as Record<string, CacheItem>
+		cache: {} as Record<string, CacheItem>,
+		token: (() => {
+			const data = uni.getStorageSync('TOKEN')
+			if (data) {
+				try {
+					const parsed = JSON.parse(data)
+					if (parsed.expire > Date.now()) return parsed.value
+				} catch {}
+			}
+			return null
+		})() as string | null
 	}),
 	actions: {
 		set(key : string, value : any, ttl ?: number) {
@@ -15,21 +25,21 @@ export const useCacheStore = defineStore('cache', {
 				? Number.MAX_SAFE_INTEGER
 				: Date.now() + ttl * 1000;
 			this.cache[key] = { value, expire }
-			// 同步到本地存储
 			uni.setStorageSync(key, JSON.stringify({ value, expire }))
+			if (key === 'TOKEN') this.token = value
 		},
 		get<T = any>(key : string) : T | null {
-			// 优先内存中读取
 			if (this.cache[key] && this.cache[key].expire > Date.now()) {
+				if (key === 'TOKEN') this.token = this.cache[key]?.value ?? null
 				return this.cache[key].value
 			}
-			// 本地存储读取
 			const data = uni.getStorageSync(key)
 			if (data) {
 				try {
 					const parsed : CacheItem = JSON.parse(data)
 					if (parsed.expire > Date.now()) {
 						this.cache[key] = parsed
+						if (key === 'TOKEN') this.token = parsed.value
 						return parsed.value
 					}
 					this.remove(key)
@@ -37,15 +47,18 @@ export const useCacheStore = defineStore('cache', {
 					console.error('缓存解析失败', e)
 				}
 			}
+			if (key === 'TOKEN') this.token = null
 			return null
 		},
 		remove(key : string) {
 			delete this.cache[key]
 			uni.removeStorageSync(key)
+			if (key === 'TOKEN') this.token = null
 		},
 		clear() {
 			this.cache = {}
 			uni.clearStorageSync()
+			this.token = null
 		}
 	}
 })

+ 1 - 1
src/utils/common/upload.ts

@@ -4,7 +4,7 @@ import { useCacheStore } from '@/stores/cache'
 export function uploadImage(tempFilePath: string, onSuccess?: (url: string) => void, onFail?: (err: any) => void) {
     const cache = useCacheStore()
     uni.uploadFile({
-        url: 'http://192.168.0.11:8080/jeecg-boot/sys/common/upload',
+        url: 'https://api.qlapp.cn/jeecgboot/sys/common/upload',
         filePath: tempFilePath,
         name: 'file',
         header: {

+ 13 - 5
src/utils/http/index.ts

@@ -25,7 +25,6 @@
  */
 import type { RequestTask } from '@dcloudio/types'
 import type { UniRequestConfig, UniResponse } from '@dcloudio/uni-app'
-
 // 定义基础响应类型
 export interface HttpResponse<T = any> {
   code: number
@@ -145,7 +144,7 @@ export class HttpClient {
             complete: () => {
               this.pendingRequests.delete(requestKey)
               if (mergedConfig.loading) {
-                uni.hideLoading({noConflict:true})
+                uni.hideLoading({ noConflict: true })
               }
             }
           }) as RequestTask
@@ -182,6 +181,7 @@ export const http = new HttpClient({
   // baseURL: 'http://192.168.0.217:8080/jeecg-boot/app',
   // baseURL: 'http://192.168.1.166:8080/jeecg-boot/app',
   baseURL: 'http://192.168.0.11:8080/jeecg-boot/app',
+  // baseURL: 'https://api.qlapp.cn/jeecgboot/app', //生产
   headers: {
     'Content-Type': 'application/json'
   }
@@ -209,18 +209,26 @@ uni.addInterceptor('request', {
 
 //响应拦截器
 let isShowing = false;
+let is401Handled = false
 uni.addInterceptor('request', {
   success: (res) => {
     const data = res.data as HttpResponse
     if (data.code === 401) {
+      uni.clearStorageSync() // 清除所有本地缓存,页面响应式会自动刷新
       uni.showToast({
         title: data.message || '登录已失效,请重新登录',
         icon: 'none',
         duration: 2000
       })
-      setTimeout(() => {
-        uni.clearStorage()
-      }, 500)
+      if (!is401Handled) {
+        is401Handled = true
+        setTimeout(() => {
+          console.log('Token 失效,触发刷新');
+          uni.switchTab({
+            url: '/pages/index/index'
+          })
+        }, 500)
+      }
       return {
         ...res,
         errMsg: `Token失效: ${data.message}`,

+ 36 - 24
src/utils/util/index.ts

@@ -189,29 +189,41 @@ export const randomColor = (): string => {
  * 预览图片
  * @param url - 图片地址
  */
-export const _previewImage = (urls: any, current: string) => {
-	let previewUrls = urls;
-	let previewCurrent = current;
-	if (Array.isArray(urls) && urls.length === 1) {
-		previewUrls = [current];
-		previewCurrent = current;
-	}
-	uni.previewImage({
-		urls: previewUrls,
-		current: previewCurrent, // 指定当前图片
-		longPressActions: {
-			itemList: ['发送给朋友', '保存图片', '收藏'],
-			success: function (data) {
-				uni.showToast({
-					title: '操作成功',
-					icon: 'none'
-				})
-			},
-			fail: function (err) {
-				console.log(err.errMsg);
-			}
-		}
-	});
+export const _previewImage = (urls: any, current?: string) => {
+    let previewUrls: string[] = [];
+    let previewCurrent: string | undefined = current;
+    // 如果 urls 是字符串,转换为数组
+    if (typeof urls === 'string') {
+        previewUrls = [urls];
+        // 如果没有指定 current,则使用第一个图片作为当前图片
+        if (!previewCurrent) {
+            previewCurrent = urls;
+        }
+    } 
+    // 如果 urls 是数组,直接使用
+    else if (Array.isArray(urls)) {
+        previewUrls = urls;
+        // 如果没有指定 current 且数组不为空,则使用数组第一个元素
+        if (!previewCurrent && urls.length > 0) {
+            previewCurrent = urls[0];
+        }
+    }
+    uni.previewImage({
+        urls: previewUrls,
+        current: previewCurrent,
+        longPressActions: {
+            itemList: ['发送给朋友', '保存图片', '收藏'],
+            success: function (data) {
+                uni.showToast({
+                    title: '操作成功',
+                    icon: 'none'
+                })
+            },
+            fail: function (err) {
+                console.log(err.errMsg);
+            }
+        }
+    });
 }
 
 /**
@@ -238,7 +250,7 @@ export const phoneHide = (phone: any) => {
 }
 
 /**
- *修复HTML字符串中图片样式
+ *处理富文本图片溢出
  * @param html - 富文本字符串
  * @returns 
  */