linee 1 week ago
parent
commit
d04a603858
54 changed files with 4878 additions and 541 deletions
  1. 1 1
      entry/agconnect-services.json
  2. 9 1
      entry/build.gradle
  3. 43 15
      entry/src/main/config.json
  4. 65 4
      entry/src/main/java/com/fujica/abk/MainAbility.java
  5. 31 31
      entry/src/main/java/com/fujica/abk/api/auth.java
  6. 57 0
      entry/src/main/java/com/fujica/abk/api/cache.java
  7. 43 5
      entry/src/main/java/com/fujica/abk/api/common.java
  8. 3 1
      entry/src/main/java/com/fujica/abk/api/config.java
  9. 85 0
      entry/src/main/java/com/fujica/abk/api/pay.java
  10. 2 2
      entry/src/main/java/com/fujica/abk/component/AuthorizationDialog.java
  11. 22 8
      entry/src/main/java/com/fujica/abk/component/ParkDetailComponent.java
  12. 7 10
      entry/src/main/java/com/fujica/abk/component/ParkItemComponent.java
  13. 441 0
      entry/src/main/java/com/fujica/abk/component/PayDetailDialog.java
  14. 121 0
      entry/src/main/java/com/fujica/abk/component/PayFailDialog.java
  15. 121 0
      entry/src/main/java/com/fujica/abk/component/PaySuccessDialog.java
  16. 555 0
      entry/src/main/java/com/fujica/abk/component/QRCodeScanDialog.java
  17. 42 4
      entry/src/main/java/com/fujica/abk/component/nav/ChargeComponent.java
  18. 139 41
      entry/src/main/java/com/fujica/abk/component/nav/ParkComponent.java
  19. 282 0
      entry/src/main/java/com/fujica/abk/manager/CardTriggerManager.java
  20. 119 0
      entry/src/main/java/com/fujica/abk/model/in/PayRequest.java
  21. 61 6
      entry/src/main/java/com/fujica/abk/model/out/ParkingFeeInfo.java
  22. 179 0
      entry/src/main/java/com/fujica/abk/model/out/PayChannelInfo.java
  23. 199 0
      entry/src/main/java/com/fujica/abk/model/out/PayChannelResponse.java
  24. 40 0
      entry/src/main/java/com/fujica/abk/model/out/PayResponse.java
  25. 146 0
      entry/src/main/java/com/fujica/abk/model/out/PayStatusResponse.java
  26. 222 124
      entry/src/main/java/com/fujica/abk/slice/MainAbilitySlice.java
  27. 40 0
      entry/src/main/java/com/fujica/abk/utils/PermissionManager.java
  28. 191 0
      entry/src/main/java/com/fujica/abk/utils/QRCodeUtil.java
  29. 59 8
      entry/src/main/java/com/fujica/abk/utils/Toast.java
  30. 1 1
      entry/src/main/java/com/fujica/abk/utils/api.java
  31. 39 0
      entry/src/main/js/jsability/pages/index/index.css
  32. 8 0
      entry/src/main/js/jsability/pages/index/index.hml
  33. 84 0
      entry/src/main/js/jsability/pages/index/index.js
  34. BIN
      entry/src/main/js/widget/common/app_icon.png
  35. BIN
      entry/src/main/js/widget/common/ic_default_image@3x.png
  36. BIN
      entry/src/main/js/widget/common/refresh.png
  37. 1 2
      entry/src/main/js/widget/i18n/en-US.json
  38. 1 2
      entry/src/main/js/widget/i18n/zh-CN.json
  39. 43 46
      entry/src/main/js/widget/pages/index/index.css
  40. 13 9
      entry/src/main/js/widget/pages/index/index.hml
  41. 8 3
      entry/src/main/js/widget/pages/index/index.json
  42. 0 11
      entry/src/main/js/widget/pages/index/index1.hml
  43. 1 1
      entry/src/main/js/widget1/i18n/zh-CN.json
  44. 20 0
      entry/src/main/resources/base/graphic/background_toast.xml
  45. 203 204
      entry/src/main/resources/base/layout/ability_main.xml
  46. 67 0
      entry/src/main/resources/base/layout/dialog_pay_fail.xml
  47. 83 0
      entry/src/main/resources/base/layout/dialog_pay_success.xml
  48. 33 0
      entry/src/main/resources/base/layout/layout_custom_toast.xml
  49. 84 0
      entry/src/main/resources/base/layout/layout_input_dialog.xml
  50. 388 0
      entry/src/main/resources/base/layout/layout_pay_detail_dialog.xml
  51. 388 0
      entry/src/main/resources/base/layout/layout_pay_detail_qr_dialog.xml
  52. 87 0
      entry/src/main/resources/base/layout/layout_qrcode_scan_dialog.xml
  53. BIN
      entry/src/main/resources/base/media/bg.png
  54. 1 1
      entry/src/main/resources/rawfile/agconnect-services.json

File diff suppressed because it is too large
+ 1 - 1
entry/agconnect-services.json


+ 9 - 1
entry/build.gradle

@@ -1,6 +1,8 @@
 apply plugin: 'com.huawei.ohos.hap'
 apply plugin: 'com.huawei.agconnect'
 apply plugin: 'com.huawei.ohos.decctest'
+
+
 //For instructions on signature configuration, see https://developer.harmonyos.com/cn/docs/documentation/doc-guides-V3/ide_debug_device-0000001053822404-V3#section1112183053510
 ohos {
     signingConfigs {
@@ -33,12 +35,18 @@ dependencies {
     implementation fileTree(dir: 'libs', include: ['*.jar', '*.har'])
     // 高德地图 SDK 依赖 - 显式指定har文件
 //    implementation files('libs/mapslibrary-release.har')
-    ohosTestImplementation 'com.huawei.ohos.testkit:runner:2.0.0.400'
 
     implementation 'com.huawei.hms:hwid-ohos:6.5.0.300'
     implementation 'com.huawei.agconnect:agconnect-core-harmony:1.3.0.300'
     // Gson JSON 解析库
     implementation 'com.google.code.gson:gson:2.10.1'
+    // ZXing 二维码生成库
+    implementation 'com.google.zxing:core:3.5.2'
+    // 华为支付 SDK 建议取最新的版本
+    implementation 'com.huawei.hms:paymentservice:6.12.0.300'
+
+    // hms jsb adapter
+//    implementation 'com.huawei.hms:jsb-ohos-adapter:6.5.0.300'
 }
 decc {
     supportType = ['html', 'xml']

+ 43 - 15
entry/src/main/config.json

@@ -1,17 +1,18 @@
 {
   "app": {
-    "vendor": "example",
+    "vendor": "fujica",
     "bundleName": "com.fujica.abk",
     "version": {
-      "code": 1000000,
-      "name": "1.0.0"
+      "code": 1000001,
+      "name": "1.0.1"
     }
   },
   "deviceConfig": {
     "default": {
       "network": {
         "cleartextTraffic": true
-      }
+      },
+      "allowComponentsProxy": true
     }
   },
   "module": {
@@ -23,7 +24,7 @@
       },
       {
         "name": "ohos.permission.LOCATION",
-        "reason": "需要定位权限以在地图上显示当前位置",
+        "reason": "需要定位权限以查询附近停车场",
         "usedScene": {
           "ability": [
             "com.fujica.abk.MainAbility"
@@ -81,12 +82,7 @@
         },
         {
           "name": "com.huawei.hms.client.appid",
-          "value": "6917590990169282724"
-        },
-        {
-          "name": "com.amap.api.v2.apikey",
-          "value": "您的高德地图API Key",
-          "extra": ""
+          "value": "116162389"
         }
       ]
     },
@@ -121,11 +117,11 @@
             "scheduledUpdateTime": "10:30",
             "defaultDimension": "2*2",
             "name": "widget",
-            "description": "爱泊客停车缴费1",
+            "description": "爱泊客停车缴费",
             "colorMode": "auto",
             "type": "JS",
             "supportDimensions": [
-              "2*2"
+              "2*4","2*2"
             ],
             "updateEnabled": true,
             "updateDuration": 1
@@ -136,17 +132,28 @@
             "scheduledUpdateTime": "10:30",
             "defaultDimension": "2*2",
             "name": "widget1",
-            "description": "爱泊客停车缴费2",
+            "description": "爱泊客停车缴费",
             "colorMode": "auto",
             "type": "JS",
             "supportDimensions": [
-              "2*2"
+              "2*4","2*2"
             ],
             "updateEnabled": true,
             "updateDuration": 1
           }
         ],
         "launchType": "standard"
+      },
+      {
+        "orientation": "landscape",
+        "visible": true,
+        "name": ".JsAbility",
+        "srcPath": "jsability",
+        "icon": "$media:icon",
+        "description": "JS Ability 示例",
+        "label": "JS Ability",
+        "type": "page",
+        "launchType": "standard"
       }
     ],
     "distro": {
@@ -168,6 +175,27 @@
           "autoDesignWidth": true
         },
         "type": "form"
+      },
+      {
+        "name": "widget1",
+        "pages": [
+          "pages/index/index"
+        ],
+        "window": {
+          "designWidth": 720,
+          "autoDesignWidth": true
+        },
+        "type": "form"
+      },
+      {
+        "name": "jsability",
+        "pages": [
+          "pages/index/index"
+        ],
+        "window": {
+          "designWidth": 720,
+          "autoDesignWidth": true
+        }
       }
     ]
   }

+ 65 - 4
entry/src/main/java/com/fujica/abk/MainAbility.java

@@ -1,18 +1,21 @@
 package com.fujica.abk;
 
+import com.fujica.abk.manager.CardTriggerManager;
 import com.fujica.abk.slice.MainAbilitySlice;
-import ohos.aafwk.ability.Ability;
+import com.fujica.abk.common.EventBus;
+import com.fujica.abk.utils.*;
+import ohos.aafwk.ability.*;
 import ohos.aafwk.content.Intent;
 import com.fujica.abk.widget.controller.FormController;
 import com.fujica.abk.widget.controller.FormControllerManager;
-import ohos.aafwk.ability.AbilitySlice;
-import ohos.aafwk.ability.ProviderFormInfo;
 import ohos.agp.window.service.WindowManager;
 import ohos.hiviewdfx.HiLog;
 import ohos.hiviewdfx.HiLogLabel;
 import ohos.agp.window.service.Window;
+import ohos.utils.zson.ZSONObject;
 
 public class MainAbility extends Ability {
+
     public static final int DEFAULT_DIMENSION_2X2 = 2; //System-defined constant. Do not change its value.
     private static final int INVALID_FORM_ID = -1;
     private static final HiLogLabel TAG = new HiLogLabel(HiLog.DEBUG, 0x0, MainAbility.class.getName());
@@ -32,6 +35,15 @@ public class MainAbility extends Ability {
         }
     }
 
+    @Override
+    public void onRequestPermissionsFromUserResult(int requestCode, String[] permissions, int[] grantResults) {
+        super.onRequestPermissionsFromUserResult(requestCode, permissions, grantResults);
+        if (requestCode == PermissionManager.Request_Location) {
+            PermissionManager.updateLocation(permissions, grantResults);
+            EventBus.getInstance().emit("onLocationPermissionGranted");
+        }
+    }
+
     /**
      * 设置全屏显示
      */
