16 次代碼提交 525f48df48 ... 48a4c1b314

作者 SHA1 備註 提交日期
  zouzexu 48a4c1b314 ``` 1 天之前
  zouzexu 2f63efaeba ``` 1 天之前
  zouzexu 1299ed2f8b ``` 3 天之前
  zouzexu 9dd8461bb0 ``` 3 天之前
  zouzexu aee4e1cdc5 ``` 4 天之前
  zouzexu 07f6465a9b Merge branch 'master' into zzx 4 天之前
  zhangtao 17d23596e2 Merge branch 'zhangtao' 4 天之前
  zouzexu 885cb2e4d7 ``` 4 天之前
  zouzexu f4dc167e97 Merge remote-tracking branch 'origin/zzx' 4 天之前
  zouzexu 2f022cfb8d feat(components): 添加 WdCircle 和 WdOverlay 组件类型声明 4 天之前
  zouzexu b67570503f ``` 4 天之前
  zouzexu f460a08ae4 ``` 4 天之前
  zouzexu 97fb8da06e ``` 4 天之前
  zouzexu 0aae44409f ``` 5 天之前
  zouzexu 634aa4c694 ``` 6 天之前
  zouzexu 2daaa8b331 ``` 6 天之前
共有 31 個文件被更改,包括 3096 次插入231 次删除
  1. 1 0
      package.json
  2. 3 0
      pnpm-lock.yaml
  3. 501 0
      src/api/api.type.d.ts
  4. 13 1
      src/api/apiDefinitions.ts
  5. 117 4
      src/api/globals.d.ts
  6. 2 0
      src/components.d.ts
  7. 3 1
      src/config/index.ts
  8. 28 0
      src/package.json
  9. 70 0
      src/pages.json
  10. 1 1
      src/pages/index/index.vue
  11. 214 0
      src/subPack-charge/chargeDetail/chargeDetail.vue
  12. 169 0
      src/subPack-charge/chargeMap/chargeMap.vue
  13. 172 0
      src/subPack-charge/chargeOrderDetail/chargeOrderDetail.vue
  14. 149 0
      src/subPack-charge/chargeSearchList/chargeSearchList.vue
  15. 340 0
      src/subPack-charge/chargeSiteDetail/chargeSiteDetail.vue
  16. 139 0
      src/subPack-charge/chargeStart/chargeStart.vue
  17. 256 0
      src/subPack-charge/chargeing/chargeing.vue
  18. 86 0
      src/subPack-charge/components/charge-loading.vue
  19. 31 1
      src/subPack-charge/components/charge-tab.vue
  20. 41 21
      src/subPack-charge/components/search.vue
  21. 208 0
      src/subPack-charge/components/wlp-progress-new/wlp-progress-new.vue
  22. 147 91
      src/subPack-charge/index/index.vue
  23. 39 0
      src/subPack-charge/store-charge/sys.ts
  24. 74 0
      src/subPack-charge/utils/index.ts
  25. 45 0
      src/subPack-smqjh/components/charge-orderList/charge-orderList.vue
  26. 127 0
      src/subPack-smqjh/components/xsb-orderList/xsb-orderList.vue
  27. 62 0
      src/subPack-smqjh/order/components/OrderRenderer.vue
  28. 47 110
      src/subPack-smqjh/order/index.vue
  29. 1 0
      src/subPack-smqjh/order/order-data.ts
  30. 3 1
      src/subPack-xsb/utils/confirm-order.ts
  31. 7 0
      src/uni-pages.d.ts

+ 1 - 0
package.json

@@ -84,6 +84,7 @@
     "echarts": "^6.0.0",
     "pinia": "^2.3.1",
     "vue": "~3.4.38",
+    "vue-demi": "^0.14.10",
     "vue-i18n": "^9.14.0",
     "wot-design-uni": "^1.13.0"
   },

+ 3 - 0
pnpm-lock.yaml

@@ -85,6 +85,9 @@ importers:
       vue:
         specifier: ~3.4.38
         version: 3.4.38(typescript@5.5.4)
+      vue-demi:
+        specifier: ^0.14.10
+        version: 0.14.10(vue@3.4.38(typescript@5.5.4))
       vue-i18n:
         specifier: ^9.14.0
         version: 9.14.0(vue@3.4.38(typescript@5.5.4))

+ 501 - 0
src/api/api.type.d.ts

@@ -1471,5 +1471,506 @@ namespace Api {
     spec?: string
     [property: string]: any
   }
+  // ===============充电模块================
+  interface chargeStationInfoPage {
+    /**
+     * 充电站id
+     */
+    stationId?: number
+    /**
+     * 充电站名称
+     */
+    stationName?: string
+    /**
+     * 提示语
+     */
+    tips?: string
+    /**
+     * 快充
+     */
+    fastCharging?: string
+    /**
+     * 慢充
+     */
+    slowCharging?: string
+    /**
+     * 距离
+     */
+    distance?: number
+    /**
+     * 企业价格
+     */
+    enterprisePrice?: number
+    /**
+     * 平台价格
+     */
+    platformPrice?: number
+    /**
+     * 当前峰值
+     */
+    peakValue?: string
+    /**
+     * 时间段
+     */
+    peakTime?: string
+  }
+
+  interface chargeStationDetail {
+    /**
+     * 详细地址
+     */
+    address?: string
+    /**
+     * 营业时间(如:周一至周日 00:00-24:00)
+     */
+    businessHours?: string
+    /**
+     * 充电终端列表
+     */
+    connectorList?: ConnectorInfoVO[]
+    /**
+     * 当前时段(如:峰10:00-13:00)
+     */
+    currentPeriod?: string
+    /**
+     * 当前价(元/度)
+     */
+    currentPrice?: number
+    /**
+     * 客服热线
+     */
+    customerServiceHotline?: string
+    /**
+     * 距离(km)
+     */
+    distance?: number
+    /**
+     * 企业专享价(元/度)
+     */
+    enterprisePrice?: number
+    /**
+     * 单笔预计省(元)
+     */
+    estimatedSaving?: number
+    /**
+     * 是否企业用户
+     */
+    firmUser?: boolean
+    /**
+     * 空闲终端数
+     */
+    idleCount?: number
+    /**
+     * 发票提供方
+     */
+    invoiceProvider?: string
+    /**
+     * 纬度
+     */
+    latitude?: number
+    /**
+     * 经度
+     */
+    longitude?: number
+    /**
+     * 占用终端数
+     */
+    occupiedCount?: number
+    /**
+     * 离线终端数
+     */
+    offlineCount?: number
+    /**
+     * 原价/划线价(元/度)
+     */
+    originalPrice?: number
+    /**
+     * 站点图片列表(JSON数组)
+     */
+    pictures?: string
+    /**
+     * 服务提供方
+     */
+    serviceProvider?: string
+    /**
+     * 是否显示特惠价标签
+     */
+    showSpecialPriceTag?: boolean
+    /**
+     * 站点ID
+     */
+    stationId?: number
+    /**
+     * 站点名称
+     */
+    stationName?: string
+    /**
+     * 提示语/标签(如:充电减免2小时停车费,超出部分按每小时3元计费)
+     */
+    tips?: string
+  }
+
+  interface chargeStationPrices {
+    /**
+     * 是否有企业价格
+     */
+    hasEnterprisePrice?: boolean
+    /**
+     * 价格列表
+     */
+    priceList?: PriceItemVO[]
+    /**
+     * 站点ID
+     */
+    stationId?: number
+    /**
+     * 站点名称
+     */
+    stationName?: string
+    /**
+     * 提示语/标签(如:充电减免2小时停车费,超出部分按每小时3元计费)
+     */
+    tips?: string
+  }
+
+  interface chargeStationConnectors {
+    /**
+     * 充电终端列表
+     */
+    connectorList?: ConnectorItemVO[]
+    /**
+     * 空闲终端数
+     */
+    idleCount?: number
+    /**
+     * 占用终端数
+     */
+    occupiedCount?: number
+    /**
+     * 离线终端数
+     */
+    offlineCount?: number
+    /**
+     * 站点ID
+     */
+    stationId?: number
+    /**
+     * 站点名称
+     */
+    stationName?: string
+    /**
+     * 提示语/标签(如:充电减免2小时停车费,超出部分按每小时3元计费)
+     */
+    tips?: string
+  }
+
+  interface chargeConnectorDetail {
+    /**
+     * 用户可用余额(元)
+     */
+    availableBalance?: number
+    /**
+     * 充电设备接口编码
+     */
+    connectorCode?: string
+    /**
+     * 充电设备接口ID
+     */
+    connectorId?: number
+    /**
+     * 充电设备接口名称
+     */
+    connectorName?: string
+    /**
+     * 接口类型:1-家用插座 2-交流接口插座 3-交流接口插头 4-直流接口枪头 5-无线充电座 6-其他
+     */
+    connectorType?: number
+    /**
+     * 接口类型名称
+     */
+    connectorTypeName?: string
+    /**
+     * 额定电流(A)
+     */
+    current?: number
+    /**
+     * 当前时段描述
+     */
+    currentPeriodDesc?: string
+    /**
+     * 常规价格(元/度),电价+服务费+常规运营费+增值费用
+     */
+    currentPrice?: number
+    /**
+     * 企业价格(元/度),电价+服务费+企业运营费+增值费用,仅企业用户有值
+     */
+    enterprisePrice?: number
+    /**
+     * 设备编码
+     */
+    equipmentCode?: string
+    /**
+     * 设备ID
+     */
+    equipmentId?: number
+    /**
+     * 设备名称
+     */
+    equipmentName?: string
+    /**
+     * 设备类型:1-直流设备 2-交流设备 3-交直流一体设备 4-无线设备 5-其他
+     */
+    equipmentType?: number
+    /**
+     * 设备类型名称
+     */
+    equipmentTypeName?: string
+    /**
+     * 是否企业用户
+     */
+    isFirmUser?: boolean
+    /**
+     * 最后更新时间
+     */
+    lastUpdateTime?: string
+    /**
+     * 国家标准:1-2011 2-2015
+     */
+    nationalStandard?: number
+    /**
+     * 国家标准名称
+     */
+    nationalStandardName?: string
+    /**
+     * 新用户首单优惠金额(元),仅新用户且有优惠活动时返回
+     */
+    newUserDiscount?: number
+    /**
+     * 提示语/停车费说明
+     */
+    parkingTips?: string
+    /**
+     * 车位号
+     */
+    parkNo?: string
+    /**
+     * 额定功率(kW)
+     */
+    power?: number
+    /**
+     * 充电站地址
+     */
+    stationAddress?: string
+    /**
+     * 充电站ID
+     */
+    stationId?: number
+    /**
+     * 充电站名称
+     */
+    stationName?: string
+    /**
+     * 终端状态:0-离网 1-空闲 2-占用(未充电) 3-占用(充电中) 4-占用(预约锁定) 255-故障
+     */
+    status?: number
+    /**
+     * 终端状态名称
+     */
+    statusName?: string
+    /**
+     * 额定电压下限(V)
+     */
+    voltageLowerLimits?: number
+    /**
+     * 额定电压上限(V)
+     */
+    voltageUpperLimits?: number
+    currentVoltage?: number
+  }
+
+  interface invokeChargeList {
+    /**
+     * 充电桩编号
+     */
+    equipmentId?: number
+    /**
+     * 充电桩id
+     */
+    stationId?: number
+    /**
+     * 充电设备接口编码
+     */
+    connectorId?: string
+    /**
+     * 用户昵称
+     */
+    consigneeName?: string
+    /**
+     * 用户手机号
+     */
+    consigneeMobile?: string
+  }
+
+  interface chargeSearchList {
+    /**
+     * 地址
+     */
+    address?: string
+    /**
+     * 距离(km)
+     */
+    distance?: number
+    /**
+     * 快充空闲数
+     */
+    fastIdleCount?: number
+    /**
+     * 快充总数
+     */
+    fastTotalCount?: number
+    /**
+     * 慢充空闲数
+     */
+    slowIdleCount?: number
+    /**
+     * 慢充总数
+     */
+    slowTotalCount?: number
+    /**
+     * 站点ID
+     */
+    stationId?: number
+    /**
+     * 站点名称
+     */
+    stationName?: string
+    /**
+     * 提示语
+     */
+    tips?: string
+  }
+
+  interface chargeingCostList {
+    /**
+     * 时段明细JSON(跨时段充电时有值)
+     */
+    chargeDetails?: string
+    /**
+     * 充电订单号
+     */
+    chargeOrderNo?: string
+    /**
+     * 充电时长(秒)
+     */
+    chargingDuration?: number
+    /**
+     * 充电时长描述(如:00:12:35)
+     */
+    chargingDurationDesc?: string
+    /**
+     * 充电接口编码
+     */
+    connectorCode?: string
+    /**
+     * 充电终端名称
+     */
+    connectorName?: string
+    /**
+     * 当前电流(A)
+     */
+    current?: number
+    /**
+     * 累计电费(元)
+     */
+    elecMoney?: number
+    /**
+     * 最后更新时间
+     */
+    lastUpdateTime?: string
+    /**
+     * 订单状态:1-启动中,2-充电中,3-停止中,4-已结束,5-未知
+     */
+    orderStatus?: number
+    /**
+     * 订单状态描述
+     */
+    orderStatusDesc?: string
+    /**
+     * 当前功率(kW)
+     */
+    power?: number
+    /**
+     * 累计服务费(元)
+     */
+    serviceMoney?: number
+    /**
+     * 电池剩余电量SOC(%)
+     */
+    soc?: number
+    /**
+     * 充电开始时间
+     */
+    startTime?: string
+    /**
+     * 充电站名称
+     */
+    stationName?: string
+    /**
+     * 充电状态 状态0待启动 1 充电中 2 结算中 3 已完成, 5未成功充电
+     */
+    status?: string
+    /**
+     * 累计总金额(元)
+     */
+    totalMoney?: number
+    /**
+     * 累计充电量(度/kWh)
+     */
+    totalPower?: number
+    /**
+     * 当前电压(V)
+     */
+    voltage?: number
+  }
+  interface stopChargeList {
+    /**
+     * 订单号
+     */
+    chargeOrderId?: number
+    /**
+     * 订单号
+     */
+    chargeOrderNo?: string
+    /**
+     * 充电状态 状态0待启动 1 充电中 2 结算中 3 已完成, 5未成功充电
+     */
+    status?: number
+  }
 
+  interface markers {
+    /**
+     * 标点id
+     */
+    id?: number
+    /**
+     * 维度
+     */
+    latitude?: number
+    /**
+     * 经度
+     */
+    longitude?: number
+    /**
+     * 标点图标
+     */
+    iconPath?: string
+    /**
+     * 标点图标宽度
+     */
+    width?: number
+    /**
+     * 标点图标高度
+     */
+    height?: number
+  }
 }

+ 13 - 1
src/api/apiDefinitions.ts

@@ -68,5 +68,17 @@ export default {
   'common.shoppingCartOrderConfirm':['GET', '/smqjh-oms/app-api/v1/shoppingCart/shoppingCartOrderConfirm/{ids}'],
   'common.addOrder':['POST', '/smqjh-oms/api/v1/order/addOrder'],
   'common.hybridPayment':['POST', '/smqjh-oms/service/pay/hybridPayment'],
-  'smqjh.getCategoryList':['POST', '/smqjh-pms/app-api/v1/categories/getCategoryList'],
+  'smqjh.getCategoryList': ['POST', '/smqjh-pms/app-api/v1/categories/getCategoryList'],
+
+  'charge.getStationInfoPage':['POST','/smqjh-system/applet/v1/homePage/getStationInfoPage'],
+  'charge.getMemberInfo': ['GET', '/smqjh-system/applet/v1/homePage/getMemberInfo'],
+  'charge.detail': ['GET', '/smqjh-system/applet/v1/station/detail'],
+  'charge.prices':['GET','/smqjh-system/applet/v1/station/prices'],
+  'charge.connectors':['GET','/smqjh-system/applet/v1/station/connectors'],
+  'charge.connectorDetail':['GET','/smqjh-system/applet/v1/station/connector/detail'],
+  'charge.invokeCharge':['POST','/smqjh-system/applet/v1/station/addCDOrder'],
+  'charge.search': ['GET', '/smqjh-system/applet/v1/station/search'],
+  'charge.chargeingCost': ['GET', '/smqjh-system/applet/v1/station/charging-cost'],
+  'charge.stopCharge': ['POST', '/smqjh-system/applet/v1/station/stopCharge'],
+  'charge.stationInfoMapList': ['GET', '/smqjh-system/applet/v1/homePage/getStationInfoMapList'],
 };

