| @ -0,0 +1,144 @@ | |||||
| <template> | |||||
| <view class="card"> | |||||
| <image class="card-bg" :src="data.url" mode="scaleToFill"></image> | |||||
| <view class="flex card-bar"> | |||||
| <view class="flex countdown" v-if="countdown"> | |||||
| 距开始<text class="count">{{ countdown.day }}</text>天 | |||||
| <text class="count">{{ countdown.hour }}</text>:<text class="count">{{ countdown.minute }}</text>:<text class="count">{{ countdown.second }}</text> | |||||
| </view> | |||||
| <button class="flex btn">进入直播间</button> | |||||
| </view> | |||||
| </view> | |||||
| </template> | |||||
| <script> | |||||
| import dayjs from "dayjs"; | |||||
| import isSameOrBefore from 'dayjs/plugin/isSameOrBefore' | |||||
| dayjs.extend(isSameOrBefore); | |||||
| export default { | |||||
| props: { | |||||
| data: { | |||||
| type: Object, | |||||
| default() { | |||||
| return {} | |||||
| } | |||||
| } | |||||
| }, | |||||
| data() { | |||||
| return { | |||||
| timer: null, | |||||
| countdown: null, | |||||
| } | |||||
| }, | |||||
| watch: { | |||||
| data: { | |||||
| handler() { | |||||
| this.updateCountdown() | |||||
| }, | |||||
| immediate: true, | |||||
| deep: true, | |||||
| } | |||||
| }, | |||||
| methods: { | |||||
| updateCountdown() { | |||||
| this.timer && clearTimeout(this.timer) | |||||
| let current = dayjs() | |||||
| let startTime = dayjs(this.data.startTime) | |||||
| if (startTime.isSameOrBefore(current)) { | |||||
| this.countdown = null | |||||
| return | |||||
| } | |||||
| let countdown = { | |||||
| day: 0, | |||||
| hour: 0, | |||||
| minute: 0, | |||||
| second: 0, | |||||
| } | |||||
| let day = Math.floor(startTime.diff(current, 'day', true)) | |||||
| countdown.day = day | |||||
| let hour = Math.floor(startTime.diff(current, 'hour', true)) | |||||
| countdown.hour = hour - day * 24 | |||||
| countdown.hour = countdown.hour < 10 ? `0${countdown.hour}` : countdown.hour | |||||
| let minute = Math.floor(startTime.diff(current, 'minute', true)) | |||||
| countdown.minute = minute - hour * 60 | |||||
| countdown.minute = countdown.minute < 10 ? `0${countdown.minute}` : countdown.minute | |||||
| let second = startTime.diff(current, 'second') | |||||
| countdown.second = second - minute * 60 | |||||
| countdown.second = countdown.second < 10 ? `0${countdown.second}` : countdown.second | |||||
| this.countdown = countdown | |||||
| this.timer = setTimeout(() => { | |||||
| this.updateCountdown() | |||||
| }, 1000) | |||||
| }, | |||||
| }, | |||||
| } | |||||
| </script> | |||||
| <style scoped lang="scss"> | |||||
| .card { | |||||
| position: relative; | |||||
| width: 100%; | |||||
| height: 316rpx; | |||||
| border-radius: 40rpx; | |||||
| overflow: hidden; | |||||
| box-shadow: -5rpx -5rpx 10rpx 0 #FFFFFF, | |||||
| 10rpx 10rpx 20rpx 0 #AAAACC80, | |||||
| 4rpx 4rpx 10rpx 0 #AAAACC40, | |||||
| -2rpx -2rpx 5rpx 0 #FFFFFF; | |||||
| &-bg { | |||||
| width: 100%; | |||||
| height: 100%; | |||||
| } | |||||
| &-bar { | |||||
| justify-content: space-between; | |||||
| position: absolute; | |||||
| left: 0; | |||||
| bottom: 0; | |||||
| width: 100%; | |||||
| padding: 13rpx 32rpx; | |||||
| background: #FFFFFF69; | |||||
| box-sizing: border-box; | |||||
| .countdown { | |||||
| font-family: PingFang SC; | |||||
| font-weight: 400; | |||||
| font-size: 28rpx; | |||||
| line-height: 1.4; | |||||
| color: #252545; | |||||
| .count { | |||||
| margin: 0 8rpx; | |||||
| display: inline-flex; | |||||
| align-items: center; | |||||
| justify-content: center; | |||||
| min-width: 40rpx; | |||||
| height: 40rpx; | |||||
| background: #0000002B; | |||||
| border-radius: 8rpx; | |||||
| } | |||||
| } | |||||
| .btn { | |||||
| font-family: PingFang SC; | |||||
| font-weight: 600; | |||||
| font-size: 24rpx; | |||||
| line-height: 1.5; | |||||
| color: #252545; | |||||
| padding: 7rpx 16rpx; | |||||
| border-radius: 24rpx; | |||||
| background: #FFFFFF; | |||||
| } | |||||
| } | |||||
| } | |||||
| </style> | |||||
| @ -0,0 +1,120 @@ | |||||
| <template> | |||||
| <view> | |||||
| <view class="tabs"> | |||||
| <uv-tabs | |||||
| :list="tabs" | |||||
| :activeStyle="{ | |||||
| 'font-family': 'PingFang SC', | |||||
| 'font-weight': 600, | |||||
| 'font-size': '28rpx', | |||||
| 'line-height': 1.5, | |||||
| 'color': '#FFFFFF', | |||||
| 'background-color': '#252545', | |||||
| 'border-radius': '32rpx', | |||||
| 'padding': '9rpx 40rpx', | |||||
| }" | |||||
| :inactiveStyle="{ | |||||
| 'font-family': 'PingFang SC', | |||||
| 'font-weight': 400, | |||||
| 'font-size': '28rpx', | |||||
| 'line-height': 1.5, | |||||
| 'color': '#252545', | |||||
| 'background-color': '#E5E4EB', | |||||
| 'border-radius': '32rpx', | |||||
| 'padding': '9rpx 40rpx', | |||||
| }" | |||||
| lineWidth="0" | |||||
| lineHeight="0" | |||||
| @change="onChange" | |||||
| ></uv-tabs> | |||||
| </view> | |||||
| <view class="content"> | |||||
| <view v-for="item in list" :key="item.id"> | |||||
| <productCard | |||||
| :data="item" | |||||
| cardStyle="width: 100%; height: 210px;" | |||||
| imgStyle="width: 100%; height: 110px;" | |||||
| ></productCard> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| </template> | |||||
| <script> | |||||
| import productCard from '@/components/product/productCard.vue' | |||||
| export default { | |||||
| components: { | |||||
| productCard, | |||||
| }, | |||||
| data() { | |||||
| return { | |||||
| tabs: [], | |||||
| current: 0, | |||||
| list: [], | |||||
| } | |||||
| }, | |||||
| mounted() { | |||||
| this.tabs = [ | |||||
| { name: '生理' }, | |||||
| { name: '心理' }, | |||||
| ] | |||||
| this.list = [ | |||||
| { | |||||
| id: '001', | |||||
| url: '/pages_order/static/product/course-1.png', | |||||
| productName: '情绪管理课程', | |||||
| sales: 24770, | |||||
| productPriceVal: 688.00, | |||||
| productPriceBef: 1664, | |||||
| }, | |||||
| { | |||||
| id: '002', | |||||
| url: '/pages_order/static/product/course-2.png', | |||||
| productName: '我认知与成长课程', | |||||
| sales: 24770, | |||||
| productPriceVal: 688.00, | |||||
| productPriceBef: 1664, | |||||
| }, | |||||
| { | |||||
| id: '003', | |||||
| url: '/pages_order/static/product/course-3.png', | |||||
| productName: '情绪管理课程', | |||||
| sales: 24770, | |||||
| productPriceVal: 688.00, | |||||
| productPriceBef: 1664, | |||||
| }, | |||||
| { | |||||
| id: '004', | |||||
| url: '/pages_order/static/product/course-4.png', | |||||
| productName: '我认知与成长课程', | |||||
| sales: 24770, | |||||
| productPriceVal: 688.00, | |||||
| productPriceBef: 1664, | |||||
| }, | |||||
| ] | |||||
| }, | |||||
| methods: { | |||||
| onChange(e) { | |||||
| console.log('current', e.index) | |||||
| this.current = e.index | |||||
| // todo | |||||
| }, | |||||
| }, | |||||
| } | |||||
| </script> | |||||
| <style scoped lang="scss"> | |||||
| .tabs { | |||||
| margin: 0 5px; | |||||
| } | |||||
| .content { | |||||
| padding: 16rpx 32rpx 24rpx 32rpx; | |||||
| display: grid; | |||||
| grid-template-columns: repeat(2, 1fr); | |||||
| gap: 32rpx; | |||||
| } | |||||
| </style> | |||||
| @ -0,0 +1,77 @@ | |||||
| <template> | |||||
| <view class="view"> | |||||
| <view v-for="item in list" :key="item.id"> | |||||
| <productCard | |||||
| :data="item" | |||||
| cardStyle="width: 100%; height: 210px;" | |||||
| imgStyle="width: 100%; height: 110px;" | |||||
| ></productCard> | |||||
| </view> | |||||
| </view> | |||||
| </template> | |||||
| <script> | |||||
| import productCard from '@/components/product/productCard.vue' | |||||
| export default { | |||||
| components: { | |||||
| productCard, | |||||
| }, | |||||
| data() { | |||||
| return { | |||||
| list: [], | |||||
| } | |||||
| }, | |||||
| mounted() { | |||||
| this.list = [ | |||||
| { | |||||
| id: '001', | |||||
| url: '/pages_order/static/product/detect-3.png', | |||||
| productName: '腹部超声', | |||||
| sales: 24770, | |||||
| productPriceVal: 688.00, | |||||
| productPriceBef: 1664, | |||||
| }, | |||||
| { | |||||
| id: '002', | |||||
| url: '/pages_order/static/product/detect-4.png', | |||||
| productName: '血常规', | |||||
| sales: 24770, | |||||
| productPriceVal: 688.00, | |||||
| productPriceBef: 1664, | |||||
| }, | |||||
| { | |||||
| id: '003', | |||||
| url: '/pages_order/static/product/detect-3.png', | |||||
| productName: '腹部超声', | |||||
| sales: 24770, | |||||
| productPriceVal: 688.00, | |||||
| productPriceBef: 1664, | |||||
| }, | |||||
| ] | |||||
| }, | |||||
| methods: { | |||||
| onLevel1TabChange(e) { | |||||
| console.log('level1', e.index) | |||||
| this.level1 = e.index | |||||
| this.level2 = this.tabs[this.level1].children?.length ? 0 : null | |||||
| // todo | |||||
| }, | |||||
| onLevel2TabChange(e) { | |||||
| console.log('level2', e.index) | |||||
| this.level2 = e.index | |||||
| // todo | |||||
| }, | |||||
| }, | |||||
| } | |||||
| </script> | |||||
| <style scoped lang="scss"> | |||||
| .view { | |||||
| padding: 0 32rpx 24rpx 32rpx; | |||||
| display: grid; | |||||
| grid-template-columns: repeat(2, 1fr); | |||||
| gap: 32rpx; | |||||
| } | |||||
| </style> | |||||
| @ -0,0 +1,154 @@ | |||||
| <template> | |||||
| <view class="package__view"> | |||||
| <view class="flex package" v-for="packageItem in list" :key="packageItem.id"> | |||||
| <view class="flex flex-column package-info"> | |||||
| <view class="package-info-title">{{ packageItem.title }}</view> | |||||
| <view class="package-info-desc">{{ packageItem.desc }}</view> | |||||
| </view> | |||||
| <view class="package-detail"> | |||||
| <view class="package-detail-item" v-for="item in packageItem.children" :key="item.id"> | |||||
| <view class="package-detail-item-img"> | |||||
| <image class="img" :src="item.url" mode="aspectFill"></image> | |||||
| </view> | |||||
| <view class="package-detail-item-label">{{ item.label }}</view> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| </template> | |||||
| <script> | |||||
| export default { | |||||
| data() { | |||||
| return { | |||||
| list: [], | |||||
| } | |||||
| }, | |||||
| mounted() { | |||||
| this.list = [ | |||||
| { | |||||
| id: '001', | |||||
| title: '儿童体检套餐', | |||||
| desc: '适合3-12岁的儿童', | |||||
| children: [ | |||||
| { id: '0011', label: '腹部超声', url: '/pages_order/static/product/detect-3.png', }, | |||||
| { id: '0012', label: '视力检查', url: '/pages_order/static/product/detect-5.png', }, | |||||
| { id: '0013', label: '骨龄检测', url: '/pages_order/static/product/detect-6.png', }, | |||||
| { id: '0014', label: '生长激素水平检测', url: '/pages_order/static/product/detect-7.png', }, | |||||
| ], | |||||
| }, | |||||
| { | |||||
| id: '002', | |||||
| title: '青少年体检套餐', | |||||
| desc: '适用于13-18岁的青少年', | |||||
| children: [ | |||||
| { id: '0021', label: '身高', url: '/pages_order/static/product/detect-8.png', }, | |||||
| { id: '0022', label: '血常规', url: '/pages_order/static/product/detect-9.png', }, | |||||
| { id: '0023', label: '胸部 X 光', url: '/pages_order/static/product/detect-10.png', }, | |||||
| { id: '0024', label: '心电图检查', url: '/pages_order/static/product/detect-11.png', }, | |||||
| ], | |||||
| }, | |||||
| { | |||||
| id: '003', | |||||
| title: '孕产妇体检套餐', | |||||
| desc: '适用于孕期女性', | |||||
| children: [ | |||||
| { id: '0031', label: '胎儿超声检查', url: '/pages_order/static/product/detect-12.png', }, | |||||
| { id: '0032', label: '唐氏筛查', url: '/pages_order/static/product/detect-13.png', }, | |||||
| { id: '0033', label: '糖筛查试验', url: '/pages_order/static/product/detect-14.png', }, | |||||
| { id: '0034', label: '血压', url: '/pages_order/static/product/detect-15.png', }, | |||||
| ], | |||||
| }, | |||||
| ] | |||||
| }, | |||||
| } | |||||
| </script> | |||||
| <style scoped lang="scss"> | |||||
| .package__view { | |||||
| width: 100%; | |||||
| padding: 0 32rpx; | |||||
| box-sizing: border-box; | |||||
| } | |||||
| .package { | |||||
| width: 100%; | |||||
| padding: 8rpx 8rpx 8rpx 16rpx; | |||||
| box-sizing: border-box; | |||||
| background: #FAFAFF; | |||||
| border: 2rpx solid #FFFFFF; | |||||
| border-radius: 24rpx; | |||||
| & + & { | |||||
| margin-top: 32rpx; | |||||
| } | |||||
| &-info { | |||||
| flex: none; | |||||
| display: inline-flex; | |||||
| align-items: flex-start; | |||||
| width: 200rpx; | |||||
| font-family: PingFang SC; | |||||
| line-height: 1.4; | |||||
| &-title { | |||||
| font-weight: 600; | |||||
| font-size: 28rpx; | |||||
| color: #000000; | |||||
| } | |||||
| &-desc { | |||||
| margin-top: 8rpx; | |||||
| font-weight: 400; | |||||
| font-size: 24rpx; | |||||
| color: #8B8B8B; | |||||
| } | |||||
| } | |||||
| &-detail { | |||||
| flex: 1; | |||||
| white-space: nowrap; | |||||
| overflow-x: auto; | |||||
| padding: 16rpx; | |||||
| background-image: linear-gradient(#FAFAFF, #F3F3F3); | |||||
| border-radius: 16rpx; | |||||
| &-item { | |||||
| $size: 120rpx; | |||||
| & + & { | |||||
| margin-left: 16rpx; | |||||
| } | |||||
| display: inline-block; | |||||
| width: $size; | |||||
| &-img { | |||||
| width: $size; | |||||
| height: $size; | |||||
| border: 2rpx solid #E6E6E6; | |||||
| border-radius: 8rpx; | |||||
| overflow: hidden; | |||||
| .img { | |||||
| width: 100%; | |||||
| height: 100%; | |||||
| } | |||||
| } | |||||
| &-label { | |||||
| margin-top: 8rpx; | |||||
| font-family: PingFang SC; | |||||
| font-weight: 400; | |||||
| font-size: 24rpx; | |||||
| line-height: 1; | |||||
| color: #8B8B8B; | |||||
| width: 100%; | |||||
| text-overflow: ellipsis; | |||||
| white-space: nowrap; | |||||
| overflow: hidden; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| </style> | |||||
| @ -0,0 +1,94 @@ | |||||
| <template> | |||||
| <view style="padding: 0 32rpx;"> | |||||
| <swiper | |||||
| class="swiper" | |||||
| :current="current" | |||||
| :autoplay="false" | |||||
| :display-multiple-items="2.09" | |||||
| @change="onChange" | |||||
| > | |||||
| <swiper-item v-for="item in list" :key="item.id" style="display: inline-block;"> | |||||
| <view class="swiper-item"> | |||||
| <productCard | |||||
| :data="item" | |||||
| cardStyle="width: 100%; height: 192px;" | |||||
| imgStyle="width: 100%; height: 110px;" | |||||
| ></productCard> | |||||
| </view> | |||||
| </swiper-item> | |||||
| <swiper-item style="display: inline-block;"> | |||||
| <view class="swiper-item"></view> | |||||
| </swiper-item> | |||||
| <swiper-item style="display: inline-block;"> | |||||
| <view class="swiper-item"></view> | |||||
| </swiper-item> | |||||
| </swiper> | |||||
| <indicator :current="current" :length="list.length" @click="current = $event"></indicator> | |||||
| </view> | |||||
| </template> | |||||
| <script> | |||||
| import productCard from '@/components/product/productCard.vue' | |||||
| import indicator from '@/components/home/indicator.vue' | |||||
| export default { | |||||
| components: { | |||||
| productCard, | |||||
| indicator, | |||||
| }, | |||||
| data() { | |||||
| return { | |||||
| current: 0, | |||||
| list: [], | |||||
| } | |||||
| }, | |||||
| mounted() { | |||||
| this.list = [ | |||||
| { | |||||
| id: '001', | |||||
| url: '/pages_order/static/product/detect-1.png', | |||||
| productName: '心电图检查', | |||||
| productPriceVal: 688.00, | |||||
| productPriceBef: 1664, | |||||
| }, | |||||
| { | |||||
| id: '002', | |||||
| url: '/pages_order/static/product/detect-2.png', | |||||
| productName: '甲状腺功能检查', | |||||
| productPriceVal: 688.00, | |||||
| productPriceBef: 1664, | |||||
| }, | |||||
| { | |||||
| id: '003', | |||||
| url: '/pages_order/static/product/detect-1.png', | |||||
| productName: '心电图检查', | |||||
| productPriceVal: 688.00, | |||||
| productPriceBef: 1664, | |||||
| }, | |||||
| ] | |||||
| }, | |||||
| methods: { | |||||
| onChange(e) { | |||||
| this.current = e.detail.current | |||||
| } | |||||
| }, | |||||
| } | |||||
| </script> | |||||
| <style scoped lang="scss"> | |||||
| .swiper { | |||||
| width: 100vw; | |||||
| height: 194px; | |||||
| margin-bottom: 24rpx; | |||||
| &-item { | |||||
| width: 100%; | |||||
| height: 460rpx; | |||||
| padding-right: 32rpx; | |||||
| box-sizing: border-box; | |||||
| } | |||||
| } | |||||
| </style> | |||||
| @ -0,0 +1,159 @@ | |||||
| <template> | |||||
| <view> | |||||
| <view class="tabs"> | |||||
| <uv-tabs | |||||
| :list="tabs" | |||||
| :activeStyle="{ | |||||
| 'font-family': 'PingFang SC', | |||||
| 'font-weight': 600, | |||||
| 'font-size': '28rpx', | |||||
| 'line-height': 1.5, | |||||
| 'color': '#FFFFFF', | |||||
| 'background-color': '#252545', | |||||
| 'border-radius': '32rpx', | |||||
| 'padding': '9rpx 40rpx', | |||||
| }" | |||||
| :inactiveStyle="{ | |||||
| 'font-family': 'PingFang SC', | |||||
| 'font-weight': 400, | |||||
| 'font-size': '28rpx', | |||||
| 'line-height': 1.5, | |||||
| 'color': '#252545', | |||||
| 'background-color': '#E5E4EB', | |||||
| 'border-radius': '32rpx', | |||||
| 'padding': '9rpx 40rpx', | |||||
| }" | |||||
| lineWidth="0" | |||||
| lineHeight="0" | |||||
| @change="onLevel1TabChange" | |||||
| ></uv-tabs> | |||||
| <view v-if="tabs[level1] && tabs[level1].children && tabs[level1].children.length" | |||||
| class="tabs-second" | |||||
| > | |||||
| <uv-tabs | |||||
| :list="tabs[level1].children" | |||||
| :activeStyle="{ | |||||
| 'font-family': 'PingFang SC', | |||||
| 'font-weight': 600, | |||||
| 'font-size': '28rpx', | |||||
| 'line-height': 1.5, | |||||
| 'color': '#7451DE', | |||||
| }" | |||||
| :inactiveStyle="{ | |||||
| 'font-family': 'PingFang SC', | |||||
| 'font-weight': 400, | |||||
| 'font-size': '28rpx', | |||||
| 'line-height': 1.5, | |||||
| 'color': '#252545', | |||||
| }" | |||||
| lineWidth="0" | |||||
| lineHeight="0" | |||||
| @change="onLevel2TabChange" | |||||
| ></uv-tabs> | |||||
| </view> | |||||
| </view> | |||||
| <view class="content"> | |||||
| <view v-for="item in list" :key="item.id"> | |||||
| <productCard | |||||
| :data="item" | |||||
| cardStyle="width: 100%; height: 210px;" | |||||
| imgStyle="width: 100%; height: 110px;" | |||||
| ></productCard> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| </template> | |||||
| <script> | |||||
| import productCard from '@/components/product/productCard.vue' | |||||
| export default { | |||||
| components: { | |||||
| productCard, | |||||
| }, | |||||
| data() { | |||||
| return { | |||||
| tabs: [], | |||||
| level1: 0, | |||||
| level2: null, | |||||
| list: [], | |||||
| } | |||||
| }, | |||||
| mounted() { | |||||
| let children = [ | |||||
| { name: '草本类' }, | |||||
| { name: '蔬菜类' }, | |||||
| { name: '维生素类' }, | |||||
| { name: '草本类' }, | |||||
| { name: '蔬菜类' }, | |||||
| ] | |||||
| this.tabs = [ | |||||
| { name: '全部' }, | |||||
| { name: '皮肤', children, }, | |||||
| { name: '身材管理', children, }, | |||||
| { name: '精力', children, }, | |||||
| ] | |||||
| this.list = [ | |||||
| { | |||||
| id: '001', | |||||
| url: '/pages_order/static/index/recommend-pic.png', | |||||
| productName: '月度装定制营养包', | |||||
| sales: 24770, | |||||
| productPriceVal: 688.00, | |||||
| productPriceBef: 1664, | |||||
| }, | |||||
| { | |||||
| id: '002', | |||||
| url: '/pages_order/static/index/recommend-pic.png', | |||||
| productName: '月度装定制营养包', | |||||
| sales: 24770, | |||||
| productPriceVal: 688.00, | |||||
| productPriceBef: 1664, | |||||
| }, | |||||
| { | |||||
| id: '003', | |||||
| url: '/pages_order/static/index/recommend-pic.png', | |||||
| productName: '月度装定制营养包', | |||||
| sales: 24770, | |||||
| productPriceVal: 688.00, | |||||
| productPriceBef: 1664, | |||||
| }, | |||||
| ] | |||||
| }, | |||||
| methods: { | |||||
| onLevel1TabChange(e) { | |||||
| console.log('level1', e.index) | |||||
| this.level1 = e.index | |||||
| this.level2 = this.tabs[this.level1].children?.length ? 0 : null | |||||
| // todo | |||||
| }, | |||||
| onLevel2TabChange(e) { | |||||
| console.log('level2', e.index) | |||||
| this.level2 = e.index | |||||
| // todo | |||||
| }, | |||||
| }, | |||||
| } | |||||
| </script> | |||||
| <style scoped lang="scss"> | |||||
| .tabs { | |||||
| margin: 0 5px; | |||||
| &-second { | |||||
| margin: 0 11px; | |||||
| padding-left: 9px; | |||||
| background: #E5E4EB; | |||||
| border-radius: 16rpx; | |||||
| } | |||||
| } | |||||
| .content { | |||||
| padding: 24rpx 32rpx; | |||||
| display: grid; | |||||
| grid-template-columns: repeat(2, 1fr); | |||||
| gap: 32rpx; | |||||
| } | |||||
| </style> | |||||
| @ -0,0 +1,92 @@ | |||||
| <template> | |||||
| <view> | |||||
| <swiper | |||||
| class="swiper" | |||||
| :current="current" | |||||
| :autoplay="false" | |||||
| :display-multiple-items="1.8" | |||||
| @change="onChange" | |||||
| > | |||||
| <swiper-item v-for="item in list" :key="item.id" style="display: inline-block;"> | |||||
| <view class="swiper-item"> | |||||
| <productCard | |||||
| :data="item" | |||||
| cardStyle="width: 100%; height: 228px;" | |||||
| imgStyle="width: 100%; height: 130px;" | |||||
| ></productCard> | |||||
| </view> | |||||
| </swiper-item> | |||||
| <swiper-item style="display: inline-block;"> | |||||
| <view class="swiper-item"></view> | |||||
| </swiper-item> | |||||
| </swiper> | |||||
| <indicator :current="current" :length="list.length" @click="current = $event"></indicator> | |||||
| </view> | |||||
| </template> | |||||
| <script> | |||||
| import productCard from '@/components/product/productCard.vue' | |||||
| import indicator from '@/components/home/indicator.vue' | |||||
| export default { | |||||
| components: { | |||||
| productCard, | |||||
| indicator, | |||||
| }, | |||||
| data() { | |||||
| return { | |||||
| current: 0, | |||||
| list: [], | |||||
| } | |||||
| }, | |||||
| mounted() { | |||||
| this.list = [ | |||||
| { | |||||
| id: '001', | |||||
| url: '/pages_order/static/index/recommend-pic.png', | |||||
| productName: '月度装定制营养包', | |||||
| sales: 24770, | |||||
| productPriceVal: 688.00, | |||||
| productPriceBef: 1664, | |||||
| }, | |||||
| { | |||||
| id: '002', | |||||
| url: '/pages_order/static/index/recommend-pic.png', | |||||
| productName: '月度装定制营养包', | |||||
| sales: 24770, | |||||
| productPriceVal: 688.00, | |||||
| productPriceBef: 1664, | |||||
| }, | |||||
| { | |||||
| id: '003', | |||||
| url: '/pages_order/static/index/recommend-pic.png', | |||||
| productName: '月度装定制营养包', | |||||
| sales: 24770, | |||||
| productPriceVal: 688.00, | |||||
| productPriceBef: 1664, | |||||
| }, | |||||
| ] | |||||
| }, | |||||
| methods: { | |||||
| onChange(e) { | |||||
| this.current = e.detail.current | |||||
| } | |||||
| }, | |||||
| } | |||||
| </script> | |||||
| <style scoped lang="scss"> | |||||
| .swiper { | |||||
| width: 100vw; | |||||
| height: 230px; | |||||
| margin-bottom: 24rpx; | |||||
| &-item { | |||||
| height: 460rpx; | |||||
| padding-left: 32rpx; | |||||
| } | |||||
| } | |||||
| </style> | |||||
| @ -0,0 +1,136 @@ | |||||
| <template> | |||||
| <view class="card product-card__view" :style="cardStyle"> | |||||
| <view class="card-img flex" :style="imgStyle"> | |||||
| <image class="img" :src="data.url" mode="scaleToFill"></image> | |||||
| </view> | |||||
| <view class="card-detail"> | |||||
| <view class="product-name">{{ data.productName }}</view> | |||||
| <view class="product-sales" v-if="data.sales">{{ `已售出${data.sales}+单` }}</view> | |||||
| <view class="flex product-price"> | |||||
| <view> | |||||
| <view class="product-price-val"> | |||||
| <text>¥</text> | |||||
| <text class="highlight">{{ data.productPriceVal }}</text> | |||||
| <text>/份</text> | |||||
| </view> | |||||
| <view class="product-price-bef"> | |||||
| {{ `¥${data.productPriceBef}/份` }} | |||||
| </view> | |||||
| </view> | |||||
| <button class="btn flex" @click="addToCart(data.id)"> | |||||
| <image class="btn-img" src="@/pages_order/static/report/plus.png" mode="widthFix"></image> | |||||
| </button> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| </template> | |||||
| <script> | |||||
| export default { | |||||
| props: { | |||||
| data: { | |||||
| type: Object, | |||||
| default() { | |||||
| return {} | |||||
| }, | |||||
| }, | |||||
| cardStyle: { | |||||
| type: String, | |||||
| default: '', | |||||
| }, | |||||
| imgStyle: { | |||||
| type: String, | |||||
| default: '', | |||||
| } | |||||
| }, | |||||
| methods: { | |||||
| addToCart(id) { | |||||
| // todo | |||||
| }, | |||||
| }, | |||||
| } | |||||
| </script> | |||||
| <style scoped lang="scss"> | |||||
| .card { | |||||
| font-size: 0; | |||||
| height: 420rpx; | |||||
| background-image: linear-gradient(#FAFAFF, #F3F3F3); | |||||
| border: 2rpx solid #FFFFFF; | |||||
| border-radius: 32rpx; | |||||
| overflow: hidden; | |||||
| &-img { | |||||
| width: 100%; | |||||
| height: 220rpx; | |||||
| .img { | |||||
| width: 100%; | |||||
| height: 100%; | |||||
| } | |||||
| } | |||||
| &-detail { | |||||
| padding: 16rpx 24rpx 0 24rpx; | |||||
| .product { | |||||
| &-name { | |||||
| font-family: PingFang SC; | |||||
| font-weight: 600; | |||||
| font-size: 28rpx; | |||||
| line-height: 1.4; | |||||
| color: #000000; | |||||
| } | |||||
| &-sales { | |||||
| margin-top: 8rpx; | |||||
| font-family: PingFang SC; | |||||
| font-weight: 400; | |||||
| font-size: 24rpx; | |||||
| line-height: 1; | |||||
| color: #8B8B8B; | |||||
| } | |||||
| &-price { | |||||
| margin-top: 16rpx; | |||||
| justify-content: space-between; | |||||
| &-val { | |||||
| font-family: PingFang SC; | |||||
| font-weight: 600; | |||||
| font-size: 24rpx; | |||||
| line-height: 1.4; | |||||
| color: $uni-color; | |||||
| .highlight { | |||||
| font-size: 32rpx; | |||||
| margin: 0 8rpx; | |||||
| } | |||||
| } | |||||
| &-bef { | |||||
| margin-top: 4rpx; | |||||
| text-decoration: line-through; | |||||
| font-family: PingFang SC; | |||||
| font-weight: 400; | |||||
| font-size: 24rpx; | |||||
| line-height: 1; | |||||
| color: #8B8B8B; | |||||
| } | |||||
| .btn { | |||||
| width: 56rpx; | |||||
| height: 56rpx; | |||||
| border-radius: 50%; | |||||
| background: $uni-color; | |||||
| &-img { | |||||
| width: 20rpx; | |||||
| height: 20rpx; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| </style> | |||||
| @ -0,0 +1,56 @@ | |||||
| <template> | |||||
| <view class="header-box" :style="style"> | |||||
| <view class="flex header"> | |||||
| <view class="title">{{ title }}</view> | |||||
| <button class="flex btn" @click="$emit('showAll')"> | |||||
| <text class="btn-text">查看全部</text> | |||||
| <uv-icon name="arrow-right" color="#C6C6C6" size="24rpx"></uv-icon> | |||||
| </button> | |||||
| </view> | |||||
| </view> | |||||
| </template> | |||||
| <script> | |||||
| export default { | |||||
| props: { | |||||
| title: { | |||||
| type: String, | |||||
| default: '', | |||||
| }, | |||||
| style: { | |||||
| type: String, | |||||
| default: '', | |||||
| } | |||||
| }, | |||||
| } | |||||
| </script> | |||||
| <style scoped lang="scss"> | |||||
| .header { | |||||
| &-box { | |||||
| padding: 0 32rpx 24rpx 32rpx; | |||||
| } | |||||
| justify-content: space-between; | |||||
| .title { | |||||
| font-family: PingFang SC; | |||||
| font-size: 36rpx; | |||||
| font-weight: 600; | |||||
| line-height: 1.2; | |||||
| color: #252545; | |||||
| } | |||||
| .btn { | |||||
| font-family: PingFang SC; | |||||
| font-size: 24rpx; | |||||
| font-weight: 400; | |||||
| line-height: 1.4; | |||||
| color: #A8A8A8; | |||||
| &-text { | |||||
| margin-right: 4rpx; | |||||
| } | |||||
| } | |||||
| } | |||||
| </style> | |||||
| @ -0,0 +1,86 @@ | |||||
| .search { | |||||
| padding: 30rpx 32rpx 0 32rpx; | |||||
| /deep/ .uv-search__content__icon { | |||||
| margin-top: 2rpx; | |||||
| } | |||||
| } | |||||
| .intro { | |||||
| position: relative; | |||||
| margin: 38rpx 32rpx 0 32rpx; | |||||
| width: calc(100% - 32rpx * 2); | |||||
| height: 316rpx; | |||||
| background: #E5E5E5; | |||||
| border-radius: 40rpx; | |||||
| box-shadow: -5rpx -5rpx 10rpx 0 #FFFFFF, | |||||
| 10rpx 10rpx 20rpx 0 #AAAACC80, | |||||
| 4rpx 4rpx 10rpx 0 #AAAACC40, | |||||
| -2rpx -2rpx 5rpx 0 #FFFFFF; | |||||
| .bg { | |||||
| float: right; | |||||
| width: 100%; | |||||
| height: 100%; | |||||
| } | |||||
| .content { | |||||
| position: absolute; | |||||
| left: 0; | |||||
| top: 0; | |||||
| width: 100%; | |||||
| height: 100%; | |||||
| padding: 40rpx; | |||||
| box-sizing: border-box; | |||||
| .font1 { | |||||
| font-size: 28rpx; | |||||
| font-weight: 600; | |||||
| line-height: 1.4; | |||||
| font-family: PingFang SC; | |||||
| color: #252545; | |||||
| } | |||||
| .font2 { | |||||
| font-size: 36rpx; | |||||
| font-weight: 600; | |||||
| line-height: 1.4; | |||||
| font-family: PingFang SC; | |||||
| color: transparent; | |||||
| background-image: linear-gradient(to right, #4B348F, #845CFA); | |||||
| background-clip: text; | |||||
| display: inline-block; | |||||
| } | |||||
| .font3 { | |||||
| font-size: 24rpx; | |||||
| font-weight: 400; | |||||
| line-height: 1.4; | |||||
| font-family: PingFang SC; | |||||
| color: #252545; | |||||
| } | |||||
| .btn { | |||||
| margin-top: 56rpx; | |||||
| display: inline-flex; | |||||
| padding: 9rpx 22rpx; | |||||
| font-size: 24rpx; | |||||
| font-weight: 400; | |||||
| font-family: PingFang SC; | |||||
| line-height: 1.4; | |||||
| color: #252545; | |||||
| border-radius: 28rpx; | |||||
| border: 2rpx solid #252545; | |||||
| &-icon { | |||||
| width: 28rpx; | |||||
| height: 28rpx; | |||||
| margin-right: 8rpx; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| .section { | |||||
| margin-top: 48rpx; | |||||
| } | |||||
| @ -0,0 +1,85 @@ | |||||
| <template> | |||||
| <view> | |||||
| <!-- 搜索栏 --> | |||||
| <view class="search"> | |||||
| <uv-search | |||||
| v-model="keyword" | |||||
| placeholder="请输入要查询的内容" | |||||
| placeholderColor="#C6C6C6" | |||||
| searchIconColor="#8B8B8B" | |||||
| :searchIconSize="40" | |||||
| :inputStyle="{ | |||||
| 'font-family': 'PingFang SC', | |||||
| 'font-weight': 400, | |||||
| 'font-size': '28rpx', | |||||
| 'line-height': 1.4, | |||||
| 'padding': '12rpx 0', | |||||
| }" | |||||
| bgColor="#fff" | |||||
| :showAction="false" | |||||
| @search="search" | |||||
| ></uv-search> | |||||
| </view> | |||||
| <view class="section"> | |||||
| <!-- todo --> | |||||
| <sectionHeader :title="`直播 · 05月11日 12:00`" @showAll="jumpToLive"></sectionHeader> | |||||
| <view style="padding: 0 32rpx;"> | |||||
| <courseLiveCard v-for="item in liveList" :key="item.id" :data="item"></courseLiveCard> | |||||
| </view> | |||||
| </view> | |||||
| <view class="section"> | |||||
| <sectionHeader style="padding-bottom: 16rpx;" title="推荐课程" @showAll="jumpToRecommendCourse"></sectionHeader> | |||||
| <courseRecommendView></courseRecommendView> | |||||
| </view> | |||||
| </view> | |||||
| </template> | |||||
| <script> | |||||
| import sectionHeader from './sectionHeader.vue' | |||||
| import courseLiveCard from './courseLiveCard.vue' | |||||
| import courseRecommendView from './courseRecommendView.vue' | |||||
| export default { | |||||
| components: { | |||||
| sectionHeader, | |||||
| courseLiveCard, | |||||
| courseRecommendView, | |||||
| }, | |||||
| data() { | |||||
| return { | |||||
| keyword: '', | |||||
| liveList: [], | |||||
| } | |||||
| }, | |||||
| mounted() { | |||||
| this.liveList = [ | |||||
| { | |||||
| id: '001', | |||||
| url: '/pages_order/static/product/live.png', | |||||
| startTime: '2025-07-25 19:30:00', | |||||
| }, | |||||
| ] | |||||
| }, | |||||
| methods: { | |||||
| // 搜素 | |||||
| search() { | |||||
| // todo | |||||
| uni.navigateTo({ | |||||
| url: '/pages/index/category?search=' + this.keyword | |||||
| }) | |||||
| this.keyword = '' | |||||
| }, | |||||
| jumpToLive() { | |||||
| // todo | |||||
| }, | |||||
| jumpToRecommendCourse() { | |||||
| // todo | |||||
| }, | |||||
| }, | |||||
| } | |||||
| </script> | |||||
| <style scoped lang="scss"> | |||||
| @import './styles/tab.scss'; | |||||
| </style> | |||||
| @ -0,0 +1,95 @@ | |||||
| <template> | |||||
| <view> | |||||
| <!-- 搜索栏 --> | |||||
| <view class="search"> | |||||
| <uv-search | |||||
| v-model="keyword" | |||||
| placeholder="请输入要查询的内容" | |||||
| placeholderColor="#C6C6C6" | |||||
| searchIconColor="#8B8B8B" | |||||
| :searchIconSize="40" | |||||
| :inputStyle="{ | |||||
| 'font-family': 'PingFang SC', | |||||
| 'font-weight': 400, | |||||
| 'font-size': '28rpx', | |||||
| 'line-height': 1.4, | |||||
| 'padding': '12rpx 0', | |||||
| }" | |||||
| bgColor="#fff" | |||||
| :showAction="false" | |||||
| @search="search" | |||||
| ></uv-search> | |||||
| </view> | |||||
| <view class="intro"> | |||||
| <image class="bg" src="@/pages_order/static/product/intro-bg.png" mode="heightFix"></image> | |||||
| <view class="content"> | |||||
| <view class="font1">你是独一无二的</view> | |||||
| <view class="font2">你的健康数据也是</view> | |||||
| <view class="font3">普兆,即精准</view> | |||||
| <button class="flex btn"> | |||||
| <image class="btn-icon" src="@/pages_order/static/index/btn-icon.png" mode="widthFix"></image> | |||||
| <text>定制健康档案</text> | |||||
| </button> | |||||
| </view> | |||||
| </view> | |||||
| <view class="section"> | |||||
| <sectionHeader title="推荐检测" @showAll="jumpToRecommendDetect"></sectionHeader> | |||||
| <detectRecommendSwiper></detectRecommendSwiper> | |||||
| </view> | |||||
| <view class="section"> | |||||
| <sectionHeader title="个性化检测包" @showAll="jumpToPersonalDetect"></sectionHeader> | |||||
| <detectPackageViewVue></detectPackageViewVue> | |||||
| </view> | |||||
| <view class="section"> | |||||
| <sectionHeader title="自选检测" @showAll="jumpToCustomDetect"></sectionHeader> | |||||
| <detectCustomView></detectCustomView> | |||||
| </view> | |||||
| </view> | |||||
| </template> | |||||
| <script> | |||||
| import sectionHeader from './sectionHeader.vue' | |||||
| import detectRecommendSwiper from './detectRecommendSwiper.vue' | |||||
| import detectPackageViewVue from './detectPackageView.vue' | |||||
| import detectCustomView from './detectCustomView.vue' | |||||
| export default { | |||||
| components: { | |||||
| sectionHeader, | |||||
| detectRecommendSwiper, | |||||
| detectPackageViewVue, | |||||
| detectCustomView, | |||||
| }, | |||||
| data() { | |||||
| return { | |||||
| keyword: '', | |||||
| } | |||||
| }, | |||||
| methods: { | |||||
| // 搜素 | |||||
| search() { | |||||
| // todo | |||||
| uni.navigateTo({ | |||||
| url: '/pages/index/category?search=' + this.keyword | |||||
| }) | |||||
| this.keyword = '' | |||||
| }, | |||||
| jumpToRecommendDetect() { | |||||
| // todo | |||||
| }, | |||||
| jumpToPersonalDetect() { | |||||
| // todo | |||||
| }, | |||||
| jumpToCustomDetect() { | |||||
| // todo | |||||
| }, | |||||
| }, | |||||
| } | |||||
| </script> | |||||
| <style scoped lang="scss"> | |||||
| @import './styles/tab.scss'; | |||||
| </style> | |||||
| @ -0,0 +1,89 @@ | |||||
| <template> | |||||
| <view> | |||||
| <!-- 搜索栏 --> | |||||
| <view class="search"> | |||||
| <uv-search | |||||
| v-model="keyword" | |||||
| placeholder="请输入要查询的内容" | |||||
| placeholderColor="#C6C6C6" | |||||
| searchIconColor="#8B8B8B" | |||||
| :searchIconSize="40" | |||||
| :inputStyle="{ | |||||
| 'font-family': 'PingFang SC', | |||||
| 'font-weight': 400, | |||||
| 'font-size': '28rpx', | |||||
| 'line-height': 1.4, | |||||
| 'padding': '12rpx 0', | |||||
| }" | |||||
| bgColor="#fff" | |||||
| :showAction="false" | |||||
| @search="search" | |||||
| ></uv-search> | |||||
| </view> | |||||
| <view class="intro"> | |||||
| <image class="bg" src="@/pages_order/static/product/intro-bg.png" mode="heightFix"></image> | |||||
| <view class="content"> | |||||
| <view class="font1">你是独一无二的</view> | |||||
| <view class="font2">你的健康数据也是</view> | |||||
| <view class="font3">普兆,即精准</view> | |||||
| <button class="flex btn"> | |||||
| <image class="btn-icon" src="@/pages_order/static/index/btn-icon.png" mode="widthFix"></image> | |||||
| <text>定制健康档案</text> | |||||
| </button> | |||||
| </view> | |||||
| </view> | |||||
| <view class="section"> | |||||
| <sectionHeader title="推荐产品" @showAll="jumpToRecommendNutrient"></sectionHeader> | |||||
| <nutrientRecommendSwiper></nutrientRecommendSwiper> | |||||
| </view> | |||||
| <view class="section section-custom"> | |||||
| <sectionHeader style="padding-bottom: 16rpx;" title="自选补剂" @showAll="jumpToCustomNutrient"></sectionHeader> | |||||
| <nutrientCustomView></nutrientCustomView> | |||||
| </view> | |||||
| </view> | |||||
| </template> | |||||
| <script> | |||||
| import sectionHeader from './sectionHeader.vue' | |||||
| import nutrientRecommendSwiper from './nutrientRecommendSwiper.vue' | |||||
| import nutrientCustomView from './nutrientCustomView.vue' | |||||
| export default { | |||||
| components: { | |||||
| sectionHeader, | |||||
| nutrientRecommendSwiper, | |||||
| nutrientCustomView, | |||||
| }, | |||||
| data() { | |||||
| return { | |||||
| keyword: '', | |||||
| } | |||||
| }, | |||||
| mounted() { | |||||
| }, | |||||
| methods: { | |||||
| // 搜素 | |||||
| search() { | |||||
| // todo | |||||
| uni.navigateTo({ | |||||
| url: '/pages/index/category?search=' + this.keyword | |||||
| }) | |||||
| this.keyword = '' | |||||
| }, | |||||
| jumpToRecommendNutrient() { | |||||
| // todo | |||||
| }, | |||||
| jumpToCustomNutrient() { | |||||
| // todo | |||||
| }, | |||||
| }, | |||||
| } | |||||
| </script> | |||||
| <style scoped lang="scss"> | |||||
| @import './styles/tab.scss'; | |||||
| </style> | |||||
| @ -0,0 +1,89 @@ | |||||
| <template> | |||||
| <view class="page__view"> | |||||
| <navbar bgColor="#FFFFFF" > | |||||
| <view> | |||||
| <uv-tabs | |||||
| :current="current" | |||||
| :list="tabs" | |||||
| :activeStyle="{ | |||||
| 'font-family': 'PingFang SC', | |||||
| 'font-weight': 600, | |||||
| 'font-size': '40rpx', | |||||
| 'line-height': 1.2, | |||||
| 'color': '#252545', | |||||
| }" | |||||
| :inactiveStyle="{ | |||||
| 'font-family': 'PingFang SC', | |||||
| 'font-weight': 400, | |||||
| 'font-size': '32rpx', | |||||
| 'line-height': 1.5, | |||||
| 'color': '#A8A8A8', | |||||
| }" | |||||
| lineWidth="22rpx" | |||||
| lineHeight="4rpx" | |||||
| lineColor="#252545" | |||||
| @change="onTabChange" | |||||
| ></uv-tabs> | |||||
| </view> | |||||
| </navbar> | |||||
| <!-- 营养素 --> | |||||
| <tabNutrient v-if="current == 0"></tabNutrient> | |||||
| <!-- 检测 --> | |||||
| <tabDetect v-else-if="current == 1"></tabDetect> | |||||
| <!-- 课程 --> | |||||
| <tabCourse v-else-if="current == 2"></tabCourse> | |||||
| <tabber select="product" /> | |||||
| </view> | |||||
| </template> | |||||
| <script> | |||||
| import tabber from '@/components/base/tabbar.vue' | |||||
| import tabNutrient from '@/components/product/tabNutrient.vue' | |||||
| import tabDetect from '@/components/product/tabDetect.vue' | |||||
| import tabCourse from '@/components/product/tabCourse.vue' | |||||
| export default { | |||||
| components: { | |||||
| tabNutrient, | |||||
| tabDetect, | |||||
| tabCourse, | |||||
| tabber, | |||||
| }, | |||||
| data() { | |||||
| return { | |||||
| tabs: [ | |||||
| { name: '营养素' }, | |||||
| { name: '检测' }, | |||||
| { name: '课程' }, | |||||
| ], | |||||
| current: 0, | |||||
| } | |||||
| }, | |||||
| methods: { | |||||
| onTabChange(e) { | |||||
| console.log('current', e.index) | |||||
| this.current = e.index | |||||
| // todo | |||||
| }, | |||||
| }, | |||||
| } | |||||
| </script> | |||||
| <style scoped lang="scss"> | |||||
| .page__view { | |||||
| width: 100vw; | |||||
| min-height: 100vh; | |||||
| background-image: linear-gradient(#EAE5FF, #F3F2F7, #F3F2F7); | |||||
| position: relative; | |||||
| /deep/ .uv-tabs__wrapper__nav__line { | |||||
| border-radius: 2rpx; | |||||
| } | |||||
| } | |||||
| </style> | |||||