【vue3.0】22.0 某东到家( 廿二)——订单商品列表代码拆分和确认订单弹窗
目前src\views\orderConfirmation\OrderConfirmation.vue已有超过250行代码。这里将此组件进行拆分。
src\views\orderConfirmation\TopArea.vue
<template>
<div class="top">
<div class="top__bgcolor" />
<div class="top__header">
<div class="top__header__back" @click="handleBackClick">
<i class="custom-icon custom-icon-back"></i>
</div>
<span>确认订单</span>
</div>
<div class="top__receiver">
<div class="top__receiver__title">收货地址</div>
<div class="top__receiver__address">
西安一二三大学四五六科技园2号楼
</div>
<div class="top__receiver__info">
<span class="top__receiver__info__name">张三(先生)</span>
<span class="top__receiver__info__phone">18012341234</span>
</div>
<div class="top__receiver__icon">
<i class="custom-icon custom-icon-back"></i>
</div>
</div>
</div>
</template>
<script>
import { useRouter } from 'vue-router' // 路由跳转方法
export default {
name: 'TopArea',
setup() {
const router = useRouter()
const handleBackClick = () => {
router.back()
}
return {
handleBackClick
}
}
}
</script>
<style lang="scss" scoped>
@import '@/style/viriables.scss';
.top {
position: relative;
height: 1.96rem;
background-size: 100% 1.59rem;
/* 渐变轴为0度,相当于从下到上,
高度4%位置从rgba(0, 145, 255, 0) 开始渐变
到高度50%位置的蓝色(#0091ff)结束 */
background-image: linear-gradient(
0deg,
rgba(0, 145, 255, 0) 4%,
$btn-bg-color 50%
);
background-repeat: no-repeat;
&__header {
position: relative;
padding-top: 0.26rem;
line-height: 0.24rem;
color: $bg-color;
text-align: center;
font-size: 0.16rem;
&__back {
position: absolute;
font-size: 0.22rem;
left: 0.18rem;
}
}
&__receiver {
position: absolute;
left: 0.18rem;
right: 0.18rem;
bottom: 0rem;
height: 1.11rem;
background: $bg-color;
border-radius: 0.04rem;
&__title {
line-height: 0.22rem;
padding: 0.16rem 0 0.14rem 0.16rem;
font-size: 0.16rem;
color: $content-font-color;
}
&__address {
line-height: 0.2rem;
padding: 0 0.4rem 0 0.16rem;
font-size: 0.16rem;
color: $content-font-color;
}
&__info {
padding: 0.06rem 0 0 0.16rem;
&__name &__phone {
margin-right: 0.1rem;
line-height: 0.18rem;
font-size: 0.12rem;
color: $content-font-color;
}
}
&__icon {
//旋转180度
transform: rotate(180deg);
position: absolute;
right: 0.16rem;
top: 0.53rem;
font-size: 0.16rem;
color: $medium-font-color;
}
}
}
</style>
新建src\views\orderConfirmation\ProductList.vue
<template>
<div class="products">
<div class="products__title">{{ shopName }}</div>
<div class="products__wrapper">
<div class="products__list">
<template v-for="item in productList" :key="item._id">
<div class="products__item" v-if="item.count > 0">
<img class="products__item__img" :src="item.imgUrl" />
<div class="products__item__detail">
<h4 class="products__item__title">{{ item.name }}</h4>
<p class="products__item__price">
<span>
<span class="products__item__yen"> ¥ </span>
{{ item.price }}×{{ item.count }}
</span>
<span class="products__item__total">
<span class="products__item__yen"> ¥ </span>
{{ (item.price * item.count).toFixed(2) }}
</span>
</p>
</div>
</div>
</template>
</div>
</div>
</div>
</template>
<script>
import { useCommonCartEffect } from '@/effects/cartEffects'
import { useRoute } from 'vue-router' // 路由跳转方法
export default {
name: 'ProductList',
setup() {
const route = useRoute()
const shopId = route.params.shopId // 店铺id
const { shopName, productList } = useCommonCartEffect(shopId)
return {
shopName,
productList,
}
},
}
</script>
<style lang="scss" scoped>
@import '@/style/viriables.scss';
@import '@/style/mixins.scss';
.products {
margin: 0.16rem 0.18rem 0.2rem 0.18rem;
background: $bg-color;
&__title {
padding: 0.16rem;
font-size: 0.16rem;
color: $content-font-color;
}
// list外层的wrapper容器
&__wrapper {
overflow-y: scroll;
position: absolute;
margin: 0 0.18rem;
left: 0;
right: 0;
bottom: 0.6rem;
top: 2.6rem;
}
&__list {
background: $bg-color;
}
&__item {
position: relative;
display: flex;
padding: 0 0.16rem 0.16rem 0.16rem;
&__img {
width: 0.46rem;
height: 0.46rem;
margin-right: 0.16rem;
}
// 配合解决超出长度以省略号显示而不会出现换行
&__detail {
overflow: hidden;
flex: 1;
}
&__title {
margin: 0;
line-height: 0.2rem;
font-size: 0.14rem;
color: $content-font-color;
// 超出长度以省略号显示而不会出现换行
@include ellipsis;
}
&__price {
display: flex;
margin: 0.06rem 0 0 0;
line-height: 0.2rem;
font-size: 0.14rem;
color: $height-light-font-color;
}
&__total {
text-align: right;
color: $dark-font-color;
flex: 1;
}
&__yen {
font-size: 0.12rem;
}
}
}
</style>
新增src\views\orderConfirmation\Order.vue
<template>
<div class="order">
<div class="order__price">
实付金额 ¥<b>{{ calculations.totalPrice }}</b>
</div>
<div class="order__btn">
<!-- <router-link :to="{ path: `/orderConfirmation/${shopId}` }"> -->
提交订单
<!-- </router-link> -->
</div>
</div>
</template>
<script>
// import { ref } from 'vue'
import { useCommonCartEffect } from '@/effects/cartEffects'
import { useRoute } from 'vue-router' // 路由跳转方法
export default {
name: 'Order',
setup() {
const route = useRoute()
const shopId = route.params.shopId // 店铺id
const { calculations } = useCommonCartEffect(shopId)
return { calculations }
},
}
</script>
<style lang="scss" scoped>
@import '@/style/viriables.scss';
.order {
position: absolute;
left: 0;
right: 0;
bottom: 0;
display: flex;
box-sizing: border-box; //往内塞入border
line-height: 0.49rem;
height: 0.49rem;
border-top: 0.01rem solid $content-bg-color;
background: $bg-color;
&__price {
flex: 1;
text-indent: 0.24rem;
font-size: 0.14rem;
color: $content-font-color;
}
&__btn {
width: 0.98rem;
background-color: #4fb0f9;
text-align: center;
color: $bg-color;
font-size: 0.14rem;
// 去掉a标签的下划线
a {
color: $bg-color;
text-decoration: none; //去掉文本修饰
}
}
}
</style>
修改src\views\orderConfirmation\OrderConfirmation.vue
<template>
<div class="wrapper">
<top-area />
<product-list />
<order />
</div>
</template>
<script>
// import { ref } from 'vue'
import TopArea from '@/views/orderConfirmation/TopArea'
import ProductList from '@/views/orderConfirmation/ProductList'
import Order from '@/views/orderConfirmation/Order'
export default {
name: 'OrderConfirmation',
components: { TopArea, ProductList, Order },
}
</script>
<style lang="scss" scoped>
.wrapper {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: #eee;
overflow-y: scroll; //防止超出屏幕
}
</style>
最终效果一致。
增加一个确认支付的弹窗
修改src\views\orderConfirmation\Order.vue
<template>
<div class="order">
......
</div>
<div class="mask">
<div class="mask__content">
<div class="mask__content__title">确认离开收银台</div>
<p>请尽快完成支付,否则将被取消</p>
<div>
<div class="mask__content__btn">取消订单</div>
<div class="mask__content__btn">确认支付</div>
</div>
</div>
</div>
</template>
<script>
......
</script>
<style lang="scss" scoped>
@import '@/style/viriables.scss';
.order {
......
}
.mask {
position: absolute;
left: 0;
right: 0;
bottom: 0;
top: 0;
z-index: 1;
background: rgba(0, 0, 0, 0.5);
&__content {
position: absolute;
top: 50%;
left: 50%;
width: 3rem;
height: 1.56rem;
transform: translate(-50%, -50%);
background: #fff;
border-radius: 0.04rem;
&__title {
margin: 0.24rem 0 0 0;
font-size: 0.18rem;
color: #333;
text-align: center;
}
}
}
</style>
进一步完善样式:
<template>
<div class="order">
......
</div>
<div class="mask">
<div class="mask__content">
<div class="mask__content__title">确认离开收银台</div>
<p>请尽快完成支付,否则将被取消</p>
<div class="mask__content__btns">
<div class="mask__content__btn mask__content__btn--first">取消订单</div>
<div class="mask__content__btn mask__content__btn--second">
确认支付
</div>
</div>
</div>
</div>
</template>
<script>
......
</script>
<style lang="scss" scoped>
@import '@/style/viriables.scss';
.order {
......
}
.mask {
position: absolute;
left: 0;
right: 0;
bottom: 0;
top: 0;
z-index: 1;
background: rgba(0, 0, 0, 0.5);
&__content {
position: absolute;
top: 50%;
left: 50%;
width: 3rem;
height: 1.56rem;
transform: translate(-50%, -50%);
background: #fff;
border-radius: 0.04rem;
text-align: center;
&__title {
margin: 0.24rem 0 0 0;
font-size: 0.18rem;
color: #333;
}
&__desc {
margin: 0.08rem 0 0 0;
font-size: 0.14rem;
color: #666;
}
&__btns {
display: flex;
margin: 0.24rem 0.58rem;
}
&__btn {
flex: 1;
width: 0.8rem;
line-height: 0.32rem;
border: 0.01rem solid #4fb0f9;
border-radius: 0.16rem;
font-size: 0.14rem;
&--first {
margin-right: 0.12rem;
color: #4fb0f9;
}
&--second {
margin-left: 0.12rem;
color: #fff;
background: #4fb0f9;
}
}
}
}
</style>
完善按钮逻辑,进入fastmock增加一个post接口
/api/createOrder
/**
* 输入
* conten-type:json
* body:{
addressId:“xxx”//收货地址 id
shopId:""//商店id
shopName:"某什么码1",
isCanceled:false,//订单是否被取消了
products:[
{
id:"xxx",//商品id
num:6//商品数量
},
{
id:"xxx",//商品id
num:6//商品数量
},
]
}
**/
{
"code": 200,
"data": { _id: '1',},
"desc": "成功"
}
修改src\views\orderConfirmation\Order.vue
<template>
<div class="order">
......
</div>
<div class="mask">
<div class="mask__content">
<div class="mask__content__title">确认离开收银台</div>
<p>请尽快完成支付,否则将被取消</p>
<div class="mask__content__btns">
<div
class="mask__content__btn mask__content__btn--first"
@click="handleCancelOrder"
>
取消订单
</div>
<div
class="mask__content__btn mask__content__btn--second"
@click="handleConfirmOrder"
>
确认支付
</div>
</div>
</div>
<Toast v-if="show" :message="message" />
</div>
</template>
<script>
// import { ref } from 'vue'
import { useCommonCartEffect } from '@/effects/cartEffects'
import { useRoute, useRouter } from 'vue-router' // 路由跳转方法
import { post } from '@/utils/request'
import Toast, { useToastEffect } from '@/components/Toast/Toast'
export default {
name: 'Order',
components: {
Toast,
},
setup() {
const route = useRoute()
// 获取路由实例
const router = useRouter()
const shopId = route.params.shopId // 店铺id
const { shopName, calculations, productList } = useCommonCartEffect(shopId)
const handleCancelOrder = () => {}
const { show, message, toastMsg } = useToastEffect()
const handleConfirmOrder = async () => {
try {
console.log('productList:')
console.log(productList)
const products = []
for (const i in productList.value) {
const product = productList.value[i]
products.push({ id: product._id, num: product.count })
}
console.log('products:')
console.log(products)
const resultData = await post('/api/createOrder', {
addressId: 'xxx', // 收货地址 id
shopId: shopId, // 商店id
shopName: shopName.value,
isCanceled: false, // 订单是否被取消了
products: products,
})
console.log('post /api/createOrder:')
console.log(resultData)
if (resultData?.code === 200) {
router.push({ name: 'Home' })
} else {
toastMsg('订单提交失败!')
}
} catch (e) {
toastMsg('请求失败!')
}
}
return {
show,
message,
calculations,
handleCancelOrder,
handleConfirmOrder,
}
},
}
</script>
<style lang="scss" scoped>
......
</style>
发表评论 (审核通过后显示评论):