Browse Source

feat: page-cart;

pull/1/head
Fox-33 2 months ago
parent
commit
028f6cb746
27 changed files with 2143 additions and 276 deletions
  1. +8
    -0
      components/base/tabbar.vue
  2. +236
    -0
      components/cart/productCard.vue
  3. +12
    -12
      components/product/courseRecommendView.vue
  4. +9
    -9
      components/product/detectCustomView.vue
  5. +9
    -9
      components/product/detectRecommendSwiper.vue
  6. +9
    -9
      components/product/nutrientCustomView.vue
  7. +9
    -9
      components/product/nutrientRecommendSwiper.vue
  8. +7
    -4
      components/product/productCard.vue
  9. +6
    -6
      components/report/recommendTest.vue
  10. +6
    -0
      pages.json
  11. +260
    -0
      pages/index/cart copy.vue
  12. +454
    -212
      pages/index/cart.vue
  13. +137
    -0
      pages_order/comment/commentCard.vue
  14. +196
    -0
      pages_order/comment/commentRecords.vue
  15. +2
    -2
      pages_order/components/reportCard.vue
  16. +98
    -0
      pages_order/product/agreementPopup.vue
  17. +232
    -0
      pages_order/product/countSelectPopup.vue
  18. +444
    -0
      pages_order/product/productDetail.vue
  19. +1
    -1
      pages_order/report/detail/index.vue
  20. +1
    -1
      pages_order/report/nutritionProgram/index.vue
  21. +1
    -1
      pages_order/report/nutritionProgram/productCard.vue
  22. +1
    -1
      pages_order/report/result/index.vue
  23. BIN
      pages_order/static/cart/cart-icon.png
  24. BIN
      pages_order/static/product/comment.png
  25. BIN
      pages_order/static/product/product-detail.png
  26. +0
    -0
      static/image/tabbar/cart-active.png
  27. +5
    -0
      store/store.js

+ 8
- 0
components/base/tabbar.vue View File

@ -48,6 +48,13 @@
"title": "产品",
key: 'product',
},
{
"selectedIconPath": "/static/image/tabbar/cart-active.png",
"iconPath": "/static/image/tabbar/cart.png",
"pagePath": "/pages/index/cart",
"title": "购物车",
key: 'cart',
},
{
"selectedIconPath": "/static/image/tabbar/user-center-active.png",
"iconPath": "/static/image/tabbar/user-center.png",
@ -90,6 +97,7 @@
bottom: 0;
left: 0;
color: #BCBCBC;
border-top: 2rpx solid #F1F1F1;
.tabbar-item {
flex: 1;


+ 236
- 0
components/cart/productCard.vue View File

@ -0,0 +1,236 @@
<template>
<view class="flex card">
<view>
<uv-checkbox-group
v-model="checkboxValue"
shape="circle"
@change="onCheckChange"
>
<uv-checkbox
size="36rpx"
icon-size="36rpx"
activeColor="#7451DE"
:name="1"
></uv-checkbox>
</uv-checkbox-group>
</view>
<view class="flex right" @click="jumpToProductDetail">
<view class="img-box">
<image class="img" :src="data.url" mode="aspectFit"></image>
</view>
<view class="info">
<view class="title">{{ data.name }}</view>
<view class="desc">{{ data.desc }}</view>
<view class="flex price-box">
<view class="flex price">¥<text class="highlight">{{ data.price.toFixed(2) }}</text></view>
</view>
<view class="flex tool">
<view class="flex count">
规格<text class="highlight">{{ data.countDesc || data.count }}</text>
<uv-icon name="arrow-down" color="#7451DE" size="24rpx" :bold="true"></uv-icon>
</view>
<button class="flex btn" @click.stop="openPicker">编辑</button>
</view>
</view>
</view>
<view v-if="data.customized" class="sup customized">
定制组合
</view>
<view v-else-if="data.free" class="sup free">
自定组合
</view>
<uv-picker ref="picker" :columns="[data.options]" keyName="label" confirmColor="#7451DE" @confirm="onChange"></uv-picker>
</view>
</template>
<script>
export default {
props: {
data: {
type: Object,
default() {
return {}
}
},
mode: {
type: String,
default: 'read'
},
},
data() {
return {
checkboxValue : [],
}
},
computed: {
checked: {
set(val) {
this.checkboxValue = val ? [1] : []
if (this.data.selected == val) {
return
}
this.$emit('select', val)
},
get() {
return this.checkboxValue[0] == 1 ? true : false
}
}
},
watch: {
data: {
handler(val) {
this.checked = val.selected
},
immediate: true,
deep: true,
}
},
methods: {
onCheckChange(arr) {
this.checked = arr[0] == 1 ? true : false
},
openPicker() {
console.log(this.data.id, 'openPicker')
this.$refs.picker.open();
},
onChange(e) {
const target = e.value[0]
console.log('onChange', target)
this.$emit('change', { price: target.value, count: target.count, countDesc: target.label })
},
jumpToProductDetail() {
console.log(this.data.id, 'jumpToProductDetail')
this.$utils.navigateTo(`/pages_order/product/productDetail?id=${this.data.id}`)
},
},
}
</script>
<style scoped lang="scss">
.card {
position: relative;
height: 240rpx;
padding: 0 32rpx;
background-image: linear-gradient(#FAFAFF, #F3F3F3);
border: 2rpx solid #FFFFFF;
border-radius: 32rpx;
box-sizing: border-box;
column-gap: 24rpx;
overflow: hidden;
/deep/ .uv-checkbox__label-wra {
padding: 0;
}
}
.right {
flex: 1;
column-gap: 24rpx;
}
.img {
&-box {
width: 144rpx;
height: 144rpx;
border-radius: 16rpx;
overflow: hidden;
}
width: 100%;
height: 100%;
}
.info {
flex: 1;
font-family: PingFang SC;
font-weight: 400;
line-height: 1.4;
font-size: 26rpx;
color: #8B8B8B;
.title {
font-weight: 600;
font-size: 28rpx;
color: #000000;
}
.desc {
margin-top: 8rpx;
line-height: 1.5;
}
.price {
&-box {
margin-top: 8rpx;
justify-content: flex-start;
column-gap: 20rpx;
}
font-weight: 600;
font-size: 24rpx;
color: #7451DE;
.highlight {
margin: 0 8rpx;
font-size: 32rpx;
}
&-origin {
font-size: 28rpx;
line-height: 1;
text-decoration: line-through;
}
}
.tool {
margin-top: 8rpx;
justify-content: space-between;
.count {
.highlight {
margin: 0 8rpx;
color: #252545;
}
}
.btn {
padding: 8rpx 40rpx;
font-family: PingFang SC;
font-weight: 600;
font-size: 28rpx;
line-height: 1.5;
color: #FFFFFF;
background: #7451DE;
border-radius: 30rpx;
}
}
}
.sup {
position: absolute;
top: 28rpx;
right: -60rpx;
padding: 5rpx 52rpx;
font-family: PingFang SC;
font-weight: 400;
font-size: 28rpx;
line-height: 1.5;
white-space: nowrap;
transform: rotate(45deg);
&.customized {
color: #FFFFFF;
background: #252545;
}
&.free {
color: #252545;
background: #D7D7FF;
}
}
</style>

+ 12
- 12
components/product/courseRecommendView.vue View File

@ -65,34 +65,34 @@
{
id: '001',
url: '/pages_order/static/product/course-1.png',
productName: '情绪管理课程',
name: '情绪管理课程',
sales: 24770,
productPriceVal: 688.00,
productPriceBef: 1664,
price: 688.00,
originalPrice: 1664,
},
{
id: '002',
url: '/pages_order/static/product/course-2.png',
productName: '我认知与成长课程',
name: '我认知与成长课程',
sales: 24770,
productPriceVal: 688.00,
productPriceBef: 1664,
price: 688.00,
originalPrice: 1664,
},
{
id: '003',
url: '/pages_order/static/product/course-3.png',
productName: '情绪管理课程',
name: '情绪管理课程',
sales: 24770,
productPriceVal: 688.00,
productPriceBef: 1664,
price: 688.00,
originalPrice: 1664,
},
{
id: '004',
url: '/pages_order/static/product/course-4.png',
productName: '我认知与成长课程',
name: '我认知与成长课程',
sales: 24770,
productPriceVal: 688.00,
productPriceBef: 1664,
price: 688.00,
originalPrice: 1664,
},
]
},


+ 9
- 9
components/product/detectCustomView.vue View File

@ -28,26 +28,26 @@
{
id: '001',
url: '/pages_order/static/product/detect-3.png',
productName: '腹部超声',
name: '腹部超声',
sales: 24770,
productPriceVal: 688.00,
productPriceBef: 1664,
price: 688.00,
originalPrice: 1664,
},
{
id: '002',
url: '/pages_order/static/product/detect-4.png',
productName: '血常规',
name: '血常规',
sales: 24770,
productPriceVal: 688.00,
productPriceBef: 1664,
price: 688.00,
originalPrice: 1664,
},
{
id: '003',
url: '/pages_order/static/product/detect-3.png',
productName: '腹部超声',
name: '腹部超声',
sales: 24770,
productPriceVal: 688.00,
productPriceBef: 1664,
price: 688.00,
originalPrice: 1664,
},
]
},


