소스 검색

购买下单接口

冯诚 3 년 전
부모
커밋
b034e918a0

+ 74 - 26
src/pages/fill-order/StepOne.vue

@@ -3,33 +3,43 @@
     <div class="ptc-block">
       <div class="ptc-inner">
         <p class="ptc-label">Choose a version</p>
-        <PtcRadioGroup v-model="state.product" style="display: flex">
-          <PtcRadio class="version" value="lite">
-            <i class="icon-lite"></i>
-            <span class="mt18">Lite</span>
-          </PtcRadio>
-          <PtcRadio class="version" value="pro">
-            <i class="icon-pro"></i>
-            <span class="mt18">Pro</span>
+        <PtcRadioGroup v-model="state.form.product_id" style="display: flex">
+          <PtcRadio
+            v-for="product of state.productList"
+            :key="product.id"
+            class="version"
+            :value="product.id"
+          >
+            <i :class="`icon-${1 ? 'lite' : 'pro'}`"></i>
+            <span class="mt18">{{ product.name }}</span>
           </PtcRadio>
         </PtcRadioGroup>
-        <div class="version-desc" :class="{ pro: state.product === 'pro' }">
-          Introduction of member products,Introduction of member products
+        <div
+          class="version-desc"
+          :class="{ pro: state.form.product_id === 'pro' }"
+        >
+          {{ selectedProduct.remark }}
         </div>
       </div>
     </div>
     <div class="ptc-block">
       <div class="ptc-inner">
         <p class="ptc-label">Choose a subscription method</p>
-        <PtcRadioGroup v-model="state.type">
-          <PtcRadio class="method" :value="1">
-            <span class="cost">$99</span>
+        <PtcRadioGroup v-model="state.form.subscribe_type">
+          <PtcRadio class="method" value="year">
+            <span class="cost">${{ selectedProduct.amount_year }}</span>
             <span class="name">Annual</span>
-            <span class="ptc-tag">-25% OFF</span>
+            <span class="ptc-tag"
+              >-{{ selectedProduct.better_than_monthly * 100 }}% OFF</span
+            >
           </PtcRadio>
-          <PtcRadio class="method" :value="2">
-            <span class="cost">$12.5</span>
-            <span class="name"> Monthly&nbsp; Activation fee $20</span>
+          <PtcRadio class="method" value="month">
+            <span class="cost">${{ selectedProduct.amount_month }}</span>
+            <span class="name">
+              Monthly&nbsp; Activation fee ${{
+                selectedProduct.amount_month_open
+              }}</span
+            >
           </PtcRadio>
         </PtcRadioGroup>
       </div>
@@ -39,11 +49,11 @@
         <p class="ptc-label">Do you have a discount code?</p>
         <div v-if="!showCoupon" class="input-wrap pr">
           <input
-            v-model="state.couponCode"
+            v-model="state.form.discount_code"
             class="ptc-input"
             placeholder="Enter promotional code"
           />
-          <button class="input-btn" @click="showCoupon = true">sbumit</button>
+          <button class="input-btn" @click="checkDiscount">sbumit</button>
         </div>
         <div v-else class="coupon-wrap">
           <div class="coupon">
@@ -52,8 +62,8 @@
             <p class="p3">- $10</p>
           </div>
           <div class="action">
-            <span class="code">87889122</span>
-            <span class="primary" @click="showCoupon = false">Revise</span>
+            <span class="code">{{ state.form.discount_code }}</span>
+            <span class="primary" @click="reviseDiscount">Revise</span>
           </div>
         </div>
       </div>
@@ -61,28 +71,66 @@
 
     <div class="total">
       <div class="ptc-inner">
-        <p>total<strong>$99</strong></p>
+        <p>
+          total<strong>${{ cost }}</strong>
+        </p>
         <p class="highlight">($10 discounted)</p>
       </div>
     </div>
     <div class="ptc-button-group">
       <div class="ptc-inner">
-        <button class="ptc-button" @click="$emit('next')">NEXT</button>
+        <button class="ptc-button" @click="next">NEXT</button>
       </div>
     </div>
   </div>
 </template>
 
 <script setup lang="ts">
-import { ref } from 'vue'
+import { ref, computed } from 'vue'
 import { PtcRadioGroup, PtcRadio } from '@/components/radio'
-import { state } from './store'
+import { state, getBrandList } from './store'
+import * as api from '@/service/order'
+import Toast from '@/components/toast'
 
