Sfoglia il codice sorgente

下单虚拟商品

lifanagju_citu 4 mesi fa
parent
commit
1cdf09b0e3

+ 85 - 6
src/views/mall/components/confirm_order/confirm.vue

@@ -1,8 +1,20 @@
 <template>
   <div>
     <!-- 头部地址选择【配送地址】【自提地址】 -->
-    <AddressSelection v-model="addressState" class="addressBox" />
+    <AddressSelection v-if="!goodsType" v-model="addressState" class="addressBox" />
     
+    <!-- 表头 -->
+    <div class="d-flex px-6 mb-2">
+      <div class="img">小图</div>
+      <div class="headerTitleList">
+        <div class="title">商品名称</div>
+        <div class="skuString">商品属性</div>
+        <div class="price">单价</div>
+        <div class="buyNum">数量</div>
+        <div class="subtotal">小计</div>
+      </div>
+    </div>
+
     <!-- 购买的商品信息 -->
     <v-card class="goodsListBox mb-3 pa-3">
       <s-goods-item
@@ -40,6 +52,10 @@
         <!-- 门店自提时,需要填写姓名和手机号 -->
       </div>
       
+      <div v-if="goodsType" class="mt-5" style="width: 800px;">
+        <TextUI v-model="email" :item="emailObj"></TextUI>
+      </div>
+
       <div class="mt-5">
         <v-text-field
           v-model="state.orderPayload.remark"
@@ -74,6 +90,9 @@
   import { spaces } from '@/utils/index.js'
   import { getTradeConfig, createOrder, settlementOrder } from '@/api/mall/trade'
   import Snackbar from '@/plugins/snackbar'
+  import { isNumber } from '@/utils/is'
+  import { checkCompanyEmail } from '@/utils/validate'
+  import TextUI from '@/components/FormUI/TextInput'
   const emit = defineEmits(['orderCreated'])
   const props = defineProps({
     data: {
@@ -82,6 +101,9 @@
     }
   })
 
+  const goodsType = ref(0)
+  const email = ref('') // 如果商品spu的type不是0(不是普通商品)则要填这个邮箱
+
   const state = reactive({
     orderPayload: {},
     orderInfo: {
@@ -94,7 +116,23 @@
     // ========== 积分 ==========
     pointStatus: false, //是否使用积分
   });
-  
+  const emailObj = {
+    type: 'text',
+    key: 'email',
+    value: '',
+    label: '接收邮箱 *(虚拟商品会发送到填写的邮箱,填写错误的邮箱会导致接收失败,请注意检查!)',
+    rules: [
+      value => {
+        if (value) return true
+        return '请输入邮箱'
+      },
+      value => {
+        if (checkCompanyEmail(value)) return true
+        return '请输入正确的邮箱'
+      }
+    ],
+  }
+
   // 检测支付环境
   // const payState = reactive({
   //   orderType: 'goods', // 订单类型; goods - 商品订单, recharge - 充值订单
@@ -115,10 +153,17 @@
   
   watch(
     () => props.data, 
-    (newVal) => {
+    async (newVal) => {
       if (newVal) {
         state.orderPayload = JSON.parse(newVal);
-        tradeConfig()
+        // 是否是普通快递商品
+        goodsType.value = state.orderPayload && isNumber(state.orderPayload?.goodsType-0) ? state.orderPayload.goodsType-0 : 0
+        
+        if (!goodsType.value) tradeConfig()
+        else {
+          // addressState.value.deliveryType = null
+          getOrderInfo()
+        }
       }
     },
     { immediate: true },
@@ -155,12 +200,20 @@
       Snackbar.warning('请选择收货地址')
       return;
     }
+    if (goodsType.value && !email.value) {
+      Snackbar.warning('请填写邮箱')
+      return;
+    }
+    if (goodsType.value && !checkCompanyEmail(email.value)) {
+      Snackbar.warning('请输入正确的邮箱')
+      return;
+    }
     submitOrder()
   }
   
   // 创建订单&跳转
   async function submitOrder() {
-    const data = await createOrder({
+    let query = {
       items: state.orderPayload.items,
       couponId: state.orderPayload.couponId,
       remark: state.orderPayload.remark,
@@ -174,7 +227,10 @@
       combinationHeadId: state.orderPayload.combinationHeadId,
       seckillActivityId: state.orderPayload.seckillActivityId,
       pointActivityId: state.orderPayload.pointActivityId,
-    });
+    }
+    if (email.value) query = Object.assign(query, { receiverExtend: { email: email.value} })
+
+    const data = await createOrder(query)
     if (!data.payOrderId && data.payOrderId > 0) return
     emit('orderCreated', data.payOrderId, data.id) // 更新购物车列表,如果来自购物车
     // payImmediately(data.payOrderId)
@@ -240,4 +296,27 @@
       color: #7a7a7a;
     }
   }