+ 9
- 9
components/product/detectRecommendSwiper.vue View File

@ -48,23 +48,23 @@
{
id: '001',
url: '/pages_order/static/product/detect-1.png',
productName: '心电图检查',
productPriceVal: 688.00,
productPriceBef: 1664,
name: '心电图检查',
price: 688.00,
originalPrice: 1664,
},
{
id: '002',
url: '/pages_order/static/product/detect-2.png',
productName: '甲状腺功能检查',
productPriceVal: 688.00,
productPriceBef: 1664,
name: '甲状腺功能检查',
price: 688.00,
originalPrice: 1664,
},
{
id: '003',
url: '/pages_order/static/product/detect-1.png',
productName: '心电图检查',
productPriceVal: 688.00,
productPriceBef: 1664,
name: '心电图检查',
price: 688.00,
originalPrice: 1664,
},
]
},


+ 9
- 9
components/product/nutrientCustomView.vue View File

@ -99,26 +99,26 @@
{
id: '001',
url: '/pages_order/static/index/recommend-pic.png',
productName: '月度装定制营养包',
name: '月度装定制营养包',
sales: 24770,
productPriceVal: 688.00,
productPriceBef: 1664,
price: 688.00,
originalPrice: 1664,
},
{
id: '002',
url: '/pages_order/static/index/recommend-pic.png',
productName: '月度装定制营养包',
name: '月度装定制营养包',
sales: 24770,
productPriceVal: 688.00,
productPriceBef: 1664,
price: 688.00,
originalPrice: 1664,
},
{
id: '003',
url: '/pages_order/static/index/recommend-pic.png',
productName: '月度装定制营养包',
name: '月度装定制营养包',
sales: 24770,
productPriceVal: 688.00,
productPriceBef: 1664,
price: 688.00,
originalPrice: 1664,
},
]
},


+ 9
- 9
components/product/nutrientRecommendSwiper.vue View File

@ -45,26 +45,26 @@
{
id: '001',
url: '/pages_order/static/index/recommend-pic.png',
productName: '月度装定制营养包',
name: '月度装定制营养包',
sales: 24770,
productPriceVal: 688.00,
productPriceBef: 1664,
price: 688.00,
originalPrice: 1664,
},
{
id: '002',
url: '/pages_order/static/index/recommend-pic.png',
productName: '月度装定制营养包',
name: '月度装定制营养包',
sales: 24770,
productPriceVal: 688.00,
productPriceBef: 1664,
price: 688.00,
originalPrice: 1664,
},
{
id: '003',
url: '/pages_order/static/index/recommend-pic.png',
productName: '月度装定制营养包',
name: '月度装定制营养包',
sales: 24770,
productPriceVal: 688.00,
productPriceBef: 1664,
price: 688.00,
originalPrice: 1664,
},
]
},


+ 7
- 4
components/product/productCard.vue View File

@ -1,20 +1,20 @@
<template>
<view class="card product-card__view" :style="cardStyle">
<view class="card product-card__view" :style="cardStyle" @click="jumpToProductDetail">
<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-name">{{ data.name }}</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 class="highlight">{{ data.price }}</text>
<text>/</text>
</view>
<view class="product-price-bef">
{{ `¥${data.productPriceBef}/份` }}
{{ `¥${data.originalPrice}/份` }}
</view>
</view>
<button class="btn flex" @click="addToCart(data.id)">
@ -47,6 +47,9 @@
addToCart(id) {
// todo
},
jumpToProductDetail() {
this.$utils.navigateTo(`/pages_order/product/productDetail?id=${this.data.id}`)
},
},
}
</script>


+ 6
- 6
components/report/recommendTest.vue View File

@ -27,18 +27,18 @@
{
id: '001',
url: '/pages_order/static/index/recommend-pic.png',
productName: '月度装定制营养包',
name: '月度装定制营养包',
sales: 24770,
productPriceVal: 688.00,
productPriceBef: 1664,
price: 688.00,
originalPrice: 1664,
},
{
id: '002',
url: '/pages_order/static/index/recommend-pic.png',
productName: '月度装定制营养包',
name: '月度装定制营养包',
sales: 24770,
productPriceVal: 688.00,
productPriceBef: 1664,
price: 688.00,
originalPrice: 1664,
},
]
},


+ 6
- 0
pages.json View File