-defineEmits<{
+const emit = defineEmits<{
   (e: 'next'): void
 }>()
 
 const showCoupon = ref(false)
+const selectedProduct = computed(() =>
+  state.productList.find(item => item.id === state.form.product_id)
+)
+const cost = computed(() => {
+  const { amount_year, amount_month, amount_month_open } = selectedProduct.value
+  switch (state.form.subscribe_type) {
+    case 'year':
+      return amount_year
+    case 'month':
+      return amount_month + amount_month_open
+    default:
+      return ''
+  }
+})
+
+async function checkDiscount() {
+  if (!state.form.discount_code) return Toast('Please enter promotional code')
+  try {
+    const { results } = await api.checkDiscount(state.form.discount_code)
+    showCoupon.value = true
+  } catch {
+    state.form.discount_code = ''
+  }
+}
+
+function reviseDiscount() {
+  showCoupon.value = false
+  state.form.discount_code = ''
+}
+
+async function next() {
+  if (!state.brandList.length) await getBrandList()
+  emit('next')
+}
 </script>
 
 <style lang="scss" scoped>

+ 29 - 3
src/pages/fill-order/StepThree.vue

@@ -6,7 +6,10 @@
         <div class="detail">
           <strong class="s1">Lite</strong>
           <span style="font-size: 0"
-            ><strong class="s2">$99</strong><span class="s3">Annual</span></span
+            ><strong class="s2">$99</strong
+            ><span class="s3">{{
+              state.form.subscribe_type === 'year' ? 'Annual' : 'Monthly'
+            }}</span></span
           >
           <strong class="s4" @click="$router.go(-2)">Modify ></strong>
         </div>
@@ -28,18 +31,41 @@
             Please enter a valid email address, we will send you the latest
             status of the order through this contact method。
           </p>
-          <input class="ptc-input" placeholder="email address" />
+          <input
+            v-model="state.form.email"
+            class="ptc-input"
+            placeholder="email address"
+          />
         </div>
       </div>
       <div class="ptc-button-group">
         <div class="ptc-inner">
-          <button class="ptc-button">SUBMIT</button>
+          <button class="ptc-button" @click="submit">SUBMIT</button>
         </div>
       </div>
     </div>
   </div>
 </template>
 
+<script setup lang="ts">
+import { string } from 'yup'
+import { state } from './store'
+import { checkoutOrder } from '@/service/order'
+import Toast from '@/components/toast'
+
+async function submit() {
+  try {
+    await string()
+      .email('Please enter a valid email address')
+      .validate(state.form.email)
+    const { results } = await checkoutOrder(state.form)
+    location.href = results
+  } catch (err) {
+    Toast(err.message)
+  }
+}
+</script>
+
 <style lang="scss" scoped>
 .text {
   margin-bottom: 48px;

+ 19 - 24
src/pages/fill-order/StepTwo.vue

@@ -6,7 +6,10 @@
         <div class="detail">
           <strong class="s1">Lite</strong>
           <span style="font-size: 0"
-            ><strong class="s2">$99</strong><span class="s3">Annual</span></span
+            ><strong class="s2">$99</strong
+            ><span class="s3">{{
+              state.form.subscribe_type === 'year' ? 'Annual' : 'Monthly'
+            }}</span></span
           >
           <strong class="s4" @click="$router.back()">Modify ></strong>
         </div>
@@ -16,15 +19,15 @@
       <div class="ptc-inner">
         <p class="ptc-label">Choose a mobile phone brand</p>
         <PtcRadioGroup
-          v-model="state.brand"
+          v-model="state.form.brand_id"
           class="device-list"
-          @change="state.model = ''"
+          @change="onSelectBrand"
         >
           <PtcRadio
-            v-for="brand of brandList"
-            :key="brand.name"
+            v-for="brand of state.brandList"
+            :key="brand.id"
             class="device-item"
-            :value="brand.name"
+            :value="brand.id"
           >
             <img class="device-img" />
             <p class="device-name">{{ brand.name }}</p>
@@ -32,20 +35,20 @@
         </PtcRadioGroup>
       </div>
     </div>
-    <template v-if="state.brand">
+    <template v-if="state.form.brand_id">
       <div class="ptc-block">
         <div class="ptc-inner">
           <p class="ptc-label">Choose phone model</p>
           <PtcRadioGroup
-            v-model="state.model"
+            v-model="state.form.phone_id"
             class="device-list"
             @change="onSelectModel"
           >
             <PtcRadio
-              v-for="model of modelList"
-              :key="model.name"
+              v-for="model of state.modelList"
+              :key="model.id"
               class="device-item"
-              :value="model.name"
+              :value="model.id"
             >
               <img class="device-img" />
               <p class="device-name">{{ model.name }}</p>
@@ -59,24 +62,16 @@
 
 <script setup lang="ts">
 import { PtcRadioGroup, PtcRadio } from '@/components/radio'
-import { state } from './store'
+import { state, getModelList } from './store'
 
 const emit = defineEmits<{
   (e: 'next'): void
 }>()
 
-const brandList = [
-  { name: 'iPhone', img: '' },
-  { name: 'iPad', img: '' },
-  { name: 'Samsung', img: '' },
-  { name: 'Xiaomi', img: '' },
-]
-const modelList = [
-  { name: 'iPhone13 Pro', img: '' },
-  { name: 'iPhone13', img: '' },
-  { name: 'iPhone12', img: '' },
-  { name: 'iPhoneSE', img: '' },
-]
+function onSelectBrand() {
+  state.form.phone_id = ''
+  getModelList()
+}
 
 function onSelectModel() {
   setTimeout(() => emit('next'), 200)

+ 12 - 0
src/pages/fill-order/index.vue

@@ -5,6 +5,18 @@
   </div>
 </template>
 
+<script lang="ts">
+import { defineComponent } from 'vue'
+import { state, initProducts } from './store'
+
+export default defineComponent({
+  name: 'FillOrder',
+  beforeRouteEnter(to, from, next) {
+    initProducts().then(next)
+  },
+})
+</script>
+
 <script setup lang="ts">
 import { useRoute, useRouter } from 'vue-router'
 import StepOne from './StepOne.vue'

+ 29 - 5
src/pages/fill-order/store.ts

@@ -1,9 +1,33 @@
 import { reactive } from 'vue'
+import * as api from '@/service/order'
 
 export const state = reactive({
-  product: 'lite',
-  type: -1,
-  couponCode: '',
-  brand: '',
-  model: '',
+  productList: [] as any[],
+  brandList: [] as any[],
+  modelList: [] as any[],
+  form: {
+    product_id: '',
+    subscribe_type: '' as 'year' | 'month',
+    discount_code: '',
+    brand_id: '',
+    phone_id: '',
+    email: '',
+    from: '',
+    invitor: '',
+  },
 })
+
+export async function initProducts() {
+  if (!state.productList.length) {
+    state.productList = (await api.getProductList()).results
+  }
+  state.form.product_id = state.productList[0].id
+}
+
+export async function getBrandList() {
+  state.brandList = (await api.getBrands()).results
+}
+
+export async function getModelList() {
+  state.brandList = (await api.getModels(state.form.brand_id)).results
+}

+ 37 - 0
src/service/order.ts

@@ -32,3 +32,40 @@ export function getPostInfo(member_right_id: string) {
 export function getGiftCardList(status: 0 | 1 | 2) {
   return request.get('/gift-card/list', { params: { status } })
 }
+
+export function getProductList() {
+  return request.get('/product/list')
+}
+
+/** 校验优惠码 */
+export function checkDiscount(code: string) {
+  return request.post('/product/discount/check', { code })
+}
+
+export function getBrands() {
+  return request.get('/igeektek?api=v2/brands')
+}
+
+export function getModels(brand_id: string) {
+  return request.get('/igeektek?api=v2/phones', {
+    params: {
+      brand_id,
+      per_page: 1000,
+      igeektek_id: '',
+      from: 'PC',
+    },
+  })
+}
+
+/** 提交订单 */
+export function checkoutOrder(data: any) {
+  return request.post('/order/checkout', data)
+}
+
+export function bindIMEI(data: { id: number; imei: string }) {
+  return request.post('/order/bindIMEI', data)
+}
+
+export function unsubscribe(id: number) {
+  return request.post('/order/unSubscribe', { id })
+}

+ 4 - 2
src/style/normalize.scss

@@ -10,8 +10,10 @@ html {
   font-family: Avenir, Helvetica, Arial, sans-serif;
   -webkit-font-smoothing: antialiased;
   -moz-osx-font-smoothing: grayscale;
-  user-select: none;
-  -webkit-user-select: none;
+  @include media-breakpoint-down(md) {
+    user-select: none;
+    -webkit-user-select: none;
+  }
 }
 
 body,