| @ -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> | |||