+ 117 - 4
src/api/globals.d.ts

@@ -195,7 +195,7 @@ declare global {
       refundDetails<
         Config extends Alova2MethodConfig<apiResData<Api.OrderRefundDetails>> & {
           data: {
-             refundNumber: string;
+            refundNumber: string;
           };
         }
       >(
@@ -214,7 +214,7 @@ declare global {
         Config extends Alova2MethodConfig<listData<Api.AppRefundOrderListVo>> & {
           data: {
             pageNum: number;
-            pageSize:number
+            pageSize: number
           };
         }
       >(
@@ -665,11 +665,124 @@ declare global {
         config: Config
       ): Alova2Method<apiResData<Api.smqjhCategoryList[]>, 'smqjh.getCategoryList', Config>;
     }
+    charge: {
+      getStationInfoPage<
+        Config extends Alova2MethodConfig<listData<Api.chargeStationInfoPage>> & {
+          data: {
+            pageNum?: number;
+            pageSize?: number;
+            sortType?: number;
+            longitude?: number;
+            latitude?: number;
+            userId?: number;
+          }
+        }
+      >(
+        config: Config
+      ): Alova2Method<listData<Api.chargeStationInfoPage>, 'charge.getStationInfoPage', Config>;
 
-  }
+      getMemberInfo<
+        Config extends Alova2MethodConfig<apiResData<Api.chargeMemberInfo>> & {}
+      >(
+        config: Config
+      ): Alova2Method<apiResData<Api.chargeMemberInfo>, 'charge.getMemberInfo', Config>;
+
+      detail<
+        Config extends Alova2MethodConfig<apiResData<Api.chargeStationDetail>> & {
+          data: {
+            stationId?: number;
+            longitude?: number | null;
+            latitude?: number | null;
+          }
+        }
+      >(
+        config: Config
+      ): Alova2Method<apiResData<Api.chargeStationDetail>, 'charge.detail', Config>;
 
-  var Apis: Apis;
+      prices<
+        Config extends Alova2MethodConfig<apiResData<Api.chargeStationPrices>> & {
+          data: {
+            stationId?: number;
+          }
+        }
+      >(
+        config: Config
+      ): Alova2Method<apiResData<Api.chargeStationPrices>, 'charge.prices', Config>;
+
+      connectors<
+        Config extends Alova2MethodConfig<apiResData<Api.chargeStationConnectors>> & {
+          data: {
+            stationId?: number;
+          }
+        }
+      >(
+        config: Config
+      ): Alova2Method<apiResData<Api.chargeStationConnectors>, 'charge.connectors', Config>;
+
+      connectorDetail<
+        Config extends Alova2MethodConfig<apiResData<Api.chargeConnectorDetail>> & {
+          data: {
+            connectorCode?: string;
+          }
+        }
+      >(
+        config: Config
+      ): Alova2Method<apiResData<Api.chargeConnectorDetail>, 'charge.detail', Config>;
+
+      invokeCharge<
+        Config extends Alova2MethodConfig<any> & {
+          data: Api.invokeChargeList;
+        }
+      >(
+        config: Config
+      ): Alova2Method<any, 'charge.invokeCharge', Config>;
+
+      search<
+        Config extends Alova2MethodConfig<apiResData<any>> & {
+          data: {
+            keyword?: string;
+            longitude?: number | null
+            latitude?: number | null
+          }
+        }
+      >(
+        config: Config
+      ): Alova2Method<apiResData<any>, 'charge.search', Config>;
+
+      chargeingCost<
+        Config extends Alova2MethodConfig<apiResData<chargeingCostList>> & {
+          data: {
+            orderNo?: string;
+          }
+        }
+      >(
+        config: Config
+      ): Alova2Method<apiResData<chargeingCostList>, 'charge.search', Config>;
+
+      stopCharge<
+        Config extends Alova2MethodConfig<listData<Api.stopChargeList>> & {
+          data: {
+            chargeOrderNo?: string;
+          }
+        }
+      >(
+        config: Config
+      ): Alova2Method<listData<Api.stopChargeList>, 'charge.stopCharge', Config>;
+
+      stationInfoMapList<
+        Config extends Alova2MethodConfig<apiResData<any>> & {
+          data: {
+            longitude?: number|null;
+            latitude?: number|null;
+          }
+        }
+      >(
+        config: Config
+      ): Alova2Method<apiResData<any>, 'charge.stationInfoMapList', Config>;
+    }
+  }
 }
