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