buyer-confirm.vue 8.51 KB
<template>
  <LayoutApp :show-back="true" title="确认订单" :back-action="backAction">
    <div class="body">
      <AddressInfo :data="address" class="order-item" :show-tip="false"></AddressInfo>
      <ProductInfo :data="productDetail" class="product-info order-item"></ProductInfo>
      <Coupon class="order-item" v-if="couponList.length > 0" :data="orderDetail.recommendedCouponInfo"
              @click="onCouponClick"></Coupon>
      <Promotion class="order-item" v-if="promotionList.length > 0" :data="orderDetail.promotionTips"
                 @click="onPromotionClick"></Promotion>
      <BuyerFeeInfo :data="orderDetail.promotionFormulaList" v-if="orderDetail.promotionFormulaList"
                    class="order-item"></BuyerFeeInfo>
      <div class="tip2 order-item" v-if="orderDetail.specialTips">{{orderDetail.specialTips}}</div>
      <div class="tip order-item" v-if="orderDetail.damagesDesc" v-html="replaceBr(orderDetail.damagesDesc)"></div>
      <OrderInfo class="order-item" v-if="orderDetail.paymentWay" :pay-way="orderDetail.paymentWay"
                 :delivery-way="orderDetail.deliveryWay"></OrderInfo>
    </div>

    <OrderFooter class="footer" :amount="orderDetail.amount" @click="onPayAction"></OrderFooter>
  </LayoutApp>
</template>

<script>

import ProductInfo from './components/confirm/buyer-product';
import AddressInfo from './components/confirm/address';
import TitleComp from './components/confirm/title';
import BuyerFeeInfo from './components/confirm/buyer-fee';
import OrderInfo from './components/confirm/buyer-order-info';
import OrderFooter from './components/confirm/buyer-order-footer';
import Coupon from './components/confirm/buyer-coupon';
import Promotion from './components/confirm/buyer-promotion';
import { Types, UserType } from 'store/order/order-confirm';
import { get } from 'lodash';

import { createNamespacedHelpers, mapState } from 'vuex';

const { mapState: mapOrderState, mapActions: mapOrderAction, mapMutations: mapOrderMutations } = createNamespacedHelpers('order/orderConfirm');

