在shop页面选中商品添加到购物车,可选好后,进行确认和支付。具体呈现在shop页面。

1 购物车栏
shop页面代码:
购物车代码:

代码:
html
<template>
<view>
<view class="carlayout">
<!-- 车里面 点击购物车 弹出的内容 -->
<view class="goods" v-if="carShow">
<!-- 弹窗列表 -->
<view class="head">
<view class="text">
已选商品
</view>
<view class="empty" @click="clearCar">
清空
</view>
</view>
<scroll-view scroll-y="true" class="body">
<view calss="scrollContent">
<view class="caritem" v-for="item,index in carsList" :key="index">
<car-item :item="item"></car-item>
</view>
</view>
</scroll-view>
</view>
<!-- 购物车 -->
<view class="content">
<view class="left">
<view class="icon" hover-class="iconhover" hover-stay-time="50" hover-start-time="10" @click="onClickCar" v-if="!type">
<!-- 鼠标点击就会 触发 iconhover 这个类名 -->
<!-- hover-stay-time 弹回 就很块了只有 50ms -->
<u-icon name="shopping-cart" size="50" color="#5ac725"></u-icon>
<view class="num">{{totalNumValue}}</view>
</view>
<view class="price" >合计<text class="text">¥{{totalPrice}}</text></view>
</view>
<view class="right">
<view class="btn disable" v-if="!type" @click="goPaypage">选好了</view>
<view class="btn disable" v-else @click="confirmPay">支付</view>
</view>
</view>
<view class="safeAreaBottom"></view>
<!-- 上面安全区域是设置为ios使用的,怕底部的区域被遮挡了 -->
</view>
<!-- 遮罩层 u-overlay 通过zindex 来层级显示-->
<u-overlay :show="carShow" z-index="9" @click="onClickCar" duration="100"></u-overlay>
</view>
<!-- 这里有一个遮罩在view外,所以总的来说就还要一个 盒子,这vue2规定只能有一个顶级盒子在template中,不能多个盒子并起来,
必须把里面的盒子包裹起来 -->
</template>
<script>
import {
mapState,
mapMutations,
mapGetters
} from "vuex"
export default {
name: "car-Layout",
data() {
return {
carShow:false,
};
},
props:{
type:{
type:String,
default:""
}
},
computed:{
...mapGetters(["carsList","totalPrice","totalNumValue"])
},
methods:{
...mapMutations(["setCarsList"]),
//确认支付
confirmPay(){
console.log("确认支付");
},
//清空购物车
clearCar(){
this.setCarsList(0);
},
//点击购物车,改变carShow,进而改变显示状态
onClickCar(){
this.carShow=!this.carShow;
},
//点击选好了,跳转到支付页面
goPaypage(){
uni.navigateTo({
url:"/pagesub/pageshop/paypage/paypage"
})
}
}
}
</script>
<style lang="scss" scoped>
.carlayout {
//有这个 content 下面的css始终不生效 太tmd 想爆粗口了 找了好久这个问题,最后发现是 class写错了 写成了 <view calss="carlayout">
position: relative; //相对定位,不脱离文档流
z-index: 10; //比 u-overlay 遮罩层 高就好
.goods {
border-bottom: 1rpx solid $border-color-light;
padding: 30rpx 30rpx 0;
border-radius: 20rpx 20rpx 0 0;
background-color: #fff;
.head {
@include flex-box();
color: $text-font-color-3;
padding: 25rpx 0;
.empty {
color: $brand-theme-color-aux;
}
}
.body {
height: 500rpx;
}
}
.content {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 30rpx;
height: 140rpx;
background: #fff;
.left {
@include flex-box();
.iconhover {
transform: scale(0.7); //鼠标点击后就缩小到0.8 然后松开鼠标就弹回 1
}
.icon {
width: 80rpx;
height: 80rpx;
background-color: #eee;
border-radius: 10rpx;
@include flex-box-set();
position: relative; //这里就是相对定位 就是为后面的num 固定到右上角的绝对定位做铺垫 num就是子级 这里的icon 就是父级
margin-right: 30rpx;
.num {
width: 36rpx;
height: 36rpx;
background: $brand-theme-color;
border-radius: 50%; //圆形
color: #fff;
position: absolute; //这里就是绝对定位 固定到icon右上角的绝对定位 num就是子级 icon 就是父级
right: -18rpx;
top: -18rpx;
@include flex-box-set();
font-size: 22rpx;
}
}
.price {
font-size: 28rpx;
.text {
font-size: 32rpx;
font-weight: bold;
}
}
}
.right {
.btn {
width: 210rpx;
height: 75rpx;
background: $brand-theme-color;
@include flex-box-set();
color: #fff;
border-radius: 10rpx;
&.disable {
opacity: 0.4; //表示透明度 变透明意思是disable了
}
}
}
}
.safeAreaBottom {
//这个是 用来设置ios的安全区域的,安卓是不能执行env(safe-area-inset-bottom) 这句话的
width: 100%;
height: env(safe-area-inset-bottom);
background: #fff;
}
}
//有这个 下面的css始终不生效
</style>
2 购物篮代码解析
2.1、shop就使用了组件
2.2、购物车中,右边的文字就是支付和选好了
选好了跳转到确认订单页面
支付就是在订单页面展现的
实现的是一个组件多个页面共用
3 确认订单页面的代码
3.1、页面组成
a、确认页面,存在外送 自提选项,主要差异:
外送和自提组件:delivery-layout
自提选项中,需要展示商家地址、 自提时间 还有商家的联系方式
外送选项中,主要就是收货地址 收货人
b、相同点 为 购物车中商品信息(goods-list组件)
c、另外还存在支付选项
支付宝和微信,默认选项为微信
d、购物车中,右边 为支付(在shop页面显示为选好了)
3.2 确认订单具体代码
html
<template>
<view class="paypage">
<!-- 确认订单,支付订单 -->
<!-- 配送方式 -->
<delivery-layout></delivery-layout>
<!-- 购物列表 -->
<view class="goodsList">
<goods-list></goods-list>
</view>
<!-- #ifndef MP-WEIXIN -->
<view class="payType">
<view class="box" :class="item.value==payDefValue ? 'active' : ''" v-for="item,index in payType"
:key="index" @click="clickBtn(item.value)">
<u-icon :name="item.icon" size="26" class="icon"
:color="item.value==payDefValue ? item.color :''"></u-icon>
<text class="font">{{item.name}}</text>
<!--
<u-icon name="weixin-fill" size="26" class="font"></u-icon>
<text class="font">微信</text>
-->
</view>
</view>
<!-- #endif -->
<view class="payTabbar">
<car-Layout type="pay"></car-Layout>
</view>
<view class="safeAreaBottom"></view>
<!-- 上面安全区域是设置为ios使用的,怕底部的区域被遮挡了 -->
</view>
</template>
<script>
export default {
data() {
return {
// #ifdef MP-WEIXIN
payDefValue: "wxpay",
// #endif
// #ifndef MP-WEIXIN
payDefValue: "alipy",
// #endif
payType: [{
name: "支付宝",
value: "alipy", //必须写这个值,后面要用到
icon: "zhifubao",
color: "#1578ff", //:color="item.value==payDefValue ? item.color :''"
},
{
name: "微 信",
value: "wxpay", //必须写这个值,后面要用到
icon: "weixin-fill",
color: "#04c15f", //:color="item.value==payDefValue ? item.color :''"
},
]
};
},
methods: {
//切换支付方式
clickBtn(type) {
this.payDefValue = type
}
}
}
</script>
<style lang="scss">
page {
background-color: $page-bg-color;
}
.paypage {
padding: 30rpx;
.goodsList {
margin-top: 30rpx;
}
.payType {
@include flex-box();
.box {
//box 就两个支付方式
width: 45%; //一个支付方式站49 剩下中间的2的空格
height: 75rpx;
background: #fff;
border-radius: 10rpx;
@include flex-box-set();
// filter: grayscale(100%); //滤镜效果 100%把颜色全滤掉 我们已经用了 :color="item.value==payDefValue ? item.color :''" 就不用滤镜了
border: 1rpx solid #fff;
.font {
padding-left: 10rpx;
}
}
//可以这样 当用text时,若用view + style 就不用下面的方式
.box:first-child.active {
border-color: #1578ff; //边框颜色
color: #1578ff;
}
.box:last-child.active {
border-color: #04c15f;
color: #04c15f;
}
}
.payTabbar {
position: fixed;
width: 100%;
bottom: 0;
left: 0
}
}
</style>
3.3 配送方式代码:
html
<template>
<view class="delivery">
<view class="headNav">外送</view>
<view class="body">
<view class="box" @click="goAddress">
<view class="left">收货地址</view>
<view class="center">
<view v-if="deliveryInfo.address">
<view class="detail">{{deliveryInfo.address}}</view>
<view class="userinfo">{{deliveryInfo.username + "-" + deliveryInfo.mobile}}</view>
</view>
<view class="addressTxt" v-else>请添加收货地址</view>
</view>
<view class="right">
<u-icon name="arrow-right" color="#999" size="18"></u-icon>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
name:"delivery-layout",
data() {
return {
deliveryInfo:{
address:"北京市海定区颐和园路",
username:"李晓峰",
mobile:null
}
}
},
methods:{
goAddress(){
uni.navigateTo({
url:"/pagesub/pageshop/address/addrlist"
})
}
}
}
</script>
<style lang="scss">
.delivery{
.headNav{
width: 100%;
height: 78rpx;
background: #fff;
@include flex-box-set();
color:$brand-theme-color;
border-radius: 15rpx 15rpx 0 0;
}
.body{
background: #fff;
padding:25rpx;
.box{
padding:40rpx 20rpx;
background: $page-bg-color;
border-radius: 10rpx;
font-size: 30rpx;
@include flex-box();
.center{
flex:1;
padding:0 30rpx;
font-size: 30rpx;
.userinfo{
padding-top:10rpx;
}
}
}
}
}
</style>
3.4 收货地址页面:
订单页面需要添加地址时,需跳转到这个页面
html
<template>
<view class="selfAddress">
<!-- 地址列表 -->
<view class="headTop">
<view class="title">地址簿</view>
<navigator class="addressBtn" url="/pagesub/pageshop/address/addredit">
+ 添加地址
</navigator>
</view>
<view class="list">
<view class="item" v-for="item,index in 3" :key="index">
<view class="head">
<view class="user">张三,18066668888</view>
<view class="select">
<u-button v-if="false" color="#EC544F" plain size="mini" text="默认地址"></u-button>
<u-button color="#666" v-else plain size="mini" text="设为默认"></u-button>
</view>
</view>
<view class="more">
云南省昆明市高新区XXX楼
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
};
}
}
</script>
<style lang="scss">
page{
background: $page-bg-color;
}
.selfAddress{
padding:30rpx;
.headTop{
@include flex-box();
font-size: 30rpx;
font-weight: bold;
.addressBtn{
border:1px solid #000;
border-radius: 50rpx;
padding:6rpx 15rpx;
}
}
.list{
padding-top:30rpx;
.item{
background: #fff;
padding:40rpx 20rpx;
margin-bottom: 30rpx;
border-radius: 15rpx;
.head{
@include flex-box();
font-weight: bold;
}
.more{
font-size: 28rpx;
color:$text-font-color-3;
padding-top:10rpx;
}
}
}
}
</style>
3.5 地址页面修改和添加
html
<template>
<view class="addressForm">
<!-- 地址编辑 -->
<u--form
labelPosition="top"
:model="addressForm"
:rules="addressRules"
labelWidth="100"
ref="uForm"
>
<u-form-item
label="姓名"
prop="username"
>
<u--input
v-model="addressForm.username"
placeholder="请输入姓名"
></u--input>
</u-form-item>
<u-form-item
label="联系电话"
prop="mobile"
>
<u--input
v-model="addressForm.mobile"
placeholder="请输入联系电话"
></u--input>
</u-form-item>
<u-form-item
label="详细地址"
prop="address"
>
<u--input
v-model="addressForm.address"
placeholder="请输入街道门牌号"
></u--input>
</u-form-item>
<u-form-item label="是否默认">
<u-switch v-model="addressForm.selected"
inactiveColor="#eee"
></u-switch>
</u-form-item>
<u-form-item></u-form-item>
<u-form-item>
<u-button type="primary" @click="onSubmit">提交</u-button>
</u-form-item>
</u--form>
</view>
</template>
<script>
export default {
data() {
return {
addressForm:{
username:"",
mobile:"",
address:"",
selected:false
},
addressRules:{
username:[
{
required: true,
message: '姓名是必填的',
trigger: ['blur', 'change']
},{
min: 2,
max: 8,
message: '长度在2-8个字符之间',
trigger: ['blur', 'change']
}
],
mobile:[
{
required: true,
message: '电话是必填的',
trigger: ['blur', 'change']
},{
validator: (rule, value, callback) => {
return uni.$u.test.mobile(value);
},
message: '手机号码不正确',
trigger: ['change','blur']
}
],
address:[
{
required: true,
message: '地址是必填的',
trigger: ['blur', 'change']
}
]
}
};
},
methods:{
onSubmit(){
this.$refs.uForm.validate().then(res => {
uni.$u.toast('校验通过')
}).catch(errors => {
uni.$u.toast('校验失败')
})
}
}
}
</script>
<style lang="scss">
.addressForm{
padding:30rpx;
}
</style>