Sfoglia il codice sorgente

feat(api): 增加支持加油相关接口及类型定义

- 更新开发环境API基础URL
- 修改alova配置中的OpenAPI地址
- 扩充apiDefinitions.ts,新增多项加油平台相关接口定义
- 优化handleAlovaResponse,针对特定错误码显示toast并抛出异常
- 大量新增加油业务相关的请求/响应类型定义,包括订单、优惠券、油品价格、门店等
- 增加验证码接口相关类型定义
- 新增加油订单创建、取消、支付、退款等接口请求响应结构
- 完善用户信息、优惠券信息、订单促销信息等复杂结构定义
- 所有新增接口均遵循固定开放渠道参数规范,支持外部用户标识及门店参数
zhangtao 1 settimana fa
parent
commit
f82b1c4fec

+ 2 - 1
.env.development

@@ -2,7 +2,8 @@
 # 在开发模式下使用 (npm run dev)
 
 # API 基础 URL - 开发环境
-VITE_API_BASE_URL=http://192.168.0.11:8080
+VITE_API_BASE_URL=http://192.168.0.19:8080
+# VITE_API_BASE_URL=http://192.168.0.11:8080
 
 # 静态资源基础 URL - 测试环境
 VITE_STATIC_BASE_URL=https://zswl-smqjh.oss-cn-chengdu.aliyuncs.com/static/static

+ 1 - 1
alova.config.ts

