You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							583 lines
						
					
					
						
							13 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							583 lines
						
					
					
						
							13 KiB
						
					
					
				| <template> | |
| 	<view class="bg"> | |
| 		<!-- 日期选择区域 --> | |
| 		<view class="date-all-box"> | |
| 			<!-- 月份选择 --> | |
| 			<view class="month-box"> | |
| 				<view @tap="changeMonth(index)" :class="'month-item' + (monthIndex === index ? ' active' : '')" | |
| 					v-for="(item, index) in month" :key="index"> | |
| 					{{ item }}月 | |
| 				</view> | |
| 			</view> | |
|  | |
| 			<!-- 星期表头 --> | |
| 			<view class="day-header"> | |
| 				<view class="day-header-item">日</view> | |
| 				<view class="day-header-item">一</view> | |
| 				<view class="day-header-item">二</view> | |
| 				<view class="day-header-item">三</view> | |
| 				<view class="day-header-item">四</view> | |
| 				<view class="day-header-item">五</view> | |
| 				<view class="day-header-item">六</view> | |
| 			</view> | |
|  | |
| 			<!-- 日期展示 --> | |
| 			<view class="day-box" v-if="selectDate"> | |
| 				<!-- 填充空白 --> | |
| 				<view class="day-item" v-for="(item, index) in currentMonthDays[1]" :key="index"> | |
| 					<view class="date-item-in"> | |
| 						<view class="date-num"></view> | |
| 						<view class="date-price-place"></view> | |
| 					</view> | |
| 				</view> | |
| 				<!-- 显示日期 --> | |
| 				<view | |
| 					:class="'day-item' + (selectDate.selectMonth === month[monthIndex] && selectDate.selectDate === index + 1 ? ' active' : '')" | |
| 					v-for="(item, index) in currentMonthDays[0]" :key="index"> | |
| 					<view class="date-item-in" @tap="selectDateFun(index + 1)"> | |
| 						<view :class=" | |
|                                 'date-num' + (getPriceInfo(month[monthIndex], index + 1) && getPriceInfo(month[monthIndex], index + 1).product_price !== null ? ' active' : '') | |
|                             "> | |
| 							{{ formatDay(index + 1) }} | |
| 						</view> | |
| 						<view class="price" v-if=" | |
|                                 getPriceInfo(month[monthIndex], index + 1) && | |
|                                 getPriceInfo(month[monthIndex], index + 1).product_price !== null && | |
|                                 getPriceInfo(month[monthIndex], index + 1).stock !== null | |
|                             "> | |
| 							¥{{ getPriceInfo(month[monthIndex], index + 1).m_price / 100 }} | |
| 						</view> | |
| 						<view class="date-price-place" | |
| 							v-else-if="getPriceInfo(month[monthIndex], index + 1) && getPriceInfo(month[monthIndex], index + 1).stock === 0"> | |
| 							售罄 | |
| 						</view> | |
| 						<view class="date-price-place" v-else></view> | |
| 					</view> | |
| 				</view> | |
| 			</view> | |
| 		</view> | |
|  | |
| 		<!-- 规格选择区域 --> | |
| 		<view class="box" v-for="(item, index) in sku" :key="index"> | |
| 			<view class="box-top"> | |
| 				<view class="box-title">{{ item.sku_name }}</view> | |
| 				<view class="box-tip text-overflow">{{ item.sku_type_info }}</view> | |
| 				<view :class="'iconfont' + (nums[index] === 0 ? ' disable' : '')" @tap="minus(index)">-</view> | |
| 				<view class="number">{{ nums[index] }}</view> | |
| 				<view :class="'iconfont' + (nums[index] === selectDate.info[index].stock ? ' disable' : '')" | |
| 					@tap="add(index)">+</view> | |
| 			</view> | |
| 
 | |
| 			<view class="single-price" v-if="selectDate">{{ selectDate.info[index].price / 100 }}</view> | |
| 		</view> | |
| 
 | |
| 		<!-- 底部固定栏 --> | |
| 		<view class="fixed-bottom"> | |
| 			<text class="fixed-text">合计:</text> | |
| 			<view class="price">{{ totalPrice() / 100 }}</view> | |
| 			<view class="btn" @tap="order">下一步</view> | |
| 		</view> | |
| 	</view> | |
| </template> | |
| 
 | |
