Преглед на файлове

feat(interceptor): 下单整体流程调试

laiqi преди 1 година
родител
ревизия
1fbcdabb98

+ 1 - 1
.vscode/settings.json

@@ -22,7 +22,7 @@
     "editor.defaultFormatter": "foxundermoon.shell-format"
   },
   "[vue]": {
-    "editor.defaultFormatter": "esbenp.prettier-vscode"
+    "editor.defaultFormatter": "dbaeumer.vscode-eslint"
   },
   "[typescript]": {
     "editor.defaultFormatter": "esbenp.prettier-vscode"

+ 2 - 0
src/interceptors/request.ts

@@ -18,6 +18,8 @@ const httpInterceptor = {
   // 拦截前触发
   invoke(options: CustomRequestOptions) {
     // 接口请求支持通过 query 参数配置 queryString
+    console.log('请求参数:', options)
+
     if (options.query) {
       const queryStr = qs.stringify(options.query)
       if (options.url.includes('?')) {

+ 1 - 0
src/pages-sub/auth/index.vue

@@ -64,6 +64,7 @@ const handleLogin = async () => {
               const { token, userid, openid } = data.value as any
 
               appStore.setAppInfo({ token, userid, openid })
+              userStore.getUserInfo()
 
               uni.reLaunch({ url: '/pages/index/index' })
               uni.$emit('authComplete', { result: true })

+ 1 - 1
src/pages-sub/user/index.vue

@@ -317,7 +317,7 @@ const getUserDetail = async () => {
     // userscz: '',
     // usersbz: '',
     model.usersname = Data.usersname
-    model.userstype = Data.userstype
+    model.userstype = Data.userstype || '个人'
     model.usersidcardnumber = Data.usersidcardnumber
     model.usersbankname = Data.usersbankname
     model.usersbanknumber = Data.usersbanknumber

+ 24 - 0
src/pages.json

@@ -47,6 +47,14 @@
       }
     },
     {
+      "path": "pages/about/index",
+      "type": "page",
+      "layout": "default",
+      "style": {
+        "navigationBarTitleText": "关于"
+      }
+    },
+    {
       "path": "pages/form/formStep1",
       "type": "page",
       "style": {
@@ -82,6 +90,22 @@
       }
     },
     {
+      "path": "pages/order/detail",
+      "type": "page",
+      "layout": "default",
+      "style": {
+        "navigationBarTitleText": "订单详情"
+      }
+    },
+    {
+      "path": "pages/order/index",
+      "type": "page",
+      "layout": "default",
+      "style": {
+        "navigationBarTitleText": "我的订单"
+      }
+    },
+    {
       "path": "pages/product/detail",
       "type": "page",
       "layout": "default",

+ 40 - 0
src/pages/about/index.vue

@@ -0,0 +1,40 @@
+<route lang="json5" type="page">
+{
+  layout: 'default',
+  style: {
+    navigationBarTitleText: '关于',
+  },
+}
+</route>
+
+<template>
+  <view class="bg-white min-h-screen">
+    <view class="flex flex-col items-center justify-center pt-20 space-y-4">
+      <view class="mb-6">
+        <wd-icon name="logo" size="120" />
+      </view>
+
+      <view class="text-center">
+        <view class="text-2xl font-bold mb-3 text-gray-800">达州农机优惠劵</view>
+        <view class="text-gray-600 mb-2">达州市农机局官方优惠劵</view>
+        <view class="text-gray-500 text-sm">当前版本:V1.0.0</view>
+      </view>
+
+      <view class="mt-12 px-8 w-full">
+        <wd-cell-group>
+          <wd-cell title="官方网站" value="www.dznjj.gov.cn" is-link />
+          <wd-cell title="联系电话" value="0818-12345678" is-link />
+          <wd-cell title="关于萨莫尔" is-link />
+        </wd-cell-group>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script lang="ts" setup>
+//
+</script>
+
+<style lang="scss" scoped>
+//
+</style>

+ 5 - 2
src/pages/form/formStep2.vue

@@ -25,7 +25,7 @@
       </wd-sticky-box>
 
       <!-- 产品列表 -->
-      <view class="sticky-box-content w-100vw">
+      <view class="sticky-box-content w-100vw" v-if="productListShow.length">
         <wd-cell-group>
           <wd-cell
             v-for="item in productListShow"
@@ -37,11 +37,14 @@
           >
             <template #label>
               <p class="text-gray-500">分类:{{ item.productsfl1 }} - {{ item.productsfl2 }}</p>
-              <p class="text-gray-500">生产厂家:{{ item.productsscqyid || '未知' }}</p>
+              <p class="text-gray-500">生产厂家:{{ item.scqyinfomc || '未知' }}</p>
             </template>
           </wd-cell>
         </wd-cell-group>
       </view>
+      <view class="sticky-box-content w-100vw" v-else>
+        <wd-status-tip image="content" tip="暂无内容" />
+      </view>
     </view>
   </view>
 </template>

+ 281 - 16
src/pages/form/formStep3.vue

@@ -8,39 +8,304 @@
 
 <template>
   <!-- 选网点,选择机器型号,输入SN号,下订单 -->
-  <view class="bg-white min-h-screen px-4 py-4">
-    <view class="space-y-4">
-      <view class="flex items-center justify-between">
-        <view class="text-lg font-bold">农机详情</view>
+  <view class="bg-gray-100 min-h-screen pb-6">
+    <!-- 产品名称头部 -->
+    <view class="bg-white px-4 py-1 mb-3 shadow-sm">
+      <view class="product-title text-xl font-bold text-gray-800">
+        {{ productInfo?.productsname }}
       </view>
-      <!-- 提交按钮 -->
-      <!-- <view class="mt-8 pb-8">
-        <wd-button type="success" block @tap="handleSubmit">提交申请</wd-button>
-      </view> -->
     </view>
+
+    <!-- 农机详情卡片 -->
+    <view class="bg-white px-4 py-4 mb-3 shadow-sm">
+      <view class="flex items-center mb-4">
+        <view class="text-lg font-bold text-gray-800">农机详情</view>
+        <view class="ml-2 flex-1 h-px bg-gray-100"></view>
+      </view>
+      <div class="detail-box rounded-lg">
+        <wd-cell-group inset>
+          <wd-cell title="产品名称" :value="productInfo?.productsname" />
+          <wd-cell title="生产企业" :value="productInfo?.scqyinfomc" />
+          <wd-cell title="机具类型" :value="productInfo?.productsjjlx" />
+          <wd-cell title="产品类别" :value="productInfo?.productscategory" />
+          <wd-cell title="产品型号" :value="productInfo?.productsmodel" />
+          <wd-cell
+            title="分类"
+            :value="`${productInfo?.productsfl1} - ${productInfo?.productsfl2}`"
+          />
+          <wd-cell title="品目" :value="productInfo?.productspm" />
+          <wd-cell
+            title="产品原价"
+            :value="`¥${Number(productInfo?.productsprice).toFixed(2)}`"
+            value-class="text-red-500 font-medium"
+          />
+          <wd-cell
+            title="中央补贴金额"
+            :value="`¥${Number(productInfo?.productszybt).toFixed(2)}`"
+            value-class="text-green-500 font-medium"
+          />
+          <wd-cell
+            title="特殊县中央补贴金额"
+            :value="`¥${Number(productInfo?.productstsxzybt).toFixed(2)}`"
+            value-class="text-green-500 font-medium"
+          />
+        </wd-cell-group>
+      </div>
+    </view>
+
+    <!-- SN码 -->
+    <view class="bg-white px-4 py-4 mb-3 shadow-sm">
+      <view class="flex items-center mb-4">
+        <view class="text-lg font-bold text-gray-800">农机SN码</view>
+        <view class="ml-2 flex-1 h-px bg-gray-100"></view>
+      </view>
+      <div class="detail-box rounded-lg">
+        <wd-form ref="form" :model="model">
+          <wd-cell-group border>
+            <wd-input
+              label="SN码"
+              label-width="100px"
+              prop="ordersproductsn"
+              clearable
+              v-model="model.ordersproductsn"
+              placeholder="请输入SN码"
+              :rules="[{ required: true, message: '请填写SN码' }]"
+            />
+          </wd-cell-group>
+        </wd-form>
+      </div>
+    </view>
+
+    <!-- 优惠券卡片 -->
+    <view class="bg-white px-4 py-4 shadow-sm">
+      <view class="flex items-center mb-4">
+        <view class="text-lg font-bold text-gray-800">可用优惠券</view>
+        <view class="ml-2 flex-1 h-px bg-gray-100"></view>
+      </view>
+      <view class="coupon-box">
+        <!-- 这里添加优惠券列表组件 -->
+        <view v-if="!coupons?.length" class="text-center py-8 text-gray-400">暂无可用优惠券</view>
+        <view v-else>
+          <view class="coupon-list">
+            <wd-radio-group v-model="couponChoose" shape="dot" @change="couponRadioChange">
+              <wd-radio
+                :value="coupon.couponid"
+                v-for="coupon in couponsShow"
+                :key="coupon.couponid"
+              >
+                <view class="flex items-center justify-between">
+                  <view class="text-gray-800">{{ coupon.couponmc }}</view>
+                  <view class="flex items-center justify-end" @click.stop>
+                    <wd-button
+                      size="small"
+                      type="success"
+                      @click="handleReceive(coupon)"
+                      plain
+                      hairline
+                      :disabled="!coupon.canReceive"
+                    >
+                      {{ !coupon.canReceive ? '已领取' : '领取并使用' }}
+                    </wd-button>
+                  </view>
+                </view>
+              </wd-radio>
+            </wd-radio-group>
+          </view>
+        </view>
+      </view>
+    </view>
+
+    <!-- 提交按钮 -->
+    <view class="mt-2 pb-4 px-2">
+      <wd-button type="success" block @tap="handleSubmit" :loading="submitLoading">
+        提交订单
+      </wd-button>
+    </view>
+
+    <!-- loading -->
+    <wd-overlay :show="overlayShow">
+      <wd-loading />
+    </wd-overlay>
   </view>
 </template>
 
 <script lang="ts" setup>
-const usersid = ref('')
-const productsid = ref('')
+import { useProductStore } from '@/store/product'
+import { useCouponStore } from '@/store/coupon'
+import { useOrderStore } from '@/store/order'
+import { useAppStore } from '@/store/app'
+import { useMessage } from 'wot-design-uni'
+
+const appStore = useAppStore()
+const couponStore = useCouponStore()
+const productStore = useProductStore()
+const orderStore = useOrderStore()
+const message = useMessage()
+const usersid = ref('') // 销售网点用户id
+const productsid = ref('') // 产品id
+const productInfo = ref<any>(null) // 产品详情
+const overlayShow = ref(false) // 加载状态
+const coupons = ref<any[]>([]) // 可用优惠券列表
+const currentCoupon2id = ref('') // 当前选中的优惠劵
+const coupon2idList = ref<any[]>([]) // 已领取的优惠券ID列表
+const couponsShow = ref<any[]>([]) // 展示的优惠券列表
+const couponChoose = ref('') // 选择的优惠券ID
+const submitLoading = ref(false) // 提交订单loading
+const model = reactive<{
+  ordersproductsn: string
+}>({
+  ordersproductsn: '',
+})
+const form = ref()
 
 // 提交表单
 function handleSubmit() {
-  // ...
+  form.value.validate().then(async (res) => {
+    if (res.valid) {
+      // 判断是否选择了优惠券
+      if (couponsShow.value.length && !currentCoupon2id.value) {
+        message.alert({
+          msg: '当前有可用优惠券,请选择优惠券',
+          title: '提示',
+        })
+        return
+      }
+
+      try {
+        submitLoading.value = true
+        await orderStore.submitOrder({
+          ordersproductid: productsid.value,
+          orderscouponid: currentCoupon2id.value,
+          ordersproductsn: model.ordersproductsn,
+        })
+        message
+          .alert({
+            msg: '提交成功',
+            title: '提示',
+          })
+          .then(() => {
+            uni.navigateTo({ url: '/pages/order/index' })
+          })
+          .finally(() => {
+            submitLoading.value = false
+          })
+      } catch (error) {
+        message.alert({
+          msg: '提交失败',
+          title: '提示',
+        })
+      } finally {
+        submitLoading.value = false
+      }
+    }
+  })
+}
+
+// 获取产品详情
+async function getProductDetail() {
+  if (!productsid.value) return
+  overlayShow.value = true
+  productInfo.value = await productStore.getProductDetail(productsid.value)
+  overlayShow.value = false
+}
+
+// 获取可用优惠券列表
+async function getCouponList() {
+  if (!productsid.value) return
+  coupons.value = await couponStore.getCouponList(productsid.value)
+}
+
+// 领取优惠券
+async function handleReceive(coupon: any) {
+  overlayShow.value = true
+  await couponStore.receiveCoupon(coupon.couponid)
+  overlayShow.value = false
+
+  message.alert({
+    msg: '领取成功',
+    title: '提示',
+  })
+
+  // 重新获取优惠券列表状态
+  await getCouponsShow()
+}
+
+// 获取该用户下,已领取的优惠劵id,用于判断是否可以领取
+async function getCoupon2id() {
+  const { Data } = await couponStore.getCoupon2id({
+    coupon2userid: appStore.appInfo.userid,
+    coupon2isused: 0,
+    coupon2productids: productsid.value,
+  })
+
+  coupon2idList.value = Data
 }
 
-onLoad((query) => {
+// 优惠券选择
+async function couponRadioChange(e: any) {
+  currentCoupon2id.value = couponsShow.value.find((item) => item.couponid === e.value)?.coupon2code
+}
+
+// 获取可展示的优惠券列表
+function getCouponsShow() {
+  Promise.all([
+    getCouponList(), // 获取可用优惠券列表
+    getCoupon2id(), // 获取该用户下,已领取的优惠劵id,用于判断是否可以领取
+  ]).then(() => {
+    couponsShow.value = coupons.value.map((coupon) => {
+      // 找到匹配的已领取优惠券记录
+      const receivedCoupon = coupon2idList.value.find(
+        (item) => item.coupon2coupon1id === coupon.couponid,
+      )
+
+      return {
+        ...coupon,
+        canReceive: !receivedCoupon,
+        coupon2sid: receivedCoupon?.coupon2sid,
+        coupon2code: receivedCoupon?.coupon2code,
+      }
+    })
+  })
+}
+
+onLoad(async (query) => {
   usersid.value = query.usersid
   productsid.value = query.productsid
+  getProductDetail() // 获取产品详情
+  getCouponsShow() // 获取可展示的优惠券列表
 })
 </script>
 
 <style lang="scss" scoped>
-.form-item {
-  @apply mb-6;
-  .form-label {
-    @apply block text-gray-700 mb-2 text-base;
+.product-title {
+  @apply leading-relaxed break-all;
+}
+
+.detail-box {
+  :deep(.wd-cell) {
+    // @apply py-2;
+  }
+
+  :deep(.wd-cell__title) {
+    @apply text-gray-600 min-w-[120px] text-sm;
+  }
+
+  :deep(.wd-cell__value) {
+    @apply text-gray-800 text-sm;
+  }
+}
+
+.coupon-box {
+  @apply rounded-lg;
+}
+
+.coupon-list {
+  // :deep(.wd-radio) {
+  //   @apply py-2;
+  // }
+
+  :deep(.wd-radio__label) {
+    @apply flex-1 pr-4;
   }
 }
 </style>

+ 29 - 15
src/pages/index/index.vue

@@ -45,16 +45,21 @@
             </view>
           </view>
           <view class="flex gap-2">
-            <wd-icon
-              name="call"
-              class="p-4 mr-4 bg-green-500 text-white rounded-md"
-              @tap="handleCall(item.phone)"
-            />
-            <wd-icon
-              name="cart"
-              class="p-4 bg-green-500 text-white rounded-md"
-              @tap="handleGoods(item)"
-            />
+            <view class="p-1 mr-1">
+              <wd-icon
+                name="call"
+                class="bg-green-500 text-white rounded-md"
+                @tap="handleCall(item.phone)"
+              />
+            </view>
+
+            <view class="p-1">
+              <wd-icon
+                name="cart"
+                class="bg-green-500 text-white rounded-md"
+                @tap="handleGoods(item)"
+              />
+            </view>
           </view>
         </view>
       </view>
@@ -122,6 +127,7 @@ const getUserList = async () => {
     name: item.usersname,
     address: item.usersaddress,
     phone: item.usersphone,
+    usersid: item.usersid,
   }))
 }
 
@@ -163,11 +169,13 @@ function handleCall(phone: string) {
   })
 }
 
-// 处理跳转商品
+// 销售网点跳转
 function handleGoods(location: any) {
-  // uni.navigateTo({
-  //   url: '/pages/goods/index',
-  // })
+  console.log(location)
+
+  uni.navigateTo({
+    url: `/pages/form/formStep2?usersid=${location.usersid}`,
+  })
 }
 
 // 处理申请
@@ -185,7 +193,13 @@ uni.$on('authComplete', function (data) {
 
 // 入口完善信息提示
 const showCompleteDialog = () => {
-  if (appStore.isLogined && !userStore.isAuthComplete && appStore.needAlertComplete) {
+  console.log(appStore.isLogined, userStore.isAuthComplete, appStore.needAlertCompleteInDays)
+
+  // 如果已登录且已完善信息,则不提示
+  if (appStore.isLogined && userStore.isAuthComplete) return
+
+  // 如果需要提示完善信息,并且N天内没有提示过,则提示
+  if (appStore.needAlertCompleteInDays) {
     message
       .confirm({
         msg: '您还未完善个人信息, 无法享受优惠劵活动, 点击按钮完善信息',

+ 2 - 2
src/pages/mine/index.vue

@@ -63,7 +63,7 @@
       </view>
 
       <!-- 我的订单 -->
-      <view class="menu-item" @click="handleNavigate('/pages/settings/index')">
+      <view class="menu-item" @click="handleNavigate('/pages/order/index')">
         <view class="flex items-center">
           <wd-icon name="a-rootlist" class="text-gray-500" />
           <text class="ml-3">我的订单</text>
@@ -81,7 +81,7 @@
       </view>
 
       <!-- 关于 -->
-      <view class="menu-item" @click="handleNavigate('/pages/help-center/index')">
+      <view class="menu-item" @click="handleNavigate('/pages/about/index')">
         <view class="flex items-center">
           <wd-icon name="tips" class="text-cyan-500" />
           <text class="ml-3">关于</text>

+ 66 - 0
src/pages/order/detail.vue

@@ -0,0 +1,66 @@
+<route lang="json5" type="page">
+{
+  layout: 'default',
+  style: {
+    navigationBarTitleText: '订单详情',
+  },
+}
+</route>
+
+<template>
+  <view class="">
+    <wd-cell-group>
+      <wd-cell title="订单号" :value="orderDetail.ordersnumber" />
+      <wd-cell title="产品名称" :value="orderDetail.ordersproductname" />
+      <wd-cell title="产品SN" :value="orderDetail.ordersproductsn" />
+      <wd-cell title="订单总金额" :value="`¥${orderDetail.orderstotalprice}`" />
+      <wd-cell title="优惠金额" :value="`¥${orderDetail.ordersyhprice}`" />
+      <wd-cell title="实付金额" :value="`¥${orderDetail.ordersdiscountprice}`" />
+      <wd-cell title="订单状态" :value="getOrderStatus(orderDetail.ordersorderstatus)" />
+      <wd-cell title="下单时间" :value="orderDetail.ordersorderdate" />
+    </wd-cell-group>
+
+    <!-- 回到订单列表 -->
+    <view class="sticky-box-content w-full box-border px-2 pb-2 mt-4">
+      <wd-button type="primary" block @click="handleBack">回到订单列表</wd-button>
+    </view>
+  </view>
+</template>
+
+<script lang="ts" setup>
+import { useOrderStore } from '@/store/order'
+import type { OrderType } from '@/types/order'
+
+const orderStore = useOrderStore()
+const currentOrdersId = ref('')
+const orderDetail = ref<OrderType>({} as OrderType)
+
+const getOrderDetail = async () => {
+  const res = await orderStore.getOrderDetail(currentOrdersId.value)
+  orderDetail.value = res
+}
+
+const getOrderStatus = (status: number) => {
+  const statusMap = {
+    0: '待审核',
+    1: '已支付',
+    2: '已完成',
+  }
+  return statusMap[status] || '未知状态'
+}
+
+function handleBack() {
+  uni.navigateTo({
+    url: '/pages/order/index',
+  })
+}
+
+onLoad((query) => {
+  currentOrdersId.value = query.ordersid
+  getOrderDetail()
+})
+</script>
+
+<style lang="scss" scoped>
+//
+</style>

+ 131 - 0
src/pages/order/index.vue

@@ -0,0 +1,131 @@
+<route lang="json5" type="page">
+{
+  layout: 'default',
+  style: {
+    navigationBarTitleText: '我的订单',
+  },
+}
+</route>
+
+<template>
+  <view class="bg-white min-h-screen">
+    <view class="space-y-4">
+      <wd-sticky-box>
+        <!-- 订单选择 -->
+        <view class="sticky-box-content w-100vw">
+          <wd-search
+            placeholder="请输入订单号"
+            cancel-txt="搜索"
+            @blur="blur"
+            @search="search"
+            @clear="clear"
+            @change="change"
+          />
+        </view>
+      </wd-sticky-box>
+
+      <!-- 订单列表 -->
+      <view class="sticky-box-content w-100vw" v-if="orderListShow.length">
+        <wd-cell-group>
+          <wd-cell
+            v-for="item in orderListShow"
+            :key="item.ordersid"
+            :title="`${item.ordersproductname}`"
+            is-link
+            @click="handleClick(item)"
+            custom-class="product-cell"
+          >
+            <template #label>
+              <p class="text-gray-500">订单号:{{ item.ordersnumber }}</p>
+              <p class="text-gray-500">下单时间:{{ item.ordersorderdate }}</p>
+              <p class="text-gray-500">订单总金额:{{ Number(item.orderstotalprice).toFixed(2) }}</p>
+            </template>
+          </wd-cell>
+        </wd-cell-group>
+      </view>
+      <view class="sticky-box-content w-100vw" v-else>
+        <wd-status-tip image="content" tip="暂无内容" />
+      </view>
+
+      <!-- loading -->
+      <wd-overlay :show="overlayShow">
+        <wd-loading />
+      </wd-overlay>
+
+      <!-- 回到首页 -->
+      <view class="sticky-box-content w-full box-border px-2 pb-2">
+        <wd-button type="primary" block @click="handleBack">回到首页</wd-button>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script lang="ts" setup>
+import { useOrderStore } from '@/store/order'
+import { useAppStore } from '@/store/app'
+import { useThrottleFn } from '@vueuse/core'
+
+const appStore = useAppStore()
+const orderStore = useOrderStore()
+const orderListAll = ref([])
+const orderListShow = ref([])
+const overlayShow = ref(false)
+
+function blur(e: any) {
+  const filters = orderListAll.value.filter((item: any) => item.ordersnumber.includes(e.value))
+  orderListShow.value = filters
+}
+
+function search(e: any) {
+  const filters = orderListAll.value.filter((item: any) => item.ordersnumber.includes(e.value))
+  orderListShow.value = filters
+}
+
+function clear() {
+  orderListShow.value = orderListAll.value
+}
+
+const handleChange = useThrottleFn(({ value }) => {
+  const filters = orderListAll.value.filter((item: any) => item.ordersnumber.includes(value))
+  orderListShow.value = filters
+}, 500) // 500ms 的节流时间
+
+function change(e: any) {
+  handleChange(e)
+}
+
+function handleClick(item: any) {
+  uni.navigateTo({
+    url: `/pages/order/detail?ordersid=${item.ordersid}`,
+  })
+}
+
+function handleBack() {
+  uni.switchTab({
+    url: '/pages/index/index',
+  })
+}
+
+onLoad((query) => {
+  overlayShow.value = true
+  orderStore
+    .getOrderList(appStore.appInfo.userid)
+    .then((res) => {
+      orderListAll.value = res
+      orderListShow.value = res
+      overlayShow.value = false
+    })
+    .finally(() => {
+      overlayShow.value = false
+    })
+})
+</script>
+
+<style lang="scss" scoped>
+::v-deep(.order-cell) {
+  .wd-cell__right {
+    flex: inherit !important;
+    width: 50px !important;
+  }
+}
+</style>

+ 36 - 0
src/service/coupon1/index.ts

@@ -0,0 +1,36 @@
+import { http } from '@/utils/http'
+import type { Coupon1Type } from '@/types/coupon1'
+import type { Coupon2Type } from '@/types/coupon2'
+import type { ListType, ListResponseType } from '@/types/list'
+// import { parseQueryValues } from '@/utils'
+
+/** 获取商品可用优惠券列表 */
+export const getCouponListApi = (params: Partial<Coupon1Type>, page: Partial<ListType>) => {
+  return http.get<ListResponseType<Coupon1Type>>('/api/query/list?pagevalue=33', {
+    ...page,
+    // ...parseQueryValues(params),
+    'couponproductids.like': params.couponproductids,
+  })
+}
+
+/** 领取优惠券 */
+export const receiveCouponApi = (couponid: string) => {
+  return http.get<any>('/api/nlua/call?pagevalue=43', {
+    couponid,
+  })
+}
+
+/** 获取该用户下,已领取的优惠劵id,用于判断是否可以领取 */
+export const getCoupon2idApi = (
+  params: Partial<Coupon2Type> & {
+    coupon2userid: string
+    coupon2isused: number
+    coupon2productids: string
+  },
+) => {
+  return http.get<any>('/api/query/list?pagevalue=38', {
+    'coupon2userid.value': params.coupon2userid, // 用户id
+    'coupon2isused.value': params.coupon2isused, // 0:未使用 1:已使用
+    'coupon2productids.like': params.coupon2productids, // 产品id
+  })
+}

+ 30 - 0
src/service/order/index.ts

@@ -0,0 +1,30 @@
+import { http } from '@/utils/http'
+import type { OrderType } from '@/types/order'
+import type { ListType, ListResponseType } from '@/types/list'
+import { parseQueryValues } from '@/utils'
+
+/** 订单列表 */
+export const getOrderListApi = (params: Partial<OrderType>, page: Partial<ListType>) => {
+  return http.get<ListResponseType<OrderType>>('/api/query/list?pagevalue=51', {
+    ...page,
+    ...parseQueryValues(params),
+  })
+}
+
+/** 获取订单详情 */
+export const getOrderDetailApi = (id: string) => {
+  return http.get<OrderType>(
+    '/api/query/view?pagevalue=61',
+    {
+      ...parseQueryValues({ ordersid: id }),
+    },
+    {
+      formatData: true,
+    },
+  )
+}
+
+/** 使用优惠劵提交订单 */
+export const submitOrderApi = (params: { ordersproductid: string; orderscouponid: string }) => {
+  return http.get<any>('/api/nlua/call?pagevalue=44', params)
+}

+ 8 - 5
src/service/product/index.ts

@@ -1,11 +1,14 @@
 import { http } from '@/utils/http'
-import type { ProductType } from '@/types/product'
+import type { ProductUserScqyType } from '@/types/product-user-scqy'
 import type { ListType, ListResponseType } from '@/types/list'
 import { parseQueryValues } from '@/utils'
 
 /** 商品列表 */
-export const getProductListApi = (params: Partial<ProductType>, page: Partial<ListType>) => {
-  return http.get<ListResponseType<ProductType>>('/api/query/list?pagevalue=23', {
+export const getProductListApi = (
+  params: Partial<ProductUserScqyType>,
+  page: Partial<ListType>,
+) => {
+  return http.get<ListResponseType<ProductUserScqyType>>('/api/query/list?pagevalue=59', {
     ...page,
     ...parseQueryValues(params),
   })
@@ -13,8 +16,8 @@ export const getProductListApi = (params: Partial<ProductType>, page: Partial<Li
 
 /** 获取商品详情 */
 export const getProductDetailApi = (id: string) => {
-  return http.get<ProductType>(
-    '/api/query/view?pagevalue=58',
+  return http.get<ProductUserScqyType>(
+    '/api/query/view?pagevalue=60',
     {
       ...parseQueryValues({ productsid: id }),
     },

+ 1 - 1
src/service/user/index.ts

@@ -16,7 +16,7 @@ export const getUserDetailApi = (id: string) => {
   return http.get<UserType>(
     '/api/query/view?pagevalue=56',
     {
-      ...parseQueryValues({ usersid: id }),
+      // ...parseQueryValues({ usersid: id }),
     },
     {
       formatData: true,

+ 10 - 3
src/store/app.ts

@@ -2,7 +2,11 @@ import { defineStore } from 'pinia'
 import { ref } from 'vue'
 import dayjs from 'dayjs'
 
-const initState = { token: '', userid: '', openid: '' }
+const initState = {
+  token: '', // 登录token
+  userid: '', // 用户id
+  openid: '', // 微信openid
+}
 
 export const useAppStore = defineStore(
   'app',
@@ -20,12 +24,15 @@ export const useAppStore = defineStore(
     const clearAppInfo = () => {
       appInfo.value = { ...initState }
     }
+
     // 一般没有reset需求,不需要的可以删除
     const reset = () => {
       appInfo.value = { ...initState }
     }
+
     const isLogined = computed(() => !!appInfo.value.token)
-    const needAlertComplete = computed(() => {
+
+    const needAlertCompleteInDays = computed(() => {
       // 如果已经提示过,并且距离上一次提示的时间在3天以内,则不需要提示
       if (alertCompleteInfo.value && dayjs().diff(alertCompleteInfo.value.time, 'day') < 3) {
         return false
@@ -45,7 +52,7 @@ export const useAppStore = defineStore(
       reset,
       alertCompleteInfo,
       setAlertCompleteInfo,
-      needAlertComplete,
+      needAlertCompleteInDays,
     }
   },
   {

+ 50 - 0
src/store/coupon.ts

@@ -0,0 +1,50 @@
+import { defineStore } from 'pinia'
+import { getCouponListApi, receiveCouponApi, getCoupon2idApi } from '@/service/coupon1'
+import { until } from '@vueuse/core'
+
+export const useCouponStore = defineStore(
+  'coupon',
+  () => {
+    // 获取优惠券列表
+    const getCouponList = async (couponproductids: string) => {
+      const { data: couponList, loading } = useRequest(
+        () => getCouponListApi({ couponproductids }, { pageindex: 1, rows: 999 }),
+        {
+          immediate: true,
+        },
+      )
+
+      await until(loading).toBe(false)
+      return couponList.value.Data
+    }
+
+    // 领取优惠券
+    const receiveCoupon = async (couponid: string) => {
+      const { data: couponList, loading } = useRequest(() => receiveCouponApi(couponid), {
+        immediate: true,
+      })
+
+      await until(loading).toBe(false)
+      return couponList.value
+    }
+
+    // 获取该用户下,已领取的优惠劵id,用于判断是否可以领取
+    const getCoupon2id = async (params) => {
+      const { data: couponList, loading } = useRequest(() => getCoupon2idApi(params), {
+        immediate: true,
+      })
+
+      await until(loading).toBe(false)
+      return couponList.value
+    }
+
+    return {
+      getCouponList,
+      receiveCoupon,
+      getCoupon2id,
+    }
+  },
+  {
+    persist: true,
+  },
+)

+ 54 - 0
src/store/order.ts

@@ -0,0 +1,54 @@
+import { defineStore } from 'pinia'
+import { getOrderDetailApi, getOrderListApi, submitOrderApi } from '@/service/order'
+import { until } from '@vueuse/core'
+
+export const useOrderStore = defineStore(
+  'order',
+  () => {
+    // 获取订单列表
+    const getOrderList = async (ordersuserid: string) => {
+      const { data: orderList, loading } = useRequest(
+        () => getOrderListApi({ ordersuserid }, { pageindex: 1, rows: 999 }),
+        {
+          immediate: true,
+        },
+      )
+
+      await until(loading).toBe(false)
+      return orderList.value.Data
+    }
+
+    // 获取订单详情
+    const getOrderDetail = async (ordersid: string) => {
+      const { data: orderDetail, loading } = useRequest(() => getOrderDetailApi(ordersid), {
+        immediate: true,
+      })
+
+      await until(loading).toBe(false)
+      return orderDetail.value
+    }
+
+    // 使用优惠劵提交订单
+    const submitOrder = async (params: {
+      ordersproductid: string
+      orderscouponid: string
+      ordersproductsn: string
+    }) => {
+      const { data: order, loading } = useRequest(() => submitOrderApi(params), {
+        immediate: true,
+      })
+
+      await until(loading).toBe(false)
+      return order.value
+    }
+
+    return {
+      getOrderList,
+      getOrderDetail,
+      submitOrder,
+    }
+  },
+  {
+    persist: true,
+  },
+)

+ 11 - 2
src/store/product.ts

@@ -1,7 +1,5 @@
 import { defineStore } from 'pinia'
-import { ref } from 'vue'
 import { getProductDetailApi, getProductListApi } from '@/service/product'
-import type { ProductType } from '@/types/product'
 import { until } from '@vueuse/core'
 
 export const useProductStore = defineStore(
@@ -20,8 +18,19 @@ export const useProductStore = defineStore(
       return productList.value.Data
     }
 
+    // 获取产品详情
+    const getProductDetail = async (productsid: string) => {
+      const { data: productDetail, loading } = useRequest(() => getProductDetailApi(productsid), {
+        immediate: true,
+      })
+
+      await until(loading).toBe(false)
+      return productDetail.value
+    }
+
     return {
       getProductList,
+      getProductDetail,
     }
   },
   {

+ 5 - 1
src/store/user.ts

@@ -24,7 +24,11 @@ export const useUserStore = defineStore(
     // 是否已完善资料 (身份证或统一社会信用代码是否为空)
     const isAuthComplete = computed(() => {
       if (!userDetail.value.userstype) return false
-      return !!userDetail.value.usersidcardnumber || !!userDetail.value.usersshtyxydm
+      if (userDetail.value.userstype === '个人') {
+        return !!userDetail.value.usersidcardnumber
+      } else {
+        return !!userDetail.value.usersshtyxydm
+      }
     })
 
     const setUserInfo = (val: IUserInfo) => {

+ 29 - 0
src/types/coupon1.ts

@@ -0,0 +1,29 @@
+// CREATE TABLE `coupon1` (
+//     `couponid` varchar(50) NOT NULL COMMENT '优惠券流水号',
+//     `couponmc` varchar(50) DEFAULT NULL COMMENT '优惠券名称',
+//     `couponproductids` varchar(5000) DEFAULT NULL COMMENT '优惠券可用产品',
+//     `couponsfky` tinyint(2) DEFAULT NULL COMMENT '优惠券是否可用',
+//     `couponcreatedate` datetime DEFAULT NULL COMMENT '优惠券创建时间',
+//     `couponcreateuser` varchar(50) DEFAULT NULL COMMENT '优惠券创建人',
+//     `couponupdate` datetime DEFAULT NULL COMMENT '优惠券更新时间',
+//     `couponupuser` varchar(50) DEFAULT NULL COMMENT '优惠券更新人',
+//     PRIMARY KEY (`couponid`)
+//   ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='优惠券信息';
+
+export interface Coupon1Type {
+  couponid: string
+  /** 优惠券名称 */
+  couponmc: string
+  /** 优惠券可用产品 */
+  couponproductids: string
+  /** 优惠券是否可用 */
+  couponsfky: number
+  /** 优惠券创建时间 */
+  couponcreatedate: string
+  /** 优惠券创建人 */
+  couponcreateuser: string
+  /** 优惠券更新时间 */
+  couponupdate: string
+  /** 优惠券更新人 */
+  couponupuser: string
+}

+ 33 - 0
src/types/coupon2.ts

@@ -0,0 +1,33 @@
+// CREATE TABLE `coupon2` (
+//   `coupon2sid` varchar(50) NOT NULL COMMENT '优惠券id',
+//   `coupon2code` varchar(50) DEFAULT NULL COMMENT '优惠券代码',
+//   `coupon2adddatetime` datetime DEFAULT NULL COMMENT '优惠券申请时间',
+//   `coupon2reviewdatetime` datetime DEFAULT NULL COMMENT '优惠券审核时间',
+//   `coupon2userid` varchar(50) DEFAULT NULL COMMENT '关联申请人id',
+//   `coupon2sype` tinyint(2) DEFAULT NULL COMMENT '优惠券(0:申请中,1:审核通过,2:审核失败)',
+//   `coupon2isused` tinyint(2) DEFAULT NULL COMMENT '是否已使用(0:未使用,1:已使用)',
+//   `coupon2productids` varchar(5000) DEFAULT NULL COMMENT '可用产品id',
+//   `coupon2coupon1id` varchar(50) DEFAULT NULL COMMENT '关联主券id',
+//   PRIMARY KEY (`coupon2sid`) USING BTREE,
+//   KEY `couponsid` (`coupon2sid`)
+// ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='我的优惠券信息';
+
+export interface Coupon2Type {
+  coupon2sid: string
+  /** 优惠券代码 */
+  coupon2code: string
+  /** 优惠券申请时间 */
+  coupon2adddatetime: string
+  /** 优惠券审核时间 */
+  coupon2reviewdatetime: string
+  /** 关联申请人id */
+  coupon2userid: string
+  /** 优惠券类型 */
+  coupon2sype: number
+  /** 是否已使用 */
+  coupon2isused: number
+  /** 可用产品id */
+  coupon2productids: string
+  /** 关联主券id */
+  coupon2coupon1id: string
+}

+ 51 - 0
src/types/order.ts

@@ -0,0 +1,51 @@
+/** 订单信息 */
+// CREATE TABLE `orders` (
+//   `ordersid` varchar(50) NOT NULL COMMENT '订单id',
+//   `ordersnumber` varchar(50) DEFAULT NULL COMMENT '订单号',
+//   `ordersuserid` varchar(50) DEFAULT NULL COMMENT '订单关联用户id',
+//   `ordersproductid` varchar(50) DEFAULT NULL COMMENT '订单关联产品id',
+//   `ordersproductname` varchar(50) DEFAULT NULL COMMENT '产品名称',
+//   `ordersproductsn` varchar(50) DEFAULT NULL COMMENT '产品sn',
+//   `orderstotalprice` decimal(10,2) DEFAULT NULL COMMENT '订单总金额',
+//   `ordersdiscountprice` decimal(10,2) DEFAULT NULL COMMENT '订单优惠后金额',
+//   `ordersyhprice` decimal(10,2) DEFAULT NULL COMMENT '优惠金额',
+//   `orderscouponid` varchar(50) DEFAULT NULL COMMENT '优惠卷id',
+//   `ordersorderstatus` tinyint(2) DEFAULT NULL COMMENT '订单状态(0:待审核,1:已支付,2:已完成)',
+//   `ordersorderdate` datetime DEFAULT NULL COMMENT '下单时间',
+//   PRIMARY KEY (`ordersid`),
+//   KEY `ordersuserid` (`ordersuserid`),
+//   KEY `ordersproductid` (`ordersproductid`),
+//   KEY `orderscouponid` (`orderscouponid`),
+//   CONSTRAINT `orderscouponid` FOREIGN KEY (`orderscouponid`) REFERENCES `coupon2` (`coupon2sid`) ON UPDATE NO ACTION,
+//   CONSTRAINT `ordersproductid` FOREIGN KEY (`ordersproductid`) REFERENCES `products` (`productsid`) ON UPDATE NO ACTION,
+//   CONSTRAINT `ordersuserid` FOREIGN KEY (`ordersuserid`) REFERENCES `users` (`usersid`) ON UPDATE NO ACTION
+// ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单信息';
+
+interface OrderType {
+  /** 订单id */
+  ordersid: string
+  /** 订单号 */
+  ordersnumber: string
+  /** 订单关联用户id */
+  ordersuserid: string
+  /** 订单关联产品id */
+  ordersproductid: string
+  /** 产品名称 */
+  ordersproductname: string
+  /** 产品sn */
+  ordersproductsn: string
+  /** 订单总金额 */
+  orderstotalprice: number
+  /** 订单优惠后金额 */
+  ordersdiscountprice: number
+  /** 优惠金额 */
+  ordersyhprice: number
+  /** 优惠卷id */
+  orderscouponid: string
+  /** 订单状态 */
+  ordersorderstatus: number
+  /** 下单时间 */
+  ordersorderdate: string
+}
+
+export type { OrderType }

+ 152 - 0
src/types/product-user-scqy.ts

@@ -0,0 +1,152 @@
+// select
+//     `dzlyj-wxapp`.`products`.`productsid` AS `productsid`,
+//     `dzlyj-wxapp`.`products`.`productsname` AS `productsname`,
+//     `dzlyj-wxapp`.`products`.`productscategory` AS `productscategory`,
+//     `dzlyj-wxapp`.`products`.`productsprice` AS `productsprice`,
+//     `dzlyj-wxapp`.`products`.`productsmodel` AS `productsmodel`,
+//     `dzlyj-wxapp`.`products`.`productssn` AS `productssn`,
+//     `dzlyj-wxapp`.`products`.`productsmerchantid` AS `productsmerchantid`,
+//     `dzlyj-wxapp`.`products`.`productsdate` AS `productsdate`,
+//     `dzlyj-wxapp`.`products`.`productsscqyid` AS `productsscqyid`,
+//     `dzlyj-wxapp`.`products`.`productsfl1` AS `productsfl1`,
+//     `dzlyj-wxapp`.`products`.`productsfl2` AS `productsfl2`,
+//     `dzlyj-wxapp`.`products`.`productspm` AS `productspm`,
+//     `dzlyj-wxapp`.`products`.`productsfdmc` AS `productsfdmc`,
+//     `dzlyj-wxapp`.`products`.`productsfdbh` AS `productsfdbh`,
+//     `dzlyj-wxapp`.`products`.`productszybt` AS `productszybt`,
+//     `dzlyj-wxapp`.`products`.`productstsxzybt` AS `productstsxzybt`,
+//     `dzlyj-wxapp`.`products`.`productsjjlx` AS `productsjjlx`,
+//     `dzlyj-wxapp`.`users`.`usersid` AS `usersid`,
+//     `dzlyj-wxapp`.`users`.`usersname` AS `usersname`,
+//     `dzlyj-wxapp`.`users`.`usersnature` AS `usersnature`,
+//     `dzlyj-wxapp`.`users`.`userssuperiorid` AS `userssuperiorid`,
+//     `dzlyj-wxapp`.`users`.`usersidcardnumber` AS `usersidcardnumber`,
+//     `dzlyj-wxapp`.`users`.`usersbankname` AS `usersbankname`,
+//     `dzlyj-wxapp`.`users`.`usersbanknumber` AS `usersbanknumber`,
+//     `dzlyj-wxapp`.`users`.`usersphone` AS `usersphone`,
+//     `dzlyj-wxapp`.`users`.`usersemail` AS `usersemail`,
+//     `dzlyj-wxapp`.`users`.`usersaddress` AS `usersaddress`,
+//     `dzlyj-wxapp`.`users`.`userscontactphone` AS `userscontactphone`,
+//     `dzlyj-wxapp`.`users`.`userscontactemail` AS `userscontactemail`,
+//     `dzlyj-wxapp`.`users`.`userscontactaddress` AS `userscontactaddress`,
+//     `dzlyj-wxapp`.`users`.`usersopenid` AS `usersopenid`,
+//     `dzlyj-wxapp`.`users`.`usersauthstatus` AS `usersauthstatus`,
+//     `dzlyj-wxapp`.`users`.`usersdate` AS `usersdate`,
+//     `dzlyj-wxapp`.`users`.`userstype` AS `userstype`,
+//     `dzlyj-wxapp`.`users`.`usersfrdbdh` AS `usersfrdbdh`,
+//     `dzlyj-wxapp`.`users`.`usersfrdbsjh` AS `usersfrdbsjh`,
+//     `dzlyj-wxapp`.`users`.`usersxssjh` AS `usersxssjh`,
+//     `dzlyj-wxapp`.`users`.`usersxsdh` AS `usersxsdh`,
+//     `dzlyj-wxapp`.`users`.`usersshtyxydm` AS `usersshtyxydm`,
+//     `dzlyj-wxapp`.`users`.`userszcd` AS `userszcd`,
+//     `dzlyj-wxapp`.`users`.`userscz` AS `userscz`,
+//     `dzlyj-wxapp`.`users`.`usersbz` AS `usersbz`,
+//     `dzlyj-wxapp`.`scqyinfo`.`scqyinfoid` AS `scqyinfoid`,
+//     `dzlyj-wxapp`.`scqyinfo`.`scqyinfomc` AS `scqyinfomc`,
+//     `dzlyj-wxapp`.`scqyinfo`.`scqyinfoaddress` AS `scqyinfoaddress`,
+//     `dzlyj-wxapp`.`scqyinfo`.`scqyinfofrmc` AS `scqyinfofrmc`,
+//     `dzlyj-wxapp`.`scqyinfo`.`scqyinfomail` AS `scqyinfomail`,
+//     `dzlyj-wxapp`.`scqyinfo`.`scqyinfoxsmc` AS `scqyinfoxsmc`,
+//     `dzlyj-wxapp`.`scqyinfo`.`scqyinfoxsphone` AS `scqyinfoxsphone`,
+//     `dzlyj-wxapp`.`scqyinfo`.`scqyinfodate` AS `scqyinfodate`
+
+export interface ProductUserScqyType {
+  /** 产品id */
+  productsid: string
+  /** 产品名称 */
+  productsname: string
+  /** 产品类别 */
+  productscategory: string
+  /** 产品原价 */
+  productsprice: number
+  /** 产品型号 */
+  productsmodel: string
+  /** 产品序列号 */
+  productssn: string
+  /** 产品商户id */
+  productsmerchantid: string
+  /** 产品创建时间 */
+  productsdate: string
+  /** 产品所属企业id */
+  productsscqyid: string
+  /** 产品一级分类 */
+  productsfl1: string
+  /** 产品二级分类 */
+  productsfl2: string
+  /** 产品品目 */
+  productspm: string
+  /** 产品分档编号 */
+  productsfdbh: string
+  /** 中央补贴金额 */
+  productszybt: number
+  /** 特殊县中央补贴金额 */
+  productstsxzybt: number
+  /** 机具类型 */
+  productsjjlx: string
+  /** 用户id */
+  usersid: string
+  /** 用户名称 */
+  usersname: string
+  /** 用户性质 */
+  usersnature: string
+  /** 用户关联上级id */
+  userssuperiorid: string
+  /** 用户证件号码 */
+  usersidcardnumber: string
+  /** 用户开户银行名称 */
+  usersbankname: string
+  /** 用户开户银行账号 */
+  usersbanknumber: string
+  /** 用户手机号 */
+  usersphone: string
+  /** 用户邮箱 */
+  usersemail: string
+  /** 用户地址 */
+  usersaddress: string
+  /** 用户联系手机号 */
+  userscontactphone: string
+  /** 用户联系邮箱 */
+  userscontactemail: string
+  /** 用户联系地址 */
+  userscontactaddress: string
+  /** 用户微信openid */
+  usersopenid: string
+  /** 用户是否实名 */
+  usersauthstatus: number
+  /** 用户创建时间 */
+  usersdate: string
+  /** 用户类型 */
+  userstype: string
+  /** 法人代表电话(座机) */
+  usersfrdbdh: string
+  /** 法人代表手机号 */
+  usersfrdbsjh: string
+  /** 销售手机号 */
+  usersxssjh: string
+  /** 销售电话(座机) */
+  usersxsdh: string
+  /** 社会统一企业代码 */
+  usersshtyxydm: string
+  /** 企业注册地 */
+  userszcd: string
+  /** 传真 */
+  userscz: string
+  /** 备注 */
+  usersbz: string
+  /** 企业信息id */
+  scqyinfoid: string
+  /** 企业名称 */
+  scqyinfomc: string
+  /** 企业地址 */
+  scqyinfoaddress: string
+  /** 企业法人代表 */
+  scqyinfofrmc: string
+  /** 企业邮箱 */
+  scqyinfomail: string
+  /** 企业销售员 */
+  scqyinfoxsmc: string
+  /** 企业销售员手机号 */
+  scqyinfoxsphone: string
+  /** 企业信息创建时间 */
+  scqyinfodate: string
+}

+ 3 - 0
src/types/uni-pages.d.ts

@@ -5,11 +5,14 @@
 
 interface NavigateToOptions {
   url: "/pages/index/index" |
+       "/pages/about/index" |
        "/pages/form/formStep1" |
        "/pages/form/formStep2" |
        "/pages/form/formStep3" |
        "/pages/form/formStep4" |
        "/pages/mine/index" |
+       "/pages/order/detail" |
+       "/pages/order/index" |
        "/pages/product/detail" |
        "/pages-sub/auth/index" |
        "/pages-sub/user/index";

+ 2 - 0
src/utils/http.ts

@@ -23,6 +23,8 @@ export const http = <T>(options: CustomRequestOptions & { formatData?: boolean }
       // #endif
       // 响应成功
       success(res) {
+        console.log('响应成功:', options, res)
+
         const { Status, Message, Data } = res.data as any
 
         // 2. http的状态码 状态码 2xx,参考 axios 的设计

+ 1 - 0
src/utils/request.ts

@@ -16,6 +16,7 @@ const http = <T>(options: CustomRequestOptions) => {
       // #endif
       // 响应成功
       success(res) {
+        console.log('请求成功:', res)
         // 状态码 2xx,参考 axios 的设计
         if (res.statusCode >= 200 && res.statusCode < 300) {
           // 2.1 提取核心数据 res.data