export default {
  name: 'BuyOrderConfirm',
  props: ['productId', 'storageId'],
  data() {
    return {
      isActive: false
    };
  },
  components: {
    ProductInfo,
    AddressInfo,
    TitleComp,
    BuyerFeeInfo,
    OrderInfo,
    OrderFooter,
    Coupon,
    Promotion
  },
  activated() {
    this.init();
    this.isActive = true;
  },
  deactivated() {
    this.isActive = false;
  },
  beforeRouteLeave(to, from, next) {
    if (to.name !== 'address') {
      this[Types.CLEAR_BUY_STATUS]();
    }
    next();
  },
  computed: {
    ...mapOrderState(['address', 'orderDetail']),
    ...mapState({
      productDetail: state => {
        return {
          goodImg: get(state.product.selectedProductInfo, 'product.goods_list[0].image_list[0].image_url', ''),
          productName: get(state.product.selectedProductInfo, 'product.product_name', ''),
          colorName: get(state.product.selectedProductInfo, 'product.goods_list[0].color_name', ''),
          sizeName: get(state.product.selectedProductInfo, 'size.size_name', ''),
          goodPrice: get(state.product.selectedProductInfo, 'size.least_price', ''),
          skup: get(state.product.selectedProductInfo, 'size.skup', '')
        };
      }
    }),
    couponList() {
      return get(this.orderDetail, 'couponList', []);
    },
    promotionList() {
      return get(this.orderDetail, 'promotionList', []);
    },
  },
  watch: {
    address: {
      handler() {
        if (this.isActive) {
          this.compute();
        }
      },
      deep: true
    }
  },
  methods: {
    ...mapOrderAction(['fetchOrderAddress', 'fetchUserStatus', 'fetchPayList', 'fetchPayment', 'computeOrder', 'buyPayAction']),
    ...mapOrderMutations([Types.CHANGE_SELECT_COUPON_LIST, Types.CHANGE_SELECT_PROMOTION, Types.CLEAR_BUY_STATUS]),
    replaceBr(str) {
      return str ? str.replace(/\n/g, '<br />') : '';
    },
    onCouponClick() {
      let vm = this;

      this.couponListActionSheet = this.$createOrderCouponList({
        $props: {
          data: this.orderDetail.couponList,
        },
        onItemClickAction(item) {
          vm.onCouponItemClick(item);
        },
        onConfirmAction() {
          vm.couponListActionSheet.hide();
          vm.compute();
        },
        onCloseAction() {
          vm.compute();
        }
      }).show();
    },
    onCouponItemClick(item) {
      this[Types.CHANGE_SELECT_COUPON_LIST](item);
    },
    onPromotionClick() {
      let vm = this;

      this.promotionListActionSheet = this.$createOrderPromotionList({
        $props: {
          data: this.orderDetail.promotionList,
        },
        onItemClickAction(item) {
          vm.onPromotionItemClick(item);
        },
        onConfirmAction() {
          vm.promotionListActionSheet.hide();
          vm.compute();
        },
        onCloseAction() {
          vm.compute();
        }
      }).show();
    },
    onPromotionItemClick(item) {
      this[Types.CHANGE_SELECT_PROMOTION](item);
    },
    compute() {
      return this.computeOrder({
        skup: this.productDetail.skup,
        addressId: this.address?.address_id,
        couponCode: get(this.orderDetail, 'recommendedCouponInfo.coupon_code', ''),
        promotionId: get(this.orderDetail, 'promotionTips.promotionIds', '')
      }).then(result => {
        if (result.code !== 200) {
          this.$createToast({
            time: 1500,
            txt: result.message,
            type: 'txt'
          }).show();
        }
      });
    },
    checkAddress() {
      if (!this.address) {
        this.$createToast({
          time: 1500,
          txt: '请选择地址',
          type: 'txt'
        }).show();

        return false;
      }

      return true;
    },
    async onPayAction() {
      const user = await this.$yoho.auth();

      if (!user) {
        return;
      }

      const vm = this;

      if (!this.checkAddress()) {
        return;
      }

      await this.compute();

      const result = await this.buyPayAction({
        skup: this.productDetail.skup,
        addressId: this.address?.address_id,
        couponCode: get(this.orderDetail, 'recommendedCouponInfo.coupon_code', ''),
        promotionId: get(this.orderDetail, 'promotionTips.promotionIds', '')
      });

      if (!result?.data?.orderCode) {
        this.$createToast({
          time: 1500,
          txt: result?.message,
          type: 'txt'
        }).show();
        return;
      }

      this.$createOrderPayType({
        orderCode: result.data.orderCode,
        price: this.orderDetail.amount,
        desc: '金额',
        extra: JSON.stringify({
          type: UserType.buy,
          back: {
            name: 'ProductDetail',
            params: {
              productId: this.productId
            }
          },
          forward: {
            name: 'BuyPayOk',
            query: {
              productId: this.productId,
              orderCode: result.data.orderCode
            }
          }
        }),
        onCloseAction() {
          vm.onClose(result.data.orderCode);
        },
      }).show();
    },
    onClose(orderCode) {
      this.$router.replace({
        name: 'buyOrderDetail',
        params: {
          owner: UserType.buy,
          code: orderCode
        }
      });
    },
    backAction() {
      this.$router.replace({
        name: 'ProductDetail',
        params: {
          productId: this.productId
        }
      });
    },
    async init() {
      this.fetchOrderAddress({ tabType: UserType.buy });

      await this.$store.dispatch('product/getSelectedTradeProduct', {
        productId: this.productId,
        storageId: this.storageId
      });

      let user = await this.$sdk.getUser();

      if (user && user.uid) {
        const payInfo = await this.fetchPayment({ skup: this.productDetail.skup });

        if (payInfo?.code !== 200) {
          this.$createToast({
            time: 2000,
            txt: payInfo.message,
            type: 'txt'
          }).show();
        }

        if (this.address?.address_id) {
          await this.compute();
        }
      }
    },
  }
};
</script>

<style lang="scss" scoped>
.footer {
  position: absolute;
  bottom: 0;
  width: 100%;
  z-index: 100;
  background-color: white;
  border-top: 1px solid #eee;
}

.body {
  height: 100%;
  margin: 0 40px;
  padding-bottom: 180px;
  overflow-y: auto;
}

.title-class {
  margin-bottom: 30px;
}

.order-item {
  padding-top: 40px;
  padding-bottom: 40px;
  border-top: 1px solid #eee;
}

.product-info {
  height: 260px;
  display: flex;
}

.tip {
  font-size: 24px;
  color: #999;
}

.tip2 {
  font-size: 28px;
}

</style>