@ -76,6 +76,12 @@
{
"path": "report/compare/result"
},
{
"path": "product/productDetail"
},
{
"path": "comment/commentRecords"
},
{


+ 260
- 0
pages/index/cart copy.vue View File

@ -0,0 +1,260 @@
<template>
<view class="page">
<navbar/>
<view class="user">
<uv-checkbox-group
shape="circle"
v-model="checkboxValue">
<uv-swipe-action>
<view
v-for="(item, index) in list"
:key="index">
<view style="margin-top: 20rpx;"></view>
<uv-swipe-action-item
:options="options">
<view class="item">
<view class="checkbox">
<uv-checkbox
:name="item.id"
activeColor="#FA5A0A"
size="40rpx"
icon-size="35rpx"
></uv-checkbox>
</view>
<image
class="image"
src="https://img95.699pic.com/photo/50058/1378.jpg_wh860.jpg"
mode=""></image>
<view class="info">
<view class="title">
<view class="">
{{ item.title }}
</view>
<view class="">
<uv-number-box v-model="item.num"
@change="valChange"></uv-number-box>
</view>
</view>
<view class="unit">
规格{{ item.unit }}
<uv-icon name="arrow-down"></uv-icon>
</view>
<view class="price">
<text>{{ item.price }}</text>
</view>
</view>
</view>
</uv-swipe-action-item>
</view>
</uv-swipe-action>
</uv-checkbox-group>
<view class="action">
<view class="icon">
<image src="/static/image/cart/1.png" mode=""></image>
<view class="num">
{{ checkboxValue.length }}
</view>
</view>
<view class="price">
<view class="count">
合计
<view class="">
<text>{{ totalPrice }}</text>
</view>
</view>
<view class="text">
{{ checkboxValue.length }}已享受更低优惠
</view>
</view>
<view class="btn">
去结算
</view>
</view>
</view>
<tabber select="cart" />
</view>
</template>
<script>
import tabber from '@/components/base/tabbar.vue'
export default {
components: {
tabber,
},
data() {
return {
value : 0,
checkboxValue : [],
options: [
{
text: '删除',
style: {
backgroundColor: '#FA5A0A'
}
},
],
list : [
{
id : 1,
title : '桌布租赁',
num : 1,
price : 299,
unit : '120*40*75【桌子尺寸】',
},
{
id : 2,
title : '桌布租赁',
num : 1,
price : 299,
unit : '120*40*75【桌子尺寸】',
},
],
}
},
computed: {
totalPrice(){
if (!this.checkboxValue.length) {
return 0
}
let price = 0
this.list.forEach(n => {
if(this.checkboxValue.includes(n.id)){
price += n.price * n.num
}
})
return price
},
},
methods: {
valChange(){
},
}
}
</script>
<style scoped lang="scss">
.page {
padding-bottom: 200rpx;
/deep/ .uv-swipe-action{
width: 100%;
}
}
.user {
.item{
background-color: #fff;
display: flex;
padding: 30rpx;
.checkbox{
display: flex;
justify-content: center;
align-items: center;
}
.image{
width: 200rpx;
height: 200rpx;
border-radius: 20rpx;
}
.info{
flex: 1;
.title{
display: flex;
padding: 10rpx 20rpx;
justify-content: space-between;
}
.unit{
font-size: 24rpx;
padding: 10rpx 20rpx;
color: #717171;
display: flex;
align-items: center;
}
.price{
color: $uni-color;
font-size: 28rpx;
padding: 10rpx 20rpx;
text{
font-size: 36rpx;
font-weight: 900;
}
}
}
}
.action{
width: 700rpx;
position: fixed;
bottom: 220rpx;
left: 25rpx;
background-color: #fff;
height: 100rpx;
border-radius: 50rpx;
box-shadow: 0 0 6rpx 6rpx #00000010;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
z-index: 999;
.icon{
position: relative;
width: 80rpx;
height: 80rpx;
margin: 0 20rpx;
image{
width: 80rpx;
height: 80rpx;
}
.num{
position: absolute;
right: 10rpx;
top: 0rpx;
background-color: $uni-color;
color: #fff;
font-size: 18rpx;
border-radius: 50%;
height: 30rpx;
width: 30rpx;
display: flex;
justify-content: center;
align-items: center;
}
}
.price{
.count{
display: flex;
font-size: 26rpx;
align-items: center;
view{
color: $uni-color;
margin-left: 10rpx;
text{
font-size: 32rpx;
font-weight: 900;
}
}
}
.text{
font-size: 20rpx;
color: #717171;
}
}
.btn{
margin-left: auto;
background-color: $uni-color;
height: 100%;
padding: 0 50rpx;
color: #fff;
display: flex;
justify-content: center;
align-items: center;
}
}
}
</style>

+ 454
- 212
pages/index/cart.vue View File

@ -1,260 +1,502 @@
<template>
<view class="page">
<navbar/>
<view class="page__view">
<navbar bgColor="#F3F2F7" >
<image class="nav-icon" src="@/static/image/icon-nav.png" mode="widthFix"></image>
</navbar>
<view class="user">
<uv-checkbox-group
shape="circle"
v-model="checkboxValue">
<uv-swipe-action>
<view
v-for="(item, index) in list"
:key="index">
<view style="margin-top: 20rpx;"></view>
<uv-swipe-action-item
:options="options">
<view class="item">
<view class="checkbox">
<uv-checkbox
:name="item.id"
activeColor="#FA5A0A"
size="40rpx"
icon-size="35rpx"
></uv-checkbox>
</view>
<image
class="image"
src="https://img95.699pic.com/photo/50058/1378.jpg_wh860.jpg"
mode=""></image>
<view class="info">
<view class="title">
<view class="">
{{ item.title }}
</view>
<view class="">
<uv-number-box v-model="item.num"
@change="valChange"></uv-number-box>
</view>
</view>
<view class="unit">
规格{{ item.unit }}
<uv-icon name="arrow-down"></uv-icon>
</view>
<view class="price">
<text>{{ item.price }}</text>
</view>
</view>
</view>
</uv-swipe-action-item>
</view>
</uv-swipe-action>
</uv-checkbox-group>
<view class="action">
<view class="icon">
<image src="/static/image/cart/1.png" mode=""></image>
<view class="num">
{{ checkboxValue.length }}
<view class="main">
<view class="top">
<view class="flex header">
<view class="flex label">
<view>购物车</view>
<view v-if="total" class="desc">{{ `${total}` }}</view>
</view>
<button v-if="mode == 'edit'" class="btn" @click="onLeaveEdit">完成</button>
<button v-else class="btn" @click="onEnterEdit">管理</button>
</view>
<view class="price">
<view class="count">
合计
<view class="">
<text>{{ totalPrice }}</text>
</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>
<template v-if="total">
<view>
<view class="card" v-for="(item, index) in list" :key="item.id">
<productCard
:data="item"
@select="onSelect(index, $event)"
@change="onChange(index, $event)"
></productCard>
</view>
<view class="text">
{{ checkboxValue.length }}已享受更低优惠
</view>
</template>
<template v-else>
<view class="flex flex-column empty">
<view class="empty-title">购物车为空</view>
<view class="empty-desc">请将喜欢的商品加入购物袋</view>
</view>
<view class="recommend">
<view v-for="item in recommendList" :key="item.id">
<recommendProductCard
:data="item"
cardStyle="width: 100%; height: 210px;"
imgStyle="width: 100%; height: 110px;"
></recommendProductCard>
</view>
</view>
<view class="btn">
去结算
</template>
</view>
<view class="flex bottom">
<template v-if="mode == 'edit'">
<view class="flex bar bar-edit">
<button class="btn" @click="onLeaveEdit">取消</button>
<button class="btn" @click="onDelete">删除</button>
</view>
</view>
</template>
<template v-else>
<view class="flex bar bar-settle">
<view class="flex info">
<image class="icon" src="@/pages_order/static/cart/cart-icon.png" mode="widthFix"></image>
<view>
<view class="flex row">已选<text class="count">{{ `${selectedList.length}` }}</text>已享受更低优惠</view>
<view class="flex row">合计<text class="unit">¥</text><text class="price">{{ totalPrice }}</text></view>
</view>
</view>
<button class="btn">去结算</button>
</view>
</template>
</view>
<tabber select="cart" />
</view>
</template>
<script>
import mixinsList from '@/mixins/list.js'
import tabber from '@/components/base/tabbar.vue'
import productCard from '@/components/cart/productCard.vue'
import recommendProductCard from '@/components/product/productCard.vue'
export default {
mixins: [mixinsList],
components: {
productCard,
recommendProductCard,
tabber,
},
data() {
return {
// todo
mixinsListApi: '',
// todo
keyword: '',
mode: 'read',
selectedList: [],
recommendList: [],
}
},
computed: {
// selectedList() {
// return this.list.filter(item => item.selected)
// },
totalPrice() {
return this.selectedList.reduce((price, item) => {
// return price + item.price * (item.count || 1)
return price + item.price
}, 0)
},
},
data() {
return {
value : 0,
checkboxValue : [],
options: [
methods: {
//
search() {
// todo
},
getData() {
this.list = [
{
text: '删除',
style: {
backgroundColor: '#FA5A0A'
}
},
],
list : [
id: '001',
url: '/pages_order/static/index/recommend-pic.png',
name: '月度装定制营养包',
price: 688,
count: 1,
countDesc: '1月装',
options: [
{ id: '001', label: '1月装', count: 1, value: 688 },
{ id: '002', label: '3月装', count: 3, value: 688*3 },
{ id: '003', label: '6月装', count: 6, value: 688*6 },
],
customized: true,
checked: false,
},
{
id : 1,
title : '桌布租赁',
num : 1,
price : 299,
unit : '120*40*75【桌子尺寸】',
id: '002',
url: '/pages_order/static/index/recommend-pic.png',
name: '月度装定制营养包',
price: 688,
count: 1,
countDesc: '1月装',
options: [
{ id: '001', label: '1月装', count: 1, value: 688 },
{ id: '002', label: '3月装', count: 3, value: 688*3 },
{ id: '003', label: '6月装', count: 6, value: 688*6 },
],
free: true,
checked: false,
},
{
id : 2,
title : '桌布租赁',
num : 1,
price : 299,
unit : '120*40*75【桌子尺寸】',
id: '003',
url: '/pages_order/static/index/recommend-pic.png',
name: '月度装定制营养包',
price: 688,
count: 1,
countDesc: '1月装',
options: [
{ id: '001', label: '1月装', count: 1, value: 688 },
{ id: '002', label: '3月装', count: 3, value: 688*3 },
{ id: '003', label: '6月装', count: 6, value: 688*6 },
],
free: true,
checked: false,
},
],
}
},
computed: {
totalPrice(){
if (!this.checkboxValue.length) {
return 0
{
id: '004',
url: '/pages_order/static/index/recommend-pic.png',
name: '月度装定制营养包',
price: 688,
count: 1,
countDesc: '1月装',
options: [
{ id: '001', label: '1月装', count: 1, value: 688 },
{ id: '002', label: '3月装', count: 3, value: 688*3 },
{ id: '003', label: '6月装', count: 6, value: 688*6 },
],
free: true,
checked: false,
},
{
id: '005',
url: '/pages_order/static/index/recommend-pic.png',
name: '月度装定制营养包',
price: 688,
count: 1,
countDesc: '1月装',
options: [
{ id: '001', label: '1月装', count: 1, value: 688 },
{ id: '002', label: '3月装', count: 3, value: 688*3 },
{ id: '003', label: '6月装', count: 6, value: 688*6 },
],
free: true,
checked: false,
},
]
this.total = this.list.length
this.getDataThen && this.getDataThen(this.list, this.total)
},
getDataThen(records, total) {
console.log('getDataThen')
// todo
if (total) {
return
}
let price = 0
this.list.forEach(n => {
if(this.checkboxValue.includes(n.id)){
price += n.price * n.num
}
})
return price
this.recommendList = [
{
id: '001',
url: '/pages_order/static/index/recommend-pic.png',
name: '月度装定制营养包',
sales: 24770,
price: 688.00,
originalPrice: 1664,
},
{
id: '002',
url: '/pages_order/static/index/recommend-pic.png',
name: '月度装定制营养包',
sales: 24770,
price: 688.00,
originalPrice: 1664,
},
{
id: '003',
url: '/pages_order/static/index/recommend-pic.png',
name: '月度装定制营养包',
sales: 24770,
price: 688.00,
originalPrice: 1664,
},
{
id: '004',
url: '/pages_order/static/index/recommend-pic.png',
name: '月度装定制营养包',
sales: 24770,
price: 688.00,
originalPrice: 1664,
},
]
},
},
methods: {
valChange(){
updateSelectedList() {
this.selectedList = this.list.filter(item => item.selected)
},
onSelect(index, selected) {
console.log('onSelect', index, selected)
this.list[index].selected = selected
// todo
this.updateSelectedList()
},
onChange(index, obj) {
console.log('onChange', index, obj)
// todo: check
this.list[index].price = obj.price
this.list[index].count = obj.count
this.list[index].countDesc = obj.countDesc
// todo
this.updateSelectedList()
},
onEnterEdit() {
this.mode = 'edit'
},
}
onLeaveEdit() {
this.mode = 'read'
},
onDelete() {
uni.showModal({
title: '确认删除?',
success : e => {
if(e.confirm){
// todo
this.list = this.list.filter(item => !item.selected)
this.total = this.list.length
}
}
})
},
},
}
</script>
<style scoped lang="scss">
.page {
padding-bottom: 200rpx;
/deep/ .uv-swipe-action{
width: 100%;
.page__view {
width: 100vw;
min-height: 100vh;
background-color: $uni-bg-color;
position: relative;
/deep/ .nav-bar__view {
position: fixed;
top: 0;
left: 0;
}
.nav-icon {
width: 200rpx;
height: auto;
vertical-align: top;
}
/deep/ .tabbar-box .tabbar {
z-index: 9999;
}
}
.user {
.item{
background-color: #fff;
display: flex;
padding: 30rpx;
.checkbox{
display: flex;
justify-content: center;
align-items: center;
}
.image{
width: 200rpx;
height: 200rpx;
border-radius: 20rpx;
}
.info{
.main {
padding: calc(var(--status-bar-height) + 288rpx) 32rpx 186rpx 32rpx;
}
.top {
position: fixed;
top: calc(var(--status-bar-height) + 120rpx);
left: 0;
width: 100%;
height: 168rpx;
padding: 16rpx 32rpx 8rpx 32rpx;
background-color: $uni-bg-color;
box-sizing: border-box;
z-index: 1;
}
.header {
justify-content: space-between;
column-gap: 4rpx;
.label {
font-family: PingFang SC;
font-weight: 600;
font-size: 36rpx;
line-height: 1.2;
color: #252545;
}
.desc {
font-family: PingFang SC;
font-weight: 400;
font-size: 24rpx;
line-height: 1.4;
color: #2A2A2A;
}
.btn {
font-family: PingFang SC;
font-weight: 600;
font-size: 28rpx;
line-height: 1.5;
color: #FFFFFF;
padding: 8rpx 32rpx;
background-image: linear-gradient(to right, #4B348F, #845CFA);
border-radius: 30rpx;
}
}
.search {
margin: 24rpx 0 40rpx 0;
/deep/ .uv-search__content__icon {
margin-top: 2rpx;
}
}
.empty {
width: 100%;
font-family: PingFang SC;
line-height: 1.4;
padding: 104rpx 0;
box-sizing: border-box;
&-title {
font-weight: 500;
font-size: 32rpx;
color: #000000;
}
&-desc {
margin-top: 16rpx;
font-weight: 400;
font-size: 26rpx;
color: #8B8B8B;
}
}
.recommend {
margin-top: 40rpx;
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 32rpx;
}
.card {
margin-top: 32rpx;
}
.bottom {
position: fixed;
left: 0;
bottom: calc(env(safe-area-inset-bottom) + #{$tabbar-height});
width: 100vw;
height: 122rpx;
padding: 0 40rpx;
background: #FFFFFF;
box-sizing: border-box;
}
.bar {
width: 100%;
&-edit {
column-gap: 32rpx;
.btn {
flex: 1;
.title{
display: flex;
padding: 10rpx 20rpx;
justify-content: space-between;
}
.unit{
font-size: 24rpx;
padding: 10rpx 20rpx;
color: #717171;
display: flex;
align-items: center;
}
.price{
color: $uni-color;
font-size: 28rpx;
padding: 10rpx 20rpx;
text{
font-size: 36rpx;
font-weight: 900;
}
}
padding: 16rpx 0;
font-family: PingFang SC;
font-weight: 500;
font-size: 36rpx;
line-height: 1;
color: #252545;
border: 2rpx solid #252545;
border-radius: 41rpx;
}
}
.action{
width: 700rpx;
position: fixed;
bottom: 220rpx;
left: 25rpx;
background-color: #fff;
height: 100rpx;
border-radius: 50rpx;
box-shadow: 0 0 6rpx 6rpx #00000010;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
z-index: 999;
.icon{
position: relative;
width: 80rpx;
height: 80rpx;
margin: 0 20rpx;
image{
width: 80rpx;
height: 80rpx;
&-settle {
justify-content: space-between;
.info {
column-gap: 16rpx;
font-family: PingFang SC;
font-weight: 400;
font-size: 24rpx;
line-height: 1.4;
color: #626262;
.icon {
width: 76rpx;
height: auto;
}
.num{
position: absolute;
right: 10rpx;
top: 0rpx;
background-color: $uni-color;
color: #fff;
font-size: 18rpx;
border-radius: 50%;
height: 30rpx;
width: 30rpx;
display: flex;
justify-content: center;
align-items: center;
.row {
justify-content: flex-start;
}
}
.price{
.count{
display: flex;
font-size: 26rpx;
align-items: center;
view{
color: $uni-color;
margin-left: 10rpx;
text{
font-size: 32rpx;
font-weight: 900;
}
}
.count,
.unit,
.price {
font-weight: 500;
color: #7451DE;
}
.count {
margin: 0 12rpx;
}
.text{
font-size: 20rpx;
color: #717171;
.unit {
margin: 0 8rpx;
}
.price {
font-size: 40rpx;
}
}
.btn{
margin-left: auto;
background-color: $uni-color;
height: 100%;
padding: 0 50rpx;
color: #fff;
display: flex;
justify-content: center;
align-items: center;
.btn {
padding: 16rpx 46rpx;
color: #FFFFFF;
font-family: PingFang SC;
font-weight: 500;
font-size: 36rpx;
line-height: 1;
background-image: linear-gradient(to right, #4B348F, #845CFA);
border-radius: 41rpx;
}
}
}
</style>

+ 137
- 0
pages_order/comment/commentCard.vue View File

@ -0,0 +1,137 @@
<template>
<view class="card">
<view class="flex header">
<view class="avatar">
<image class="avatar-img" :src="data.avatar"></image>
</view>
<view class="info">
<view class="name">{{ data.userName }}</view>
<view>{{ `${data.countDesc} | ${$dayjs(data.createTime).format('YYYY-MM-DD')}` }}</view>
</view>
</view>
<view class="section content">{{ data.content }}</view>
<view class="flex section imgs">
<image class="img"
v-for="(item, iIdx) in data.images"
:key="iIdx" :src="item"
mode="scaleToFill"
></image>
</view>
<view class="section score">
<view class="flex score-item">
<view class="score-item-label">产品服务度</view>
<uv-rate :value="data.productServeScore" size="48rpx" gutter="16rpx" activeColor="#F7BA1E" :allowHalf="true" readonly></uv-rate>
</view>
<view class="flex score-item">
<view class="score-item-label">问卷体验</view>
<uv-rate :value="data.questionExperienceScore" size="48rpx" gutter="16rpx" activeColor="#F7BA1E" :allowHalf="true" readonly></uv-rate>
</view>
<view class="flex score-item">
<view class="score-item-label">物流速度</view>
<uv-rate :value="data.deliverySpeedScore" size="48rpx" gutter="16rpx" activeColor="#F7BA1E" :allowHalf="true" :minCount="0.5" readonly></uv-rate>
</view>
</view>
</view>
</template>
<script>
export default {
props: {
data: {
type: Object,
default() {
return {}
}
},
}
}
</script>
<style scoped lang="scss">
.card {
width: 100%;
padding: 32rpx;
box-sizing: border-box;
background: #FAFAFF;
border: 2rpx solid #FFFFFF;
border-radius: 32rpx;
}
.header {
justify-content: flex-start;
column-gap: 24rpx;
.avatar {
width: 100rpx;
height: 100rpx;
border: 4rpx solid #FFFFFF;
border-radius: 50%;
overflow: hidden;
&-img {
width: 100%;
height: 100%;
}
}
.info {
font-family: PingFang SC;
font-weight: 400;
font-size: 24rpx;
line-height: 1.5;
color: #8B8B8B;
.name {
font-weight: 600;
font-size: 36rpx;
line-height: 1.2;
color: #252545;
margin-bottom: 8rpx;
}
}
}
.section {
margin-top: 24rpx;
}
.content {
font-family: PingFang SC;
font-weight: 400;
font-size: 32rpx;
line-height: 1.4;
color: #181818;
}
.imgs {
justify-content: flex-start;
flex-wrap: wrap;
gap: 24rpx;
.img {
width: 190rpx;
height: 190rpx;
}
}
.score {
&-item {
padding: 12rpx 0;
justify-content: space-between;
& + & {
margin-top: 4rpx;
}
&-label {
font-family: PingFang SC;
font-weight: 400;
font-size: 26rpx;
line-height: 1.4;
color: #181818;
}
}
}
</style>

+ 196
- 0
pages_order/comment/commentRecords.vue View File

@ -0,0 +1,196 @@
<template>
<view class="page__view">
<navbar :title="title" leftClick @leftClick="$utils.navigateBack" color="#191919" bgColor="#FFFFFF" />
<view class="main">
<view class="tabs">
<uv-tabs
:list="tabs"
:scrollable="false"
lineColor="#7451DE"
lineWidth="48rpx"
lineHeight="4rpx"
:activeStyle="{
'font-family': 'PingFang SC',
'font-weight': 500,
'font-size': '32rpx',
'line-height': 1.4,
'color': '#7451DE',
}"
:inactiveStyle="{
'font-family': 'PingFang SC',
'font-weight': 400,
'font-size': '32rpx',
'line-height': 1.4,
'color': '#181818',
}"
@click="clickTabs"
></uv-tabs>
</view>
<view class="comment">
<view class="comment-item" v-for="item in list" :key="item.id">
<commentCard :data="item"></commentCard>
</view>
</view>
</view>
</view>
</template>
<script>
import mixinsList from '@/mixins/list.js'
import commentCard from '@/pages_order/comment/commentCard.vue'
export default {
mixins: [mixinsList],
components: {
commentCard,
},
data() {
return {
title: '用户评价',
tabs: [
{ name: '全部' },
{ name: '有图/视频' },
{ name: '最新' },
],
id: null,
creator: null,
mixinsListApi: '',
}
},
onShow() {
console.log('onShow')
},
onLoad(arg) {
console.log('onLoad')
const { title, id, creator } = arg
title && (this.title = title)
this.id = id
this.creator = creator
// todo set queryParams
this.getData()
},
methods: {
//tab
clickTabs({ index }) {
if (index == 0) {
delete this.queryParams.status
} else {
this.queryParams.status = index - 1
}
this.getData()
},
// todo: delete
getData() {
this.list = [
{
id: '001',
userName: '战斗世界',
avatar: '/pages_order/static/report/avatar.png',
countDesc: '三月装',
createTime: '2023-04-18',
content: '包装很精致,性价比非常高,终于收到啦,期待效果,每日一包,超级方便,真的能坚持服用',
images: [
'/pages_order/static/index/medicine-1.png',
'/pages_order/static/index/medicine-2.png',
'/pages_order/static/index/medicine-3.png',
],
productServeScore: 5,
questionExperienceScore: 4,
deliverySpeedScore: 4.5,
},
{
id: '002',
userName: '战斗世界',
avatar: '/pages_order/static/report/avatar.png',
countDesc: '三月装',
createTime: '2023-04-18',
content: '包装很精致,性价比非常高,终于收到啦,期待效果,每日一包,超级方便,真的能坚持服用',
images: [
'/pages_order/static/index/medicine-1.png',
'/pages_order/static/index/medicine-2.png',
'/pages_order/static/index/medicine-3.png',
],
productServeScore: 5,
questionExperienceScore: 4,
deliverySpeedScore: 4.5,
},
{
id: '003',
userName: '战斗世界',
avatar: '/pages_order/static/report/avatar.png',
countDesc: '三月装',
createTime: '2023-04-18',
content: '包装很精致,性价比非常高,终于收到啦,期待效果,每日一包,超级方便,真的能坚持服用',
images: [
'/pages_order/static/index/medicine-1.png',
'/pages_order/static/index/medicine-2.png',
'/pages_order/static/index/medicine-3.png',
],
productServeScore: 5,
questionExperienceScore: 4,
deliverySpeedScore: 4.5,
},
]
this.total = this.list.length
},
},
}
</script>
<style scoped lang="scss">
.page__view {
width: 100vw;
min-height: 100vh;
background-color: $uni-bg-color;
position: relative;
/deep/ .nav-bar__view {
position: fixed;
top: 0;
left: 0;
}
}
.main {
width: 100vw;
padding-top: calc(var(--status-bar-height) + 204rpx);
box-sizing: border-box;
.tabs {
position: fixed;
top: calc(var(--status-bar-height) + 120rpx);
left: 0;
width: 100%;
height: 84rpx;
background: #FFFFFF;
/deep/ .uv-tabs__wrapper__nav__line {
border-radius: 2rpx;
bottom: 0;
}
}
}
.comment {
padding: 40rpx 32rpx;
&-item {
& + & {
margin-top: 40rpx;
}
}
}
</style>

+ 2
- 2
pages_order/components/reportCard.vue View File

@ -1,11 +1,11 @@
<template>
<view class="card report-card__view">
<view class="card-header">
<image class="card-header-bg" src="/pages_order/static/report/report-card-header-bg.png" mode="scaleToFill"></image>
<image class="card-header-bg" src="@/pages_order/static/report/report-card-header-bg.png" mode="scaleToFill"></image>
<view class="flex card-header-content">
<view class="avatar">
<!-- todo -->
<image class="avatar-img" src="/pages_order/static/report/avatar.png" mode="scaleToFill"></image>
<image class="avatar-img" src="@/pages_order/static/report/avatar.png" mode="scaleToFill"></image>
</view>
<view class="info">
<!-- todo -->


+ 98
- 0
pages_order/product/agreementPopup.vue View File

@ -0,0 +1,98 @@
<template>
<view>
<uv-popup ref="popup" mode="center" bgColor="none" >
<view class="popup__view">
<view class="header">温馨提示</view>
<view class="content">
<uv-parse :content="content"></uv-parse>
</view>
<view class="footer">
<button class="flex btn" @click="onConfirm">我知道了</button>
</view>
</view>
</uv-popup>
</view>
</template>
<script>
import { mapState } from 'vuex'
export default {
data() {
return {
content : '',
}
},
computed : {
...mapState(['configList'])
},
methods: {
open() {
// todo
// this.content = this.configList[key]
this.content = `
<p>
亲爱的用户欢迎选购我们的健康营养素包<br/>
在购买前请仔细阅读以下内容我们所提供的营养素包均严格遵循国际健康标准与规范进行研发和生产旨在根据您的问卷调查或个人体检情况精准匹配适合您的营养补充方案<br/>
在下单购买时请确保您所提供的身体信息真实准确以便我们为您推荐最合适的营养素组合同时由于海外运输及海关政策可能会影响包裹的送达时间我们会在发货后第一时间为您更新物流信息预计送达时间仅供参考请耐心等待<br/>
若您在购买过程中有任何疑问或是收到产品后遇到任何问题我们的客服团队将竭诚为您提供 24 小时服务祝您健康常伴
</p>
`
this.$refs.popup.open()
},
onConfirm() {
this.$refs.popup.close()
this.$emit('confirm')
},
},
}
</script>
<style lang="scss" scoped>
.popup__view {
width: 550rpx;
display: flex;
flex-direction: column;
padding: 32rpx;
box-sizing: border-box;
background-image: linear-gradient(#F2EDFF, #FCFEFE);
border-radius: 64rpx;
}
.header {
text-align: center;
font-family: PingFang SC;
font-weight: 500;
font-size: 40rpx;
line-height: 1.4;
color: #181818;
}
.content {
padding: 40rpx 0;
text-align: left;
font-family: PingFang SC;
font-weight: 400;
font-size: 28rpx;
line-height: 1.4;
color: #5B5B5B;
}
.footer {
.btn {
width: 100%;
padding: 16rpx 0;
font-family: PingFang SC;
font-weight: 500;
font-size: 36rpx;
line-height: 1.4;
color: #FFFFFF;
background-image: linear-gradient(to right, #4B348F, #845CFA);
border-radius: 41rpx;
}
}
</style>

+ 232
- 0
pages_order/product/countSelectPopup.vue View File

@ -0,0 +1,232 @@
<template>
<view>
<uv-popup ref="popup" mode="bottom" bgColor="none" >
<view class="popup__view">
<view class="flex header">
<view class="title">选择规格</view>
<button class="btn" @click="close">关闭</button>
</view>
<view class="section info">
<view class="flex card">
<view class="left">
<image class="img" :src="coverImg" mode="aspectFill"></image>
</view>
<view class="right">
<view class="name">{{ data.name }}</view>
<view class="desc">可在以下安全剂量内根据你的额外需求选择颗数</view>
</view>
</view>
</view>
<view class="section option">
<view
v-for="item in data.options"
:key="item.id"
:class="['option-item', selectId == item.id ? 'is-active' : '']"
@click="selectId = item.id"
>
{{ item.label }}
</view>
</view>
<view class="footer">
<button class="flex btn" @click="onConfirm">下一步</button>
</view>
</view>
</uv-popup>
</view>
</template>
<script>
import { mapState } from 'vuex'
export default {
props: {
data: {
type: Object,
default() {
return {}
}
}
},
data() {
return {
selectId: null,
}
},
computed : {
...mapState(['configList']),
coverImg() {
const { image } = this.data
if (!image) {
return ''
}
let arr = Array.isArray(image) ? image : image.split(',')
return arr[0]
},
},
methods: {
open() {
this.$refs.popup.open()
},
close() {
this.$refs.popup.close()
this.selectId = null
},
onConfirm() {
if (!this.selectId) {
uni.showToast({
title: '请选择规格',
icon: 'none',
})
return
}
this.$emit('confirm', this.selectId)
this.close()
},
},
}
</script>
<style lang="scss" scoped>
.popup__view {
width: 100vw;
display: flex;
flex-direction: column;
box-sizing: border-box;
background: #FFFFFF;
border-top-left-radius: 32rpx;
border-top-right-radius: 32rpx;
}
.header {
position: relative;
width: 100%;
padding: 24rpx 0;
box-sizing: border-box;
.title {
font-family: PingFang SC;
font-weight: 500;
font-size: 34rpx;
line-height: 1.4;
color: #181818;
}
.btn {
font-family: PingFang SC;
font-weight: 500;
font-size: 32rpx;
line-height: 1.4;
color: #8B8B8B;
position: absolute;
top: 26rpx;
left: 40rpx;
}
}
.section {
border-top: 2rpx solid #EEEEEE;
}
.info {
width: 100%;
padding: 32rpx;
box-sizing: border-box;
.card {
width: 100%;
padding: 32rpx;
box-sizing: border-box;
background-image: linear-gradient(#FAFAFF, #F3F3F3);
border-radius: 32rpx;
column-gap: 24rpx;
.left {
width: 144rpx;
height: 144rpx;
border-radius: 16rpx;
overflow: hidden;
.img {
width: 100%;
height: 100%;
}
}
.right {
flex: 1;
.name {
font-family: PingFang SC;
font-weight: 500;
font-size: 28rpx;
line-height: 1.4;
color: #000000;
}
.desc {
margin-top: 8rpx;
font-family: PingFang SC;
font-weight: 400;
font-size: 26rpx;
line-height: 1.5;
color: #8B8B8B;
}
}
}
}
.option {
width: 100%;
padding: 44rpx;
box-sizing: border-box;
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 24rpx;
&-item {
padding: 18rpx 14rpx;
text-align: center;
font-family: PingFang SC;
font-weight: 400;
font-size: 28rpx;
line-height: 1.4;
color: #181818;
background: #F9F9F9;
border: 2rpx solid #F9F9F9;
border-radius: 16rpx;
&.is-active {
color: #7451DE;
background: #F2EEFF;
border-color: #7451DE;
}
}
}
.footer {
width: 100%;
padding: 32rpx 40rpx;
box-sizing: border-box;
.btn {
width: 100%;
padding: 16rpx 0;
font-family: PingFang SC;
font-weight: 500;
font-size: 36rpx;
line-height: 1.4;
color: #FFFFFF;
background-image: linear-gradient(to right, #4B348F, #845CFA);
border-radius: 41rpx;
}
}
</style>

+ 444
- 0
pages_order/product/productDetail.vue View File

@ -0,0 +1,444 @@
<template>
<view class="page__view">
<navbar title="商品详情页" leftClick @leftClick="$utils.navigateBack" color="#191919" bgColor="#FFFFFF" />
<view class="main">
<uv-swiper :list="bannerList" indicator indicatorMode="dot" height="680rpx" keyName="image"></uv-swiper>
<view class="summary">
<view class="card info">
<view class="name">{{ detail.fullName }}</view>
<view class="flex tags">
<view class="tag" v-for="(tag, tIdx) in detail.tags" :key="tIdx">
{{ tag }}
</view>
</view>
<view class="flex price">
<view class="flex price-val">¥<text class="highlight">{{ (detail.price || 0).toFixed(2) }}</text>/</view>
<view class="price-bef">¥<text>{{ detail.originalPrice }}</text>/</view>
</view>
</view>
<view class="card bar">
<view class="flex row">
<view class="flex row-content">
<view class="label">品类</view>
<view class="value">{{ detail.category }}</view>
</view>
</view>
<view class="flex row" @click="openPicker">
<view class="flex row-content">
<view class="label">规格</view>
<view class="value">{{ detail.countDesc || '请选择规格' }}</view>
</view>
<uv-picker ref="picker" :columns="[detail.options]" keyName="label" confirmColor="#7451DE" @confirm="onChange"></uv-picker>
<uv-icon name="arrow-right" color="#C6C6C6" size="24rpx"></uv-icon>
</view>
<view class="flex row">
<view class="flex row-content">
<view class="label">服务</view>
<view class="value">{{ detail.deliverService }}</view>
</view>
</view>
</view>
</view>
<view class="detail">
<uv-parse :content="detail.details"></uv-parse>
</view>
<view class="comment">
<view class="header">
<view class="highlight">用户评价</view>
<view>User reviews</view>
</view>
<view class="comment-item" v-for="item in commentList" :key="item.id">
<commentCard :data="item"></commentCard>
</view>
</view>
</view>
<view class="flex bottom">
<button class="flex flex-column btn btn-simple" @click="jumpToComment">
<image class="icon" src="@/pages_order/static/product/comment.png" mode="widthFix"></image>
<view>评价</view>
</button>
<button class="flex btn btn-palin">加入购物车</button>
<button class="flex btn btn-primary" @click="onBuy">立即购买</button>
</view>
<countSelectPopup ref="countSelectPopup" :data="detail" @confirm="onSelectCount"></countSelectPopup>
<agreementPopup ref="agreementPopup" @confirm="jumpToCreateOrder"></agreementPopup>
</view>
</template>
<script>
import commentCard from '@/pages_order/comment/commentCard.vue'
import agreementPopup from './agreementPopup.vue'
import countSelectPopup from './countSelectPopup.vue'
export default {
components: {
commentCard,
agreementPopup,
countSelectPopup,
},
data() {
return {
id: null,
detail: {},
commentList: [],
}
},
computed: {
bannerList() {
const { image } = this.detail
if (!image) {
return []
}
return Array.isArray(image) ? image : image.split(',')
},
},
onLoad(arg) {
console.log('onLoad', arg)
this.id = arg.id
// todo: fetch detail data
this.detail = {
id: '001',
image: new Array(4).fill('/pages_order/static/product/product-detail.png'),
name: 'NMN',
fullName: 'NMN 是 NAD* 的前体,在细胞能量代谢、DNA 修复和抗衰老等方面发挥重要作用。提高 NAD*水平能改善代谢健康1-8。',
tags: ['专业设备', '科学流程', '质量保证'],
sales: 24770,
price: 688.00,
originalPrice: 1664,
category: '逆龄抗衰',
count: null,
countDesc: null,
options: [
{ id: '001', label: '每天1颗', count: 1, value: 688, originValue: 1664 },
{ id: '002', label: '每天2颗', count: 2, value: 688*2, originValue: 1664*2 },
{ id: '003', label: '每天3颗', count: 3, value: 688*3, originValue: 1664*3 },
{ id: '004', label: '每天4颗', count: 4, value: 688*4, originValue: 1664*4 },
],
deliverService: '上门取件·送货上门',
details: `<p>商品详情↓<br/><br/><br/><br/>商品详情↑</p>`
}
this.commentList = [
{
id: '001',
userName: '战斗世界',
avatar: '/pages_order/static/report/avatar.png',
countDesc: '三月装',
createTime: '2023-04-18',
content: '包装很精致,性价比非常高,终于收到啦,期待效果,每日一包,超级方便,真的能坚持服用',
images: [
'/pages_order/static/index/medicine-1.png',
'/pages_order/static/index/medicine-2.png',
'/pages_order/static/index/medicine-3.png',
],
productServeScore: 5,
questionExperienceScore: 4,
deliverySpeedScore: 4.5,
},
{
id: '002',
userName: '战斗世界',
avatar: '/pages_order/static/report/avatar.png',
countDesc: '三月装',
createTime: '2023-04-18',
content: '包装很精致,性价比非常高,终于收到啦,期待效果,每日一包,超级方便,真的能坚持服用',
images: [
'/pages_order/static/index/medicine-1.png',
'/pages_order/static/index/medicine-2.png',
'/pages_order/static/index/medicine-3.png',
],
productServeScore: 5,
questionExperienceScore: 4,
deliverySpeedScore: 4.5,
},
{
id: '003',
userName: '战斗世界',
avatar: '/pages_order/static/report/avatar.png',
countDesc: '三月装',
createTime: '2023-04-18',
content: '包装很精致,性价比非常高,终于收到啦,期待效果,每日一包,超级方便,真的能坚持服用',
images: [
'/pages_order/static/index/medicine-1.png',
'/pages_order/static/index/medicine-2.png',
'/pages_order/static/index/medicine-3.png',
],
productServeScore: 5,
questionExperienceScore: 4,
deliverySpeedScore: 4.5,
},
]
},
methods: {
openPicker() {
this.$refs.picker.open();
},
onChange(e) {
const target = e.value[0]
console.log('onChange', target)
this.detail.price = target.value
this.detail.count = target.count
this.detail.countDesc = target.label
},
jumpToComment() {
this.$utils.navigateTo('/pages_order/comment/commentRecords')
},
jumpToCreateOrder() {
// todo
},
onSelectCount(optionId) {
const { options } = this.detail
let target = options.find(item => item.id === optionId)
this.detail.price = target.value
this.detail.count = target.count
this.detail.countDesc = target.label
this.onBuy()
},
onBuy() {
const { count, options } = this.detail
if (!count && options?.length) {
this.$refs.countSelectPopup.open()
return
}
// todo
this.$refs.agreementPopup.open()
// this.jumpToCreateOrder()
},
},
}
</script>
<style scoped lang="scss">
.page__view {
width: 100vw;
min-height: 100vh;
background-color: $uni-bg-color;
position: relative;
/deep/ .nav-bar__view {
position: fixed;
top: 0;
left: 0;
}
}
.main {
width: 100vw;
padding: calc(var(--status-bar-height) + 120rpx) 0 198rpx 0;
box-sizing: border-box;
}
.summary {
width: 100%;
padding: 40rpx 32rpx;
box-sizing: border-box;
}
.card {
border-radius: 24rpx;
& + & {
margin-top: 40rpx;
}
&.info {
width: 100%;
padding: 32rpx;
box-sizing: border-box;
background: #FFFFFF;
.name {
font-family: PingFang SC;
font-weight: 400;
font-size: 32rpx;
line-height: 1.4;
color: #181818;
}
.tags {
margin-top: 16rpx;
justify-content: flex-start;
flex-wrap: wrap;
gap: 16rpx;
.tag {
padding: 2rpx 14rpx;
font-family: PingFang SC;
font-weight: 400;
font-size: 24rpx;
line-height: 1.4;
color: #7451DE;
background: #EFEAFF;
border: 2rpx solid #7451DE;
border-radius: 8rpx;
}
}
.price {
margin-top: 32rpx;
justify-content: flex-start;
column-gap: 20rpx;
&-val {
font-family: PingFang SC;
font-weight: 500;
font-size: 24rpx;
line-height: 1.4;
color: #7451DE;
.highlight {
margin: 0 8rpx;
font-size: 48rpx;
}
}
&-bef {
font-family: PingFang SC;
text-decoration: line-through;
font-weight: 400;
font-size: 28rpx;
line-height: 1;
color: #8B8B8B;
}
}
}
&.bar {
width: 100%;
padding: 20rpx 32rpx;
box-sizing: border-box;
background: #FAFAFF;
box-shadow: -4rpx -4rpx 20rpx 0 #FFFFFFC4,
4rpx 4rpx 20rpx 0 #AAAACC1F,
2rpx 2rpx 4rpx 0 #AAAACC40,
-2rpx -2rpx 4rpx 0 #FFFFFF;
.row {
padding: 8rpx 0;
&-content {
flex: 1;
justify-content: flex-start;
column-gap: 4rpx;
font-family: PingFang SC;
font-weight: 400;
font-size: 28rpx;
line-height: 1.4;
.label {
color: #8B8B8B;
}
.value {
color: #393939;
}
}
}
.row + .row {
margin-top: 24rpx;
}
}
}
.comment {
padding: 40rpx 32rpx;
.header {
margin-bottom: 24rpx;
font-family: PingFang SC;
font-weight: 400;
font-size: 26rpx;
line-height: 1.4;
color: #252545;
.highlight {
font-weight: 600;
font-size: 48rpx;
}
}
&-item {
& + & {
margin-top: 32rpx;
}
}
}
.bottom {
position: fixed;
left: 0;
bottom: 0;
align-items: flex-start;
column-gap: 32rpx;
width: 100vw;
height: 198rpx;
padding: 24rpx 40rpx 0 40rpx;
background: #FFFFFF;
box-sizing: border-box;
.btn {
font-family: PingFang SC;
&-simple {
font-weight: 400;
font-size: 22rpx;
line-height: 1.1;
color: #999999;
.icon {
width: 52rpx;
height: auto;
}
}
&-palin {
flex: 1;
padding: 14rpx 0;
font-weight: 500;
font-size: 36rpx;
line-height: 1.4;
color: #252545;
border: 2rpx solid #252545;
border-radius: 41rpx;
}
&-primary {
flex: 1;
padding: 16rpx 0;
font-weight: 500;
font-size: 36rpx;
line-height: 1.4;
color: #FFFFFF;
background-image: linear-gradient(to right, #4B348F, #845CFA);
border-radius: 41rpx;
}
}
}
</style>

+ 1
- 1
pages_order/report/detail/index.vue View File

@ -183,7 +183,7 @@
<style scoped lang="scss">
.page__view {
width: 100vw;
height: 100vh;
min-height: 100vh;
background-color: $uni-bg-color;
position: relative;


+ 1
- 1
pages_order/report/nutritionProgram/index.vue View File

@ -199,7 +199,7 @@
<style scoped lang="scss">
.page__view {
width: 100vw;
height: 100vh;
min-height: 100vh;
background-color: $uni-bg-color;
position: relative;


+ 1
- 1
pages_order/report/nutritionProgram/productCard.vue View File

@ -83,7 +83,7 @@
this.checked = arr[0] == 1 ? true : false
},
jumpToProductDetail() {
// todo
this.$utils.navigateTo(`/pages_order/product/productDetail?id=${this.data.id}`)
},
},
}


+ 1
- 1
pages_order/report/result/index.vue View File

@ -152,7 +152,7 @@
<style scoped lang="scss">
.page__view {
width: 100vw;
height: 100vh;
min-height: 100vh;
background-color: $uni-bg-color;
position: relative;
}


BIN
pages_order/static/cart/cart-icon.png View File

Before After
Width: 38  |  Height: 39  |  Size: 2.8 KiB

BIN
pages_order/static/product/comment.png View File

Before After
Width: 26  |  Height: 27  |  Size: 537 B

BIN
pages_order/static/product/product-detail.png View File

Before After
Width: 188  |  Height: 170  |  Size: 40 KiB

static/image/tabbar/cart-center.png → static/image/tabbar/cart-active.png View File


+ 5
- 0
store/store.js View File

@ -11,6 +11,7 @@ const store = new Vuex.Store({
configList: {}, //配置列表
shop : false,//身份判断如果不需要,可以删除
userInfo : {}, //用户信息
payOrderProduct: [], //支付订单中的商品
},
getters: {
// 角色 true为水洗店 false为酒店 : 身份判断如果不需要,可以删除
@ -103,6 +104,10 @@ const store = new Vuex.Store({
}
})
},
// 设置支付订单中的商品
setPayOrderProduct(state, data) {
state.payOrderProduct = data
},
},
actions: {},
})


Loading…
Cancel
Save