14 changed files with 1050 additions and 20 deletions
@ -1,8 +1,21 @@ |
|||
<template> |
|||
<view class="bg"> |
|||
|
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
data() { |
|||
return { |
|||
|
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style> |
|||
<style lang="scss" scoped> |
|||
.bg { |
|||
min-height: 100vh; |
|||
} |
|||
</style> |
@ -1,5 +1,134 @@ |
|||
<template> |
|||
<view class="bg"> |
|||
<view class="item" v-for="(item,index) in list" :key="index" @click="gotoDetailByType(item)"> |
|||
<image :src="showImg(item.headimg)" mode="aspectFill "></image> |
|||
<view class="content flex-column"> |
|||
<view> |
|||
|
|||
<view class="title">{{item.title}}</view> |
|||
<view class="tags" v-if="item.display_tags"> |
|||
<view class="tag" v-for="(tagItem,tagIndex) in item.display_tags.split(',').slice(0,2)" :key="tagIndex"> |
|||
{{tagItem}} |
|||
</view> |
|||
</view> |
|||
</view> |
|||
<view class="item-bottom flex-between"> |
|||
<view class="price">{{item.price / 100}}</view> |
|||
<view class="btn">预订</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
data() { |
|||
return { |
|||
list: [], |
|||
finished: false |
|||
} |
|||
}, |
|||
onReady() { |
|||
this.getList() |
|||
}, |
|||
onReachBottom() { |
|||
setTimeout(() => { |
|||
if (!this.finished) this.getList() |
|||
},1000) |
|||
}, |
|||
methods: { |
|||
getList() { |
|||
this.Post({ |
|||
offset: this.list.length, |
|||
limit: 10, |
|||
type_id: 23, |
|||
tag_id: 17, |
|||
sort: 'weight' |
|||
},'/api/product/get_product_by_tag').then(res => { |
|||
this.list = [...this.list, ...res.data.list] |
|||
|
|||
if (res.data.list.length < 10) { |
|||
this.finished = true |
|||
} |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
.bg { |
|||
min-height: 100vh; |
|||
background-color: rgba(249, 252, 243, 1); |
|||
padding-bottom: 100rpx; |
|||
} |
|||
|
|||
.item { |
|||
margin: 30rpx 26rpx; |
|||
display: flex; |
|||
|
|||
image { |
|||
width: 241rpx; |
|||
height: 295rpx; |
|||
border-radius: 20rpx; |
|||
margin-right: 20rpx; |
|||
flex-shrink: 0; |
|||
} |
|||
|
|||
.content { |
|||
height: 295rpx; |
|||
padding-top: 12rpx; |
|||
justify-content: space-between; |
|||
flex: 1; |
|||
|
|||
.title { |
|||
font-weight: bold; |
|||
font-size: 31rpx; |
|||
color: #333333; |
|||
} |
|||
|
|||
.tags { |
|||
display: flex; |
|||
margin-top: 23rpx; |
|||
|
|||
.tag { |
|||
font-size: 24rpx; |
|||
color: #6A8A27; |
|||
margin-right: 11rpx; |
|||
} |
|||
.tag:not(:last-child)::after{ |
|||
content: '|'; |
|||
display: inline-block; |
|||
margin-left: 11rpx; |
|||
} |
|||
} |
|||
|
|||
.item-bottom { |
|||
.price { |
|||
font-size: 34.67rpx; |
|||
color: rgba(220, 37, 37, 1); |
|||
} |
|||
.price::before { |
|||
font-size: 22.67rpx; |
|||
content: '¥'; |
|||
} |
|||
.price::after { |
|||
font-size: 22.67rpx; |
|||
content: '起'; |
|||
color: rgba(153, 153, 153, 1); |
|||
} |
|||
|
|||
.btn { |
|||
width: 133rpx; |
|||
line-height: 53rpx; |
|||
background: #6A8A27; |
|||
border-radius: 12rpx; |
|||
text-align: center; |
|||
font-weight: 500; |
|||
font-size: 31rpx; |
|||
color: #FFFFFF; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,278 @@ |
|||
<template> |
|||
<view class="bg" v-if="detail"> |
|||
<swiper class="top-banner" :circular="true" :interval="6000" :duration="800" :indicator-dots="true" |
|||
:autoplay="true" indicator-active-color="#fff"> |
|||
<swiper-item v-for="(item, index) in detail.listimg" :key="index"> |
|||
<image class="top-banner" :src="showImg(item)" mode="aspectFill" lazy-load="true"></image> |
|||
</swiper-item> |
|||
</swiper> |
|||
|
|||
<view class="top-box"> |
|||
<view class="price">{{detail.price / 100}}</view> |
|||
<view class="title">{{detail.title}}</view> |
|||
<view class="subtitle">{{detail.subtitle}}</view> |
|||
<view class="tags" v-if="detail.display_tags"> |
|||
<view class="tag" v-for="(item,index) in detail.display_tags.split(',').slice(0,3)" :key="index"> |
|||
{{item}} |
|||
</view> |
|||
</view> |
|||
</view> |
|||
|
|||
<view class="scroll-all-box" id="menus"> |
|||
<view :class="'scroll-menus' + (fixed ? ' fixed-menus' : '')"> |
|||
<view :class="'scroll-menu-item' + (type == 1 ? ' active' : '')" @click="changeMenu(1)">产品详情</view> |
|||
<view :class="'scroll-menu-item' + (type == 2 ? ' active' : '')" @click="changeMenu(2)">预定须知</view> |
|||
<view :class="'scroll-menu-item' + (type == 3 ? ' active' : '')" @click="changeMenu(3)">退改说明</view> |
|||
<view :class="'scroll-menu-item' + (type == 4 ? ' active' : '')" @click="changeMenu(4)">费用说明</view> |
|||
</view> |
|||
<view style="height: 85rpx" v-if="fixed"></view> |
|||
<view class="info-box" id="box1"> |
|||
<view class="info-title">产品详情</view> |
|||
<view class="info-content" v-html="formateRichText(detail.content)"></view> |
|||
</view> |
|||
<view class="info-box" id="box2"> |
|||
<view class="info-title">预定须知</view> |
|||
<view class="info-content" v-html="formateRichText(detail.book_info)"></view> |
|||
</view> |
|||
<view class="info-box" id="box3"> |
|||
<view class="info-title">退改说明</view> |
|||
<view class="info-content" v-html="formateRichText(detail.cancel_info)"></view> |
|||
</view> |
|||
<view class="info-box" id="box4"> |
|||
<view class="info-title">费用说明</view> |
|||
<view class="info-content" v-html="formateRichText(detail.expense_info)"></view> |
|||
</view> |
|||
</view> |
|||
|
|||
<view class="btn-box flex-center"> |
|||
<view @click="order">立即购买</view> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
const device = uni.getSystemInfoSync(); |
|||
const ratio = device.windowWidth / 750; |
|||
export default { |
|||
data() { |
|||
return { |
|||
id: '', |
|||
detail: {}, |
|||
top: 0, |
|||
fixed: false, |
|||
type: 0, |
|||
down: false, |
|||
} |
|||
}, |
|||
onLoad(option) { |
|||
if (option && option.id) this.id = option.id |
|||
this.getDetail() |
|||
let rect = uni.getMenuButtonBoundingClientRect(); |
|||
this.top = (rect.top - device.statusBarHeight) * 2 + rect.height + device.statusBarHeight; |
|||
}, |
|||
onPageScroll(e){ |
|||
let query = uni.createSelectorQuery() |
|||
query.select("#menus").boundingClientRect(res => { |
|||
if(res.top < 0){ |
|||
this.fixed = true |
|||
}else{ |
|||
this.fixed = false |
|||
} |
|||
}).exec() |
|||
|
|||
if (this.down) { |
|||
return |
|||
}else{ |
|||
this.down = true |
|||
for(let i = 1; i < 4; i++) { |
|||
query.select("#box" + i).boundingClientRect(res => { |
|||
if(res.top < 0) { |
|||
this.type = i |
|||
} |
|||
}).exec() |
|||
} |
|||
this.down = false |
|||
} |
|||
}, |
|||
methods: { |
|||
getDetail() { |
|||
this.Post({ |
|||
id: this.id |
|||
}, '/api/product/get_product_detail').then(res => { |
|||
this.detail = res.data |
|||
}) |
|||
}, |
|||
changeMenu(e) { |
|||
this.down = true |
|||
let index = e; |
|||
let that = this |
|||
const query = uni.createSelectorQuery(); //创建节点查询器 |
|||
query.select('#box' + index).boundingClientRect(); //选择toViewid获取位置信息 |
|||
query.selectViewport().scrollOffset(); //获取页面查询位置的 |
|||
query.exec(function (res) { |
|||
let scrollTop = res[0].top + res[1].scrollTop - 110 * ratio - that.top; |
|||
uni.pageScrollTo({ |
|||
scrollTop: scrollTop + 4, |
|||
duration: 0 |
|||
}); |
|||
that.type = index |
|||
setTimeout(()=>{ |
|||
that.down = false |
|||
},1000) |
|||
}); |
|||
}, |
|||
// 去下单 |
|||
order() { |
|||
uni.navigateTo({ |
|||
url: "/subPackages/line/order?id=" + this.id |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
.bg { |
|||
min-height: 100vh; |
|||
background: #F7F7F7; |
|||
padding-bottom: 200rpx; |
|||
} |
|||
|
|||
.top-banner { |
|||
width: 750rpx; |
|||
height: 413rpx; |
|||
} |
|||
|
|||
.top-box { |
|||
background: #FFFFFF; |
|||
padding: 26rpx; |
|||
|
|||
.price { |
|||
font-weight: bold; |
|||
font-size: 36rpx; |
|||
color: #DC2525; |
|||
} |
|||
|
|||
.price::before { |
|||
content: '¥'; |
|||
font-size: 23rpx; |
|||
} |
|||
|
|||
.price::after { |
|||
content: '/人'; |
|||
font-size: 23rpx; |
|||
} |
|||
|
|||
.title { |
|||
margin-top: 20rpx; |
|||
font-weight: bold; |
|||
font-size: 31rpx; |
|||
color: #333333; |
|||
} |
|||
|
|||
.subtitle { |
|||
margin-top: 20rpx; |
|||
font-weight: 500; |
|||
font-size: 24rpx; |
|||
color: #888888; |
|||
} |
|||
|
|||
.tags { |
|||
margin-top: 26rpx; |
|||
display: flex; |
|||
|
|||
.tag { |
|||
margin-right: 13rpx; |
|||
line-height: 37rpx; |
|||
border-radius: 7rpx; |
|||
border: 1px solid #6A8A27; |
|||
padding: 0 10rpx; |
|||
font-size: 24rpx; |
|||
color: #6A8A27; |
|||
} |
|||
} |
|||
} |
|||
|
|||
.scroll-all-box { |
|||
margin: 20rpx 0; |
|||
background-color: #fff; |
|||
|
|||
.scroll-menus { |
|||
padding: 0 40rpx; |
|||
display: flex; |
|||
justify-content: space-between; |
|||
align-items: center; |
|||
font-size: 29rpx; |
|||
color: #333; |
|||
height: 84rpx; |
|||
border-bottom: 1rpx solid #d9d9d9; |
|||
|
|||
.scroll-menu-item { |
|||
position: relative; |
|||
line-height: 84rpx; |
|||
} |
|||
|
|||
.scroll-menu-item.active::after { |
|||
content: '1'; |
|||
font-size: 0; |
|||
display: block; |
|||
position: absolute; |
|||
width: 46rpx; |
|||
height: 6rpx; |
|||
border-radius: 3rpx; |
|||
background: #6A8A27; |
|||
left: 50%; |
|||
margin-left: -23rpx; |
|||
bottom: 0rpx; |
|||
} |
|||
} |
|||
|
|||
.fixed-menus { |
|||
position: fixed; |
|||
top: 0; |
|||
left: 0; |
|||
right: 0; |
|||
background: white; |
|||
z-index: 1; |
|||
} |
|||
|
|||
.info-box { |
|||
padding: 20rpx 40rpx; |
|||
|
|||
.info-title { |
|||
font-size: 35rpx; |
|||
font-weight: bold; |
|||
color: #000; |
|||
} |
|||
|
|||
.info-content { |
|||
width: 697rpx; |
|||
background: #FFFFFF; |
|||
border-radius: 20rpx; |
|||
padding: 22rpx 14rpx; |
|||
margin-top: 20rpx; |
|||
} |
|||
} |
|||
} |
|||
|
|||
.btn-box { |
|||
width: 750rpx; |
|||
height: 153rpx; |
|||
background: #FFFFFF; |
|||
box-shadow: 0rpx 0rpx 13rpx 0rpx rgba(82,82,82,0.25); |
|||
position: fixed; |
|||
left: 0; |
|||
bottom: 0; |
|||
|
|||
view { |
|||
width: 697rpx; |
|||
line-height: 73rpx; |
|||
text-align: center; |
|||
background: #6A8A27; |
|||
border-radius: 11rpx; |
|||
font-weight: bold; |
|||
font-size: 32rpx; |
|||
color: #FFFFFF; |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,579 @@ |
|||
<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> |
|||
<navigator url="/pages/user/service/index" class="kefu-box"> |
|||
<view class="iconfont icon-kefu"></view> |
|||
<view>客服</view> |
|||
</navigator> |
|||
<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; |
|||
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); |
|||
if (info && info.product_price && info.product_price !== null && info.stock !== 0) { |
|||
info.selectMonth = selectMonth; |
|||
info.selectDate = day; |
|||
this.selectDate = info; |
|||
} |
|||
}, |
|||
// 减少数量 |
|||
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({}); |
|||
}, |
|||
// 规格排序 |
|||
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) { |
|||
const [month, day] = key.split('-'); |
|||
if (!selectDate) { |
|||
selectDate = parseInt(day); |
|||
selectMonth = parseInt(month); |
|||
} |
|||
} |
|||
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: #d62828; |
|||
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: #d62828; |
|||
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 { |
|||
flex-shrink: 0; |
|||
font-size: 29rpx; |
|||
} |
|||
|
|||
.price { |
|||
flex: 1; |
|||
font-size: 36rpx; |
|||
color: #d62828; |
|||
font-weight: 500; |
|||
} |
|||
|
|||
.kefu-box { |
|||
flex-shrink: 0; |
|||
text-align: center; |
|||
font-size: 23rpx; |
|||
color: #666; |
|||
width: 100rpx; |
|||
} |
|||
|
|||
.btn { |
|||
width: 267rpx; |
|||
text-align: center; |
|||
line-height: 113rpx; |
|||
background: #d62828; |
|||
color: #fff; |
|||
font-size: 36rpx; |
|||
font-weight: 500; |
|||
margin-left: 30rpx; |
|||
} |
|||
} |
|||
</style> |
Loading…
Reference in new issue