| <script> | |
| 	export default { | |
| 		data() { | |
| 			return { | |
| 				id: '', | |
| 				monthCount: 2, // 显示的月份数量 | |
| 				month: [], | |
| 				monthDays: [], | |
| 				monthIndex: 0, | |
| 				productInfo: null, | |
| 				sku: [], | |
| 				nums: [], | |
| 				selectDate: null, | |
| 				price: 0, | |
| 				prices: {} | |
| 			}; | |
| 		}, | |
| 		onLoad(option) { | |
| 			if (option && option.id) this.id = option.id; | |
| 		}, | |
| 		onShow() { | |
| 			this.getSku(); | |
| 			this.initDate(); | |
| 		}, | |
| 		computed: { | |
| 			// 计算当前月份的天数信息 | |
| 			currentMonthDays() { | |
| 				return this.monthDays[this.monthIndex]; | |
| 			} | |
| 		}, | |
| 		methods: { | |
| 			// 获取产品下的规格 | |
| 			getSku() { | |
| 				this.Post({ | |
| 					id: this.id | |
| 				}, '/api/product/get_product_detail').then(res => { | |
| 					const nums = res.data.sku.map(() => 1); | |
| 					// 排序 | |
| 					this.sortSku(res.data.sku); | |
| 					this.productInfo = res.data; | |
| 					this.sku = res.data.sku; | |
| 					this.nums = nums; | |
| 				}); | |
| 			}, | |
| 			// 初始化日期信息 | |
| 			initDate() { | |
| 				const today = new Date(); | |
| 				const monthInfoList = []; | |
| 
 | |
| 				// 生成monthCount个月份的数据 | |
| 				for (let i = 0; i < this.monthCount; i++) { | |
| 					const month = today.getMonth() + 1 + i; | |
| 					const year = today.getFullYear() + Math.floor((month - 1) / 12); | |
| 					const currentMonth = (month - 1) % 12 + 1; | |
| 					monthInfoList.push({ | |
| 						month: currentMonth, | |
| 						year | |
| 					}); | |
| 				} | |
| 
 | |
| 				this.month = monthInfoList.map(item => item.month); | |
| 				this.monthDays = monthInfoList.map(item => this.getMonthDays(item.month, item.year)); | |
| 
 | |
| 				// 计算日期范围,获取更多月份的价格信息 | |
| 				const startDate = this.formatDate(today); | |
| 				const endYear = monthInfoList[this.monthCount - 1].year; | |
| 				const endMonth = monthInfoList[this.monthCount - 1].month; | |
| 				const endDay = this.monthDays[this.monthCount - 1][0]; | |
| 				const endDate = `${endYear}/${endMonth}/${endDay}`; | |
| 
 | |
| 				this.Post({ | |
| 					product_id: this.id, | |
| 					start_date: startDate, | |
| 					end_date: endDate | |
| 				}, '/api/product/get_product_sku_price_by_date').then(res => { | |
| 					const prices = this.processPriceData(res.data); | |
| 					this.prices = prices; | |
| 					console.log('prices',this.prices) | |
| 					const { | |
| 						selectDate, | |
| 						selectMonth | |
| 					} = this.findFirstAvailableDate(prices); | |
| 					if (!selectDate) { | |
| 						return; | |
| 					} | |
| 					const info = prices[`${selectMonth}-${selectDate}`]; | |
| 					info.selectMonth = selectMonth; | |
| 					info.selectDate = selectDate; | |
| 					this.selectDate = info; | |
| 					this.monthIndex = this.month.indexOf(selectMonth); | |
| 					console.log(111, this.selectDate); | |
| 				}); | |
| 			}, | |
| 			// 获取月份信息 | |
| 			getMonthInfo(today) { | |
| 				const month1 = today.getMonth() + 1; | |
| 				const month2 = (month1 + 1) % 12; | |
| 				const year = today.getFullYear(); | |
| 				const year2 = month1 < month2 ? year : year + 1; | |
| 				return { | |
| 					month1, | |
| 					month2, | |
| 					year, | |
| 					year2 | |
| 				}; | |
| 			}, | |
| 			// 获取这个月有几天 | |
| 			getMonthDays(month, year) { | |
| 				const date = new Date(`${year}/${month}/01`).getDay(); | |
| 				if (month === 2) { | |
| 					if ((year % 100 !== 0 && year % 4 === 0) || year % 400 === 0) { | |
| 						return [29, date]; | |
| 					} else { | |
| 						return [28, date]; | |
| 					} | |
| 				} else if ((month < 8 && month % 2 === 1) || (month >= 8 && month % 2 === 0)) { | |
| 					return [31, date]; | |
| 				} else { | |
| 					return [30, date]; | |
| 				} | |
| 			}, | |
| 			// 格式化日期 | |
| 			formatDate(date) { | |
| 				const year = date.getFullYear(); | |
| 				const month = date.getMonth() + 1 < 10 ? `0${date.getMonth() + 1}` : date.getMonth() + 1; | |
| 				const day = date.getDate(); | |
| 				return [year, month, day].join('-'); | |
| 			}, | |
| 			// 切换月份 | |
| 			changeMonth(index) { | |
| 				this.monthIndex = index; | |
| 			}, | |
| 			// 选择日期 | |
| 			selectDateFun(day) { | |
| 				const selectMonth = this.month[this.monthIndex]; | |
| 				if (!selectMonth) { | |
| 					return; | |
| 				} | |
| 				const info = this.getPriceInfo(selectMonth, day); | |
| 				console.log(info) | |
| 				if (info && info.product_price !== null) { | |
| 					info.selectMonth = selectMonth; | |
| 					info.selectDate = day; | |
| 					this.selectDate = info; | |
| 				} | |
| 				this.$forceUpdate() | |
| 			}, | |
| 			// 减少数量 | |
| 			minus(index) { | |
| 				if (!this.selectDate) { | |
| 					uni.showToast({ | |
| 						title: '请先选择出行日期', | |
| 						icon: 'none' | |
| 					}); | |
| 					return; | |
| 				} | |
| 				if (this.nums[index] === 0) { | |
| 					return; | |
| 				} | |
| 				this.nums[index]--; | |
| 				this.$forceUpdate(); | |
| 			}, | |
| 			// 添加数量 | |
| 			add(index) { | |
| 				if (!this.selectDate) { | |
| 					uni.showToast({ | |
| 						title: '请先选择出行日期', | |
| 						icon: 'none' | |
| 					}); | |
| 					return; | |
| 				} | |
| 				if (this.selectDate.info[index].stock === this.nums[index]) { | |
| 					return; | |
| 				} | |
| 				this.nums[index]++; | |
| 				this.$forceUpdate(); | |
| 			}, | |
| 			// 总价 | |
| 			totalPrice() { | |
| 				if (!this.selectDate) return 0; | |
| 				return this.nums.reduce((total, num, index) => { | |
| 					return total + num * this.selectDate.info[index].price; | |
| 				}, 0); | |
| 			}, | |
| 			// 下一步 | |
| 			order() { | |
| 				if (!this.selectDate) { | |
| 					uni.showToast({ | |
| 						title: '请先选择日期', | |
| 						icon: 'none' | |
| 					}); | |
| 					return; | |
| 				} | |
| 				const allNum = this.nums.reduce((total, num) => total + num, 0); | |
| 				if (allNum === 0) { | |
| 					uni.showToast({ | |
| 						title: '至少选择一个规格', | |
| 						icon: 'none' | |
| 					}); | |
| 					return; | |
| 				} | |
| 				this.sku.forEach((item, index) => { | |
| 					item.num = this.nums[index]; | |
| 					item.price = this.selectDate.info[index].price; | |
| 				}); | |
| 				const data = { | |
| 					product: this.productInfo, | |
| 					sku: this.sku, | |
| 					selectDate: this.selectDate, | |
| 					price: this.totalPrice() | |
| 				}; | |
| 				this.$store.commit('changeLineInfo', data); | |
| 
 | |
| 				uni.navigateTo({ | |
| 					url: '/subPackages/line/orders' | |
| 				}); | |
| 			}, | |
| 			// 规格排序 | |
| 			sortSku(sku) { | |
| 				sku.sort((a, b) => a.id - b.id); | |
| 			}, | |
| 			// 处理价格数据 | |
| 			processPriceData(data) { | |
| 				const prices = {}; | |
| 				data.forEach(item => { | |
| 					this.sortSku(item.info); | |
| 					const stock = item.info.reduce((total, i) => total + i.stock, 0); | |
| 					item.stock = stock; | |
| 					if (item.stock > 0) { | |
| 						const [, ...dateParts] = item.date.split('-'); | |
| 						const newDate = dateParts.map(d => parseInt(d)); | |
| 						const key = newDate.join('-'); | |
| 						prices[key] = item; | |
| 					} | |
| 				}); | |
| 				return prices; | |
| 			}, | |
| 			// 查找第一个可用日期 | |
| 			findFirstAvailableDate(prices) { | |
| 				let selectDate; | |
| 				let selectMonth; | |
| 				for (const key in prices) { | |
| 					if(prices[key].product_price != null) { | |
| 						const [month, day] = key.split('-'); | |
| 						if (!selectDate) { | |
| 							selectDate = parseInt(day); | |
| 							selectMonth = parseInt(month); | |
| 						} | |
| 						 | |
| 						break; | |
| 					} | |
| 					console.log(prices[key]) | |
| 				} | |
| 				return { | |
| 					selectDate, | |
| 					selectMonth | |
| 				}; | |
| 			}, | |
| 			// 获取价格信息 | |
| 			getPriceInfo(month, day) { | |
| 				return this.prices[`${month}-${day}`]; | |
| 			}, | |
| 			// 格式化日期显示 | |
| 			formatDay(day) { | |
| 				return day >= 10 ? day : `0${day}`; | |
| 			} | |
| 		} | |
| 	}; | |
| </script> | |
| 
 | |
