You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
608 lines
21 KiB
608 lines
21 KiB
<template>
|
|
<!-- Header Start -->
|
|
<header class="header">
|
|
<div class="logo-wrap">
|
|
<i class="icon-arrow-left-bold-box icli" @click="$router.go(-1)"></i>
|
|
<h1 class="title-color font-md">
|
|
商品結帳
|
|
<span class="font-sm content-color">({{ cartStore.cartNum }} 樣商品)</span>
|
|
</h1>
|
|
</div>
|
|
<div class="avatar-wrap" @click="$router.push('/home')">
|
|
<i class="icon-home icli"></i>
|
|
</div>
|
|
</header>
|
|
|
|
<!-- Header End -->
|
|
|
|
<!-- Main Start -->
|
|
<main class="main-wrap payment-page cart-page mb-xxl">
|
|
<div class="cartitem-list">
|
|
<div>訂單詳細</div>
|
|
<div></div>
|
|
</div>
|
|
<!-- Cart Item Section Start -->
|
|
<div class="cart-item-wrap pt-0">
|
|
<div class="swipe-to-show" v-for="item in items" :key="item.rec_id">
|
|
<div class="product-list media">
|
|
<a href="javascript:void(0);">
|
|
<img :src="`https://shop.h888.fun/${item.goods_thumb}`" alt="offer" />
|
|
</a>
|
|
<div class="media-body">
|
|
<a href="product.html" class="font-sm"> {{ item.goods_name }} </a>
|
|
<span class="price-color font-sm">${{ item.goods_price }}</span>
|
|
<div class="plus-minus">X {{ item.goods_number }}</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- Cart Item Section End -->
|
|
|
|
<!-- <button class="d-block btn-outline-grey" data-bs-toggle="offcanvas" data-bs-target="#add-card"
|
|
aria-controls="add-card">+ Add New Card</button> -->
|
|
|
|
<!-- Payment Section Start -->
|
|
<section class="payment-section">
|
|
<!-- Payment Method Accordian Start -->
|
|
<div class="accordion" id="accordionShipping">
|
|
<!-- Accordion Start -->
|
|
<div class="accordion-item">
|
|
<h2 class="accordion-header" id="headingTwo">
|
|
<button
|
|
class="accordion-button font-md title-color"
|
|
type="button"
|
|
data-bs-toggle="collapse"
|
|
aria-expanded="true"
|
|
data-bs-target="#shipping"
|
|
aria-controls="shipping"
|
|
>
|
|
配送方式
|
|
</button>
|
|
</h2>
|
|
<div
|
|
id="shipping"
|
|
class="accordion-collapse collapse show"
|
|
aria-labelledby="headingOne"
|
|
data-bs-parent="#accordionShipping"
|
|
>
|
|
<div class="accordion-body">
|
|
<ul class="filter-row">
|
|
<li
|
|
class="filter-col"
|
|
:class="{ active: shippingData.shipping_code === v.shipping_code }"
|
|
@click="selectShipping(v)"
|
|
v-for="(v, index) in shippingList"
|
|
:key="index"
|
|
>
|
|
{{ v.shipping_name }}
|
|
<span class="check"><img src="@/assets/icons/svg/active.svg" alt="active" /></span>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="shipping-data">
|
|
<div v-show="showExtra">
|
|
<template v-if="shippingData.shipping_code == 'shipping'">
|
|
<div>
|
|
<ul>
|
|
<li>收件人:{{ shippingData.extra_data.consignee }}</li>
|
|
<li>電 話:{{ shippingData.extra_data.tel }}</li>
|
|
<li>
|
|
地 址:{{
|
|
shippingData.extra_data.zipcode +
|
|
shippingData.extra_data.city +
|
|
shippingData.extra_data.district +
|
|
shippingData.extra_data.address
|
|
}}
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</template>
|
|
<template v-else-if="shippingData.shipping_code == 'ecpay'">
|
|
<div>
|
|
<ul v-if="shippingData.extra_data.type">
|
|
<li>
|
|
店 名:{{
|
|
logisticType[shippingData.extra_data.type] +
|
|
" " +
|
|
shippingData.extra_data.store_name
|
|
}}
|
|
</li>
|
|
<li>地 址:{{ shippingData.extra_data.store_address }}</li>
|
|
<li>電 話:{{ shippingData.extra_data.store_tel }}</li>
|
|
</ul>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
<div v-show="orderStore.shipping.shipping_id">
|
|
<van-button type="success" size="mini" @click="changeShipping">修改</van-button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- Accordion End -->
|
|
</div>
|
|
<div class="accordion" id="accordionExample">
|
|
<!-- Accordion Start -->
|
|
<div class="accordion-item">
|
|
<h2 class="accordion-header" id="headingOne">
|
|
<button
|
|
class="accordion-button font-md title-color"
|
|
type="button"
|
|
data-bs-toggle="collapse"
|
|
data-bs-target="#payment"
|
|
aria-expanded="true"
|
|
aria-controls="payment"
|
|
>
|
|
支付方式
|
|
</button>
|
|
</h2>
|
|
<div
|
|
id="payment"
|
|
class="accordion-collapse collapse show"
|
|
aria-labelledby="headingOne"
|
|
data-bs-parent="#accordionExample"
|
|
>
|
|
<div class="accordion-body">
|
|
<ul class="filter-row">
|
|
<li
|
|
class="filter-col"
|
|
:class="{ active: orderStore.payment.pay_code === 'cod' }"
|
|
v-if="orderStore.shipping.shipping_code === 'ecpay'"
|
|
@click="selectPayment({ pay_id: 0, pay_code: 'cod', pay_name: '貨到付款' })"
|
|
>
|
|
貨到付款
|
|
<span class="check"><img src="@/assets/icons/svg/active.svg" alt="active" /></span>
|
|
</li>
|
|
<li
|
|
class="filter-col"
|
|
:class="{ active: orderStore.payment.pay_code === v.pay_code }"
|
|
@click="selectPayment(v)"
|
|
v-for="(v, index) in paymentList"
|
|
:key="index"
|
|
>
|
|
<img class="payment-card" :src="v.logo" :alt="v.pay_name" />
|
|
{{ v.pay_name }}
|
|
<span class="check"><img src="@/assets/icons/svg/active.svg" alt="active" /></span>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- Accordion End -->
|
|
</div>
|
|
<!-- Payment Method Accordian End -->
|
|
<div class="accordion" id="accordionShipping">
|
|
<!-- Accordion Start -->
|
|
<div class="accordion-item">
|
|
<h2 class="accordion-header" id="headingTwo">
|
|
<button
|
|
class="accordion-button font-md title-color"
|
|
type="button"
|
|
data-bs-toggle="collapse"
|
|
aria-expanded="true"
|
|
data-bs-target="#bonus"
|
|
aria-controls="bonus"
|
|
>
|
|
優惠代碼
|
|
</button>
|
|
</h2>
|
|
<div
|
|
id="bonus"
|
|
class="accordion-collapse collapse show"
|
|
aria-labelledby="headingOne"
|
|
data-bs-parent="#accordionBonus"
|
|
>
|
|
<div class="accordion-body">
|
|
<div class="input-box">
|
|
<input
|
|
type="text"
|
|
placeholder="請輸入優惠代碼"
|
|
v-model="bonus.sn"
|
|
class="form-control"
|
|
/>
|
|
</div>
|
|
<div class="bonus-desc">
|
|
{{ bonus.name }}
|
|
<span v-if="bonus.number > 0"
|
|
>數量: {{ bonus.number }} 剩下: {{ bonus.remain }} 張</span
|
|
>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- Accordion End -->
|
|
</div>
|
|
</section>
|
|
<!-- Payment Section End -->
|
|
|
|
<!-- Order Detail Start -->
|
|
<section class="order-detail">
|
|
<h3 class="title-2">訂單詳細</h3>
|
|
<!-- Product Detail Start -->
|
|
<ul>
|
|
<li>
|
|
<span>金額</span>
|
|
<span>${{ detail.sum_amount }}</span>
|
|
</li>
|
|
<li>
|
|
<span>折扣</span>
|
|
<span class="font-theme">-${{ detail.discount }}</span>
|
|
</li>
|
|
<!-- <li>
|
|
<span>折價卷</span>
|
|
<a href="javascript:void(0);" class="font-danger">Apply Coupon</a>
|
|
</li> -->
|
|
<li v-show="detail.pay_fee > 0">
|
|
<span>金流手續費</span>
|
|
<span>{{ detail.pay_fee }}</span>
|
|
</li>
|
|
<li v-show="detail.shipping_fee > 0">
|
|
<span>運費</span>
|
|
<span>{{ detail.shipping_fee }}</span>
|
|
</li>
|
|
|
|
<li>
|
|
<span>總金額</span>
|
|
<span>${{ detail.total_amount }}</span>
|
|
</li>
|
|
</ul>
|
|
<!-- Product Detail End -->
|
|
</section>
|
|
<!-- Order Detail End -->
|
|
</main>
|
|
<!-- Main End -->
|
|
<!-- Footer Start -->
|
|
<footer class="footer-wrap footer-button">
|
|
<!-- <el-button type="primary" color="#0baf9a" disabled ></el-button> -->
|
|
<van-button type="success" color="#0baf9a" @click="handleFinish" block :loading="btnLoading"
|
|
>完成訂單</van-button
|
|
>
|
|
</footer>
|
|
<!-- Footer End -->
|
|
</template>
|
|
|
|
<script setup>
|
|
import _ from "lodash";
|
|
import { ref, reactive, onMounted, computed, watch } from "vue";
|
|
import { useCartStore } from "@/store/Cart";
|
|
import { useOrderStore } from "@/store/Order";
|
|
import { storeToRefs } from "pinia";
|
|
|
|
import { showToast } from "vant";
|
|
|
|
import { addOrder } from "@/services/order";
|
|
|
|
import { getPayments } from "@/services/payment";
|
|
import { getShippings, getUserDefaultCvs } from "@/services/shipping";
|
|
import { getUserDefaultAddress } from "@/services/user";
|
|
import { checkBonusSn } from "@/services/bonus";
|
|
|
|
import router from "@/router";
|
|
|
|
import linepayicon from "/src/assets/icons/png/linepay.png";
|
|
import mastericon from "/src/assets/icons/png/mastercard1.png";
|
|
|
|
const cartStore = useCartStore();
|
|
const orderStore = useOrderStore();
|
|
|
|
const { goodsItems: items } = storeToRefs(orderStore);
|
|
|
|
const order = reactive({
|
|
payment: 0,
|
|
shipping: 0,
|
|
goods: [],
|
|
});
|
|
|
|
const paymentList = ref([]);
|
|
|
|
const shippingList = ref([]);
|
|
|
|
const logisticType = {
|
|
1: "711",
|
|
2: "全家",
|
|
3: "萊爾富",
|
|
4: "OK",
|
|
};
|
|
|
|
const btnLoading = ref(false);
|
|
|
|
onMounted(async () => {
|
|
cartToOrder();
|
|
|
|
let res1 = await getPayments();
|
|
if (res1.code === 200) {
|
|
paymentList.value = res1.data;
|
|
}
|
|
|
|
let res2 = await getShippings();
|
|
if (res2.code === 200) {
|
|
shippingList.value = res2.data;
|
|
}
|
|
});
|
|
|
|
const bonus = reactive({
|
|
name: "沒有優惠劵",
|
|
sn: "",
|
|
number: 0,
|
|
remain: 0,
|
|
});
|
|
//檢查優惠代碼
|
|
|
|
const handleCheckBonusSn = async () => {
|
|
if (bonus.sn.length !== 10) {
|
|
bonus.name = "沒有優惠劵";
|
|
bonus.number = 0;
|
|
bonus.remain = 0;
|
|
|
|
orderStore.discount = 0;
|
|
return;
|
|
}
|
|
|
|
let res = await checkBonusSn(bonus.sn);
|
|
|
|
if (res.code === 200) {
|
|
orderStore.bonus_sn = bonus.sn;
|
|
bonus.name = res.data.type_name;
|
|
bonus.remain = res.data.remain_number;
|
|
bonus.number = res.data.bonus_number;
|
|
//如果res.data最後是% 就相剩,沒有%就直接扣
|
|
if (res.data.type_money.slice(-1) === "%") {
|
|
orderStore.discount = ((100 - res.data.type_money.slice(0, -1)) / 100) * orderStore.sum_amount;
|
|
} else {
|
|
orderStore.discount = res.data;
|
|
}
|
|
} else {
|
|
showToast(res.data);
|
|
}
|
|
};
|
|
|
|
watch(() => bonus.sn, _.debounce(handleCheckBonusSn, 500));
|
|
|
|
//將購物車商品資料轉換成訂單商品資料
|
|
const cartToOrder = () => {
|
|
if (cartStore.cartItems.length === 0) {
|
|
showToast("購物車中沒有商品,請先加入商品");
|
|
return router.push("/card");
|
|
}
|
|
items.value = cartStore.cartItems;
|
|
|
|
//檢查商品是否有goods_id為1的商品,有的話則設定order的extension_code為slashcard
|
|
let is_slashcard = items.value.find((item) => item.goods_id === 1);
|
|
|
|
if (is_slashcard) {
|
|
orderStore.extension_code = "slashcard";
|
|
}
|
|
};
|
|
|
|
// 物流
|
|
const selectShipping = async (value) => {
|
|
if (shippingData.value.shipping_code === value.shipping_code) return;
|
|
|
|
switch (value.shipping_code) {
|
|
case "shipping":
|
|
let resAddr = await getUserDefaultAddress();
|
|
console.log(resAddr.data);
|
|
|
|
if (resAddr.code === 200) {
|
|
orderStore.shipping = {
|
|
shipping_code: value.shipping_code,
|
|
shipping_id: value.shipping_id,
|
|
shipping_fee: 0,
|
|
extra_data: {
|
|
zipcode: resAddr.data.zipcode,
|
|
address: resAddr.data.address,
|
|
city: resAddr.data.city,
|
|
district: resAddr.data.district,
|
|
consignee: resAddr.data.consignee,
|
|
tel: resAddr.data.tel,
|
|
},
|
|
};
|
|
} else {
|
|
orderStore.shipping = {
|
|
shipping_code: value.shipping_code,
|
|
shipping_id: value.shipping_id,
|
|
shipping_fee: 0,
|
|
extra_data: {},
|
|
};
|
|
router.push("/address?from=order");
|
|
}
|
|
break;
|
|
case "ecpay":
|
|
let res = await getUserDefaultCvs();
|
|
if (res.code === 200) {
|
|
orderStore.shipping = {
|
|
shipping_code: value.shipping_code,
|
|
shipping_id: value.shipping_id,
|
|
shipping_fee: 0,
|
|
extra_data: {
|
|
type: res.data.type,
|
|
store_id: res.data.store_id,
|
|
store_name: res.data.store_name,
|
|
store_address: res.data.store_address,
|
|
store_tel: res.data.store_tel,
|
|
},
|
|
};
|
|
} else {
|
|
orderStore.shipping = {
|
|
shipping_code: value.shipping_code,
|
|
shipping_id: value.shipping_id,
|
|
shipping_fee: 0,
|
|
extra_data: {},
|
|
};
|
|
router.push("/order/shipping");
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
};
|
|
|
|
const changeShipping = () => {
|
|
switch (shippingData.value.shipping_code) {
|
|
case "ecpay":
|
|
router.push("/order/shipping");
|
|
break;
|
|
case "shipping":
|
|
router.push("/address?from=order");
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
};
|
|
|
|
const shippingData = computed(() => {
|
|
return orderStore.shipping;
|
|
});
|
|
|
|
// 顯示物流額外資訊
|
|
const showExtra = computed(() => {
|
|
let is_empty = _.isEmpty(orderStore.shipping.extra_data);
|
|
if (is_empty) {
|
|
return false;
|
|
} else {
|
|
return true;
|
|
}
|
|
});
|
|
|
|
// 金流
|
|
const selectPayment = (value) => {
|
|
orderStore.payment = {
|
|
pay_code: value.pay_code,
|
|
pay_id: value.pay_id,
|
|
pay_fee: 0,
|
|
};
|
|
};
|
|
|
|
//完成訂單
|
|
const handleFinish = async () => {
|
|
let order = orderStore.$state;
|
|
|
|
if (!order.shipping.shipping_id) {
|
|
return showToast("請選擇配送方式");
|
|
}
|
|
if (order.payment.pay_id === null) {
|
|
return showToast("請選擇付款方式");
|
|
}
|
|
if (JSON.stringify(order.shipping.extra_data) == "{}") {
|
|
return showToast("請選擇配送地址");
|
|
}
|
|
if (order.goodsItems.length === 0) {
|
|
showToast("購物車中沒有商品,請先加入商品");
|
|
router.push("/card");
|
|
}
|
|
order = { ...order, goods_amount: orderStore.sum_amount, order_amount: orderStore.total_amount };
|
|
btnLoading.value = true;
|
|
|
|
try {
|
|
let res = await addOrder(order);
|
|
|
|
if (res.code === 200) {
|
|
// 清空購物車
|
|
cartStore.clearCart();
|
|
orderStore.$reset();
|
|
// window.location.href = res.data.info.paymentUrl.web
|
|
// console.log('resdata',res.data)
|
|
return router.replace({
|
|
name: "Payment",
|
|
query: {
|
|
order_sn: res.data.order_sn,
|
|
pay_code: res.data.pay_code,
|
|
},
|
|
});
|
|
}
|
|
} catch (err) {
|
|
btnLoading.value = false;
|
|
return
|
|
}
|
|
|
|
btnLoading.value = false;
|
|
return showToast("操作失敗");
|
|
};
|
|
|
|
// 計算訂單詳細
|
|
const detail = computed(() => {
|
|
let sum_amount = orderStore.sum_amount;
|
|
let discount = orderStore.discount;
|
|
let shipping_fee = orderStore.shipping.shipping_fee;
|
|
let pay_fee = orderStore.payment.pay_fee;
|
|
let total_amount = orderStore.total_amount;
|
|
return { sum_amount, discount, shipping_fee, pay_fee, total_amount };
|
|
});
|
|
</script>
|
|
|
|
<style lang="less" scoped>
|
|
.cart-item-wrap {
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.delete-button {
|
|
i {
|
|
font-size: 20px;
|
|
color: #ffffff;
|
|
}
|
|
}
|
|
|
|
.cartitem-list {
|
|
width: 100%;
|
|
border: 1px #cacaca solid;
|
|
border-radius: 5px;
|
|
height: 45px;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
|
|
div:nth-child(1) {
|
|
color: red;
|
|
padding-left: 10px;
|
|
}
|
|
|
|
div:nth-child(2) {
|
|
padding-right: 10px;
|
|
}
|
|
}
|
|
|
|
.price-color {
|
|
color: red;
|
|
}
|
|
|
|
.filter-row {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
justify-content: space-around;
|
|
|
|
.filter-col {
|
|
width: 40%;
|
|
}
|
|
}
|
|
|
|
// 物流
|
|
.shipping-data {
|
|
width: 100%;
|
|
display: flex;
|
|
padding: 10px 15px;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
div:nth-child(1) {
|
|
flex: 1;
|
|
width: 100%;
|
|
// padding: 10px 0;
|
|
// border-bottom: 1px #cacaca solid;
|
|
}
|
|
div:nth-child(2) {
|
|
width: 40px;
|
|
i {
|
|
font-size: 20px;
|
|
color: #cacaca;
|
|
}
|
|
}
|
|
}
|
|
|
|
.footer-wrap {
|
|
background-color: initial;
|
|
}
|
|
|
|
.bonus-desc {
|
|
padding: 0 10px;
|
|
}
|
|
</style>
|