+var Apis: Apis;
 
 
 export interface loginModel {

+ 2 - 0
src/components.d.ts

@@ -20,6 +20,7 @@ declare module 'vue' {
     WdCellGroup: typeof import('wot-design-uni/components/wd-cell-group/wd-cell-group.vue')['default']
     WdCheckbox: typeof import('wot-design-uni/components/wd-checkbox/wd-checkbox.vue')['default']
     WdCheckboxGroup: typeof import('wot-design-uni/components/wd-checkbox-group/wd-checkbox-group.vue')['default']
+    WdCircle: typeof import('wot-design-uni/components/wd-circle/wd-circle.vue')['default']
     WdConfigProvider: typeof import('wot-design-uni/components/wd-config-provider/wd-config-provider.vue')['default']
     WdCountDown: typeof import('wot-design-uni/components/wd-count-down/wd-count-down.vue')['default']
     WdDivider: typeof import('wot-design-uni/components/wd-divider/wd-divider.vue')['default']
@@ -32,6 +33,7 @@ declare module 'vue' {
     WdNavbar: typeof import('wot-design-uni/components/wd-navbar/wd-navbar.vue')['default']
     WdNoticeBar: typeof import('wot-design-uni/components/wd-notice-bar/wd-notice-bar.vue')['default']
     WdNotify: typeof import('wot-design-uni/components/wd-notify/wd-notify.vue')['default']
+    WdOverlay: typeof import('wot-design-uni/components/wd-overlay/wd-overlay.vue')['default']
     WdPopup: typeof import('wot-design-uni/components/wd-popup/wd-popup.vue')['default']
     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']

+ 3 - 1
src/config/index.ts

@@ -6,9 +6,11 @@ const mapEnvVersion = {
   // develop: 'http://192.168.1.101:8080',
   // develop: 'http://192.168.0.157:8080',
   // develop: 'http://192.168.1.253:8080',
+  develop: 'http://192.168.0.19:8080',
+  // develop: 'http://192.168.0.217:8080',
   // develop: 'http://192.168.1.89:8080', // 田
   // develop: 'http://47.109.84.152:8081',
-  develop: 'https://smqjh.api.zswlgz.com',
+  // develop: 'https://smqjh.api.zswlgz.com',
   /**
    * 体验版
    */

+ 28 - 0
src/package.json

@@ -0,0 +1,28 @@
+{
+  "id": "wlp-progress-new",
+  "name": "超级好用的最基础的半、全、渐变圆环进度条组件,可二次开发或者联系我二次开发哟",
+  "displayName": "超级好用的最基础的半、全、渐变圆环进度条组件,可二次开发或者联系我二次开发哟",
+  "version": "1.0.0",
+  "description": "超级好用的最基础的圆环进度条组件,可二次开发,半圆,全圆,渐变等等,利用canvas实现",
+  "keywords": [
+    "进度条",
+    "半圆环",
+    "全圆环",
+    "渐变"
+  ],
+  "dcloudext": {
+    "type": "component-vue",
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    }
+  },
+  "uni_modules": {
+    "dependencies": [],
+    "encrypt": []
+  }
+}

+ 70 - 0
src/pages.json

@@ -310,6 +310,76 @@
     {
       "root": "subPack-charge",
       "pages": [
+        {
+          "path": "chargeDetail/chargeDetail",
+          "type": "page",
+          "name": "charge-detail",
+          "islogin": false,
+          "style": {
+            "navigationBarTitleText": "充电详情",
+            "navigationStyle": "custom"
+          }
+        },
+        {
+          "path": "chargeing/chargeing",
+          "type": "page",
+          "name": "chargeing",
+          "islogin": true,
+          "style": {
+            "navigationBarTitleText": "正在充电",
+            "navigationStyle": "custom"
+          }
+        },
+        {
+          "path": "chargeMap/chargeMap",
+          "type": "page",
+          "name": "charge-map",
+          "islogin": false,
+          "style": {
+            "navigationBarTitleText": "地图模式",
+            "navigationStyle": "custom"
+          }
+        },
+        {
+          "path": "chargeOrderDetail/chargeOrderDetail",
+          "type": "page",
+          "name": "charge-order-detail",
+          "islogin": true,
+          "style": {
+            "navigationBarTitleText": "订单详情",
+            "navigationStyle": "custom"
+          }
+        },
+        {
+          "path": "chargeSearchList/chargeSearchList",
+          "type": "page",
+          "name": "cahrge-search-list",
+          "islogin": false,
+          "style": {
+            "navigationBarTitleText": "搜索列表",
+            "navigationStyle": "custom"
+          }
+        },
+        {
+          "path": "chargeSiteDetail/chargeSiteDetail",
+          "type": "page",
+          "name": "charge-site-detail",
+          "islogin": true,
+          "style": {
+            "navigationBarTitleText": "站点详情",
+            "navigationStyle": "custom"
+          }
+        },
+        {
+          "path": "chargeStart/chargeStart",
+          "type": "page",
+          "name": "charge-start",
+          "islogin": true,
+          "style": {
+            "navigationBarTitleText": "启动终端",
+            "navigationStyle": "custom"
+          }
+        },
         {
           "path": "index/index",
           "type": "page",

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

@@ -55,7 +55,7 @@ onReachBottom(() => {
 const navList = computed(() => {
   const list = [
     { icon: `${StaticUrl}/xsb.png`, title: '星闪豹', name: 'xsb-homeTabbar', show: true },
-    { icon: `${StaticUrl}/smqjh-index-cd.png`, title: '充电', name: '', show: !isOnlineAudit.value }, // !isOnlineAudit.value
+    { icon: `${StaticUrl}/smqjh-index-cd.png`, title: '充电', name: 'charge-index', show: true }, // !isOnlineAudit.value
     { icon: `${StaticUrl}/smqjh-sp.png`, title: '电影演出', name: '', show: !isOnlineAudit.value },
     { icon: `${StaticUrl}/smqjh-vip.png`, title: '视频权益', name: '', show: !isOnlineAudit.value },
     { icon: `${StaticUrl}/smqjh-diancan.png`, title: '大牌点餐', name: '', show: !isOnlineAudit.value },

+ 214 - 0
src/subPack-charge/chargeDetail/chargeDetail.vue

@@ -0,0 +1,214 @@
+<script setup lang="ts">
+import { formatStatusName } from '../utils/index'
+import router from '@/router'
+import { StaticUrl } from '@/config'
+
+const { statusBarHeight, MenuButtonHeight } = storeToRefs(useSysStore())
+const activeTab = ref('price')
+definePage({
+  name: 'charge-detail',
+  islogin: false,
+  style: {
+    navigationBarTitleText: '充电详情',
+    navigationStyle: 'custom',
+  },
+})
+const stationId = ref()
+onLoad((options: any) => {
+  stationId.value = Number(options.stationId)
+  activeTab.value = options.type
+})
+onMounted(() => {
+  getPricesList()
+  getConnectorsList()
+})
+
+const priceDetail = ref<Api.chargeStationPrices>()
+async function getPricesList() {
+  const res = await Apis.charge.prices({ data: { stationId: stationId.value } })
+  priceDetail.value = res.data
+}
+
+const connectorsDetail = ref<Api.chargeStationConnectors>()
+async function getConnectorsList() {
+  const res = await Apis.charge.connectors({ data: { stationId: stationId.value } })
+  connectorsDetail.value = res.data
+}
+
+/**
+ * 处理站点设备状态
+ *status 状态:0-离线 1-空闲 2-占用
+ */
+function getStatusImageByStatus(deviceStatus: number) {
+  switch (deviceStatus) {
+    case 1: // 空闲
+      return 'kx'
+    case 2: // 占用
+      return 'zy'
+    case 3: // 占用
+      return 'zy'
+    case 0: // 离线
+      return 'lx'
+    default:
+      return 'unknown'
+  }
+}
+// 切换选项卡的方法
+function switchTab(tab: string) {
+  activeTab.value = tab
+}
+
+// 计算样式的方法
+function getTabStyle(tab: string) {
+  return activeTab.value === tab
+    ? { background: '#9ED605', color: '#FFF' }
+    : {}
+}
+</script>
+
+<template>
+  <view class="charge-detail-page min-h-screen bg-[linear-gradient(90deg,#F1FECC_0%,#EAFEFA_100%)]">
+    <wd-navbar
+      title="充电详情" custom-style="background: linear-gradient(90deg, #F1FECC 0%, #EAFEFA 100%);"
+      :bordered="false" :z-index="999" safe-area-inset-top left-arrow fixed @click-left="router.back()"
+    />
+    <view :style="{ paddingTop: `${(Number(statusBarHeight) || 44) + MenuButtonHeight + 12}px` }" />
+    <view class="content-page box-border px24rpx">
+      <view class="flex items-center justify-between">
+        <view>
+          <view class="text-32rpx font-bold">
+            {{ priceDetail?.stationName }}
+          </view>
+          <view class="mt-16rpx text-24rpx text-#AAA">
+            {{ priceDetail?.tips || '--' }}
+          </view>
+        </view>
+        <view>
+          <image class="h-132rpx w-140rpx" :src="`${StaticUrl}/site-name-icon.png`" />
+        </view>
+      </view>
+      <view class="items-centerrounded-16rpx mt-20rpx flex bg-#FFF p-20rpx">
+        <view class="w-230rpx text-center">
+          <view class="text-32rpx text-#9ED605 font-bold">
+            {{ connectorsDetail?.idleCount }}
+          </view>
+          <view class="text-24rpx font-500">
+            空闲
+          </view>
+        </view>
+        <view class="h-76rpx w-2rpx bg-#F0F0F0" />
+        <view class="w-230rpx text-center">
+          <view class="text-32rpx text-#9ED605 font-bold">
+            {{ connectorsDetail?.occupiedCount }}
+          </view>
+          <view class="text-24rpx font-500">
+            占用
+          </view>
+        </view>
+        <view class="h-76rpx w-2rpx bg-#F0F0F0" />
+        <view class="w-230rpx text-center">
+          <view class="text-32rpx text-#9ED605 font-bold">
+            {{ connectorsDetail?.offlineCount }}
+          </view>
+          <view class="text-24rpx font-500">
+            离线
+          </view>
+        </view>
+      </view>
+      <view class="mt-28rpx">
+        <view class="flex items-center justify-between rounded-42rpx bg-#FFF p-6rpx">
+          <view
+            class="h-80rpx w-348rpx rounded-60rpx text-center line-height-[80rpx]" :style="getTabStyle('price')"
+            @click="switchTab('price')"
+          >
+            电站价格
+          </view>
+          <view
+            class="h-80rpx w-348rpx rounded-60rpx text-center line-height-[80rpx]" :style="getTabStyle('terminal')"
+            @click="switchTab('terminal')"
+          >
+            充电终端
+          </view>
+        </view>
+      </view>
+      <view v-if="activeTab == 'price'">
+        <view
+          v-for="item in priceDetail?.priceList" :key="item.timePeriod"
+          class="mt-20rpx rounded-16rpx bg-#FFF p-24rpx"
+          :style="{ border: item.currentPeriod ? '2rpx solid #9ED605' : '' }"
+        >
+          <view class="relative flex items-center justify-between">
+            <view class="flex items-center gap-20rpx">
+              <view
+                class="h-40rpx w-40rpx rounded-8rpx bg-#CCC text-center text-28rpx text-#FFF font-bold line-height-[40rpx]"
+              >
+                {{ item.periodFlagName }}
+              </view>
+              <view class="text-28rpx font-bold">
+                {{ item.timePeriod }}
+              </view>
+            </view>
+            <view
+              v-if="item.currentPeriod"
+              class="absolute h-40rpx w-152rpx rounded-[0_16rpx_0_16rpx] bg-[linear-gradient(99deg,#D2F670_0%,#9ED605_100%)] text-center text-28rpx text-#FFF font-600 -right-24rpx -top-24rpx"
+            >
+              当前时段
+            </view>
+          </view>
+          <view class="mt-24rpx rounded-16rpx bg-#F6F6F6 p-20rpx">
+            <view class="flex items-center justify-between">
+              <view class="text-24rpx text-#222222">
+                抵扣券电价
+              </view>
+              <view
+                class="text-24rpx"
+                :style="{ color: item.currentPeriod ? '#FF6464' : '', fontWeight: item.currentPeriod ? '800' : '' }"
+              >
+                <text>{{ item.totalPrice }}</text>
+                <text class="text-#AAA">
+                  元/度
+                </text>
+              </view>
+            </view>
+          </view>
+        </view>
+      </view>
+      <view v-if="activeTab == 'terminal'">
+        <view
+          v-for="item in connectorsDetail?.connectorList" :key="item.connectorId"
+          class="mt-20rpx flex items-center gap-20rpx rounded-16rpx bg-#FFF p-20rpx"
+          @click="router.push({ name: 'charge-start', params: { connectorCode: item.connectorCode } })"
+        >
+          <view
+            class="h-116rpx w-116rpx text-center"
+            :style="{ backgroundImage: `url(${StaticUrl}/site-status-${getStatusImageByStatus(item.status)}.png)`, backgroundSize: 'cover', backgroundPosition: 'center' }"
+          >
+            <image class="mt-20rpx h-38rpx w-27.18rpx" :src="`${StaticUrl}/terminal-icon.png`" />
+            <view class="text-24rpx font-bold">
+              {{ formatStatusName(item.statusName) }}
+            </view>
+          </view>
+          <view>
+            <view class="text-bold text-28rpx">
+              {{ item.connectorName }}
+            </view>
+            <view class="mt-4rpx text-24rpx text-#AAA">
+              电类分类:{{ item.equipmentType }}
+            </view>
+            <view class="mt-4rpx w-400rpx overflow-hidden truncate whitespace-nowrap text-24rpx text-#AAA">
+              终端编号:{{ item.connectorCode }}
+            </view>
+          </view>
+        </view>
+      </view>
+    </view>
+    <view class="h-180rpx" />
+    <view
+      class="fixed bottom-66rpx left-24rpx h-100rpx w-702rpx rounded-16rpx bg-[linear-gradient(90deg,#DBFC81_0%,#9ED605_100%)] text-center text-28rpx font-800 line-height-[100rpx] shadow-[inset_0rpx_6rpx_20rpx_2rpx_#FFFFFF]"
+    >
+      扫码充电
+    </view>
+  </view>
+</template>
+
+<style lang="scss" scoped></style>

+ 169 - 0
src/subPack-charge/chargeMap/chargeMap.vue

@@ -0,0 +1,169 @@
+<script setup lang="ts">
+import chargeSearch from '../components/search.vue'
+import chargeFooter from '../components/charge-tab.vue'
+import router from '@/router'
+import { StaticUrl } from '@/config'
+
+const { Location } = storeToRefs(useAddressStore())
+const { statusBarHeight, MenuButtonHeight } = storeToRefs(useSysStore())
+definePage({
+  name: 'charge-map',
+  islogin: false,
+  style: {
+    navigationBarTitleText: '地图模式',
+    navigationStyle: 'custom',
+  },
+})
+onMounted(() => {
+  getStationInfoMapList()
+})
+const markersData = ref<any[]>([])
+const markerMapList = ref<any[]>([])
+async function getStationInfoMapList() {
+  const res = await Apis.charge.stationInfoMapList({ data: { longitude: Location.value.longitude, latitude: Location.value.latitude } })
+  markerMapList.value = res.data
+  res.data.forEach((item: any) => {
+    markersData.value.push({
+      id: item.stationId,
+      latitude: item.latitude,
+      longitude: item.longitude,
+      iconPath: `${StaticUrl}/marker-tag.png`,
+      width: 30,
+      height: 34,
+    })
+  })
+}
+const markerShow = ref(false)
+const selectData = ref<any>({})
+function openMarkerTap(item: any) {
+  const selected = markerMapList.value.find((station: any) => station.stationId === item.detail.markerId)
+  if (selected) {
+    selectData.value = selected
+    markerShow.value = true
+  }
+}
+</script>
+
+<template>
+  <view class="map-page min-h-screen bg-#F6FAFF">
+    <wd-navbar
+      title="" custom-style="background:linear-gradient( 180deg, #E2FF91 0%, rgba(158,214,5,0) 100%)"
+      :bordered="false" :z-index="99" safe-area-inset-top fixed
+    >
+      <template #left>
+        <view class="flex items-center">
+          <!-- <wd-icon name="arrow-left" size="22px" color="#000" /> -->
+          <view class="relative z-10 h62rpx w-full w180rpx opacity-100">
+            <image class="absolute left-0 top-0 h62rpx w180rpx" :src="`${StaticUrl}/charge-logo.png`" />
+          </view>
+        </view>
+      </template>
+    </wd-navbar>
+    <view class="relative">
+      <view
+        class="absolute z-1 box-border px24rpx"
+        :style="{ paddingTop: `${(Number(statusBarHeight) || 44) + MenuButtonHeight + 12}px` }"
+      >
+        <charge-search
+          map-mode-text-value="列表模式" :map-mode-icon="`${StaticUrl}/charge-list.png`"
+          @map-mode-click="router.replace({ name: 'charge-index' })"
+        />
+      </view>
+      <view class="absolute left-0 top-0 z-0 h-full w-full">
+        <map
+          style="width: 100%;height: 100vh;" :longitude="Location.longitude || 113.264435"
+          :latitude="Location.latitude || 23.129163" :markers="markersData" @markertap.stop="openMarkerTap"
+        />
+      </view>
+      <transition name="slide-up">
+        <view v-if="markerShow" class="absolute top-960rpx px-24rpx">
+          <view class="h-432rpx w-660rpx rounded-32rpx bg-#FFF p-24rpx shadow-[0rpx_6rpx_12rpx_2rpx_rgba(122,168,222,0.3)]" @click="router.push({ name: 'charge-site-detail', params: { stationId: String(selectData.stationId) } })">
+            <view class="" @click.stop="markerShow = false">
+              <wd-icon name="close" size="16px" color="#9ED605" />
+            </view>
+            <view class="flex items-center justify-between">
+              <view class="text-32rpx font-800">
+                {{ selectData.stationName }}
+              </view>
+              <view
+                class="ml-150rpx h-44rpx w-148rpx flex items-center border-2rpx border-#9ED605 rounded-34rpx border-solid line-height-[44rpx]"
+              >
+                <view class="w-44rpx rounded-[34rpx_0rpx_0rpx_34rpx] bg-#9ED605 text-center">
+                  <wd-icon name="location" size="16px" color="#FFF" />
+                </view>
+                <view class="text-24rpx text-#9ED605">
+                  {{ selectData.distance }}km
+                </view>
+              </view>
+            </view>
+            <view class="mt-20rpx text-24rpx text-#AAA">
+              {{ selectData.address }}
+            </view>
+            <view class="mt-20rpx flex items-center justify-between">
+              <view class="h-120rpx w-204rpx flex flex-col items-center justify-center rounded-8rpx bg-[linear-gradient(180deg,#45E67D_0%,rgba(218,249,229,0)_100%)]">
+                <view class="mt-16rpx h-40rpx w-100rpx rounded-8rpx bg-[linear-gradient(180deg,#4FEF86_0%,#00AA3A_100%)] text-center text-24rpx text-#FFF font-bold line-height-[40rpx]">
+                  快充
+                </view>
+                <view class="mt-10rpx text-32rpx font-bold">
+                  {{ selectData.fastCharging }}
+                </view>
+              </view>
+              <view class="h-120rpx w-204rpx flex flex-col items-center justify-center rounded-8rpx bg-[linear-gradient(180deg,#BED2FF_0%,rgba(62,82,128,0)_100%)]">
+                <view class="mt-16rpx h-40rpx w-100rpx rounded-8rpx bg-[linear-gradient(180deg,#8EB1FF_0%,#3071FF_100%)] text-center text-24rpx text-#FFF font-bold line-height-[40rpx]">
+                  慢充
+                </view>
+                <view class="mt-10rpx text-32rpx font-bold">
+                  {{ selectData.slowCharging }}
+                </view>
+              </view>
+            </view>
+            <view class="mt-20rpx h-72rpx w-654rpx flex items-center justify-between bg-#F6FAFF">
+              <view>
+                <text class="text-48rpx text-#FF6464 font-800">
+                  {{ selectData.platformPrice }}
+                </text>
+                <text class="text-24rpx">
+                  元/度
+                </text>
+              </view>
+              <view class="28rpx">
+                {{ selectData.peakValue }}:{{ selectData.peakTime }}
+              </view>
+            </view>
+            <view class="mt-20rpx flex items-center gap-16rpx">
+              <view class="h-30rpx w-30rpx rounded-4rpx bg-#5BE7FF text-center text-24rpx text-#FFF line-height-[30rpx]">
+                P
+              </view>
+              <view class="text-24rpx text-#AAA">
+                {{ selectData.tips }}
+              </view>
+            </view>
+          </view>
+        </view>
+      </transition>
+    </view>
+    <chargeFooter />
+  </view>
+</template>
+
+<style lang="scss" scoped>
+.slide-up-enter-active, .slide-up-leave-active {
+  transition: transform 0.3s ease;
+}
+
+.slide-up-enter-from {
+  transform: translateY(100%);
+}
+
+.slide-up-enter-to {
+  transform: translateY(0%);
+}
+
+.slide-up-leave-from {
+  transform: translateY(0%);
+}
+
+.slide-up-leave-to {
+  transform: translateY(100%);
+}
+</style>

+ 172 - 0
src/subPack-charge/chargeOrderDetail/chargeOrderDetail.vue

@@ -0,0 +1,172 @@
+<script setup lang="ts">
+import router from '@/router'
+
+const { statusBarHeight, MenuButtonHeight } = storeToRefs(useSysStore())
+
+definePage({
+  name: 'charge-order-detail',
+  islogin: true,
+  style: {
+    navigationBarTitleText: '订单详情',
+    navigationStyle: 'custom',
+  },
+})
+</script>
+
+<template>
+  <view class="min-h-screen bg-[linear-gradient(90deg,#F1FECC_0%,#EAFEFA_100%)]">
+    <wd-navbar
+      title="订单详情" custom-style="background: linear-gradient(90deg, #F1FECC 0%, #EAFEFA 100%);"
+      :bordered="false" :z-index="999" safe-area-inset-top left-arrow fixed @click-left="router.back()"
+    />
+    <view :style="{ paddingTop: `${(Number(statusBarHeight) || 44) + MenuButtonHeight + 12}px` }" />
+    <view class="box-border px24rpx">
+      <view class="rounded-16rpx bg-#FFF p-24rpx">
+        <view class="flex items-center gap-20rpx">
+          <view>icon</view>
+          <view class="text-28rpx">
+            充电度数
+          </view>
+        </view>
+        <view class="mt-20rpx text-28rpx text-#9ED605 font-bold">
+          60.800度电
+        </view>
+      </view>
+      <view class="mt-20rpx rounded-16rpx bg-#FFF p-24rpx">
+        <view>
+          <view class="text-24rpx text-#AAA">
+            起始时间
+          </view>
+          <view class="mt-20rpx text-32rpx font-bold">
+            2024-07-02  23:10:05
+          </view>
+        </view>
+        <view class="mt-28rpx">
+          <view class="text-24rpx text-#AAA">
+            终止时间
+          </view>
+          <view class="mt-20rpx text-32rpx font-bold">
+            2024-07-02  23:10:05
+          </view>
+        </view>
+        <view class="mt-28rpx">
+          <view class="text-24rpx text-#AAA">
+            终止方式
+          </view>
+          <view class="mt-20rpx text-32rpx font-bold">
+            用户主动终止
+          </view>
+        </view>
+      </view>
+      <view class="mt-20rpx rounded-16rpx bg-#FFF p-24rpx">
+        <view class="flex items-center justify-between">
+          <view class="text-28rpx font-500">
+            订单状态
+          </view>
+          <view class="text-28rpx text-#AAA">
+            已完成
+          </view>
+        </view>
+        <view class="mt-28rpx flex items-center justify-between">
+          <view class="text-28rpx font-500">
+            订单编号
+          </view>
+          <view class="text-28rpx text-#AAA">
+            5215564861554994
+          </view>
+        </view>
+        <view class="mt-28rpx flex items-center justify-between">
+          <view class="text-28rpx font-500">
+            订单时间
+          </view>
+          <view class="text-28rpx text-#AAA">
+            2024-07-07 23:13:12
+          </view>
+        </view>
+        <view class="mt-28rpx flex items-center justify-between">
+          <view class="text-28rpx font-500">
+            充电电站
+          </view>
+          <view class="text-28rpx text-#AAA">
+            华能贵州盘州市风电有限责任公司
+          </view>
+        </view>
+        <view class="mt-28rpx flex items-center justify-between">
+          <view class="text-28rpx font-500">
+            终端名称
+          </view>
+          <view class="text-28rpx text-#AAA">
+            402号直流快充
+          </view>
+        </view>
+        <view class="mt-28rpx flex items-center justify-between">
+          <view class="text-28rpx font-500">
+            终端编号
+          </view>
+          <view class="text-28rpx text-#AAA">
+            52155648615
+          </view>
+        </view>
+        <view class="mt-28rpx flex items-center justify-between">
+          <view class="text-28rpx font-500">
+            车位编号
+          </view>
+          <view class="text-28rpx text-#AAA">
+            无
+          </view>
+        </view>
+        <view class="mt-28rpx flex items-center justify-between">
+          <view class="text-28rpx font-500">
+            电费
+          </view>
+          <view class="text-28rpx text-#AAA">
+            2.82元
+          </view>
+        </view>
+        <view class="mt-28rpx flex items-center justify-between">
+          <view class="text-28rpx font-500">
+            服务费
+          </view>
+          <view class="text-28rpx text-#AAA">
+            0.71元
+          </view>
+        </view>
+        <wd-divider />
+        <view class="mt-28rpx flex items-center justify-between">
+          <view class="text-28rpx font-500">
+            新用户首单立减
+          </view>
+          <view class="text-28rpx text-#F44033">
+            0.71元
+          </view>
+        </view>
+        <view class="mt-28rpx flex items-center justify-between">
+          <view class="text-28rpx font-500">
+            优惠立减
+          </view>
+          <view class="text-28rpx text-#F44033">
+            0.71元
+          </view>
+        </view>
+        <view class="mt-28rpx flex items-center justify-between">
+          <view class="text-28rpx font-500">
+            实际结算费用
+          </view>
+          <view class="text-28rpx text-#F44033">
+            0.71元
+          </view>
+        </view>
+      </view>
+      <view class="mt-20rpx flex items-center gap-12rpx rounded-8rpx bg-[rgba(158_214_5_0.4)] p-[12rpx_24rpx_12rpx_24rpx]">
+        <view class="h-28rpx w-28rpx rounded-50% bg-#9ED605 text-center text-18rpx text-#FFF line-height-[28rpx]">
+          !
+        </view>
+        <view class="text-24rpx">
+          本次充电费用已从您的“账户余额”中抵扣结算
+        </view>
+      </view>
+    </view>
+  </view>
+</template>
+
+<style lang="scss" scoped></style>

+ 149 - 0
src/subPack-charge/chargeSearchList/chargeSearchList.vue

@@ -0,0 +1,149 @@
+<script setup lang="ts">
+import router from '@/router'
+import { useSysChargeStore } from '@/subPack-charge/store-charge/sys'
+
+const { statusBarHeight, MenuButtonHeight, opcity } = storeToRefs(useSysStore())
+const { Location } = storeToRefs(useAddressStore())
+const sysChargeStore = useSysChargeStore()
+const { searchHistory } = storeToRefs(sysChargeStore)
+definePage({
+  name: 'cahrge-search-list',
+  islogin: false,
+  style: {
+    navigationBarTitleText: '搜索列表',
+    navigationStyle: 'custom',
+  },
+})
+const keyword = ref('')
+
+onMounted(() => {
+  opcity.value = 0
+  // 搜索历史由 persistPlugin 自动恢复
+})
+onPageScroll((e) => {
+  const calculatedOpacity = e.scrollTop / 100
+  opcity.value = Math.min(1, Math.max(0.1, calculatedOpacity))
+})
+
+const searchList = ref<any>([])
+async function searchData() {
+  if (!keyword.value) {
+    useGlobalToast().show('请输入搜索内容!')
+    return
+  }
+  useGlobalLoading().loading({})
+  const res = await Apis.charge.search({ data: { keyword: keyword.value, longitude: Location.value?.longitude, latitude: Location.value?.latitude } })
+  searchList.value = res.data
+  useGlobalLoading().close()
+  // 添加到搜索历史
+  sysChargeStore.addToSearchHistory(keyword.value)
+}
+
+function reSearch(e: string) {
+  keyword.value = e
+  searchData()
+}
+
+function clearHistory() {
+  useGlobalMessage().confirm({
+    msg: '确认清空搜索历史吗?',
+    cancelButtonText: '取消',
+    success: () => {
+      sysChargeStore.clearSearchHistory()
+    },
+  })
+}
+</script>
+
+<template>
+  <view class="min-h-screen from-[#E2FF91] to-[rgba(158,214,5,0)] bg-gradient-to-b">
+    <wd-navbar
+      title="站点搜索" :custom-style="`background-color: rgba(226, 255, 145, ${opcity})`" :bordered="false"
+      :z-index="99" safe-area-inset-top left-arrow fixed @click-left="router.back()"
+    />
+    <view :style="{ paddingTop: `${(Number(statusBarHeight) || 44) + MenuButtonHeight + 12}px` }" />
+    <view class="search-list-content box-border px24rpx">
+      <view class="flex items-center justify-between rounded-lg bg-white p-16rpx px12rpx">
+        <view class="flex items-center gap-20rpx">
+          <wd-icon name="search" size="14" color="#ccc" />
+          <input v-model="keyword" class="search-list-input" placeholder-class="search-pla-class" placeholder="请输入站点名称">
+        </view>
+        <view class="flex items-center gap-20rpx">
+          <wd-icon v-if="keyword != ''" name="close" size="12" color="#ccc" @click="keyword = ''" />
+          <view class="text-28rpx text-#9ED605 font-bold" @click="searchData">
+            搜索
+          </view>
+        </view>
+      </view>
+      <view v-if="searchHistory.length > 0" class="mt-20rpx">
+        <view class="flex items-center justify-between">
+          <view class="text-28rpx">
+            搜索历史
+          </view>
+          <view @click="clearHistory">
+            <wd-icon name="delete" size="18px" color="#ccc" />
+          </view>
+        </view>
+        <view class="mt-10rpx w-702rpx flex flex-wrap items-center gap-14rpx">
+          <view v-for="item in searchHistory" :key="item" class="rounded-30rpx bg-#FFF p-[10rpx_20rpx_10rpx_20rpx] text-24rpx" @click="reSearch(item)">
+            {{ item }}
+          </view>
+        </view>
+      </view>
+      <view class="mt-20rpx">
+        <view class="flex items-center justify-between">
+          <view class="text-28rpx">
+            搜索结果
+          </view>
+          <view class="text-24rpx text-#AAA">
+            共计{{ searchList.length }}条
+          </view>
+        </view>
+        <view v-for="item in searchList" :key="item.stationId" class="mt-20rpx rounded-16rpx bg-#FFF p-24rpx" @click="router.push({ name: 'charge-site-detail', params: { stationId: String(item.stationId) } })">
+          <view class="text-32rpx font-bold">
+            {{ item.stationName }}
+          </view>
+          <view class="mt-20rpx text-24rpx text-#AAA">
+            {{ item.tips }}
+          </view>
+          <view class="mt-26rpx flex items-center">
+            <view class="w-280rpx">
+              <text class="text-28rpx text-#00ff8c">
+                快
+              </text>
+              <text class="text-bold text-28rpx">
+                {{ item.fastIdleCount }}/{{ item.fastTotalCount }}
+              </text>
+            </view>
+            <view class="w-280rpx">
+              <text class="text-28rpx text-#0a249e">
+                慢
+              </text>
+              <text class="text-bold text-28rpx">
+                {{ item.slowIdleCount }}/{{ item.slowTotalCount }}
+              </text>
+            </view>
+            <view class="w-280rpx">
+              <text class="text-28rpx text-#ff9300">
+                距离
+              </text>
+              <text class="text-bold text-28rpx">
+                {{ item.distance || '-' }}km
+              </text>
+            </view>
+          </view>
+        </view>
+      </view>
+    </view>
+  </view>
+</template>
+
+<style lang="scss" scoped>
+.search-list-input{
+  font-size: 28rpx;
+  width: 500rpx;
+}
+.search-pla-class{
+  font-size: 28rpx;
+}
+</style>

+ 340 - 0
src/subPack-charge/chargeSiteDetail/chargeSiteDetail.vue

@@ -0,0 +1,340 @@
+<script setup lang="ts">
+import { ScanCodeUtil, formatStatusName } from '../utils/index'
+import router from '@/router'
+import { StaticUrl } from '@/config'
+
+const { statusBarHeight, MenuButtonHeight } = storeToRefs(useSysStore())
+const { Location } = storeToRefs(useAddressStore())
+const { opcity } = storeToRefs(useSysStore())
+const stationId = ref()
+onLoad((options: any) => {
+  console.log(options)
+  stationId.value = Number(options.stationId)
+})
+definePage({
+  name: 'charge-site-detail',
+  islogin: true,
+  style: {
+    navigationBarTitleText: '站点详情',
+    navigationStyle: 'custom',
+  },
+})
+const activeFilter = ref('0')
+onMounted(() => {
+  getStationDetail()
+  opcity.value = 0
+})
+/**
+ * 获取电站详情
+ */
+const stationDetail = ref<Api.chargeStationDetail>()
+async function getStationDetail() {
+  useGlobalLoading().loading({})
+  const res = await Apis.charge.detail({ data: { stationId: stationId.value, latitude: Location.value.latitude, longitude: Location.value.longitude } })
+  stationDetail.value = res.data
+  useGlobalLoading().close()
+}
+// 使用计算属性动态计算筛选选项
+const filterOptions = computed(() => {
+  const counts = {
+    0: 0, // 离线
+    1: 0, // 空闲
+    2: 0, // 占用
+  }
+
+  // 遍历充电站连接器列表,统计各状态数量
+  if (stationDetail.value?.connectorList) {
+    stationDetail.value.connectorList.forEach((item) => {
+      // 检查status是否为有效键值
+      if (item.status === 0 || item.status === 1 || item.status === 2) {
+        counts[item.status as keyof typeof counts]++
+      }
+    })
+  }
+
+  return [
+    { key: '0', label: `离线(${counts['0']})` },
+    { key: '1', label: `空闲(${counts['1']})` },
+    { key: '2', label: `占用(${counts['2']})` },
+  ]
+})
+
+// 添加计算属性来过滤设备列表
+const filteredConnectors = computed(() => {
+  if (!stationDetail.value?.connectorList)
+    return []
+  // 根据当前选中的状态过滤设备,并限制为前3个
+  return stationDetail.value.connectorList.filter(
+    item => String(item.status) === activeFilter.value,
+  ).slice(0, 3)
+})
+/**
+ * 处理站点设备状态
+ *status 状态:0-离线 1-空闲 2-占用
+ */
+function getStatusImageByStatus(deviceStatus: number) {
+  switch (deviceStatus) {
+    case 1: // 空闲
+      return 'kx'
+    case 2: // 占用
+      return 'zy'
+    case 0: // 离线
+      return 'lx'
+    default:
+      return 'unknown'
+  }
+}
+
+onPageScroll((e) => {
+  const calculatedOpacity = e.scrollTop / 100
+  opcity.value = Math.min(1, Math.max(0.1, calculatedOpacity))
+})
+
+// 处理筛选项点击的方法
+function handleFilterClick(filterKey: string) {
+  activeFilter.value = filterKey
+  console.log(`选择了: ${filterKey}`)
+}
+
+function openMap() {
+  uni.openLocation({
+    latitude: Number(stationDetail.value?.latitude),
+    longitude: Number(stationDetail.value?.longitude),
+  })
+}
+
+async function getDeviceInfo(connectorCode: string) {
+  useGlobalLoading().loading({})
+  const res = await Apis.charge.connectorDetail({ data: { connectorCode } })
+  useGlobalLoading().close()
+  if (res.data.status === 0 || res.data.status === 255) {
+    useGlobalMessage().alert('此设备异常或被占用,请更换其他设备')
+  }
+  else {
+    router.push({ name: 'charge-start', params: { connectorCode } })
+  }
+}
+
+async function scanCode() {
+  try {
+    const connectorCode = await ScanCodeUtil.scanAndGetConnectorCode()
+    if (!connectorCode) {
+      useGlobalMessage().alert('二维码不正确')
+      return
+    }
+    // 获取设备信息
+    getDeviceInfo(connectorCode)
+  }
+  catch (error) {
+    console.error('扫码失败:', error)
+  }
+}
+</script>
+
+<template>
+  <view class="site-detail-page min-h-screen bg-#F6FAFF">
+    <wd-navbar
+      title="站点详情" :custom-style="`background-color: rgba(226, 255, 145, ${opcity})`" :bordered="false"
+      :z-index="999" safe-area-inset-top left-arrow fixed @click-left="router.back()"
+    />
+    <view :style="{ paddingTop: `${(Number(statusBarHeight) || 44) + MenuButtonHeight + 12}px` }" />
+    <view class="site-detail-content">
+      <!-- <view>
+        <wd-swiper :list="swiperList" :height="260" :indicator="{ type: 'fraction' }" value-key="advertImg" />
+      </view> -->
+      <view class="bg-#FFF p-20rpx">
+        <view class="mt-28rpx box-border px24rpx">
+          <view class="text-32rpx font-800">
+            {{ stationDetail?.stationName }}
+          </view>
+          <view class="mt-20rpx flex items-center gap-20rpx">
+            <view class="h-30rpx w-30rpx rounded-4rpx bg-#5BE7FF text-center text-24rpx text-#fff line-height-[30rpx]">
+              P
+            </view>
+            <view class="text-24rpx text-#AAA">
+              {{ stationDetail?.tips || '--' }}
+            </view>
+          </view>
+        </view>
+        <view class="ml-10rpx">
+          <view
+            class="cardBg-set mt-20rpx box-border h-138rpx w-680rpx flex items-center justify-between rounded-16rpx"
+            :style="{ backgroundImage: `url(${StaticUrl}/site-detail-navBg.png)` }"
+          >
+            <view class="ml-24rpx">
+              <view class="text-28rpx text-#2B303A font-bold">
+                距离您{{ stationDetail?.distance || '--' }}km
+              </view>
+              <view class="mt-8rpx w-408rpx overflow-hidden text-ellipsis whitespace-nowrap text-24rpx text-#AAA">
+                {{ stationDetail?.address }}
+              </view>
+            </view>
+            <view class="mr-24rpx" @click="openMap">
+              <view>
+                <image class="h-40rpx w-40rpx" :src="`${StaticUrl}/site-detail-nav.png`" />
+              </view>
+              <view class="mt-8rpx text-24rpx">
+                导航
+              </view>
+            </view>
+          </view>
+        </view>
+      </view>
+    </view>
+    <view class="mt20rpx box-border px24rpx">
+      <view class="rounded-24rpx bg-#FFF p-24rpx">
+        <view class="flex items-center justify-between">
+          <view class="text-32rpx font-bold">
+            费用信息
+          </view>
+          <view class="flex items-center" @click="router.push({ name: 'charge-detail', params: { stationId: String(stationDetail?.stationId), type: 'price' } })">
+            <view class="text-24rpx text-#AAA">
+              查看全部
+            </view>
+            <wd-icon name="chevron-right" size="22px" color="#AAAAAA" />
+          </view>
+        </view>
+        <view class="mt-24rpx rounded-16rpx bg-[linear-gradient(90deg,#FEE4C6_0%,rgba(251,235,198,0.23)_100%)] p-24rpx">
+          <view class="relative flex items-center justify-between">
+            <view class="text-28rpx font-bold">
+              当前价
+            </view>
+            <view class="absolute -right-20rpx -top-20rpx">
+              <image class="h-52rpx w-125rpx" :src="`${StaticUrl}/site-price-tag.png`" />
+            </view>
+          </view>
+          <view class="mt-24rpx flex items-center justify-between">
+            <view>
+              <view class="flex items-center">
+                <text class="text-48rpx text-#FF6464 font-800">
+                  {{ stationDetail?.currentPrice }}
+                </text>
+                <text class="text-24rpx">
+                  元/度
+                </text>
+              </view>
+              <view class="mt-12rpx text-28rpx">
+                当前时段:
+              </view>
+              <view class="text-bold mt-16rpx text-28rpx">
+                {{ stationDetail?.currentPeriod }}
+              </view>
+            </view>
+            <view>
+              <image class="h-182rpx w-88rpx" :src="`${StaticUrl}/site-price-icon.png`" />
+            </view>
+          </view>
+        </view>
+      </view>
+      <view class="mt-20rpx rounded-24rpx bg-#FFF p-24rpx">
+        <view class="flex items-center justify-between">
+          <view class="text-32rpx font-bold">
+            充电终端
+          </view>
+          <view class="flex items-center" @click="router.push({ name: 'charge-detail', params: { stationId: String(stationDetail?.stationId), type: 'terminal' } })">
+            <view class="text-24rpx text-#AAA">
+              查看全部
+            </view>
+            <wd-icon name="chevron-right" size="22px" color="#AAAAAA" />
+          </view>
+        </view>
+        <view class="mt-28rpx flex items-center gap-20rpx">
+          <view
+            v-for="item in filterOptions" :key="item.key"
+            class="select-item h-60rpx w-152rpx text-28rpx line-height-[60rpx]" :class="[{ 'select-item-active': activeFilter === item.key }]" @click="handleFilterClick(item.key)"
+          >
+            {{ item.label }}
+          </view>
+        </view>
+        <view class="mt-24rpx">
+          <view v-for="item in filteredConnectors" :key="item.connectorId" class="mb-20rpx flex items-center gap-20rpx rounded-16rpx bg-#F6F6F6 p-20rpx" @click="router.push({ name: 'charge-start', params: { connectorCode: item.connectorCode } })">
+            <view
+              class="h-116rpx w-116rpx text-center"
+              :style="{ backgroundImage: `url(${StaticUrl}/site-status-${getStatusImageByStatus(item.status)}.png)`, backgroundSize: 'cover', backgroundPosition: 'center' }"
+            >
+              <image
+                class="mt-20rpx h-38rpx w-27.18rpx"
+                :src="`${StaticUrl}/terminal-icon.png`"
+              />
+              <view class="text-24rpx font-bold">
+                {{ formatStatusName(item.statusName) }}
+              </view>
+            </view>
+            <view>
+              <view class="text-bold text-28rpx">
+                {{ item.connectorName }}
+              </view>
+              <view class="mt-4rpx text-24rpx text-#AAA">
+                电类分类:{{ item.equipmentType }}
+              </view>
+              <view class="mt-4rpx w-300rpx overflow-hidden truncate whitespace-nowrap text-24rpx text-#AAA">
+                终端编号:{{ item.connectorCode }}
+              </view>
+            </view>
+          </view>
+          <view v-if="filteredConnectors.length < 1" class="h-100rpx w-full text-center text-24rpx text-#AAA line-height-[100rpx]">
+            暂无终端信息
+          </view>
+        </view>
+      </view>
+    </view>
+    <view class="h-170rpx" />
+    <view class="fixed bottom-0 left-0 right-0 h-166rpx w-full rounded-[30rpx_30rpx_0_0] bg-#FFF">
+      <view
+        class="h-166rpx"
+        :style="{ backgroundImage: `url(${StaticUrl}/site-price-bg.png)`, backgroundSize: 'cover', backgroundPosition: 'center' }"
+      >
+        <view class="h-166rpx flex items-center justify-center gap-32rpx">
+          <view class="ml-248rpx">
+            <text class="text-bold text-#F5531A">
+              ¥
+            </text>
+            <text class="text-bold text-40rpx text-#F5531A">
+              {{ stationDetail?.currentPrice }}
+            </text>
+            <text class="text-24rpx text-#AAA">
+              元/度
+            </text>
+          </view>
+          <view class="scan-qrcode" @click="scanCode">
+            扫码充电
+          </view>
+        </view>
+      </view>
+    </view>
+  </view>
+</template>
+
+<style lang="scss" scoped>
+.cardBg-set {
+  background-size: cover;
+  background-position: center;
+}
+
+.select-item {
+  background: #f5f3f3;
+  border-radius: 16rpx;
+  color: #2B303A;
+  text-align: center;
+}
+
+.select-item-active {
+  background: #9ED605;
+  box-shadow: inset 0rpx 20rpx 40rpx 2rpx rgba(100, 255, 218, 0.26);
+  border-radius: 0rpx 16rpx 0rpx 16rpx;
+  font-weight: bold;
+  color: #FFFFFF;
+}
+
+.scan-qrcode {
+  width: 220rpx;
+  height: 100rpx;
+  background: linear-gradient(90deg, #DBFC81 0%, #9ED605 100%);
+  box-shadow: inset 0rpx 6rpx 20rpx 2rpx #FFFFFF;
+  border-radius: 16rpx;
+  font-weight: 800;
+  font-size: 28rpx;
+  line-height: 112rpx;
+  text-align: center;
+}
+</style>

+ 139 - 0
src/subPack-charge/chargeStart/chargeStart.vue

@@ -0,0 +1,139 @@
+<script setup lang="ts">
+import router from '@/router'
+import { StaticUrl } from '@/config'
+
+const { statusBarHeight, MenuButtonHeight, opcity } = storeToRefs(useSysStore())
+const { userInfo } = storeToRefs(useUserStore())
+definePage({
+  name: 'charge-start',
+  islogin: true,
+  style: {
+    navigationBarTitleText: '启动终端',
+    navigationStyle: 'custom',
+  },
+})
+const connectorCode = ref()
+onLoad((options: any) => {
+  connectorCode.value = options.connectorCode
+})
+
+onMounted(() => {
+  opcity.value = 0
+  getConnectorDetail()
+})
+
+onPageScroll((e) => {
+  const calculatedOpacity = e.scrollTop / 100
+  opcity.value = Math.min(1, Math.max(0.1, calculatedOpacity))
+})
+
+const connectorDetailInfo = ref<Api.chargeConnectorDetail>()
+async function getConnectorDetail() {
+  const res = await Apis.charge.connectorDetail({ data: { connectorCode: connectorCode.value } })
+  connectorDetailInfo.value = res.data
+}
+
+const fromData = ref<Api.invokeChargeList>({
+  equipmentId: 0,
+  stationId: 0,
+  connectorId: '',
+  consigneeName: userInfo.value?.nickName,
+  consigneeMobile: userInfo.value?.mobile,
+})
+async function launchCharge() {
+  // router.push({ name: 'chargeing' })
+  // return
+  fromData.value.equipmentId = connectorDetailInfo.value?.equipmentId
+  fromData.value.stationId = connectorDetailInfo.value?.stationId
+  fromData.value.connectorId = connectorDetailInfo.value?.connectorCode
+  const res = await Apis.charge.invokeCharge({ data: fromData.value })
+  if (res.code === '00000') {
+    router.push({ name: 'chargeing', params: { orderNo: res.data } })
+  }
+}
+</script>
+
+<template>
+  <view class="charge-start-page min-h-screen bg-[linear-gradient(180deg,#F5FEDD_0%,#FCFFF3_22.46%,#FAFCFB_27.26%,#FBFDFC_45.2%,#FBFCFB_68.94%,#FBFCFB_100%)]">
+    <wd-navbar
+      title="启动终端" :custom-style="`background-color: rgba(226, 255, 145, ${opcity})`" :bordered="false"
+      :z-index="999" safe-area-inset-top left-arrow fixed @click-left="router.back()"
+    />
+    <view :style="{ paddingTop: `${(Number(statusBarHeight) || 44) + MenuButtonHeight + 12}px` }" />
+    <view>
+      <view class="h-486rpx w-648rpx">
+        <image
+          class="h-full w-full"
+          :src="`${StaticUrl}/start-charge.png`"
+        />
+      </view>
+      <view class="mt-94rpx flex items-center justify-center">
+        <view class="w-182rpx text-center">
+          <view class="text-28rpx text-#AAA">
+            电流A
+          </view>
+          <view class="mt-24rpx text-32rpx font-800">
+            {{ connectorDetailInfo?.current }}
+          </view>
+        </view>
+        <view class="h-40rpx w-2rpx bg-#DEDEDE" />
+        <view class="w-182rpx text-center">
+          <view class="text-28rpx text-#AAA">
+            电压V
+          </view>
+          <view class="mt-24rpx text-32rpx font-800">
+            {{ connectorDetailInfo?.currentVoltage || '0' }}
+          </view>
+        </view>
+        <view class="h-40rpx w-2rpx bg-#DEDEDE" />
+        <view class="w-182rpx text-center">
+          <view class="text-28rpx text-#AAA">
+            功率KW
+          </view>
+          <view class="mt-24rpx text-32rpx font-800">
+            {{ connectorDetailInfo?.power }}
+          </view>
+        </view>
+      </view>
+      <view class="mt-40rpx px24rpx">
+        <view class="flex items-center justify-between">
+          <view class="text-28rpx font-bold">
+            当前电价
+          </view>
+          <view class="flex items-center">
+            <text class="text-30rpx text-#FC5A5A font-bold">
+              {{ connectorDetailInfo?.currentPrice }}元
+            </text>
+            <text class="text-28rpx text-#AAA">
+              /度
+            </text>
+          </view>
+        </view>
+        <view class="mt-20rpx flex items-center justify-between">
+          <view class="text-28rpx font-bold">
+            当前时段
+          </view>
+          <view class="text-28rpx text-#AAA">
+            {{ connectorDetailInfo?.currentPeriodDesc }}
+          </view>
+        </view>
+        <view class="mt-20rpx flex items-center justify-between">
+          <view class="text-28rpx font-bold">
+            停车参考
+          </view>
+          <view class="text-28rpx text-#AAA">
+            {{ connectorDetailInfo?.parkingTips || '--' }}
+          </view>
+        </view>
+        <view class="mt-28rpx text-24rpx text-#AAA">
+          账单信息可能会有所延迟,具体以实际结算为准
+        </view>
+      </view>
+    </view>
+    <view class="fixed bottom-66rpx left-24rpx h-100rpx w-702rpx rounded-16rpx bg-[linear-gradient(90deg,#DBFC81_0%,#9ED605_100%)] text-center text-28rpx font-800 line-height-[100rpx] shadow-[inset_0rpx_6rpx_20rpx_2rpx_#FFFFFF]" @click="launchCharge">
+      启动终端充电
+    </view>
+  </view>
+</template>
+
+<style lang="scss" scoped></style>

+ 256 - 0
src/subPack-charge/chargeing/chargeing.vue

@@ -0,0 +1,256 @@
+<script setup lang="ts">
+import wlpProgress from '../components/wlp-progress-new/wlp-progress-new.vue'
+import chargeLoading from '../components/charge-loading.vue'
+import router from '@/router'
+import { StaticUrl } from '@/config'
+
+const stopCharge = ref(false)
+const current = ref(0)
+const isLongPressing = ref(false)
+const longPressTimer = ref< NodeJS.Timeout>()
+const longPressDuration = 2000 // 3秒
+
+const { statusBarHeight, MenuButtonHeight, opcity } = storeToRefs(useSysStore())
+definePage({
+  name: 'chargeing',
+  islogin: true,
+  style: {
+    navigationBarTitleText: '正在充电',
+    navigationStyle: 'custom',
+  },
+})
+const chargeingDetail = ref<Api.chargeingCostList>()
+const orderNo = ref()
+const { resume, pause } = useIntervalFn(() => {
+  getChargeingCost()
+}, 5000)
+
+onLoad((options: any) => {
+  orderNo.value = options.orderNo
+})
+
+onMounted(() => {
+  getChargeingCost()
+  resume()
+  opcity.value = 0
+})
+
+onPageScroll((e) => {
+  const calculatedOpacity = e.scrollTop / 100
+  opcity.value = Math.min(1, Math.max(0.1, calculatedOpacity))
+})
+async function getChargeingCost() {
+  const res = await Apis.charge.chargeingCost({ data: { orderNo: orderNo.value } })
+  chargeingDetail.value = res.data
+  if (chargeingDetail.value?.status === '2') {
+    pause()
+    clearInterval(longPressTimer.value)
+    router.replace({ name: 'smqjh-order' })
+  }
+}
+
+function onTouchStart() {
+  isLongPressing.value = true
+  current.value = 0
+  const startTime = Date.now()
+  longPressTimer.value = setInterval(() => {
+    if (isLongPressing.value) {
+      const elapsed = Date.now() - startTime
+      current.value = Math.round(Math.min(100, (elapsed / longPressDuration) * 100))
+      if (elapsed >= longPressDuration) {
+        current.value = 100
+        console.log('停止充电')
+        initiatedStopCharge()
+      }
+    }
+  }, 50) // 减少频率到50ms,避免抖动
+}
+
+function onTouchEnd() {
+  isLongPressing.value = false
+  if (current.value < 100) {
+    current.value = 0
+  }
+  clearInterval(longPressTimer.value)
+}
+
+async function initiatedStopCharge() {
+  useGlobalLoading().loading({})
+  const res: any = await Apis.charge.stopCharge({ data: { chargeOrderNo: chargeingDetail.value?.chargeOrderNo } })
+  if (res.code === '00000') {
+    pause()
+    clearInterval(longPressTimer.value)
+    useGlobalToast().success('停止充电成功')
+    stopCharge.value = false // 关闭弹窗
+    current.value = 0
+    router.replace({ name: 'smqjh-order' })
+  }
+  useGlobalLoading().close()
+}
+
+function closeOverlay() {
+  stopCharge.value = false
+  current.value = 0
+}
+
+onUnmounted(() => {
+  clearInterval(longPressTimer.value)
+})
+</script>
+
+<template>
+  <view class="chargeing-page min-h-screen bg-[linear-gradient(180deg,#F5FEDD_0%,#FCFFF3_22.46%,#FAFCFB_27.26%,#FBFDFC_45.2%,#FBFCFB_68.94%,#FBFCFB_100%)]">
+    <wd-navbar
+      :title="!chargeingDetail ? '启动中' : '正在充电'" :custom-style="`background-color: rgba(226, 255, 145, ${opcity})`" :bordered="false"
+      :z-index="999" safe-area-inset-top left-arrow fixed @click-left="router.back()"
+    />
+    <view :style="{ paddingTop: `${(Number(statusBarHeight) || 44) + MenuButtonHeight + 12}px` }" />
+    <view v-if="!chargeingDetail">
+      <charge-loading />
+    </view>
+    <view v-if="chargeingDetail?.status == '1'">
+      <view class="flex items-center justify-center">
+        <wlpProgress
+          :percent="chargeingDetail?.soc"
+          bg-color="#ebffb2"
+          progress-color="#CCF35F"
+          gradual-color="#9ED605"
+          title="充电枪正在充电中"
+        />
+      </view>
+      <view class="h-320rpx w-750rpx">
+        <image
+          class="h-full w-full"
+          :src="`${StaticUrl}/chargeing-in-progress.gif`"
+        />
+      </view>
+    </view>
+    <view class="mt-64rpx text-center">
+      <view class="text-60rpx text-#9ED605 font-bold">
+        {{ chargeingDetail?.chargingDurationDesc || '00:00:00' }}
+      </view>
+      <view class="mt-16rpx text-32rpx font-bold">
+        充电时间
+      </view>
+    </view>
+    <view class="mt-32rpx flex items-center justify-center">
+      <view class="w-182rpx text-center">
+        <view class="text-28rpx text-#AAA">
+          电流
+        </view>
+        <view class="mt-20rpx">
+          <text v-if="chargeingDetail?.current" class="text-32rpx font-800">
+            {{ chargeingDetail?.current }}
+          </text>
+          <image
+            v-else
+            class="h-40rpx w-40rpx"
+            :src="`${StaticUrl}/charge-loading.png`"
+          />
+        </view>
+      </view>
+      <view class="h-40rpx w-2rpx bg-#DEDEDE" />
+      <view class="w-182rpx text-center">
+        <view class="text-28rpx text-#AAA">
+          功率KW
+        </view>
+        <view class="mt-20rpx">
+          <text v-if="chargeingDetail?.power" class="text-32rpx font-800">
+            {{ chargeingDetail?.power }}
+          </text>
+          <image
+            v-else
+            class="h-40rpx w-40rpx"
+            :src="`${StaticUrl}/charge-loading.png`"
+          />
+        </view>
+      </view>
+      <view class="h-40rpx w-2rpx bg-#DEDEDE" />
+      <view class="w-182rpx text-center">
+        <view class="text-28rpx text-#AAA">
+          电量/度
+        </view>
+        <view class="mt-20rpx">
+          <text v-if="chargeingDetail?.totalPower" class="text-32rpx font-800">
+            {{ chargeingDetail?.totalPower }}
+          </text>
+          <image
+            v-else
+            class="h-40rpx w-40rpx"
+            :src="`${StaticUrl}/charge-loading.png`"
+          />
+        </view>
+      </view>
+      <view class="h-40rpx w-2rpx bg-#DEDEDE" />
+      <view class="w-182rpx text-center">
+        <view class="text-28rpx text-#AAA">
+          费用/元
+        </view>
+        <view class="mt-20rpx">
+          <text v-if="chargeingDetail?.totalMoney" class="text-32rpx font-800">
+            {{ chargeingDetail?.totalMoney }}
+          </text>
+          <image
+            v-else
+            class="h-40rpx w-40rpx"
+            :src="`${StaticUrl}/charge-loading.png`"
+          />
+        </view>
+      </view>
+    </view>
+    <view class="mt-30rpx flex items-center justify-center">
+      <view class="h-76rpx w-192rpx rounded-16rpx bg-#9ED605 text-center text-28rpx text-#FFF font-800 line-height-[76rpx]" @click="stopCharge = true">
+        <wd-loading v-if="!chargeingDetail" color="#FFF" :size="16" />
+        {{ !chargeingDetail ? '启动中' : '结束充电' }}
+      </view>
+    </view>
+    <view class="mt-56rpx box-border px24rpx">
+      <view class="mt-28rpx flex items-center justify-between">
+        <view class="text-28rpx font-bold">
+          订单编号
+        </view>
+        <view class="text-28rpx text-#AAA">
+          {{ chargeingDetail?.chargeOrderNo || '--' }}
+        </view>
+      </view>
+      <view class="mt-28rpx flex items-center justify-between">
+        <view class="text-28rpx font-bold">
+          终端编号
+        </view>
+        <view class="text-28rpx text-#AAA">
+          {{ chargeingDetail?.connectorCode || '--' }}
+        </view>
+      </view>
+      <view class="mt-28rpx flex items-center justify-between">
+        <view class="text-28rpx font-bold">
+          充电电站
+        </view>
+        <view class="text-28rpx text-#AAA">
+          {{ chargeingDetail?.stationName || '--' }}
+        </view>
+      </view>
+      <view class="mt-28rpx flex items-center justify-between">
+        <view class="text-28rpx font-bold">
+          充电终端
+        </view>
+        <view class="text-28rpx text-#AAA">
+          {{ chargeingDetail?.connectorName || '--' }}
+        </view>
+      </view>
+      <view class="mt-28rpx text-24rpx text-#AAA">
+        账单信息可能会有所延迟,具体以实际结算为准
+      </view>
+    </view>
+    <wd-overlay :show="stopCharge" :z-index="9999" @click="closeOverlay">
+      <view class="h-full w-full flex items-center justify-center" @touchstart="onTouchStart" @touchend="onTouchEnd">
+        <wd-circle v-model="current" color="#9ED605" :stroke-width="20" :size="160" layer-color="#FFF">
+          <view class="text-center text-28rpx text-#FFF line-height-[290rpx]">
+            长按停止充电
+          </view>
+        </wd-circle>
+      </view>
+    </wd-overlay>
+  </view>
+</template>
+
+<style lang="scss" scoped></style>

+ 86 - 0
src/subPack-charge/components/charge-loading.vue

@@ -0,0 +1,86 @@
+<script setup lang="ts">
+</script>
+
+<template>
+  <view class="">
+    <view class="circleBox">
+      <view class="circle" />
+      <view class="circle1" />
+      <view class="circle2" />
+      <view class="circle3" />
+    </view>
+    <view class="text-center">
+      <view class="text-32rpx text-#9ED605 font-800">
+        充电正在启动中
+      </view>
+      <view class="mt-20rpx text-24rpx text-#AAA">
+        长时间无法启动可“长按结束充电"按钮结束订单
+      </view>
+    </view>
+  </view>
+</template>
+
+<style lang="scss" scoped>
+  .circleBox {
+  position: relative;
+  width: 400rpx;
+  height: 400rpx;
+  margin:auto;
+}
+
+.circle,
+.circle1,
+.circle2,
+.circle3 {
+  width: 80rpx;
+  height: 80rpx;
+  background: rgba(255, 255, 255, 1);
+  /* border: 1px solid rgba(62, 182, 248, 0.7); */
+  box-shadow: inset 0rpx 6rpx 40rpx 2rpx rgba(186,239,42,0.8);
+  border-radius: 999px;
+  position: absolute;
+  top: 38%;
+  left: 41%;
+  /* transform: translate(-50%,-75%); */
+}
+.circle1,
+.circle2,
+.circle3 {
+  animation-name: circleChange;
+  animation-duration: 3s;
+  animation-iteration-count: infinite;
+  animation-timing-function: linear;
+}
+.circle1 {
+  animation-delay: 1s;
+}
+.circle2 {
+  animation-delay: 2s;
+}
+.circle3 {
+  animation-delay: 3s;
+}
+
+@keyframes circleChange {
+  0% {
+    transform: scale(1);
+    opacity: 0.95;
+  }
+  25% {
+    transform: scale(2);
+    opacity: 0.75;
+  }
+  50% {
+    transform: scale(3);
+    opacity: 0.5;
+  }
+  75% {
+    transform: scale(4);
+    opacity: 0.25;
+  }
+  100% {
+    transform: scale(5);
+    opacity: 0.05;
+  }
+}
+</style>

+ 31 - 1
src/subPack-charge/components/charge-tab.vue

@@ -1,11 +1,40 @@
 <script lang="ts" setup>
+import { ScanCodeUtil } from '../utils/index'
 import { StaticUrl } from '@/config'
+import router from '@/router'
+
+async function getDeviceInfo(connectorCode: string) {
+  useGlobalLoading().loading({})
+  const res = await Apis.charge.connectorDetail({ data: { connectorCode } })
+  useGlobalLoading().close()
+  if (res.data.status === 0 || res.data.status === 255) {
+    useGlobalMessage().alert('此设备异常或被占用,请更换其他设备')
+  }
+  else {
+    router.push({ name: 'charge-start', params: { connectorCode } })
+  }
+}
+
+async function scanCode() {
+  try {
+    const connectorCode = await ScanCodeUtil.scanAndGetConnectorCode()
+    if (!connectorCode) {
+      useGlobalMessage().alert('二维码不正确')
+      return
+    }
+    // 获取设备信息
+    getDeviceInfo(connectorCode)
+  }
+  catch (error) {
+    console.error('扫码失败:', error)
+  }
+}
 </script>
 
 <template>
   <view class="charge-footer">
     <view class="ios flex items-center justify-center pb-20rpx -mt-26rpx">
-      <view class="img-box">
+      <view class="img-box" @click="scanCode">
         <image class="h-120rpx w-120rpx" :src="`${StaticUrl}/charge-qrCode.png`" />
       </view>
     </view>
@@ -20,6 +49,7 @@ import { StaticUrl } from '@/config'
   border-radius: 32rpx 32rpx 0rpx 0rpx;
   background: #FFFFFF;
   box-shadow: 0rpx -6rpx 12rpx 2rpx rgba(0, 0, 0, 0.05);
+  z-index: 9999;
   .img-box{
     border-radius: 50%;
     width: 140rpx;

+ 41 - 21
src/subPack-charge/components/search.vue

@@ -1,42 +1,62 @@
 <script lang="ts" setup>
-import { ref } from 'vue'
+import { ref, watch } from 'vue'
 import { StaticUrl } from '@/config'
-// 如果需要从外部传入动态文本,可以使用 props
-defineProps<{
-  initialMapModeText?: string
-}>()
-// 如果需要从外部传入点击事件处理方法,也可以定义 emit
-defineEmits<{
-  (e: 'mapModeClick'): void
-}>()
-// 定义动态文本
-const mapModeText = ref('地图模式')
+import router from '@/router'
+// 添加动态图标和文字的 props
+interface Props {
+  mapModeIcon?: string
+  mapModeTextValue?: string
+}
+
+const props = withDefaults(defineProps<Props>(), {
+  mapModeIcon: `${StaticUrl}/charge-map.png`,
+  mapModeTextValue: '',
+})
+
+const emit = defineEmits<Emits>()
+interface Emits {
+  (e: 'mapModeClick'): void // 简化 emit,不需要事件参数
+}
+// 定义动态文本和图标
+const mapModeText = ref(props.mapModeTextValue)
+const iconPath = ref(props.mapModeIcon)
+
+// 监听外部传入的文字和图标变化
+watch(() => props.mapModeTextValue, (newVal) => {
+  mapModeText.value = newVal
+})
+
+watch(() => props.mapModeIcon, (newVal) => {
+  iconPath.value = newVal
+})
+
 // 定义点击事件处理方法
 function onMapModeClick() {
-  // 在这里添加点击逻辑
-  console.log('地图模式被点击')
-  // 示例:切换显示文本
-  // mapModeText.value = mapModeText.value === '地图模式' ? '列表模式' : '地图模式'
+  emit('mapModeClick')
+}
+
+function searchStation() {
+  router.push({ name: 'cahrge-search-list' })
 }
 </script>
 
 <template>
-  <view class="flex items-center justify-between">
-    <view class="search-box flex items-center">
+  <view class="flex items-center justify-between gap-20rpx">
+    <view class="search-box w-430rpx flex items-center" @click="searchStation">
       <view class="mr-16rpx flex items-center">
         <image :src="`${StaticUrl}/location-black.png`" class="h33.8rpx min-w28.97rpx w28.97rpx" />
-        <text class="ml-1">
+        <text class="text-bold ml-1 text-32rpx">
           贵阳
         </text>
       </view>
       <view class="h-36rpx border-2rpx border-#AAAAAA border-solid" />
-      <view class="ml-16rpx text-#AAAAAA">
+      <view class="ml-16rpx text-28rpx text-#AAAAAA">
         请输入目的地/电站名
       </view>
     </view>
     <view class="search-box flex items-center gap-20rpx" @click="onMapModeClick">
-      <image :src="`${StaticUrl}/charge-map.png`" class="h-40rpx w-40rpx" mode="" />
-      <text>
+      <image :src="iconPath" class="h-40rpx w-40rpx" />
+      <text class="text-28rpx font-bold">
         {{ mapModeText }}
       </text>
     </view>

+ 208 - 0
src/subPack-charge/components/wlp-progress-new/wlp-progress-new.vue

@@ -0,0 +1,208 @@
+<script lang="ts" setup>
+import { computed, getCurrentInstance, onMounted, ref, watch } from 'vue'
+
+const props = defineProps({
+  boxWidth: { type: Number, default: 200 },
+  boxHeight: { type: Number, default: 120 },
+  lineWidth: { type: Number, default: 8 },
+  isBgShow: { type: Boolean, default: true },
+  bgColor: { type: String, default: '#c1d1ea' },
+  type: {
+    type: String as () => 'circular' | 'halfCircular',
+    default: 'halfCircular',
+  },
+  percent: { type: Number, default: 0 },
+  title: { type: String, default: '' },
+  progressColor: { type: String, default: '#3FC987' },
+  gradualColor: { type: String, default: '' },
+})
+
+const instance = getCurrentInstance()
+const platform = uni.getSystemInfoSync().platform
+const isWeixin = platform === 'wechat' || platform === 'devtools'
+
+const canvasId = ref(`progressCanvas_${Date.now()}`)
+const bgCanvasId = ref(`bgCanvas_${Date.now()}`)
+const startPercent = ref(0)
+const ctxRef = ref<any>(null)
+const gradientRef = ref<any>(null)
+
+const realCanvasHeight = computed(() => props.boxHeight)
+const formattedPercent = computed(() => props.percent.toFixed(2))
+
+watch(() => props.percent, () => draw())
+
+onMounted(() => {
+  draw(true)
+})
+
+function draw(init = false) {
+  const start = Math.max(0, Math.min(startPercent.value, Math.floor(props.percent)))
+  if (props.isBgShow && init)
+    drawBackground()
+  drawProgress(start)
+}
+
+function drawBackground() {
+  const ctx = uni.createCanvasContext(bgCanvasId.value, instance?.proxy)
+  ctx.setLineWidth(props.lineWidth)
+  ctx.setStrokeStyle(props.bgColor)
+
+  const radius = props.boxWidth / 2
+  const offset = props.lineWidth
+  const startAngle = props.type === 'circular' ? -Math.PI / 2 : -Math.PI
+  const endAngle = props.type === 'circular' ? 1.5 * Math.PI : 0
+
+  ctx.setLineCap('round')
+  ctx.beginPath()
+  ctx.arc(radius, radius, radius - offset, startAngle, endAngle, false)
+  ctx.stroke()
+  ctx.draw()
+}
+
+function drawProgress(current: number) {
+  if (!ctxRef.value) {
+    const ctx = uni.createCanvasContext(canvasId.value, instance?.proxy)
+    const gradient = ctx.createLinearGradient(0, 0, props.boxWidth, 0)
+    gradient.addColorStop(0, props.progressColor)
+    if (props.gradualColor)
+      gradient.addColorStop(1, props.gradualColor)
+    ctxRef.value = ctx
+    gradientRef.value = gradient
+  }
+
+  const ctx = ctxRef.value
+  const gradient = gradientRef.value
+  const radius = props.boxWidth / 2
+  ctx.clearRect(0, 0, props.boxWidth, props.boxHeight)
+
+  const startAngle = props.type === 'circular' ? -Math.PI / 2 : -Math.PI
+  const arcLength
+    = props.type === 'circular'
+      ? (2 * Math.PI * current) / 100
+      : (Math.PI * current) / 100
+
+  ctx.setLineWidth(props.lineWidth)
+  ctx.setStrokeStyle(gradient)
+  if (current <= 0) {
+    ctx.setLineCap('butt') // 不显示小圆点
+  }
+  else {
+    ctx.setLineCap('round')
+  }
+  ctx.beginPath()
+  ctx.arc(radius, radius, radius - props.lineWidth, startAngle, startAngle + arcLength, false)
+  ctx.stroke()
+
+  if (isWeixin) {
+    ctx.draw(false, () => {
+      if (current < props.percent) {
+        setTimeout(() => {
+          startPercent.value = current + 1
+          drawProgress(startPercent.value)
+        }, 10)
+      }
+      else {
+        startPercent.value = current
+      }
+    })
+  }
+  else {
+    ctx.draw()
+    if (current < props.percent) {
+      setTimeout(() => {
+        startPercent.value = current + 1
+        drawProgress(startPercent.value)
+      }, 10)
+    }
+    else {
+      startPercent.value = current
+    }
+  }
+}
+</script>
+
+<template>
+  <view
+    class="circular-container"
+    :style="{ width: `${boxWidth}px`, height: `${boxHeight}px` }"
+  >
+    <!-- 背景 canvas -->
+    <canvas
+      v-if="isBgShow"
+      :id="bgCanvasId"
+      class="circular-bg"
+      :canvas-id="bgCanvasId"
+      :width="boxWidth"
+      :height="realCanvasHeight"
+      :style="{ width: `${boxWidth}px`, height: `${realCanvasHeight}px` }"
+    />
+
+    <!-- 前景 canvas -->
+    <canvas
+      :id="canvasId"
+      class="circular-progress"
+      :canvas-id="canvasId"
+      :width="boxWidth"
+      :height="realCanvasHeight"
+      :style="{ width: `${boxWidth}px`, height: `${realCanvasHeight}px` }"
+    />
+
+    <!-- 居中显示文本 -->
+    <view
+      class="center-label"
+      :style="{ width: `${boxWidth}px`, height: `${realCanvasHeight}px` }"
+    >
+      <text class="percent">
+        <text class="text-60rpx font-800">
+          {{ formattedPercent }}
+        </text>
+        %
+      </text>
+      <text class="title">
+        {{ title }}
+      </text>
+    </view>
+  </view>
+</template>
+
+<style lang="scss" scoped>
+.circular-container {
+  position: relative;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+
+  .circular-bg,
+  .circular-progress {
+    position: absolute;
+    top: 0;
+    left: 0;
+    z-index: 1;
+  }
+
+  .center-label {
+    position: absolute;
+    top: 24rpx;
+    left: 0;
+    z-index: 2;
+    width: 100%;
+    height: 100%;
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    align-items: center;
+
+    .title {
+      font-size: 22rpx;
+      color: #000;
+    }
+
+    .percent {
+      font-size: 28rpx;
+      font-weight: bold;
+      color: #000;
+    }
+  }
+}
+</style>

+ 147 - 91
src/subPack-charge/index/index.vue

@@ -3,9 +3,11 @@ import chargeSearch from '../components/search.vue'
 import chargeFooter from '../components/charge-tab.vue'
 import router from '@/router'
 import { StaticUrl } from '@/config'
+import { createGlobalLoadingMiddleware } from '@/api/core/middleware'
 
-const { statusBarHeight, MenuButtonHeight, opcity, userInfo } = storeToRefs(useSysStore())
-const swiperList = ['https://www.keaitupian.cn/cjpic/frombd/2/253/1659552792/3869332496.jpg']
+const { statusBarHeight, MenuButtonHeight, opcity } = storeToRefs(useSysStore())
+const { token, userInfo } = storeToRefs(useUserStore())
+const { Location } = storeToRefs(useAddressStore())
 definePage({
   name: 'charge-index',
   islogin: false,
@@ -15,29 +17,61 @@ definePage({
     backgroundColorBottom: '#fff',
   },
 })
+const activeFilter = ref<number>(1)
+const loading = ref(true)
 const filterOptions = [
-  { key: 'nearest', label: '离我最近', widthClass: 'w-152rpx' },
-  { key: 'most-available', label: '空闲最多', widthClass: '' },
-  { key: 'lowest-price', label: '电费最低', widthClass: '' },
+  { key: 1, label: '离我最近', widthClass: 'w-152rpx' },
+  { key: 2, label: '空闲最多', widthClass: '' },
+  { key: 3, label: '电费最低', widthClass: '' },
 ]
-const activeFilter = ref('nearest')
 
+/**
+ * 获取充电站列表
+ */
+const { data: stationList, isLastPage, page, refresh, reload } = usePagination((pageNum, pageSize) =>
+  Apis.charge.getStationInfoPage({ data: { pageNum, pageSize, sortType: activeFilter.value, longitude: Location.value.longitude || 106.620256, latitude: Location.value.latitude || 26.648327, userId: userInfo.value.id } }), {
+  data: (resp) => {
+    return resp.data?.list
+  },
+  initialData: [],
+  initialPage: 1,
+  initialPageSize: 10,
+  append: true,
+  immediate: true,
+  middleware: createGlobalLoadingMiddleware(),
+}).onSuccess(() => {
+  loading.value = false
+})
+onMounted(() => {
+  getUserAccountInfo()
+  opcity.value = 0
+})
+onShow(() => {
+  refresh()
+  getUserAccountInfo()
+})
+onPageScroll((e) => {
+  const calculatedOpacity = e.scrollTop / 100
+  opcity.value = Math.min(1, Math.max(0.1, calculatedOpacity))
+})
+onReachBottom(() => {
+  if (!isLastPage.value) {
+    page.value++
+  }
+})
+
+/**
+ * 获取用户账户信息
+ */
+const userAccountInfo = ref()
+async function getUserAccountInfo() {
+  const res = await Apis.charge.getMemberInfo({})
+  userAccountInfo.value = res.data
+}
 // 处理筛选项点击的方法
-function handleFilterClick(filterKey: string) {
+function handleFilterClick(filterKey: number) {
   activeFilter.value = filterKey
-  console.log(`选择了: ${filterKey}`)
-  // 根据不同筛选类型执行相应操作
-  switch (filterKey) {
-    case 'nearest':
-      // 执行距离排序逻辑
-      break
-    case 'most-available':
-      // 执行空闲数量排序逻辑
-      break
-    case 'lowest-price':
-      // 执行价格排序逻辑
-      break
-  }
+  reload()
 }
 </script>
 
@@ -57,7 +91,7 @@ function handleFilterClick(filterKey: string) {
       </template>
     </wd-navbar>
     <view :style="{ paddingTop: `${(Number(statusBarHeight) || 44) + MenuButtonHeight + 12}px` }" class="px24rpx">
-      <charge-search />
+      <charge-search map-mode-text-value="地图模式" @map-mode-click="router.push({ name: 'charge-map' })" />
       <view class="userInfo-card">
         <view class="flex items-center gap-20rpx">
           <image
@@ -68,9 +102,12 @@ function handleFilterClick(filterKey: string) {
             <view class="text-32rpx text-#2B303A font-bold">
               {{ userInfo?.nickName || '游客' }}
             </view>
-            <view class="text-24rpx text-#9ED605">
+            <view v-if="!token" class="text-24rpx text-#9ED605" @click="router.replace({ name: 'smqjh-login' })">
               授权登录
             </view>
+            <view v-else class="rounded-8rpx bg-#9ED605 px12rpx py4rpx text-24rpx text-#FFF opacity-70">
+              {{ userInfo.channelName }}
+            </view>
           </view>
         </view>
         <view class="mt-20rpx flex items-center justify-between gap-18rpx">
@@ -79,35 +116,37 @@ function handleFilterClick(filterKey: string) {
               <view>我的积分</view>
               <view>可用充电余额</view>
             </view>
-            <view class="mt-24rpx flex items-center gap-30rpx text-40rpx text-#9ED605 font-bold">
+            <view class="mt-24rpx flex items-center gap-30rpx text-28rpx text-#9ED605 font-500">
               <view class="flex items-center gap-20rpx">
-                <text>896</text>
-                <image class="h-48rpx w-48rpx" :src="`${StaticUrl}/charge-acc.png`" />
+                <text class="w-120rpx overflow-hidden truncate whitespace-nowrap">
+                  {{ userAccountInfo?.availablePoints || '--' }}
+                </text>
+                <image class="h-30rpx w-30rpx" :src="`${StaticUrl}/charge-acc.png`" />
               </view>
-              <view>
-                <text class="text-28rpx">
+              <view class="w-120rpx overflow-hidden truncate whitespace-nowrap">
+                <text class="text-20rpx">
                 </text>
-                89.6
+                {{ userAccountInfo?.balance || '--' }}
               </view>
             </view>
           </view>
-          <view class="flex items-center gap-20rpx bg-#F3FFD1 p-24rpx">
+          <view class="flex items-center gap-20rpx bg-#F3FFD1 p-24rpx" @click="router.push({ name: 'smqjh-order' })">
             <view>
               <view class="text-28rpx font-bold">
                 充电订单
               </view>
-              <view class="mt-24rpx text-40rpx text-#9ED605 font-bold">
-                956
+              <view class="mt-24rpx text-28rpx text-#9ED605 font-500">
+                {{ userAccountInfo?.chargingOrderCount || '--' }}
               </view>
             </view>
             <image class="h-80rpx w-80rpx" :src="`${StaticUrl}/charge-order.png`" />
           </view>
         </view>
       </view>
-      <view class="mt-24rpx">
+      <!-- <view class="mt-24rpx">
         <wd-swiper :list="swiperList" :height="100" :indicator="false" value-key="advertImg" />
-      </view>
+      </view> -->
       <view class="mt-24rpx flex items-center gap-20rpx">
         <view
           v-for="option in filterOptions"
@@ -121,75 +160,92 @@ function handleFilterClick(filterKey: string) {
           {{ option.label }}
         </view>
       </view>
-      <view>
-        <view class="relative mt-24rpx rounded-16rpx bg-#FFFFFF p-24rpx">
-          <image
-            class="absolute right-0 top-0 h-52rpx w-186rpx"
-            :src="`${StaticUrl}/charge-firm-tag.png`"
-          />
-          <view class="text-32rpx text-#2B303A font-bold">
-            贵阳花果园购物中心充电站
-          </view>
-          <view class="mt-20rpx text-24rpx text-#aaa">
-            充电减免2小时停车费,超出部分按每小时3元计算
-          </view>
-          <view class="mt-24rpx flex items-center rounded-16rpx bg-[linear-gradient(90deg,rgba(170,255,235,0.3)_0%,rgba(175,247,252,0.2)_43.57%,rgba(139,232,252,0)_100%)] p-20rpx">
-            <view class="flex items-center gap-16rpx">
-              <view class="h-40rpx w-40rpx rounded-8rpx bg-[linear-gradient(180deg,#4FEF86_0%,#00AA3A_100%)] text-center text-28rpx text-#FFF font-bold line-height-[40rpx]">
-                快
-              </view>
-              <view class="flex items-center">
-                <text class="text-32rpx font-bold">
-                  12
-                </text>
-                <text class="text-24rpx text-#AAAAAA">
-                  /12
-                </text>
-              </view>
+      <view :class="[loading ? 'pt-24rpx' : '']">
+        <wd-skeleton theme="paragraph" animation="gradient" :loading="loading" :row-col="[{ height: '100px', width: '100%' }, { height: '100px', width: '100%' }, { height: '100px', width: '100%' }]">
+          <view v-for="item in stationList" :key="item.stationId" class="relative mt-24rpx rounded-16rpx bg-#FFFFFF p-24rpx" @click="router.push({ name: 'charge-site-detail', params: { stationId: String(item.stationId) } })">
+            <image
+              class="absolute right-0 top-0 h-52rpx w-186rpx"
+              :src="`${StaticUrl}/charge-firm-tag.png`"
+            />
+            <view class="text-32rpx text-#2B303A font-bold">
+              {{ item.stationName }}
             </view>
-            <view class="ml-40rpx flex items-center gap-16rpx">
-              <view class="h-40rpx w-40rpx rounded-8rpx bg-[linear-gradient(180deg,#8EB1FF_0%,#3071FF_100%)] text-center text-28rpx text-#FFF font-bold line-height-[40rpx]">
-                慢
+            <view class="mt-20rpx text-24rpx text-#aaa">
+              {{ item.tips || '暂无提示' }}
+            </view>
+            <view class="mt-24rpx flex items-center rounded-16rpx bg-[linear-gradient(90deg,rgba(170,255,235,0.3)_0%,rgba(175,247,252,0.2)_43.57%,rgba(139,232,252,0)_100%)] p-20rpx">
+              <view class="flex items-center gap-16rpx">
+                <view class="h-40rpx w-40rpx rounded-8rpx bg-[linear-gradient(180deg,#4FEF86_0%,#00AA3A_100%)] text-center text-28rpx text-#FFF font-bold line-height-[40rpx]">
+                  快
+                </view>
+                <view class="flex items-center">
+                  <text class="text-32rpx font-bold">
+                    {{ item.fastCharging }}
+                  </text>
+                </view>
               </view>
-              <view class="flex items-center">
-                <text class="text-32rpx font-bold">
-                  12
-                </text>
-                <text class="text-24rpx text-#AAAAAA">
-                  /12
-                </text>
+              <view class="ml-40rpx flex items-center gap-16rpx">
+                <view class="h-40rpx w-40rpx rounded-8rpx bg-[linear-gradient(180deg,#8EB1FF_0%,#3071FF_100%)] text-center text-28rpx text-#FFF font-bold line-height-[40rpx]">
+                  慢
+                </view>
+                <view class="flex items-center">
+                  <text class="text-32rpx font-bold">
+                    {{ item.slowCharging }}
+                  </text>
+                </view>
+              </view>
+              <view class="ml-150rpx h-44rpx w-148rpx flex items-center border-2rpx border-#3EB6F8 rounded-34rpx border-solid line-height-[44rpx]">
+                <view class="w-44rpx rounded-[34rpx_0rpx_0rpx_34rpx] bg-#3EB6F8 text-center">
+                  <wd-icon name="location" size="16px" color="#FFF" />
+                </view>
+                <view class="text-24rpx text-#3EB6F8">
+                  {{ item.distance }}km
+                </view>
               </view>
             </view>
-            <view class="ml-150rpx h-44rpx w-148rpx flex items-center border-2rpx border-#3EB6F8 rounded-34rpx border-solid line-height-[44rpx]">
-              <view class="w-44rpx rounded-[34rpx_0rpx_0rpx_34rpx] bg-#3EB6F8 text-center">
-                <wd-icon name="location" size="16px" color="#FFF" />
+            <view v-if="!item.enterprisePrice" class="mt-28rpx flex items-center justify-between">
+              <view class="relative flex">
+                <view class="absolute left-30rpx z-10 flex items-center -top-26rpx">
+                  <text class="text-40rpx text-#FF6464 font-bold">
+                    {{ item.platformPrice }}
+                  </text>
+                  <text class="w-100rpx text-24rpx">
+                    元/度
+                  </text>
+                </view>
+                <image
+                  class="absolute h-60rpx w-365rpx -top-30rpx"
+                  :src="`${StaticUrl}/to-charge-tag.png`"
+                />
               </view>
-              <view class="text-24rpx text-#3EB6F8">
-                1.55km
+              <view class="text-24rpx text-#2B303A">
+                {{ item.peakValue }}:{{ item.peakTime }}
               </view>
             </view>
-          </view>
-          <view class="mt-28rpx flex items-center justify-between">
-            <view class="relative flex">
-              <view class="absolute left-30rpx z-10 flex items-center -top-26rpx">
-                <text class="text-40rpx text-#FF6464 font-bold">
-                  1.0026
-                </text>
-                <text class="w-100rpx text-24rpx">
-                  元/度
-                </text>
+            <view v-else class="mt-20rpx flex items-center justify-between">
+              <view class="flex items-center">
+                <view class="flex items-center -mt-10rpx">
+                  <text class="text-40rpx text-#FF6464 font-bold">
+                    {{ item.platformPrice }}
+                  </text>
+                  <text class="w-100rpx text-24rpx">
+                    元/度
+                  </text>
+                </view>
+                <view class="h-52rpx w-212rpx text-center" :style="{ backgroundImage: `url(${StaticUrl}/charge-firm.png)`, backgroundSize: 'cover', backgroundPosition: 'center' }">
+                  <text class="ml-70rpx text-28rpx text-#FF6464">
+                    {{ item.enterprisePrice }}
+                  </text>
+                </view>
+              </view>
+              <view class="text-24rpx text-#2B303A">
+                {{ item.peakValue }}:{{ item.peakTime }}
               </view>
-              <image
-                class="absolute h-60rpx w-365rpx -top-30rpx"
-                :src="`${StaticUrl}/to-charge-tag.png`"
-              />
-            </view>
-            <view class="text-24rpx text-#2B303A">
-              峰:10:00-13:00
             </view>
           </view>
-        </view>
+        </wd-skeleton>
       </view>
+      <view class="h-160rpx" />
     </view>
     <chargeFooter />
   </view>

+ 39 - 0
src/subPack-charge/store-charge/sys.ts

@@ -0,0 +1,39 @@
+import { defineStore } from 'pinia'
+
+interface SysState {
+  /**
+   * 搜索历史
+   */
+  searchHistory: string[]
+}
+
+export const useSysChargeStore = defineStore('system-charge', {
+  state: (): SysState => ({
+    searchHistory: [],
+  }),
+  actions: {
+    /**
+     * 获取搜索历史
+     */
+    getSearchHistory() {
+    },
+    /**
+     * 添加到搜索历史
+     * @param keyword 搜索关键词
+     */
+    addToSearchHistory(keyword: string) {
+      if (keyword && !this.searchHistory.includes(keyword)) {
+        this.searchHistory.unshift(keyword)
+        if (this.searchHistory.length > 10) {
+          this.searchHistory = this.searchHistory.slice(0, 10)
+        }
+      }
+    },
+    /**
+     * 清空搜索历史
+     */
+    clearSearchHistory() {
+      this.searchHistory = []
+    },
+  },
+})

+ 74 - 0
src/subPack-charge/utils/index.ts

@@ -0,0 +1,74 @@
+/**
+ * @param statusName 去掉括号及括号内的内容
+ */
+export function formatStatusName(statusName: string) {
+  return statusName.replace(/\([^)]*\)/g, '')
+}
+
+/**
+ * 扫码工具类
+ */
+export class ScanCodeUtil {
+  /**
+   * 调用扫码统一处理
+   * @param opts 参数配置,详细查看 https://uniapp.dcloud.net.cn/api/system/barcode.html
+   */
+  static scan(opts: any = {}) {
+    return new Promise((resolve, reject) => {
+      uni.scanCode(
+        Object.assign(
+          {},
+          {
+            success: (res: any) => resolve(res),
+            fail: reject,
+          },
+          opts,
+        ),
+      )
+    })
+  }
+
+  /**
+   * 解析 URL 参数
+   * @param url URL 字符串
+   */
+  static parseUrlParams(url: string) {
+    console.log(url, '二维码数据格式')
+
+    try {
+      const urlObj = new URL(url)
+      const params = new URLSearchParams(urlObj.search)
+      return Object.fromEntries(params.entries())
+    }
+    catch (error) {
+      console.warn('URL 构造函数不可用,使用手动解析:', error)
+      const queryString = url.split('?')[1]
+      if (!queryString)
+        return {}
+      const params: Record<string, string> = {}
+      queryString.split('&').forEach((pair) => {
+        const [key, value] = pair.split('=')
+        if (key) {
+          params[decodeURIComponent(key)] = decodeURIComponent(value || '')
+        }
+      })
+      return params
+    }
+  }
+
+  /**
+   * 扫码并提取 connectorCode
+   * @param opts 参数配置
+   */
+  static async scanAndGetConnectorCode(opts: any = {}): Promise<string | null> {
+    try {
+      const res: any = await this.scan(opts)
+      const params = this.parseUrlParams(res.result)
+      return params.connectorCode || null
+    }
+    catch (error) {
+      console.error('扫码或解析失败:', error)
+      throw error
+    }
+  }
+}

+ 45 - 0
src/subPack-smqjh/components/charge-orderList/charge-orderList.vue

@@ -0,0 +1,45 @@
+<script setup lang="ts">
+import router from '@/router'
+
+defineProps<{
+  orderList: Api.xsbOrderList[]
+  subPackOrder: any
+}>()
+</script>
+
+<template>
+  <view class="">
+    <view v-for="item in orderList" :key="item.orderNumber" class="mt-20rpx mt20rpx rounded-16rpx bg-#FFF p-24rpx" @click="router.push({ name: 'charge-order-detail' })">
+      <view class="flex items-center justify-between">
+        <view>
+          <view class="text-28rpx font-bold">
+            {{ item.shopName }}
+          </view>
+          <view class="mt-20rpx text-24rpx text-#AAA">
+            订单时间:{{ item.createTime || '未知' }}
+          </view>
+          <view class="mt-20rpx text-24rpx text-#AAA">
+            终端名称:{{ item.orderItemList?.[0]?.goodsName || '未知' }}
+          </view>
+        </view>
+        <view class="text-28rpx text-#4EDC86">
+          {{ subPackOrder?.handleCommonOrderStatusText(item) }}
+        </view>
+      </view>
+      <wd-divider />
+      <view class="flex items-center justify-between">
+        <view class="text-28rpx">
+          充电费用:
+        </view>
+        <view class="text-32rpx text-#FF6464 font-800">
+          <text class="text-18rpx">
+            ¥
+          </text>
+          {{ item.actualTotal }}
+        </view>
+      </view>
+    </view>
+  </view>
+</template>
+
+<style lang="scss" scoped></style>

+ 127 - 0
src/subPack-smqjh/components/xsb-orderList/xsb-orderList.vue

@@ -0,0 +1,127 @@
+<script setup lang="ts">
+import { StaticUrl } from '@/config'
+import router from '@/router'
+
+const props = defineProps<{
+  orderList: Api.xsbOrderList[]
+  subPackOrder?: typeof import('@/subPack-xsb/utils/order-data')
+  subPackConfirm?: typeof import('@/subPack-xsb/utils/confirm-order')
+}>()
+
+const _emit = defineEmits<{
+  'cancel': [order: Api.xsbOrderList]
+  'pay': [orderNumber: string]
+  'submit': [order: Api.xsbOrderList]
+  'del': [order: Api.xsbOrderList]
+  'after-sale': [item: Api.xsbOrderList]
+  'refresh': []
+}>()
+
+function handleClick(no: string) {
+  router.push({ name: 'xsb-orderDetaile', params: { id: no } })
+}
+</script>
+
+<template>
+  <view v-for="item in orderList" :key="item.orderNumber" class="mt20rpx rounded-16rpx bg-white p24rpx">
+    <view class="flex items-center justify-between">
+      <view class="flex items-center">
+        <image :src="`${StaticUrl}/order-icon.png`" class="h36rpx w36rpx" />
+        <view class="ml20rpx text-32rpx font-semibold">
+          {{ item.shopName }}
+        </view>
+      </view>
+      <view class="text-24rpx text-#FF4D3A">
+        <template v-if="item.hbOrderStatus !== props.subPackOrder?.OrderStatus.PaddingPay">
+          {{ props.subPackOrder?.handleCommonOrderStatusText(item) }}
+        </template>
+        <template v-else>
+          <view class="flex items-center">
+            待支付( 还剩 <wd-count-down :time="props.subPackOrder?.handleCommonOrderStatusText(item)" @finish="$emit('refresh')" /> )
+          </view>
+        </template>
+      </view>
+    </view>
+    <view class="my24rpx h2rpx w-full bg-#F0F0F0" />
+    <view>
+      <!-- <view class="mb20rpx box-border rounded-16rpx bg-#F9F9F9 p24rpx">
+            <view class="flex items-center">
+              <image :src="`${StaticUrl}/order-car.png`" class="h36rpx w36rpx" />
+              <view class="ml20rpx text-28rpx text-#222 font-semibold">
+                预计10:40前可送达
+              </view>
+            </view>
+            <view class="mt18rpx">
+              您的订单预计3月7日 10:40前送达
+            </view>
+            <view class="mt20rpx">
+              2025-03-26 11:56:07
+            </view>
+          </view> -->
+      <view
+        class="box-border h176rpx w-full flex items-center justify-between rounded-16rpx bg-#F9F9F9"
+        @click="handleClick(item.orderNumber as string)"
+      >
+        <view class="box-border h-full w480rpx py28rpx pl20rpx">
+          <scroll-view scroll-x class="h-full w-full whitespace-nowrap">
+            <view class="flex items-center">
+              <view v-for="goods in item.orderItemList" :key="goods.skuId" class="mr50rpx">
+                <image :src="goods.pic" class="h120rpx w120rpx" />
+              </view>
+            </view>
+          </scroll-view>
+        </view>
+        <view class="box-shadow box-border h-full flex-1 flex-shrink-0 px14rpx py40rpx">
+          <view class="text-center text-32rpx text-#FF4D3A font-semibold">
+            ¥{{ item.actualTotal }}
+          </view>
+          <view class="text-center text-28rpx text-#AAAAAA">
+            共{{ item.goodsTotal }}件
+          </view>
+        </view>
+      </view>
+    </view>
+    <view class="my24rpx flex items-center justify-end">
+      <template v-if="item.hbOrderStatus === props.subPackOrder?.OrderStatus.PaddingPay">
+        <view class="mr20rpx">
+          <wd-button size="small" plain type="info" @click.stop="$emit('cancel', item)">
+            取消订单
+          </wd-button>
+        </view>
+        <view class="mr20rpx">
+          <wd-button size="small" plain type="error" @click.stop="$emit('pay', item.orderNumber as string)">
+            付款
+          </wd-button>
+        </view>
+      </template>
+      <template v-if="[props.subPackOrder?.OrderStatus.OrderCancel, props.subPackOrder?.OrderStatus.OrderCompleted].includes(item.hbOrderStatus) ">
+        <view class="mr20rpx">
+          <wd-button size="small" plain type="info" @click.stop="$emit('del', item)">
+            删除订单
+          </wd-button>
+        </view>
+        <!-- <view class="ml20rpx">
+              <wd-button size="small" plain type="error" >
+                再次购买
+              </wd-button>
+            </view> -->
+      </template>
+      <template v-if="item.hbOrderStatus === props.subPackOrder?.OrderStatus.OrderArrived">
+        <view class="mr20rpx">
+          <wd-button size="small" plain type="info" @click.stop="$emit('submit', item)">
+            确认收货
+          </wd-button>
+        </view>
+      </template>
+      <template v-if="item.refundStatus != 2 || [props.subPackOrder?.OrderStatus.OrderCompleted, props.subPackOrder?.OrderStatus.OrderWaitDelivery, props.subPackOrder?.OrderStatus.OrderAccepted].includes(item.hbOrderStatus) ">
+        <view class="mr20rpx">
+          <wd-button size="small" plain type="info" @click.stop="$emit('after-sale', item)">
+            申请售后
+          </wd-button>
+        </view>
+      </template>
+    </view>
+  </view>
+</template>
+
+<style lang="scss" scoped></style>

+ 62 - 0
src/subPack-smqjh/order/components/OrderRenderer.vue

@@ -0,0 +1,62 @@
+<script setup lang="ts">
+import chargeList from '../../components/charge-orderList/charge-orderList.vue'
+import xsbList from '../../components/xsb-orderList/xsb-orderList.vue'
+
+interface Props {
+  orderList: Api.xsbOrderList[]
+  navActiveTab: string
+  subPackOrder: any
+  subPackConfirm: any
+}
+
+defineProps<Props>()
+defineEmits<{
+  'cancel': [order: Api.xsbOrderList]
+  'pay': [orderNumber: string]
+  'submit': [order: Api.xsbOrderList]
+  'del': [order: Api.xsbOrderList]
+  'after-sale': [item: Api.xsbOrderList]
+  'refresh': []
+}>()
+</script>
+
+<template>
+  <template v-if="navActiveTab === 'all'">
+    <template v-for="order in orderList" :key="order.orderNumber">
+      <xsbList
+        v-if="order.businessType === 'XSB'"
+        :order-list="[order]"
+        :sub-pack-order="subPackOrder"
+        :sub-pack-confirm="subPackConfirm"
+        @cancel="$emit('cancel', $event)"
+        @pay="$emit('pay', $event)"
+        @submit="$emit('submit', $event)"
+        @del="$emit('del', $event)"
+        @after-sale="$emit('after-sale', $event)"
+        @refresh="$emit('refresh')"
+      />
+      <chargeList
+        v-else-if="order.businessType === 'CD'"
+        :order-list="[order]"
+        :sub-pack-order="subPackOrder"
+      />
+    </template>
+  </template>
+  <xsbList
+    v-else-if="navActiveTab === 'XSB'"
+    :order-list="orderList"
+    :sub-pack-order="subPackOrder"
+    :sub-pack-confirm="subPackConfirm"
+    @cancel="$emit('cancel', $event)"
+    @pay="$emit('pay', $event)"
+    @submit="$emit('submit', $event)"
+    @del="$emit('del', $event)"
+    @after-sale="$emit('after-sale', $event)"
+    @refresh="$emit('refresh')"
+  />
+  <chargeList
+    v-else-if="navActiveTab === 'CHARGE'"
+    :order-list="orderList"
+    :sub-pack-order="subPackOrder"
+  />
+</template>

+ 47 - 110
src/subPack-smqjh/order/index.vue

@@ -1,8 +1,8 @@
 <script setup lang="ts">
+import { computed } from 'vue'
+import OrderRenderer from './components/OrderRenderer.vue'
 import { navTabTypeList, orderStatusList } from './order-data'
 import { createGlobalLoadingMiddleware } from '@/api/core/middleware'
-import { StaticUrl } from '@/config'
-import router from '@/router'
 
 definePage({
   name: 'smqjh-order',
@@ -33,6 +33,34 @@ const { data: orderList, refresh, isLastPage, page, reload } = usePagination((pa
   append: true,
   middleware: createGlobalLoadingMiddleware(),
 })
+
+function createFilteredList(navTabValue: string, businessType: string) {
+  return computed(() => {
+    if (navActiveTab.value === 'all') {
+      return orderList.value.filter(order => order.businessType === businessType)
+    }
+    else if (navActiveTab.value === navTabValue) {
+      return orderList.value
+    }
+    return []
+  })
+}
+
+const xsbOrderList = createFilteredList('XSB', 'XSB')
+const chargeOrderList = createFilteredList('CHARGE', 'CD')
+
+const currentOrderList = computed(() => {
+  if (navActiveTab.value === 'all') {
+    return orderList.value
+  }
+  else if (navActiveTab.value === 'XSB') {
+    return xsbOrderList.value
+  }
+  else if (navActiveTab.value === 'CHARGE') {
+    return chargeOrderList.value
+  }
+  return []
+})
 onMounted(async () => {
   subPackOrder.value = await AsyncImport('@/subPack-xsb/utils/order-data')
   subPackComfirm.value = await AsyncImport('@/subPack-xsb/utils/confirm-order')
@@ -48,20 +76,16 @@ onShow(() => {
   orderList.value = []
   refresh()
 })
-function handleChangeStatus(value: string) {
-  orderStatusActive.value = value
-  orderList.value = []
-  reload()
-}
-function handleClick(no: string) {
-  console.log(12)
-  router.push({ name: 'xsb-orderDetaile', params: { id: no } })
-}
 onReachBottom(() => {
   if (!isLastPage.value) {
     page.value++
   }
 })
+function handleChangeStatus(value: string) {
+  orderStatusActive.value = value
+  orderList.value = []
+  reload()
+}
 async function handleCancel(order: Api.xsbOrderList) {
   await subPackOrder.value?.handleCommonCancelOrder(order)
   reload()
@@ -126,105 +150,18 @@ async function handleAfterSale(item: Api.xsbOrderList) {
       </view>
     </view>
     <view class="px24rpx">
-      <view v-for="item in orderList" :key="item.orderNumber" class="mt20rpx rounded-16rpx bg-white p24rpx">
-        <view class="flex items-center justify-between">
-          <view class="flex items-center">
-            <image :src="`${StaticUrl}/order-icon.png`" class="h36rpx w36rpx" />
-            <view class="ml20rpx text-32rpx font-semibold">
-              {{ item.shopName }}
-            </view>
-          </view>
-          <view class="text-24rpx text-#FF4D3A">
-            <template v-if="item.hbOrderStatus !== subPackOrder?.OrderStatus.PaddingPay">
-              {{ subPackOrder?.handleCommonOrderStatusText(item) }}
-            </template>
-            <template v-else>
-              <view class="flex items-center">
-                待支付( 还剩 <wd-count-down :time="subPackOrder?.handleCommonOrderStatusText(item)" @finish="refresh" /> )
-              </view>
-            </template>
-          </view>
-        </view>
-        <view class="my24rpx h2rpx w-full bg-#F0F0F0" />
-        <view>
-          <!-- <view class="mb20rpx box-border rounded-16rpx bg-#F9F9F9 p24rpx">
-            <view class="flex items-center">
-              <image :src="`${StaticUrl}/order-car.png`" class="h36rpx w36rpx" />
-              <view class="ml20rpx text-28rpx text-#222 font-semibold">
-                预计10:40前可送达
-              </view>
-            </view>
-            <view class="mt18rpx">
-              您的订单预计3月7日 10:40前送达
-            </view>
-            <view class="mt20rpx">
-              2025-03-26 11:56:07
-            </view>
-          </view> -->
-          <view
-            class="box-border h176rpx w-full flex items-center justify-between rounded-16rpx bg-#F9F9F9"
-            @click="handleClick(item.orderNumber as string)"
-          >
-            <view class="box-border h-full w480rpx py28rpx pl20rpx">
-              <scroll-view scroll-x class="h-full w-full whitespace-nowrap">
-                <view class="flex items-center">
-                  <view v-for="goods in item.orderItemList" :key="goods.skuId" class="mr50rpx">
-                    <image :src="goods.pic" class="h120rpx w120rpx" />
-                  </view>
-                </view>
-              </scroll-view>
-            </view>
-            <view class="box-shadow box-border h-full flex-1 flex-shrink-0 px14rpx py40rpx">
-              <view class="text-center text-32rpx text-#FF4D3A font-semibold">
-                ¥{{ item.actualTotal }}
-              </view>
-              <view class="text-center text-28rpx text-#AAAAAA">
-                共{{ item.goodsTotal }}件
-              </view>
-            </view>
-          </view>
-        </view>
-        <view class="my24rpx flex items-center justify-end">
-          <template v-if="item.hbOrderStatus === subPackOrder?.OrderStatus.PaddingPay">
-            <view class="mr20rpx">
-              <wd-button size="small" plain type="info" @click.stop="handleCancel(item)">
-                取消订单
-              </wd-button>
-            </view>
-            <view class="mr20rpx">
-              <wd-button size="small" plain type="error" @click.stop="handlePay(item.orderNumber as string)">
-                付款
-              </wd-button>
-            </view>
-          </template>
-          <template v-if="[subPackOrder?.OrderStatus.OrderCancel, subPackOrder?.OrderStatus.OrderCompleted].includes(item.hbOrderStatus) ">
-            <view class="mr20rpx">
-              <wd-button size="small" plain type="info" @click.stop="handleDel(item)">
-                删除订单
-              </wd-button>
-            </view>
-            <!-- <view class="ml20rpx">
-              <wd-button size="small" plain type="error" >
-                再次购买
-              </wd-button>
-            </view> -->
-          </template>
-          <template v-if="item.hbOrderStatus === subPackOrder?.OrderStatus.OrderArrived">
-            <view class="mr20rpx">
-              <wd-button size="small" plain type="info" @click.stop="handleSubmitOrder(item)">
-                确认收货
-              </wd-button>
-            </view>
-          </template>
-          <template v-if="item.refundStatus != 2 || [subPackOrder?.OrderStatus.OrderCompleted, subPackOrder?.OrderStatus.OrderWaitDelivery, subPackOrder?.OrderStatus.OrderAccepted].includes(item.hbOrderStatus) ">
-            <view class="mr20rpx">
-              <wd-button size="small" plain type="info" @click.stop="handleAfterSale(item)">
-                申请售后
-              </wd-button>
-            </view>
-          </template>
-        </view>
-      </view>
+      <OrderRenderer
+        :order-list="currentOrderList"
+        :nav-active-tab="navActiveTab"
+        :sub-pack-order="subPackOrder"
+        :sub-pack-confirm="subPackComfirm"
+        @cancel="handleCancel"
+        @pay="handlePay"
+        @submit="handleSubmitOrder"
+        @del="handleDel"
+        @after-sale="handleAfterSale"
+        @refresh="refresh"
+      />
       <StatusTip v-if="!orderList.length" tip="暂无内容" />
     </view>
     <view class="h-20rpx" />

+ 1 - 0
src/subPack-smqjh/order/order-data.ts

@@ -1,6 +1,7 @@
 export const navTabTypeList = [
   { name: '全部', value: 'all' },
   { name: '星闪豹', value: 'XSB' },
+  { name: '充电', value: 'CHARGE' },
   { name: '电影演出', value: 'MOVIE' },
   { name: '视频权益', value: 'VIDEO' },
   { name: '大牌点餐', value: 'SHOP' },

+ 3 - 1
src/subPack-xsb/utils/confirm-order.ts

@@ -85,7 +85,7 @@ export function getWxCommonPayment(orderPay: wxpay) {
       },
       fail(e) {
         console.log(e, '失败')
-
+        payError()
         reject(e)
       },
       complete() {
@@ -115,6 +115,8 @@ export function paySuccess() {
  * 支付成功统一跳转
  */
 export function payError() {
+  console.log('进入支付失败')
+
   return new Promise((resolve) => {
     const { paySuccessPath, payBackIndexPath } = storeToRefs(useSysStore())
     paySuccessPath.value = 'xsb-order'

+ 7 - 0
src/uni-pages.d.ts

@@ -29,6 +29,13 @@ type _LocationUrl =
   "/subPack-common/revalueSuccess/index" |
   "/subPack-common/user-center/index" |
   "/subPack-smqjh/order/index" |
+  "/subPack-charge/chargeDetail/chargeDetail" |
+  "/subPack-charge/chargeing/chargeing" |
+  "/subPack-charge/chargeMap/chargeMap" |
+  "/subPack-charge/chargeOrderDetail/chargeOrderDetail" |
+  "/subPack-charge/chargeSearchList/chargeSearchList" |
+  "/subPack-charge/chargeSiteDetail/chargeSiteDetail" |
+  "/subPack-charge/chargeStart/chargeStart" |
   "/subPack-charge/index/index";
 
 interface NavigateToOptions {