| <style scoped lang="scss"> | |
| 	/* 样式部分保持不变 */ | |
| 	.bg { | |
| 		background: #f6f6f6; | |
| 		padding-bottom: 200rpx; | |
| 	} | |
| 
 | |
| 	.date-all-box { | |
| 		margin: 25rpx; | |
| 
 | |
| 		.month-box { | |
| 			padding: 0 20rpx; | |
| 			height: 116rpx; | |
| 			display: flex; | |
| 			border-bottom: 1rpx solid #ccc; | |
| 			align-items: center; | |
| 			overflow-x: auto; | |
| 			 | |
| 			::-webkit-scrollbar { | |
| 				display: none; | |
| 			} | |
| 
 | |
| 			.month-item { | |
| 				margin-right: 70rpx; | |
| 				font-size: 33rpx; | |
| 				color: #000; | |
| 				font-weight: 500; | |
| 				line-height: 116rpx; | |
| 				position: relative; | |
| 			} | |
| 
 | |
| 			.month-item.active::after { | |
| 				content: '1'; | |
| 				display: block; | |
| 				font-size: 0; | |
| 				position: absolute; | |
| 				left: 0; | |
| 				right: 0; | |
| 				height: 8rpx; | |
| 				background: #6A8A27; | |
| 				border-radius: 4rpx; | |
| 				bottom: 0; | |
| 			} | |
| 		} | |
| 
 | |
| 		.day-header { | |
| 			padding-top: 40rpx; | |
| 			line-height: 45rpx; | |
| 			font-size: 29rpx; | |
| 			color: #000; | |
| 			display: flex; | |
| 			align-items: center; | |
| 			flex-wrap: wrap; | |
| 			margin-bottom: 50rpx; | |
| 
 | |
| 			.day-header-item { | |
| 				width: calc(702rpx / 7); | |
| 				text-align: center; | |
| 				flex-shrink: 0; | |
| 			} | |
| 		} | |
| 
 | |
| 		.day-box { | |
| 			display: flex; | |
| 			align-items: center; | |
| 			font-size: 35rpx; | |
| 			flex-wrap: wrap; | |
| 			color: #999; | |
| 
 | |
| 			.day-item { | |
| 				width: calc(702rpx / 7); | |
| 				text-align: center; | |
| 				flex-shrink: 0; | |
| 				display: flex; | |
| 				align-items: center; | |
| 				justify-content: center; | |
| 				margin-bottom: 30rpx; | |
| 
 | |
| 				.date-item-in { | |
| 					width: 87rpx; | |
| 					display: flex; | |
| 					align-items: center; | |
| 					justify-content: center; | |
| 					flex-direction: column; | |
| 					height: 87rpx; | |
| 
 | |
| 					.date-num { | |
| 						line-height: 40rpx; | |
| 					} | |
| 
 | |
| 					.date-num.active { | |
| 						color: #000; | |
| 					} | |
| 
 | |
| 					.price { | |
| 						font-size: 23rpx; | |
| 						color: #F84A56; | |
| 						line-height: 20rpx; | |
| 					} | |
| 
 | |
| 					.price::after { | |
| 						content: '起'; | |
| 						font-size: 17rpx; | |
| 					} | |
| 
 | |
| 					.date-price-place { | |
| 						height: 20rpx; | |
| 					} | |
| 				} | |
| 			} | |
| 
 | |
| 			.day-item.active { | |
| 				.date-item-in { | |
| 					background: #6A8A27; | |
| 					color: #fff; | |
| 					border-radius: 7rpx; | |
| 
 | |
| 					.price { | |
| 						color: #fff; | |
| 					} | |
| 
 | |
| 					.date-num { | |
| 						color: #fff; | |
| 					} | |
| 				} | |
| 			} | |
| 		} | |
| 	} | |
| 
 | |