+  .img {
+    width: 92px
+  }
+  .headerTitleList {
+    width: 100%;
+    display: flex;
+    justify-content: space-between;
+    .title {
+      width: 30%;
+    }
+    .skuString {
+      width: 25%;
+    }
+    .price {
+      width: 15%;
+    }
+    .buyNum {
+      width: 10%;
+    }
+    .subtotal {
+      width: 15%;
+    }
+  }
 </style>

+ 4 - 5
src/views/mall/components/confirm_order/index.vue

@@ -30,7 +30,7 @@ import Confirm from '@/plugins/confirm'
 import Snackbar from '@/plugins/snackbar'
 import { useI18n } from '@/hooks/web/useI18n'
 import { useRouter } from 'vue-router'; const router = useRouter()
-import { computed, ref } from 'vue'
+import { ref } from 'vue'
 import confirm from './confirm.vue'
 import pay from './pay.vue'
 const { t } = useI18n()
@@ -60,19 +60,18 @@ const orderCreated = (id, order) => {
   orderId.value = order
   showPay.value = true
 }
-const confirmWord = computed(() => {
-  return orderId.value ? '立即购买' : '立即支付'
-})
+const confirmWord = ref('立即支付') // '立即购买' : '立即支付'
 
 let closeConfirm = false // 关闭路由拦截
 
 const paySuccess = (e) => {
   closeConfirm = true
-  router.replace({ path: '/mall/payOver', query: { price: e.price, spuId: id, orderId: orderId.value } })
+  router.replace({ path: '/mall/payOver', query: { price: e.price, orderId: orderId.value } })
 }
 const payCancel = () => {
   Snackbar.warning('您已取消支付!')
   showPay.value = false
+  closeConfirm = true
   setTimeout(() => { router.replace({ path: '/mall/user/order', query: { tab: 0 } }) }, 500);
 }
 

+ 5 - 42
src/views/mall/components/details.vue

@@ -78,15 +78,6 @@
   <!-- 快速登录 -->
   <loginPage v-if="showLogin" @loginSuccess="loginSuccess" @close="loginClose"></loginPage>
 
-  <!-- 结算 -->
-  <!-- <CtDialog :visible="showSettlement" titleClass="text-h6" :widthType="3" title="订单提交" submitText="提交支付" @submit="handleSubmit" @close="handleClose">
-    <confirm ref="confirmRef" :data="skuInfo" @orderCreated="orderCreated"></confirm>
-  </CtDialog> -->
-  
-  <!-- 支付 -->
-  <!-- <CtDialog :visible="showPay" titleClass="text-h6" :widthType="3" title="收银台" :footer="false" @close="payCancel">
-    <pay ref="payRef" :id="payOrderId" @paySuccess="paySuccess"></pay>
-  </CtDialog> -->
 </div>
 </template>
 
@@ -99,7 +90,6 @@ import selectSku from './details/s-select-sku.vue'
 import describe from './details/describe.vue'
 // import commentCard from './details/detail-comment-card.vue'
 // import prizeDrawContent from './details/prizeDrawContent.vue'
-// import confirm from './details/order/confirm.vue'
 import { ref, reactive, nextTick } from 'vue'
 import { useRouter } from 'vue-router'
 import Snackbar from '@/plugins/snackbar'