@@ -63,6 +75,7 @@ public class MainAbility extends Ability {
         String formName = intent.getStringParam(AbilitySlice.PARAM_FORM_NAME_KEY);
         int dimension = intent.getIntParam(AbilitySlice.PARAM_FORM_DIMENSION_KEY, DEFAULT_DIMENSION_2X2);
         HiLog.info(TAG, "onCreateForm: formId=" + formId + ",formName=" + formName);
+        Log.error("onCreateForm: formId=" + formId + ",formName=" + formName);
         FormControllerManager formControllerManager = FormControllerManager.getInstance(this);
         FormController formController = formControllerManager.getController(formId);
         formController = (formController == null) ? formControllerManager.createFormController(formId,
@@ -76,6 +89,7 @@ public class MainAbility extends Ability {
 
     @Override
     protected void onUpdateForm(long formId) {
+        Log.error("onUpdateForm:" + formId);
         HiLog.info(TAG, "onUpdateForm");
         super.onUpdateForm(formId);
         FormControllerManager formControllerManager = FormControllerManager.getInstance(this);
@@ -85,6 +99,7 @@ public class MainAbility extends Ability {
 
     @Override
     protected void onDeleteForm(long formId) {
+        Log.error("onDeleteForm:" + formId);
         HiLog.info(TAG, "onDeleteForm: formId=" + formId);
         super.onDeleteForm(formId);
         FormControllerManager formControllerManager = FormControllerManager.getInstance(this);
@@ -93,13 +108,59 @@ public class MainAbility extends Ability {
         formControllerManager.deleteFormController(formId);
     }
 
+    private void updateFormValue(long formId) {
+        ZSONObject zsonObject = new ZSONObject();
+        zsonObject.put("line2", "爱泊客停车无忧");
+        zsonObject.put("line3", "自助缴费 便捷立场");
+        FormBindingData formBindingData = new FormBindingData(zsonObject);
+        // 调用updateForm接口去更新对应的卡片,仅更新入参中携带的数据信息,其他信息保持不变
+        try {
+            if (!updateForm(formId, formBindingData)) {
+                // err process
+            }
+        } catch (FormException e) {
+            Toast.error(getContext(), "卡片信息更新失败");
+            Log.error("卡片信息更新失败");
+        }
+    }
+
+    private void updateFormValue(long formId, String line2, String line3) {
+        ZSONObject zsonObject = new ZSONObject();
+        zsonObject.put("line2", line2);
+        zsonObject.put("line3", line3);
+        FormBindingData formBindingData = new FormBindingData(zsonObject);
+        // 调用updateForm接口去更新对应的卡片,仅更新入参中携带的数据信息,其他信息保持不变
+        try {
+            if (!updateForm(formId, formBindingData)) {
+                // err process
+            }
+        } catch (FormException e) {
+            Toast.error(getContext(), "卡片信息更新失败");
+            Log.error("卡片信息更新失败");
+        }
+    }
+
     @Override
     protected void onTriggerFormEvent(long formId, String message) {
-        HiLog.info(TAG, "onTriggerFormEvent: " + message);
+        Log.error("onTriggerFormEvent:" + formId + " " + message);
         super.onTriggerFormEvent(formId, message);
         FormControllerManager formControllerManager = FormControllerManager.getInstance(this);
         FormController formController = formControllerManager.getController(formId);
         formController.onTriggerFormEvent(formId, message);
+
+        // 使用LoadingStateManager检查加载状态,防止并发请求
+        CardTriggerManager cardTriggerManager = CardTriggerManager.getInstance();
+        if (!cardTriggerManager.tryStartLoading()) {
+            return; // 如果已经在加载中,直接返回
+        }
+
+        // 调用CardTriggerManager加载停车场数据
+        cardTriggerManager.loadParkingData(
+                getContext(),
+                formId,
+                this::updateFormValue,
+                (fId, data) -> updateFormValue(fId, data[0], data[1])
+        );
     }
 
     @Override

+ 31 - 31
entry/src/main/java/com/fujica/abk/api/auth.java

@@ -54,7 +54,7 @@ public class auth {
         // 设置登录状态
         authing = true;
 
-        if (true) {
+        if (config.isDebug) {
             proceedWithLogin(context, future);
         } else {
             // 登录之前先显示授权确认弹框
@@ -88,10 +88,10 @@ public class auth {
      * 执行实际的登录流程
      */
     private static void proceedWithLogin(Context context, CompletableFuture<Boolean> future) {
-        if (true) {
+        if (config.isDebug) {
             HWResult hwResult = new HWResult();
 
-            hwResult.setAppId(config.appId);
+            hwResult.setAppId(config.getAppId());
 
             //dev环境
 //            hwResult.setOpenId("AAAjdc3utGbjvCsmhASifWUoEpmH");
@@ -106,7 +106,8 @@ public class auth {
             // 注意:HMS SDK可能不直接提供authorizationCode,这里需要根据实际情况调整
             // 如果HMS SDK不提供code,可能需要使用其他方式获取
             java.util.Map<String, String> data = new java.util.HashMap<>();
-            data.put("appId", config.appId);
+            data.put("appId", config.getAppId());
+            data.put("code", hwResult.getCode()); // 需要从授权结果中获取
             data.put("openId", hwResult.getOpenId());
             data.put("unionId", hwResult.getUnionId());
             option.setData(data);
@@ -131,8 +132,8 @@ public class auth {
                 // 注意:HMS SDK可能不直接提供authorizationCode,这里需要根据实际情况调整
                 // 如果HMS SDK不提供code,可能需要使用其他方式获取
                 java.util.Map<String, String> data = new java.util.HashMap<>();
-                data.put("appId", config.appId);
-                // data.put("code", authResult.code); // 需要从授权结果中获取
+                data.put("appId", config.getAppId());
+                 data.put("code", hwResult.getCode()); // 需要从授权结果中获取
                 data.put("openId", hwResult.getOpenId());
                 data.put("unionId", hwResult.getUnionId());
                 option.setData(data);
@@ -250,6 +251,7 @@ public class auth {
             // 创建授权请求参数
             AccountAuthParams accountAuthParams = new AccountAuthParamsHelper(
                     AccountAuthParams.DEFAULT_AUTH_REQUEST_PARAM)
+                    .setAuthorizationCode()
                     .createParams();
 
             AccountAuthService accountAuthService;
@@ -270,7 +272,8 @@ public class auth {
             Task<AuthAccount> taskSilentSignIn = accountAuthService.silentSignIn();
             taskSilentSignIn.addOnSuccessListener(authAccount -> {
                 HWResult result = new HWResult(true);
-                result.setAppId(config.appId);
+                result.setCode(authAccount.getAuthorizationCode());
+                result.setAppId(config.getAppId());
                 result.setOpenId(authAccount.getOpenId());
                 result.setUnionId(authAccount.getUnionId());
                 // HMS SDK可能不直接提供手机号,需要单独申请权限
@@ -286,29 +289,26 @@ public class auth {
                         int statusCode = apiException.getStatusCode();
 
                         // 静默登录失败,尝试前台登录
-                        if (statusCode == 8) { // 需要用户授权
-                            Task<AuthAccount> taskSignIn = accountAuthService.signIn();
-                            taskSignIn.addOnSuccessListener(new OnSuccessListener<AuthAccount>() {
-                                @Override
-                                public void onSuccess(AuthAccount authAccount) {
-                                    HWResult result = new HWResult(true);
-                                    result.setAppId(config.appId);
-                                    result.setOpenId(authAccount.getOpenId());
-                                    result.setUnionId(authAccount.getUnionId());
-                                    result.setPhone("");
-                                    future.complete(result);
-                                }
-                            });
-
-                            taskSignIn.addOnFailureListener(new OnFailureListener() {
-                                @Override
-                                public void onFailure(Exception e) {
-                                    handleAuthError(context, e, future);
-                                }
-                            });
-                        } else {
-                            handleAuthError(context, e, future);
-                        }
+                        Task<AuthAccount> taskSignIn = accountAuthService.signIn();
+                        taskSignIn.addOnSuccessListener(new OnSuccessListener<AuthAccount>() {
+                            @Override
+                            public void onSuccess(AuthAccount authAccount) {
+                                HWResult result = new HWResult(true);
+                                result.setCode(authAccount.getAuthorizationCode());
+                                result.setAppId(config.getAppId());
+                                result.setOpenId(authAccount.getOpenId());
+                                result.setUnionId(authAccount.getUnionId());
+                                result.setPhone("");
+                                future.complete(result);
+                            }
+                        });
+
+                        taskSignIn.addOnFailureListener(new OnFailureListener() {
+                            @Override
+                            public void onFailure(Exception e) {
+                                handleAuthError(context, e, future);
+                            }
+                        });
                     } else {
                         handleAuthError(context, e, future);
                     }
@@ -333,7 +333,7 @@ public class auth {
             // 模拟器调试模式
             if (code == 12300001 && config.isDebug) {
                 HWResult result = new HWResult(true);
-                result.setAppId(config.appId);
+                result.setAppId(config.getAppId());
                 result.setOpenId("AAAjdc3utGbjvphuWASifWUoEpm1");
                 result.setUnionId("");
                 result.setPhone("");

+ 57 - 0
entry/src/main/java/com/fujica/abk/api/cache.java

@@ -22,6 +22,9 @@ public class cache {
     public static final String KEY_TOKEN = "token";
     public static final String KEY_OPEN_ID = "open_id";
     public static final String KEY_MOBILE = "mobile";
+    public static final String KEY_LOCATION_LATITUDE = "location_latitude";
+    public static final String KEY_LOCATION_LONGITUDE = "location_longitude";
+    public static final String KEY_DEFAULT_PLATE_NO = "default_plate_no";
 
     /**
      * 获取Preferences实例
@@ -127,4 +130,58 @@ public class cache {
         return token != null && !token.isEmpty();
     }
 
+    /**
+     * 获取缓存的经度
+     */
+    public static double getLocationLatitude(Context context) {
+        String value = get(context, KEY_LOCATION_LATITUDE);
+        if (value == null || value.isEmpty()) {
+            return 0.0; // 默认值
+        }
+        try {
+            return Double.parseDouble(value);
+        } catch (Exception e) {
+            Log.error(e);
+            return 0.0;
+        }
+    }
+
+    /**
+     * 获取缓存的纬度
+     */
+    public static double getLocationLongitude(Context context) {
+        String value = get(context, KEY_LOCATION_LONGITUDE);
+        if (value == null || value.isEmpty()) {
+            return 0.0; // 默认值
+        }
+        try {
+            return Double.parseDouble(value);
+        } catch (Exception e) {
+            Log.error(e);
+            return 0.0;
+        }
+    }
+
+    /**
+     * 设置位置缓存
+     */
+    public static void setLocation(Context context, double latitude, double longitude) {
+        set(context, KEY_LOCATION_LATITUDE, String.valueOf(latitude));
+        set(context, KEY_LOCATION_LONGITUDE, String.valueOf(longitude));
+    }
+
+    /**
+     * 获取默认车牌号
+     */
+    public static String getDefaultPlateNo(Context context) {
+        return get(context, KEY_DEFAULT_PLATE_NO);
+    }
+
+    /**
+     * 设置默认车牌号
+     */
+    public static void setDefaultPlateNo(Context context, String plateNo) {
+        set(context, KEY_DEFAULT_PLATE_NO, plateNo);
+    }
+
 }

+ 43 - 5
entry/src/main/java/com/fujica/abk/api/common.java

@@ -19,8 +19,8 @@ public class common {
      * 查询停车费用API (真实接口)
      * 参考 TypeScript 版本的 pay.getChargeData 实现
      *
-     * @param context      上下文
-     * @param query 查询条件
+     * @param context 上下文
+     * @param query   查询条件
      * @return 停车费用信息
      */
     public static CompletableFuture<R<ParkingFeeInfo>> queryParkingFee(Context context, ChargeQuery query) {
@@ -68,15 +68,53 @@ public class common {
         });
     }
 
-    public static void updateDefaultPlateNo(Context context, String plateNo){
-        if(plateNo!=null && !plateNo.isEmpty()){
+    public static void updateDefaultPlateNo(Context context, String plateNo) {
+        if (plateNo != null && !plateNo.isEmpty()) {
             ApiOption option = new ApiOption("/member/plate/default");
             option.setMethod(ApiOption.POST);
             Map<String, Object> params = new HashMap<>();
             params.put("plateNo", plateNo);
             params.put("powerType", 1);
             option.setData(params);
-            api.http(context, option, new TypeToken<R<String>>() {});
+            api.http(context, option, new TypeToken<R<String>>() {
+            }).thenAccept(result -> {
+                // API 调用成功后,将车牌写入缓存
+                if (result != null && result.isSuccess()) {
+                    cache.setDefaultPlateNo(context, plateNo);
+                    Log.info("默认车牌已更新并写入缓存: " + plateNo);
+                }
+            }).exceptionally(e -> {
+                Log.error("更新默认车牌失败: " + e.getMessage());
+                return null;
+            });
         }
     }
+
+    /**
+     * 获取订单有效时间(倒计时时长)
+     * 返回值单位为分钟数,大于0表示需要倒计时
+     *
+     * @param context 上下文
+     * @return 订单有效时间(分钟)
+     */
+    public static CompletableFuture<R<Integer>> getOrderValidTime(Context context) {
+        return CompletableFuture.supplyAsync(() -> {
+            try {
+                if (config.isDebug) {
+                    return new R<>(true, "", 0, 1);
+                }
+                ApiOption option = new ApiOption("/cg/getOrderValidTime");
+                option.setMethod(ApiOption.GET);
+                option.setToast(false); // 不显示错误提示
+
+                TypeToken<R<Integer>> typeToken = new TypeToken<R<Integer>>() {
+                };
+                R<Integer> result = api.http(context, option, typeToken).get();
+                return result;
+            } catch (Exception e) {
+                Log.error("获取订单有效时间失败: " + e.getMessage());
+                return new R<>("获取失败: " + e.getMessage());
+            }
+        });
+    }
 }

+ 3 - 1
entry/src/main/java/com/fujica/abk/api/config.java

@@ -5,8 +5,10 @@ package com.fujica.abk.api;
  */
 public class config {
 //    public static String appId = "6917590990169282724"; // 需要替换为实际的appId
-    public static String appId = "wxd3598cc7953b6a59"; // 查询支付记录
 
+    public static String getAppId(){
+        return  isDebug? "wxd3598cc7953b6a59" : "116162389";
+    }
 
     public static boolean isDebug = true; // 是否调试模式
 }

+ 85 - 0
entry/src/main/java/com/fujica/abk/api/pay.java

@@ -0,0 +1,85 @@
+package com.fujica.abk.api;
+
+import com.fujica.abk.model.in.PayRequest;
+import com.fujica.abk.model.out.PayChannelResponse;
+import com.fujica.abk.model.out.PayResponse;
+import com.fujica.abk.model.out.PayStatusResponse;
+import com.fujica.abk.utils.*;
+import com.google.gson.reflect.TypeToken;
+import ohos.app.Context;
+
+import java.util.concurrent.CompletableFuture;
+
+/**
+ * 支付相关API
+ */
+public class pay {
+
+    /**
+     * 统一支付接口
+     *
+     * @param context 上下文
+     * @param request 支付请求参数
+     * @return 支付响应
+     */
+    public static CompletableFuture<R<PayResponse>> payByUnify(Context context, PayRequest request) {
+
+        if (config.isDebug) {
+            // 返回固定数据
+            PayResponse payResponse = new PayResponse();
+            payResponse.setQrCode("weixin://wxpay/bizpayurl?pr=XDkA8wDz3");
+
+            R<PayResponse> result = new R<>();
+            result.setCode(0);
+            result.setMsg(null);
+            result.setData(payResponse);
+            result.setSuccess(true);
+
+            return CompletableFuture.completedFuture(result);
+        }
+
+        ApiOption option = new ApiOption("/pay/payByUnify", request);
+        option.setMethod(ApiOption.POST);
+
+        TypeToken<R<PayResponse>> typeToken = new TypeToken<R<PayResponse>>() {
+        };
+        return api.http(context, option, typeToken);
+    }
+
+    /**
+     * 查询支付状态
+     * 接口文档: https://gatewayservicev2dev.fujica.com.cn/doc.html#/transfer-service-mobile/移动端-支付业务-http接口/getOrderResultUsingGET_1
+     *
+     * @param context 上下文
+     * @param payNo   支付流水号
+     * @return 支付状态信息(包含订单详情和支付状态)
+     */
+    public static CompletableFuture<R<PayStatusResponse>> queryPayStatus(Context context, String payNo) {
+        ApiOption option = new ApiOption("/pay/getOrderResult?payNo=" + payNo);
+        option.setMethod(ApiOption.GET);
+        option.setToast(false); // 不显示错误提示
+//        {"code":0,"msg":null,"data":{"payNo":"36b084edaf304845b4cea76250c6cf9b","orderId":"PP604507685867589570843935105093","goodsName":"粤B22222","parkId":"570843935105093","parkName":"车场0919","projectNo":"P20250919672046","totalAmount":2,"actualAmount":2,"payStatus":1,"bizType":1,"mergeOrderFlag":0,"payChannelCode":"ALI","paySourceCode":"HW_CAR","payWayCode":"ALI","paySceneCode":"ALI_PCRE"},"success":true,"reqId":"9c7c6d8de95c483d92a361aa83c504c0"}
+        TypeToken<R<PayStatusResponse>> typeToken = new TypeToken<R<PayStatusResponse>>() {
+        };
+        return api.http(context, option, typeToken);
+    }
+
+    /**
+     * 获取支付渠道
+     * 接口路径: /transfer/mobile/setting/payChannel/{parkId}
+     *
+     * @param context 上下文
+     * @param parkId  车场ID
+     * @return 支付渠道信息
+     */
+    public static CompletableFuture<R<PayChannelResponse>> getPayChannel(Context context, String parkId) {
+        ApiOption option = new ApiOption("/pay/getChannelByPark?parkId=" + parkId);
+        option.setMethod(ApiOption.GET);
+        option.setToast(false); // 不显示错误提示
+
+        TypeToken<R<PayChannelResponse>> typeToken = new TypeToken<R<PayChannelResponse>>() {
+        };
+        return api.http(context, option, typeToken);
+    }
+}
+

+ 2 - 2
entry/src/main/java/com/fujica/abk/component/AuthorizationDialog.java

@@ -32,7 +32,7 @@ public class AuthorizationDialog extends CommonDialog {
         setContentCustomComponent(dialogComponent);
 
         // 授权按钮
-        Button btnAuthorize = (Button) dialogComponent.findComponentById(ResourceTable.Id_btn_authorize);
+        Button btnAuthorize = dialogComponent.findComponentById(ResourceTable.Id_btn_authorize);
         if (btnAuthorize != null) {
             btnAuthorize.setClickedListener(v -> {
                 if (listener != null) {
@@ -43,7 +43,7 @@ public class AuthorizationDialog extends CommonDialog {
         }
 
         // 取消按钮
-        Button btnBack = (Button) dialogComponent.findComponentById(ResourceTable.Id_btn_back);
+        Button btnBack = dialogComponent.findComponentById(ResourceTable.Id_btn_back);
         if (btnBack != null) {
             btnBack.setClickedListener(v -> {
                 if (listener != null) {

+ 22 - 8
entry/src/main/java/com/fujica/abk/component/ParkDetailComponent.java

@@ -3,11 +3,14 @@ package com.fujica.abk.component;
 import com.fujica.abk.ResourceTable;
 import com.fujica.abk.model.out.ParkNearRes;
 import com.fujica.abk.utils.Log;
+import com.fujica.abk.utils.PermissionManager;
+import ohos.aafwk.content.Intent;
 import ohos.agp.colors.RgbColor;
 import ohos.agp.components.*;
 import ohos.agp.components.element.ShapeElement;
 import ohos.agp.utils.Color;
 import ohos.app.Context;
+import ohos.utils.net.Uri;
 
 /**
  * 停车场详情组件
@@ -98,18 +101,29 @@ public class ParkDetailComponent extends DirectionalLayout {
             addServiceTags();
 
             // 设置收费信息
-            Text chargeInfoText = (Text) rootLayout.findComponentById(ResourceTable.Id_charge_info);
+            Text chargeInfoText = rootLayout.findComponentById(ResourceTable.Id_charge_info);
             if (chargeInfoText != null) {
                 String chargeInfo = parkData.getChargeInfo();
                 chargeInfoText.setText(chargeInfo != null && !chargeInfo.isEmpty() ? chargeInfo : "暂无信息");
             }
 
             // 设置导航按钮点击事件
-            Button btnNavigate = (Button) rootLayout.findComponentById(ResourceTable.Id_btn_navigate);
+            Button btnNavigate = rootLayout.findComponentById(ResourceTable.Id_btn_navigate);
             if (btnNavigate != null) {
                 btnNavigate.setClickedListener(component -> {
-                    // TODO: 实现导航功能
-                    Log.info("导航到停车场: " + parkData.getParkName());
+                    try {
+                        // 构建导航 URI
+//                        Uri content_url = Uri.parse("petalmaps://navigation?saddr=25.102916,55.165363&daddr=25.164610000000,55.228869000000&type=drive&utm_source=fb");
+                        Uri content_url = Uri.parse("petalmaps://navigation?daddr=" + parkData.getLatitude() + "," + parkData.getLongitude() + "&type=drive&utm_source=fb");
+                        // 创建隐式 Intent
+                        Intent intent = new Intent();
+                        intent.setUri(content_url);
+                        // 启动地图导航
+                        getContext().startAbility(intent, PermissionManager.Common);
+                    } catch (Exception e) {
+                        Log.error("启动导航失败: " + e.getMessage());
+                        e.printStackTrace();
+                    }
                 });
             }
         } catch (Exception e) {
@@ -171,7 +185,7 @@ public class ParkDetailComponent extends DirectionalLayout {
         tag.setText(text);
         tag.setTextSize(11, Text.TextSizeType.FP);
         tag.setTextColor(new Color(0xFFFA6332));
-        
+
         // 设置边框和圆角
         ShapeElement background = new ShapeElement();
         background.setShape(ShapeElement.RECTANGLE);
@@ -179,10 +193,10 @@ public class ParkDetailComponent extends DirectionalLayout {
         background.setCornerRadius(3);
         background.setStroke(1, new RgbColor(250, 99, 50)); // #FA6332
         tag.setBackground(background);
-        
+
         // 设置内边距
         tag.setPadding(8, 4, 8, 4);
-        
+
         // 设置布局参数
         DirectionalLayout.LayoutConfig layoutConfig = new DirectionalLayout.LayoutConfig(
                 ComponentContainer.LayoutConfig.MATCH_CONTENT,
@@ -190,7 +204,7 @@ public class ParkDetailComponent extends DirectionalLayout {
         );
         layoutConfig.setMarginRight(8);
         tag.setLayoutConfig(layoutConfig);
-        
+
         return tag;
     }
 }

+ 7 - 10
entry/src/main/java/com/fujica/abk/component/ParkItemComponent.java

@@ -3,6 +3,7 @@ package com.fujica.abk.component;
 import com.fujica.abk.ResourceTable;
 import com.fujica.abk.model.out.ParkNearRes;
 import com.fujica.abk.utils.Log;
+import com.fujica.abk.utils.PermissionManager;
 import com.fujica.abk.utils.ScreenUtil;
 import ohos.aafwk.content.Intent;
 import ohos.agp.colors.RgbColor;
@@ -184,16 +185,12 @@ public class ParkItemComponent extends DirectionalLayout {
             Image navButton = (Image) rootLayout.findComponentById(ResourceTable.Id_btn_navigate);
             if (navButton != null) {
                 navButton.setClickedListener(component -> {
-
-//                    Uri content_url = Uri.parse("petalmaps://navigation?saddr=25.102916,55.165363&daddr=25.164610000000,55.228869000000&type=drive&utm_source=fb");
-//                    Intent intent = new Intent(Intent.ACTION_VIEW, content_url);
-//                    if (intent.resolveActivity(getPackageManager()) != null) {
-//                        startActivity(intent);
-//                    }
-
-                    // 导航功能
-                    Log.info("导航到: " + parkData.getParkName());
-                    // TODO: 实现导航功能
+                    Uri content_url = Uri.parse("petalmaps://navigation?daddr=" + parkData.getLatitude() + "," + parkData.getLongitude() + "&type=drive&utm_source=fb");
+                    // 创建隐式 Intent
+                    Intent intent = new Intent();
+                    intent.setUri(content_url);
+                    // 启动地图导航
+                    getContext().startAbility(intent, PermissionManager.Common);
                 });
             }
         } catch (Exception e) {

+ 441 - 0
entry/src/main/java/com/fujica/abk/component/PayDetailDialog.java

@@ -0,0 +1,441 @@
+package com.fujica.abk.component;
+
+import com.fujica.abk.ResourceTable;
+import com.fujica.abk.api.common;
+import com.fujica.abk.model.in.ChargeQuery;
+import com.fujica.abk.model.out.ParkingFeeInfo;
+import com.fujica.abk.utils.DialogUtil;
+import com.fujica.abk.utils.Log;
+import com.fujica.abk.utils.R;
+import com.fujica.abk.utils.Toast;
+import ohos.agp.components.*;
+import ohos.agp.utils.LayoutAlignment;
+import ohos.agp.window.dialog.CommonDialog;
+import ohos.app.Context;
+import ohos.eventhandler.EventHandler;
+import ohos.eventhandler.EventRunner;
+
+import java.text.DecimalFormat;
+import java.util.concurrent.CompletableFuture;
+
+/**
+ * 支付订单详情弹框
+ * 参考 pay.vue 实现
+ */
+public class PayDetailDialog {
+    private Context context;
+    private CommonDialog dialog;
+    private Component rootView;
+    private ParkingFeeInfo feeInfo;
+    private OnPayClickListener onPayClickListener;
+    
+    // 倒计时相关
+    private EventHandler countdownHandler;
+    private int countdownSeconds = 0; // 倒计时秒数
+    private boolean isCountdownRunning = false;
+    private Button btnPay; // 支付按钮
+
+    /**
+     * 支付按钮点击监听器
+     */
+    public interface OnPayClickListener {
+        void onPayClick(ParkingFeeInfo feeInfo);
+    }
+
+    /**
+     * 构造函数
+     */
+    public PayDetailDialog(Context context) {
+        this.context = context;
+        countdownHandler = new EventHandler(EventRunner.getMainEventRunner());
+        initDialog();
+    }
+
+    /**
+     * 初始化对话框
+     */
+    private void initDialog() {
+        // 创建 CommonDialog
+        dialog = new CommonDialog(context);
+        
+        // 加载自定义布局
+        rootView = LayoutScatter.getInstance(context)
+                .parse(ResourceTable.Layout_layout_pay_detail_dialog, null, false);
+
+        // 设置关闭按钮点击事件
+        Image btnClose = (Image) rootView.findComponentById(ResourceTable.Id_btn_close_dialog);
+        if (btnClose != null) {
+            btnClose.setClickedListener(component -> {
+                stopCountdown();
+                hide();
+            });
+        }
+
+        // 设置支付按钮点击事件
+        btnPay = (Button) rootView.findComponentById(ResourceTable.Id_btn_pay);
+        if (btnPay != null) {
+            btnPay.setClickedListener(component -> handlePayButtonClick());
+        }
+
+        // 设置对话框内容
+        dialog.setContentCustomComponent(rootView);
+
+        // 设置对话框属性
+        dialog.setTransparent(true); // 设置透明背景
+        dialog.setSize(ComponentContainer.LayoutConfig.MATCH_PARENT,
+                ComponentContainer.LayoutConfig.MATCH_PARENT);
+        dialog.setAlignment(LayoutAlignment.CENTER);
+    }
+    
+    /**
+     * 处理支付按钮点击
+     */
+    private void handlePayButtonClick() {
+        // 检查是否是刷新模式(倒计时结束)
+        if (!isCountdownRunning && countdownSeconds <= 0) {
+            // 刷新重新计费
+            refreshParkingFee();
+        } else {
+            // 正常支付
+            if (onPayClickListener != null && feeInfo != null) {
+                stopCountdown();
+                onPayClickListener.onPayClick(feeInfo);
+            } else {
+                Toast.info(context, "暂无支付信息");
+            }
+        }
+    }
+
+    /**
+     * 设置停车费信息并更新UI
+     */
+    public void setFeeInfo(ParkingFeeInfo feeInfo) {
+        this.feeInfo = feeInfo;
+        bindData();
+    }
+
+    /**
+     * 设置支付按钮点击监听器
+     */
+    public void setOnPayClickListener(OnPayClickListener listener) {
+        this.onPayClickListener = listener;
+    }
+
+    /**
+     * 重置倒计时
+     */
+    public void resetCountdown(int minutes) {
+        stopCountdown();
+        this.countdownSeconds = minutes * 60;
+        startCountdown();
+        updatePayButton(false);
+    }
+
+    /**
+     * 绑定数据到 UI
+     */
+    private void bindData() {
+        if (feeInfo == null || rootView == null) {
+            return;
+        }
+
+        try {
+            DecimalFormat df = new DecimalFormat("0.00");
+
+            // 设置车牌号
+            setText(ResourceTable.Id_pay_detail_plate_no, feeInfo.getPlateNo());
+
+            // 设置停车场
+            setText(ResourceTable.Id_pay_detail_park_name, feeInfo.getParkName());
+
+            // 设置入场时间
+            setText(ResourceTable.Id_pay_detail_in_time, feeInfo.getInTime());
+
+            // 设置已停时长
+            setText(ResourceTable.Id_pay_detail_stay_time, feeInfo.getStayTime());
+
+            // 设置停车费(分转元)
+            double totalAmount = feeInfo.getTotalAmount() != null ? feeInfo.getTotalAmount() / 100.0 : 0.0;
+            setText(ResourceTable.Id_pay_detail_total_amount, "¥" + df.format(totalAmount));
+
+            // 设置优惠金额
+            if (feeInfo.getDiscountAmount() != null && feeInfo.getDiscountAmount() > 0) {
+                setVisibility(ResourceTable.Id_layout_discount_amount, Component.VISIBLE);
+                double discountAmount = feeInfo.getDiscountAmount() / 100.0;
+                setText(ResourceTable.Id_pay_detail_discount_amount, "¥-" + df.format(discountAmount));
+            } else {
+                setVisibility(ResourceTable.Id_layout_discount_amount, Component.HIDE);
+            }
+
+            // 设置历史欠费(feeType == 16时可能有)
+            if (feeInfo.getFollowSum() != null && feeInfo.getFollowSum() > 0) {
+                setVisibility(ResourceTable.Id_layout_follow_sum, Component.VISIBLE);
+                double followSum = feeInfo.getFollowSum() / 100.0;
+                setText(ResourceTable.Id_pay_detail_follow_sum, "¥" + df.format(followSum));
+            } else {
+                setVisibility(ResourceTable.Id_layout_follow_sum, Component.HIDE);
+            }
+
+            // 设置车位费
+            if (feeInfo.getLotAmount() != null && feeInfo.getLotAmount() > 0) {
+                setVisibility(ResourceTable.Id_layout_lot_amount, Component.VISIBLE);
+                double lotAmount = feeInfo.getLotAmount() / 100.0;
+                setText(ResourceTable.Id_pay_detail_lot_amount, "¥" + df.format(lotAmount));
+            } else {
+                setVisibility(ResourceTable.Id_layout_lot_amount, Component.HIDE);
+            }
+
+            // 计算总计金额
+            double actualAmount = calculateActualAmount();
+            setText(ResourceTable.Id_pay_detail_actual_amount, df.format(actualAmount));
+
+            // 设置提示信息
+            updateTipText();
+
+        } catch (Exception e) {
+            Log.error("绑定支付订单详情数据失败: " + e.getMessage());
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 计算实际支付金额
+     * 参考 pay.vue 中的 actualAmount computed 属性
+     */
+    private double calculateActualAmount() {
+        double total = 0;
+
+        // 实付金额
+        if (feeInfo.getActualAmount() != null) {
+            total = feeInfo.getActualAmount() / 100.0;
+        }
+
+        // 加上历史欠费(如果有)
+        if (feeInfo.getFollowSum() != null && feeInfo.getFollowSum() > 0) {
+            total += feeInfo.getFollowSum() / 100.0;
+        }
+
+        return total;
+    }
+
+    /**
+     * 更新提示文本
+     * 参考 pay.vue 的提示逻辑
+     */
+    private void updateTipText() {
+        Text tipText = (Text) rootView.findComponentById(ResourceTable.Id_pay_detail_tip);
+        if (tipText == null) {
+            return;
+        }
+
+        StringBuilder tip = new StringBuilder();
+
+        // 如果有优惠金额且有历史欠费,显示提示
+        if (feeInfo.getDiscountAmount() != null && feeInfo.getDiscountAmount() > 0 
+            && feeInfo.getFollowSum() != null && feeInfo.getFollowSum() > 0 
+            && feeInfo.getActualAmount() != null && feeInfo.getActualAmount() > 0) {
+            tip.append("说明:历史欠费不享受商户减免优惠!");
+        }
+
+        // 如果有优惠金额且有车位费,显示提示
+        if (feeInfo.getDiscountAmount() != null && feeInfo.getDiscountAmount() > 0 
+            && feeInfo.getLotAmount() != null && feeInfo.getLotAmount() > 0) {
+            if (tip.length() > 0) {
+                tip.append("\n");
+            }
+            tip.append("说明:车位费不享受商户减免优惠!");
+        }
+
+        if (tip.length() > 0) {
+            tipText.setText(tip.toString());
+            tipText.setVisibility(Component.VISIBLE);
+        } else {
+            tipText.setVisibility(Component.HIDE);
+        }
+    }
+
+    /**
+     * 设置文本内容的辅助方法
+     */
+    private void setText(int componentId, String text) {
+        Text textComponent = (Text) rootView.findComponentById(componentId);
+        if (textComponent != null) {
+            textComponent.setText(text != null && !text.isEmpty() ? text : "--");
+        }
+    }
+
+    /**
+     * 设置组件可见性的辅助方法
+     */
+    private void setVisibility(int componentId, int visibility) {
+        Component component = rootView.findComponentById(componentId);
+        if (component != null) {
+            component.setVisibility(visibility);
+        }
+    }
+    
+    /**
+     * 开始倒计时
+     */
+    private void startCountdown() {
+        if (countdownSeconds <= 0) {
+            return;
+        }
+        
+        isCountdownRunning = true;
+        updateCountdownUI();
+        
+        countdownHandler.postTask(() -> {
+            if (isCountdownRunning && countdownSeconds > 0) {
+                countdownSeconds--;
+                updateCountdownUI();
+                
+                if (countdownSeconds > 0) {
+                    startCountdown(); // 递归调用
+                } else {
+                    onCountdownFinish();
+                }
+            }
+        }, 1000);
+    }
+    
+    /**
+     * 停止倒计时
+     */
+    private void stopCountdown() {
+        isCountdownRunning = false;
+        if (countdownHandler != null) {
+            countdownHandler.removeAllEvent();
+        }
+    }
+    
+    /**
+     * 更新倒计时UI
+     */
+    private void updateCountdownUI() {
+        if (btnPay != null && countdownSeconds > 0) {
+            btnPay.setText("立即支付(" + countdownSeconds + "s)");
+        } else if (btnPay != null && countdownSeconds <= 0) {
+            btnPay.setText("立即支付");
+        }
+    }
+    
+    /**
+     * 倒计时结束
+     */
+    private void onCountdownFinish() {
+        isCountdownRunning = false;
+        updatePayButton(true);
+        Toast.info(context, "订单已经超时,请刷新");
+    }
+    
+    /**
+     * 更新支付按钮状态
+     * @param isRefreshMode 是否为刷新模式
+     */
+    private void updatePayButton(boolean isRefreshMode) {
+        if (btnPay != null) {
+            if (isRefreshMode) {
+                btnPay.setText("刷新重新计费");
+            } else {
+                btnPay.setText("立即支付");
+            }
+        }
+    }
+    
+    /**
+     * 显示对话框
+     */
+    public void show() {
+        if (dialog != null) {
+            dialog.show();
+        }
+        // 弹框显示时自动获取倒计时时间并重新计费
+        fetchOrderValidTime();
+        refreshParkingFee();
+    }
+    
+    /**
+     * 隐藏对话框
+     */
+    public void hide() {
+        // 停止倒计时
+        stopCountdown();
+        
+        // 清理事件处理器
+        if (countdownHandler != null) {
+            countdownHandler.removeAllEvent();
+            countdownHandler = null;
+        }
+        
+        // 清理数据引用
+        feeInfo = null;
+        onPayClickListener = null;
+        rootView = null;
+        btnPay = null;
+        
+        // 隐藏对话框
+        if (dialog != null) {
+            dialog.hide();
+        }
+    }
+    
+    /**
+     * 获取订单有效时间并设置倒计时
+     */
+    private void fetchOrderValidTime() {
+        CompletableFuture<R<Integer>> validTimeFuture = common.getOrderValidTime(context);
+        validTimeFuture.thenAccept(result -> {
+            DialogUtil.postTask(() -> {
+                if (result != null && result.isSuccess() && result.getData() != null && result.getData() > 0) {
+                    // 返回值为分钟数,大于0表示需要倒计时
+                    resetCountdown(result.getData());
+                }
+                // 如果返回值为0或null,则不设置倒计时
+            });
+        });
+    }
+    
+    /**
+     * 刷新停车费用信息(重新计费)
+     */
+    private void refreshParkingFee() {
+        if (feeInfo == null || feeInfo.getPlateNo() == null) {
+            Toast.error(context, "车牌号信息缺失");
+            return;
+        }
+        
+        // 构建查询参数
+        ChargeQuery query = new ChargeQuery();
+        query.setChargeScene(2);  // 计费场景: 2-临停缴费
+        query.setPlateNo(feeInfo.getPlateNo());
+        if (feeInfo.getParkId() != null) {
+            query.setParkId(feeInfo.getParkId());
+        }
+        
+        // 查询停车费用
+        CompletableFuture<R<ParkingFeeInfo>> future = common.queryParkingFee(context, query);
+        future.thenAccept(result -> {
+            DialogUtil.postTask(() -> {
+                if (result != null && result.isSuccess() && result.getData() != null) {
+                    // 更新费用信息
+                    ParkingFeeInfo newFeeInfo = result.getData();
+                    setFeeInfo(newFeeInfo);
+                    
+                    // 重新获取倒计时时间
+                    fetchOrderValidTime();
+                } else {
+                    String errorMsg = result != null ? result.getMsg() : "查询失败";
+                    Toast.error(context, "获取计费信息失败: " + errorMsg);
+                }
+            });
+        }).exceptionally(e -> {
+            DialogUtil.postTask(() -> {
+                Log.error("刷新停车费用失败: " + e.getMessage());
+                Toast.error(context, "刷新失败,请稍后重试");
+            });
+            return null;
+        });
+    }
+}
+

+ 121 - 0
entry/src/main/java/com/fujica/abk/component/PayFailDialog.java

@@ -0,0 +1,121 @@
+package com.fujica.abk.component;
+
+import com.fujica.abk.ResourceTable;
+import ohos.agp.components.*;
+import ohos.agp.utils.LayoutAlignment;
+import ohos.agp.window.dialog.CommonDialog;
+import ohos.app.Context;
+
+/**
+ * 支付失败弹窗
+ */
+public class PayFailDialog {
+    private Context context;
+    private CommonDialog dialog;
+    private Component dialogRootView;
+    private OnDismissListener dismissListener;
+    
+    // UI组件
+    private Text txtErrorMsg;
+    private Button btnConfirm;
+    
+    // 错误信息
+    private String errorMsg;
+    
+    /**
+     * 弹窗关闭监听器
+     */
+    public interface OnDismissListener {
+        void onDismiss();
+    }
+    
+    /**
+     * 构造函数
+     */
+    public PayFailDialog(Context context) {
+        this.context = context;
+        initDialog();
+    }
+    
+    /**
+     * 设置错误信息
+     */
+    public void setErrorMsg(String errorMsg) {
+        this.errorMsg = errorMsg;
+        updateErrorMsg();
+    }
+    
+    /**
+     * 设置弹窗关闭监听器
+     */
+    public void setOnDismissListener(OnDismissListener listener) {
+        this.dismissListener = listener;
+    }
+    
+    /**
+     * 初始化对话框
+     */
+    private void initDialog() {
+        // 创建 CommonDialog
+        dialog = new CommonDialog(context);
+        
+        // 加载自定义布局
+        dialogRootView = LayoutScatter.getInstance(context)
+                .parse(ResourceTable.Layout_dialog_pay_fail, null, false);
+        
+        // 获取UI组件
+        txtErrorMsg = (Text) dialogRootView.findComponentById(ResourceTable.Id_txt_error_msg);
+        btnConfirm = (Button) dialogRootView.findComponentById(ResourceTable.Id_btn_confirm);
+        
+        // 设置确认按钮点击事件
+        if (btnConfirm != null) {
+            btnConfirm.setClickedListener(component -> {
+                hide();
+                if (dismissListener != null) {
+                    dismissListener.onDismiss();
+                }
+            });
+        }
+        
+        // 设置对话框内容
+        dialog.setContentCustomComponent(dialogRootView);
+        
+        // 设置对话框属性
+        dialog.setTransparent(true); // 设置透明背景
+        dialog.setSize(ComponentContainer.LayoutConfig.MATCH_PARENT,
+                ComponentContainer.LayoutConfig.MATCH_PARENT);
+        dialog.setAlignment(LayoutAlignment.CENTER);
+    }
+    
+    /**
+     * 更新错误信息显示
+     */
+    private void updateErrorMsg() {
+        if (txtErrorMsg != null) {
+            String msg = errorMsg != null && !errorMsg.isEmpty() ? errorMsg : "支付失败,请重试";
+            txtErrorMsg.setText(msg);
+        }
+    }
+    
+    /**
+     * 显示对话框
+     */
+    public void show() {
+        if (dialog != null) {
+            dialog.show();
+        }
+    }
+    
+    /**
+     * 隐藏对话框
+     */
+    public void hide() {
+        if (dismissListener != null) {
+            dismissListener.onDismiss();
+        }
+        if (dialog != null) {
+            dialog.hide();
+        }
+    }
+}
+

+ 121 - 0
entry/src/main/java/com/fujica/abk/component/PaySuccessDialog.java

@@ -0,0 +1,121 @@
+package com.fujica.abk.component;
+
+import com.fujica.abk.ResourceTable;
+import ohos.agp.components.*;
+import ohos.agp.utils.LayoutAlignment;
+import ohos.agp.window.dialog.CommonDialog;
+import ohos.app.Context;
+
+/**
+ * 支付成功弹窗
+ */
+public class PaySuccessDialog {
+    private Context context;
+    private CommonDialog dialog;
+    private Component dialogRootView;
+    private OnDismissListener dismissListener;
+    
+    // UI组件
+    private Text txtAmount;
+    private Button btnConfirm;
+    
+    // 支付金额(分)
+    private Integer payAmount;
+    
+    /**
+     * 弹窗关闭监听器
+     */
+    public interface OnDismissListener {
+        void onDismiss();
+    }
+    
+    /**
+     * 构造函数
+     */
+    public PaySuccessDialog(Context context) {
+        this.context = context;
+        initDialog();
+    }
+    
+    /**
+     * 设置支付金额(分)
+     */
+    public void setPayAmount(Integer amount) {
+        this.payAmount = amount;
+        updateAmount();
+    }
+    
+    /**
+     * 设置弹窗关闭监听器
+     */
+    public void setOnDismissListener(OnDismissListener listener) {
+        this.dismissListener = listener;
+    }
+    
+    /**
+     * 初始化对话框
+     */
+    private void initDialog() {
+        // 创建 CommonDialog
+        dialog = new CommonDialog(context);
+        
+        // 加载自定义布局
+        dialogRootView = LayoutScatter.getInstance(context)
+                .parse(ResourceTable.Layout_dialog_pay_success, null, false);
+        
+        // 获取UI组件
+        txtAmount = (Text) dialogRootView.findComponentById(ResourceTable.Id_txt_pay_amount);
+        btnConfirm = (Button) dialogRootView.findComponentById(ResourceTable.Id_btn_confirm);
+        
+        // 设置确认按钮点击事件
+        if (btnConfirm != null) {
+            btnConfirm.setClickedListener(component -> {
+                hide();
+                if (dismissListener != null) {
+                    dismissListener.onDismiss();
+                }
+            });
+        }
+        
+        // 设置对话框内容
+        dialog.setContentCustomComponent(dialogRootView);
+        
+        // 设置对话框属性
+        dialog.setTransparent(true); // 设置透明背景
+        dialog.setSize(ComponentContainer.LayoutConfig.MATCH_PARENT,
+                ComponentContainer.LayoutConfig.MATCH_PARENT);
+        dialog.setAlignment(LayoutAlignment.CENTER);
+    }
+    
+    /**
+     * 更新金额显示
+     */
+    private void updateAmount() {
+        if (txtAmount != null && payAmount != null) {
+            double amount = payAmount / 100.0;
+            txtAmount.setText(String.format("%.2f", amount));
+        }
+    }
+    
+    /**
+     * 显示对话框
+     */
+    public void show() {
+        if (dialog != null) {
+            dialog.show();
+        }
+    }
+    
+    /**
+     * 隐藏对话框
+     */
+    public void hide() {
+        if (dismissListener != null) {
+            dismissListener.onDismiss();
+        }
+        if (dialog != null) {
+            dialog.hide();
+        }
+    }
+}
+

+ 555 - 0
entry/src/main/java/com/fujica/abk/component/QRCodeScanDialog.java

@@ -0,0 +1,555 @@
+package com.fujica.abk.component;
+
+import com.fujica.abk.ResourceTable;
+import com.fujica.abk.api.pay;
+import com.fujica.abk.model.in.PayRequest;
+import com.fujica.abk.model.out.PayResponse;
+import com.fujica.abk.model.out.ParkingFeeInfo;
+import com.fujica.abk.model.out.PayStatusResponse;
+import com.fujica.abk.utils.*;
+import ohos.agp.components.*;
+import ohos.agp.utils.LayoutAlignment;
+import ohos.agp.window.dialog.CommonDialog;
+import ohos.app.Context;
+import ohos.eventhandler.EventHandler;
+import ohos.eventhandler.EventRunner;
+import ohos.media.image.PixelMap;
+
+import java.util.concurrent.CompletableFuture;
+
+/**
+ * 微信扫码支付弹框
+ * 使用 CommonDialog 实现
+ */
+public class QRCodeScanDialog {
+    private Context context;
+    private CommonDialog dialog;
+    private Component dialogRootView;
+    private ParkingFeeInfo feeInfo;
+    private OnPayResultListener payResultListener;
+    private OnCloseListener closeListener;
+    private String paySceneCode = "ALI_PCRE"; // 默认支付宝扫码支付
+    
+    // UI组件
+    private Image imgQRCode;
+    private Text txtTitle;
+    private Text txtLoading;
+    private Button btnCancelPay;
+    
+    // 倒计时相关
+    private static final int COUNTDOWN_SECONDS = 180; // 3分钟 = 180秒
+    private int remainingSeconds = COUNTDOWN_SECONDS;
+    private EventHandler countdownHandler;
+    private boolean isCountdownRunning = false;
+    
+    // 支付查询相关
+    private String payNo;
+    private boolean isPollingPayStatus = false;
+    private static final int POLL_INTERVAL = 3000; // 轮询间隔3秒
+    private boolean isClosedByPayResult = false; // 是否由支付结果关闭的
+    
+    /**
+     * 支付结果回调接口
+     */
+    public interface OnPayResultListener {
+        void onPaySuccess(String payNo);
+        void onPayFailed(String errorMsg);
+        void onPayTimeout();
+    }
+    
+    /**
+     * 弹框关闭回调接口
+     * 用于在弹框关闭时触发ChargeComponent的刷新
+     */
+    public interface OnCloseListener {
+        void onClose();
+    }
+    
+    /**
+     * 构造函数
+     */
+    public QRCodeScanDialog(Context context) {
+        this.context = context;
+        initDialog();
+    }
+    
+    /**
+     * 设置费用信息
+     */
+    public void setFeeInfo(ParkingFeeInfo feeInfo) {
+        this.feeInfo = feeInfo;
+    }
+    
+    /**
+     * 设置支付结果监听器
+     */
+    public void setOnPayResultListener(OnPayResultListener listener) {
+        this.payResultListener = listener;
+    }
+    
+    /**
+     * 设置弹框关闭监听器
+     */
+    public void setOnCloseListener(OnCloseListener listener) {
+        this.closeListener = listener;
+    }
+    
+    /**
+     * 设置支付场景代码
+     * @param paySceneCode 支付场景代码(如:WX_NA-微信Native支付,ALI_PCRE-支付宝扫码支付)
+     */
+    public void setPaySceneCode(String paySceneCode) {
+        this.paySceneCode = paySceneCode;
+    }
+    
+    /**
+     * 初始化对话框
+     */
+    private void initDialog() {
+        // 创建 CommonDialog
+        dialog = new CommonDialog(context);
+        
+        // 加载自定义布局
+        dialogRootView = LayoutScatter.getInstance(context)
+                .parse(ResourceTable.Layout_layout_qrcode_scan_dialog, null, false);
+        
+        // 获取UI组件
+        imgQRCode = (Image) dialogRootView.findComponentById(ResourceTable.Id_img_qrcode);
+        txtTitle = (Text) dialogRootView.findComponentById(ResourceTable.Id_txt_title);
+        txtLoading = (Text) dialogRootView.findComponentById(ResourceTable.Id_txt_loading);
+        btnCancelPay = (Button) dialogRootView.findComponentById(ResourceTable.Id_btn_cancel_pay);
+        
+        // 设置关闭按钮点击事件
+        Image btnClose = (Image) dialogRootView.findComponentById(ResourceTable.Id_btn_close_scan);
+        if (btnClose != null) {
+            btnClose.setClickedListener(component -> {
+                stopCountdown();
+                hide();
+            });
+        }
+        
+        // 设置取消支付按钮点击事件
+        if (btnCancelPay != null) {
+            btnCancelPay.setClickedListener(component -> {
+                stopCountdown();
+                hide();
+            });
+        }
+        
+        // 设置对话框内容
+        dialog.setContentCustomComponent(dialogRootView);
+        
+        // 设置对话框属性
+        dialog.setTransparent(true); // 设置透明背景
+        dialog.setSize(ComponentContainer.LayoutConfig.MATCH_PARENT,
+                ComponentContainer.LayoutConfig.MATCH_PARENT);
+        dialog.setAlignment(LayoutAlignment.CENTER);
+        
+        // 初始化倒计时Handler
+        countdownHandler = new EventHandler(EventRunner.getMainEventRunner());
+    }
+    
+    /**
+     * 调用支付接口生成订单和二维码
+     */
+    private void createPayOrder() {
+        if (feeInfo == null) {
+            showError("支付信息缺失");
+            return;
+        }
+        
+        // 显示加载提示
+        showLoading(true);
+        
+        // 构建支付请求参数
+        PayRequest request = new PayRequest();
+        request.setActualAmount(feeInfo.getActualAmount() != null ? feeInfo.getActualAmount() : 1);
+        request.setBizType(1); // 1-临停
+        request.setDiscountAmount(feeInfo.getDiscountAmount() != null ? feeInfo.getDiscountAmount() : 0);
+        request.setDoubleConfirm(true);
+        request.setGoodsName(feeInfo.getPlateNo() != null ? feeInfo.getPlateNo() : "停车费");
+        request.setOrderId(feeInfo.getOrderId());
+        request.setParkId(feeInfo.getParkId());
+        request.setParkName(feeInfo.getParkName());
+        request.setPaySceneCode(paySceneCode); // 使用设置的支付场景代码
+        request.setPaySourceCode("HW_CAR"); // 华为车机
+        request.setProjectNo(feeInfo.getProjectNo()); // 项目编号
+        request.setTotalAmount(feeInfo.getTotalAmount() != null ? feeInfo.getTotalAmount() : 1);
+        
+        Log.info("发起支付请求: orderId=" + request.getOrderId());
+        
+        // 调用支付接口
+        CompletableFuture<R<PayResponse>> future = pay.payByUnify(context, request);
+        future.thenAccept(result -> {
+            context.getUITaskDispatcher().asyncDispatch(() -> {
+                showLoading(false);
+                
+                if (result != null && result.isSuccess() && result.getData() != null) {
+                    PayResponse payData = result.getData();
+                    String qrCode = payData.getQrCode();
+                    payNo = payData.getOutTradeNo();
+                    
+                    if (qrCode != null && !qrCode.isEmpty()) {
+                        // 生成并显示二维码
+                        displayQRCode(qrCode);
+                        
+                        // 开始倒计时
+                        startCountdown();
+                        
+                        // 开始轮询支付状态
+                        startPaymentPolling();
+                    } else {
+                        showError("未获取到支付二维码");
+                    }
+                } else {
+                    String errorMsg = result != null && result.getMsg() != null ? 
+                            result.getMsg() : "生成支付订单失败";
+                    showError(errorMsg);
+                }
+            });
+        }).exceptionally(e -> {
+            context.getUITaskDispatcher().asyncDispatch(() -> {
+                showLoading(false);
+                Log.error("支付接口调用失败: " + e.getMessage());
+                showError("网络请求失败,请稍后重试");
+            });
+            return null;
+        });
+    }
+    
+    /**
+     * 显示二维码
+     */
+    private void displayQRCode(String qrCodeContent) {
+        try {
+            // 生成二维码图片
+            int qrCodeSize = 800; // 二维码像素大小
+            PixelMap qrCodePixelMap = QRCodeUtil.generateQRCode(qrCodeContent, qrCodeSize);
+            
+            if (qrCodePixelMap != null && imgQRCode != null) {
+                imgQRCode.setPixelMap(qrCodePixelMap);
+                Log.info("二维码生成成功");
+            } else {
+                Log.error("二维码生成失败");
+                showError("二维码生成失败");
+            }
+        } catch (Exception e) {
+            Log.error("显示二维码失败: " + e.getMessage());
+            e.printStackTrace();
+            showError("二维码显示失败");
+        }
+    }
+    
+    /**
+     * 开始倒计时
+     */
+    private void startCountdown() {
+        if (isCountdownRunning) {
+            return;
+        }
+        
+        isCountdownRunning = true;
+        remainingSeconds = COUNTDOWN_SECONDS;
+        updateCountdownText();
+        
+        // 使用Handler进行倒计时
+        countdownRunnable.run();
+    }
+    
+    /**
+     * 停止倒计时
+     */
+    private void stopCountdown() {
+        isCountdownRunning = false;
+        if (countdownHandler != null) {
+            countdownHandler.removeTask(countdownRunnable);
+        }
+    }
+    
+    /**
+     * 倒计时Runnable
+     */
+    private final Runnable countdownRunnable = new Runnable() {
+        @Override
+        public void run() {
+            if (!isCountdownRunning) {
+                return;
+            }
+            
+            remainingSeconds--;
+            updateCountdownText();
+            
+            if (remainingSeconds <= 0) {
+                // 倒计时结束
+                onCountdownFinished();
+            } else {
+                // 继续倒计时
+                countdownHandler.postTask(this, 1000); // 1秒后再次执行
+            }
+        }
+    };
+    
+    /**
+     * 更新倒计时文本
+     */
+    private void updateCountdownText() {
+        // 更新标题中的倒计时
+        if (txtTitle != null) {
+            // 根据支付场景代码显示不同的提示文本
+            String payTypeText = "微信";
+            if (paySceneCode != null && paySceneCode.startsWith("ALI")) {
+                payTypeText = "支付宝";
+            }
+            String titleText = String.format("%s扫码支付(%d秒)", payTypeText, remainingSeconds);
+            txtTitle.setText(titleText);
+        }
+    }
+    
+    /**
+     * 倒计时结束处理
+     */
+    private void onCountdownFinished() {
+        stopCountdown();
+        stopPaymentPolling();
+        
+        // 标记为由支付结果关闭
+        isClosedByPayResult = true;
+        hide();
+        
+        // 回调支付超时
+        if (payResultListener != null) {
+            payResultListener.onPayTimeout();
+        }
+        
+        // 显示支付失败弹窗(超时)
+        PayFailDialog failDialog = new PayFailDialog(context);
+        failDialog.setErrorMsg("支付超时,请重新支付");
+        failDialog.setOnDismissListener(() -> {
+            // 支付失败弹窗关闭后,触发刷新回调
+            if (closeListener != null) {
+                closeListener.onClose();
+            }
+        });
+        
+        // 显示失败对话框
+        failDialog.show();
+    }
+    
+    /**
+     * 开始轮询支付状态
+     */
+    private void startPaymentPolling() {
+        if (payNo == null || payNo.isEmpty()) {
+            Log.error("payNo为空,无法轮询支付状态");
+            return;
+        }
+        
+        isPollingPayStatus = true;
+        
+        // 创建轮询任务
+        new Thread(() -> {
+            while (isPollingPayStatus && remainingSeconds > 0) {
+                try {
+                    Thread.sleep(POLL_INTERVAL);
+                    
+                    // 查询支付状态
+                    checkPaymentStatus();
+                    
+                } catch (InterruptedException e) {
+                    Log.error("支付状态查询线程中断: " + e.getMessage());
+                    break;
+                }
+            }
+        }).start();
+    }
+    
+    /**
+     * 停止轮询支付状态
+     */
+    private void stopPaymentPolling() {
+        isPollingPayStatus = false;
+    }
+    
+    /**
+     * 查询支付状态
+     */
+    private void checkPaymentStatus() {
+        if (payNo == null || payNo.isEmpty()) {
+            return;
+        }
+        
+        CompletableFuture<R<PayStatusResponse>> future = pay.queryPayStatus(context, payNo);
+        future.thenAccept(result -> {
+            // 检查是否应该继续处理响应:
+            // 1. 轮询必须还在进行中
+            // 2. 倒计时必须还在运行
+            // 3. 对话框必须还在显示
+            if (!isPollingPayStatus || !isCountdownRunning || dialog == null || !dialog.isShowing()) {
+                Log.info("支付状态查询响应被忽略:对话框已关闭或轮询已停止");
+                return;
+            }
+            
+            if (result != null && result.isSuccess() && result.getData() != null) {
+                Integer status = result.getData().getPayStatus();
+
+                //0-未支付(默认),1-支付中,2-支付成功,3-支付关闭,4-支付退款
+                if (status == 2) {
+                    // 支付成功
+                    onPaymentSuccess();
+                }
+//                else if (status == -1) {
+//                    // 支付失败
+//                    context.getUITaskDispatcher().asyncDispatch(() -> {
+//                        onPaymentFailed("支付失败");
+//                    });
+//                }
+                // status == 0 表示支付中,继续轮询
+            }
+        }).exceptionally(e -> {
+            // 异常情况下也检查是否应该记录日志
+            if (isPollingPayStatus && isCountdownRunning) {
+                Log.error("查询支付状态失败: " + e.getMessage());
+            }
+            return null;
+        });
+    }
+    
+    /**
+     * 支付成功处理
+     */
+    private void onPaymentSuccess() {
+        context.getUITaskDispatcher().asyncDispatch(() -> {
+            stopCountdown();
+            stopPaymentPolling();
+            
+            // 标记为由支付结果关闭
+            isClosedByPayResult = true;
+            hide();
+            
+            // 显示支付成功弹窗
+            PaySuccessDialog successDialog = new PaySuccessDialog(context);
+            successDialog.setPayAmount(feeInfo != null ? feeInfo.getActualAmount() : 0);
+            successDialog.setOnDismissListener(() -> {
+                // 支付成功弹窗关闭后,触发刷新回调
+                if (closeListener != null) {
+                    closeListener.onClose();
+                }
+            });
+            
+            // 显示成功对话框
+            successDialog.show();
+            
+            // 回调支付成功
+            if (payResultListener != null) {
+                payResultListener.onPaySuccess(payNo);
+            }
+        });
+    }
+    
+    /**
+     * 支付失败处理
+     */
+    private void onPaymentFailed(String errorMsg) {
+        stopCountdown();
+        stopPaymentPolling();
+        
+        // 标记为由支付结果关闭
+        isClosedByPayResult = true;
+        hide();
+        
+        // 显示支付失败弹窗
+        PayFailDialog failDialog = new PayFailDialog(context);
+        failDialog.setErrorMsg(errorMsg);
+        failDialog.setOnDismissListener(() -> {
+            // 支付失败弹窗关闭后,触发刷新回调
+            if (closeListener != null) {
+                closeListener.onClose();
+            }
+        });
+        
+        // 显示失败对话框
+        failDialog.show();
+        
+        // 回调支付失败
+        if (payResultListener != null) {
+            payResultListener.onPayFailed(errorMsg);
+        }
+    }
+    
+    /**
+     * 显示/隐藏加载提示
+     */
+    private void showLoading(boolean show) {
+        if (txtLoading != null) {
+            txtLoading.setVisibility(show ? Component.VISIBLE : Component.HIDE);
+        }
+        if (imgQRCode != null) {
+            imgQRCode.setVisibility(show ? Component.HIDE : Component.VISIBLE);
+        }
+        if (btnCancelPay != null) {
+            btnCancelPay.setVisibility(show ? Component.HIDE : Component.VISIBLE);
+        }
+    }
+    
+    /**
+     * 显示错误信息
+     */
+    private void showError(String errorMsg) {
+        Toast.error(context, errorMsg);
+        hide();
+        
+        // 回调支付失败
+        if (payResultListener != null) {
+            payResultListener.onPayFailed(errorMsg);
+        }
+    }
+    
+    /**
+     * 显示对话框
+     */
+    public void show() {
+        if (dialog != null) {
+            dialog.show();
+        }
+        // 弹框显示时自动调用支付接口
+        createPayOrder();
+    }
+    
+    /**
+     * 隐藏对话框
+     */
+    public void hide() {
+        stopCountdown();
+        stopPaymentPolling();
+        
+        // 只有在手动关闭(非支付结果关闭)时,才触发刷新回调
+        // 支付结果关闭时,会在支付成功/失败弹窗关闭后才触发回调
+        if (!isClosedByPayResult && closeListener != null) {
+            closeListener.onClose();
+        }
+        
+        // 重置标志
+        isClosedByPayResult = false;
+        
+        // 隐藏对话框
+        if (dialog != null) {
+            dialog.hide();
+        }
+    }
+    
+    /**
+     * 销毁对话框,释放资源
+     */
+    public void destroy() {
+        stopCountdown();
+        stopPaymentPolling();
+        payResultListener = null;
+        closeListener = null;
+        
+        // 释放二维码图片资源
+        if (imgQRCode != null && imgQRCode.getPixelMap() != null) {
+            imgQRCode.getPixelMap().release();
+        }
+    }
+}
+

+ 42 - 4
entry/src/main/java/com/fujica/abk/component/nav/ChargeComponent.java

@@ -1,6 +1,7 @@
 package com.fujica.abk.component.nav;
 
 import com.fujica.abk.ResourceTable;
+import com.fujica.abk.api.cache;
 import com.fujica.abk.api.common;
 import com.fujica.abk.component.LoadingComponent;
 import com.fujica.abk.model.in.ChargeQuery;
@@ -69,6 +70,15 @@ public class ChargeComponent extends DirectionalLayout {
     private ParkingFeeInfo currentFeeInfo;
 
     private LoadingComponent loadingComponent; // Loading组件
+    
+    private OnPayDetailShowListener onPayDetailShowListener; // 支付详情展示监听器
+
+    /**
+     * 支付详情展示监听器
+     */
+    public interface OnPayDetailShowListener {
+        void onShowPayDetail(ParkingFeeInfo feeInfo);
+    }
 
     /**
      * 设置Loading组件
@@ -77,6 +87,13 @@ public class ChargeComponent extends DirectionalLayout {
         this.loadingComponent = loadingComponent;
     }
 
+    /**
+     * 设置支付详情展示监听器
+     */
+    public void setOnPayDetailShowListener(OnPayDetailShowListener listener) {
+        this.onPayDetailShowListener = listener;
+    }
+
     /**
      * 构造函数
      */
@@ -169,9 +186,29 @@ public class ChargeComponent extends DirectionalLayout {
         // 立即缴费按钮点击事件
         if (btnPayNow != null) {
             btnPayNow.setClickedListener(component -> {
+//                if(true){
+//                    Runnable payRunnable = new Runnable() {
+//                        @Override
+//                        public void run() {
+//                            com.huawei.hms.a
+//                            AggrPayClient client = Pay.getPayClient(this);
+//                            PayResult payResult = client.carPay(orderStr);
+//                            mHandler.post(() -> dealPayResult(payResult));
+//                        }
+//                    };
+//                    Thread payThread = new Thread(payRunnable);
+//                    payThread.start();
+//                    return;
+//                }
+
+
                 if (currentFeeInfo != null) {
-                    // TODO: 跳转到支付页面
-                    Toast.info(context, "跳转到支付页面");
+                    // 展示支付详情
+                    if (onPayDetailShowListener != null) {
+                        onPayDetailShowListener.onShowPayDetail(currentFeeInfo);
+                    } else {
+                        Toast.info(context, "请稍后重试");
+                    }
                 }
             });
         }
@@ -232,6 +269,7 @@ public class ChargeComponent extends DirectionalLayout {
                     MemberPlateH5Dto plateData = result.getData();
                     if (plateData.getPlateNo() != null && !plateData.getPlateNo().isEmpty()) {
                         plateNo = plateData.getPlateNo();
+                        cache.setDefaultPlateNo(getContext(), plateNo);
                     }
                 }
                 if(plateNo == null || plateNo.isEmpty()){
@@ -303,9 +341,9 @@ public class ChargeComponent extends DirectionalLayout {
         // 更新顶部车牌显示
         filterPlateNo.setVisibility(VISIBLE);
         textPlateNo.setText(licensePlate);
-
+        this.plateNo = licensePlate;
         // 查询计费
-        queryParkingFee(licensePlate);
+        queryParkingFee(this.plateNo);
     }
 
     /**

+ 139 - 41
entry/src/main/java/com/fujica/abk/component/nav/ParkComponent.java

@@ -1,6 +1,8 @@
 package com.fujica.abk.component.nav;
 
 import com.fujica.abk.ResourceTable;
+import com.fujica.abk.api.cache;
+import com.fujica.abk.common.EventBus;
 import com.fujica.abk.component.LoadingComponent;
 import com.fujica.abk.component.ParkItemComponent;
 import com.fujica.abk.model.out.ParkNearRes;
@@ -10,10 +12,14 @@ import com.google.gson.Gson;
 import com.google.gson.reflect.TypeToken;
 import ohos.agp.components.*;
 import com.fujica.abk.utils.CustomListDialog;
+import ohos.agp.window.dialog.ToastDialog;
 import ohos.app.Context;
 import ohos.eventhandler.EventHandler;
 import ohos.eventhandler.EventRunner;
 import ohos.location.Location;
+import ohos.location.Locator;
+import ohos.location.LocatorCallback;
+import ohos.location.RequestParam;
 
 import java.lang.reflect.Type;
 import java.net.URLEncoder;
@@ -45,6 +51,8 @@ public class ParkComponent extends DirectionalLayout {
     private boolean hasMore = true; // 是否还有更多数据
     private long lastLoadTime = 0; // 上次加载时间,用于防抖
     private static final long LOAD_THROTTLE_MS = 500; // 防抖时间间隔(毫秒)
+    private long lastLocationRequestTime = 0; // 上次定位请求时间
+    private static final long LOCATION_REQUEST_INTERVAL = 5000; // 定位请求最小间隔(5秒)
 
     // 数据
     private List<ParkNearRes> parkingList = new ArrayList<>(); // 停车场列表数据
@@ -53,15 +61,18 @@ public class ParkComponent extends DirectionalLayout {
 
     // 外部依赖
     private Context context;
-    private Location currentLocation; // 当前定位坐标
     private LoadingComponent loadingComponent; // Loading组件
     private OnParkSelectedListener onParkSelectedListener; // 停车场选中监听器
 
+    // 定位权限授予事件监听器
+    private EventBus.EventListener locationPermissionGrantedListener;
+
     /**
      * 停车场选中监听器
      */
     public interface OnParkSelectedListener {
         void onParkSelected(ParkNearRes park);
+
         void onParkDeselected();
     }
 
@@ -94,8 +105,8 @@ public class ParkComponent extends DirectionalLayout {
         // 设置事件监听
         setupListeners();
 
-        // 默认选中全部车场
-        switchTab(2);
+        // 订阅定位权限授予事件
+        subscribeLocationPermissionGrantedEvent();
     }
 
     /**
@@ -127,17 +138,19 @@ public class ParkComponent extends DirectionalLayout {
         if (inputParkName != null) {
             // 创建用于防抖的Handler
             searchHandler = new EventHandler(EventRunner.getMainEventRunner());
-            
+
             inputParkName.addTextObserver(new Text.TextObserver() {
                 @Override
                 public void onTextUpdated(String s, int i, int i1, int i2) {
                     // 移除之前的搜索任务
                     searchHandler.removeAllEvent();
-                    
+
                     // 延迟执行查询,实现防抖效果
                     searchHandler.postTask(() -> {
                         // 重新加载数据
                         switchTab(filterType);
+                        // 加载数据
+                        loadParkingData(true);
                     }, LOAD_THROTTLE_MS);
                 }
             });
@@ -201,7 +214,7 @@ public class ParkComponent extends DirectionalLayout {
     /**
      * 切换标签页
      */
-    private void switchTab(int filter) {
+    public void switchTab(int filter) {
         filterType = filter;
         currentPage = 1;
         hasMore = true;
@@ -212,9 +225,6 @@ public class ParkComponent extends DirectionalLayout {
         }
         // 清除选中状态
         selectedParkingItem = null;
-
-        // 加载数据
-        loadParkingData(true);
     }
 
     /**
@@ -223,7 +233,7 @@ public class ParkComponent extends DirectionalLayout {
     private void showDistanceFilterDialog() {
         String[] options = {"500m", "1km", "3km"};
         int[] values = {500, 1000, 3000};
-        
+
         // 找到当前选中的索引
         int currentIndex = -1;
         for (int i = 0; i < values.length; i++) {
@@ -232,7 +242,7 @@ public class ParkComponent extends DirectionalLayout {
                 break;
             }
         }
-        
+
         CustomListDialog listDialog = DialogUtil.createListDialog(context, options, (iDialog, index) -> {
             selectedDistance = values[index];
             if (btnDistanceFilter != null && btnDistanceFilter.getChildCount() > 0) {
@@ -243,14 +253,15 @@ public class ParkComponent extends DirectionalLayout {
             }
             // 重新加载数据
             switchTab(filterType);
+            loadParkingData(true);
             iDialog.destroy();
         });
-        
+
         // 设置当前选中项
         if (currentIndex >= 0) {
             listDialog.setSelectedIndex(currentIndex);
         }
-        
+
         listDialog.show();
     }
 
@@ -260,7 +271,7 @@ public class ParkComponent extends DirectionalLayout {
     private void showSortFilterDialog() {
         String[] options = {"车位最多", "距离最近", "免费时长最长"};
         int[] values = {1, 2, 3};
-        
+
         // 找到当前选中的索引
         int currentIndex = -1;
         for (int i = 0; i < values.length; i++) {
@@ -269,7 +280,7 @@ public class ParkComponent extends DirectionalLayout {
                 break;
             }
         }
-        
+
         CustomListDialog listDialog = DialogUtil.createListDialog(context, options, (iDialog, index) -> {
             selectedFilter = values[index];
             if (btnDistanceSort != null && btnDistanceSort.getChildCount() > 0) {
@@ -280,21 +291,89 @@ public class ParkComponent extends DirectionalLayout {
             }
             // 重新加载数据
             switchTab(filterType);
+            loadParkingData(true);
             iDialog.destroy();
         });
-        
+
         // 设置当前选中项
         if (currentIndex >= 0) {
             listDialog.setSelectedIndex(currentIndex);
         }
-        
+
         listDialog.show();
     }
 
+    public void loadParkingDataByLocation() {
+        
+        if(isLoading) return;
+        
+        // 检查距离上次定位请求的时间间隔
+        long currentTime = System.currentTimeMillis();
+        if (currentTime - lastLocationRequestTime < LOCATION_REQUEST_INTERVAL) {
+            Toast.info(getContext(), "请稍后再试");
+            return;
+        }
+        lastLocationRequestTime = currentTime;
+        
+        DialogUtil.postTask(()->{
+            try {
+                Locator locator = new Locator(getContext());
+                if(!locator.isLocationSwitchOn()) {
+                    switchTab(filterType);
+                    loadParkingData(true);
+                    Toast.error(getContext(), "未开启定位");
+                    return;
+                }
+                // 请求定位
+                RequestParam requestParam = new RequestParam(RequestParam.PRIORITY_ACCURACY, 0, 0);
+                locator.requestOnce(requestParam, new LocatorCallback() {
+                    @Override
+                    public void onLocationReport(Location location) {
+                        Log.info("onLocationReport: ");
+                        // 保存当前位置坐标
+                        double latitude = location.getLatitude();
+                        double longitude = location.getLongitude();
+                        if (latitude == 0 && longitude == 0) {
+                            Toast.error(getContext(), "无法获取到您附近车场");
+                        } else {
+                            // 保存位置到缓存
+                            cache.setLocation(context, latitude, longitude);
+                            Log.info("位置已保存到缓存: 纬度=" + latitude + ", 经度=" + longitude);
+                        }
+                        DialogUtil.postTask(() -> {
+                            switchTab(filterType);
+                            loadParkingData(true);
+                        });
+                    }
+
+                    @Override
+                    public void onStatusChanged(int type) {
+                        Log.info("定位状态变化: " + type);
+                    }
+
+                    @Override
+                    public void onErrorReport(int errorCode) {
+                        Log.info("onErrorReport: " + errorCode);
+                        DialogUtil.postTask(() -> {
+                            Toast.error(getContext(), "获取定位失败:" + errorCode);
+                            switchTab(filterType);
+                            loadParkingData(true);
+                        });
+                    }
+                });
+            } catch (Exception e) {
+                switchTab(filterType);
+                loadParkingData(true);
+                Log.error("初始化定位服务失败: " + e.getMessage());
+            }
+        });
+
+    }
+
     /**
      * 加载停车场数据
      */
-    private void loadParkingData(boolean isRefresh) {
+    public void loadParkingData(boolean isRefresh) {
         if (isLoading) {
             return;
         }
@@ -318,12 +397,8 @@ public class ParkComponent extends DirectionalLayout {
         isLoading = true;
 
         // 获取定位坐标
-        double latitude = 0;
-        double longitude = 0;
-        if (currentLocation != null) {
-            latitude = currentLocation.getLatitude();
-            longitude = currentLocation.getLongitude();
-        }
+        double latitude = cache.getLocationLatitude(getContext());
+        double longitude = cache.getLocationLongitude(getContext());
 
         // 获取车场名称输入框的值
         String parkName = "";
@@ -345,7 +420,8 @@ public class ParkComponent extends DirectionalLayout {
         option.setMethod(ApiOption.GET);
 
         // 发送请求(网络请求已在后台线程)
-        CompletableFuture<R<Page<ParkNearRes>>> future = api.http(context, option, new TypeToken<R<Page<ParkNearRes>>>(){});
+        CompletableFuture<R<Page<ParkNearRes>>> future = api.http(context, option, new TypeToken<R<Page<ParkNearRes>>>() {
+        });
         if (loadingComponent != null) {
             loadingComponent.show();
         }
@@ -363,7 +439,8 @@ public class ParkComponent extends DirectionalLayout {
                 Page<ParkNearRes> page = null;
                 if (dataObj != null) {
                     Gson gson = new Gson();
-                    Type pageType = new TypeToken<Page<ParkNearRes>>(){}.getType();
+                    Type pageType = new TypeToken<Page<ParkNearRes>>() {
+                    }.getType();
                     String dataJson = gson.toJson(dataObj);
                     page = gson.fromJson(dataJson, pageType);
                 }
@@ -465,7 +542,7 @@ public class ParkComponent extends DirectionalLayout {
         try {
             // 使用 ParkingItemComponent 组件
             ParkItemComponent item = new ParkItemComponent(context, park);
-            
+
             // 设置选中监听器,实现全局选中状态管理
             item.setOnItemSelectedListener(new ParkItemComponent.OnItemSelectedListener() {
                 @Override
@@ -504,14 +581,19 @@ public class ParkComponent extends DirectionalLayout {
         }
     }
 
-    /**
-     * 设置当前定位坐标
-     */
-    public void setCurrentLocation(Location location) {
-        this.currentLocation = location;
-        // 如果已有定位,重新加载数据
-        if (location != null) {
-            loadParkingData(true);
+
+    // 定位相关
+    private Locator locator;
+    private LocatorCallback locatorCallback;
+
+    public void stopLocation() {
+        // 停止定位
+        if (locator != null && locatorCallback != null) {
+            try {
+                locator.stopLocating(locatorCallback);
+            } catch (Exception e) {
+                Log.error("停止定位失败: " + e.getMessage());
+            }
         }
     }
 
@@ -523,17 +605,33 @@ public class ParkComponent extends DirectionalLayout {
     }
 
     /**
-     * 刷新数据
+     * 设置停车场选中监听器
+     */
+    public void setOnParkSelectedListener(OnParkSelectedListener listener) {
+        this.onParkSelectedListener = listener;
+    }
+
+    /**
+     * 订阅定位权限授予事件
      */
-    public void refresh() {
-        loadParkingData(true);
+    private void subscribeLocationPermissionGrantedEvent() {
+        locationPermissionGrantedListener = event -> {
+            // 在主线程更新UI并执行定位
+            Log.info("收到定位权限授予事件,刷新找车位页面");
+            // 刷新数据
+            loadParkingDataByLocation();
+        };
+        EventBus.getInstance().on("onLocationPermissionGranted", locationPermissionGrantedListener);
     }
 
     /**
-     * 设置停车场选中监听器
+     * 取消订阅事件(组件销毁时调用)
      */
-    public void setOnParkSelectedListener(OnParkSelectedListener listener) {
-        this.onParkSelectedListener = listener;
+    public void unsubscribeEvents() {
+        // 取消订阅定位权限授予事件
+        if (locationPermissionGrantedListener != null) {
+            EventBus.getInstance().off("onLocationPermissionGranted", locationPermissionGrantedListener);
+        }
     }
 }
 

+ 282 - 0
entry/src/main/java/com/fujica/abk/manager/CardTriggerManager.java

@@ -0,0 +1,282 @@
+package com.fujica.abk.manager;
+
+import com.fujica.abk.api.cache;
+import com.fujica.abk.api.common;
+import com.fujica.abk.model.in.ChargeQuery;
+import com.fujica.abk.model.out.Page;
+import com.fujica.abk.model.out.ParkNearRes;
+import com.fujica.abk.model.out.ParkingFeeInfo;
+import com.fujica.abk.utils.ApiOption;
+import com.fujica.abk.utils.Log;
+import com.fujica.abk.utils.R;
+import com.fujica.abk.utils.api;
+import com.google.gson.reflect.TypeToken;
+import ohos.aafwk.ability.DataAbilityHelper;
+import ohos.agp.components.webengine.WebView;
+import ohos.app.Context;
+import ohos.sysappcomponents.settings.SystemSettings;
+
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.CompletableFuture;
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+
+/**
+ * 加载状态管理器
+ * 用于管理应用中的加载状态,提供线程安全的状态访问和修改
+ */
+public class CardTriggerManager {
+
+    private static volatile CardTriggerManager instance;
+    private volatile boolean loading;
+
+    // 车牌计费缓存相关字段
+    private String cachedPlateNo; // 缓存的车牌号
+    private ParkingFeeInfo cachedFeeInfo; // 缓存的计费信息
+    private long cacheTimestamp; // 缓存时间戳
+//    private boolean lastQueryHasFee; // 上次查询是否有费用
+
+    /**
+     * 私有构造函数,防止外部实例化
+     */
+    private CardTriggerManager() {
+        this.loading = false;
+    }
+
+    /**
+     * 获取单例实例(双重检查锁定)
+     *
+     * @return LoadingStateManager实例
+     */
+    public static CardTriggerManager getInstance() {
+        if (instance == null) {
+            synchronized (CardTriggerManager.class) {
+                if (instance == null) {
+                    instance = new CardTriggerManager();
+                }
+            }
+        }
+        return instance;
+    }
+
+    /**
+     * 检查是否正在加载
+     *
+     * @return true表示正在加载,false表示未加载
+     */
+    public boolean isLoading() {
+        return loading;
+    }
+
+    /**
+     * 设置加载状态
+     *
+     * @param loading 加载状态
+     */
+    public void setLoading(boolean loading) {
+        this.loading = loading;
+    }
+
+    /**
+     * 尝试开始加载
+     *
+     * @return true表示成功开始加载,false表示已经在加载中
+     */
+    public synchronized boolean tryStartLoading() {
+        if (loading) {
+            return false;
+        }
+        loading = true;
+        return true;
+    }
+
+    /**
+     * 结束加载
+     */
+    public synchronized void finishLoading() {
+        loading = false;
+    }
+
+    /**
+     * 加载停车场数据并更新卡片
+     *
+     * @param context         上下文对象
+     * @param formId          卡片ID
+     * @param onUpdateDefault 更新默认信息的回调
+     * @param onUpdateData    更新停车场数据的回调
+     */
+    public void loadParkingData(Context context, long formId,
+                                Consumer<Long> onUpdateDefault,
+                                BiConsumer<Long, String[]> onUpdateData) {
+        // 先尝试查询车牌计费
+        queryPlateNoAndFee(context, formId, onUpdateDefault, onUpdateData);
+    }
+
+    /**
+     * 查询车牌号并计费
+     */
+    private void queryPlateNoAndFee(Context context, long formId,
+                                    Consumer<Long> onUpdateDefault,
+                                    BiConsumer<Long, String[]> onUpdateData) {
+        // 缓存过期或不存在,查询车牌号
+        String plateNo = getPlateNo(context);
+        if (plateNo == null || plateNo.isEmpty()) {
+            // 没有车牌号,走车场查询
+            loadParkingLotData(context, formId, onUpdateDefault, onUpdateData);
+        } else {
+            // 有车牌号,查询计费
+            queryFeeByPlateNo(context, plateNo, formId, onUpdateDefault, onUpdateData);
+        }
+    }
+
+    /**
+     * 获取车牌号(先从API获取,如果没有则从系统设置获取)
+     */
+    private String getPlateNo(Context context) {
+        try {
+            String plateNo = cache.getDefaultPlateNo(context);
+
+            if (plateNo == null || plateNo.isEmpty()) {
+                // API没有车牌,从系统设置获取
+                DataAbilityHelper dataAbilityHelper = DataAbilityHelper.creator(context);
+                return SystemSettings.getValue(dataAbilityHelper, "car_license_plate_number");
+            } else {
+                return plateNo;
+            }
+        } catch (Exception e) {
+            Log.error("获取车牌号异常: " + e.getMessage());
+            return null;
+        }
+    }
+
+    /**
+     * 根据车牌号查询费用
+     */
+    private void queryFeeByPlateNo(Context context, String plateNo, long formId,
+                                   Consumer<Long> onUpdateDefault,
+                                   BiConsumer<Long, String[]> onUpdateData) {
+        ChargeQuery query = new ChargeQuery();
+        query.setChargeScene(2); // 计费场景:2-临停缴费
+        query.setPlateNo(plateNo);
+
+        CompletableFuture<R<ParkingFeeInfo>> future = common.queryParkingFee(context, query);
+        future.thenAccept(result -> {
+            try {
+                if (result != null && result.isSuccess() && result.getData() != null) {
+                    ParkingFeeInfo feeInfo = result.getData();
+                    Integer actualAmount = feeInfo.getActualAmount();
+
+                    // 更新缓存
+                    cachedPlateNo = plateNo;
+                    cachedFeeInfo = feeInfo;
+                    cacheTimestamp = System.currentTimeMillis();
+
+                    if (actualAmount != null && actualAmount > 0) {
+                        // 有费用
+                        String line2 = formatFee(actualAmount);
+                        String line3 = feeInfo.getStayTime() != null ? "停车时长:" + feeInfo.getStayTime() : "停车时长未知";
+                        onUpdateData.accept(formId, new String[]{line2, line3});
+                    } else {
+                        // 无费用,走车场查询
+                        loadParkingLotData(context, formId, onUpdateDefault, onUpdateData);
+                    }
+                } else {
+                    // 查询失败,走车场查询
+                    loadParkingLotData(context, formId, onUpdateDefault, onUpdateData);
+                }
+            } catch (Exception e) {
+                Log.error("处理计费数据异常: " + e.getMessage());
+                loadParkingLotData(context, formId, onUpdateDefault, onUpdateData);
+            } finally {
+                finishLoading();
+            }
+        }).exceptionally(e -> {
+            Log.error("查询计费失败: " + e.getMessage());
+            // 查询失败,走车场查询
+            loadParkingLotData(context, formId, onUpdateDefault, onUpdateData);
+            finishLoading();
+            return null;
+        });
+    }
+
+    /**
+     * 格式化费用(分转元)
+     */
+    private String formatFee(Integer amountInCents) {
+        if (amountInCents == null || amountInCents == 0) {
+            return "0元";
+        }
+        double yuan = amountInCents / 100.0;
+        return String.format("%.2f元", yuan);
+    }
+
+    /**
+     * 加载车场数据(原有逻辑)
+     */
+    private void loadParkingLotData(Context context, long formId,
+                                    Consumer<Long> onUpdateDefault,
+                                    BiConsumer<Long, String[]> onUpdateData) {
+        // 获取定位坐标
+        double latitude = cache.getLocationLatitude(context);
+        double longitude = cache.getLocationLongitude(context);
+
+        // 构建请求URL
+        ApiOption option = new ApiOption();
+        option.setUrl(String.format("/park/near/page?type=2&filter=2&latitude=%f&longitude=%f&current=1&size=10", latitude, longitude));
+        option.setMethod(ApiOption.GET);
+
+        CompletableFuture<R<Page<ParkNearRes>>> future = api.http(context, option, new TypeToken<R<Page<ParkNearRes>>>() {
+        });
+
+        // 处理API返回结果
+        future.thenAccept(response -> {
+            try {
+                if (response == null || !response.isSuccess()) {
+                    String errorMsg = response != null ? response.getMsg() : "请求失败";
+                    Log.error("加载停车场数据失败: " + errorMsg);
+                    onUpdateDefault.accept(formId);
+                    return;
+                }
+
+                Page<ParkNearRes> page = response.getData();
+                if (page == null || page.getRecords() == null || page.getRecords().isEmpty()) {
+                    Log.error("停车场数据为空");
+                    onUpdateDefault.accept(formId);
+                    return;
+                }
+
+                List<ParkNearRes> records = page.getRecords();
+
+                // 随机选择一个停车场
+                Random random = new Random();
+                ParkNearRes randomPark = records.get(random.nextInt(records.size()));
+
+                // 格式化数据
+                String line2 = randomPark.getParkName() != null ? randomPark.getParkName() : "未知停车场";
+
+                String distanceStr = randomPark.getDistance() != null ?
+                        String.format("%.1fkm", randomPark.getDistance() / 1000.0) : "0km";
+
+                int residuePlace = randomPark.getResiduePlace() != null ? randomPark.getResiduePlace() : 0;
+                String line3 = String.format("距离%s米 余位 %s", distanceStr, residuePlace);
+
+                // 更新卡片显示
+                onUpdateData.accept(formId, new String[]{line2, line3});
+
+            } catch (Exception e) {
+                Log.error("处理停车场数据异常: " + e.getMessage());
+                onUpdateDefault.accept(formId);
+            } finally {
+                finishLoading();
+            }
+        }).exceptionally(e -> {
+            finishLoading();
+            // 异常处理
+            Log.error("获取停车场数据失败: " + e.getMessage());
+            onUpdateDefault.accept(formId);
+            return null;
+        });
+    }
+}
+

+ 119 - 0
entry/src/main/java/com/fujica/abk/model/in/PayRequest.java

@@ -0,0 +1,119 @@
+package com.fujica.abk.model.in;
+
+/**
+ * 支付请求参数
+ */
+public class PayRequest {
+    private Integer actualAmount;      // 实际支付金额(分)
+    private Integer bizType;           // 业务类型: 1-临停
+    private Integer discountAmount;    // 优惠金额(分)
+    private Boolean doubleConfirm;     // 是否需要二次确认
+    private String goodsName;          // 商品名称(如车牌号)
+    private String orderId;            // 订单ID
+    private String parkId;             // 车场ID
+    private String parkName;           // 车场名称
+    private String paySceneCode;       // 支付场景编码: WX_NA-微信Native支付
+    private String paySourceCode;      // 支付来源: HW_CAR-华为车机
+    private String projectNo;          // 项目编号
+    private Integer totalAmount;       // 总金额(分)
+
+    public PayRequest() {
+    }
+
+    public Integer getActualAmount() {
+        return actualAmount;
+    }
+
+    public void setActualAmount(Integer actualAmount) {
+        this.actualAmount = actualAmount;
+    }
+
+    public Integer getBizType() {
+        return bizType;
+    }
+
+    public void setBizType(Integer bizType) {
+        this.bizType = bizType;
+    }
+
+    public Integer getDiscountAmount() {
+        return discountAmount;
+    }
+
+    public void setDiscountAmount(Integer discountAmount) {
+        this.discountAmount = discountAmount;
+    }
+
+    public Boolean getDoubleConfirm() {
+        return doubleConfirm;
+    }
+
+    public void setDoubleConfirm(Boolean doubleConfirm) {
+        this.doubleConfirm = doubleConfirm;
+    }
+
+    public String getGoodsName() {
+        return goodsName;
+    }
+
+    public void setGoodsName(String goodsName) {
+        this.goodsName = goodsName;
+    }
+
+    public String getOrderId() {
+        return orderId;
+    }
+
+    public void setOrderId(String orderId) {
+        this.orderId = orderId;
+    }
+
+    public String getParkId() {
+        return parkId;
+    }
+
+    public void setParkId(String parkId) {
+        this.parkId = parkId;
+    }
+
+    public String getParkName() {
+        return parkName;
+    }
+
+    public void setParkName(String parkName) {
+        this.parkName = parkName;
+    }
+
+    public String getPaySceneCode() {
+        return paySceneCode;
+    }
+
+    public void setPaySceneCode(String paySceneCode) {
+        this.paySceneCode = paySceneCode;
+    }
+
+    public String getPaySourceCode() {
+        return paySourceCode;
+    }
+
+    public void setPaySourceCode(String paySourceCode) {
+        this.paySourceCode = paySourceCode;
+    }
+
+    public String getProjectNo() {
+        return projectNo;
+    }
+
+    public void setProjectNo(String projectNo) {
+        this.projectNo = projectNo;
+    }
+
+    public Integer getTotalAmount() {
+        return totalAmount;
+    }
+
+    public void setTotalAmount(Integer totalAmount) {
+        this.totalAmount = totalAmount;
+    }
+}
+

File diff suppressed because it is too large
+ 61 - 6
entry/src/main/java/com/fujica/abk/model/out/ParkingFeeInfo.java


+ 179 - 0
entry/src/main/java/com/fujica/abk/model/out/PayChannelInfo.java

@@ -0,0 +1,179 @@
+package com.fujica.abk.model.out;
+
+/**
+ * 支付渠道信息
+ */
+public class PayChannelInfo {
+    private String bindId;
+    private String payChannelId;
+    private String payChannelCode;
+    private String parkId;
+    private String parkName;
+    private String companyId;
+    private String companyName;
+    private String projectNo;
+    private String projectName;
+    private Integer signPriority;
+    private Integer autoPayMode;
+    private Integer bizType;
+    private String aliParam;
+    private String createTime;
+    private String createName;
+    private String updateTime;
+    private String updateName;
+    private Integer bandNum;
+    private String bandChannelStr;
+
+    public String getBindId() {
+        return bindId;
+    }
+
+    public void setBindId(String bindId) {
+        this.bindId = bindId;
+    }
+
+    public String getPayChannelId() {
+        return payChannelId;
+    }
+
+    public void setPayChannelId(String payChannelId) {
+        this.payChannelId = payChannelId;
+    }
+
+    public String getPayChannelCode() {
+        return payChannelCode;
+    }
+
+    public void setPayChannelCode(String payChannelCode) {
+        this.payChannelCode = payChannelCode;
+    }
+
+    public String getParkId() {
+        return parkId;
+    }
+
+    public void setParkId(String parkId) {
+        this.parkId = parkId;
+    }
+
+    public String getParkName() {
+        return parkName;
+    }
+
+    public void setParkName(String parkName) {
+        this.parkName = parkName;
+    }
+
+    public String getCompanyId() {
+        return companyId;
+    }
+
+    public void setCompanyId(String companyId) {
+        this.companyId = companyId;
+    }
+
+    public String getCompanyName() {
+        return companyName;
+    }
+
+    public void setCompanyName(String companyName) {
+        this.companyName = companyName;
+    }
+
+    public String getProjectNo() {
+        return projectNo;
+    }
+
+    public void setProjectNo(String projectNo) {
+        this.projectNo = projectNo;
+    }
+
+    public String getProjectName() {
+        return projectName;
+    }
+
+    public void setProjectName(String projectName) {
+        this.projectName = projectName;
+    }
+
+    public Integer getSignPriority() {
+        return signPriority;
+    }
+
+    public void setSignPriority(Integer signPriority) {
+        this.signPriority = signPriority;
+    }
+
+    public Integer getAutoPayMode() {
+        return autoPayMode;
+    }
+
+    public void setAutoPayMode(Integer autoPayMode) {
+        this.autoPayMode = autoPayMode;
+    }
+
+    public Integer getBizType() {
+        return bizType;
+    }
+
+    public void setBizType(Integer bizType) {
+        this.bizType = bizType;
+    }
+
+    public String getAliParam() {
+        return aliParam;
+    }
+
+    public void setAliParam(String aliParam) {
+        this.aliParam = aliParam;
+    }
+
+    public String getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(String createTime) {
+        this.createTime = createTime;
+    }
+
+    public String getCreateName() {
+        return createName;
+    }
+
+    public void setCreateName(String createName) {
+        this.createName = createName;
+    }
+
+    public String getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(String updateTime) {
+        this.updateTime = updateTime;
+    }
+
+    public String getUpdateName() {
+        return updateName;
+    }
+
+    public void setUpdateName(String updateName) {
+        this.updateName = updateName;
+    }
+
+    public Integer getBandNum() {
+        return bandNum;
+    }
+
+    public void setBandNum(Integer bandNum) {
+        this.bandNum = bandNum;
+    }
+
+    public String getBandChannelStr() {
+        return bandChannelStr;
+    }
+
+    public void setBandChannelStr(String bandChannelStr) {
+        this.bandChannelStr = bandChannelStr;
+    }
+}
+

+ 199 - 0
entry/src/main/java/com/fujica/abk/model/out/PayChannelResponse.java

@@ -0,0 +1,199 @@
+package com.fujica.abk.model.out;
+
+import java.util.List;
+
+/**
+ * 支付渠道响应
+ */
+public class PayChannelResponse {
+    private String bindId;
+    private String payChannelId;
+    private String payChannelCode;
+    private String parkId;
+    private String parkName;
+    private String companyId;
+    private String companyName;
+    private String projectNo;
+    private String projectName;
+    private Integer signPriority;
+    private Integer autoPayMode;
+    private Integer bizType;
+    private String aliParam;
+    private String createTime;
+    private String createName;
+    private String updateTime;
+    private String updateName;
+    private Integer bandNum;
+    private String bandChannelStr;
+    private List<PayChannelInfo> payChannelInfoList;
+    private List<PayChannelInfo> companyChannelList;
+
+    public String getBindId() {
+        return bindId;
+    }
+
+    public void setBindId(String bindId) {
+        this.bindId = bindId;
+    }
+
+    public String getPayChannelId() {
+        return payChannelId;
+    }
+
+    public void setPayChannelId(String payChannelId) {
+        this.payChannelId = payChannelId;
+    }
+
+    public String getPayChannelCode() {
+        return payChannelCode;
+    }
+
+    public void setPayChannelCode(String payChannelCode) {
+        this.payChannelCode = payChannelCode;
+    }
+
+    public String getParkId() {
+        return parkId;
+    }
+
+    public void setParkId(String parkId) {
+        this.parkId = parkId;
+    }
+
+    public String getParkName() {
+        return parkName;
+    }
+
+    public void setParkName(String parkName) {
+        this.parkName = parkName;
+    }
+
+    public String getCompanyId() {
+        return companyId;
+    }
+
+    public void setCompanyId(String companyId) {
+        this.companyId = companyId;
+    }
+
+    public String getCompanyName() {
+        return companyName;
+    }
+
+    public void setCompanyName(String companyName) {
+        this.companyName = companyName;
+    }
+
+    public String getProjectNo() {
+        return projectNo;
+    }
+
+    public void setProjectNo(String projectNo) {
+        this.projectNo = projectNo;
+    }
+
+    public String getProjectName() {
+        return projectName;
+    }
+
+    public void setProjectName(String projectName) {
+        this.projectName = projectName;
+    }
+
+    public Integer getSignPriority() {
+        return signPriority;
+    }
+
+    public void setSignPriority(Integer signPriority) {
+        this.signPriority = signPriority;
+    }
+
+    public Integer getAutoPayMode() {
+        return autoPayMode;
+    }
+
+    public void setAutoPayMode(Integer autoPayMode) {
+        this.autoPayMode = autoPayMode;
+    }
+
+    public Integer getBizType() {
+        return bizType;
+    }
+
+    public void setBizType(Integer bizType) {
+        this.bizType = bizType;
+    }
+
+    public String getAliParam() {
+        return aliParam;
+    }
+
+    public void setAliParam(String aliParam) {
+        this.aliParam = aliParam;
+    }
+
+    public String getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(String createTime) {
+        this.createTime = createTime;
+    }
+
+    public String getCreateName() {
+        return createName;
+    }
+
+    public void setCreateName(String createName) {
+        this.createName = createName;
+    }
+
+    public String getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(String updateTime) {
+        this.updateTime = updateTime;
+    }
+
+    public String getUpdateName() {
+        return updateName;
+    }
+
+    public void setUpdateName(String updateName) {
+        this.updateName = updateName;
+    }
+
+    public Integer getBandNum() {
+        return bandNum;
+    }
+
+    public void setBandNum(Integer bandNum) {
+        this.bandNum = bandNum;
+    }
+
+    public String getBandChannelStr() {
+        return bandChannelStr;
+    }
+
+    public void setBandChannelStr(String bandChannelStr) {
+        this.bandChannelStr = bandChannelStr;
+    }
+
+    public List<PayChannelInfo> getPayChannelInfoList() {
+        return payChannelInfoList;
+    }
+
+    public void setPayChannelInfoList(List<PayChannelInfo> payChannelInfoList) {
+        this.payChannelInfoList = payChannelInfoList;
+    }
+
+    public List<PayChannelInfo> getCompanyChannelList() {
+        return companyChannelList;
+    }
+
+    public void setCompanyChannelList(List<PayChannelInfo> companyChannelList) {
+        this.companyChannelList = companyChannelList;
+    }
+}
+

+ 40 - 0
entry/src/main/java/com/fujica/abk/model/out/PayResponse.java

@@ -0,0 +1,40 @@
+package com.fujica.abk.model.out;
+
+import java.util.Set;
+
+/**
+ * 支付接口响应数据
+ */
+public class PayResponse {
+    private String outTradeNo;        // 支付流水号
+    private String qrCode;       // 二维码内容(用于微信扫码支付)
+    private String reqId;        // 请求ID
+
+    public PayResponse() {
+    }
+
+    public String getOutTradeNo() {
+        return outTradeNo;
+    }
+
+    public void setOutTradeNo(String outTradeNo) {
+        this.outTradeNo = outTradeNo;
+    }
+
+    public String getQrCode() {
+        return qrCode;
+    }
+
+    public void setQrCode(String qrCode) {
+        this.qrCode = qrCode;
+    }
+
+    public String getReqId() {
+        return reqId;
+    }
+
+    public void setReqId(String reqId) {
+        this.reqId = reqId;
+    }
+}
+

+ 146 - 0
entry/src/main/java/com/fujica/abk/model/out/PayStatusResponse.java

@@ -0,0 +1,146 @@
+package com.fujica.abk.model.out;
+
+/**
+ * 支付状态查询响应数据
+ */
+public class PayStatusResponse {
+    private String payNo;              // 支付流水号
+    private String orderId;            // 订单ID
+    private String goodsName;          // 商品名称
+    private String parkId;             // 车场ID
+    private String parkName;           // 车场名称
+    private String projectNo;          // 项目编号
+    private Integer totalAmount;       // 总金额(分)
+    private Integer actualAmount;      // 实际支付金额(分)
+    private Integer payStatus;         // 支付状态 (1-支付成功, 0-支付中, -1-支付失败)
+    private Integer bizType;           // 业务类型
+    private Integer mergeOrderFlag;    // 合并订单标识
+    private String payChannelCode;     // 支付渠道编码
+    private String paySourceCode;      // 支付来源编码
+    private String payWayCode;         // 支付方式编码
+    private String paySceneCode;       // 支付场景编码
+
+    public PayStatusResponse() {
+    }
+
+    public String getPayNo() {
+        return payNo;
+    }
+
+    public void setPayNo(String payNo) {
+        this.payNo = payNo;
+    }
+
+    public String getOrderId() {
+        return orderId;
+    }
+
+    public void setOrderId(String orderId) {
+        this.orderId = orderId;
+    }
+
+    public String getGoodsName() {
+        return goodsName;
+    }
+
+    public void setGoodsName(String goodsName) {
+        this.goodsName = goodsName;
+    }
+
+    public String getParkId() {
+        return parkId;
+    }
+
+    public void setParkId(String parkId) {
+        this.parkId = parkId;
+    }
+
+    public String getParkName() {
+        return parkName;
+    }
+
+    public void setParkName(String parkName) {
+        this.parkName = parkName;
+    }
+
+    public String getProjectNo() {
+        return projectNo;
+    }
+
+    public void setProjectNo(String projectNo) {
+        this.projectNo = projectNo;
+    }
+
+    public Integer getTotalAmount() {
+        return totalAmount;
+    }
+
+    public void setTotalAmount(Integer totalAmount) {
+        this.totalAmount = totalAmount;
+    }
+
+    public Integer getActualAmount() {
+        return actualAmount;
+    }
+
+    public void setActualAmount(Integer actualAmount) {
+        this.actualAmount = actualAmount;
+    }
+
+    public Integer getPayStatus() {
+        return payStatus;
+    }
+
+    public void setPayStatus(Integer payStatus) {
+        this.payStatus = payStatus;
+    }
+
+    public Integer getBizType() {
+        return bizType;
+    }
+
+    public void setBizType(Integer bizType) {
+        this.bizType = bizType;
+    }
+
+    public Integer getMergeOrderFlag() {
+        return mergeOrderFlag;
+    }
+
+    public void setMergeOrderFlag(Integer mergeOrderFlag) {
+        this.mergeOrderFlag = mergeOrderFlag;
+    }
+
+    public String getPayChannelCode() {
+        return payChannelCode;
+    }
+
+    public void setPayChannelCode(String payChannelCode) {
+        this.payChannelCode = payChannelCode;
+    }
+
+    public String getPaySourceCode() {
+        return paySourceCode;
+    }
+
+    public void setPaySourceCode(String paySourceCode) {
+        this.paySourceCode = paySourceCode;
+    }
+
+    public String getPayWayCode() {
+        return payWayCode;
+    }
+
+    public void setPayWayCode(String payWayCode) {
+        this.payWayCode = payWayCode;
+    }
+
+    public String getPaySceneCode() {
+        return paySceneCode;
+    }
+
+    public void setPaySceneCode(String paySceneCode) {
+        this.paySceneCode = paySceneCode;
+    }
+}
+

+ 222 - 124
entry/src/main/java/com/fujica/abk/slice/MainAbilitySlice.java

@@ -3,18 +3,18 @@ package com.fujica.abk.slice;
 import com.fujica.abk.ResourceTable;
 import com.fujica.abk.api.auth;
 import com.fujica.abk.api.cache;
+import com.fujica.abk.api.pay;
 import com.fujica.abk.common.EventBus;
-import com.fujica.abk.component.LoadingComponent;
-import com.fujica.abk.component.OrderDetailComponent;
-import com.fujica.abk.component.ParkDetailComponent;
+import com.fujica.abk.component.*;
 import com.fujica.abk.component.nav.ChargeComponent;
 import com.fujica.abk.component.nav.OrderComponent;
 import com.fujica.abk.component.nav.ParkComponent;
 import com.fujica.abk.model.out.OrderRes;
 import com.fujica.abk.model.out.ParkNearRes;
-import com.fujica.abk.utils.DialogUtil;
-import com.fujica.abk.utils.Log;
-import com.fujica.abk.utils.Toast;
+import com.fujica.abk.model.out.ParkingFeeInfo;
+import com.fujica.abk.model.out.PayChannelResponse;
+import com.fujica.abk.model.out.PayChannelInfo;
+import com.fujica.abk.utils.*;
 import com.huawei.hms.accountsdk.constant.CommonConstant;
 import com.huawei.hms.accountsdk.exception.ApiException;
 import com.huawei.hms.accountsdk.support.account.AccountAuthManager;
@@ -29,14 +29,8 @@ import ohos.aafwk.ability.AbilitySlice;
 import ohos.aafwk.content.Intent;
 import ohos.agp.components.*;
 import ohos.agp.utils.Color;
-import ohos.agp.window.dialog.ToastDialog;
 import ohos.agp.window.service.Window;
 import ohos.agp.window.service.WindowManager;
-import ohos.location.Location;
-import ohos.location.Locator;
-import ohos.location.LocatorCallback;
-import ohos.location.RequestParam;
-import ohos.rpc.RemoteException;
 
 public class MainAbilitySlice extends AbilitySlice {
     // 页面容器
@@ -59,19 +53,11 @@ public class MainAbilitySlice extends AbilitySlice {
     private Image iconOrder;
     private Image iconOrder1;
 
-    // 当前选中的 tab
-    private int currentTab = 0; // 0: 找车位, 1: 计费, 2: 缴费记录
-
-    // 定位相关
-    private Locator locator;
-    private LocatorCallback locatorCallback;
-    private Location currentLocation; // 当前定位坐标
-
     // 页面组件
     private ChargeComponent chargeComponent;
     private ParkComponent parkComponent; // 找车位页面组件
     private OrderComponent orderComponent; // 缴费记录页面组件
-    
+
     // 页面初始化标志
     private boolean isChargeComponentInitialized = false;
     private boolean isParkComponentInitialized = false;
@@ -92,16 +78,19 @@ public class MainAbilitySlice extends AbilitySlice {
 
     private Image quit;
 
+    // 当前选中的 tab
+    private int currentTab = 0; // 0: 找车位, 1: 计费, 2: 缴费记录
+
     @Override
     public void onStart(Intent intent) {
         super.onStart(intent);
 
-        try {
-            //com.fujica.abk_BD8VI9k5bO0HeGAPnhTGeYX++mgKw87G8y+3RZ6nrb9evCePddojupXJN03auUKxTKn1qbFrYQAjFyGumpjsHzw=
-            String appId = getApplicationContext().getBundleManager().getBundleInfo(getBundleName(), 0).getAppId();
-            Log.info(appId);
-        } catch (RemoteException e) {
-        }
+//        try {
+//            //com.fujica.abk_BD8VI9k5bO0HeGAPnhTGeYX++mgKw87G8y+3RZ6nrb9evCePddojupXJN03auUKxTKn1qbFrYQAjFyGumpjsHzw=
+//            String appId = getApplicationContext().getBundleManager().getBundleInfo(getBundleName(), 0).getAppId();
+//            Log.info(appId);
+//        } catch (RemoteException e) {
+//        }
 
         // 设置全屏显示
         setFullScreen();
@@ -135,9 +124,6 @@ public class MainAbilitySlice extends AbilitySlice {
         // 设置事件监听
         setupListeners();
 
-        // 初始化定位
-        initLocation();
-
         Button mBtnHuaweiIdSignIn = findComponentById(ResourceTable.Id_btn_hwid_sign_in);
         mBtnHuaweiIdSignIn.setClickedListener((Component c) -> {
             huaweiIdSignIn();
@@ -255,7 +241,7 @@ public class MainAbilitySlice extends AbilitySlice {
 
         // 初始化底部导航栏
         initBottomNavigation();
-        
+
         // 默认初始化找车位页面(因为默认显示该页面)
 //        initParkComponent();
 
@@ -270,11 +256,18 @@ public class MainAbilitySlice extends AbilitySlice {
         if (isChargeComponentInitialized || pageContainer == null) {
             return;
         }
-        
+
         try {
             Log.info("首次初始化缴费页面");
             chargeComponent = new ChargeComponent(MainAbilitySlice.this);
             chargeComponent.setLoadingComponent(loadingComponent);
+            // 设置支付详情展示监听器
+            chargeComponent.setOnPayDetailShowListener(new ChargeComponent.OnPayDetailShowListener() {
+                @Override
+                public void onShowPayDetail(ParkingFeeInfo feeInfo) {
+                    showPayDetail(feeInfo);
+                }
+            });
             chargeComponent.setVisibility(Component.HIDE);
             pageContainer.addComponent(chargeComponent);
             isChargeComponentInitialized = true;
@@ -284,7 +277,7 @@ public class MainAbilitySlice extends AbilitySlice {
             e.printStackTrace();
         }
     }
-    
+
     /**
      * 初始化找车位页面组件
      */
@@ -292,15 +285,13 @@ public class MainAbilitySlice extends AbilitySlice {
         if (isParkComponentInitialized || pageContainer == null) {
             return;
         }
-        
+
         try {
+
             Log.info("首次初始化找车位页面");
             parkComponent = new ParkComponent(MainAbilitySlice.this);
             parkComponent.setLoadingComponent(loadingComponent);
-            // 如果已有定位信息,设置到组件中
-            if (currentLocation != null) {
-                parkComponent.setCurrentLocation(currentLocation);
-            }
+
             // 设置停车场选中监听器
             parkComponent.setOnParkSelectedListener(new ParkComponent.OnParkSelectedListener() {
                 @Override
@@ -316,13 +307,17 @@ public class MainAbilitySlice extends AbilitySlice {
             parkComponent.setVisibility(Component.HIDE);
             pageContainer.addComponent(parkComponent);
             isParkComponentInitialized = true;
+            //是否要申请权限
+            if(!PermissionManager.requestLocation(getContext())){
+                parkComponent.loadParkingDataByLocation();
+            }
             Log.info("找车位页面初始化完成");
         } catch (Exception e) {
             Log.error("创建找车位页面组件失败: " + e.getMessage());
             e.printStackTrace();
         }
     }
-    
+
     /**
      * 初始化缴费记录页面组件
      */
@@ -330,7 +325,7 @@ public class MainAbilitySlice extends AbilitySlice {
         if (isOrderComponentInitialized || pageContainer == null) {
             return;
         }
-        
+
         try {
             Log.info("首次初始化缴费记录页面");
             orderComponent = new OrderComponent(MainAbilitySlice.this);
@@ -388,13 +383,14 @@ public class MainAbilitySlice extends AbilitySlice {
         }
         if (navCurrentLocation != null) {
             navCurrentLocation.setClickedListener(component -> {
-                Log.info("点击了当前位置按钮");
-                locateCurrentPosition();
+                if(currentTab == 0 && parkComponent!=null && isParkComponentInitialized){
+                    parkComponent.loadParkingDataByLocation();
+                }
             });
         }
     }
 
-    private void switchToPageAfterLogin(int index){
+    private void switchToPageAfterLogin(int index) {
         // 先检查是否已登录
         if (!cache.isAuth(this)) {
             // 未登录,调用登录方法
@@ -419,6 +415,7 @@ public class MainAbilitySlice extends AbilitySlice {
     }
 
 
+
     /**
      * 切换到指定页面
      */
@@ -438,16 +435,18 @@ public class MainAbilitySlice extends AbilitySlice {
             orderComponent.setVisibility(Component.HIDE);
         }
 
+
         // 显示目标页面
         switch (index) {
             case 0: // 找车位
                 // 首次打开时初始化
                 if (!isParkComponentInitialized) {
-                    initParkComponent();
                     // 首次初始化时,组件内部已经加载了数据,无需再调用refresh()
+                    initParkComponent();
                 } else if (parkComponent != null) {
                     // 非首次打开时才刷新数据
-                    parkComponent.refresh();
+                    parkComponent.switchTab(2);
+                    parkComponent.loadParkingData(true);
                 }
                 if (parkComponent != null) {
                     parkComponent.setVisibility(Component.VISIBLE);
@@ -483,6 +482,7 @@ public class MainAbilitySlice extends AbilitySlice {
 
         // 更新当前tab状态
         currentTab = index;
+
         updateBottomNavState(index);
 
         // 切换页面时隐藏详情
@@ -549,65 +549,6 @@ public class MainAbilitySlice extends AbilitySlice {
         // 事件监听已在initBottomNavigation中设置
     }
 
-    /**
-     * 初始化定位服务
-     */
-    private void initLocation() {
-        try {
-            locator = new Locator(this);
-            locatorCallback = new LocatorCallback() {
-                @Override
-                public void onLocationReport(Location location) {
-                    // 保存当前位置坐标
-                    currentLocation = location;
-                    double latitude = location.getLatitude();
-                    double longitude = location.getLongitude();
-
-                    Log.info("定位成功: " + latitude + ", " + longitude);
-                    // 定位成功后,如果当前在找车位页面,更新定位信息
-                    if (currentTab == 0 && parkComponent != null) {
-                        parkComponent.setCurrentLocation(location);
-                    }
-                }
-
-                @Override
-                public void onStatusChanged(int type) {
-                    Log.info("定位状态变化: " + type);
-                }
-
-                @Override
-                public void onErrorReport(int errorCode) {
-                    Log.error("定位错误: " + errorCode);
-                    new ToastDialog(getContext())
-                            .setText("定位失败,错误码: " + errorCode)
-                            .show();
-                }
-            };
-        } catch (Exception e) {
-            Log.error("初始化定位服务失败: " + e.getMessage());
-        }
-    }
-
-    /**
-     * 定位到当前位置
-     */
-    private void locateCurrentPosition() {
-        if (locator == null || locatorCallback == null) {
-            Log.error("定位服务未初始化");
-            return;
-        }
-
-        try {
-            // 请求定位
-            RequestParam requestParam = new RequestParam(RequestParam.PRIORITY_ACCURACY, 0, 0);
-            locator.startLocating(requestParam, locatorCallback);
-            Log.info("开始定位...");
-        } catch (Exception e) {
-            Log.error("定位失败: " + e.getMessage());
-        }
-    }
-
-
     /**
      * 订阅登录成功事件
      */
@@ -644,23 +585,24 @@ public class MainAbilitySlice extends AbilitySlice {
                 }
                 // 可以在这里添加其他需要更新的UI逻辑
             });
-                // 认证过期后重新登录
-                auth.login(MainAbilitySlice.this).thenAccept(success -> {
-                    if (success) {
-                        Log.info("重新登录成功");
-                    } else {
-                        Log.error("重新登录失败");
-                    }
-                }).exceptionally(e -> {
-                    Log.error("重新登录异常: " + e.getMessage());
-                    return null;
-                });
+            // 认证过期后重新登录
+            auth.login(MainAbilitySlice.this).thenAccept(success -> {
+                if (success) {
+                    Log.info("重新登录成功");
+                } else {
+                    Log.error("重新登录失败");
+                }
+            }).exceptionally(e -> {
+                Log.error("重新登录异常: " + e.getMessage());
+                return null;
+            });
         };
         EventBus.getInstance().on("onLoginExpired", authChangedListener);
     }
 
     @Override
     protected void onStop() {
+//        AggrPayClient
         super.onStop();
         // 取消订阅登录成功事件
         if (loginSuccessListener != null) {
@@ -670,14 +612,11 @@ public class MainAbilitySlice extends AbilitySlice {
         if (authChangedListener != null) {
             EventBus.getInstance().off("onLoginExpired", authChangedListener);
         }
-
-        // 停止定位
-        if (locator != null && locatorCallback != null) {
-            try {
-                locator.stopLocating(locatorCallback);
-            } catch (Exception e) {
-                Log.error("停止定位失败: " + e.getMessage());
-            }
+        
+        // 取消parkComponent的事件订阅
+        if (parkComponent != null) {
+            parkComponent.unsubscribeEvents();
+            parkComponent.stopLocation();
         }
     }
 
@@ -685,13 +624,19 @@ public class MainAbilitySlice extends AbilitySlice {
      * 显示订单详情
      */
     private void showOrderDetail(OrderRes order) {
+//        Uri content_url = Uri.parse("petalmaps://navigation?saddr=25.102916,55.165363&daddr=25.164610000000,55.228869000000&type=drive&utm_source=fb");
+//        Intent intent = new Intent(Intent.ACTION_VIEW, content_url);
+//        if (intent.resolveActivity(getPackageManager()) != null) {
+//            startActivity(intent);
+//        }
+//        sta
         if (mainRight == null || orderDetailComponent == null) {
             return;
         }
         // 移除所有子组件
         mainRight.removeAllComponents();
         // 设置订单数据
-        orderDetailComponent.setOrderData(order,getContext());
+        orderDetailComponent.setOrderData(order, getContext());
         // 添加详情组件
         mainRight.addComponent(orderDetailComponent);
         // 显示详情区域
@@ -715,6 +660,159 @@ public class MainAbilitySlice extends AbilitySlice {
         mainRight.setVisibility(Component.VISIBLE);
     }
 
+    /**
+     * 显示支付订单详情
+     */
+    private void showPayDetail(ParkingFeeInfo feeInfo) {
+        PayDetailDialog payDetailDialog = new PayDetailDialog(this);
+
+        // 设置支付详情组件的支付按钮点击监听器
+        payDetailDialog.setOnPayClickListener(fee -> {
+            // 获取车场ID
+            String parkId = fee.getParkId();
+            if (parkId == null || parkId.isEmpty()) {
+                Log.error("车场ID为空,无法获取支付渠道");
+                return;
+            }
+
+            // 先获取支付渠道
+            pay.getPayChannel(getContext(), parkId).thenAccept(result -> {
+                getContext().getUITaskDispatcher().asyncDispatch(() -> {
+                    String paySceneCode = null;
+
+                    if (result != null && result.isSuccess() && result.getData() != null) {
+                        PayChannelResponse channelData = result.getData();
+
+                        // 判断支付渠道
+                        if (channelData.getPayChannelInfoList() != null && !channelData.getPayChannelInfoList().isEmpty()) {
+                            boolean hasWx = false;
+                            boolean hasAli = false;
+
+                            for (PayChannelInfo channelInfo : channelData.getPayChannelInfoList()) {
+                                String channelCode = channelInfo.getPayChannelCode();
+                                if (channelCode != null) {
+                                    if (channelCode.contains("WX")) {
+                                        hasWx = true;
+                                    }
+                                    if (channelCode.contains("ALI")) {
+                                        hasAli = true;
+                                    }
+                                }
+                            }
+
+                            // 优先使用微信支付
+                            if (hasWx) {
+                                paySceneCode = "WX_NA";
+                                Log.info("支持微信支付,使用微信扫码");
+                            } else if (hasAli) {
+                                paySceneCode = "ALI_PCRE";
+                                Log.info("支持支付宝支付,使用支付宝扫码");
+                            } else {
+                                Log.warn("未配置支持的支付渠道");
+                            }
+                        } else {
+                            Log.warn("未获取到支付渠道列表");
+                        }
+                    } else {
+                        Log.warn("获取支付渠道失败");
+                    }
+
+                    // 检查是否获取到支付渠道
+                    if (paySceneCode == null) {
+                        // 先关闭支付详情弹框,避免倒计时继续运行导致空指针
+                        payDetailDialog.hide();
+                        Toast.error(getContext(), "未配置支付渠道");
+                        return;
+                    }
+
+                    // 关闭支付详情弹框
+                    payDetailDialog.hide();
+
+                    // 创建并显示二维码弹框
+                    QRCodeScanDialog qrCodeScanDialog = new QRCodeScanDialog(this);
+
+                    // 设置费用信息
+                    qrCodeScanDialog.setFeeInfo(fee);
+
+                    // 设置支付场景代码
+                    qrCodeScanDialog.setPaySceneCode(paySceneCode);
+
+                    // 设置弹框关闭监听器 - 关闭时刷新ChargeComponent
+                    qrCodeScanDialog.setOnCloseListener(() -> {
+                        Log.info("二维码弹框关闭,刷新ChargeComponent");
+                        if (chargeComponent != null) {
+                            chargeComponent.refresh();
+                        }
+                    });
+
+                    // 设置支付结果监听器
+                    qrCodeScanDialog.setOnPayResultListener(new QRCodeScanDialog.OnPayResultListener() {
+                        @Override
+                        public void onPaySuccess(String payNo) {
+                            Log.info("支付成功: payNo=" + payNo);
+                        }
+
+                        @Override
+                        public void onPayFailed(String errorMsg) {
+                            Log.error("支付失败: " + errorMsg);
+                        }
+
+                        @Override
+                        public void onPayTimeout() {
+                            Log.info("支付超时");
+                        }
+                    });
+
+                    // 显示二维码扫描对话框
+                    qrCodeScanDialog.show();
+                });
+            }).exceptionally(ex -> {
+                getContext().getUITaskDispatcher().asyncDispatch(() -> {
+                    Log.error("获取支付渠道异常: " + ex.getMessage());
+                    // 异常时使用默认支付方式
+                    payDetailDialog.hide();
+
+                    QRCodeScanDialog qrCodeScanDialog = new QRCodeScanDialog(this);
+                    qrCodeScanDialog.setFeeInfo(fee);
+                    qrCodeScanDialog.setPaySceneCode("ALI_PCRE"); // 默认支付宝
+                    qrCodeScanDialog.setOnCloseListener(() -> {
+                        Log.info("二维码弹框关闭,刷新ChargeComponent");
+                        if (chargeComponent != null) {
+                            chargeComponent.refresh();
+                        }
+                    });
+
+                    qrCodeScanDialog.setOnPayResultListener(new QRCodeScanDialog.OnPayResultListener() {
+                        @Override
+                        public void onPaySuccess(String payNo) {
+                            Log.info("支付成功: payNo=" + payNo);
+                        }
+
+                        @Override
+                        public void onPayFailed(String errorMsg) {
+                            Log.error("支付失败: " + errorMsg);
+                        }
+
+                        @Override
+                        public void onPayTimeout() {
+                            Log.info("支付超时");
+                        }
+                    });
+
+                    qrCodeScanDialog.show();
+                });
+                return null;
+            });
+        });
+
+        // 设置支付订单数据
+        payDetailDialog.setFeeInfo(feeInfo);
+
+        // 显示弹框(弹框内部会自动获取倒计时时间并重新计费)
+        payDetailDialog.show();
+    }
+
+
     /**
      * 隐藏详情
      */

+ 40 - 0
entry/src/main/java/com/fujica/abk/utils/PermissionManager.java

@@ -0,0 +1,40 @@
+package com.fujica.abk.utils;
+
+import com.fujica.abk.api.config;
+import ohos.app.Context;
+import ohos.security.SystemPermission;
+
+public class PermissionManager {
+    public static final int Common = 0;
+    public static final int Request_Location = 1;
+
+    static boolean canLocation = false;
+
+    public static boolean requestLocation(Context context) {
+        if (config.isDebug) {
+            return true;
+        }
+        if (context.verifySelfPermission(SystemPermission.LOCATION) != -1) {
+            canLocation = true;
+            return false;
+        }
+        String[] permissions = {SystemPermission.LOCATION};
+        context.requestPermissionsFromUser(permissions, Request_Location);
+        return true;
+    }
+
+    public static void updateLocation(String[] permissions, int[] grantResults) {
+        if (permissions != null && grantResults != null) {
+            for (int i = 0; i < permissions.length; i++) {
+                if (SystemPermission.LOCATION.equalsIgnoreCase(permissions[i])) {
+                    if (grantResults.length > i) {
+                        canLocation = grantResults[i] != -1;
+                    } else {
+                        canLocation = false;
+                    }
+                    break;
+                }
+            }
+        }
+    }
+}

+ 191 - 0
entry/src/main/java/com/fujica/abk/utils/QRCodeUtil.java

@@ -0,0 +1,191 @@
+package com.fujica.abk.utils;
+
+import com.google.zxing.BarcodeFormat;
+import com.google.zxing.EncodeHintType;
+import com.google.zxing.WriterException;
+import com.google.zxing.common.BitMatrix;
+import com.google.zxing.qrcode.QRCodeWriter;
+import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
+import ohos.media.image.ImageSource;
+import ohos.media.image.PixelMap;
+import ohos.media.image.common.PixelFormat;
+import ohos.media.image.common.Size;
+
+import java.io.ByteArrayOutputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 二维码生成工具类
+ * 使用 ZXing 库生成标准的 QR Code
+ */
+public class QRCodeUtil {
+    
+    /**
+     * 生成二维码PixelMap
+     * 
+     * @param content 二维码内容
+     * @param size 二维码大小(宽高相同)
+     * @return 二维码PixelMap对象
+     */
+    public static PixelMap generateQRCode(String content, int size) {
+        if (content == null || content.isEmpty()) {
+            Log.error("二维码内容不能为空");
+            return null;
+        }
+        
+        try {
+            // 使用 ZXing 生成标准 QR Code
+            BitMatrix bitMatrix = generateQRCodeBitMatrix(content, size, size);
+            if (bitMatrix == null) {
+                Log.error("生成二维码矩阵失败");
+                return null;
+            }
+            
+            // 将 BitMatrix 转换为 PixelMap
+            return bitMatrixToPixelMap(bitMatrix);
+        } catch (Exception e) {
+            Log.error("生成二维码失败: " + e.getMessage());
+            e.printStackTrace();
+            return null;
+        }
+    }
+    
+    /**
+     * 使用 ZXing 生成二维码矩阵
+     */
+    private static BitMatrix generateQRCodeBitMatrix(String content, int width, int height) {
+        try {
+            // 配置二维码参数
+            Map<EncodeHintType, Object> hints = new HashMap<>();
+            // 设置字符编码
+            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
+            // 设置容错等级 (L < M < Q < H),L 为最低容错级别
+            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
+            // 设置边距(默认为4)
+            hints.put(EncodeHintType.MARGIN, 1);
+            
+            // 生成二维码矩阵
+            QRCodeWriter writer = new QRCodeWriter();
+            return writer.encode(content, BarcodeFormat.QR_CODE, width, height, hints);
+        } catch (WriterException e) {
+            Log.error("生成二维码矩阵失败: " + e.getMessage());
+            e.printStackTrace();
+            return null;
+        }
+    }
+    
+    /**
+     * 将 BitMatrix 转换为 PixelMap
+     */
+    private static PixelMap bitMatrixToPixelMap(BitMatrix bitMatrix) {
+        try {
+            int width = bitMatrix.getWidth();
+            int height = bitMatrix.getHeight();
+            
+            // 生成 BMP 格式图像数据
+            byte[] bmpData = bitMatrixToBmp(bitMatrix);
+            
+            // 使用 ImageSource 解码 BMP 数据创建 PixelMap
+            ImageSource.SourceOptions srcOpts = new ImageSource.SourceOptions();
+            srcOpts.formatHint = "image/bmp";
+            
+            ImageSource imageSource = ImageSource.create(bmpData, srcOpts);
+            if (imageSource == null) {
+                Log.error("ImageSource创建失败");
+                return null;
+            }
+            
+            ImageSource.DecodingOptions decodingOpts = new ImageSource.DecodingOptions();
+            decodingOpts.desiredSize = new Size(width, height);
+            decodingOpts.desiredPixelFormat = PixelFormat.ARGB_8888;
+            
+            PixelMap pixelMap = imageSource.createPixelmap(decodingOpts);
+            imageSource.release();
+            
+            return pixelMap;
+        } catch (Exception e) {
+            Log.error("BitMatrix转换为PixelMap失败: " + e.getMessage());
+            e.printStackTrace();
+            return null;
+        }
+    }
+    
+    /**
+     * 将 BitMatrix 转换为 BMP 格式图像数据
+     */
+    private static byte[] bitMatrixToBmp(BitMatrix bitMatrix) throws Exception {
+        int width = bitMatrix.getWidth();
+        int height = bitMatrix.getHeight();
+        
+        // BMP 文件头和信息头
+        int rowPadding = (4 - (width * 3) % 4) % 4; // 每行需要填充到4字节对齐
+        int imageSize = (width * 3 + rowPadding) * height;
+        int fileSize = 54 + imageSize; // 文件头54字节 + 像素数据
+        
+        ByteArrayOutputStream bos = new ByteArrayOutputStream(fileSize);
+        
+        // BMP 文件头 (14字节)
+        bos.write(0x42); // 'B'
+        bos.write(0x4D); // 'M'
+        writeInt(bos, fileSize); // 文件大小
+        writeShort(bos, 0); // 保留字段
+        writeShort(bos, 0); // 保留字段
+        writeInt(bos, 54); // 像素数据偏移
+        
+        // BMP 信息头 (40字节)
+        writeInt(bos, 40); // 信息头大小
+        writeInt(bos, width); // 图像宽度
+        writeInt(bos, height); // 图像高度
+        writeShort(bos, 1); // 颜色平面数
+        writeShort(bos, 24); // 位深度(24位RGB)
+        writeInt(bos, 0); // 压缩方式(不压缩)
+        writeInt(bos, imageSize); // 图像数据大小
+        writeInt(bos, 0); // 水平分辨率
+        writeInt(bos, 0); // 垂直分辨率
+        writeInt(bos, 0); // 调色板颜色数
+        writeInt(bos, 0); // 重要颜色数
+        
+        // 像素数据(BMP 从下到上存储)
+        for (int y = height - 1; y >= 0; y--) {
+            for (int x = 0; x < width; x++) {
+                // BitMatrix.get() 返回 true 表示黑色,false 表示白色
+                if (bitMatrix.get(x, y)) {
+                    // 黑色
+                    bos.write(0x00); // B
+                    bos.write(0x00); // G
+                    bos.write(0x00); // R
+                } else {
+                    // 白色
+                    bos.write(0xFF); // B
+                    bos.write(0xFF); // G
+                    bos.write(0xFF); // R
+                }
+            }
+            // 填充对齐字节
+            for (int p = 0; p < rowPadding; p++) {
+                bos.write(0x00);
+            }
+        }
+        
+        return bos.toByteArray();
+    }
+    
+    /**
+     * 写入 int 值(小端序)
+     */
+    private static void writeInt(ByteArrayOutputStream bos, int value) {
+        bos.write(value & 0xFF);
+        bos.write((value >> 8) & 0xFF);
+        bos.write((value >> 16) & 0xFF);
+        bos.write((value >> 24) & 0xFF);
+    }
+    
+    /**
+     * 写入 short 值(小端序)
+     */
+    private static void writeShort(ByteArrayOutputStream bos, int value) {
+        bos.write(value & 0xFF);
+        bos.write((value >> 8) & 0xFF);
+    }
+}

+ 59 - 8
entry/src/main/java/com/fujica/abk/utils/Toast.java

@@ -1,31 +1,82 @@
 package com.fujica.abk.utils;
 
-import ohos.agp.window.dialog.CommonDialog;
+import ohos.agp.components.*;
 import ohos.agp.window.dialog.ToastDialog;
 import ohos.app.Context;
-import ohos.eventhandler.EventHandler;
-import ohos.eventhandler.EventRunner;
+import com.fujica.abk.ResourceTable;
 
 public class Toast {
+    
+    public enum ToastType {
+        INFO,
+        SUCCESS,
+        ERROR
+    }
+    
     /**
      * 在主线程显示 Toast
      */
     private static void showOnMainThread(Context context, String message) {
+        showOnMainThread(context, message, ToastType.INFO);
+    }
+    
+    /**
+     * 在主线程显示带类型的 Toast
+     */
+    private static void showOnMainThread(Context context, String message, ToastType type) {
         if (context == null) {
             return;
         }
         // 创建主线程的 EventHandler
         DialogUtil.postTask(() -> {
-            new ToastDialog(context).setText(message).show();
+            // 使用自定义布局
+            Component toastLayout = LayoutScatter.getInstance(context)
+                    .parse(ResourceTable.Layout_layout_custom_toast, null, false);
+            
+            // 设置 Toast 文本
+            Text toastText = (Text) toastLayout.findComponentById(ResourceTable.Id_toast_text);
+            if (toastText != null) {
+                toastText.setText(message);
+            }
+            
+            // 根据类型设置图标(可选)
+            Image toastIcon = (Image) toastLayout.findComponentById(ResourceTable.Id_toast_icon);
+            if (toastIcon != null) {
+                switch (type) {
+                    case SUCCESS:
+                        // toastIcon.setPixelMap(ResourceTable.Media_icon); // 设置成功图标
+                        // toastIcon.setVisibility(Component.VISIBLE);
+                        break;
+                    case ERROR:
+                        // toastIcon.setPixelMap(ResourceTable.Media_icon); // 设置错误图标
+                        // toastIcon.setVisibility(Component.VISIBLE);
+                        break;
+                    case INFO:
+                    default:
+                        toastIcon.setVisibility(Component.HIDE);
+                        break;
+                }
+            }
+            
+            // 创建并显示 ToastDialog
+            ToastDialog toastDialog = new ToastDialog(context);
+            toastDialog.setAlignment(TableLayout.Alignment.ALIGNMENT_TOP);
+            toastDialog.setComponent(toastLayout);
+            toastDialog.setDuration(2000); // 显示2秒
+            toastDialog.show();
         });
     }
-    
+
     public static void info(Context context, String message) {
-        showOnMainThread(context, message);
+        showOnMainThread(context, message, ToastType.INFO);
     }
-    
+
+    public static void success(Context context, String message) {
+        showOnMainThread(context, message, ToastType.SUCCESS);
+    }
+
     public static void error(Context context, String message) {
-        showOnMainThread(context, message);
+        showOnMainThread(context, message, ToastType.ERROR);
     }
 }
 

+ 1 - 1
entry/src/main/java/com/fujica/abk/utils/api.java

@@ -123,7 +123,7 @@ public class api {
      */
     public static <T> CompletableFuture<R<T>> http(Context context, ApiOption option, TypeToken<R<T>> dataClass) {
         String jsonData = option.getData() != null ? objectToJson(option.getData()) : "";
-        Log.error("请求:" + option.getUrl() + " 参数:" + jsonData);
+        Log.error("请求:" + option.getUrl());
 
         // 显示Loading:默认显示,只有当hideLoading!=null && hideLoading==false时才不显示
 

+ 39 - 0
entry/src/main/js/jsability/pages/index/index.css

@@ -0,0 +1,39 @@
+.container {
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    align-items: center;
+    width: 100%;
+    height: 100%;
+    background-color: #f5f5f5;
+}
+
+.title {
+    font-size: 48px;
+    color: #1a1a1a;
+    margin-bottom: 20px;
+    font-weight: bold;
+}
+
+.message {
+    font-size: 32px;
+    color: #333333;
+    margin-bottom: 16px;
+}
+
+.data {
+    font-size: 28px;
+    color: #666666;
+    margin-bottom: 40px;
+}
+
+.button {
+    width: 400px;
+    height: 80px;
+    font-size: 32px;
+    background-color: #007dff;
+    color: #ffffff;
+    border-radius: 8px;
+    margin-top: 20px;
+}
+

+ 8 - 0
entry/src/main/js/jsability/pages/index/index.hml

@@ -0,0 +1,8 @@
+<div class="container">
+    <text class="title">JS Ability 页面</text>
+    <text class="message">{{ message }}</text>
+    <text class="data">接收到的数据: {{ receivedData }}</text>
+    <input class="button" type="button" value="返回数据给 Java" onclick="returnData"></input>
+    <input class="button" type="button" value="关闭页面" onclick="closePage"></input>
+</div>
+

+ 84 - 0
entry/src/main/js/jsability/pages/index/index.js

@@ -0,0 +1,84 @@
+import router from '@system.router';
+import featureAbility from '@ohos.ability.featureAbility';
+
+export default {
+    data: {
+        message: '欢迎来到 JS Ability',
+        receivedData: '无'
+    },
+    onInit() {
+        console.info('JS Ability onInit');
+        // 获取从 Java Ability 传递过来的参数
+        this.getIntentParams();
+    },
+    onShow() {
+        console.info('JS Ability onShow');
+    },
+    onHide() {
+        console.info('JS Ability onHide');
+    },
+    onDestroy() {
+        console.info('JS Ability onDestroy');
+    },
+    
+    // 获取 Intent 参数
+    getIntentParams() {
+        var context = featureAbility.getContext();
+        context.getWant((error, want) => {
+            if (error) {
+                console.error('获取 Intent 参数失败: ' + JSON.stringify(error));
+                return;
+            }
+            console.info('获取到的 Want: ' + JSON.stringify(want));
+            
+            // 获取传递的参数
+            if (want.parameters) {
+                var dataFromJava = want.parameters.data;
+                var messageFromJava = want.parameters.message;
+                
+                if (dataFromJava) {
+                    this.receivedData = dataFromJava;
+                }
+                if (messageFromJava) {
+                    this.message = messageFromJava;
+                }
+            }
+        });
+    },
+    
+    // 返回数据给 Java Ability
+    returnData() {
+        var result = {
+            resultCode: 1,
+            want: {
+                parameters: {
+                    status: 'success',
+                    data: 'JS Ability 返回的数据',
+                    timestamp: new Date().getTime()
+                }
+            }
+        };
+        
+        var context = featureAbility.getContext();
+        context.terminateSelfWithResult(result, (error) => {
+            if (error) {
+                console.error('返回数据失败: ' + JSON.stringify(error));
+            } else {
+                console.info('成功返回数据并关闭页面');
+            }
+        });
+    },
+    
+    // 关闭页面
+    closePage() {
+        var context = featureAbility.getContext();
+        context.terminateSelf((error) => {
+            if (error) {
+                console.error('关闭页面失败: ' + JSON.stringify(error));
+            } else {
+                console.info('成功关闭页面');
+            }
+        });
+    }
+}
+

BIN
entry/src/main/js/widget/common/app_icon.png


BIN
entry/src/main/js/widget/common/ic_default_image@3x.png


BIN
entry/src/main/js/widget/common/refresh.png


+ 1 - 2
entry/src/main/js/widget/i18n/en-US.json

@@ -1,6 +1,5 @@
 {
   "strings": {
-    "title": "Today's delicious food",
-    "detail": "A bowl of fragrant fried noodles, back to childhood memories"
+    "title": "爱泊客"
   }
 }

+ 1 - 2
entry/src/main/js/widget/i18n/zh-CN.json

@@ -1,6 +1,5 @@
 {
   "strings": {
-    "title": "爱泊客",
-    "detail": "富士只能大厦停车场"
+    "title": "爱泊客"
   }
 }

+ 43 - 46
entry/src/main/js/widget/pages/index/index.css

@@ -1,61 +1,58 @@
 .container {
-    flex-direction: column;
+    background-color: #525252;
+    flex-direction: row;
     justify-content: center;
     align-items: center;
+    padding: 10px;
 }
-.bg-img{
-    flex-shrink: 0;
-    height: 100%;
-}
-.container-inner {
+.left {
     flex-direction: column;
-    justify-content: flex-end;
-    align-items: flex-start;
+}
+.right{
     height: 100%;
-    width: 100%;
-    padding: 12px;
+    width: 82px;
+    display: flex;
+    align-items: center;
+    margin-left: 10px;
+}
+.bg-img{
+    width: 80px;
+    height: 80px;
+    background-image: url("/common/refresh.png");
+    background-size: contain;
+    background-position: center;
+    background-repeat: no-repeat;
+}
+.line1{
+    display: flex;
+    flex-direction: row;
+    margin: 2px 0;
+}
+.logo{
+    height: 20px;
+    width: 20px;
+    background-image: url("/common/app_icon.png");
+    background-size: contain;
+    background-position: center;
+    background-repeat: no-repeat;
 }
 .title {
-    font-size: 19px;
+    margin-left: 5px;
+    font-size: 10px;
+    color: white;
+}
+.line2 {
+    margin-top: 20%;
     font-weight: bold;
+    font-size: 13px;
     color: white;
     text-overflow: ellipsis;
     max-lines: 1;
 }
-.detail_text {
-    font-size: 16px;
-    color: white;
-    opacity: 0.66;
+.line3 {
+    margin-top: 10%;
+    font-size: 10px;
+    color: #9e9e9e;
     text-overflow: ellipsis;
     max-lines: 1;
-    margin-top: 6px;
-}
-@media (device-type: tablet) {
-    .bg-img {
-        object-fit: fill;
-    }
-}
-@media (device-type: wearable) {
-    .container-inner {
-        justify-content: center;
-        align-items: center;
-        margin: 40px 26px;
-        padding: 0;
-    }
-    .title {
-        text-align: center;
-    }
-    .detail_text {
-        max-lines: 2;
-        text-align: center;
-    }
-}
-
-@media (device-type: tv) {
-    .title {
-        font-size: 16px;
-    }
-    .detail_text {
-        font-size: 12px;
-    }
-}
+}

+ 13 - 9
entry/src/main/js/widget/pages/index/index.hml

@@ -1,11 +1,15 @@
-<div class="container">
-    <stack>
-        <div class="container-img">
-            <image src="/common/ic_default_image@3x.png" class="bg-img" onclick="routerEvent"></image>
+<div class="container" onclick="routerEvent">
+    <div class="left">
+        <div class="line1">
+            <div class="logo"></div>
+            <text class="title" > {{ $t('strings.title') }}</text>
         </div>
-        <div class="container-inner">
-            <text class="title">{{ $t('strings.title') }}</text>
-            <text class="detail_text"> {{ $t('strings.detail') }}</text>
-        </div>
-    </stack>
+
+        <text class="line2"> {{line2}}</text>
+
+        <text class="line3"> {{line3}}</text>
+    </div>
+    <div class="right" onclick="messageEvent">
+        <div class="bg-img"></div>
+    </div>
 </div>

+ 8 - 3
entry/src/main/js/widget/pages/index/index.json

@@ -1,8 +1,7 @@
 {
   "data": {
-    "title": "Title",
-    "detail": "Text",
-    "iconTitle": "Picture"
+    "line2": "爱泊客停车无忧",
+    "line3": "自助缴费 便捷立场"
   },
   "actions": {
     "routerEvent": {
@@ -12,6 +11,12 @@
       "params": {
         "message": "add detail"
       }
+    },
+    "messageEvent": {
+      "action": "message",
+      "params": {
+        "message": "weather update"
+      }
     }
   }
 }

+ 0 - 11
entry/src/main/js/widget/pages/index/index1.hml

@@ -1,11 +0,0 @@
-<div class="container">
-    <stack>
-        <div class="container-img">
-            <image src="/common/ic_default_image@3x.png" class="bg-img" onclick="routerEvent"></image>
-        </div>
-        <div class="container-inner">
-            <text class="title">{{ $t('strings.title') }}</text>
-            <text class="detail_text"> {{ $t('strings.detail') }}</text>
-        </div>
-    </stack>
-</div>

+ 1 - 1
entry/src/main/js/widget1/i18n/zh-CN.json

@@ -1,6 +1,6 @@
 {
   "strings": {
     "title": "爱泊客",
-    "detail": "富士能大厦停车场"
+    "detail": "富士能大厦停车场"
   }
 }

+ 20 - 0
entry/src/main/resources/base/graphic/background_toast.xml

@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:ohos="http://schemas.huawei.com/res/ohos"
+    ohos:shape="rectangle">
+    
+    <!-- 圆角 -->
+    <corners
+        ohos:radius="8vp"/>
+    
+    <!-- 背景颜色(半透明黑色) -->
+    <solid
+        ohos:color="#CC000000"/>
+    
+    <!-- 可选:添加边框 -->
+    <!--
+    <stroke
+        ohos:width="1vp"
+        ohos:color="#80FFFFFF"/>
+    -->
+</shape>
+

+ 203 - 204
entry/src/main/resources/base/layout/ability_main.xml

@@ -3,7 +3,7 @@
     xmlns:ohos="http://schemas.huawei.com/res/ohos"
     ohos:height="match_parent"
     ohos:width="match_parent"
-    ohos:background_element="$media:bg"
+    ohos:background_element="#404040"
     ohos:orientation="horizontal">
 
     <PositionLayout
@@ -28,225 +28,224 @@
             ohos:width="match_content"
             ohos:orientation="horizontal">
 
-        <DirectionalLayout
-            ohos:id="$+id:main_left"
-            ohos:height="match_parent"
-            ohos:width="400vp"
-            ohos:orientation="vertical">
-
             <DirectionalLayout
-                ohos:height="40vp"
-                ohos:width="match_parent"
-                ohos:alignment="left"
-                ohos:background_element="$graphic:container_top"
-                ohos:end_padding="16vp"
-                ohos:orientation="horizontal"
-                ohos:start_padding="16vp">
+                ohos:id="$+id:main_left"
+                ohos:height="match_parent"
+                ohos:width="400vp"
+                ohos:orientation="vertical">
 
                 <DirectionalLayout
-                    ohos:height="match_content"
+                    ohos:height="40vp"
                     ohos:width="match_parent"
                     ohos:alignment="left"
-                    ohos:layout_alignment="center"
-                    ohos:orientation="horizontal">
-
-                    <Image
-                        ohos:height="25vp"
-                        ohos:width="25vp"
-                        ohos:image_src="$media:logo_white"
-                        ohos:right_margin="10vp"
-                        ohos:scale_mode="stretch"
-                        ></Image>
-
-                    <!-- 标题文字 -->
-                    <Text
-                        ohos:id="$+id:title_text"
-                        ohos:height="match_content"
-                        ohos:width="0"
-                        ohos:layout_alignment="vertical_center"
-                        ohos:text="爱泊客.停车缴费"
-                        ohos:text_color="#FFFFFFFF"
-                        ohos:text_size="14fp"
-                        ohos:text_weight="600"
-                        ohos:weight="1"/>
-
-                    <Image
-                        ohos:id="$+id:quit"
-                        ohos:height="25vp"
-                        ohos:width="25vp"
-                        ohos:image_src="$media:logout"
-                        ohos:scale_mode="stretch"
-
-                        ></Image>
-
-                </DirectionalLayout>
-            </DirectionalLayout>
+                    ohos:background_element="$graphic:container_top"
+                    ohos:end_padding="16vp"
+                    ohos:orientation="horizontal"
+                    ohos:start_padding="16vp">
 
-            <!-- 页面容器 - 使用StackLayout堆叠显示 -->
-            <StackLayout
-                ohos:id="$+id:page_container"
-                ohos:height="0vp"
-                ohos:width="match_parent"
-                ohos:background_element="$graphic:container_body"
-                ohos:bottom_padding="10vp"
-                ohos:left_padding="1vp"
-                ohos:right_padding="1vp"
-                ohos:weight="1">
-                <!-- 三个页面组件将动态添加到这里 -->
-            </StackLayout>
-
-            <!-- 底部导航栏 -->
-            <DirectionalLayout
-                ohos:height="64vp"
-                ohos:width="match_parent"
-                ohos:background_element="$graphic:container_bottom"
-                ohos:bottom_padding="8vp"
-                ohos:orientation="horizontal"
-                ohos:top_margin="8vp"
-                ohos:top_padding="8vp">
-
-                <!-- 找车位 -->
-                <DirectionalLayout
-                    ohos:id="$+id:nav_find_parking"
-                    ohos:height="match_parent"
-                    ohos:width="0vp"
-                    ohos:alignment="center"
-                    ohos:orientation="vertical"
-                    ohos:weight="1">
-
-                    <Image
-                        ohos:id="$+id:icon_park"
-                        ohos:height="24vp"
-                        ohos:width="24vp"
-                        ohos:bottom_margin="4vp"
-                        ohos:image_src="$media:park"
-                        ohos:scale_mode="stretch"
-                        ohos:visibility="hide"/>
-
-                    <Image
-                        ohos:id="$+id:icon_park_1"
-                        ohos:height="24vp"
-                        ohos:width="24vp"
-                        ohos:bottom_margin="4vp"
-                        ohos:image_src="$media:park_1"
-                        ohos:scale_mode="stretch"/>
-
-                    <Text
-                        ohos:id="$+id:text_park"
+                    <DirectionalLayout
                         ohos:height="match_content"
-                        ohos:width="match_content"
-                        ohos:text="找车位"
-                        ohos:text_color="#FA6332"
-                        ohos:text_size="12fp"/>
+                        ohos:width="match_parent"
+                        ohos:alignment="left"
+                        ohos:layout_alignment="center"
+                        ohos:orientation="horizontal">
+
+                        <Image
+                            ohos:height="25vp"
+                            ohos:width="25vp"
+                            ohos:image_src="$media:logo_white"
+                            ohos:right_margin="10vp"
+                            ohos:scale_mode="stretch"
+                            ></Image>
+
+                        <!-- 标题文字 -->
+                        <Text
+                            ohos:id="$+id:title_text"
+                            ohos:height="match_content"
+                            ohos:width="0"
+                            ohos:layout_alignment="vertical_center"
+                            ohos:text="爱泊客.停车缴费"
+                            ohos:text_color="#FFFFFFFF"
+                            ohos:text_size="14fp"
+                            ohos:text_weight="600"
+                            ohos:weight="1"/>
+
+                        <Image
+                            ohos:id="$+id:quit"
+                            ohos:height="25vp"
+                            ohos:width="25vp"
+                            ohos:image_src="$media:logout"
+                            ohos:scale_mode="stretch"
+
+                            ></Image>
+
+                    </DirectionalLayout>
                 </DirectionalLayout>
 
-                <!-- 我的 -->
-                <DirectionalLayout
-                    ohos:id="$+id:nav_charge"
-                    ohos:height="match_parent"
-                    ohos:width="0vp"
-                    ohos:alignment="center"
-                    ohos:orientation="vertical"
+                <!-- 页面容器 - 使用StackLayout堆叠显示 -->
+                <StackLayout
+                    ohos:id="$+id:page_container"
+                    ohos:height="0vp"
+                    ohos:width="match_parent"
+                    ohos:background_element="$graphic:container_body"
+                    ohos:bottom_padding="10vp"
+                    ohos:left_padding="1vp"
+                    ohos:right_padding="1vp"
                     ohos:weight="1">
+                    <!-- 三个页面组件将动态添加到这里 -->
+                </StackLayout>
 
-                    <Image
-                        ohos:id="$+id:icon_charge"
-                        ohos:height="24vp"
-                        ohos:width="24vp"
-                        ohos:bottom_margin="4vp"
-                        ohos:image_src="$media:charge"
-                        ohos:scale_mode="stretch"/>
-
-                    <Image
-                        ohos:id="$+id:icon_charge_1"
-                        ohos:height="24vp"
-                        ohos:width="24vp"
-                        ohos:bottom_margin="4vp"
-                        ohos:image_src="$media:charge_1"
-                        ohos:scale_mode="stretch"
-                        ohos:visibility="hide"/>
-
-                    <Text
-                        ohos:id="$+id:text_charge"
-                        ohos:height="match_content"
-                        ohos:width="match_content"
-                        ohos:text="缴费"
-                        ohos:text_color="#FF666666"
-                        ohos:text_size="12fp"/>
-                </DirectionalLayout>
-
-                <!-- 缴费记录 -->
+                <!-- 底部导航栏 -->
                 <DirectionalLayout
-                    ohos:id="$+id:nav_order"
-                    ohos:height="match_parent"
-                    ohos:width="0vp"
-                    ohos:alignment="center"
-                    ohos:orientation="vertical"
-                    ohos:weight="1">
-
-                    <Image
-                        ohos:id="$+id:icon_order"
-                        ohos:height="24vp"
-                        ohos:width="24vp"
-                        ohos:bottom_margin="4vp"
-                        ohos:image_src="$media:order"
-                        ohos:scale_mode="stretch"/>
-
-                    <Image
-                        ohos:id="$+id:icon_order_1"
-                        ohos:height="24vp"
-                        ohos:width="24vp"
-                        ohos:bottom_margin="4vp"
-                        ohos:image_src="$media:order_1"
-                        ohos:scale_mode="stretch"
-                        ohos:visibility="hide"/>
-
-                    <Text
-                        ohos:id="$+id:text_order"
-                        ohos:height="match_content"
-                        ohos:width="match_content"
-                        ohos:text="缴费记录"
-                        ohos:text_color="#FF666666"
-                        ohos:text_size="12fp"/>
+                    ohos:height="64vp"
+                    ohos:width="match_parent"
+                    ohos:background_element="$graphic:container_bottom"
+                    ohos:bottom_padding="8vp"
+                    ohos:orientation="horizontal"
+                    ohos:top_margin="8vp"
+                    ohos:top_padding="8vp">
+
+                    <!-- 找车位 -->
+                    <DirectionalLayout
+                        ohos:id="$+id:nav_find_parking"
+                        ohos:height="match_parent"
+                        ohos:width="0vp"
+                        ohos:alignment="center"
+                        ohos:orientation="vertical"
+                        ohos:weight="1">
+
+                        <Image
+                            ohos:id="$+id:icon_park"
+                            ohos:height="24vp"
+                            ohos:width="24vp"
+                            ohos:bottom_margin="4vp"
+                            ohos:image_src="$media:park"
+                            ohos:scale_mode="stretch"
+                            ohos:visibility="hide"/>
+
+                        <Image
+                            ohos:id="$+id:icon_park_1"
+                            ohos:height="24vp"
+                            ohos:width="24vp"
+                            ohos:bottom_margin="4vp"
+                            ohos:image_src="$media:park_1"
+                            ohos:scale_mode="stretch"/>
+
+                        <Text
+                            ohos:id="$+id:text_park"
+                            ohos:height="match_content"
+                            ohos:width="match_content"
+                            ohos:text="找车位"
+                            ohos:text_color="#FA6332"
+                            ohos:text_size="12fp"/>
+                    </DirectionalLayout>
+
+                    <!-- 我的 -->
+                    <DirectionalLayout
+                        ohos:id="$+id:nav_charge"
+                        ohos:height="match_parent"
+                        ohos:width="0vp"
+                        ohos:alignment="center"
+                        ohos:orientation="vertical"
+                        ohos:weight="1">
+
+                        <Image
+                            ohos:id="$+id:icon_charge"
+                            ohos:height="24vp"
+                            ohos:width="24vp"
+                            ohos:bottom_margin="4vp"
+                            ohos:image_src="$media:charge"
+                            ohos:scale_mode="stretch"/>
+
+                        <Image
+                            ohos:id="$+id:icon_charge_1"
+                            ohos:height="24vp"
+                            ohos:width="24vp"
+                            ohos:bottom_margin="4vp"
+                            ohos:image_src="$media:charge_1"
+                            ohos:scale_mode="stretch"
+                            ohos:visibility="hide"/>
+
+                        <Text
+                            ohos:id="$+id:text_charge"
+                            ohos:height="match_content"
+                            ohos:width="match_content"
+                            ohos:text="缴费"
+                            ohos:text_color="#FF666666"
+                            ohos:text_size="12fp"/>
+                    </DirectionalLayout>
+
+                    <!-- 缴费记录 -->
+                    <DirectionalLayout
+                        ohos:id="$+id:nav_order"
+                        ohos:height="match_parent"
+                        ohos:width="0vp"
+                        ohos:alignment="center"
+                        ohos:orientation="vertical"
+                        ohos:weight="1">
+
+                        <Image
+                            ohos:id="$+id:icon_order"
+                            ohos:height="24vp"
+                            ohos:width="24vp"
+                            ohos:bottom_margin="4vp"
+                            ohos:image_src="$media:order"
+                            ohos:scale_mode="stretch"/>
+
+                        <Image
+                            ohos:id="$+id:icon_order_1"
+                            ohos:height="24vp"
+                            ohos:width="24vp"
+                            ohos:bottom_margin="4vp"
+                            ohos:image_src="$media:order_1"
+                            ohos:scale_mode="stretch"
+                            ohos:visibility="hide"/>
+
+                        <Text
+                            ohos:id="$+id:text_order"
+                            ohos:height="match_content"
+                            ohos:width="match_content"
+                            ohos:text="缴费记录"
+                            ohos:text_color="#FF666666"
+                            ohos:text_size="12fp"/>
+                    </DirectionalLayout>
+
+                    <!-- 当前位置 -->
+                    <DirectionalLayout
+                        ohos:id="$+id:nav_current_location"
+                        ohos:height="match_parent"
+                        ohos:width="0vp"
+                        ohos:alignment="center"
+                        ohos:orientation="vertical"
+                        ohos:weight="1">
+
+                        <Image
+                            ohos:id="$+id:icon_current_location"
+                            ohos:height="24vp"
+                            ohos:width="24vp"
+                            ohos:bottom_margin="4vp"
+                            ohos:image_src="$media:location"
+                            ohos:scale_mode="stretch"/>
+
+                        <Text
+                            ohos:id="$+id:text_current_location"
+                            ohos:height="match_content"
+                            ohos:width="match_content"
+                            ohos:text="当前位置"
+                            ohos:text_color="#FF666666"
+                            ohos:text_size="12fp"/>
+                    </DirectionalLayout>
                 </DirectionalLayout>
 
-                <!-- 当前位置 -->
-                <DirectionalLayout
-                    ohos:id="$+id:nav_current_location"
-                    ohos:height="match_parent"
-                    ohos:width="0vp"
-                    ohos:alignment="center"
-                    ohos:orientation="vertical"
-                    ohos:weight="1">
-
-                    <Image
-                        ohos:id="$+id:icon_current_location"
-                        ohos:height="24vp"
-                        ohos:width="24vp"
-                        ohos:bottom_margin="4vp"
-                        ohos:image_src="$media:location"
-                        ohos:scale_mode="stretch"/>
-
-                    <Text
-                        ohos:id="$+id:text_current_location"
-                        ohos:height="match_content"
-                        ohos:width="match_content"
-                        ohos:text="当前位置"
-                        ohos:text_color="#FF666666"
-                        ohos:text_size="12fp"/>
-                </DirectionalLayout>
+                <Button
+                    ohos:id="$+id:btn_hwid_sign_in"
+                    ohos:height="60vp"
+                    ohos:width="match_parent"
+                    ohos:layout_alignment="right|horizontal_center"
+                    ohos:text="华为账号登录"
+                    ohos:visibility="hide"></Button>
             </DirectionalLayout>
 
-            <Button
-                ohos:id="$+id:btn_hwid_sign_in"
-                ohos:height="60vp"
-                ohos:width="match_parent"
-                ohos:layout_alignment="right|horizontal_center"
-                ohos:text="华为账号登录"
-                ohos:visibility="hide"></Button>
-        </DirectionalLayout>
-
-
             <!-- Loading组件放在最后,确保在最上层显示 -->
             <com.fujica.abk.component.LoadingComponent
                 ohos:id="$+id:loading_component"

+ 67 - 0
entry/src/main/resources/base/layout/dialog_pay_fail.xml

@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<DirectionalLayout
+    xmlns:ohos="http://schemas.huawei.com/res/ohos"
+    ohos:height="match_parent"
+    ohos:width="match_parent"
+    ohos:alignment="center"
+    ohos:orientation="vertical"
+    ohos:background_element="#99000000">
+    <!-- 半透明黑色背景 -->
+
+    <!-- 对话框内容容器(白色圆角卡片) -->
+    <DirectionalLayout
+        ohos:height="match_content"
+        ohos:width="320vp"
+        ohos:orientation="vertical"
+        ohos:alignment="center"
+        ohos:background_element="$graphic:background_circle_16"
+        ohos:padding="32vp">
+
+        <!-- 失败图标 -->
+        <Text
+            ohos:height="64vp"
+            ohos:width="64vp"
+            ohos:text="✕"
+            ohos:text_size="48fp"
+            ohos:text_color="#FFFF3333"
+            ohos:text_alignment="center"
+            ohos:text_weight="700"/>
+
+        <!-- 标题 -->
+        <Text
+            ohos:height="match_content"
+            ohos:width="match_parent"
+            ohos:text="支付失败"
+            ohos:text_size="20fp"
+            ohos:text_color="#FF333333"
+            ohos:text_weight="700"
+            ohos:text_alignment="center"
+            ohos:top_margin="16vp"/>
+
+        <!-- 错误信息 -->
+        <Text
+            ohos:id="$+id:txt_error_msg"
+            ohos:height="match_content"
+            ohos:width="match_parent"
+            ohos:text="支付失败,请重试"
+            ohos:text_size="14fp"
+            ohos:text_color="#FF666666"
+            ohos:text_alignment="center"
+            ohos:top_margin="16vp"
+            ohos:multiple_lines="true"/>
+
+        <!-- 确认按钮 -->
+        <Button
+            ohos:id="$+id:btn_confirm"
+            ohos:height="44vp"
+            ohos:width="match_parent"
+            ohos:text="确定"
+            ohos:text_size="16fp"
+            ohos:text_color="#FFFFFFFF"
+            ohos:background_element="$graphic:button"
+            ohos:top_margin="32vp"/>
+
+    </DirectionalLayout>
+
+</DirectionalLayout>
+

+ 83 - 0
entry/src/main/resources/base/layout/dialog_pay_success.xml

@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="utf-8"?>
+<DirectionalLayout
+    xmlns:ohos="http://schemas.huawei.com/res/ohos"
+    ohos:height="match_parent"
+    ohos:width="match_parent"
+    ohos:alignment="center"
+    ohos:orientation="vertical"
+    ohos:background_element="#99000000">
+    <!-- 半透明黑色背景 -->
+
+    <!-- 对话框内容容器(白色圆角卡片) -->
+    <DirectionalLayout
+        ohos:height="match_content"
+        ohos:width="320vp"
+        ohos:orientation="vertical"
+        ohos:alignment="center"
+        ohos:background_element="$graphic:background_circle_16"
+        ohos:padding="32vp">
+
+        <!-- 成功图标 -->
+        <Text
+            ohos:height="64vp"
+            ohos:width="64vp"
+            ohos:text="✓"
+            ohos:text_size="48fp"
+            ohos:text_color="#FF00CC66"
+            ohos:text_alignment="center"
+            ohos:text_weight="700"/>
+
+        <!-- 标题 -->
+        <Text
+            ohos:height="match_content"
+            ohos:width="match_parent"
+            ohos:text="支付成功"
+            ohos:text_size="20fp"
+            ohos:text_color="#FF333333"
+            ohos:text_weight="700"
+            ohos:text_alignment="center"
+            ohos:top_margin="16vp"/>
+
+        <!-- 金额容器 -->
+        <DirectionalLayout
+            ohos:height="match_content"
+            ohos:width="match_parent"
+            ohos:orientation="horizontal"
+            ohos:alignment="center"
+            ohos:top_margin="24vp">
+
+            <Text
+                ohos:height="match_content"
+                ohos:width="match_content"
+                ohos:text="¥"
+                ohos:text_size="24fp"
+                ohos:text_color="#FFFF6600"
+                ohos:text_weight="700"/>
+
+            <Text
+                ohos:id="$+id:txt_pay_amount"
+                ohos:height="match_content"
+                ohos:width="match_content"
+                ohos:text="0.00"
+                ohos:text_size="32fp"
+                ohos:text_color="#FFFF6600"
+                ohos:text_weight="700"
+                ohos:left_margin="4vp"/>
+
+        </DirectionalLayout>
+
+        <!-- 确认按钮 -->
+        <Button
+            ohos:id="$+id:btn_confirm"
+            ohos:height="44vp"
+            ohos:width="match_parent"
+            ohos:text="确定"
+            ohos:text_size="16fp"
+            ohos:text_color="#FFFFFFFF"
+            ohos:background_element="$graphic:button"
+            ohos:top_margin="32vp"/>
+
+    </DirectionalLayout>
+
+</DirectionalLayout>
+

+ 33 - 0
entry/src/main/resources/base/layout/layout_custom_toast.xml

@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<DirectionalLayout
+    xmlns:ohos="http://schemas.huawei.com/res/ohos"
+    ohos:width="match_content"
+    ohos:height="match_content"
+    ohos:orientation="horizontal"
+    ohos:padding="16vp"
+    ohos:background_element="$graphic:background_toast"
+    ohos:alignment="center">
+
+    <!-- Toast 图标 (可选) -->
+    <Image
+        ohos:id="$+id:toast_icon"
+        ohos:width="24vp"
+        ohos:height="24vp"
+        ohos:right_margin="8vp"
+        ohos:visibility="hide"
+        ohos:image_src="$media:icon"/>
+
+    <!-- Toast 文本 -->
+    <Text
+        ohos:id="$+id:toast_text"
+        ohos:width="match_content"
+        ohos:height="match_content"
+        ohos:text="Toast 消息"
+        ohos:text_size="16fp"
+        ohos:text_color="#FFFFFF"
+        ohos:max_width="300vp"
+        ohos:multiple_lines="true"
+        ohos:text_alignment="center"/>
+
+</DirectionalLayout>
+

+ 84 - 0
entry/src/main/resources/base/layout/layout_input_dialog.xml

@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="utf-8"?>
+<DirectionalLayout
+    xmlns:ohos="http://schemas.huawei.com/res/ohos"
+    ohos:height="match_parent"
+    ohos:width="match_parent"
+    ohos:alignment="center"
+    ohos:orientation="vertical"
+    ohos:background_element="#80000000">
+    <!-- 半透明黑色背景 -->
+
+    <!-- 对话框内容容器(白色圆角卡片) -->
+    <DirectionalLayout
+        ohos:id="$+id:input_dialog_container"
+        ohos:height="match_content"
+        ohos:width="280vp"
+        ohos:orientation="vertical"
+        ohos:background_element="$graphic:background_circle_16"
+        ohos:padding="24vp">
+
+        <!-- 标题 -->
+        <Text
+            ohos:height="match_content"
+            ohos:width="match_parent"
+            ohos:text="手动输入"
+            ohos:text_size="18fp"
+            ohos:text_color="#FF666666"
+            ohos:text_weight="700"
+            ohos:text_alignment="center"
+            ohos:margin="0vp"/>
+
+        <!-- 输入框 -->
+        <TextField
+            ohos:id="$+id:input_field"
+            ohos:height="44vp"
+            ohos:width="match_parent"
+            ohos:hint="请输入二维码内容"
+            ohos:text_size="15fp"
+            ohos:text_color="#FF333333"
+            ohos:hint_color="#FFCCCCCC"
+            ohos:top_margin="16vp"
+            ohos:left_padding="12vp"
+            ohos:right_padding="12vp"
+            ohos:top_padding="8vp"
+            ohos:bottom_padding="8vp"
+            ohos:background_element="$graphic:background_filter_item"/>
+
+        <!-- 按钮容器 -->
+        <DirectionalLayout
+            ohos:height="match_content"
+            ohos:width="match_parent"
+            ohos:orientation="horizontal"
+            ohos:top_margin="24vp"
+            ohos:alignment="center">
+
+            <!-- 取消按钮(左边) -->
+            <Button
+                ohos:id="$+id:btn_cancel_input"
+                ohos:height="40vp"
+                ohos:width="0vp"
+                ohos:weight="1"
+                ohos:text="取消"
+                ohos:text_size="15fp"
+                ohos:text_color="#FFFFFFFF"
+                ohos:background_element="$graphic:button_cancel"
+                ohos:right_margin="8vp"/>
+
+            <!-- 确定按钮(右边) -->
+            <Button
+                ohos:id="$+id:btn_confirm"
+                ohos:height="40vp"
+                ohos:width="0vp"
+                ohos:weight="1"
+                ohos:text="确定"
+                ohos:text_size="15fp"
+                ohos:text_color="#FFFFFFFF"
+                ohos:background_element="$graphic:button"
+                ohos:left_margin="8vp"/>
+
+        </DirectionalLayout>
+
+    </DirectionalLayout>
+
+</DirectionalLayout>
+

+ 388 - 0
entry/src/main/resources/base/layout/layout_pay_detail_dialog.xml

@@ -0,0 +1,388 @@
+<?xml version="1.0" encoding="utf-8"?>
+<DirectionalLayout
+    xmlns:ohos="http://schemas.huawei.com/res/ohos"
+    ohos:height="match_parent"
+    ohos:width="match_parent"
+    ohos:alignment="center"
+    ohos:background_element="#99000000">
+
+    <!-- 半透明背景 -->
+
+    <!-- 弹框内容容器 -->
+    <DirectionalLayout
+        ohos:height="match_content"
+        ohos:width="320vp"
+        ohos:layout_alignment="center"
+        ohos:alignment="center"
+        ohos:background_element="$graphic:background_circle_16"
+        ohos:orientation="vertical">
+
+        <!-- 顶部关闭按钮区域 -->
+        <DirectionalLayout
+            ohos:height="match_content"
+            ohos:width="match_parent"
+            ohos:alignment="right"
+            ohos:bottom_padding="0vp"
+            ohos:orientation="horizontal">
+
+            <Image
+                ohos:top_margin="12vp"
+                ohos:right_margin="12vp"
+                ohos:id="$+id:btn_close_dialog"
+                ohos:height="24vp"
+                ohos:width="24vp"
+                ohos:clickable="true"
+                ohos:image_src="$media:close"
+                ohos:scale_mode="zoom_center"/>
+        </DirectionalLayout>
+
+        <!-- 滚动内容区域 -->
+        <ScrollView
+            ohos:height="0vp"
+            ohos:width="match_parent"
+            ohos:left_padding="16vp"
+            ohos:right_padding="16vp"
+            ohos:bottom_padding="16vp"
+            ohos:top_padding="4vp"
+            ohos:weight="1">
+
+            <DirectionalLayout
+                ohos:height="match_content"
+                ohos:width="match_parent"
+                ohos:orientation="vertical">
+
+                <!-- 车牌号 -->
+                <DirectionalLayout
+                    ohos:height="match_content"
+                    ohos:width="match_parent"
+                    ohos:alignment="center"
+                    ohos:bottom_margin="16vp"
+                    ohos:orientation="vertical">
+
+                    <Text
+                        ohos:id="$+id:pay_detail_plate_no"
+                        ohos:height="match_content"
+                        ohos:width="match_content"
+                        ohos:text="粤B12345"
+                        ohos:text_color="#FF333333"
+                        ohos:text_size="16fp"
+                        ohos:text_weight="700"/>
+                </DirectionalLayout>
+
+                <!-- 停车信息组 -->
+                <DirectionalLayout
+                    ohos:height="match_content"
+                    ohos:width="match_parent"
+                    ohos:bottom_margin="16vp"
+                    ohos:orientation="vertical">
+
+                    <!-- 停车场 -->
+                    <DirectionalLayout
+                        ohos:height="match_content"
+                        ohos:width="match_parent"
+                        ohos:bottom_margin="12vp"
+                        ohos:orientation="horizontal">
+
+                        <Text
+                            ohos:height="match_content"
+                            ohos:width="match_content"
+                            ohos:right_margin="20vp"
+                            ohos:text="停车场"
+                            ohos:text_color="#FF999999"
+                            ohos:text_size="16fp"/>
+
+                        <Text
+                            ohos:id="$+id:pay_detail_park_name"
+                            ohos:height="match_content"
+                            ohos:width="0vp"
+                            ohos:max_text_lines="2"
+                            ohos:text="--"
+                            ohos:text_alignment="right"
+                            ohos:text_color="#FF333333"
+                            ohos:text_size="16fp"
+                            ohos:truncation_mode="ellipsis_at_end"
+                            ohos:weight="1"/>
+                    </DirectionalLayout>
+
+                    <!-- 入场时间 -->
+                    <DirectionalLayout
+                        ohos:height="match_content"
+                        ohos:width="match_parent"
+                        ohos:bottom_margin="12vp"
+                        ohos:orientation="horizontal">
+
+                        <Text
+                            ohos:height="match_content"
+                            ohos:width="match_content"
+                            ohos:right_margin="20vp"
+                            ohos:text="入场时间"
+                            ohos:text_color="#FF999999"
+                            ohos:text_size="16fp"/>
+
+                        <Text
+                            ohos:id="$+id:pay_detail_in_time"
+                            ohos:height="match_content"
+                            ohos:width="0vp"
+                            ohos:text="--"
+                            ohos:text_alignment="right"
+                            ohos:text_color="#FF333333"
+                            ohos:text_size="16fp"
+                            ohos:weight="1"/>
+                    </DirectionalLayout>
+
+                    <!-- 已停时长 -->
+                    <DirectionalLayout
+                        ohos:height="match_content"
+                        ohos:width="match_parent"
+                        ohos:orientation="horizontal">
+
+                        <Text
+                            ohos:height="match_content"
+                            ohos:width="match_content"
+                            ohos:right_margin="20vp"
+                            ohos:text="已停时长"
+                            ohos:text_color="#FF999999"
+                            ohos:text_size="16fp"/>
+
+                        <Text
+                            ohos:id="$+id:pay_detail_stay_time"
+                            ohos:height="match_content"
+                            ohos:width="0vp"
+                            ohos:text="--"
+                            ohos:text_alignment="right"
+                            ohos:text_color="#FF333333"
+                            ohos:text_size="16fp"
+                            ohos:weight="1"/>
+                    </DirectionalLayout>
+
+                </DirectionalLayout>
+
+                <!-- 分隔线 -->
+                <DirectionalLayout
+                    ohos:height="1vp"
+                    ohos:width="match_parent"
+                    ohos:background_element="#FFEEEEEE"
+                    ohos:bottom_margin="16vp"/>
+
+                <!-- 费用信息组 -->
+                <DirectionalLayout
+                    ohos:height="match_content"
+                    ohos:width="match_parent"
+                    ohos:bottom_margin="16vp"
+                    ohos:orientation="vertical">
+
+                    <!-- 停车费 -->
+                    <DirectionalLayout
+                        ohos:height="match_content"
+                        ohos:width="match_parent"
+                        ohos:bottom_margin="12vp"
+                        ohos:orientation="horizontal">
+
+                        <Text
+                            ohos:height="match_content"
+                            ohos:width="match_content"
+                            ohos:right_margin="20vp"
+                            ohos:text="停车费"
+                            ohos:text_color="#FF999999"
+                            ohos:text_size="16fp"/>
+
+                        <Text
+                            ohos:id="$+id:pay_detail_total_amount"
+                            ohos:height="match_content"
+                            ohos:width="0vp"
+                            ohos:text="--"
+                            ohos:text_alignment="right"
+                            ohos:text_color="#FF333333"
+                            ohos:text_size="16fp"
+                            ohos:weight="1"/>
+                    </DirectionalLayout>
+
+                    <!-- 优惠金额 -->
+                    <DirectionalLayout
+                        ohos:id="$+id:layout_discount_amount"
+                        ohos:height="match_content"
+                        ohos:width="match_parent"
+                        ohos:bottom_margin="12vp"
+                        ohos:orientation="horizontal"
+                        ohos:visibility="hide">
+
+                        <Text
+                            ohos:height="match_content"
+                            ohos:width="match_content"
+                            ohos:right_margin="20vp"
+                            ohos:text="优惠金额"
+                            ohos:text_color="#FF999999"
+                            ohos:text_size="16fp"/>
+
+                        <Text
+                            ohos:id="$+id:pay_detail_discount_amount"
+                            ohos:height="match_content"
+                            ohos:width="0vp"
+                            ohos:text="--"
+                            ohos:text_alignment="right"
+                            ohos:text_color="#FFFF6600"
+                            ohos:text_size="16fp"
+                            ohos:weight="1"/>
+                    </DirectionalLayout>
+
+                    <!-- 历史欠费 -->
+                    <DirectionalLayout
+                        ohos:id="$+id:layout_follow_sum"
+                        ohos:height="match_content"
+                        ohos:width="match_parent"
+                        ohos:bottom_margin="12vp"
+                        ohos:orientation="horizontal"
+                        ohos:visibility="hide">
+
+                        <Text
+                            ohos:height="match_content"
+                            ohos:width="match_content"
+                            ohos:right_margin="20vp"
+                            ohos:text="历史欠费"
+                            ohos:text_color="#FF999999"
+                            ohos:text_size="16fp"/>
+
+                        <DirectionalLayout
+                            ohos:height="match_content"
+                            ohos:width="0vp"
+                            ohos:alignment="right"
+                            ohos:orientation="horizontal"
+                            ohos:weight="1">
+
+                            <Text
+                                ohos:id="$+id:pay_detail_follow_sum"
+                                ohos:height="match_content"
+                                ohos:width="match_content"
+                                ohos:right_margin="4vp"
+                                ohos:text="--"
+                                ohos:text_alignment="right"
+                                ohos:text_color="#FF333333"
+                                ohos:text_size="16fp"/>
+
+                            <Image
+                                ohos:height="16vp"
+                                ohos:width="16vp"
+                                ohos:image_src="$media:close"
+                                ohos:scale_mode="zoom_center"/>
+                        </DirectionalLayout>
+                    </DirectionalLayout>
+
+                    <!-- 车位费 -->
+                    <DirectionalLayout
+                        ohos:id="$+id:layout_lot_amount"
+                        ohos:height="match_content"
+                        ohos:width="match_parent"
+                        ohos:orientation="horizontal"
+                        ohos:visibility="hide">
+
+                        <Text
+                            ohos:height="match_content"
+                            ohos:width="match_content"
+                            ohos:right_margin="20vp"
+                            ohos:text="车位费"
+                            ohos:text_color="#FF999999"
+                            ohos:text_size="16fp"/>
+
+                        <DirectionalLayout
+                            ohos:height="match_content"
+                            ohos:width="0vp"
+                            ohos:alignment="right"
+                            ohos:orientation="horizontal"
+                            ohos:weight="1">
+
+                            <Text
+                                ohos:id="$+id:pay_detail_lot_amount"
+                                ohos:height="match_content"
+                                ohos:width="match_content"
+                                ohos:right_margin="4vp"
+                                ohos:text="--"
+                                ohos:text_alignment="right"
+                                ohos:text_color="#FF333333"
+                                ohos:text_size="16fp"/>
+
+                            <Image
+                                ohos:height="16vp"
+                                ohos:width="16vp"
+                                ohos:image_src="$media:close"
+                                ohos:scale_mode="zoom_center"/>
+                        </DirectionalLayout>
+                    </DirectionalLayout>
+
+                </DirectionalLayout>
+
+                <!-- 总计区域 -->
+                <DirectionalLayout
+                    ohos:height="match_content"
+                    ohos:width="match_parent"
+                    ohos:background_element="#FFF5F5F5"
+                    ohos:bottom_margin="12vp"
+                    ohos:orientation="horizontal"
+                    ohos:padding="12vp">
+
+                    <Text
+                        ohos:height="match_content"
+                        ohos:width="match_content"
+                        ohos:right_margin="20vp"
+                        ohos:text="总计"
+                        ohos:text_color="#FF999999"
+                        ohos:text_size="16fp"/>
+
+                    <DirectionalLayout
+                        ohos:height="match_content"
+                        ohos:width="0vp"
+                        ohos:alignment="right"
+                        ohos:orientation="horizontal"
+                        ohos:weight="1">
+
+                        <Text
+                            ohos:height="match_content"
+                            ohos:width="match_content"
+                            ohos:text="¥"
+                            ohos:text_color="#FF333333"
+                            ohos:text_size="18fp"
+                            ohos:text_weight="700"/>
+
+                        <Text
+                            ohos:id="$+id:pay_detail_actual_amount"
+                            ohos:height="match_content"
+                            ohos:width="match_content"
+                            ohos:text="0.00"
+                            ohos:text_alignment="right"
+                            ohos:text_color="#FF333333"
+                            ohos:text_size="20fp"
+                            ohos:text_weight="700"/>
+                    </DirectionalLayout>
+                </DirectionalLayout>
+
+                <!-- 提示信息 -->
+                <Text
+                    ohos:id="$+id:pay_detail_tip"
+                    ohos:height="match_content"
+                    ohos:width="match_parent"
+                    ohos:bottom_margin="16vp"
+                    ohos:text=""
+                    ohos:text_color="#FF999999"
+                    ohos:text_size="12fp"
+                    ohos:visibility="hide"/>
+
+            </DirectionalLayout>
+
+        </ScrollView>
+
+        <!-- 底部支付按钮 -->
+        <Button
+            ohos:id="$+id:btn_pay"
+            ohos:height="44vp"
+            ohos:width="match_parent"
+            ohos:background_element="$graphic:button"
+            ohos:bottom_margin="16vp"
+            ohos:left_margin="16vp"
+            ohos:right_margin="16vp"
+            ohos:text="立即支付"
+            ohos:text_color="#FFFFFFFF"
+            ohos:text_size="16fp"/>
+
+    </DirectionalLayout>
+
+</DirectionalLayout>
+

+ 388 - 0
entry/src/main/resources/base/layout/layout_pay_detail_qr_dialog.xml

@@ -0,0 +1,388 @@
+<?xml version="1.0" encoding="utf-8"?>
+<DirectionalLayout
+    xmlns:ohos="http://schemas.huawei.com/res/ohos"
+    ohos:height="match_parent"
+    ohos:width="match_parent"
+    ohos:alignment="center"
+    ohos:background_element="#99000000">
+
+    <!-- 半透明背景 -->
+
+    <!-- 弹框内容容器 -->
+    <DirectionalLayout
+        ohos:height="match_content"
+        ohos:width="320vp"
+        ohos:layout_alignment="center"
+        ohos:alignment="center"
+        ohos:background_element="$graphic:background_circle_16"
+        ohos:orientation="vertical">
+
+        <!-- 顶部关闭按钮区域 -->
+        <DirectionalLayout
+            ohos:height="match_content"
+            ohos:width="match_parent"
+            ohos:alignment="right"
+            ohos:bottom_padding="0vp"
+            ohos:orientation="horizontal">
+
+            <Image
+                ohos:top_margin="12vp"
+                ohos:right_margin="12vp"
+                ohos:id="$+id:btn_close_dialog"
+                ohos:height="24vp"
+                ohos:width="24vp"
+                ohos:clickable="true"
+                ohos:image_src="$media:close"
+                ohos:scale_mode="zoom_center"/>
+        </DirectionalLayout>
+
+        <!-- 滚动内容区域 -->
+        <ScrollView
+            ohos:height="0vp"
+            ohos:width="match_parent"
+            ohos:left_padding="16vp"
+            ohos:right_padding="16vp"
+            ohos:bottom_padding="16vp"
+            ohos:top_padding="4vp"
+            ohos:weight="1">
+
+            <DirectionalLayout
+                ohos:height="match_content"
+                ohos:width="match_parent"
+                ohos:orientation="vertical">
+
+                <!-- 车牌号 -->
+                <DirectionalLayout
+                    ohos:height="match_content"
+                    ohos:width="match_parent"
+                    ohos:alignment="center"
+                    ohos:bottom_margin="16vp"
+                    ohos:orientation="vertical">
+
+                    <Text
+                        ohos:id="$+id:pay_detail_plate_no"
+                        ohos:height="match_content"
+                        ohos:width="match_content"
+                        ohos:text="粤B12345"
+                        ohos:text_color="#FF333333"
+                        ohos:text_size="16fp"
+                        ohos:text_weight="700"/>
+                </DirectionalLayout>
+
+                <!-- 停车信息组 -->
+                <DirectionalLayout
+                    ohos:height="match_content"
+                    ohos:width="match_parent"
+                    ohos:bottom_margin="16vp"
+                    ohos:orientation="vertical">
+
+                    <!-- 停车场 -->
+                    <DirectionalLayout
+                        ohos:height="match_content"
+                        ohos:width="match_parent"
+                        ohos:bottom_margin="12vp"
+                        ohos:orientation="horizontal">
+
+                        <Text
+                            ohos:height="match_content"
+                            ohos:width="match_content"
+                            ohos:right_margin="20vp"
+                            ohos:text="停车场"
+                            ohos:text_color="#FF999999"
+                            ohos:text_size="16fp"/>
+
+                        <Text
+                            ohos:id="$+id:pay_detail_park_name"
+                            ohos:height="match_content"
+                            ohos:width="0vp"
+                            ohos:max_text_lines="2"
+                            ohos:text="--"
+                            ohos:text_alignment="right"
+                            ohos:text_color="#FF333333"
+                            ohos:text_size="16fp"
+                            ohos:truncation_mode="ellipsis_at_end"
+                            ohos:weight="1"/>
+                    </DirectionalLayout>
+
+                    <!-- 入场时间 -->
+                    <DirectionalLayout
+                        ohos:height="match_content"
+                        ohos:width="match_parent"
+                        ohos:bottom_margin="12vp"
+                        ohos:orientation="horizontal">
+
+                        <Text
+                            ohos:height="match_content"
+                            ohos:width="match_content"
+                            ohos:right_margin="20vp"
+                            ohos:text="入场时间"
+                            ohos:text_color="#FF999999"
+                            ohos:text_size="16fp"/>
+
+                        <Text
+                            ohos:id="$+id:pay_detail_in_time"
+                            ohos:height="match_content"
+                            ohos:width="0vp"
+                            ohos:text="--"
+                            ohos:text_alignment="right"
+                            ohos:text_color="#FF333333"
+                            ohos:text_size="16fp"
+                            ohos:weight="1"/>
+                    </DirectionalLayout>
+
+                    <!-- 已停时长 -->
+                    <DirectionalLayout
+                        ohos:height="match_content"
+                        ohos:width="match_parent"
+                        ohos:orientation="horizontal">
+
+                        <Text
+                            ohos:height="match_content"
+                            ohos:width="match_content"
+                            ohos:right_margin="20vp"
+                            ohos:text="已停时长"
+                            ohos:text_color="#FF999999"
+                            ohos:text_size="16fp"/>
+
+                        <Text
+                            ohos:id="$+id:pay_detail_stay_time"
+                            ohos:height="match_content"
+                            ohos:width="0vp"
+                            ohos:text="--"
+                            ohos:text_alignment="right"
+                            ohos:text_color="#FF333333"
+                            ohos:text_size="16fp"
+                            ohos:weight="1"/>
+                    </DirectionalLayout>
+
+                </DirectionalLayout>
+
+                <!-- 分隔线 -->
+                <DirectionalLayout
+                    ohos:height="1vp"
+                    ohos:width="match_parent"
+                    ohos:background_element="#FFEEEEEE"
+                    ohos:bottom_margin="16vp"/>
+
+                <!-- 费用信息组 -->
+                <DirectionalLayout
+                    ohos:height="match_content"
+                    ohos:width="match_parent"
+                    ohos:bottom_margin="16vp"
+                    ohos:orientation="vertical">
+
+                    <!-- 停车费 -->
+                    <DirectionalLayout
+                        ohos:height="match_content"
+                        ohos:width="match_parent"
+                        ohos:bottom_margin="12vp"
+                        ohos:orientation="horizontal">
+
+                        <Text
+                            ohos:height="match_content"
+                            ohos:width="match_content"
+                            ohos:right_margin="20vp"
+                            ohos:text="停车费"
+                            ohos:text_color="#FF999999"
+                            ohos:text_size="16fp"/>
+
+                        <Text
+                            ohos:id="$+id:pay_detail_total_amount"
+                            ohos:height="match_content"
+                            ohos:width="0vp"
+                            ohos:text="--"
+                            ohos:text_alignment="right"
+                            ohos:text_color="#FF333333"
+                            ohos:text_size="16fp"
+                            ohos:weight="1"/>
+                    </DirectionalLayout>
+
+                    <!-- 优惠金额 -->
+                    <DirectionalLayout
+                        ohos:id="$+id:layout_discount_amount"
+                        ohos:height="match_content"
+                        ohos:width="match_parent"
+                        ohos:bottom_margin="12vp"
+                        ohos:orientation="horizontal"
+                        ohos:visibility="hide">
+
+                        <Text
+                            ohos:height="match_content"
+                            ohos:width="match_content"
+                            ohos:right_margin="20vp"
+                            ohos:text="优惠金额"
+                            ohos:text_color="#FF999999"
+                            ohos:text_size="16fp"/>
+
+                        <Text
+                            ohos:id="$+id:pay_detail_discount_amount"
+                            ohos:height="match_content"
+                            ohos:width="0vp"
+                            ohos:text="--"
+                            ohos:text_alignment="right"
+                            ohos:text_color="#FFFF6600"
+                            ohos:text_size="16fp"
+                            ohos:weight="1"/>
+                    </DirectionalLayout>
+
+                    <!-- 历史欠费 -->
+                    <DirectionalLayout
+                        ohos:id="$+id:layout_follow_sum"
+                        ohos:height="match_content"
+                        ohos:width="match_parent"
+                        ohos:bottom_margin="12vp"
+                        ohos:orientation="horizontal"
+                        ohos:visibility="hide">
+
+                        <Text
+                            ohos:height="match_content"
+                            ohos:width="match_content"
+                            ohos:right_margin="20vp"
+                            ohos:text="历史欠费"
+                            ohos:text_color="#FF999999"
+                            ohos:text_size="16fp"/>
+
+                        <DirectionalLayout
+                            ohos:height="match_content"
+                            ohos:width="0vp"
+                            ohos:alignment="right"
+                            ohos:orientation="horizontal"
+                            ohos:weight="1">
+
+                            <Text
+                                ohos:id="$+id:pay_detail_follow_sum"
+                                ohos:height="match_content"
+                                ohos:width="match_content"
+                                ohos:right_margin="4vp"
+                                ohos:text="--"
+                                ohos:text_alignment="right"
+                                ohos:text_color="#FF333333"
+                                ohos:text_size="16fp"/>
+
+                            <Image
+                                ohos:height="16vp"
+                                ohos:width="16vp"
+                                ohos:image_src="$media:close"
+                                ohos:scale_mode="zoom_center"/>
+                        </DirectionalLayout>
+                    </DirectionalLayout>
+
+                    <!-- 车位费 -->
+                    <DirectionalLayout
+                        ohos:id="$+id:layout_lot_amount"
+                        ohos:height="match_content"
+                        ohos:width="match_parent"
+                        ohos:orientation="horizontal"
+                        ohos:visibility="hide">
+
+                        <Text
+                            ohos:height="match_content"
+                            ohos:width="match_content"
+                            ohos:right_margin="20vp"
+                            ohos:text="车位费"
+                            ohos:text_color="#FF999999"
+                            ohos:text_size="16fp"/>
+
+                        <DirectionalLayout
+                            ohos:height="match_content"
+                            ohos:width="0vp"
+                            ohos:alignment="right"
+                            ohos:orientation="horizontal"
+                            ohos:weight="1">
+
+                            <Text
+                                ohos:id="$+id:pay_detail_lot_amount"
+                                ohos:height="match_content"
+                                ohos:width="match_content"
+                                ohos:right_margin="4vp"
+                                ohos:text="--"
+                                ohos:text_alignment="right"
+                                ohos:text_color="#FF333333"
+                                ohos:text_size="16fp"/>
+
+                            <Image
+                                ohos:height="16vp"
+                                ohos:width="16vp"
+                                ohos:image_src="$media:close"
+                                ohos:scale_mode="zoom_center"/>
+                        </DirectionalLayout>
+                    </DirectionalLayout>
+
+                </DirectionalLayout>
+
+                <!-- 总计区域 -->
+                <DirectionalLayout
+                    ohos:height="match_content"
+                    ohos:width="match_parent"
+                    ohos:background_element="#FFF5F5F5"
+                    ohos:bottom_margin="12vp"
+                    ohos:orientation="horizontal"
+                    ohos:padding="12vp">
+
+                    <Text
+                        ohos:height="match_content"
+                        ohos:width="match_content"
+                        ohos:right_margin="20vp"
+                        ohos:text="总计"
+                        ohos:text_color="#FF999999"
+                        ohos:text_size="16fp"/>
+
+                    <DirectionalLayout
+                        ohos:height="match_content"
+                        ohos:width="0vp"
+                        ohos:alignment="right"
+                        ohos:orientation="horizontal"
+                        ohos:weight="1">
+
+                        <Text
+                            ohos:height="match_content"
+                            ohos:width="match_content"
+                            ohos:text="¥"
+                            ohos:text_color="#FF333333"
+                            ohos:text_size="18fp"
+                            ohos:text_weight="700"/>
+
+                        <Text
+                            ohos:id="$+id:pay_detail_actual_amount"
+                            ohos:height="match_content"
+                            ohos:width="match_content"
+                            ohos:text="0.00"
+                            ohos:text_alignment="right"
+                            ohos:text_color="#FF333333"
+                            ohos:text_size="20fp"
+                            ohos:text_weight="700"/>
+                    </DirectionalLayout>
+                </DirectionalLayout>
+
+                <!-- 提示信息 -->
+                <Text
+                    ohos:id="$+id:pay_detail_tip"
+                    ohos:height="match_content"
+                    ohos:width="match_parent"
+                    ohos:bottom_margin="16vp"
+                    ohos:text=""
+                    ohos:text_color="#FF999999"
+                    ohos:text_size="12fp"
+                    ohos:visibility="hide"/>
+
+            </DirectionalLayout>
+
+        </ScrollView>
+
+        <!-- 底部支付按钮 -->
+        <Button
+            ohos:id="$+id:btn_pay"
+            ohos:height="44vp"
+            ohos:width="match_parent"
+            ohos:background_element="$graphic:button"
+            ohos:bottom_margin="16vp"
+            ohos:left_margin="16vp"
+            ohos:right_margin="16vp"
+            ohos:text="立即支付"
+            ohos:text_color="#FFFFFFFF"
+            ohos:text_size="16fp"/>
+
+    </DirectionalLayout>
+
+</DirectionalLayout>
+

+ 87 - 0
entry/src/main/resources/base/layout/layout_qrcode_scan_dialog.xml

@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PositionLayout
+    xmlns:ohos="http://schemas.huawei.com/res/ohos"
+    ohos:height="match_parent"
+    ohos:width="match_parent"
+    ohos:background_element="#DD000000">
+
+    <!-- 中心内容容器,用于垂直和水平居中 -->
+    <DirectionalLayout
+        ohos:height="match_parent"
+        ohos:width="match_parent"
+        ohos:alignment="center"
+        ohos:orientation="vertical">
+
+        <!-- 标题(包含倒计时) -->
+        <Text
+            ohos:id="$+id:txt_title"
+            ohos:height="match_content"
+            ohos:width="match_content"
+            ohos:text="微信扫码支付(180秒)"
+            ohos:top_margin="20vp"
+            ohos:text_size="20fp"
+            ohos:text_color="#FFFFFFFF"
+            ohos:text_weight="700"
+            ohos:text_alignment="center"/>
+
+        <!-- 二维码容器 -->
+        <DirectionalLayout
+            ohos:id="$+id:qrcode_container"
+            ohos:height="180vp"
+            ohos:width="180vp"
+            ohos:top_margin="20vp"
+            ohos:alignment="center"
+            ohos:background_element="#FFFFFFFF"
+            ohos:orientation="vertical">
+
+            <!-- 二维码图片 -->
+            <Image
+                ohos:id="$+id:img_qrcode"
+                ohos:height="match_parent"
+                ohos:width="match_parent"
+                ohos:padding="10vp"
+                ohos:scale_mode="zoom_center"/>
+
+        </DirectionalLayout>
+
+        <!-- 取消支付按钮 -->
+        <Button
+            ohos:id="$+id:btn_cancel_pay"
+            ohos:height="44vp"
+            ohos:width="200vp"
+            ohos:top_margin="20vp"
+            ohos:text="取消支付"
+            ohos:text_size="16fp"
+            ohos:text_color="#FFFFFFFF"
+            ohos:background_element="$graphic:button_cancel"
+            ohos:clickable="true"/>
+
+        <!-- 加载提示 -->
+        <Text
+            ohos:id="$+id:txt_loading"
+            ohos:height="match_content"
+            ohos:width="match_content"
+            ohos:text="正在生成二维码..."
+            ohos:text_size="14fp"
+            ohos:text_color="#CCFFFFFF"
+            ohos:top_margin="40vp"
+            ohos:text_alignment="center"
+            ohos:visibility="hide"/>
+
+    </DirectionalLayout>
+
+    <!-- 关闭按钮(绝对定位,悬浮在右上角) -->
+    <Image
+        ohos:id="$+id:btn_close_scan"
+        ohos:height="36vp"
+        ohos:width="36vp"
+        ohos:top_margin="20vp"
+        ohos:right_margin="20vp"
+        ohos:align_parent_top="true"
+        ohos:align_parent_right="true"
+        ohos:clickable="true"
+        ohos:image_src="$media:close"
+        ohos:scale_mode="zoom_center"/>
+
+</PositionLayout>
+

BIN
entry/src/main/resources/base/media/bg.png


File diff suppressed because it is too large
+ 1 - 1
entry/src/main/resources/rawfile/agconnect-services.json