| 	.box { | |
| 		background: white; | |
| 		margin: 25rpx; | |
| 		background: #ffffff; | |
| 		border-radius: 9rpx; | |
| 		padding: 35rpx 20rpx; | |
| 
 | |
| 		.box-top { | |
| 			display: flex; | |
| 			justify-content: space-between; | |
| 			align-items: center; | |
| 			line-height: 50rpx; | |
| 			font-size: 28rpx; | |
| 			color: #666; | |
| 
 | |
| 			.box-title { | |
| 				font-size: 31rpx; | |
| 				color: #000; | |
| 			} | |
| 
 | |
| 			.box-tip { | |
| 				flex: 1; | |
| 				margin-left: 30rpx; | |
| 			} | |
| 
 | |
| 			.iconfont { | |
| 				color: #000; | |
| 				font-size: 34rpx; | |
| 			} | |
| 
 | |
| 			.iconfont.disable { | |
| 				color: #666; | |
| 			} | |
| 
 | |
| 			.number { | |
| 				width: 67rpx; | |
| 				height: 50rpx; | |
| 				background: #f0f0f0; | |
| 				border-radius: 7rpx; | |
| 				text-align: center; | |
| 				margin: 0 23rpx; | |
| 			} | |
| 		} | |
| 
 | |
| 		.single-price { | |
| 			font-size: 33rpx; | |
| 			color: #F84A56; | |
| 			text-align: right; | |
| 			margin-top: 20rpx; | |
| 		} | |
| 
 | |
| 		.single-price::before { | |
| 			content: '¥'; | |
| 			font-size: 24rpx; | |
| 			margin-right: 4rpx; | |
| 		} | |
| 	} | |
| 
 | |