@@ -13,7 +13,7 @@ export default <Config>{
        * 1. openapi json file url
        * 2. local file
        */
-      input: 'http://127.0.0.1:4523/export/openapi/2?version=2.0',
+      input: 'http://127.0.0.1:4523/export/openapi/4?version=2.0',
       /**
        * input file platform. Currently only swagger is supported.
        * When this parameter is specified, the input field only needs to specify the document address without specifying the openapi file

+ 75 - 1
src/api/apiDefinitions.ts

@@ -24,5 +24,79 @@ export default {
   'app.get_smqjh_system_app_api_coupon_exchangepoints': ['GET', '/smqjh-system/app-api/coupon/exchangePoints'],
   'general.post_smqjh_auth_oauth2_token': ['POST', '/smqjh-auth/oauth2/token'],
   'general.post_smqjh_auth_api_v1_auth_sms_code': ['POST', '/smqjh-auth/api/v1/auth/sms_code'],
-  'general.get_smqjh_system_app_api_v1_members_me': ['GET', '/smqjh-system/app-api/v1/members/me']
+  'general.get_api_v1_auth_captcha': ['GET', '/api/v1/auth/captcha'],
+  'general.post_api_v1_auth_sms_code': ['POST', '/api/v1/auth/sms_code'],
+  'general.get_smqjh_system_app_api_v1_members_me': ['GET', '/smqjh-system/app-api/v1/members/me'],
+  'general.post_smqjh_pms_api_v1_refueling_querytoken': ['POST', '/smqjh-pms/api/v1/refueling/queryToken'],
+  'general.post_smqjh_pms_api_v1_refueling_querystoreprice': ['POST', '/smqjh-pms/api/v1/refueling/queryStorePrice'],
+  'general.post_smqjh_pms_api_v1_refueling_querystoredetail': ['POST', '/smqjh-pms/api/v1/refueling/queryStoreDetail'],
+  'general.post_smqjh_pms_api_v1_refueling_querycalprice': ['POST', '/smqjh-pms/api/v1/refueling/queryCalPrice'],
+  'general.post_smqjh_pms_api_v1_refueling_querycalprices': ['POST', '/smqjh-pms/api/v1/refueling/queryCalPrices'],
+  'general.post_smqjh_pms_api_v1_refueling_queryneworder': ['POST', '/smqjh-pms/api/v1/refueling/queryNewOrder'],
+  'general.post_smqjh_pms_api_v1_refueling_cancelorder': ['POST', '/smqjh-pms/api/v1/refueling/cancelOrder'],
+  'general.post_smqjh_pms_api_v1_refueling_getpromotion': ['POST', '/smqjh-pms/api/v1/refueling/getPromotion'],
+  'general.post_smqjh_pms_api_v1_refueling_queryorderpromotionlist': [
+    'POST',
+    '/smqjh-pms/api/v1/refueling/queryOrderPromotionList'
+  ],
+  'general.post_smqjh_pms_api_v1_refueling_queryuserpromotionlist': [
+    'POST',
+    '/smqjh-pms/api/v1/refueling/queryUserPromotionList'
+  ],
+  'general.post_smqjh_pms_api_v1_refueling_generateqrcode': ['POST', '/smqjh-pms/api/v1/refueling/generateQrCode'],
+  'general.post_smqjh_pms_api_v1_refueling_receivinggasstation': [
+    'POST',
+    '/smqjh-pms/api/v1/refueling/receivingGasStation'
+  ],
+  'general.post_smqjh_pms_api_v1_refueling_notifyorderinfo': ['POST', '/smqjh-pms/api/v1/refueling/notifyOrderInfo'],
+  'general.post_api_v1_refueling_querytoken': ['POST', '/api/v1/refueling/queryToken'],
+  'general.post_api_v1_refueling_querystoreprice': ['POST', '/api/v1/refueling/queryStorePrice'],
+  'general.post_api_v1_refueling_querystoredetail': ['POST', '/api/v1/refueling/queryStoreDetail'],
+  'general.post_api_v1_refueling_querycalprice': ['POST', '/api/v1/refueling/queryCalPrice'],
+  'general.post_api_v1_refueling_querycalprices': ['POST', '/api/v1/refueling/queryCalPrices'],
+  'general.post_api_v1_refueling_queryneworder': ['POST', '/api/v1/refueling/queryNewOrder'],
+  'general.post_api_v1_refueling_cancelorder': ['POST', '/api/v1/refueling/cancelOrder'],
+  'general.post_api_v1_refueling_getpromotion': ['POST', '/api/v1/refueling/getPromotion'],
+  'general.post_api_v1_refueling_queryorderpromotionlist': ['POST', '/api/v1/refueling/queryOrderPromotionList'],
+  'general.post_api_v1_refueling_queryuserpromotionlist': ['POST', '/api/v1/refueling/queryUserPromotionList'],
+  'general.post_api_v1_refueling_generateqrcode': ['POST', '/api/v1/refueling/generateQrCode'],
+  'general.post_api_v1_refueling_receivinggasstation': ['POST', '/api/v1/refueling/receivingGasStation'],
+  'general.post_api_v1_refueling_notifyorderinfo': ['POST', '/api/v1/refueling/notifyOrderInfo'],
+  'general.post_api_v1_refueling_savepushproductoil': ['POST', '/api/v1/refueling/savePushProductOil'],
+  'general.post_smqjh_pms_app_api_v1_product_oil_savepushproductoil': [
+    'POST',
+    '/smqjh-pms/app-api/v1/product_oil/savePushProductOil'
+  ],
+  'general.post_smqjh_pms_app_api_v1_product_oil_querystoredetail': [
+    'POST',
+    '/smqjh-pms/app-api/v1/product_oil/queryStoreDetail'
+  ],
+  'general.post_smqjh_pms_app_api_v1_product_oil_page': ['POST', '/smqjh-pms/app-api/v1/product_oil/page'],
+  'general.post_smqjh_pms_app_api_v1_product_oil_querydistancefence': [
+    'POST',
+    '/smqjh-pms/app-api/v1/product_oil/queryDistanceFence'
+  ],
+  'general.post_app_api_v1_product_oil_savepushproductoil': ['POST', '/app-api/v1/product_oil/savePushProductOil'],
+  'general.post_app_api_v1_product_oil_page': ['POST', '/app-api/v1/product_oil/page'],
+  'general.post_app_api_v1_product_oil_querystoredetail': ['POST', '/app-api/v1/product_oil/queryStoreDetail'],
+  'general.post_smqjh_pms_app_api_v1_product_oil_querycalprice': [
+    'POST',
+    '/smqjh-pms/app-api/v1/product_oil/queryCalPrice'
+  ],
+  'general.post_app_api_v1_product_oil_querydistancefence': ['POST', '/app-api/v1/product_oil/queryDistanceFence'],
+  'general.post_smqjh_oms_api_v1_oil_order_createorder': ['POST', '/smqjh-oms/api/v1/oil/order/createOrder'],
+  'general.post_smqjh_oms_api_v1_oil_order_cancel': ['POST', '/smqjh-oms/api/v1/oil/order/cancel'],
+  'general.post_smqjh_oms_api_v1_oil_order_pay': ['POST', '/smqjh-oms/api/v1/oil/order/pay'],
+  'general.post_smqjh_oms_api_v1_oil_order_refundorder': ['POST', '/smqjh-oms/api/v1/oil/order/refundOrder'],
+  'general.post_api_v1_oil_order_findoilorderpage': ['POST', '/api/v1/oil/order/findOilOrderPage'],
+  'general.post_api_v1_oil_order_createorder': ['POST', '/api/v1/oil/order/createOrder'],
+  'general.post_api_v1_oil_order_cancel': ['POST', '/api/v1/oil/order/cancel'],
+  'general.post_api_v1_oil_order_invoiceorder': ['POST', '/api/v1/oil/order/invoiceOrder'],
+  'general.post_api_v1_oil_order_pay': ['POST', '/api/v1/oil/order/pay'],
+  'general.post_api_v1_oil_order_scantimeoutcancelorder': ['POST', '/api/v1/oil/order/scanTimeoutCancelOrder'],
+  'general.post_api_v1_oil_order_refundorder': ['POST', '/api/v1/oil/order/refundOrder'],
+  'general.get_smqjh_oms_api_v1_oil_order_payresultinfo': ['GET', '/smqjh-oms/api/v1/oil/order/payResultInfo'],
+  'general.get_api_v1_oil_order_payresultinfo': ['GET', '/api/v1/oil/order/payResultInfo'],
+  'general.get_api_v1_oil_order_checkonpayorder': ['GET', '/api/v1/oil/order/checkOnPayOrder'],
+  'general.post_api_v1_oil_callback_third_party': ['POST', '/api/v1/oil/callback/third-party']
 };

+ 4 - 1
src/api/core/handlers.ts

@@ -31,7 +31,6 @@ export async function handleAlovaResponse(
   const globalToast = useGlobalToast()
   // Extract status code and data from UniApp response
   const { statusCode, data } = response as UniNamespace.RequestSuccessCallbackResult
-
   // 处理401/403错误(如果不是在handleAlovaResponse中处理的)
   if ((statusCode === 401 || statusCode === 403)) {
     // 如果是未授权错误,清除用户信息并跳转到登录页
@@ -53,6 +52,10 @@ export async function handleAlovaResponse(
   // The data is already parsed by UniApp adapter
   const json = data as ApiResponse
   // Log response in development
+  if (json.code as unknown as string === 'B0001') {
+    globalToast.error(json.msg as string)
+    throw new ApiError(`Request failed with status: ${json.msg}`, json.code, json.data)
+  }
   if (import.meta.env.MODE === 'development') {
     console.log('[Alova Response]', json)
   }

File diff suppressed because it is too large
+ 4809 - 209
src/api/globals.d.ts


+ 1 - 0
src/components.d.ts

@@ -25,6 +25,7 @@ declare module 'vue' {
     WdRadio: typeof import('wot-design-uni/components/wd-radio/wd-radio.vue')['default']
     WdRadioGroup: typeof import('wot-design-uni/components/wd-radio-group/wd-radio-group.vue')['default']
     WdSticky: typeof import('wot-design-uni/components/wd-sticky/wd-sticky.vue')['default']
+    WdSwiper: typeof import('wot-design-uni/components/wd-swiper/wd-swiper.vue')['default']
     WdTabbar: typeof import('wot-design-uni/components/wd-tabbar/wd-tabbar.vue')['default']
     WdTabbarItem: typeof import('wot-design-uni/components/wd-tabbar-item/wd-tabbar-item.vue')['default']
     WdToast: typeof import('wot-design-uni/components/wd-toast/wd-toast.vue')['default']

+ 317 - 183
src/pages/confirmOrder/index.vue

@@ -1,226 +1,360 @@
 <script setup lang="ts">
+import type { GasStationDetailVO, QueryCalPriceResponse } from '@/api/globals'
+
 definePage({ name: 'confimOrder', islogin: true, style: { navigationBarTitleText: '下单', navigationStyle: 'custom' } })
 const showModel = ref(false)
 const refuelNumber = ref()
 const refuelGun = ref()
 const showModelJf = ref(false)
 const selectDk = ref()
+const storeDetail = ref<GasStationDetailVO>()
+const isSelect = ref(false)
+const refuelMoney = ref(null)
+const showModelReful = ref(false)
+const { lat, lng } = storeToRefs(useUserStore())
+const ThreePrice = ref<QueryCalPriceResponse>()
+onLoad(async (options: any) => {
+  await getData(options.storeId)
+})
+
+async function getData(storeId: string) {
+  const res = await Apis.general.post_smqjh_pms_app_api_v1_product_oil_querystoredetail({ data: { storeId, lat: useUserStore().lat, lon: useUserStore().lng } })
+  storeDetail.value = res.data
+  refuelNumber.value = res.data?.itemInfoList ? res.data?.itemInfoList[0].itemId : null
+}
+
+const refuelGunList = computed(() => {
+  return storeDetail.value?.itemInfoList ? storeDetail.value?.itemInfoList.find(item => item.itemId === refuelNumber.value)?.gunNos : []
+})
+const priceData = computed(() => {
+  return storeDetail.value?.itemInfoList ? storeDetail.value?.itemInfoList.find(item => item.itemId === refuelNumber.value) : null
+})
+function handlePay() {
+  if (!refuelGun.value) {
+    return useGlobalToast().show('请选择油枪')
+  }
+  if (!refuelMoney.value) {
+    return useGlobalToast().show('请输入加油金额')
+  }
+  if (Number(storeDetail.value?.distanceShow) > 1) {
+    useGlobalMessage().confirm({
+      title: '提示',
+      msg: '您距离加油站过远,请在油站附近下单',
+      confirmButtonText: '确认',
+      cancelButtonText: '取消',
+      success: async () => {
+        const { data } = await Apis.general.post_smqjh_pms_app_api_v1_product_oil_querydistancefence({ data: { lat: lat.value, lon: lng.value } })
+        if (data?.isClosest) {
+          showModelReful.value = true
+        }
+        else {
+          goPay()
+        }
+      },
+    })
+  }
+  else {
+    goPay()
+  }
+  console.log('handlePay')
+}
+async function handleBlur() {
+  if (Number(refuelMoney.value) < 10) {
+    return useGlobalToast().show('最小金额为10元')
+  }
+  if (!storeDetail.value)
+    return
+  const nams = storeDetail.value?.itemInfoList?.find(item => item.itemId === refuelNumber.value)?.itemName
+  const { data } = await Apis.general.post_smqjh_pms_api_v1_refueling_querycalprice({ data: {
+    storeId: storeDetail.value?.storeId as string,
+    itemName: nams as string,
+    amount: Number(refuelMoney.value) * 100,
+    openChannel: 0,
+    outUserId: '',
+    mobile: '',
+  } })
+  ThreePrice.value = data
+  console.log(data)
+}
+async function goPay() {
+  uni.showLoading({ mask: true })
+  try {
+    const res = await Apis.general.post_smqjh_oms_api_v1_oil_order_createorder({ data: {
+      lat: lat.value,
+      lon: lng.value,
+      itemId: refuelNumber.value,
+      gunNo: refuelGun.value,
+      originalAmount: Number(ThreePrice.value?.totalPrice),
+      paymentAmount: Number(ThreePrice.value?.realPrice),
+      promotionAmount: Number(ThreePrice.value?.promotionAmount),
+      litre: Number(ThreePrice.value?.litre),
+      serviceFee: Number(ThreePrice.value?.serviceFee),
+      totalPrice: Number(ThreePrice.value?.totalPrice),
+      vipPrice: Number(priceData.value?.vipPrice),
+      cityPrice: Number(priceData.value?.cityPrice),
+      storePrice: Number(priceData.value?.storePrice),
+      storeId: storeDetail.value?.storeId,
+      itemName: priceData.value?.itemName,
+    } })
+    uni.hideLoading()
+    // #ifdef H5
+    window.location.href = res.data as string
+    // #endif
+  }
+  catch {
+    uni.hideLoading()
+  }
+}
 </script>
 
 <template>
-  <view class="p24rpx">
-    <view class="rounded-16rpx bg-white px24rpx py28rpx">
-      <view class="text-36rpx font-semibold">
-        中国石化 | 富源加油站
-      </view>
-      <view class="mt20rpx text-#aaa">
-        西湖区文三路100号
-      </view>
-      <view class="my24rpx h2rpx w-full bg-#F0F0F0" />
-      <view class="flex items-center justify-between">
-        <view class="text-#ff4d3a font-semibold">
-          平台价
+  <view v-if="storeDetail">
+    <view class="p24rpx">
+      <view class="rounded-16rpx bg-white px24rpx py28rpx">
+        <view class="text-36rpx font-semibold">
+          {{ storeDetail?.storeName }}
         </view>
-        <view class="text-#aaa">
-          门店价:¥7.60/L
-        </view>
-      </view>
-      <view class="mt16rpx flex items-center justify-between">
-        <view class="text-32rpx text-#ff4d3a font-semibold">
-          ¥6.45/L
+        <view class="mt20rpx text-#aaa">
+          {{ storeDetail?.address }}
         </view>
-        <view class="text-#aaa">
-          国标价:¥7.20/L
-        </view>
-      </view>
-    </view>
-    <view class="mt20rpx rounded-16rpx bg-white px24rpx py28rpx">
-      <view class="text-28rpx font-semibold">
-        选择油号/油枪
-      </view>
-      <view class="mt24rpx flex items-center" @click="showModel = true">
-        <view class="relative w47% rounded-8rpx bg-#F9F9F9 px24rpx py20rpx">
-          <view class="text-center text-28rpx font-semibold">
-            请选择油号
+        <view class="my24rpx h2rpx w-full bg-#F0F0F0" />
+        <view class="flex items-center justify-between">
+          <view class="text-#ff4d3a font-semibold">
+            平台价
           </view>
-          <view class="absolute right-24rpx top-50% h32rpx w32rpx -transform-translate-y-50%">
-            <wd-icon name="arrow-down" size="32rpx" />
+          <view class="text-#aaa">
+            门店价:¥{{ priceData?.storePriceShow || 0 }}/L
           </view>
         </view>
-        <view class="relative ml18rpx w47% rounded-8rpx bg-#F9F9F9 px24rpx py20rpx">
-          <view class="text-center text-28rpx font-semibold">
-            请选择油枪
+        <view class="mt16rpx flex items-center justify-between">
+          <view class="text-32rpx text-#ff4d3a font-semibold">
+            ¥{{ priceData?.vipPriceShow || 0 }}/L
           </view>
-          <view class="absolute right-24rpx top-50% h32rpx w32rpx -transform-translate-y-50%">
-            <wd-icon name="arrow-down" size="32rpx" />
+          <view class="text-#aaa">
+            国标价:¥{{ priceData?.cityPriceShow || 0 }}/L
           </view>
         </view>
       </view>
-    </view>
-    <view class="mt20rpx rounded-16rpx bg-white px24rpx py28rpx">
-      <view class="text-28rpx font-semibold">
-        加油金额
-      </view>
-      <view class="mt20rpx bg-#F9F9F9 px24rpx py20rpx">
-        <input type="number" class="w-full" placeholder="请输入加油金额,优惠价格计算">
-      </view>
-      <view class="mt20rpx text-#ff4d3a">
-        最小金额10元
-      </view>
-    </view>
-    <view class="mt20rpx rounded-16rpx bg-white px24rpx py28rpx">
-      <view class="flex items-center">
-        <view class="mr20rpx text-28rpx font-semibold">
-          抵扣券
+      <view class="mt20rpx rounded-16rpx bg-white px24rpx py28rpx">
+        <view class="text-28rpx font-semibold">
+          选择油号/油枪
         </view>
-        <wd-button size="small">
-          去兑换
-        </wd-button>
-      </view>
-      <view class="mt24rpx flex items-center justify-between rounded-8rpx bg-#F9F9F9 px24rpx py20rpx" @click="showModelJf = true">
-        <view class="text-28rpx text-#aaa">
-          暂无抵扣券
+        <view class="mt24rpx flex items-center" @click="showModel = true">
+          <view class="relative w47% rounded-8rpx px24rpx py20rpx" :class="[refuelNumber ? 'bg-#F6FFDF border border-#9ED605 border-solid text-#9ED605' : 'bg-#F9F9F9']">
+            <view class="text-center text-28rpx font-semibold">
+              {{ refuelNumber ? storeDetail.itemInfoList?.find(item => item.itemId === refuelNumber)?.itemName : '请选择油号' }}
+            </view>
+            <view class="absolute right-24rpx top-50% h32rpx w32rpx -transform-translate-y-50%">
+              <wd-icon name="arrow-down" size="32rpx" />
+            </view>
+          </view>
+          <view class="relative ml18rpx w47% rounded-8rpx px24rpx py20rpx" :class="[isSelect && refuelGun ? 'bg-#F6FFDF border border-#9ED605 border-solid text-#9ED605' : 'bg-#F9F9F9']">
+            <view class="text-center text-28rpx font-semibold">
+              {{ isSelect && refuelGun ? refuelGun : '请选择油枪' }}
+            </view>
+            <view class="absolute right-24rpx top-50% h32rpx w32rpx -transform-translate-y-50%">
+              <wd-icon name="arrow-down" size="32rpx" />
+            </view>
+          </view>
         </view>
-        <wd-icon name="arrow-down" size="32rpx" color="#aaa" />
-      </view>
-      <view class="mt16rpx">
-        已选:满200元可抵扣100元(最优)
-      </view>
-      <view class="mt16rpx">
-        抵扣金额:-¥100
-      </view>
-      <view class="mb20rpx mt24rpx text-32rpx font-semibold">
-        价格明细
       </view>
-      <view class="flex items-center justify-between text-28rpx">
-        <view class="text-#aaa">
+      <view class="mt20rpx rounded-16rpx bg-white px24rpx py28rpx">
+        <view class="text-28rpx font-semibold">
           加油金额
         </view>
-        <view>¥200.00</view>
-      </view>
-      <view class="mt20rpx flex items-center justify-between text-28rpx">
-        <view class="text-#aaa">
-          抵扣券
+        <view class="mt20rpx bg-#F9F9F9 px24rpx py20rpx">
+          <input v-model="refuelMoney" type="number" class="w-full" placeholder="请输入加油金额,优惠价格计算" @blur="handleBlur">
         </view>
-        <view>-¥100</view>
-      </view>
-      <view class="mt20rpx flex items-center justify-between text-28rpx">
-        <view class="text-#aaa">
-          服务费
+        <view class="mt20rpx text-#ff4d3a">
+          最小金额10元
         </view>
-        <view>+¥1.00</view>
       </view>
-
-      <view class="my24rpx h2rpx w-full bg-#F0F0F0" />
-      <view class="flex items-center justify-between text-28rpx">
-        <view class="text-#aaa">
-          实付金额
+      <view class="mt20rpx rounded-16rpx bg-white px24rpx py28rpx">
+        <view class="flex items-center">
+          <view class="mr20rpx text-28rpx font-semibold">
+            抵扣券
+          </view>
+          <wd-button size="small">
+            去兑换
+          </wd-button>
         </view>
-        <view class="text-#ff4d3a font-semibold">
-          ¥200.00
+        <view class="mt24rpx flex items-center justify-between rounded-8rpx bg-#F9F9F9 px24rpx py20rpx" @click="showModelJf = true">
+          <view class="text-28rpx text-#aaa">
+            暂无抵扣券
+          </view>
+          <wd-icon name="arrow-down" size="32rpx" color="#aaa" />
         </view>
+        <view class="mt16rpx">
+          已选:满200元可抵扣100元(最优)
+        </view>
+        <view class="mt16rpx">
+          抵扣金额:-¥100
+        </view>
+        <template v-if="ThreePrice">
+          <view class="mb20rpx mt24rpx text-32rpx font-semibold">
+            价格明细
+          </view>
+          <view class="flex items-center justify-between text-28rpx">
+            <view class="text-#aaa">
+              加油金额
+            </view>
+            <view>¥{{ refuelMoney || 0 }}</view>
+          </view>
+          <view class="mt20rpx flex items-center justify-between text-28rpx">
+            <view class="text-#aaa">
+              抵扣券
+            </view>
+            <view>-¥100</view>
+          </view>
+          <view class="mt20rpx flex items-center justify-between text-28rpx">
+            <view class="text-#aaa">
+              服务费
+            </view>
+            <view>+¥{{ ThreePrice.promotionAmount ? ThreePrice.promotionAmount / 100 : 0 }}</view>
+          </view>
+
+          <view class="my24rpx h2rpx w-full bg-#F0F0F0" />
+          <view class="flex items-center justify-between text-28rpx">
+            <view class="text-#aaa">
+              实付金额
+            </view>
+            <view class="text-#ff4d3a font-semibold">
+              ¥{{ ThreePrice?.realPrice ? ThreePrice?.realPrice / 100 : 0 }}
+            </view>
+          </view>
+        </template>
       </view>
     </view>
-  </view>
-  <view class="h200rpx" />
-  <Zpopup v-model="showModel" bg="#fff">
-    <view class="px24rpx py28rpx">
-      <view class="text-center text-32rpx font-semibold">
-        选择油号油枪
-      </view>
-      <view class="mb20rpx text-32rpx font-semibold">
-        油号
-      </view>
-      <wd-radio-group v-model="refuelNumber" shape="button">
-        <wd-radio :value="1">
-          92#
-        </wd-radio>
-        <wd-radio :value="2">
-          95#
-        </wd-radio>
-      </wd-radio-group>
-      <view class="mb20rpx mt20rpx text-32rpx font-semibold">
-        油号
-      </view>
-      <wd-radio-group v-model="refuelGun" shape="button">
-        <wd-radio :value="1">
-          1
-        </wd-radio>
-        <wd-radio :value="2">
-          2
-        </wd-radio>
-      </wd-radio-group>
-    </view>
     <view class="h200rpx" />
-    <template #footer>
-      <view class="text-center text-28rpx text-#ff4d3a">
-        请与加油员确认油枪号
-      </view>
-      <view class="my24rpx h2rpx w-full bg-#F0F0F0" />
-      <wd-button block size="large">
-        确认
-      </wd-button>
-    </template>
-  </Zpopup>
-  <Zpopup v-model="showModelJf" bg="#fff">
-    <view class="px24rpx py28rpx">
-      <view class="mb24rpx text-center text-32rpx font-semibold">
-        选择抵扣券
+    <Zpopup v-model="showModel" bg="#fff">
+      <view class="px24rpx py28rpx">
+        <view class="text-center text-32rpx font-semibold">
+          选择油号油枪
+        </view>
+        <view class="mb20rpx text-32rpx font-semibold">
+          油号
+        </view>
+        <wd-radio-group v-model="refuelNumber" shape="button">
+          <view class="grid grid-cols-5 gap-20rpx">
+            <view v-for="item in storeDetail?.itemInfoList" :key="item.itemId">
+              <wd-radio :value="String(item.itemId)">
+                {{ item.itemName }}
+              </wd-radio>
+            </view>
+          </view>
+        </wd-radio-group>
+        <view v-if="refuelGunList" class="mb20rpx mt20rpx text-32rpx font-semibold">
+          油枪
+        </view>
+        <wd-radio-group v-model="refuelGun" shape="button">
+          <scroll-view scroll-y class="h400rpx pb40rpx">
+            <view class="grid grid-cols-5 gap-20rpx">
+              <view v-for="item in refuelGunList" :key="item">
+                <wd-radio :value="String(item)">
+                  {{ item }}
+                </wd-radio>
+              </view>
+            </view>
+          </scroll-view>
+        </wd-radio-group>
       </view>
-      <wd-radio-group v-model="selectDk" shape="dot">
-        <view class="flex items-center justify-between">
-          <view class="text-28rpx">
-            不使用抵扣券
-          </view>
-          <wd-radio :value="1" />
-        </view>
-        <view class="mt24rpx">
-          <view class="text-28rpx">
-            自动推荐
-          </view>
-          <view class="relative mt20rpx box-border h144rpx flex items-center justify-between rounded-16rpx bg-[rgba(255,77,58,0.1)] px28rpx py24rpx">
-            <view class="flex-1">
-              <view class="flex items-center">
-                <view class="text-40rpx text-#ff4d3a font-semibold">
-                  <text class="text-24rpx">
-                    ¥
-                  </text> 100
+      <template #footer>
+        <view class="text-center text-28rpx text-#ff4d3a">
+          请与加油员确认油枪号
+        </view>
+        <view class="my24rpx h2rpx w-full bg-#F0F0F0" />
+        <wd-button block size="large" @click="showModel = false, isSelect = true">
+          确认
+        </wd-button>
+      </template>
+    </Zpopup>
+    <Zpopup v-model="showModelJf" bg="#fff">
+      <view class="px24rpx py28rpx">
+        <view class="mb24rpx text-center text-32rpx font-semibold">
+          选择抵扣券
+        </view>
+        <wd-radio-group v-model="selectDk" shape="dot">
+          <view class="flex items-center justify-between">
+            <view class="text-28rpx">
+              不使用抵扣券
+            </view>
+            <wd-radio :value="1" />
+          </view>
+          <view class="mt24rpx">
+            <view class="text-28rpx">
+              自动推荐
+            </view>
+            <view class="relative mt20rpx box-border h144rpx flex items-center justify-between rounded-16rpx bg-[rgba(255,77,58,0.1)] px28rpx py24rpx">
+              <view class="flex-1">
+                <view class="flex items-center">
+                  <view class="text-40rpx text-#ff4d3a font-semibold">
+                    <text class="text-24rpx">
+                      ¥
+                    </text> 100
+                  </view>
+                  <view class="ml20rpx text-32rpx font-semibold">
+                    满200元可用
+                  </view>
                 </view>
-                <view class="ml20rpx text-32rpx font-semibold">
-                  满200元可用
+                <view class="mt24rpx flex items-center text-#aaa">
+                  <view class="text-center text-20rpx">
+                    可抵扣
+                  </view>
+                  <view class="ml20rpx text-24rpx font-semibold">
+                    有效期:2022-01-01至2022-01-01
+                  </view>
                 </view>
               </view>
-              <view class="mt24rpx flex items-center text-#aaa">
-                <view class="text-center text-20rpx">
-                  可抵扣
-                </view>
-                <view class="ml20rpx text-24rpx font-semibold">
-                  有效期:2022-01-01至2022-01-01
-                </view>
+              <view class="h-full w134rpx flex items-center justify-center border-l-2rpx border-l-#FF4D3A border-l-dashed">
+                <wd-radio :value="1" />
               </view>
+              <view class="absolute right-150rpx h30rpx w30rpx rounded-full bg-white -top-10rpx" />
+              <view class="absolute right-150rpx h30rpx w30rpx rounded-full bg-white -bottom-10rpx" />
             </view>
-            <view class="h-full w134rpx flex items-center justify-center border-l-2rpx border-l-#FF4D3A border-l-dashed">
-              <wd-radio :value="1" />
-            </view>
-            <view class="absolute right-150rpx h30rpx w30rpx rounded-full bg-white -top-10rpx" />
-            <view class="absolute right-150rpx h30rpx w30rpx rounded-full bg-white -bottom-10rpx" />
           </view>
+        </wd-radio-group>
+      </view>
+      <view class="h200rpx" />
+      <template #footer>
+        <view class="my24rpx h2rpx w-full bg-#F0F0F0" />
+        <wd-button block size="large">
+          确认选择
+        </wd-button>
+      </template>
+    </Zpopup>
+    <FixedLayout>
+      <view :class="[ThreePrice && 'justify-between flex items-center']">
+        <view v-if="ThreePrice" class="text-32rpx text-#FF4A39 font-semibold">
+          <text class="text-24rpx">
+            ¥
+          </text><text>{{ ThreePrice?.realPrice ? ThreePrice?.realPrice / 100 : 0 }}</text>
         </view>
-      </wd-radio-group>
-    </view>
-    <view class="h200rpx" />
-    <template #footer>
-      <view class="my24rpx h2rpx w-full bg-#F0F0F0" />
-      <wd-button block size="large">
-        确认选择
-      </wd-button>
-    </template>
-  </Zpopup>
-  <FixedLayout>
-    <wd-button block size="large">
-      立即支付
-    </wd-button>
-  </FixedLayout>
+        <wd-button block size="large" @click="handlePay">
+          立即支付
+        </wd-button>
+      </view>
+    </FixedLayout>
+    <Zpopup v-model="showModelReful" bg="#fff">
+      <view class="px24rpx py28rpx">
+        <view class="mb24rpx text-center text-32rpx font-semibold">
+          请确认
+        </view>
+        <view>您当前位置最近的油站是</view>
+      </view>
+      <view class="h200rpx" />
+      <template #footer>
+        <view class="my24rpx h2rpx w-full bg-#F0F0F0" />
+        <view class="flex items-center justify-between pb20rpx">
+          <wd-button type="info" block size="large">
+            取消
+          </wd-button>
+          <wd-button block size="large">
+            继续
+          </wd-button>
+        </view>
+      </template>
+    </Zpopup>
+  </view>
 </template>
 
 <style lang="scss" scoped>

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

@@ -10,17 +10,35 @@ definePage({
     navigationStyle: 'custom',
   },
 })
-const staticUrl = import.meta.env.VITE_STATIC_BASE_URL
 const tabList = ref([
-  { label: '距离优先', value: 1 },
-  { label: '价格从低到高', value: 2 },
+  { label: '距离优先', value: 0 },
+  { label: '价格从低到高', value: 1 },
 ])
-const currentTab = ref(1)
+const currentTab = ref(0)
+const { data, send } = usePagination((pageNum, pageSize) => Apis.general.post_smqjh_pms_app_api_v1_product_oil_page({ data: { pageNum, pageSize, lat: useUserStore().lat, lon: useUserStore().lng, sort: currentTab.value } }), {
+  initialPage: 1,
+  initialPageSize: 10,
+  immediate: false,
+  data: res => res.data?.list,
+  append: true,
+})
+const staticUrl = import.meta.env.VITE_STATIC_BASE_URL
+
 function handleView(_item: any) {
   router.push({
     name: 'refuelDetaile',
+    params: { id: _item.storeId },
   })
 }
+
+onMounted(async () => {
+  await useUserStore().getLocationH5()
+  send()
+})
+
+watch(() => currentTab.value, () => {
+  send()
+})
 </script>
 
 <template>
@@ -36,41 +54,40 @@ function handleView(_item: any) {
       </view>
     </wd-sticky>
 
-    <view v-for="item in 10" :key="item" class="relative mb20rpx rounded-16rpx bg-white p24rpx" @click="handleView(item)">
+    <view v-for="item in data" :key="item.storeId" class="relative mb20rpx rounded-16rpx bg-white p24rpx" @click="handleView(item)">
       <view class="mt80rpx flex items-center justify-between">
         <view class="text-36rpx font-semibold">
-          中国石化 | 富源加油站
+          {{ item.storeName }}
         </view>
         <view class="flex items-center text-24rpx">
-          <image :src="`${staticUrl}/smqjh-jy-dh.png`" class="mr3 h18.34rpx w18.34rpx" />  1.9km
+          <image :src="`${staticUrl}/smqjh-jy-dh.png`" class="mr3 h18.34rpx w18.34rpx" />  {{ item.distanceShow }}km
         </view>
       </view>
       <view class="mt20rpx text-#aaa">
-        西湖区文三路100号
+        {{ item.address }}
       </view>
       <view class="mt20rpx flex items-center justify-between">
-        <view class="flex items-center rounded-8rpx bg-#FF4A39 px12rpx py8rpx">
-          <image :src="`${staticUrl}/smqjh-jy-idicon.png`" class="h30rpx w30rpx" />
-          <view class="text-22rpx text-white">
-            满200前100升半价
+        <view v-if="!item.allowanceClientScheme" class="flex items-center rounded-8rpx bg-#E6E6E6 px12rpx py8rpx">
+          <view class="text-22rpx text-#AAAAAA">
+            不支持优惠券
           </view>
         </view>
         <view class="flex items-end">
           <view class="text-28rpx">
-            92#
+            {{ item.itemName }}
           </view>
           <view class="mx8rpx ml12rpx flex items-end text-#ff4d3a">
             特惠价 <view class="font-semibold">
               <text class="text-20rpx">
               </text> <text class="text-36rpx">
-                7.36L
+                {{ item.vipPrice }}L
               </text>
             </view>
           </view>
         </view>
       </view>
-      <image :src="`${staticUrl}/smqjh-jy-cz.png`" class="absolute left-0 top-0 h80rpx w234rpx" />
+      <!-- <image :src="`${staticUrl}/smqjh-jy-cz.png`" class="absolute left-0 top-0 h80rpx w234rpx" /> -->
     </view>
     <image
       :src="`${staticUrl}/smqjh-jy-dkj.png`"

+ 93 - 77
src/pages/refuelDetaile/index.vue

@@ -1,104 +1,120 @@
 <script setup lang="ts">
+import type { GasStationDetailVO } from '@/api/globals'
 import router from '@/router'
 
 definePage({ name: 'refuelDetaile', islogin: false, style: { navigationBarTitleText: '加油站详情', navigationStyle: 'custom' } })
 const StaticUrl = import.meta.env.VITE_STATIC_BASE_URL
 const showModel = ref(false)
+const storeDetail = ref<GasStationDetailVO>()
+onLoad(async (options: any) => {
+  await getData(options.id)
+})
+
+async function getData(storeId: string) {
+  const res = await Apis.general.post_smqjh_pms_app_api_v1_product_oil_querystoredetail({ data: { storeId, lat: useUserStore().lat, lon: useUserStore().lng } })
+  storeDetail.value = res.data
+}
+function handleShowMap() {
+  console.log('show map')
+  uni.openLocation({
+    latitude: useUserStore().lat,
+    longitude: useUserStore().lng,
+    success() {
+      console.log('success')
+    },
+  })
+}
 </script>
 
 <template>
-  <view class="p24rpx">
-    <view class="h336rpx">
-      轮播占位ie
-    </view>
-    <view class="mt20rpx h160rpx flex items-center justify-between rounded-16rpx bg-white bg-cover bg-center px24rpx" :style="{ backgroundImage: `url(${StaticUrl}/djk-shop-nav-bg.png)` }">
-      <view>
-        <view class="flex items-center text-36rpx font-semibold">
-          中国石化 | 富源加油站
-        </view>
-        <view class="mt20rpx text-#aaa">
-          西湖区文三路100号
-        </view>
+  <template v-if="storeDetail">
+    <view class="p24rpx">
+      <view class="h336rpx">
+        <wd-swiper :list="storeDetail.storePicList" height="336rpx" />
       </view>
-      <view class="flex items-center">
-        <view class="mr40rpx flex flex-col items-center justify-center">
-          <image
-            :src="`${StaticUrl}/djk-shop-dh.png`"
-            class="h40rpx w40rpx"
-          />
-          <view class="mt20rpx text-28rpx">
-            导航
+      <view class="mt20rpx h160rpx flex items-center justify-between rounded-16rpx bg-white bg-cover bg-center px24rpx" :style="{ backgroundImage: `url(${StaticUrl}/djk-shop-nav-bg.png)` }">
+        <view>
+          <view class="flex items-center text-36rpx font-semibold">
+            {{ storeDetail.storeName }}
           </view>
-        </view>
-        <view class="flex flex-col items-center justify-center">
-          <image
-            :src="`${StaticUrl}/smqjh-jy-kf.png`"
-            class="h40rpx w40rpx"
-          />
-          <view class="mt20rpx text-28rpx">
-            电话
+          <view class="mt20rpx text-#aaa">
+            {{ storeDetail.address }}
           </view>
         </view>
-      </view>
-    </view>
-    <view class="mt20rpx rounded-16rpx bg-white px24rpx py28rpx">
-      <view class="flex items-center">
-        <wd-icon name="check-circle-filled" size="22px" color="#52C41A" />
-        <view class="ml20rpx text-28rpx font-semibold">
-          本站可用抵扣券
+        <view class="flex items-center">
+          <view class="mr40rpx flex flex-col items-center justify-center" @click="handleShowMap">
+            <image
+              :src="`${StaticUrl}/djk-shop-dh.png`"
+              class="h40rpx w40rpx"
+            />
+            <view class="mt20rpx text-28rpx">
+              导航
+            </view>
+          </view>
+          <view class="flex flex-col items-center justify-center">
+            <image
+              :src="`${StaticUrl}/smqjh-jy-kf.png`"
+              class="h40rpx w40rpx"
+            />
+            <view class="mt20rpx text-28rpx">
+              客服
+            </view>
+          </view>
         </view>
       </view>
-      <view class="mt24rpx flex overflow-x-scroll">
-        <view v-for="item in 10" :key="item" class="jf-box mr16rpx flex-shrink-0 rounded-16rpx p20rpx">
-          <view class="text-center text-36rpx text-#FF4D3A font-semibold">
-            <text class="text-20rpx">
-              ¥
-            </text> 50
-          </view>
-          <view class="my8rpx text-center">
-            无门槛使用
+      <view class="mt20rpx rounded-16rpx bg-white px24rpx py28rpx">
+        <view class="flex items-center">
+          <wd-icon name="check-circle-filled" size="22px" color="#52C41A" />
+          <view class="ml20rpx text-28rpx font-semibold">
+            本站可用抵扣券
           </view>
-          <view class="rounded-26rpx bg-#FF4A39 px24rpx py6rpx text-center text-white" @click="showModel = true">
-            积分兑换
+        </view>
+        <view class="mt24rpx flex overflow-x-scroll">
+          <view v-for="item in 10" :key="item" class="jf-box mr16rpx flex-shrink-0 rounded-16rpx p20rpx">
+            <view class="text-center text-36rpx text-#FF4D3A font-semibold">
+              <text class="text-20rpx">
+                ¥
+              </text> 50
+            </view>
+            <view class="my8rpx text-center">
+              无门槛使用
+            </view>
+            <view class="rounded-26rpx bg-#FF4A39 px24rpx py6rpx text-center text-white" @click="showModel = true">
+              积分兑换
+            </view>
           </view>
         </view>
       </view>
-    </view>
-    <view v-for="item in 10" :key="item" class="mt20rpx rounded-16rpx bg-white px24rpx py28rpx">
-      <view class="flex items-center justify-between">
-        <view class="text-32rpx font-semibold">
-          92#汽油
+      <view v-for="item in storeDetail.itemInfoList" :key="item.itemId" class="mt20rpx rounded-16rpx bg-white px24rpx py28rpx">
+        <view class="flex items-center justify-between">
+          <view class="text-32rpx font-semibold">
+            {{ item.itemName }}
+          </view>
+          <view class="text-36rpx text-#FF4D3A">
+            <text class="text-20rpx">
+              平台价:
+            </text> ¥{{ item.vipPriceShow }}/L
+          </view>
         </view>
-        <view class="text-36rpx text-#FF4D3A">
-          <text class="text-20rpx">
-            平台价:
-          </text> ¥6.45/L
+        <view class="text-end text-#aaa">
+          国标价:¥{{ item.cityPriceShow }}/L 门店价:¥{{ item.storePriceShow }}L
         </view>
-      </view>
-      <view class="text-end text-#aaa">
-        国标价:¥7.20/L 门店价:¥7.60L
-      </view>
-      <view class="mt24rpx w-fit flex items-center rounded-8rpx bg-#FF4A39 px12rpx py8rpx">
-        <image :src="`${StaticUrl}/smqjh-jy-idicon.png`" class="h30rpx w30rpx" />
-        <view class="text-22rpx text-white">
-          满200前100升半价
+        <!-- <view class="mt18rpx text-#aaa">
+          (加油满200原可享前10升优惠价格)
+        </view> -->
+        <view class="mt20rpx">
+          枪号:{{ item.gunNos?.join(', ') }}
         </view>
       </view>
-      <view class="mt18rpx text-#aaa">
-        (加油满200原可享前10升优惠价格)
-      </view>
-      <view class="mt20rpx">
-        枪号:1,2,3,4,5
-      </view>
+      <view class="h200rpx" />
     </view>
-    <view class="h200rpx" />
-  </view>
-  <FixedLayout>
-    <wd-button block size="large" @click="router.push({ name: 'confimOrder' })">
-      立即加油
-    </wd-button>
-  </FixedLayout>
-  <IntegralPopup v-model="showModel" />
+    <FixedLayout>
+      <wd-button block size="large" @click="router.push({ name: 'confimOrder', params: { storeId: String(storeDetail.storeId) } })">
+        立即加油
+      </wd-button>
+    </FixedLayout>
+    <IntegralPopup v-model="showModel" />
+  </template>
 </template>
 
 <style lang="scss" scoped>

+ 121 - 1
src/store/user.ts

@@ -8,6 +8,8 @@ interface userStroe {
    */
   userInfo: MemberVO
   redirectName: string
+  lat: number
+  lng: number
 }
 export const useUserStore = defineStore('user', {
   state: (): userStroe => ({
@@ -18,11 +20,129 @@ export const useUserStore = defineStore('user', {
       channelName: '',
     },
     redirectName: '',
+    lat: 0,
+    lng: 0,
+
   }),
   actions: {
 
-    wxAuthLogin() {
+    // H5 环境获取位置
+    getLocationH5() {
+      return new Promise((resolve, reject) => {
+        uni.showLoading({ mask: true })
+
+        if (!navigator.geolocation) {
+          uni.hideLoading()
+          useGlobalToast().show('当前浏览器不支持定位功能')
+          return
+        }
+        navigator.geolocation.getCurrentPosition(
+          (position) => {
+            uni.hideLoading()
+            console.log('H5位置获取成功', position)
+            this.lat = Number(position.coords.latitude.toFixed(6))
+            this.lng = Number(position.coords.longitude.toFixed(6))
+
+            resolve(true)
+          },
+          (error) => {
+            uni.hideLoading()
+            reject(new Error('获取位置失败'))
+            console.log('H5获取位置失败', error)
+            switch (error.code) {
+              case error.PERMISSION_DENIED:
+                useGlobalToast().show('用户拒绝了定位请求')
+                break
+              case error.POSITION_UNAVAILABLE:
+                useGlobalToast().show('位置信息不可用')
+                break
+              case error.TIMEOUT:
+                useGlobalToast().show('获取位置超时,请重试')
+                break
+              default:
+                useGlobalToast().show(`获取定位失败:${error.message}`)
+            }
+          },
+          {
+            enableHighAccuracy: true, // 高精度
+            timeout: 10000, // 超时时间 10秒
+            maximumAge: 0, // 不使用缓存
+          },
+        )
+      })
+    },
+
+    // 小程序环境获取位置
+    getLocationMP() {
+      uni.showLoading({ mask: true })
+      // 1. 检查当前授权状态
+      uni.getSetting({
+        success: (res) => {
+          const locationAuth = res.authSetting['scope.userLocation']
+          // 2. 已授权 - 直接获取位置
+          if (locationAuth) {
+            this.fetchActualLocation()
+            uni.hideLoading()
+          }
+          // 3. 未授权 - 尝试请求授权
+          else {
+            uni.authorize({
+              scope: 'scope.userLocation',
+              success: () => this.fetchActualLocation(),
+              fail: () => this.showAuthGuide(), // 用户拒绝,显示引导
+              complete: () => uni.hideLoading(),
+            })
+          }
+        },
+      })
+    },
+
+    // 实际获取位置的方法(小程序)
+    fetchActualLocation() {
+      uni.getLocation({
+        type: 'wgs84',
+        isHighAccuracy: true,
+        altitude: true,
+        success: (res) => {
+          console.log('位置获取成功', res)
+          this.lat = res.latitude
+          this.lng = res.longitude
+        },
+        fail: (err) => {
+          console.log(err, '获取位置失败')
+          if (err.errMsg === 'getLocation:fail system permission denied') {
+            useGlobalToast().show('手机定位权限未打开,请手动在设置里面打开定位')
+          }
+          else {
+            useGlobalToast().show(`获取定位失败:${err.errMsg}`)
+          }
+        },
+      })
+    },
 
+    // 显示授权引导(小程序)
+    showAuthGuide() {
+      uni.showModal({
+        title: '需要位置权限',
+        content: '请开启位置授权以使用完整功能',
+        confirmText: '去设置',
+        success: (res) => {
+          if (res.confirm) {
+            // 4. 用户点击确认后打开设置页
+            uni.openSetting({
+              success: (settingRes) => {
+                // 5. 检查用户是否在设置页中开启了授权
+                if (settingRes.authSetting['scope.userLocation']) {
+                  this.fetchActualLocation()
+                }
+                else {
+                  console.log('用户仍未授权')
+                }
+              },
+            })
+          }
+        },
+      })
     },
   },
 })

Some files were not shown because too many files changed in this diff