@@ -135,10 +125,11 @@ const getData = async () => {
 
   // 查询当前商品是否参与抽奖活动
   const data = await getPrizeByGoodsId(id)
-  showPrize.value = data && Object.keys(data).length > 0
-  showActivePrices.value = data && Object.keys(data).length > 0
+
+  const bool = data && Object.keys(data).length
+  showPrize.value = showActivePrices.value = bool
   
-  lotteryId.value = data.id
+  lotteryId.value = data?.id || null
 }
 getData()
 
@@ -182,6 +173,7 @@ const onBuy = async (e) => {
         categoryId: state.goodsInfo.categoryId,
       },
     ],
+    goodsType: state.goodsInfo?.type || 0,
   })
 
   localStorage.setItem('confirm_order_data', data)
@@ -190,27 +182,6 @@ const onBuy = async (e) => {
   })
 }
 
-// 创建订单完成
-// const payRef = ref()
-// const showPay = ref(false)
-// const payOrderId = ref('')
-// const orderId = ref('')
-// const orderCreated = (id, order) => {
-//   showSettlement.value = false
-//   payOrderId.value = id
-//   orderId.value = order
-//   showPay.value = true
-// }
-// 
-// const payCancel = () => {
-//   Snackbar.warning('您已取消支付!')
-//   showPay.value = false
-//   setTimeout(() => { router.push({ path: '/mall/user/order', query: { tab: 0 } }) }, 500);
-// }
-// const paySuccess = (e) => {
-//   router.push({ path: '/mall/payOver', query: { price: e.price, spuId: id, orderId: orderId.value } })
-// }
-
 // 添加购物车
 const onAddCart = async (e) => {
   if (!getToken()) return handleLogin()
@@ -223,14 +194,6 @@ const onAddCart = async (e) => {
   // 刷新购物车列表
 }
 
-// const confirmRef = ref()
-// const handleSubmit = () => {
-//   if (confirmRef.value) confirmRef.value.onConfirm()
-// }
-// const handleClose = () => {
-//   showSettlement.value = false
-// }
-
 const showLogin = ref(false)
 const handleLogin = () => {
   Snackbar.warning('您还未登录,请先登录后再试')

+ 21 - 15
src/views/mall/components/s-goods-item/index.vue

@@ -5,23 +5,14 @@
         <v-img :src="img" :aspect-ratio="1" style="border-radius: 8px;"></v-img>
       </div>
       <div
-        class="d-flex justify-space-between"
-        style="flex: 1; font-size: 13px;"
-        :style="[{ width: titleWidth ? titleWidth + 'px' : '' }]"
+        class="d-flex justify-space-between align-center"
+        style="flex: 1; font-size: 16px;"
       >
-        <div v-if="title">{{ title }}</div>
-        <div v-if="skuString" style="color: var(--v-primary-base);">{{ skuString }}</div>
-        <div class="d-flex">
-          <div
-            :style="[{ color: priceColor }]"
-            v-if="price && Number(price) > 0"
-          >
-            ¥{{ fen2yuan(price) }}
-          </div>
-          <!-- <div v-if="point && Number(price) > 0">+</div> -->
-        </div>
+        <div v-if="title" class="title">{{ title }}</div>
+        <div v-if="skuString" class="skuString" style="color: var(--v-primary-base);">{{ skuString }}</div>
+        <div v-if="price && Number(price) > 0" class="price" :style="[{ color: priceColor }]"> ¥{{ fen2yuan(price) }} </div>
         <div v-if="num" class="buyNum ml-2"> x {{ num }}</div>
-        <div v-if="price && Number(price) > 0" class="">¥{{ fen2yuan(num*price) }}</div>
+        <div v-if="price && Number(price) > 0" class="subtotal">¥{{ fen2yuan(num*price) }}</div>
       </div>
     </div>
   </div>
@@ -103,7 +94,22 @@
   padding: 12px;
   // border: 1px dashed #000000;
 }
+.title {
+  font-size: 18px;
+  font-weight: bold;
+  width: 30%;
+}
+.skuString {
+  width: 25%;
+}
+.price {
+  width: 15%;
+}
 .buyNum {
+  width: 10%;
   color: #777;
 }
+.subtotal {
+  width: 15%;
+}
 </style>