| 	.fixed-bottom { | |
| 		position: fixed; | |
| 		left: 0; | |
| 		right: 0; | |
| 		bottom: 0; | |
| 		height: 113rpx; | |
| 		background: white; | |
| 		display: flex; | |
| 		justify-content: space-between; | |
| 		align-items: center; | |
| 		padding-left: 25rpx; | |
| 		box-shadow: 0px 0px 16rpx 0px rgba(6, 0, 1, 0.1); | |
| 		z-index: 999; | |
| 
 | |
| 		.fixed-text { | |
| 			font-weight: bold; | |
| 			font-size: 32rpx; | |
| 			color: #000000; | |
| 		} | |
| 
 | |
| 		.price { | |
| 			flex: 1; | |
| 			font-size: 40rpx; | |
| 			color: #DC2525; | |
| 			font-weight: bold; | |
| 		} | |
| 		.price::before { | |
| 			font-size: 24rpx; | |
| 			content: '¥'; | |
| 		} | |
| 
 | |
| 		.btn { | |
| 			width: 233rpx; | |
| 			text-align: center; | |
| 			line-height: 73rpx; | |
| 			background: #6A8A27; | |
| 			border-radius: 11rpx; | |
| 			font-weight: bold; | |
| 			font-size: 32rpx; | |
| 			color: #FFFFFF; | |
| 			margin: 0 26rpx 0 auto; | |
| 		} | |
| 	} | |
| </style> |