Browse Source

Initial commit: 鸿蒙项目

wangmeng 1 month ago
commit
b6dcc394eb
100 changed files with 10199 additions and 0 deletions
  1. 12 0
      .gitignore
  2. 10 0
      AppScope/app.json5
  3. 8 0
      AppScope/resources/base/element/string.json
  4. BIN
      AppScope/resources/base/media/background.png
  5. BIN
      AppScope/resources/base/media/foreground.png
  6. 7 0
      AppScope/resources/base/media/layered_image.json
  7. 30 0
      base-common/.preview/default/intermediates/merge_profile/default/module.json
  8. 17 0
      base-common/BuildProfile.ets
  9. 28 0
      base-common/build-profile.json5
  10. 7 0
      base-common/hvigorfile.ts
  11. 29 0
      base-common/oh-package-lock.json5
  12. 13 0
      base-common/oh-package.json5
  13. 1 0
      base-common/oh_modules/@xdz/base-core
  14. 1 0
      base-common/oh_modules/@xdz/capability-socketio
  15. 267 0
      base-common/src/main/ets/common/auth/AuthManager.ets
  16. 24 0
      base-common/src/main/ets/common/auth/datasource/local/AuthLocalDataSource.ets
  17. 27 0
      base-common/src/main/ets/common/auth/datasource/local/AuthLocalDataSourceImpl.ets
  18. 52 0
      base-common/src/main/ets/common/auth/datasource/remote/AuthApi.ets
  19. 62 0
      base-common/src/main/ets/common/auth/datasource/remote/AuthRemoteDataSource.ets
  20. 13 0
      base-common/src/main/ets/common/auth/model/LoginRequest.ets
  21. 35 0
      base-common/src/main/ets/common/auth/model/LoginResponse.ets
  22. 13 0
      base-common/src/main/ets/common/auth/model/RegisterRequest.ets
  23. 319 0
      base-common/src/main/ets/common/auth/pages/LoginPage.ets
  24. 248 0
      base-common/src/main/ets/common/auth/pages/RegisterPage.ets
  25. 110 0
      base-common/src/main/ets/common/auth/repository/AuthRepository.ets
  26. 146 0
      base-common/src/main/ets/common/auth/storage/TokenStore.ets
  27. 54 0
      base-common/src/main/ets/common/auth/viewmodel/LoginState.ets
  28. 73 0
      base-common/src/main/ets/common/auth/viewmodel/LoginViewModel.ets
  29. 196 0
      base-common/src/main/ets/common/bridge/BridgeManager.ets
  30. 178 0
      base-common/src/main/ets/common/camera/CameraHelper.ets
  31. 142 0
      base-common/src/main/ets/common/config/ConfigManager.ets
  32. 76 0
      base-common/src/main/ets/common/config/ServerConfigManager.ets
  33. 161 0
      base-common/src/main/ets/common/crash/CrashHelper.ets
  34. 318 0
      base-common/src/main/ets/common/dialog/DialogHelper.ets
  35. 199 0
      base-common/src/main/ets/common/executor/ExecutorManager.ets
  36. 156 0
      base-common/src/main/ets/common/file/FilePickerHelper.ets
  37. 317 0
      base-common/src/main/ets/common/image/ImageLoader.ets
  38. 38 0
      base-common/src/main/ets/common/log/LogHelper.ets
  39. 121 0
      base-common/src/main/ets/common/network/ApiBaseRemoteDataSource.ets
  40. 105 0
      base-common/src/main/ets/common/network/ApiBaseRepository.ets
  41. 175 0
      base-common/src/main/ets/common/network/ApiBaseService.ets
  42. 104 0
      base-common/src/main/ets/common/network/ApiResponseParser.ets
  43. 80 0
      base-common/src/main/ets/common/network/ApiServiceFactory.ets
  44. 90 0
      base-common/src/main/ets/common/network/NetworkHelper.ets
  45. 317 0
      base-common/src/main/ets/common/network/统一解决方案说明.md
  46. 293 0
      base-common/src/main/ets/common/permission/PermissionHelper.ets
  47. 145 0
      base-common/src/main/ets/common/router/NavigationHelper.ets
  48. 173 0
      base-common/src/main/ets/common/socketio/SocketIOManager.ets
  49. 85 0
      base-common/src/main/ets/common/storage/StorageManager.ets
  50. 40 0
      base-common/src/main/ets/common/ui/BasePage.ets
  51. 125 0
      base-common/src/main/ets/common/ui/BaseViewModel.ets
  52. 134 0
      base-common/src/main/ets/common/ui/MessageHelper.ets
  53. 115 0
      base-common/src/main/ets/common/ui/PageHelper.ets
  54. 104 0
      base-common/src/main/ets/common/ui/StateFlow.ets
  55. 60 0
      base-common/src/main/ets/common/ui/ViewModelHelper.ets
  56. 279 0
      base-common/src/main/ets/common/util/UtilManager.ets
  57. 102 0
      base-common/src/main/ets/common/version/VersionUpdateManager.ets
  58. 36 0
      base-common/src/main/ets/common/version/datasource/remote/VersionApi.ets
  59. 42 0
      base-common/src/main/ets/common/version/datasource/remote/VersionRemoteDataSource.ets
  60. 17 0
      base-common/src/main/ets/common/version/model/VersionResponse.ets
  61. 80 0
      base-common/src/main/ets/common/version/repository/VersionRepository.ets
  62. 72 0
      base-common/src/main/ets/common/version/viewmodel/VersionState.ets
  63. 86 0
      base-common/src/main/ets/common/version/viewmodel/VersionViewModel.ets
  64. 202 0
      base-common/src/main/ets/common/缺失模块清单.md
  65. 94 0
      base-common/src/main/ets/index.ets
  66. 13 0
      base-common/src/main/module.json5
  67. 30 0
      base-core/.preview/default/intermediates/merge_profile/default/module.json
  68. 17 0
      base-core/BuildProfile.ets
  69. 28 0
      base-core/build-profile.json5
  70. 7 0
      base-core/hvigorfile.ts
  71. 11 0
      base-core/oh-package.json5
  72. 175 0
      base-core/src/main/ets/core/log/ILog.ets
  73. 68 0
      base-core/src/main/ets/core/log/impl/HilogLogger.ets
  74. 46 0
      base-core/src/main/ets/core/log/impl/NoOpLogger.ets
  75. 162 0
      base-core/src/main/ets/core/network/NetworkManager.ets
  76. 76 0
      base-core/src/main/ets/core/push/IPushService.ets
  77. 166 0
      base-core/src/main/ets/core/share/IShareService.ets
  78. 30 0
      base-core/src/main/ets/core/storage/IStorage.ets
  79. 319 0
      base-core/src/main/ets/core/storage/StorageImpl.ets
  80. 201 0
      base-core/src/main/ets/core/util/JWTUtil.ets
  81. 27 0
      base-core/src/main/ets/index.ets
  82. 13 0
      base-core/src/main/module.json5
  83. 152 0
      build-profile.json5
  84. 113 0
      build.sh
  85. 31 0
      capability-ble/.preview/default/intermediates/merge_profile/default/module.json
  86. 17 0
      capability-ble/BuildProfile.ets
  87. 28 0
      capability-ble/build-profile.json5
  88. 7 0
      capability-ble/hvigorfile.ts
  89. 19 0
      capability-ble/oh-package-lock.json5
  90. 12 0
      capability-ble/oh-package.json5
  91. 1 0
      capability-ble/oh_modules/@xdz/base-core
  92. 258 0
      capability-ble/src/main/ets/ble/api/BLEService.ets
  93. 20 0
      capability-ble/src/main/ets/ble/factory/BLEServiceFactory.ets
  94. 1218 0
      capability-ble/src/main/ets/ble/impl/BLEServiceImpl.ets
  95. 67 0
      capability-ble/src/main/ets/ble/model/BLECommand.ets
  96. 32 0
      capability-ble/src/main/ets/ble/model/BLEDevice.ets
  97. 45 0
      capability-ble/src/main/ets/ble/model/BLEEncryptedData.ets
  98. 60 0
      capability-ble/src/main/ets/ble/model/BLEResponse.ets
  99. 67 0
      capability-ble/src/main/ets/ble/model/Command.ets
  100. 0 0
      capability-ble/src/main/ets/ble/model/FragmentBuffer.ets

+ 12 - 0
.gitignore

@@ -0,0 +1,12 @@
+/node_modules
+/oh_modules
+/local.properties
+/.idea
+**/build
+/.hvigor
+.cxx
+/.clangd
+/.clang-format
+/.clang-tidy
+**/.test
+/.appanalyzer

+ 10 - 0
AppScope/app.json5

@@ -0,0 +1,10 @@
+{
+  "app": {
+    "bundleName": "com.narutohuo.xdz",
+    "vendor": "example",
+    "versionCode": 1000000,
+    "versionName": "1.0.0",
+    "icon": "$media:layered_image",
+    "label": "$string:app_name"
+  }
+}

+ 8 - 0
AppScope/resources/base/element/string.json

@@ -0,0 +1,8 @@
+{
+  "string": [
+    {
+      "name": "app_name",
+      "value": "新大洲"
+    }
+  ]
+}

BIN
AppScope/resources/base/media/background.png


BIN
AppScope/resources/base/media/foreground.png


+ 7 - 0
AppScope/resources/base/media/layered_image.json

@@ -0,0 +1,7 @@
+{
+  "layered-image":
+  {
+    "background" : "$media:background",
+    "foreground" : "$media:foreground"
+  }
+}

+ 30 - 0
base-common/.preview/default/intermediates/merge_profile/default/module.json

@@ -0,0 +1,30 @@
+{
+	"app": {
+		"bundleName": "com.narutohuo.xdz",
+		"debug": true,
+		"versionCode": 1000000,
+		"versionName": "1.0.0",
+		"minAPIVersion": 60001021,
+		"targetAPIVersion": 60001021,
+		"apiReleaseType": "Release",
+		"targetMinorAPIVersion": 0,
+		"targetPatchAPIVersion": 0,
+		"compileSdkVersion": "6.0.1.112",
+		"compileSdkType": "HarmonyOS",
+		"appEnvironments": [],
+		"bundleType": "app",
+		"buildMode": "debug"
+	},
+	"module": {
+		"name": "base_common",
+		"type": "har",
+		"description": "业务封装层 - 封装 base-core 的接口,提供便捷调用",
+		"mainElement": "",
+		"deviceTypes": [
+			"phone",
+			"tablet"
+		],
+		"packageName": "@xdz/base-common",
+		"installationFree": false
+	}
+}

+ 17 - 0
base-common/BuildProfile.ets

@@ -0,0 +1,17 @@
+/**
+ * Use these variables when you tailor your ArkTS code. They must be of the const type.
+ */
+export const HAR_VERSION = '1.0.0';
+export const BUILD_MODE_NAME = 'debug';
+export const DEBUG = true;
+export const TARGET_NAME = 'default';
+
+/**
+ * BuildProfile Class is used only for compatibility purposes.
+ */
+export default class BuildProfile { 
+	static readonly HAR_VERSION = HAR_VERSION;
+	static readonly BUILD_MODE_NAME = BUILD_MODE_NAME;
+	static readonly DEBUG = DEBUG;
+	static readonly TARGET_NAME = TARGET_NAME;
+}

+ 28 - 0
base-common/build-profile.json5

@@ -0,0 +1,28 @@
+{
+  "apiType": "stageMode",
+  "buildOption": {
+    "resOptions": {
+      "copyCodeResource": {
+        "enable": false
+      }
+    }
+  },
+  "buildOptionSet": [
+    {
+      "name": "release",
+      "arkOptions": {
+        "obfuscation": {
+          "ruleOptions": {
+            "enable": false
+          }
+        }
+      }
+    }
+  ],
+  "targets": [
+    {
+      "name": "default"
+    }
+  ]
+}
+

+ 7 - 0
base-common/hvigorfile.ts

@@ -0,0 +1,7 @@
+import { harTasks } from '@ohos/hvigor-ohos-plugin';
+
+export default {
+  system: harTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
+  plugins: []       /* Custom plugin to extend the functionality of Hvigor. */
+}
+

+ 29 - 0
base-common/oh-package-lock.json5

@@ -0,0 +1,29 @@
+{
+  "meta": {
+    "stableOrder": true,
+    "enableUnifiedLockfile": false
+  },
+  "lockfileVersion": 3,
+  "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.",
+  "specifiers": {
+    "@xdz/base-core@../base-core": "@xdz/base-core@../base-core",
+    "@xdz/capability-socketio@../capability-socketio": "@xdz/capability-socketio@../capability-socketio"
+  },
+  "packages": {
+    "@xdz/base-core@../base-core": {
+      "name": "@xdz/base-core",
+      "version": "1.0.0",
+      "resolved": "../base-core",
+      "registryType": "local"
+    },
+    "@xdz/capability-socketio@../capability-socketio": {
+      "name": "@xdz/capability-socketio",
+      "version": "1.0.0",
+      "resolved": "../capability-socketio",
+      "registryType": "local",
+      "dependencies": {
+        "@xdz/base-core": "file:../base-core"
+      }
+    }
+  }
+}

+ 13 - 0
base-common/oh-package.json5

@@ -0,0 +1,13 @@
+{
+  "name": "@xdz/base-common",
+  "version": "1.0.0",
+  "description": "业务封装层 - 封装 base-core 的接口,提供便捷调用",
+  "main": "src/main/ets/index.ets",
+  "dependencies": {
+    "@xdz/base-core": "file:../base-core",
+    "@xdz/capability-socketio": "file:../capability-socketio"
+  },
+  "license": "MIT",
+  "keywords": ["base", "common", "business"]
+}
+

+ 1 - 0
base-common/oh_modules/@xdz/base-core

@@ -0,0 +1 @@
+../../../base-core

+ 1 - 0
base-common/oh_modules/@xdz/capability-socketio

@@ -0,0 +1 @@
+../../../capability-socketio

+ 267 - 0
base-common/src/main/ets/common/auth/AuthManager.ets

@@ -0,0 +1,267 @@
+import { Context } from '@kit.AbilityKit';
+import { AuthLocalDataSource } from './datasource/local/AuthLocalDataSource';
+import { AuthLocalDataSourceImpl } from './datasource/local/AuthLocalDataSourceImpl';
+import { AuthRemoteDataSource } from './datasource/remote/AuthRemoteDataSource';
+import { AuthRepository } from './repository/AuthRepository';
+import { TokenStore } from './storage/TokenStore';
+import { LogHelper } from '../log/LogHelper';
+import { LoginResponse } from './model/LoginResponse';
+import { Result } from '../network/ApiBaseRepository';
+import { JWTUtil } from '@xdz/base-core';
+
+/**
+ * 认证管理器
+ * 
+ * 封装认证相关的完整逻辑,包括:
+ * - 用户登录
+ * - 用户注册
+ * - Token 刷新
+ * - 登录状态管理
+ * 
+ * 使用方式:
+ * ```typescript
+ * // 在 Application 中初始化(推荐方式,使用默认实现)
+ * await AuthManager.init(context);
+ * 
+ * // 或者使用自定义的 localDataSource
+ * await AuthManager.init(localDataSource);
+ * 
+ * // 登录
+ * const result = await AuthManager.login(mobile, password);
+ * if (result.isSuccess) {
+ *   // 登录成功,跳转到主界面
+ * } else {
+ *   // 登录失败,显示错误
+ * }
+ * ```
+ */
+export class AuthManager {
+  private static localDataSource: AuthLocalDataSource | null = null;
+  private static remoteDataSource: AuthRemoteDataSource = new AuthRemoteDataSource();
+  private static repository: AuthRepository | null = null;
+  
+  /**
+   * 初始化认证管理器(使用默认实现)
+   * 
+   * 需要在 Application.onCreate() 中调用
+   * 会自动初始化 TokenStore 并使用默认的 AuthLocalDataSourceImpl
+   * 
+   * @param context 应用上下文
+   */
+  static async init(context: Context): Promise<void> {
+    // 初始化 TokenStore
+    await TokenStore.init(context);
+    // 使用默认实现
+    const defaultLocalDataSource = new AuthLocalDataSourceImpl();
+    AuthManager.localDataSource = defaultLocalDataSource;
+    AuthManager.repository = new AuthRepository(
+      AuthManager.remoteDataSource,
+      defaultLocalDataSource
+    );
+  }
+  
+  /**
+   * 初始化认证管理器(使用自定义实现)
+   * 
+   * 如果需要自定义本地数据源,可以使用此方法
+   * 
+   * @param localDataSource 自定义的本地数据源
+   */
+  static initWithDataSource(localDataSource: AuthLocalDataSource): void {
+    AuthManager.localDataSource = localDataSource;
+    AuthManager.repository = new AuthRepository(
+      AuthManager.remoteDataSource,
+      localDataSource
+    );
+  }
+  
+  /**
+   * 用户登录
+   * 
+   * @param mobile 手机号
+   * @param password 密码
+   * @returns 登录结果
+   */
+  static async login(mobile: string, password: string): Promise<Result<LoginResponse>> {
+    const repo = AuthManager.repository;
+    if (!repo) {
+      LogHelper.e('AuthManager', 'AuthManager 未初始化,请先调用 AuthManager.init()');
+      return Result.failure(new Error('AuthManager 未初始化'));
+    }
+    
+    try {
+      return await repo.login(mobile, password);
+    } catch (e) {
+      LogHelper.e('AuthManager', '登录异常', e as Error);
+      return Result.failure(e as Error);
+    }
+  }
+  
+  /**
+   * 用户注册
+   * 
+   * @param mobile 手机号
+   * @param password 密码
+   * @returns 注册结果
+   */
+  static async register(mobile: string, password: string): Promise<Result<LoginResponse>> {
+    const repo = AuthManager.repository;
+    if (!repo) {
+      LogHelper.e('AuthManager', 'AuthManager 未初始化,请先调用 AuthManager.init()');
+      return Result.failure(new Error('AuthManager 未初始化'));
+    }
+    
+    try {
+      return await repo.register(mobile, password);
+    } catch (e) {
+      LogHelper.e('AuthManager', '注册异常', e as Error);
+      return Result.failure(e as Error);
+    }
+  }
+  
+  /**
+   * 刷新 Token
+   * 
+   * @param refreshToken 刷新令牌
+   * @returns 刷新结果
+   */
+  static async refreshToken(refreshToken: string): Promise<Result<LoginResponse>> {
+    const repo = AuthManager.repository;
+    if (!repo) {
+      LogHelper.e('AuthManager', 'AuthManager 未初始化,请先调用 AuthManager.init()');
+      return Result.failure(new Error('AuthManager 未初始化'));
+    }
+    
+    try {
+      return await repo.refreshToken(refreshToken);
+    } catch (e) {
+      LogHelper.e('AuthManager', 'Token 刷新异常', e as Error);
+      return Result.failure(e as Error);
+    }
+  }
+  
+  // ========== 便捷方法 ==========
+  
+  /**
+   * 检查是否已登录
+   * 
+   * 参考 iOS 实现:
+   * - 检查 Access Token 是否存在且未过期
+   * - 如果 Access Token 过期,会尝试使用 Refresh Token 刷新
+   * - 只有在 Refresh Token 也过期或刷新失败时,才返回 false
+   * 
+   * 注意:由于鸿蒙暂未实现 JWTUtil,目前先检查 Token 是否存在,
+   * 如果不存在则尝试使用 Refresh Token 刷新
+   * 
+   * @returns true 表示已登录
+   */
+  static async isLoggedIn(): Promise<boolean> {
+    // 1. 先检查 Access Token 是否存在
+    const accessToken = await TokenStore.getAccessToken();
+    
+    // 2. 如果 Access Token 不存在,检查是否有 Refresh Token
+    if (!accessToken || accessToken === '') {
+      const refreshToken = await TokenStore.getRefreshToken();
+      if (refreshToken && refreshToken !== '') {
+        // 有 Refresh Token,尝试刷新 Access Token
+        LogHelper.d('AuthManager', 'Access Token 不存在,尝试使用 Refresh Token 刷新...');
+        const newToken = await AuthManager.refreshTokenIfNeeded();
+        return newToken !== null && newToken !== '';
+      }
+      // 没有 Refresh Token,返回 false
+      return false;
+    }
+    
+    // 3. Access Token 存在(TODO: 如果有 JWTUtil,应该检查是否过期)
+    // 由于鸿蒙暂未实现 JWTUtil,目前只检查是否存在
+    // 如果将来实现 JWTUtil,应该添加以下逻辑:
+    // if (!JWTUtil.isTokenValid(accessToken)) {
+    //   const refreshToken = await TokenStore.getRefreshToken();
+    //   if (refreshToken && refreshToken !== '') {
+    //     LogHelper.d('AuthManager', 'Access Token 已过期,尝试使用 Refresh Token 刷新...');
+    //     const newToken = await AuthManager.refreshTokenIfNeeded();
+    //     if (newToken && newToken !== '' && JWTUtil.isTokenValid(newToken)) {
+    //       LogHelper.d('AuthManager', 'Access Token 刷新成功,用户仍然处于登录状态');
+    //       return true;
+    //     } else {
+    //       LogHelper.w('AuthManager', 'Access Token 刷新失败或新 Token 无效,用户需要重新登录');
+    //       return false;
+    //     }
+    //   } else {
+    //     LogHelper.w('AuthManager', 'Access Token 已过期且没有 Refresh Token,用户需要重新登录');
+    //     return false;
+    //   }
+    // }
+    
+    // 4. Access Token 存在(且未过期,如果有 JWTUtil 验证)
+    return true;
+  }
+  
+  /**
+   * 获取当前 Access Token
+   * 
+   * @returns Access Token,如果未登录返回 null
+   */
+  static async getAccessToken(): Promise<string | null> {
+    return await TokenStore.getAccessToken();
+  }
+  
+  /**
+   * 获取当前 Refresh Token
+   * 
+   * @returns Refresh Token,如果未登录返回 null
+   */
+  static async getRefreshToken(): Promise<string | null> {
+    return await TokenStore.getRefreshToken();
+  }
+  
+  /**
+   * 刷新 Token(如果需要)
+   * 
+   * 参考 iOS 实现,移除可选回调参数,保持接口简洁
+   * 
+   * @returns 新的 accessToken,如果刷新失败返回 null
+   */
+  static async refreshTokenIfNeeded(): Promise<string | null> {
+    const refreshToken = await TokenStore.getRefreshToken();
+    if (!refreshToken || refreshToken === '') {
+      LogHelper.w('AuthManager', 'RefreshToken 为空,无法刷新');
+      return null;
+    }
+    
+    try {
+      const repo = AuthManager.repository;
+      if (!repo) {
+        LogHelper.e('AuthManager', 'AuthManager 未初始化,请先调用 AuthManager.init()');
+        return null;
+      }
+      
+      const result = await repo.refreshToken(refreshToken);
+      
+      const loginResponse = result.getOrNull();
+      if (loginResponse) {
+        // Token 已由 AuthRepository 自动保存
+        LogHelper.d('AuthManager', 'Token 刷新成功');
+        return loginResponse.accessToken;
+      } else {
+        const error = result.exceptionOrNull() || new Error('Token 刷新失败');
+        LogHelper.w('AuthManager', `Token 刷新失败: ${error.message}`);
+        return null;
+      }
+    } catch (e) {
+      LogHelper.e('AuthManager', 'Token 刷新异常', e as Error);
+      return null;
+    }
+  }
+  
+  /**
+   * 登出
+   * 
+   * 清除所有 Token 和用户信息
+   */
+  static async logout(): Promise<void> {
+    await TokenStore.clearToken();
+    LogHelper.d('AuthManager', '用户已登出');
+  }
+}
+

+ 24 - 0
base-common/src/main/ets/common/auth/datasource/local/AuthLocalDataSource.ets

@@ -0,0 +1,24 @@
+import { LoginResponse } from '../../model/LoginResponse';
+
+/**
+ * 认证本地数据源接口
+ * 
+ * 注意:具体实现需要子类提供
+ */
+export interface AuthLocalDataSource {
+  /**
+   * 保存Token
+   */
+  saveToken(loginResponse: LoginResponse): Promise<void>;
+  
+  /**
+   * 获取Access Token
+   */
+  getToken(): Promise<string | null>;
+  
+  /**
+   * 清除Token
+   */
+  clearToken(): Promise<void>;
+}
+

+ 27 - 0
base-common/src/main/ets/common/auth/datasource/local/AuthLocalDataSourceImpl.ets

@@ -0,0 +1,27 @@
+import { LoginResponse } from '../../model/LoginResponse';
+import { TokenStore } from '../../storage/TokenStore';
+import type { AuthLocalDataSource } from './AuthLocalDataSource';
+
+/**
+ * 认证本地数据源实现
+ * 
+ * 使用 TokenStore 进行 Token 的持久化存储
+ */
+export class AuthLocalDataSourceImpl implements AuthLocalDataSource {
+  async saveToken(loginResponse: LoginResponse): Promise<void> {
+    await TokenStore.saveToken(
+      loginResponse.accessToken,
+      loginResponse.refreshToken,
+      loginResponse.userId
+    );
+  }
+  
+  async getToken(): Promise<string | null> {
+    return await TokenStore.getAccessToken();
+  }
+  
+  async clearToken(): Promise<void> {
+    await TokenStore.clearToken();
+  }
+}
+

+ 52 - 0
base-common/src/main/ets/common/auth/datasource/remote/AuthApi.ets

@@ -0,0 +1,52 @@
+import { LoginRequest } from '../../model/LoginRequest';
+import { LoginResponse } from '../../model/LoginResponse';
+import { RegisterRequest } from '../../model/RegisterRequest';
+import { ApiBaseService } from '../../../network/ApiBaseService';
+import { Result } from '../../../network/ApiBaseRepository';
+
+/**
+ * 认证相关API接口
+ * 
+ * 继承 ApiBaseService,自动获得统一的请求处理能力
+ * 无需手动处理 URL 构建、请求头、错误处理等
+ * 
+ * 使用方式:
+ * ```typescript
+ * const authApi = new AuthApi();
+ * const result = await authApi.login(new LoginRequest('13800138000', 'password'));
+ * if (result.isSuccess) {
+ *   const response = result.getOrThrow();
+ * }
+ * ```
+ */
+export class AuthApi extends ApiBaseService {
+  /**
+   * 用户登录
+   */
+  async login(request: LoginRequest): Promise<Result<LoginResponse>> {
+    return await this.post<LoginResponse>('member/auth/login', request, '登录失败');
+  }
+  
+  /**
+   * 用户注册
+   */
+  async register(request: RegisterRequest): Promise<Result<LoginResponse>> {
+    return await this.post<LoginResponse>('member/auth/register', request, '注册失败');
+  }
+  
+  /**
+   * 刷新 Token
+   */
+  async refreshToken(refreshToken: string): Promise<Result<LoginResponse>> {
+    // 使用 POST 方式,将 refreshToken 作为查询参数
+    const queryParams: Record<string, string> = {};
+    queryParams.refreshToken = refreshToken;
+    return await this.postWithQuery<LoginResponse>(
+      'member/auth/refresh-token',
+      undefined,
+      queryParams,
+      'Token 刷新失败'
+    );
+  }
+}
+

+ 62 - 0
base-common/src/main/ets/common/auth/datasource/remote/AuthRemoteDataSource.ets

@@ -0,0 +1,62 @@
+import { LoginRequest } from '../../model/LoginRequest';
+import { LoginResponse } from '../../model/LoginResponse';
+import { RegisterRequest } from '../../model/RegisterRequest';
+import { ApiBaseRemoteDataSource, Result } from '../../../network/ApiBaseRemoteDataSource';
+import { AuthApi } from './AuthApi';
+
+/**
+ * 认证远程数据源接口
+ */
+export interface IAuthRemoteDataSource {
+  /**
+   * 用户登录
+   */
+  login(request: LoginRequest): Promise<Result<LoginResponse>>;
+  
+  /**
+   * 用户注册
+   */
+  register(request: RegisterRequest): Promise<Result<LoginResponse>>;
+  
+  /**
+   * 刷新 Token
+   */
+  refreshToken(refreshToken: string): Promise<Result<LoginResponse>>;
+}
+
+/**
+ * 认证远程数据源实现
+ * 
+ * 继承 ApiBaseRemoteDataSource,自动获得:
+ * - 统一的错误处理
+ * - 自动日志记录
+ * - 网络异常友好提示
+ */
+export class AuthRemoteDataSource extends ApiBaseRemoteDataSource implements IAuthRemoteDataSource {
+  private authApi: AuthApi | null = null;
+  
+  private getAuthApi(): AuthApi {
+    if (!this.authApi) {
+      // AuthApi 继承自 ApiBaseService,会自动使用 NetworkHelper.getBaseUrl()
+      // 如果需要自定义 baseUrl,可以传入参数
+      this.authApi = new AuthApi();
+    }
+    return this.authApi;
+  }
+  
+  async login(request: LoginRequest): Promise<Result<LoginResponse>> {
+    // AuthApi 已经返回 Result<LoginResponse>,直接返回即可
+    return await this.getAuthApi().login(request);
+  }
+  
+  async register(request: RegisterRequest): Promise<Result<LoginResponse>> {
+    // AuthApi 已经返回 Result<LoginResponse>,直接返回即可
+    return await this.getAuthApi().register(request);
+  }
+  
+  async refreshToken(refreshToken: string): Promise<Result<LoginResponse>> {
+    // AuthApi 已经返回 Result<LoginResponse>,直接返回即可
+    return await this.getAuthApi().refreshToken(refreshToken);
+  }
+}
+

+ 13 - 0
base-common/src/main/ets/common/auth/model/LoginRequest.ets

@@ -0,0 +1,13 @@
+/**
+ * 登录请求参数
+ */
+export class LoginRequest {
+  mobile: string;
+  password: string;
+  
+  constructor(mobile: string, password: string) {
+    this.mobile = mobile;
+    this.password = password;
+  }
+}
+

+ 35 - 0
base-common/src/main/ets/common/auth/model/LoginResponse.ets

@@ -0,0 +1,35 @@
+/**
+ * 登录响应数据
+ * 对应后端 AppAuthLoginRespVO
+ * 
+ * 注意:服务端返回的 expiresTime 是 LocalDateTime,会自动转换为时间戳(毫秒)
+ */
+export class LoginResponse {
+  userId: number;
+  accessToken: string;
+  refreshToken: string;
+  expiresTime?: number;  // 服务端返回 LocalDateTime,会自动转换为时间戳(毫秒)
+  openid?: string;
+  // 以下字段为兼容字段(后端不返回,但前端可能需要)
+  username?: string;
+  mobile?: string;
+  
+  constructor(
+    userId: number,
+    accessToken: string,
+    refreshToken: string,
+    expiresTime?: number,
+    openid?: string,
+    username?: string,
+    mobile?: string
+  ) {
+    this.userId = userId;
+    this.accessToken = accessToken;
+    this.refreshToken = refreshToken;
+    this.expiresTime = expiresTime;
+    this.openid = openid;
+    this.username = username;
+    this.mobile = mobile;
+  }
+}
+

+ 13 - 0
base-common/src/main/ets/common/auth/model/RegisterRequest.ets

@@ -0,0 +1,13 @@
+/**
+ * 注册请求参数
+ */
+export class RegisterRequest {
+  mobile: string;
+  password: string;
+  
+  constructor(mobile: string, password: string) {
+    this.mobile = mobile;
+    this.password = password;
+  }
+}
+

+ 319 - 0
base-common/src/main/ets/common/auth/pages/LoginPage.ets

@@ -0,0 +1,319 @@
+/**
+ * 登录页面
+ * 参考 iOS 端 LoginView.swift 实现
+ * 
+ * 包含:
+ * - 登录功能
+ * - 注册按钮(跳转到注册页面)
+ * - 左下角设置按钮(服务器配置)
+ */
+
+import { LoginViewModel } from '../viewmodel/LoginViewModel';
+import { ViewModelHelper } from '../../ui/ViewModelHelper';
+import { MessageHelper } from '../../ui/MessageHelper';
+import { AuthManager } from '../AuthManager';
+import { ServerConfigManager } from '../../config/ServerConfigManager';
+import { RegisterPage } from './RegisterPage';
+import { LoginResponse } from '../model/LoginResponse';
+
+@Component
+export struct LoginPage {
+  @State viewModel: LoginViewModel = new LoginViewModel();
+  @State mobile: string = '';
+  @State password: string = '';
+  @State showRegisterPage: boolean = false;
+  @State showServerConfig: boolean = false;
+  @State serverIP: string = '';
+  
+  private onLoginSuccess?: (response: LoginResponse | null) => void;
+  
+  aboutToAppear() {
+    ViewModelHelper.onInit(this.viewModel);
+    this.loadServerIP();
+    this.observeLoginState();
+  }
+  
+  aboutToDisappear() {
+    ViewModelHelper.onDestroy(this.viewModel);
+  }
+  
+  build() {
+    Stack() {
+      // 主登录界面
+      Column({ space: 0 }) {
+        Blank()
+          .height(80)
+        
+        // Logo 和应用名称(参考 iOS 端)
+        Column({ space: 8 }) {
+          Text('新大洲本田')
+            .fontSize(32)
+            .fontWeight(FontWeight.Bold)
+            .fontColor('#000000')
+          
+          Text('欢迎登录')
+            .fontSize(16)
+            .fontColor('#666666')
+        }
+        .margin({ bottom: 48 })
+        
+        // 输入框区域
+        Column({ space: 16 }) {
+          // 手机号输入框
+          Column({ space: 8 }) {
+            Text('手机号')
+              .fontSize(14)
+              .fontColor('#666666')
+              .alignSelf(ItemAlign.Start)
+            
+            TextInput({ placeholder: '请输入手机号', text: this.mobile })
+              .type(InputType.PhoneNumber)
+              .width('100%')
+              .height(48)
+              .padding(12)
+              .backgroundColor('#F5F5F5')
+              .borderRadius(8)
+              .border({ width: 1, color: '#E0E0E0' })
+              .onChange((value: string) => {
+                this.mobile = value;
+              })
+          }
+          .width('100%')
+          
+          // 密码输入框
+          Column({ space: 8 }) {
+            Text('密码')
+              .fontSize(14)
+              .fontColor('#666666')
+              .alignSelf(ItemAlign.Start)
+            
+            TextInput({ placeholder: '请输入密码', text: this.password })
+              .type(InputType.Password)
+              .width('100%')
+              .height(48)
+              .padding(12)
+              .backgroundColor('#F5F5F5')
+              .borderRadius(8)
+              .border({ width: 1, color: '#E0E0E0' })
+              .onChange((value: string) => {
+                this.password = value;
+              })
+          }
+          .width('100%')
+        }
+        .width('100%')
+        .padding({ left: 24, right: 24 })
+        
+        Blank()
+          .height(32)
+        
+        // 操作按钮
+        Column({ space: 16 }) {
+          // 登录按钮
+      if (this.viewModel.loginState.value.isLoading) {
+            Button() {
+        LoadingProgress()
+                .width(24)
+                .height(24)
+                .color(Color.White)
+      }
+            .width('100%')
+            .height(56)
+            .fontSize(16)
+            .fontWeight(FontWeight.Medium)
+            .fontColor(Color.White)
+            .backgroundColor('#CCCCCC')
+            .borderRadius(8)
+            .enabled(false)
+            .padding({ left: 24, right: 24 })
+          } else {
+            Button('登录')
+              .width('100%')
+              .height(56)
+              .fontSize(16)
+              .fontWeight(FontWeight.Medium)
+              .fontColor(Color.White)
+              .backgroundColor(this.canLogin() ? '#007AFF' : '#CCCCCC')
+              .borderRadius(8)
+              .enabled(this.canLogin())
+              .onClick(() => {
+                this.handleLogin();
+              })
+              .padding({ left: 24, right: 24 })
+          }
+          
+          // 注册按钮(参考 iOS 端)
+          Button('还没有账号?立即注册')
+            .width('100%')
+            .fontSize(14)
+            .fontColor('#007AFF')
+            .backgroundColor(Color.Transparent)
+            .onClick(() => {
+              this.showRegisterPage = true;
+            })
+            .padding({ left: 24, right: 24 })
+        }
+        
+        Blank()
+          .layoutWeight(1)
+        
+        // 左下角设置按钮(参考 iOS 端)
+        Row() {
+          Button('⚙️')
+            .width(40)
+            .height(40)
+            .fontSize(20)
+            .fontColor('#666666')
+            .backgroundColor('#F5F5F5')
+            .borderRadius(20)
+            .onClick(() => {
+              this.showServerConfig = true;
+            })
+          
+          Blank()
+        }
+        .width('100%')
+        .justifyContent(FlexAlign.Start)
+        .padding({ left: 16, bottom: 16 })
+      }
+      .width('100%')
+      .height('100%')
+      .justifyContent(FlexAlign.Start)
+      
+      // 注册页面(条件渲染)
+      if (this.showRegisterPage) {
+        this.RegisterPageBuilder()
+      }
+      
+      // 服务器配置对话框(条件渲染)
+      if (this.showServerConfig) {
+        this.ServerConfigDialog()
+      }
+    }
+    .width('100%')
+    .height('100%')
+  }
+  
+  @Builder
+  RegisterPageBuilder() {
+    RegisterPage()
+      .width('100%')
+      .height('100%')
+  }
+  
+  @Builder
+  ServerConfigDialog() {
+    Column({ space: 16 }) {
+      Text('服务器配置')
+        .fontSize(18)
+        .fontWeight(FontWeight.Bold)
+        .margin({ top: 16 })
+      
+      Text('服务器IP地址(测试功能)')
+        .fontSize(14)
+        .fontColor('#666666')
+        .alignSelf(ItemAlign.Start)
+        .margin({ left: 16 })
+      
+      TextInput({ placeholder: '请输入服务器IP', text: this.serverIP })
+        .type(InputType.Normal)
+        .margin({ left: 16, right: 16 })
+        .onChange((value: string) => {
+          this.serverIP = value;
+        })
+      
+      Row({ space: 12 }) {
+        Button('保存')
+          .layoutWeight(1)
+          .height(44)
+          .fontColor(Color.White)
+          .backgroundColor('#007AFF')
+          .borderRadius(8)
+          .onClick(async () => {
+            await this.saveServerIP();
+        })
+      
+        Button('重置')
+          .layoutWeight(1)
+          .height(44)
+          .fontColor('#007AFF')
+          .backgroundColor(Color.Transparent)
+          .borderRadius(8)
+          .onClick(async () => {
+            await this.resetServerIP();
+          })
+        
+        Button('取消')
+          .layoutWeight(1)
+          .height(44)
+          .fontColor('#666666')
+          .backgroundColor(Color.Transparent)
+          .borderRadius(8)
+        .onClick(() => {
+            this.showServerConfig = false;
+        })
+    }
+    .width('100%')
+      .padding({ left: 16, right: 16, bottom: 16 })
+    }
+    .width('80%')
+    .backgroundColor(Color.White)
+    .borderRadius(16)
+    .padding(16)
+    .shadow({ radius: 20, color: '#33000000', offsetX: 0, offsetY: 4 })
+    .alignItems(HorizontalAlign.Center)
+    .justifyContent(FlexAlign.Center)
+    .onClick(() => {
+      // 阻止点击事件冒泡
+    })
+  }
+  
+  private canLogin(): boolean {
+    return this.mobile.trim() !== '' && this.password.trim() !== '';
+  }
+  
+  private async handleLogin(): Promise<void> {
+    if (!this.canLogin()) {
+      return;
+    }
+    
+    try {
+      const result = await AuthManager.login(this.mobile, this.password);
+      if (result.isSuccess) {
+        MessageHelper.showSuccess('登录成功');
+        if (this.onLoginSuccess) {
+          this.onLoginSuccess(result.getOrNull());
+        }
+      } else {
+        const error = result.exceptionOrNull();
+        MessageHelper.showError(error?.message || '登录失败');
+      }
+    } catch (e) {
+      MessageHelper.showError((e as Error).message || '登录失败');
+    }
+  }
+  
+  private async loadServerIP(): Promise<void> {
+    this.serverIP = await ServerConfigManager.getServerIp();
+  }
+  
+  private async saveServerIP(): Promise<void> {
+    await ServerConfigManager.setServerIp(this.serverIP.trim());
+    MessageHelper.showSuccess('保存成功');
+    this.showServerConfig = false;
+  }
+  
+  private async resetServerIP(): Promise<void> {
+    await ServerConfigManager.resetToDefault();
+    await this.loadServerIP();
+    MessageHelper.showSuccess('重置成功');
+  }
+  
+  private observeLoginState(): void {
+    this.viewModel.loginState.observe((state) => {
+      if (state.isSuccess && this.onLoginSuccess) {
+        // 登录成功后的处理
+      }
+    });
+  }
+}

+ 248 - 0
base-common/src/main/ets/common/auth/pages/RegisterPage.ets

@@ -0,0 +1,248 @@
+/**
+ * 注册页面
+ * 参考 iOS 端 RegisterView.swift 实现
+ */
+
+import { LoginViewModel } from '../viewmodel/LoginViewModel';
+import { ViewModelHelper } from '../../ui/ViewModelHelper';
+import { MessageHelper } from '../../ui/MessageHelper';
+import { AuthManager } from '../AuthManager';
+
+@Component
+export struct RegisterPage {
+  @State viewModel: LoginViewModel = new LoginViewModel();
+  @State mobile: string = '';
+  @State password: string = '';
+  @State confirmPassword: string = '';
+  
+  private onRegisterSuccess?: () => void;
+  private onCancel?: () => void;
+  
+  build() {
+    Column({ space: 0 }) {
+      // 标题栏
+      Row() {
+        Button('取消')
+          .fontSize(16)
+          .fontColor('#007AFF')
+          .backgroundColor(Color.Transparent)
+          .onClick(() => {
+            if (this.onCancel) {
+              this.onCancel();
+            }
+          })
+        
+        Blank()
+        
+        Text('注册')
+          .fontSize(18)
+          .fontWeight(FontWeight.Bold)
+        
+        Blank()
+        
+        Blank()
+          .width(60)
+      }
+      .width('100%')
+      .height(56)
+      .padding({ left: 16, right: 16 })
+      
+      Column({ space: 0 }) {
+        Blank()
+          .height(40)
+        
+        // Logo 和应用名称
+        Column({ space: 8 }) {
+          Text('新大洲本田')
+            .fontSize(32)
+            .fontWeight(FontWeight.Bold)
+            .fontColor('#000000')
+          
+          Text('欢迎注册')
+            .fontSize(16)
+            .fontColor('#666666')
+        }
+        .margin({ bottom: 48 })
+        
+        // 输入框区域
+        Column({ space: 16 }) {
+          // 手机号输入框
+          Column({ space: 8 }) {
+            Text('手机号')
+              .fontSize(14)
+              .fontColor('#666666')
+              .alignSelf(ItemAlign.Start)
+            
+            TextInput({ placeholder: '请输入手机号', text: this.mobile })
+              .type(InputType.PhoneNumber)
+              .width('100%')
+              .height(48)
+              .padding(12)
+              .backgroundColor('#F5F5F5')
+              .borderRadius(8)
+              .border({ width: 1, color: '#E0E0E0' })
+              .onChange((value: string) => {
+                this.mobile = value;
+              })
+          }
+          .width('100%')
+          
+          // 密码输入框
+          Column({ space: 8 }) {
+            Text('密码')
+              .fontSize(14)
+              .fontColor('#666666')
+              .alignSelf(ItemAlign.Start)
+            
+            TextInput({ placeholder: '请输入密码', text: this.password })
+              .type(InputType.Password)
+              .width('100%')
+              .height(48)
+              .padding(12)
+              .backgroundColor('#F5F5F5')
+              .borderRadius(8)
+              .border({ width: 1, color: '#E0E0E0' })
+              .onChange((value: string) => {
+                this.password = value;
+              })
+          }
+          .width('100%')
+          
+          // 确认密码输入框
+          Column({ space: 8 }) {
+            Text('确认密码')
+              .fontSize(14)
+              .fontColor('#666666')
+              .alignSelf(ItemAlign.Start)
+            
+            TextInput({ placeholder: '请再次输入密码', text: this.confirmPassword })
+              .type(InputType.Password)
+              .width('100%')
+              .height(48)
+              .padding(12)
+              .backgroundColor('#F5F5F5')
+              .borderRadius(8)
+              .border({ 
+                width: 1, 
+                color: (this.password !== this.confirmPassword && this.confirmPassword !== '') ? Color.Red : '#E0E0E0' 
+              })
+              .onChange((value: string) => {
+                this.confirmPassword = value;
+              })
+            
+            if (this.password !== this.confirmPassword && this.confirmPassword !== '') {
+              Text('两次输入的密码不一致')
+                .fontSize(12)
+                .fontColor(Color.Red)
+                .alignSelf(ItemAlign.Start)
+                .margin({ left: 4 })
+            }
+          }
+          .width('100%')
+        }
+        .width('100%')
+        .padding({ left: 24, right: 24 })
+        
+        Blank()
+          .height(32)
+        
+        // 操作按钮
+        Column({ space: 16 }) {
+          // 注册按钮
+          if (this.viewModel.loginState.value.isLoading) {
+            Button() {
+              LoadingProgress()
+                .width(24)
+                .height(24)
+                .color(Color.White)
+            }
+            .width('100%')
+            .height(56)
+            .fontSize(16)
+            .fontWeight(FontWeight.Medium)
+            .fontColor(Color.White)
+            .backgroundColor('#CCCCCC')
+            .borderRadius(8)
+            .enabled(false)
+            .padding({ left: 24, right: 24 })
+          } else {
+            Button('注册')
+              .width('100%')
+              .height(56)
+              .fontSize(16)
+              .fontWeight(FontWeight.Medium)
+              .fontColor(Color.White)
+              .backgroundColor(this.canRegister() ? '#007AFF' : '#CCCCCC')
+              .borderRadius(8)
+              .enabled(this.canRegister())
+              .onClick(() => {
+                this.handleRegister();
+              })
+              .padding({ left: 24, right: 24 })
+          }
+          
+          // 返回登录按钮
+          Button('已有账号?返回登录')
+            .width('100%')
+            .fontSize(14)
+            .fontColor('#007AFF')
+            .backgroundColor(Color.Transparent)
+            .onClick(() => {
+              if (this.onCancel) {
+                this.onCancel();
+              }
+            })
+            .padding({ left: 24, right: 24 })
+        }
+        .margin({ bottom: 32 })
+      }
+      .layoutWeight(1)
+    }
+    .width('100%')
+    .height('100%')
+    .backgroundColor(Color.White)
+  }
+  
+  aboutToAppear() {
+    ViewModelHelper.onInit(this.viewModel);
+    this.observeRegisterState();
+  }
+  
+  aboutToDisappear() {
+    ViewModelHelper.onDestroy(this.viewModel);
+  }
+  
+  private canRegister(): boolean {
+    return this.mobile.trim() !== '' && 
+           this.password.trim() !== '' && 
+           this.confirmPassword.trim() !== '' &&
+           this.password === this.confirmPassword;
+  }
+  
+  private async handleRegister(): Promise<void> {
+    if (!this.canRegister()) {
+      return;
+    }
+    
+    try {
+      const result = await AuthManager.register(this.mobile, this.password);
+      if (result.isSuccess) {
+        MessageHelper.showSuccess('注册成功');
+        if (this.onRegisterSuccess) {
+          this.onRegisterSuccess();
+        }
+      } else {
+        const error = result.exceptionOrNull();
+        MessageHelper.showError(error?.message || '注册失败');
+      }
+    } catch (e) {
+      MessageHelper.showError((e as Error).message || '注册失败');
+    }
+  }
+  
+  private observeRegisterState(): void {
+    this.viewModel.loginState.observe((state) => {
+      // 状态变化处理
+    });
+  }
+}

+ 110 - 0
base-common/src/main/ets/common/auth/repository/AuthRepository.ets

@@ -0,0 +1,110 @@
+import { AuthLocalDataSource } from '../datasource/local/AuthLocalDataSource';
+import { AuthRemoteDataSource } from '../datasource/remote/AuthRemoteDataSource';
+import { LoginRequest } from '../model/LoginRequest';
+import { LoginResponse } from '../model/LoginResponse';
+import { RegisterRequest } from '../model/RegisterRequest';
+import { LogHelper } from '../../log/LogHelper';
+import { ApiBaseRepository, Result } from '../../network/ApiBaseRepository';
+
+/**
+ * 认证数据仓库
+ * 
+ * 负责统一管理认证相关的数据获取和缓存
+ * 
+ * 继承 ApiBaseRepository,自动获得:
+ * - 统一的错误处理
+ * - 日志记录
+ * - 数据转换扩展点
+ */
+export class AuthRepository extends ApiBaseRepository {
+  private remoteDataSource: AuthRemoteDataSource;
+  private localDataSource: AuthLocalDataSource;
+  
+  constructor(
+    remoteDataSource: AuthRemoteDataSource,
+    localDataSource: AuthLocalDataSource
+  ) {
+    super();
+    this.remoteDataSource = remoteDataSource;
+    this.localDataSource = localDataSource;
+  }
+  
+  /**
+   * 用户登录
+   * 
+   * @param mobile 手机号
+   * @param password 密码
+   * @returns 登录结果
+   */
+  async login(mobile: string, password: string): Promise<Result<LoginResponse>> {
+    const request = new LoginRequest(mobile, password);
+    
+    // 从远程数据源获取数据
+    const result = await this.remoteDataSource.login(request);
+    
+    // 如果成功,保存到本地
+    result.onSuccess(async (response: LoginResponse) => {
+      await this.localDataSource.saveToken(response);
+      LogHelper.d('AuthRepository', 'login: Token已保存');
+    });
+    
+    // 如果失败,可以在这里添加额外的错误处理逻辑
+    result.onFailure((error: Error) => {
+      this.handleError(error);
+    });
+    
+    return result;
+  }
+  
+  /**
+   * 用户注册
+   * 
+   * @param mobile 手机号
+   * @param password 密码
+   * @returns 注册结果
+   */
+  async register(mobile: string, password: string): Promise<Result<LoginResponse>> {
+    const request = new RegisterRequest(mobile, password);
+    
+    // 从远程数据源获取数据
+    const result = await this.remoteDataSource.register(request);
+    
+    // 如果成功,保存到本地
+    result.onSuccess(async (response: LoginResponse) => {
+      await this.localDataSource.saveToken(response);
+      LogHelper.d('AuthRepository', 'register: Token已保存');
+    });
+    
+    // 如果失败,可以在这里添加额外的错误处理逻辑
+    result.onFailure((error: Error) => {
+      this.handleError(error);
+    });
+    
+    return result;
+  }
+  
+  /**
+   * 刷新 Token
+   * 
+   * @param refreshToken 刷新令牌
+   * @returns 刷新结果(包含新的 accessToken 和 refreshToken)
+   */
+  async refreshToken(refreshToken: string): Promise<Result<LoginResponse>> {
+    // 从远程数据源获取数据
+    const result = await this.remoteDataSource.refreshToken(refreshToken);
+    
+    // 如果成功,保存到本地
+    result.onSuccess(async (response: LoginResponse) => {
+      await this.localDataSource.saveToken(response);
+      LogHelper.d('AuthRepository', 'refreshToken: Token已刷新并保存');
+    });
+    
+    // 如果失败,可以在这里添加额外的错误处理逻辑
+    result.onFailure((error: Error) => {
+      this.handleError(error);
+    });
+    
+    return result;
+  }
+}
+

+ 146 - 0
base-common/src/main/ets/common/auth/storage/TokenStore.ets

@@ -0,0 +1,146 @@
+import { Context } from '@kit.AbilityKit';
+import { StorageImpl } from '@xdz/base-core';
+
+/**
+ * Token 存储管理器
+ * 
+ * 负责 Token 的存储、读取和清除
+ * 底层使用 base-core 的 StorageImpl 统一存储
+ * 
+ * 使用方式:
+ * ```typescript
+ * // 在 Application 中初始化(StorageImpl 和 TokenStore 都需要初始化)
+ * await StorageImpl.init(context);
+ * await TokenStore.init(context);  // 可选,如果 StorageImpl 已初始化,这个可以省略
+ * 
+ * // 保存 Token
+ * await TokenStore.saveToken(accessToken, refreshToken, userId);
+ * 
+ * // 获取 Token
+ * const token = await TokenStore.getAccessToken();
+ * 
+ * // 清除 Token
+ * await TokenStore.clearToken();
+ * ```
+ */
+export class TokenStore {
+  private static readonly KEY_ACCESS_TOKEN = 'access_token';
+  private static readonly KEY_REFRESH_TOKEN = 'refresh_token';
+  private static readonly KEY_USER_ID = 'user_id';
+  private static readonly KEY_SERVER_URL = 'server_url';
+  private static readonly KEY_SOCKET_URL = 'socket_url';
+  
+  /**
+   * 初始化 TokenStore(可选)
+   * 
+   * 如果 StorageImpl 已初始化,此方法可以省略
+   * 
+   * @param context 应用上下文
+   */
+  static async init(context: Context): Promise<void> {
+    // 确保 StorageImpl 已初始化
+    if (!StorageImpl.isInitialized()) {
+      await StorageImpl.init(context);
+    }
+  }
+  
+  /**
+   * 保存Token
+   * 
+   * @param accessToken 访问令牌
+   * @param refreshToken 刷新令牌
+   * @param userId 用户ID
+   */
+  static async saveToken(accessToken: string, refreshToken: string, userId: number): Promise<void> {
+    await StorageImpl.getInstance().putString(TokenStore.KEY_ACCESS_TOKEN, accessToken);
+    await StorageImpl.getInstance().putString(TokenStore.KEY_REFRESH_TOKEN, refreshToken);
+    await StorageImpl.getInstance().putLong(TokenStore.KEY_USER_ID, userId);
+  }
+  
+  /**
+   * 获取Access Token
+   * 
+   * @returns Access Token,如果不存在返回 null
+   */
+  static async getAccessToken(): Promise<string | null> {
+    const token = await StorageImpl.getInstance().getString(TokenStore.KEY_ACCESS_TOKEN);
+    return token === '' ? null : token;
+  }
+  
+  /**
+   * 获取Refresh Token
+   * 
+   * @returns Refresh Token,如果不存在返回 null
+   */
+  static async getRefreshToken(): Promise<string | null> {
+    const token = await StorageImpl.getInstance().getString(TokenStore.KEY_REFRESH_TOKEN);
+    return token === '' ? null : token;
+  }
+  
+  /**
+   * 获取用户ID
+   * 
+   * @returns 用户ID,如果不存在返回 0
+   */
+  static async getUserId(): Promise<number> {
+    return await StorageImpl.getInstance().getLong(TokenStore.KEY_USER_ID);
+  }
+  
+  /**
+   * 判断是否已登录
+   * 
+   * @returns true 表示已登录(有有效的 Access Token)
+   */
+  static async isLoggedIn(): Promise<boolean> {
+    const token = await TokenStore.getAccessToken();
+    return token !== null && token !== '';
+  }
+  
+  /**
+   * 清除Token(登出)
+   */
+  static async clearToken(): Promise<void> {
+    await StorageImpl.getInstance().remove(TokenStore.KEY_ACCESS_TOKEN);
+    await StorageImpl.getInstance().remove(TokenStore.KEY_REFRESH_TOKEN);
+    await StorageImpl.getInstance().remove(TokenStore.KEY_USER_ID);
+  }
+  
+  /**
+   * 保存服务器地址
+   * 
+   * @param url 服务器地址
+   */
+  static async saveServerUrl(url: string): Promise<void> {
+    await StorageImpl.getInstance().putString(TokenStore.KEY_SERVER_URL, url);
+  }
+  
+  /**
+   * 获取服务器地址
+   * 
+   * @returns 服务器地址,如果不存在返回 null
+   */
+  static async getServerUrl(): Promise<string | null> {
+    const url = await StorageImpl.getInstance().getString(TokenStore.KEY_SERVER_URL);
+    return url === '' ? null : url;
+  }
+  
+  /**
+   * 保存Socket地址
+   * 
+   * @param url Socket地址
+   */
+  static async saveSocketUrl(url: string): Promise<void> {
+    await StorageImpl.getInstance().putString(TokenStore.KEY_SOCKET_URL, url);
+  }
+  
+  /**
+   * 获取Socket地址
+   * 
+   * @returns Socket地址,如果不存在返回 null
+   */
+  static async getSocketUrl(): Promise<string | null> {
+    const url = await StorageImpl.getInstance().getString(TokenStore.KEY_SOCKET_URL);
+    return url === '' ? null : url;
+  }
+}
+

+ 54 - 0
base-common/src/main/ets/common/auth/viewmodel/LoginState.ets

@@ -0,0 +1,54 @@
+/**
+ * 登录状态
+ * 
+ * 与 Android 版本保持一致的状态定义
+ */
+export class LoginState {
+  static readonly Idle = new LoginState('Idle');
+  static readonly Loading = new LoginState('Loading');
+  
+  static Success(message: string): LoginState {
+    return new LoginState('Success', message);
+  }
+  
+  static Error(message: string): LoginState {
+    return new LoginState('Error', message);
+  }
+  
+  readonly type: 'Idle' | 'Loading' | 'Success' | 'Error';
+  readonly message?: string;
+  
+  private constructor(type: 'Idle' | 'Loading' | 'Success' | 'Error', message?: string) {
+    this.type = type;
+    this.message = message;
+  }
+  
+  /**
+   * 判断是否为加载状态
+   */
+  get isLoading(): boolean {
+    return this.type === 'Loading';
+  }
+  
+  /**
+   * 判断是否为成功状态
+   */
+  get isSuccess(): boolean {
+    return this.type === 'Success';
+  }
+  
+  /**
+   * 判断是否为错误状态
+   */
+  get isError(): boolean {
+    return this.type === 'Error';
+  }
+  
+  /**
+   * 判断是否为空闲状态
+   */
+  get isIdle(): boolean {
+    return this.type === 'Idle';
+  }
+}
+

+ 73 - 0
base-common/src/main/ets/common/auth/viewmodel/LoginViewModel.ets

@@ -0,0 +1,73 @@
+import { BaseViewModel } from '../../ui/BaseViewModel';
+import { StateFlow } from '../../ui/StateFlow';
+import { AuthRepository } from '../repository/AuthRepository';
+import { AuthRemoteDataSource } from '../datasource/remote/AuthRemoteDataSource';
+import { AuthLocalDataSourceImpl } from '../datasource/local/AuthLocalDataSourceImpl';
+import { LoginState } from './LoginState';
+
+/**
+ * 登录ViewModel
+ * 
+ * 与 Android 版本保持一致的 API 和结构
+ */
+export class LoginViewModel extends BaseViewModel {
+  private authRepository: AuthRepository;
+  
+  // 使用 StateFlow 管理状态(与 Android 版本一致)
+  private _loginState = new StateFlow<LoginState>(LoginState.Idle);
+  loginState: StateFlow<LoginState> = this._loginState;
+  
+  private static readonly MIN_PASSWORD_LENGTH = 6;
+  private static readonly MAX_PASSWORD_LENGTH = 16;
+  
+  constructor() {
+    super();
+    // 初始化 Repository
+    this.authRepository = new AuthRepository(
+      new AuthRemoteDataSource(),
+      new AuthLocalDataSourceImpl()
+    );
+  }
+  
+  /**
+   * 登录
+   * 
+   * @param mobile 手机号
+   * @param password 密码
+   */
+  async login(mobile: string, password: string): Promise<void> {
+    this._loginState.value = LoginState.Loading;
+    
+    // 输入验证
+    if (!mobile || mobile.trim() === '') {
+      this._loginState.value = LoginState.Error('手机号不能为空');
+      return;
+    }
+    
+    if (password.length < LoginViewModel.MIN_PASSWORD_LENGTH || 
+        password.length > LoginViewModel.MAX_PASSWORD_LENGTH) {
+      this._loginState.value = LoginState.Error(
+        `密码长度应为${LoginViewModel.MIN_PASSWORD_LENGTH}-${LoginViewModel.MAX_PASSWORD_LENGTH}位`
+      );
+      return;
+    }
+    
+    try {
+      const result = await this.authRepository.login(mobile, password);
+      
+      if (result.isSuccess) {
+        this._loginState.value = LoginState.Success('登录成功');
+      } else {
+        const error = result.exceptionOrNull();
+        this._loginState.value = LoginState.Error(
+          error?.message || '登录失败'
+        );
+      }
+    } catch (error) {
+      this._loginState.value = LoginState.Error(
+        (error as Error).message || '登录失败'
+      );
+    }
+  }
+}
+

+ 196 - 0
base-common/src/main/ets/common/bridge/BridgeManager.ets

@@ -0,0 +1,196 @@
+import { LogHelper } from '../log/LogHelper';
+
+const TAG = "BridgeManager";
+
+/**
+ * WebView 消息接口
+ */
+export interface WebViewMessage {
+  method: string;
+  params?: object;
+}
+
+/**
+ * WebView 响应接口
+ */
+export interface WebViewResponse {
+  success: boolean;
+  data?: object;
+  error?: string;
+}
+
+/**
+ * WebView 组件接口
+ */
+export interface WebView {
+  runJavaScript?: (script: string) => void;
+}
+
+/**
+ * 空对象接口
+ */
+interface EmptyObject {
+}
+
+/**
+ * 桥接管理器
+ * 
+ * 统一封装 WebView 与原生通信功能,提供便捷的 JS 桥接方式
+ * 
+ * 使用方式:
+ * ```typescript
+ * // 注册 JS 方法
+ * BridgeManager.registerMethod("getUserInfo", (params) => {
+ *   return { userId: "123", userName: "张三" };
+ * })
+ * 
+ * // 调用 JS 方法
+ * BridgeManager.callJSMethod(webView, "showMessage", { message: "Hello" })
+ * 
+ * // 发送消息到 WebView
+ * BridgeManager.postMessage(webView, { type: "update", data: {} })
+ * ```
+ */
+export class BridgeManager {
+  private static readonly EMPTY_OBJECT: EmptyObject = {} as EmptyObject;
+  private static methods: Map<string, (params: object) => object> = new Map();
+  
+  /**
+   * 注册 JS 方法(供 WebView 调用)
+   * 
+   * @param methodName 方法名称
+   * @param handler 处理方法
+   */
+  static registerMethod(
+    methodName: string,
+    handler: (params: object) => object
+  ): void {
+    BridgeManager.methods.set(methodName, handler);
+    LogHelper.d(TAG, `注册 JS 方法: ${methodName}`);
+  }
+  
+  /**
+   * 取消注册 JS 方法
+   * 
+   * @param methodName 方法名称
+   */
+  static unregisterMethod(methodName: string): void {
+    BridgeManager.methods.delete(methodName);
+    LogHelper.d(TAG, `取消注册 JS 方法: ${methodName}`);
+  }
+  
+  /**
+   * 调用 JS 方法(原生调用 WebView)
+   * 
+   * @param webView WebView 组件引用
+   * @param methodName 方法名称
+   * @param params 参数
+   */
+  static callJSMethod(
+    webView: WebView,
+    methodName: string,
+    params?: object
+  ): void {
+    try {
+      if (!webView) {
+        LogHelper.w(TAG, "WebView 引用为空");
+        return;
+      }
+      
+      // HarmonyOS WebView 调用 JS 方法的方式
+      const paramsObj: object = params || BridgeManager.EMPTY_OBJECT;
+      const script = `window.${methodName}(${JSON.stringify(paramsObj)})`;
+      if (webView.runJavaScript) {
+        webView.runJavaScript(script);
+      }
+    } catch (e) {
+      LogHelper.e(TAG, `调用 JS 方法失败: ${methodName}`, e as Error);
+    }
+  }
+  
+  /**
+   * 发送消息到 WebView
+   * 
+   * @param webView WebView 组件引用
+   * @param message 消息对象
+   */
+  static postMessage(webView: WebView, message: object): void {
+    try {
+      if (!webView) {
+        LogHelper.w(TAG, "WebView 引用为空");
+        return;
+      }
+      
+      // HarmonyOS WebView 发送消息的方式
+      const script = `window.postMessage(${JSON.stringify(message)})`;
+      if (webView.runJavaScript) {
+        webView.runJavaScript(script);
+      }
+    } catch (e) {
+      LogHelper.e(TAG, `发送消息到 WebView 失败`, e as Error);
+    }
+  }
+  
+  /**
+   * 处理来自 WebView 的消息
+   * 
+   * @param message 消息对象
+   * @return 处理结果
+   */
+  static handleMessage(message: WebViewMessage): WebViewResponse {
+    try {
+      const method = message.method;
+      const params: object = message.params || BridgeManager.EMPTY_OBJECT;
+      
+      if (!method || !BridgeManager.methods.has(method)) {
+        LogHelper.w(TAG, `未找到 JS 方法: ${method}`);
+        const errorResponse: WebViewResponse = {
+          success: false,
+          error: `方法 ${method} 不存在`
+        };
+        return errorResponse;
+      }
+      
+      const handler = BridgeManager.methods.get(method);
+      if (handler) {
+        const result = handler(params);
+        const successResponse: WebViewResponse = {
+          success: true,
+          data: result
+        };
+        return successResponse;
+      }
+      
+      const emptyHandlerResponse: WebViewResponse = {
+        success: false,
+        error: "处理方法为空"
+      };
+      return emptyHandlerResponse;
+    } catch (e) {
+      LogHelper.e(TAG, `处理 WebView 消息失败`, e as Error);
+      const errorResponse: WebViewResponse = {
+        success: false,
+        error: (e as Error).message
+      };
+      return errorResponse;
+    }
+  }
+  
+  /**
+   * 清除所有注册的方法
+   */
+  static clear(): void {
+    BridgeManager.methods.clear();
+    LogHelper.d(TAG, "清除所有注册的 JS 方法");
+  }
+  
+  /**
+   * 获取所有注册的方法名称
+   * 
+   * @return 方法名称数组
+   */
+  static getRegisteredMethods(): string[] {
+    return Array.from(BridgeManager.methods.keys());
+  }
+}
+

+ 178 - 0
base-common/src/main/ets/common/camera/CameraHelper.ets

@@ -0,0 +1,178 @@
+import { Context, common } from '@kit.AbilityKit';
+import { LogHelper } from '../log/LogHelper';
+import { PermissionHelper } from '../permission/PermissionHelper';
+
+const TAG = "CameraHelper";
+
+/**
+ * 相机助手
+ * 
+ * 统一封装相机调用功能,提供便捷的相机使用方式
+ * 
+ * 使用方式:
+ * ```typescript
+ * // 拍照
+ * CameraHelper.takePhoto(context, (photoUri) => {
+ *   // 处理拍摄的照片
+ * })
+ * 
+ * // 录制视频
+ * CameraHelper.recordVideo(context, (videoUri) => {
+ *   // 处理录制的视频
+ * })
+ * ```
+ */
+export class CameraHelper {
+  /**
+   * 拍照
+   * 
+   * @param context Context 实例
+   * @param onResult 拍照结果回调,参数为照片 URI
+   */
+  static async takePhoto(
+    context: Context,
+    onResult: (photoUri: string) => void
+  ): Promise<void> {
+    try {
+      // 检查相机权限(使用异步方法)
+      const hasPermission = await PermissionHelper.checkPermission(
+        context,
+        'ohos.permission.CAMERA'
+      );
+      
+      if (!hasPermission) {
+        // 请求权限
+        PermissionHelper.requestPermission(
+          context as common.UIAbilityContext,
+          'ohos.permission.CAMERA',
+          async (granted) => {
+            if (granted) {
+              await CameraHelper.takePhoto(context, onResult);
+            } else {
+              LogHelper.w(TAG, "相机权限被拒绝");
+            }
+          }
+        );
+        return;
+      }
+      
+      // 使用 HarmonyOS @kit.ImageKit 拍照
+      // 注意:需要导入 @kit.ImageKit,这里使用动态导入避免编译错误
+      try {
+        // TODO: 实现拍照功能
+        // 需要使用 @kit.ImageKit 的 PhotoViewPicker
+        // import { picker } from '@kit.ImageKit';
+        // const photoSelectOptions = new picker.PhotoSelectOptions();
+        // photoSelectOptions.MIMEType = picker.PhotoViewMIMETypes.IMAGE_TYPE;
+        // photoSelectOptions.maxSelectNumber = 1;
+        // const photoPicker = new picker.PhotoViewPicker();
+        // const photoSelectResult = await photoPicker.select(photoSelectOptions);
+        LogHelper.w(TAG, "拍照功能需要使用 @kit.ImageKit 实现,当前为占位实现");
+      } catch (e) {
+        const error = e instanceof Error ? e : new Error(String(e));
+        LogHelper.e(TAG, `拍照失败`, error);
+      }
+    } catch (e) {
+      LogHelper.e(TAG, `拍照异常`, e as Error);
+    }
+  }
+  
+  /**
+   * 录制视频
+   * 
+   * @param context Context 实例
+   * @param onResult 录制结果回调,参数为视频 URI
+   * @param maxDuration 最大录制时长(秒,默认 60)
+   */
+  static async recordVideo(
+    context: Context,
+    onResult: (videoUri: string) => void,
+    maxDuration: number = 60
+  ): Promise<void> {
+    try {
+      // 检查相机权限(使用异步方法)
+      const hasPermission = await PermissionHelper.checkPermission(
+        context,
+        'ohos.permission.CAMERA'
+      );
+      
+      if (!hasPermission) {
+        // 请求权限
+        PermissionHelper.requestPermission(
+          context as common.UIAbilityContext,
+          'ohos.permission.CAMERA',
+          async (granted) => {
+            if (granted) {
+              await CameraHelper.recordVideo(context, onResult, maxDuration);
+            } else {
+              LogHelper.w(TAG, "相机权限被拒绝");
+            }
+          }
+        );
+        return;
+      }
+      
+      // 使用 HarmonyOS @kit.ImageKit 录制视频
+      // 注意:需要导入 @kit.ImageKit,这里使用动态导入避免编译错误
+      try {
+        // TODO: 实现录制视频功能
+        // 需要使用 @kit.ImageKit 的 PhotoViewPicker
+        // import { picker } from '@kit.ImageKit';
+        // const videoSelectOptions = new picker.PhotoSelectOptions();
+        // videoSelectOptions.MIMEType = picker.PhotoViewMIMETypes.VIDEO_TYPE;
+        // videoSelectOptions.maxSelectNumber = 1;
+        // const photoPicker = new picker.PhotoViewPicker();
+        // const videoSelectResult = await photoPicker.select(videoSelectOptions);
+        LogHelper.w(TAG, "录制视频功能需要使用 @kit.ImageKit 实现,当前为占位实现");
+      } catch (e) {
+        const error = e instanceof Error ? e : new Error(String(e));
+        LogHelper.e(TAG, `录制视频失败`, error);
+      }
+    } catch (e) {
+      LogHelper.e(TAG, `录制视频异常`, e as Error);
+    }
+  }
+  
+  /**
+   * 检查相机是否可用
+   * 
+   * @param context Context 实例
+   * @return true 表示相机可用
+   */
+  /**
+   * 检查相机是否可用(异步方法)
+   * 
+   * @param context Context 实例
+   * @return Promise<boolean> true 表示相机可用
+   */
+  static async isCameraAvailableAsync(context: Context): Promise<boolean> {
+    try {
+      // 检查相机权限
+      const hasPermission = await PermissionHelper.checkPermission(
+        context,
+        'ohos.permission.CAMERA'
+      );
+      return hasPermission;
+    } catch (e) {
+      LogHelper.e(TAG, `检查相机可用性失败`, e as Error);
+      return false;
+    }
+  }
+
+  /**
+   * 检查相机是否可用(同步方法,占位实现)
+   * 
+   * ⚠️ 警告:这是占位方法,总是返回 false!
+   * 
+   * 实际使用时必须使用 isCameraAvailableAsync 方法。
+   * 
+   * @param context Context 实例
+   * @return 总是返回 false(占位实现)
+   * @deprecated 请使用 isCameraAvailableAsync 方法
+   */
+  static isCameraAvailable(context: Context): boolean {
+    LogHelper.w(TAG, "isCameraAvailable 是占位方法(总是返回 false),请使用 isCameraAvailableAsync 方法");
+    return false; // 占位实现
+  }
+}
+

+ 142 - 0
base-common/src/main/ets/common/config/ConfigManager.ets

@@ -0,0 +1,142 @@
+import { Context } from '@kit.AbilityKit';
+import { StorageImpl } from '@xdz/base-core';
+
+/**
+ * 配置管理器
+ * 
+ * 业务层封装,提供便捷的配置管理方式
+ * 底层使用 StorageImpl 统一存储
+ */
+export class ConfigManager {
+  private static readonly TAG = 'ConfigManager';
+  private static readonly KEY_ENVIRONMENT = 'environment';
+  private static readonly KEY_FEATURE_PREFIX = 'feature_';
+  
+  /**
+   * 初始化配置管理器
+   * 需要在 Application 中调用
+   * 
+   * @param context 上下文
+   */
+  static async init(context: Context): Promise<void> {
+    // 确保 StorageImpl 已初始化
+    if (!StorageImpl.isInitialized()) {
+      await StorageImpl.init(context);
+    }
+  }
+  
+  // ========== 基础配置操作 ==========
+  
+  /**
+   * 获取字符串配置
+   * 
+   * @param key 配置键
+   * @param defaultValue 默认值
+   * @returns 配置值
+   */
+  static async getString(key: string, defaultValue: string = ''): Promise<string> {
+    return await StorageImpl.getInstance().getString(key, defaultValue);
+  }
+  
+  /**
+   * 获取整数配置
+   * 
+   * @param key 配置键
+   * @param defaultValue 默认值
+   * @returns 配置值
+   */
+  static async getInt(key: string, defaultValue: number = 0): Promise<number> {
+    return await StorageImpl.getInstance().getInt(key, defaultValue);
+  }
+  
+  /**
+   * 获取布尔配置
+   * 
+   * @param key 配置键
+   * @param defaultValue 默认值
+   * @returns 配置值
+   */
+  static async getBoolean(key: string, defaultValue: boolean = false): Promise<boolean> {
+    return await StorageImpl.getInstance().getBoolean(key, defaultValue);
+  }
+  
+  /**
+   * 设置字符串配置
+   * 
+   * @param key 配置键
+   * @param value 配置值
+   */
+  static async setString(key: string, value: string): Promise<void> {
+    await StorageImpl.getInstance().putString(key, value);
+  }
+  
+  /**
+   * 设置整数配置
+   * 
+   * @param key 配置键
+   * @param value 配置值
+   */
+  static async setInt(key: string, value: number): Promise<void> {
+    await StorageImpl.getInstance().putInt(key, value);
+  }
+  
+  /**
+   * 设置布尔配置
+   * 
+   * @param key 配置键
+   * @param value 配置值
+   */
+  static async setBoolean(key: string, value: boolean): Promise<void> {
+    await StorageImpl.getInstance().putBoolean(key, value);
+  }
+  
+  // ========== 环境切换 ==========
+  
+  /**
+   * 获取当前环境
+   * 
+   * @returns 环境名称(dev, test, prod)
+   */
+  static async getEnvironment(): Promise<string> {
+    return await ConfigManager.getString(ConfigManager.KEY_ENVIRONMENT, 'dev');
+  }
+  
+  /**
+   * 设置环境
+   * 
+   * @param env 环境名称(dev, test, prod)
+   */
+  static async setEnvironment(env: string): Promise<void> {
+    await ConfigManager.setString(ConfigManager.KEY_ENVIRONMENT, env);
+  }
+  
+  // ========== 功能开关 ==========
+  
+  /**
+   * 检查功能是否启用
+   * 
+   * @param feature 功能名称
+   * @returns true 表示功能已启用
+   */
+  static async isFeatureEnabled(feature: string): Promise<boolean> {
+    return await ConfigManager.getBoolean(`${ConfigManager.KEY_FEATURE_PREFIX}${feature}`, false);
+  }
+  
+  /**
+   * 设置功能开关
+   * 
+   * @param feature 功能名称
+   * @param enabled 是否启用
+   */
+  static async setFeatureEnabled(feature: string, enabled: boolean): Promise<void> {
+    await ConfigManager.setBoolean(`${ConfigManager.KEY_FEATURE_PREFIX}${feature}`, enabled);
+  }
+  
+  /**
+   * 清除所有配置
+   */
+  static async clearAll(): Promise<void> {
+    await StorageImpl.getInstance().clear();
+  }
+}
+

+ 76 - 0
base-common/src/main/ets/common/config/ServerConfigManager.ets

@@ -0,0 +1,76 @@
+import { Context } from '@kit.AbilityKit';
+import { StorageImpl, ILog } from '@xdz/base-core';
+
+/**
+ * 服务器配置管理器
+ * 用于管理开发测试时的服务器地址配置
+ * 
+ * 统一配置服务器IP,然后根据不同服务类型连接不同端口:
+ * - HTTP API服务:18080(用户服务)、18082(消息服务)
+ * - SocketIO服务:9090
+ */
+export class ServerConfigManager {
+  private static readonly KEY_SERVER_IP = 'server_ip';
+  private static readonly DEFAULT_SERVER_IP = '192.168.1.107';
+  
+  // 服务端口配置
+  private static readonly PORT_HTTP_USER = 18080;
+  private static readonly PORT_HTTP_MESSAGE = 18082;
+  private static readonly PORT_SOCKETIO = 9090;
+  
+  /**
+   * 初始化(在Application中调用)
+   */
+  static async init(context: Context): Promise<void> {
+    // 确保 StorageImpl 已初始化
+    if (!StorageImpl.isInitialized()) {
+      await StorageImpl.init(context);
+    }
+    const ip = await ServerConfigManager.getServerIp();
+    ILog.d('ServerConfigManager', `初始化完成,当前IP: ${ip}`);
+  }
+  
+  /**
+   * 获取服务器IP地址
+   */
+  static async getServerIp(): Promise<string> {
+    const ip = await StorageImpl.getInstance().getString(ServerConfigManager.KEY_SERVER_IP);
+    return ip === '' ? ServerConfigManager.DEFAULT_SERVER_IP : ip;
+  }
+  
+  /**
+   * 设置服务器IP地址
+   */
+  static async setServerIp(ip: string): Promise<void> {
+    await StorageImpl.getInstance().putString(ServerConfigManager.KEY_SERVER_IP, ip);
+    ILog.d('ServerConfigManager', `服务器IP已更新为: ${ip}`);
+  }
+  
+  /**
+   * 获取HTTP API服务器地址(用户服务)
+   */
+  static async getHttpServerUrl(): Promise<string> {
+    const ip = await ServerConfigManager.getServerIp();
+    const url = `http://${ip}:${ServerConfigManager.PORT_HTTP_USER}/app-api/`;
+    ILog.d('ServerConfigManager', `HTTP服务器地址: ${url}`);
+    return url;
+  }
+  
+  /**
+   * 获取SocketIO服务器地址
+   */
+  static async getSocketIOUrl(): Promise<string> {
+    const ip = await ServerConfigManager.getServerIp();
+    const url = `http://${ip}:${ServerConfigManager.PORT_SOCKETIO}`;
+    ILog.d('ServerConfigManager', `SocketIO服务器地址: ${url}`);
+    return url;
+  }
+  
+  /**
+   * 重置为默认IP
+   */
+  static async resetToDefault(): Promise<void> {
+    await ServerConfigManager.setServerIp(ServerConfigManager.DEFAULT_SERVER_IP);
+  }
+}
+

+ 161 - 0
base-common/src/main/ets/common/crash/CrashHelper.ets

@@ -0,0 +1,161 @@
+import { LogHelper } from '../log/LogHelper';
+import { Context } from '@kit.AbilityKit';
+
+const TAG = "CrashHelper";
+
+/**
+ * 崩溃处理助手
+ * 
+ * 统一处理应用崩溃,记录崩溃日志并上报
+ * 
+ * HarmonyOS 版本:使用 ILog.collectCrash() 收集崩溃信息
+ * 
+ * 使用方式:
+ * ```typescript
+ * // 在 Application.onCreate() 中初始化
+ * CrashHelper.init(context)
+ * 
+ * // 手动捕获异常
+ * try {
+ *   // 可能出错的代码
+ * } catch (error) {
+ *   CrashHelper.handleException(error)
+ * }
+ * ```
+ */
+export class CrashHelper {
+  private static initialized: boolean = false;
+  private static crashCallback: ((error: Error, stackTrace: string) => void) | null = null;
+  
+  /**
+   * 初始化崩溃处理
+   * 
+   * @param context Context 实例
+   * @param onCrash 崩溃回调(可选,用于上报崩溃信息)
+   */
+  static init(
+    context: Context,
+    onCrash?: (error: Error, stackTrace: string) => void
+  ): void {
+    if (CrashHelper.initialized) {
+      LogHelper.w(TAG, "CrashHelper 已初始化,跳过重复初始化");
+      return;
+    }
+    
+    CrashHelper.crashCallback = onCrash || null;
+    
+    // HarmonyOS 不支持 window 对象,错误处理通过 try-catch 和 ILog.collectCrash() 实现
+    // 全局错误处理需要在应用层面实现
+    
+    CrashHelper.initialized = true;
+    LogHelper.d(TAG, "崩溃处理初始化完成");
+  }
+  
+  /**
+   * 处理 JavaScript 错误
+   * 
+   * HarmonyOS 版本:简化实现,不依赖 window.onerror
+   */
+  private static handleError(
+    message: string,
+    source: string,
+    lineno: number,
+    colno: number,
+    error?: Error
+  ): void {
+    const errorInfo = error || new Error(message);
+    const stackTrace = error?.stack || `${source}:${lineno}:${colno}`;
+    
+    CrashHelper.handleException(errorInfo, stackTrace);
+  }
+  
+  /**
+   * 处理未捕获的 Promise 拒绝
+   * 
+   * HarmonyOS 版本:简化实现,不依赖 PromiseRejectionEvent
+   */
+  private static handleUnhandledRejection(reason: object): void {
+    const error = reason instanceof Error 
+      ? reason 
+      : new Error(String(reason));
+    
+    CrashHelper.handleException(error);
+  }
+  
+  /**
+   * 处理异常
+   * 
+   * @param error 错误对象
+   * @param stackTrace 堆栈跟踪(可选,如果 error 有 stack 则自动获取)
+   */
+  static handleException(error: Error, stackTrace?: string): void {
+    const trace = stackTrace || error.stack || "无堆栈信息";
+    
+    // 记录崩溃日志
+    LogHelper.e(TAG, `应用崩溃: ${error.message}`, error);
+    LogHelper.e(TAG, `堆栈跟踪: ${trace}`, error);
+    
+    // 调用崩溃回调(用于上报)
+    if (CrashHelper.crashCallback) {
+      try {
+        CrashHelper.crashCallback(error, trace);
+      } catch (e) {
+        LogHelper.e(TAG, "崩溃回调执行失败", e as Error);
+      }
+    }
+    
+    // 可以在这里添加崩溃上报逻辑
+    CrashHelper.reportCrash(error, trace);
+  }
+  
+  /**
+   * 上报崩溃信息
+   * 
+   * @param error 错误对象
+   * @param stackTrace 堆栈跟踪
+   */
+  private static reportCrash(error: Error, stackTrace: string): void {
+    // 这里可以实现崩溃上报逻辑
+    // 例如:发送到服务器、保存到本地文件等
+    
+    interface CrashInfo {
+      message: string;
+      stackTrace: string;
+      timestamp: number;
+      platform: string;
+    }
+    
+    const crashInfo: CrashInfo = {
+      message: error.message,
+      stackTrace: stackTrace,
+      timestamp: Date.now(),
+      platform: 'HarmonyOS',
+    };
+    
+    LogHelper.d(TAG, `崩溃信息: ${JSON.stringify(crashInfo)}`);
+    
+    // TODO: 实现崩溃上报逻辑
+    // 1. 保存到本地文件
+    // 2. 发送到服务器
+    // 3. 使用第三方崩溃收集服务(如 Bugly、Sentry 等)
+  }
+  
+  /**
+   * 设置崩溃回调
+   * 
+   * @param callback 崩溃回调函数
+   */
+  static setCrashCallback(callback: (error: Error, stackTrace: string) => void): void {
+    CrashHelper.crashCallback = callback;
+  }
+  
+  /**
+   * 检查是否已初始化
+   * 
+   * @return true 表示已初始化
+   */
+  static isInitialized(): boolean {
+    return CrashHelper.initialized;
+  }
+}
+

+ 318 - 0
base-common/src/main/ets/common/dialog/DialogHelper.ets

@@ -0,0 +1,318 @@
+import { promptAction } from '@kit.ArkUI';
+import { Context } from '@kit.AbilityKit';
+import { LogHelper } from '../log/LogHelper';
+
+const TAG = "DialogHelper";
+
+/**
+ * 对话框管理器
+ * 
+ * 统一封装常用对话框,提供简洁美观的对话框体验
+ * 使用 HarmonyOS 的 promptAction API
+ * 
+ * 使用方式:
+ * ```typescript
+ * // 简单提示(只有一个确定按钮)
+ * DialogHelper.showAlert(context, "提示", "这是一个提示框")
+ * 
+ * // 确认对话框
+ * DialogHelper.showConfirm(context, "确认", "确定要删除吗?", () => {
+ *   // 确认操作
+ * })
+ * 
+ * // 输入对话框
+ * DialogHelper.showInput(context, "输入", "请输入用户名", (input) => {
+ *   // 处理输入
+ * })
+ * 
+ * // 列表选择对话框
+ * DialogHelper.showList(context, "选择", ["选项1", "选项2"], (index, item) => {
+ *   // 处理选择
+ * })
+ * ```
+ */
+export class DialogHelper {
+  /**
+   * 显示提示框(只有一个确定按钮)
+   * 
+   * @param context Context 实例
+   * @param title 标题
+   * @param message 消息内容
+   * @param confirmText 确定按钮文本(默认"确定")
+   * @param onConfirm 确定按钮回调(可选)
+   */
+  static async showAlert(
+    context: Context,
+    title: string,
+    message: string,
+    confirmText: string = "确定",
+    onConfirm?: () => void
+  ): Promise<void> {
+    try {
+      interface DialogButton {
+        text: string;
+        color: string;
+      }
+      const buttons: DialogButton[] = [
+        {
+          text: confirmText,
+          color: '#007DFF'
+        }
+      ];
+      const dialogOptions: promptAction.ShowDialogOptions = {
+        title: title,
+        message: message,
+        buttons: buttons
+      };
+      await promptAction.showDialog(dialogOptions).then((result) => {
+        if (result.index === 0 && onConfirm) {
+          onConfirm();
+        }
+      });
+    } catch (e) {
+      LogHelper.e(TAG, `显示提示框失败: ${JSON.stringify(e)}`, e as Error);
+    }
+  }
+  
+  /**
+   * 显示确认对话框(有确定和取消按钮)
+   * 
+   * @param context Context 实例
+   * @param title 标题
+   * @param message 消息内容
+   * @param confirmText 确定按钮文本(默认"确定")
+   * @param cancelText 取消按钮文本(默认"取消")
+   * @param onConfirm 确定按钮回调
+   * @param onCancel 取消按钮回调(可选)
+   */
+  static async showConfirm(
+    context: Context,
+    title: string,
+    message: string,
+    confirmText: string = "确定",
+    cancelText: string = "取消",
+    onConfirm: () => void,
+    onCancel?: () => void
+  ): Promise<void> {
+    try {
+      interface DialogButton {
+        text: string;
+        color: string;
+      }
+      const buttons: DialogButton[] = [
+        {
+          text: cancelText,
+          color: '#999999'
+        },
+        {
+          text: confirmText,
+          color: '#007DFF'
+        }
+      ];
+      const dialogOptions: promptAction.ShowDialogOptions = {
+        title: title,
+        message: message,
+        buttons: buttons
+      };
+      await promptAction.showDialog(dialogOptions).then((result) => {
+        if (result.index === 0) {
+          // 取消按钮
+          if (onCancel) {
+            onCancel();
+          }
+        } else if (result.index === 1) {
+          // 确定按钮
+          onConfirm();
+        }
+      });
+    } catch (e) {
+      LogHelper.e(TAG, `显示确认对话框失败: ${JSON.stringify(e)}`, e as Error);
+    }
+  }
+  
+  /**
+   * 显示输入对话框
+   * 
+   * 注意:HarmonyOS 的 promptAction.showDialog 不支持输入框,
+   * 这里使用 showActionMenu 作为替代方案,或者需要自定义 Dialog
+   * 
+   * @param context Context 实例
+   * @param title 标题
+   * @param message 提示信息
+   * @param placeholder 输入框占位符(可选)
+   * @param defaultValue 默认值(可选)
+   * @param onConfirm 确认回调,参数为输入的内容
+   * @param onCancel 取消回调(可选)
+   */
+  static async showInput(
+    context: Context,
+    title: string,
+    message: string,
+    placeholder: string = "请输入",
+    defaultValue: string = "",
+    onConfirm: (input: string) => void,
+    onCancel?: () => void
+  ): Promise<void> {
+    // HarmonyOS promptAction 不支持输入框,需要使用自定义 Dialog
+    // 这里先使用 showActionMenu 作为临时方案
+    LogHelper.w(TAG, "showInput 在 HarmonyOS 中需要使用自定义 Dialog,当前使用临时方案");
+    
+    try {
+      // 临时方案:显示一个简单的提示,提示用户需要自定义实现
+      await DialogHelper.showAlert(
+        context,
+        title,
+        `${message}\n\n注意:HarmonyOS 需要自定义 Dialog 实现输入框功能`,
+        "确定",
+        () => {
+          // 临时返回默认值
+          onConfirm(defaultValue);
+        }
+      );
+    } catch (e) {
+      LogHelper.e(TAG, `显示输入对话框失败: ${JSON.stringify(e)}`, e as Error);
+    }
+  }
+  
+  /**
+   * 显示列表选择对话框
+   * 
+   * @param context Context 实例
+   * @param title 标题
+   * @param items 选项列表
+   * @param onSelect 选择回调,参数为索引和选项内容
+   * @param onCancel 取消回调(可选)
+   */
+  static async showList(
+    context: Context,
+    title: string,
+    items: string[],
+    onSelect: (index: number, item: string) => void,
+    onCancel?: () => void
+  ): Promise<void> {
+    try {
+      interface ActionMenuButton {
+        text: string;
+        color?: string;
+      }
+      const buttons: ActionMenuButton[] = [];
+      for (let i = 0; i < items.length; i++) {
+        buttons.push({
+          text: items[i],
+          color: '#007DFF'
+        });
+      }
+      // 转换为元组类型(最多6个按钮)
+      const button0: promptAction.Button = buttons.length > 0 ? {
+        text: buttons[0].text,
+        color: buttons[0].color || '#007DFF'
+      } : { text: '', color: '#007DFF' };
+      const button1: promptAction.Button | undefined = buttons.length > 1 ? {
+        text: buttons[1].text,
+        color: buttons[1].color || '#007DFF'
+      } : undefined;
+      const button2: promptAction.Button | undefined = buttons.length > 2 ? {
+        text: buttons[2].text,
+        color: buttons[2].color || '#007DFF'
+      } : undefined;
+      const button3: promptAction.Button | undefined = buttons.length > 3 ? {
+        text: buttons[3].text,
+        color: buttons[3].color || '#007DFF'
+      } : undefined;
+      const button4: promptAction.Button | undefined = buttons.length > 4 ? {
+        text: buttons[4].text,
+        color: buttons[4].color || '#007DFF'
+      } : undefined;
+      const button5: promptAction.Button | undefined = buttons.length > 5 ? {
+        text: buttons[5].text,
+        color: buttons[5].color || '#007DFF'
+      } : undefined;
+      
+      const buttonsTuple: [promptAction.Button, promptAction.Button?, promptAction.Button?, promptAction.Button?, promptAction.Button?, promptAction.Button?] = 
+        [button0, button1, button2, button3, button4, button5];
+      
+      const actionMenuOptions: promptAction.ActionMenuOptions = {
+        title: title,
+        buttons: buttonsTuple
+      };
+      await promptAction.showActionMenu(actionMenuOptions).then((result) => {
+        if (result.index >= 0 && result.index < items.length) {
+          onSelect(result.index, items[result.index]);
+        } else {
+          if (onCancel) {
+            onCancel();
+          }
+        }
+      });
+    } catch (e) {
+      LogHelper.e(TAG, `显示列表选择对话框失败: ${JSON.stringify(e)}`, e as Error);
+    }
+  }
+  
+  /**
+   * 显示自定义对话框(扩展方法)
+   * 
+   * 用于显示更复杂的对话框,需要自定义实现
+   * 
+   * @param context Context 实例
+   * @param options 对话框选项
+   */
+  static async showCustom(
+    context: Context,
+    options: CustomDialogOptions
+  ): Promise<void> {
+    try {
+      interface PromptButton {
+        text: string;
+        color: string;
+      }
+      const buttons: PromptButton[] = [];
+      if (options.buttons) {
+        for (let i = 0; i < options.buttons.length; i++) {
+          const btn = options.buttons[i];
+          const promptBtn: PromptButton = {
+            text: btn.text,
+            color: btn.color || '#007DFF'
+          };
+          buttons.push(promptBtn);
+        }
+      }
+      const dialogOptions: promptAction.ShowDialogOptions = {
+        title: options.title || "",
+        message: options.message || "",
+        buttons: buttons
+      };
+      await promptAction.showDialog(dialogOptions).then((result: promptAction.ShowDialogSuccessResponse) => {
+        if (result.index >= 0 && options.buttons && options.buttons[result.index]) {
+          const btn = options.buttons[result.index];
+          if (btn.action) {
+            btn.action();
+          }
+        }
+      });
+    } catch (e) {
+      const error: Error = e instanceof Error ? e : new Error(String(e));
+      const errorMsg = error.message;
+      LogHelper.e(TAG, `显示自定义对话框失败: ${errorMsg}`, error);
+    }
+  }
+}
+
+/**
+ * 自定义对话框按钮接口
+ */
+export interface CustomDialogButton {
+  text: string;
+  color?: string;
+  action?: () => void;
+}
+
+/**
+ * 自定义对话框选项接口
+ */
+export interface CustomDialogOptions {
+  title?: string;
+  message?: string;
+  buttons?: Array<CustomDialogButton>;
+}
+

+ 199 - 0
base-common/src/main/ets/common/executor/ExecutorManager.ets

@@ -0,0 +1,199 @@
+import { LogHelper } from '../log/LogHelper';
+
+const TAG = "ExecutorManager";
+
+/**
+ * 执行器管理器
+ * 
+ * 统一管理异步任务执行,提供便捷的任务调度方式
+ * 
+ * 注意:HarmonyOS 使用 Promise/async-await 进行异步处理,
+ * 这个类主要用于提供统一的 API 接口和任务管理
+ * 
+ * 使用方式:
+ * ```typescript
+ * // 执行异步任务
+ * ExecutorManager.execute(async () => {
+ *   // 异步任务
+ *   return await someAsyncOperation();
+ * })
+ * 
+ * // 延迟执行
+ * ExecutorManager.delay(1000, () => {
+ *   // 延迟执行的任务
+ * })
+ * 
+ * // 定时执行
+ * const timer = ExecutorManager.setInterval(() => {
+ *   // 定时执行的任务
+ * }, 1000)
+ * 
+ * // 取消定时器
+ * ExecutorManager.clearInterval(timer)
+ * ```
+ */
+export class ExecutorManager {
+  private static timers: Map<number, number> = new Map();
+  private static timerIdCounter: number = 0;
+  
+  /**
+   * 执行异步任务
+   * 
+   * @param task 异步任务函数
+   * @return Promise<T> 任务结果
+   */
+  static async execute<T>(task: () => Promise<T>): Promise<T> {
+    try {
+      return await task();
+    } catch (e) {
+      LogHelper.e(TAG, `执行异步任务失败`, e as Error);
+      if (e instanceof Error) {
+        throw e;
+      } else {
+        throw new Error(String(e));
+      }
+    }
+  }
+  
+  /**
+   * 延迟执行
+   * 
+   * @param delay 延迟时间(毫秒)
+   * @param task 要执行的任务
+   * @return 定时器 ID
+   */
+  static delay(delay: number, task: () => void): number {
+    const timerId = setTimeout(() => {
+      try {
+        task();
+      } catch (e) {
+        LogHelper.e(TAG, `延迟执行任务失败`, e as Error);
+      }
+      ExecutorManager.timers.delete(timerId);
+    }, delay) as number;
+    
+    ExecutorManager.timers.set(timerId, timerId);
+    return timerId;
+  }
+  
+  /**
+   * 定时执行
+   * 
+   * @param task 要执行的任务
+   * @param interval 执行间隔(毫秒)
+   * @return 定时器 ID
+   */
+  static setInterval(task: () => void, interval: number): number {
+    const timerId = setInterval(() => {
+      try {
+        task();
+      } catch (e) {
+        LogHelper.e(TAG, `定时执行任务失败`, e as Error);
+      }
+    }, interval) as number;
+    
+    ExecutorManager.timers.set(timerId, timerId);
+    return timerId;
+  }
+  
+  /**
+   * 取消定时器
+   * 
+   * @param timerId 定时器 ID
+   */
+  static clearInterval(timerId: number): void {
+    if (ExecutorManager.timers.has(timerId)) {
+      clearInterval(timerId);
+      ExecutorManager.timers.delete(timerId);
+    }
+  }
+  
+  /**
+   * 取消延迟执行
+   * 
+   * @param timerId 定时器 ID
+   */
+  static clearTimeout(timerId: number): void {
+    if (ExecutorManager.timers.has(timerId)) {
+      clearTimeout(timerId);
+      ExecutorManager.timers.delete(timerId);
+    }
+  }
+  
+  /**
+   * 清除所有定时器
+   */
+  static clearAllTimers(): void {
+    ExecutorManager.timers.forEach((timerId) => {
+      clearInterval(timerId);
+      clearTimeout(timerId);
+    });
+    ExecutorManager.timers.clear();
+    LogHelper.d(TAG, "清除所有定时器");
+  }
+  
+  /**
+   * 并行执行多个任务
+   * 
+   * @param tasks 任务数组
+   * @return Promise<结果数组>
+   */
+  static async executeAll<T>(tasks: Array<() => Promise<T>>): Promise<T[]> {
+    return Promise.all(tasks.map(task => ExecutorManager.execute(task)));
+  }
+  
+  /**
+   * 串行执行多个任务
+   * 
+   * @param tasks 任务数组
+   * @return Promise<结果数组>
+   */
+  static async executeSequentially<T>(tasks: Array<() => Promise<T>>): Promise<T[]> {
+    const results: T[] = [];
+    for (const task of tasks) {
+      const result = await ExecutorManager.execute(task);
+      results.push(result);
+    }
+    return results;
+  }
+  
+  /**
+   * 重试执行任务
+   * 
+   * @param task 要执行的任务
+   * @param maxRetries 最大重试次数(默认 3)
+   * @param delay 重试延迟(毫秒,默认 1000)
+   * @return Promise<T> 任务结果
+   */
+  static async executeWithRetry<T>(
+    task: () => Promise<T>,
+    maxRetries: number = 3,
+    delay: number = 1000
+  ): Promise<T> {
+    let lastError: Error | null = null;
+    
+    for (let i = 0; i < maxRetries; i++) {
+      try {
+        return await ExecutorManager.execute(task);
+      } catch (e) {
+        lastError = e as Error;
+        LogHelper.w(TAG, `任务执行失败,重试 ${i + 1}/${maxRetries}: ${lastError.message}`);
+        
+        if (i < maxRetries - 1) {
+          await new Promise<void>((resolve) => {
+            setTimeout(() => {
+              resolve();
+            }, delay);
+          });
+        }
+      }
+    }
+    
+    if (lastError) {
+      throw lastError;
+    } else {
+      throw new Error("任务执行失败");
+    }
+  }
+}
+

+ 156 - 0
base-common/src/main/ets/common/file/FilePickerHelper.ets

@@ -0,0 +1,156 @@
+import { picker } from '@kit.CoreFileKit';
+import { Context } from '@kit.AbilityKit';
+import { LogHelper } from '../log/LogHelper';
+
+const TAG = "FilePickerHelper";
+
+/**
+ * 文件选择器助手
+ * 
+ * 统一封装文件选择功能,提供便捷的文件选择方式
+ * 
+ * 使用方式:
+ * ```typescript
+ * // 选择单个文件
+ * FilePickerHelper.pickFile(context, (fileUri) => {
+ *   // 处理选择的文件
+ * })
+ * 
+ * // 选择多个文件
+ * FilePickerHelper.pickFiles(context, (fileUris) => {
+ *   // 处理选择的文件列表
+ * })
+ * 
+ * // 选择图片
+ * FilePickerHelper.pickImage(context, (imageUri) => {
+ *   // 处理选择的图片
+ * })
+ * ```
+ */
+export class FilePickerHelper {
+  /**
+   * 选择单个文件
+   * 
+   * @param context Context 实例
+   * @param onResult 选择结果回调,参数为文件 URI
+   * @param fileTypes 文件类型过滤(可选,如 ['image/*', 'application/pdf'])
+   */
+  static async pickFile(
+    context: Context,
+    onResult: (fileUri: string) => void,
+    fileTypes?: string[]
+  ): Promise<void> {
+    try {
+      const photoViewPicker = new picker.PhotoViewPicker();
+      const photoSelectOptions = new picker.PhotoSelectOptions();
+      
+      if (fileTypes && fileTypes.length > 0) {
+        // 设置文件类型过滤
+        photoSelectOptions.MIMEType = picker.PhotoViewMIMETypes.IMAGE_TYPE;
+      }
+      
+      photoSelectOptions.maxSelectNumber = 1;
+      
+      const photoSelectResult = await photoViewPicker.select(photoSelectOptions);
+      
+      if (photoSelectResult && photoSelectResult.photoUris.length > 0) {
+        onResult(photoSelectResult.photoUris[0]);
+      }
+    } catch (e) {
+      LogHelper.e(TAG, `选择文件失败`, e as Error);
+    }
+  }
+  
+  /**
+   * 选择多个文件
+   * 
+   * @param context Context 实例
+   * @param onResult 选择结果回调,参数为文件 URI 数组
+   * @param maxCount 最大选择数量(默认 9)
+   * @param fileTypes 文件类型过滤(可选)
+   */
+  static async pickFiles(
+    context: Context,
+    onResult: (fileUris: string[]) => void,
+    maxCount: number = 9,
+    fileTypes?: string[]
+  ): Promise<void> {
+    try {
+      const photoViewPicker = new picker.PhotoViewPicker();
+      const photoSelectOptions = new picker.PhotoSelectOptions();
+      
+      if (fileTypes && fileTypes.length > 0) {
+        photoSelectOptions.MIMEType = picker.PhotoViewMIMETypes.IMAGE_TYPE;
+      }
+      
+      photoSelectOptions.maxSelectNumber = maxCount;
+      
+      const photoSelectResult = await photoViewPicker.select(photoSelectOptions);
+      
+      if (photoSelectResult && photoSelectResult.photoUris.length > 0) {
+        onResult(photoSelectResult.photoUris);
+      }
+    } catch (e) {
+      LogHelper.e(TAG, `选择多个文件失败`, e as Error);
+    }
+  }
+  
+  /**
+   * 选择图片
+   * 
+   * @param context Context 实例
+   * @param onResult 选择结果回调,参数为图片 URI
+   */
+  static async pickImage(
+    context: Context,
+    onResult: (imageUri: string) => void
+  ): Promise<void> {
+    await FilePickerHelper.pickFile(context, onResult, ['image/*']);
+  }
+  
+  /**
+   * 选择多个图片
+   * 
+   * @param context Context 实例
+   * @param onResult 选择结果回调,参数为图片 URI 数组
+   * @param maxCount 最大选择数量(默认 9)
+   */
+  static async pickImages(
+    context: Context,
+    onResult: (imageUris: string[]) => void,
+    maxCount: number = 9
+  ): Promise<void> {
+    await FilePickerHelper.pickFiles(context, onResult, maxCount, ['image/*']);
+  }
+  
+  /**
+   * 选择视频
+   * 
+   * @param context Context 实例
+   * @param onResult 选择结果回调,参数为视频 URI
+   */
+  static async pickVideo(
+    context: Context,
+    onResult: (videoUri: string) => void
+  ): Promise<void> {
+    await FilePickerHelper.pickFile(context, onResult, ['video/*']);
+  }
+  
+  /**
+   * 选择文档
+   * 
+   * @param context Context 实例
+   * @param onResult 选择结果回调,参数为文档 URI
+   */
+  static async pickDocument(
+    context: Context,
+    onResult: (documentUri: string) => void
+  ): Promise<void> {
+    await FilePickerHelper.pickFile(context, onResult, [
+      'application/pdf',
+      'application/msword',
+      'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
+    ]);
+  }
+}
+

+ 317 - 0
base-common/src/main/ets/common/image/ImageLoader.ets

@@ -0,0 +1,317 @@
+import { LogHelper } from '../log/LogHelper';
+import { Context } from '@kit.AbilityKit';
+import { fileIo } from '@kit.CoreFileKit';
+import { http } from '@kit.NetworkKit';
+
+const TAG = "ImageLoader";
+
+/**
+ * ImageView 接口(用于类型定义)
+ */
+export interface ImageView {
+  src?: string;
+}
+
+/**
+ * 图片尺寸接口
+ */
+export interface ImageSize {
+  width: number;
+  height: number;
+}
+
+/**
+ * 图片加载器
+ * 
+ * 统一封装图片加载功能,提供便捷的图片加载方式
+ * 
+ * 注意:HarmonyOS 的图片加载通常使用 Image 组件的 src 属性直接加载
+ * 这个类主要用于提供统一的 API 接口和缓存管理
+ * 
+ * 使用方式:
+ * ```typescript
+ * // 加载网络图片
+ * ImageLoader.load(imageView, "https://example.com/image.jpg")
+ * 
+ * // 加载本地图片
+ * ImageLoader.load(imageView, "/data/storage/image.jpg")
+ * 
+ * // 加载并缓存
+ * ImageLoader.loadWithCache(imageView, "https://example.com/image.jpg")
+ * ```
+ */
+export class ImageLoader {
+  private static imageCache: Map<string, string> = new Map(); // URL -> 本地路径
+  private static context: Context | null = null;
+  
+  /**
+   * 初始化图片加载器(设置 Context 用于文件存储)
+   */
+  static init(context: Context): void {
+    ImageLoader.context = context;
+    LogHelper.d(TAG, "ImageLoader 初始化完成");
+  }
+
+  /**
+   * 加载图片
+   * 
+   * @param imageView Image 组件引用(在 HarmonyOS 中直接使用 src 属性)
+   * @param url 图片 URL(网络或本地路径)
+   * @param placeholder 占位图(可选)
+   * @param errorImage 错误占位图(可选)
+   */
+  static load(
+    imageView: ImageView,
+    url: string,
+    placeholder?: string,
+    errorImage?: string
+  ): void {
+    try {
+      // HarmonyOS 中图片加载直接使用 Image 组件的 src 属性
+      // 这里提供统一的 API 接口
+      if (imageView && typeof imageView.src !== 'undefined') {
+        imageView.src = url;
+      } else {
+        LogHelper.w(TAG, "ImageLoader.load: imageView 不支持 src 属性");
+      }
+    } catch (e) {
+      LogHelper.e(TAG, `加载图片失败: ${url}`, e as Error);
+      if (errorImage && imageView) {
+        imageView.src = errorImage;
+      }
+    }
+  }
+  
+  /**
+   * 加载图片(带缓存)
+   * 
+   * 如果是网络图片,会下载到本地并缓存;如果是本地图片,直接加载
+   * 
+   * @param imageView Image 组件引用
+   * @param url 图片 URL(网络或本地路径)
+   * @param placeholder 占位图(可选)
+   * @param errorImage 错误占位图(可选)
+   */
+  static async loadWithCache(
+    imageView: ImageView,
+    url: string,
+    placeholder?: string,
+    errorImage?: string
+  ): Promise<void> {
+    try {
+      // 如果是本地路径,直接加载
+      if (!url.startsWith('http://') && !url.startsWith('https://')) {
+        ImageLoader.load(imageView, url, placeholder, errorImage);
+        return;
+      }
+      
+      // 检查缓存
+      if (ImageLoader.imageCache.has(url)) {
+        const cachedPath = ImageLoader.imageCache.get(url);
+        if (cachedPath) {
+          // 检查缓存文件是否存在
+          try {
+            const stat = await fileIo.stat(cachedPath);
+            if (stat.isFile()) {
+              ImageLoader.load(imageView, cachedPath, placeholder, errorImage);
+              return;
+            } else {
+              // 缓存文件不存在,移除缓存记录
+              ImageLoader.imageCache.delete(url);
+            }
+          } catch (e) {
+            // 缓存文件不存在,移除缓存记录
+            ImageLoader.imageCache.delete(url);
+          }
+        }
+      }
+      
+      // 显示占位图
+      if (placeholder && imageView) {
+        imageView.src = placeholder;
+      }
+      
+      // 下载图片
+      const localPath = await ImageLoader.downloadImage(url);
+      if (localPath) {
+        // 缓存成功,加载本地图片
+        ImageLoader.imageCache.set(url, localPath);
+        ImageLoader.load(imageView, localPath, placeholder, errorImage);
+      } else {
+        // 下载失败,加载原 URL 或错误图片
+        if (errorImage && imageView) {
+          imageView.src = errorImage;
+        } else {
+          ImageLoader.load(imageView, url, placeholder, errorImage);
+        }
+      }
+    } catch (e) {
+      LogHelper.e(TAG, `加载图片失败: ${url}`, e as Error);
+      if (errorImage && imageView) {
+        imageView.src = errorImage;
+      }
+    }
+  }
+  
+  /**
+   * 下载图片到本地
+   * 
+   * @param url 图片 URL
+   * @return Promise<string | null> 本地文件路径,失败返回 null
+   */
+  private static async downloadImage(url: string): Promise<string | null> {
+    if (!ImageLoader.context) {
+      LogHelper.w(TAG, "ImageLoader 未初始化,无法下载图片");
+      return null;
+    }
+    
+    try {
+      // 生成缓存文件名(使用 URL 的 MD5 或简单哈希)
+      const urlHash = ImageLoader.hashUrl(url);
+      const cacheDir = `${ImageLoader.context.cacheDir}/image_cache`;
+      const fileName = `${urlHash}.jpg`;
+      const filePath = `${cacheDir}/${fileName}`;
+      
+      // 确保缓存目录存在
+      try {
+        await fileIo.mkdir(cacheDir, true);
+      } catch (e) {
+        // 目录可能已存在
+      }
+      
+      // 下载图片(使用 http 模块直接下载)
+      // 注意:NetworkManager 的 get 方法返回的是 JSON 解析后的数据,不适合下载二进制文件
+      // 这里需要使用 http 模块直接下载
+      const httpRequest = http.createHttp();
+      try {
+        const response: http.HttpResponse = await httpRequest.request(url, {
+          method: http.RequestMethod.GET,
+          header: {
+            'Accept': 'image/*'
+          },
+          readTimeout: 60000,
+          connectTimeout: 60000
+        });
+        
+        if (response.responseCode >= 200 && response.responseCode < 300) {
+          // response.result 可能是 ArrayBuffer 或 string
+          if (response.result instanceof ArrayBuffer) {
+            // 保存到本地
+            const file = await fileIo.open(filePath, fileIo.OpenMode.CREATE | fileIo.OpenMode.WRITE_ONLY | fileIo.OpenMode.TRUNC);
+            await fileIo.write(file.fd, response.result);
+            await fileIo.close(file.fd);
+            
+            LogHelper.d(TAG, `图片下载成功: ${url} -> ${filePath}`);
+            return filePath;
+          } else if (typeof response.result === 'string') {
+            // 如果是字符串,转换为 Uint8Array 再保存
+            const uint8Array = new Uint8Array(response.result.length);
+            for (let i = 0; i < response.result.length; i++) {
+              uint8Array[i] = response.result.charCodeAt(i);
+            }
+            const file = await fileIo.open(filePath, fileIo.OpenMode.CREATE | fileIo.OpenMode.WRITE_ONLY | fileIo.OpenMode.TRUNC);
+            await fileIo.write(file.fd, uint8Array.buffer);
+            await fileIo.close(file.fd);
+            
+            LogHelper.d(TAG, `图片下载成功: ${url} -> ${filePath}`);
+            return filePath;
+          } else {
+            LogHelper.w(TAG, `下载图片失败: 响应格式不正确`);
+            return null;
+          }
+        } else {
+          LogHelper.w(TAG, `下载图片失败: HTTP ${response.responseCode}`);
+          return null;
+        }
+      } finally {
+        httpRequest.destroy();
+      }
+    } catch (e) {
+      LogHelper.e(TAG, `下载图片失败: ${url}`, e as Error);
+      return null;
+    }
+  }
+  
+  /**
+   * 简单的 URL 哈希函数(用于生成缓存文件名)
+   */
+  private static hashUrl(url: string): string {
+    let hash = 0;
+    for (let i = 0; i < url.length; i++) {
+      const char = url.charCodeAt(i);
+      hash = ((hash << 5) - hash) + char;
+      hash = hash & hash; // Convert to 32bit integer
+    }
+    return Math.abs(hash).toString(16);
+  }
+  
+  /**
+   * 清除图片缓存
+   */
+  static async clearCache(): Promise<void> {
+    if (!ImageLoader.context) {
+      LogHelper.w(TAG, "ImageLoader 未初始化,无法清除缓存");
+      return;
+    }
+    
+    try {
+      const cacheDir = `${ImageLoader.context.cacheDir}/image_cache`;
+      // 删除缓存目录中的所有文件
+      const files = await fileIo.listFile(cacheDir);
+      for (let i = 0; i < files.length; i++) {
+        const filePath = `${cacheDir}/${files[i]}`;
+        try {
+          await fileIo.unlink(filePath);
+        } catch (e) {
+          LogHelper.w(TAG, `删除缓存文件失败: ${filePath}`);
+        }
+      }
+      ImageLoader.imageCache.clear();
+      LogHelper.d(TAG, "图片缓存已清除");
+    } catch (e) {
+      LogHelper.e(TAG, "清除图片缓存失败", e as Error);
+    }
+  }
+  
+  /**
+   * 预加载图片
+   * 
+   * @param urls 图片 URL 数组
+   */
+  static async preload(urls: string[]): Promise<void> {
+    const promises: Promise<void>[] = [];
+    for (let i = 0; i < urls.length; i++) {
+      const url = urls[i];
+      // 如果是网络图片,下载到缓存
+      if (url.startsWith('http://') || url.startsWith('https://')) {
+        promises.push(ImageLoader.downloadImage(url).then(localPath => {
+          if (localPath) {
+            ImageLoader.imageCache.set(url, localPath);
+            LogHelper.d(TAG, `预加载图片成功: ${url}`);
+          }
+        }));
+      }
+    }
+    await Promise.all(promises);
+    LogHelper.d(TAG, `预加载完成,共 ${urls.length} 张图片`);
+  }
+  
+  /**
+   * 获取图片尺寸
+   * 
+   * @param url 图片 URL
+   * @return Promise<ImageSize | null> 图片尺寸
+   */
+  static async getImageSize(url: string): Promise<ImageSize | null> {
+    try {
+      // HarmonyOS 需要使用 image 模块获取图片尺寸
+      // 这里返回 null,提示需要实现
+      LogHelper.w(TAG, "getImageSize 需要使用 @kit.CoreFileKit 实现");
+      return null;
+    } catch (e) {
+      LogHelper.e(TAG, `获取图片尺寸失败: ${url}`, e as Error);
+      return null;
+    }
+  }
+}
+

+ 38 - 0
base-common/src/main/ets/common/log/LogHelper.ets

@@ -0,0 +1,38 @@
+import { ILog } from '@xdz/base-core';
+
+/**
+ * 日志工具类(业务层封装)
+ * 
+ * 提供便捷的日志记录方法
+ * 底层使用 base-core 的 ILog
+ */
+export class LogHelper {
+  /**
+   * 调试日志
+   */
+  static d(tag: string, message: string): void {
+    ILog.d(tag, message);
+  }
+  
+  /**
+   * 信息日志
+   */
+  static i(tag: string, message: string): void {
+    ILog.i(tag, message);
+  }
+  
+  /**
+   * 警告日志
+   */
+  static w(tag: string, message: string): void {
+    ILog.w(tag, message);
+  }
+  
+  /**
+   * 错误日志
+   */
+  static e(tag: string, message: string, error?: Error): void {
+    ILog.e(tag, message, error);
+  }
+}
+

+ 121 - 0
base-common/src/main/ets/common/network/ApiBaseRemoteDataSource.ets

@@ -0,0 +1,121 @@
+import { NetworkManager, ILog } from '@xdz/base-core';
+import { NetworkHelper } from './NetworkHelper';
+import { LogHelper } from '../log/LogHelper';
+import { Result } from './ApiBaseRepository';
+
+// 重新导出 Result 类型,方便其他模块使用
+export { Result };
+
+/**
+ * API 基础远程数据源
+ * 
+ * 封装通用网络请求逻辑,统一处理:
+ * - 错误处理和异常捕获
+ * - 日志记录
+ * - 网络异常友好提示
+ * 
+ * 使用方式:
+ * ```typescript
+ * class AuthRemoteDataSource extends ApiBaseRemoteDataSource {
+ *   async login(request: LoginRequest): Promise<Result<LoginResponse>> {
+ *     return await this.executeRequest(
+ *       async () => {
+ *         const authApi = await ApiServiceFactory.create<AuthApi>();
+ *         return await authApi.login(request);
+ *       },
+ *       "登录失败"
+ *     );
+ *   }
+ * }
+ * ```
+ */
+export abstract class ApiBaseRemoteDataSource {
+  /**
+   * 获取日志标签(子类可重写)
+   */
+  protected getTag(): string {
+    return this.constructor.name || 'ApiBaseRemoteDataSource';
+  }
+  
+  /**
+   * 处理网络请求(通用方法)
+   * 
+   * 自动处理:
+   * - HTTP 错误码
+   * - 业务错误码
+   * - 网络异常
+   * - 超时异常
+   * - 日志记录
+   * 
+   * @param request 网络请求的异步函数
+   * @param errorMessage 错误消息前缀
+   * @returns Promise<Result<T>>
+   */
+  protected async executeRequest<T>(
+    request: () => Promise<T>,
+    errorMessage: string = '请求失败'
+  ): Promise<Result<T>> {
+    try {
+      const tag = this.getTag();
+      LogHelper.d(tag, '开始请求');
+      
+      const response = await request();
+      
+      LogHelper.d(tag, '请求成功');
+      return Result.success(response);
+    } catch (error) {
+      const tag = this.getTag();
+      let errorMsg = errorMessage;
+      
+      if (error instanceof Error) {
+        if (error.message.includes('timeout') || error.message.includes('超时')) {
+          errorMsg = '请求超时,请检查网络连接';
+        } else if (error.message.includes('network') || error.message.includes('网络')) {
+          errorMsg = '网络连接失败,请检查网络设置';
+        } else {
+          errorMsg = error.message || errorMessage;
+        }
+        LogHelper.e(tag, `请求异常: ${errorMsg}`, error);
+        return Result.failure(error);
+      } else {
+        const err = new Error(errorMessage);
+        LogHelper.e(tag, `请求异常: ${errorMessage}`, err);
+        return Result.failure(err);
+      }
+    }
+  }
+  
+  /**
+   * 发送 HTTP 请求(封装 NetworkManager)
+   * 
+   * @param url 请求 URL(完整路径或相对路径)
+   * @param method HTTP 方法
+   * @param data 请求数据(可选)
+   * @returns Promise<T>
+   */
+  protected async sendRequest<T>(
+    url: string,
+    method: 'GET' | 'POST' | 'PUT' | 'DELETE' = 'POST',
+    data?: object
+  ): Promise<T> {
+    const baseUrl = NetworkHelper.getBaseUrl();
+    const fullUrl = url.startsWith('http') ? url : `${baseUrl}${url}`;
+    const headers = await NetworkHelper.getHeaders();
+    
+    const networkManager = NetworkManager.getInstance();
+    
+    let response: T;
+    if (method === 'GET') {
+      response = await networkManager.get<T>(fullUrl, headers);
+    } else if (method === 'POST') {
+      response = await networkManager.post<T>(fullUrl, data, headers);
+    } else if (method === 'PUT') {
+      response = await networkManager.put<T>(fullUrl, data, headers);
+    } else {
+      response = await networkManager.delete<T>(fullUrl, headers);
+    }
+    
+    return response;
+  }
+}
+

+ 105 - 0
base-common/src/main/ets/common/network/ApiBaseRepository.ets

@@ -0,0 +1,105 @@
+import { LogHelper } from '../log/LogHelper';
+
+/**
+ * API 基础仓库类
+ * 
+ * 封装通用仓库逻辑:
+ * - 统一错误处理
+ * - 数据转换(Data Model → Domain Model)
+ * - 缓存策略(可选)
+ * 
+ * 使用方式:
+ * ```typescript
+ * class AuthRepository extends ApiBaseRepository {
+ *   async login(mobile: string, password: string): Promise<Result<LoginResponse>> {
+ *     const request = new LoginRequest(mobile, password);
+ *     return await this.remoteDataSource.login(request);
+ *   }
+ * }
+ * ```
+ */
+export abstract class ApiBaseRepository {
+  /**
+   * 获取日志标签(子类可重写)
+   */
+  protected getTag(): string {
+    return this.constructor.name || 'ApiBaseRepository';
+  }
+  
+  /**
+   * 处理数据转换(Data Model → Domain Model)
+   * 
+   * 子类可重写此方法实现自定义转换逻辑
+   */
+  protected transform<T>(data: T): T {
+    return data;
+  }
+  
+  /**
+   * 统一错误处理
+   * 
+   * 子类可重写此方法实现自定义错误处理
+   */
+  protected handleError(error: Error): Result<never> {
+    const errorMsg = error.message || '操作失败';
+    LogHelper.e(this.getTag(), `操作失败: ${errorMsg}`, error);
+    return Result.failure(error);
+  }
+}
+
+// Result 类型定义(类似 Kotlin Result)
+export class Result<T> {
+  private readonly _value?: T;
+  private readonly _error?: Error;
+  
+  private constructor(value?: T, error?: Error) {
+    this._value = value;
+    this._error = error;
+  }
+  
+  static success<T>(value: T): Result<T> {
+    return new Result<T>(value, undefined);
+  }
+  
+  static failure<T>(error: Error): Result<T> {
+    return new Result<T>(undefined, error);
+  }
+  
+  get isSuccess(): boolean {
+    return this._error === undefined;
+  }
+  
+  get isFailure(): boolean {
+    return this._error !== undefined;
+  }
+  
+  getOrNull(): T | null {
+    return this._value ?? null;
+  }
+  
+  getOrThrow(): T {
+    if (this._error) {
+      throw this._error;
+    }
+    return this._value!;
+  }
+  
+  exceptionOrNull(): Error | null {
+    return this._error ?? null;
+  }
+  
+  onSuccess(callback: (value: T) => void): Result<T> {
+    if (this.isSuccess && this._value !== undefined) {
+      callback(this._value);
+    }
+    return this;
+  }
+  
+  onFailure(callback: (error: Error) => void): Result<T> {
+    if (this.isFailure && this._error) {
+      callback(this._error);
+    }
+    return this;
+  }
+}
+

+ 175 - 0
base-common/src/main/ets/common/network/ApiBaseService.ets

@@ -0,0 +1,175 @@
+import { NetworkManager } from '@xdz/base-core';
+import { NetworkHelper } from './NetworkHelper';
+import { ApiCommonResult, ApiResponseParser } from './ApiResponseParser';
+import { Result } from './ApiBaseRepository';
+import { LogHelper } from '../log/LogHelper';
+
+/**
+ * API 服务基类
+ * 
+ * 提供统一的 API 调用封装,减少重复代码
+ * 所有 API 服务类继承此类,自动获得统一的请求处理能力
+ * 
+ * 使用方式:
+ * ```typescript
+ * class UserApi extends ApiBaseService {
+ *   async getUserInfo(userId: string): Promise<Result<UserInfo>> {
+ *     return await this.post<UserInfo>('user/info', { userId });
+ *   }
+ * }
+ * ```
+ */
+export abstract class ApiBaseService {
+  protected networkManager: NetworkManager;
+  protected baseUrl: string;
+  
+  constructor(baseUrl?: string) {
+    this.networkManager = NetworkManager.getInstance();
+    this.baseUrl = baseUrl || NetworkHelper.getBaseUrl();
+  }
+  
+  /**
+   * 构建完整 URL
+   */
+  protected buildUrl(path: string): string {
+    // 确保 baseUrl 以 / 结尾,path 不以 / 开头
+    const base = this.baseUrl.endsWith('/') ? this.baseUrl : `${this.baseUrl}/`;
+    const p = path.startsWith('/') ? path.substring(1) : path;
+    return `${base}${p}`;
+  }
+  
+  /**
+   * GET 请求
+   * 
+   * @param path API 路径(相对路径)
+   * @param params 查询参数(可选)
+   * @param errorMessage 错误消息前缀
+   * @returns Promise<Result<T>>
+   */
+  protected async get<T>(
+    path: string,
+    params?: Record<string, string>,
+    errorMessage: string = '请求失败'
+  ): Promise<Result<T>> {
+    try {
+      let url = this.buildUrl(path);
+      if (params) {
+        const queryString = Object.keys(params)
+          .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`)
+          .join('&');
+        url = `${url}?${queryString}`;
+      }
+      
+      const headers = await NetworkHelper.getHeaders();
+      const response = await this.networkManager.get<ApiCommonResult<T>>(url, headers);
+      
+      return ApiResponseParser.handleResponse(response, errorMessage, this.constructor.name);
+    } catch (error) {
+      LogHelper.e(this.constructor.name, `${errorMessage}: ${(error as Error).message}`, error as Error);
+      return Result.failure(error as Error);
+    }
+  }
+  
+  /**
+   * POST 请求
+   * 
+   * @param path API 路径(相对路径)
+   * @param data 请求数据(可选)
+   * @param errorMessage 错误消息前缀
+   * @returns Promise<Result<T>>
+   */
+  protected async post<T>(
+    path: string,
+    data?: object,
+    errorMessage: string = '请求失败'
+  ): Promise<Result<T>> {
+    try {
+      const url = this.buildUrl(path);
+      const headers = await NetworkHelper.getHeaders();
+      const response = await this.networkManager.post<ApiCommonResult<T>>(url, data, headers);
+      
+      return ApiResponseParser.handleResponse(response, errorMessage, this.constructor.name);
+    } catch (error) {
+      LogHelper.e(this.constructor.name, `${errorMessage}: ${(error as Error).message}`, error as Error);
+      return Result.failure(error as Error);
+    }
+  }
+  
+  /**
+   * PUT 请求
+   */
+  protected async put<T>(
+    path: string,
+    data?: object,
+    errorMessage: string = '请求失败'
+  ): Promise<Result<T>> {
+    try {
+      const url = this.buildUrl(path);
+      const headers = await NetworkHelper.getHeaders();
+      const response = await this.networkManager.put<ApiCommonResult<T>>(url, data, headers);
+      
+      return ApiResponseParser.handleResponse(response, errorMessage, this.constructor.name);
+    } catch (error) {
+      LogHelper.e(this.constructor.name, `${errorMessage}: ${(error as Error).message}`, error as Error);
+      return Result.failure(error as Error);
+    }
+  }
+  
+  /**
+   * DELETE 请求
+   */
+  protected async delete<T>(
+    path: string,
+    params?: Record<string, string>,
+    errorMessage: string = '请求失败'
+  ): Promise<Result<T>> {
+    try {
+      let url = this.buildUrl(path);
+      if (params) {
+        const queryString = Object.keys(params)
+          .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`)
+          .join('&');
+        url = `${url}?${queryString}`;
+      }
+      
+      const headers = await NetworkHelper.getHeaders();
+      const response = await this.networkManager.delete<ApiCommonResult<T>>(url, headers);
+      
+      return ApiResponseParser.handleResponse(response, errorMessage, this.constructor.name);
+    } catch (error) {
+      LogHelper.e(this.constructor.name, `${errorMessage}: ${(error as Error).message}`, error as Error);
+      return Result.failure(error as Error);
+    }
+  }
+  
+  /**
+   * POST 请求(带查询参数)
+   * 
+   * 用于需要同时传递 body 和 query 参数的场景
+   */
+  protected async postWithQuery<T>(
+    path: string,
+    data?: object,
+    queryParams?: Record<string, string>,
+    errorMessage: string = '请求失败'
+  ): Promise<Result<T>> {
+    try {
+      let url = this.buildUrl(path);
+      if (queryParams) {
+        const queryString = Object.keys(queryParams)
+          .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(queryParams[key])}`)
+          .join('&');
+        url = `${url}?${queryString}`;
+      }
+      
+      const headers = await NetworkHelper.getHeaders();
+      const response = await this.networkManager.post<ApiCommonResult<T>>(url, data, headers);
+      
+      return ApiResponseParser.handleResponse(response, errorMessage, this.constructor.name);
+    } catch (error) {
+      LogHelper.e(this.constructor.name, `${errorMessage}: ${(error as Error).message}`, error as Error);
+      return Result.failure(error as Error);
+    }
+  }
+}
+

+ 104 - 0
base-common/src/main/ets/common/network/ApiResponseParser.ets

@@ -0,0 +1,104 @@
+import { LogHelper } from '../log/LogHelper';
+import { Result } from './ApiBaseRepository';
+
+/**
+ * API 通用响应结构
+ */
+export interface ApiCommonResult<T> {
+  code: number;
+  data: T;
+  msg: string;
+}
+
+/**
+ * API 响应解析器
+ * 
+ * 统一处理 API 响应格式,自动解析 code、data、msg
+ * 统一错误处理和业务错误码处理
+ * 
+ * 使用方式:
+ * ```typescript
+ * const response = await networkManager.post<ApiCommonResult<UserInfo>>(url, data);
+ * const result = ApiResponseParser.handleResponse(response, "获取用户信息失败");
+ * if (result.isSuccess) {
+ *   const userInfo = result.getOrThrow();
+ * }
+ * ```
+ */
+export class ApiResponseParser {
+  /**
+   * 成功状态码(根据实际后端定义调整)
+   */
+  private static readonly SUCCESS_CODE = 0;
+  
+  /**
+   * 处理 API 响应
+   * 
+   * @param response API 响应(ApiCommonResult 格式)
+   * @param errorMessage 错误消息前缀
+   * @param tag 日志标签
+   * @returns Result<T>
+   */
+  static handleResponse<T>(
+    response: ApiCommonResult<T>,
+    errorMessage: string = '请求失败',
+    tag: string = 'ApiResponseParser'
+  ): Result<T> {
+    if (response.code === ApiResponseParser.SUCCESS_CODE) {
+      if (response.data !== undefined && response.data !== null) {
+        LogHelper.d(tag, '请求成功');
+        return Result.success(response.data);
+      } else {
+        const error = new Error('响应数据为空');
+        LogHelper.e(tag, `${errorMessage}: 响应数据为空`);
+        return Result.failure(error);
+      }
+    } else {
+      const errorMsg = response.msg || errorMessage;
+      const error = new Error(errorMsg);
+      LogHelper.e(tag, `${errorMessage}: ${errorMsg} (code: ${response.code})`);
+      return Result.failure(error);
+    }
+  }
+  
+  /**
+   * 处理可空数据的 API 响应
+   * 
+   * 用于处理服务器可能返回 null 的情况
+   * 
+   * @param response API 响应
+   * @param errorMessage 错误消息前缀
+   * @param tag 日志标签
+   * @returns Result<T | null>
+   */
+  static handleNullableResponse<T>(
+    response: ApiCommonResult<T>,
+    errorMessage: string = '请求失败',
+    tag: string = 'ApiResponseParser'
+  ): Result<T | null> {
+    if (response.code === ApiResponseParser.SUCCESS_CODE) {
+      LogHelper.d(tag, '请求成功(可空数据)');
+      return Result.success(response.data ?? null);
+    } else {
+      const errorMsg = response.msg || errorMessage;
+      const error = new Error(errorMsg);
+      LogHelper.e(tag, `${errorMessage}: ${errorMsg} (code: ${response.code})`);
+      return Result.failure(error);
+    }
+  }
+  
+  /**
+   * 检查响应是否成功
+   */
+  static isSuccess<T>(response: ApiCommonResult<T>): boolean {
+    return response.code === ApiResponseParser.SUCCESS_CODE;
+  }
+  
+  /**
+   * 获取错误消息
+   */
+  static getErrorMessage<T>(response: ApiCommonResult<T>, defaultMessage: string = '请求失败'): string {
+    return response.msg || defaultMessage;
+  }
+}
+

+ 80 - 0
base-common/src/main/ets/common/network/ApiServiceFactory.ets

@@ -0,0 +1,80 @@
+import { NetworkManager } from '@xdz/base-core';
+import { NetworkHelper } from './NetworkHelper';
+import { LogHelper } from '../log/LogHelper';
+
+/**
+ * API 服务工厂(工厂模式)
+ * 
+ * 统一创建 API 服务实例,避免重复代码
+ * 
+ * 使用方式:
+ * ```typescript
+ * // 方式1:使用默认 baseUrl(需要在 Application 中设置 baseUrlProvider)
+ * ApiServiceFactory.baseUrlProvider = async () => {
+ *   return await ServerConfigManager.getHttpServerUrl();
+ * };
+ * const authApi = ApiServiceFactory.create<AuthApi>();
+ * 
+ * // 方式2:使用自定义 baseUrl
+ * const authApi = ApiServiceFactory.create<AuthApi>("https://api.example.com");
+ * ```
+ */
+export class ApiServiceFactory {
+  /**
+   * baseUrl 提供器(默认配置)
+   * 
+   * 在 Application 中设置一次即可,后续调用 create() 时如果不传 baseUrl,
+   * 将使用此提供器返回的 baseUrl
+   * 
+   * 示例:
+   * ```typescript
+   * ApiServiceFactory.baseUrlProvider = async () => {
+   *   return await ServerConfigManager.getHttpServerUrl();
+   * };
+   * ```
+   */
+  static baseUrlProvider: (() => Promise<string>) | null = null;
+  
+  /**
+   * 创建 API 服务实例(工厂方法)
+   * 
+   * 注意:HarmonyOS 中需要手动创建 API 服务类,不能像 Retrofit 那样自动生成
+   * 这里提供一个统一的创建方式,实际实现需要手动编写
+   * 
+   * @param baseUrl 基础URL,如果为 null 则使用 baseUrlProvider
+   * @returns API 服务实例
+   */
+  static async create<T>(baseUrl?: string): Promise<T> {
+    // 优先级:传入的 baseUrl > baseUrlProvider > NetworkHelper.getBaseUrl()
+    let url = baseUrl;
+    if (!url) {
+      if (ApiServiceFactory.baseUrlProvider) {
+        url = await ApiServiceFactory.baseUrlProvider();
+      } else {
+        url = NetworkHelper.getBaseUrl();
+      }
+    }
+    
+    if (!url) {
+      throw new Error(
+        'baseUrl 未设置。请先调用 ApiServiceFactory.baseUrlProvider = async () => { ... } ' +
+        '或在 create() 中传入 baseUrl 参数'
+      );
+    }
+    
+    LogHelper.d('ApiServiceFactory', `创建 API 服务实例,baseUrl: ${url}`);
+    
+    // 注意:HarmonyOS 中需要手动实现 API 服务类
+    // 这里返回一个代理对象,实际请求通过 NetworkManager 发送
+    interface ApiServiceProxy {
+      baseUrl: string;
+      networkManager: NetworkManager;
+    }
+    const proxy: ApiServiceProxy = {
+      baseUrl: url,
+      networkManager: NetworkManager.getInstance()
+    };
+    return proxy as T;
+  }
+}
+

+ 90 - 0
base-common/src/main/ets/common/network/NetworkHelper.ets

@@ -0,0 +1,90 @@
+import { NetworkManager } from '@xdz/base-core';
+import { TokenStore } from '../auth/storage/TokenStore';
+import { LogHelper } from '../log/LogHelper';
+
+/**
+ * 网络管理器封装
+ * 
+ * 业务层统一使用此类进行网络初始化,不直接使用 base-core 的 NetworkManager
+ * 
+ * 使用方式:
+ * ```typescript
+ * // 在 Application 中初始化网络管理器
+ * NetworkHelper.init(
+ *     baseUrl = "https://api.example.com",
+ *     isDebug = true,
+ *     enableLogging = true
+ * );
+ * 
+ * // 设置 Token 提供器
+ * NetworkHelper.setTokenProvider(async () => {
+ *     return await TokenStore.getAccessToken();
+ * });
+ * ```
+ */
+export class NetworkHelper {
+  private static tokenProvider: (() => Promise<string | null>) | null = null;
+  private static baseUrl: string = '';
+  private static isDebug: boolean = false;
+  
+  /**
+   * 初始化网络管理器
+   * 
+   * @param baseUrl 基础URL
+   * @param isDebug 是否为调试模式
+   * @param enableLogging 是否启用日志
+   */
+  static init(
+    baseUrl: string,
+    isDebug: boolean = false,
+    enableLogging: boolean = isDebug
+  ): void {
+    NetworkHelper.baseUrl = baseUrl;
+    NetworkHelper.isDebug = isDebug;
+    LogHelper.d('NetworkHelper', `网络管理器初始化完成,baseUrl: ${baseUrl}`);
+  }
+  
+  /**
+   * 设置 Token 提供器
+   * 
+   * 用于自动在请求头中添加 Authorization Token
+   * 
+   * @param tokenProvider Token 提供器,返回当前的 accessToken
+   */
+  static setTokenProvider(tokenProvider: () => Promise<string | null>): void {
+    NetworkHelper.tokenProvider = tokenProvider;
+  }
+  
+  /**
+   * 获取 Token 提供器
+   */
+  static getTokenProvider(): (() => Promise<string | null>) | null {
+    return NetworkHelper.tokenProvider;
+  }
+  
+  /**
+   * 获取基础 URL
+   */
+  static getBaseUrl(): string {
+    return NetworkHelper.baseUrl;
+  }
+  
+  /**
+   * 获取请求头(包含 Token)
+   */
+  static async getHeaders(): Promise<Record<string, string>> {
+    const headers: Record<string, string> = {
+      'Content-Type': 'application/json'
+    };
+    
+    if (NetworkHelper.tokenProvider) {
+      const token = await NetworkHelper.tokenProvider();
+      if (token) {
+        headers['Authorization'] = `Bearer ${token}`;
+      }
+    }
+    
+    return headers;
+  }
+}
+

+ 317 - 0
base-common/src/main/ets/common/network/统一解决方案说明.md

@@ -0,0 +1,317 @@
+# HarmonyOS 网络和 UI 统一解决方案
+
+## 📋 问题说明
+
+### 1. API 服务需要手动实现
+
+**问题:** HarmonyOS 没有像 Retrofit 那样的注解处理器,无法自动生成 API 接口实现。
+
+**解决方案:** 创建 `ApiBaseService` 基类,统一封装所有 API 请求逻辑。
+
+### 2. 网络请求错误处理
+
+**问题:** 不同 API 的响应格式可能不同,错误处理逻辑重复。
+
+**解决方案:** 创建 `ApiResponseParser` 统一响应解析器,自动处理 `ApiCommonResult<T>` 格式。
+
+### 3. BasePage 继承问题
+
+**问题:** HarmonyOS 的 `@Component` 装饰器不支持类继承。
+
+**解决方案:** 使用 `PageHelper` 工具类,通过组合方式提供页面功能。
+
+---
+
+## 🔧 统一解决方案
+
+### 1. API 服务统一实现方案
+
+#### 方案:ApiBaseService 基类
+
+**优点:**
+- ✅ 统一处理 URL 构建、请求头、错误处理
+- ✅ 所有 API 服务继承此类,代码简洁
+- ✅ 自动处理 Token、错误码、日志
+
+**使用方式:**
+
+```typescript
+// 1. 定义 API 服务类,继承 ApiBaseService
+export class AuthApi extends ApiBaseService {
+  // 2. 实现 API 方法,直接调用父类的 get/post/put/delete
+  async login(request: LoginRequest): Promise<Result<LoginResponse>> {
+    return await this.post<LoginResponse>('member/auth/login', request, '登录失败');
+  }
+  
+  async getUserInfo(userId: string): Promise<Result<UserInfo>> {
+    return await this.get<UserInfo>('user/info', { userId }, '获取用户信息失败');
+  }
+}
+
+// 3. 使用 API 服务
+const authApi = new AuthApi();
+const result = await authApi.login(new LoginRequest('13800138000', 'password'));
+if (result.isSuccess) {
+  const response = result.getOrThrow();
+}
+```
+
+**核心特性:**
+- ✅ 自动构建完整 URL(baseUrl + path)
+- ✅ 自动添加请求头(Content-Type、Authorization Token)
+- ✅ 自动解析响应(ApiCommonResult<T> → Result<T>)
+- ✅ 统一错误处理(业务错误码、网络异常)
+- ✅ 自动日志记录
+
+---
+
+### 2. 网络请求错误处理统一方案
+
+#### 方案:ApiResponseParser 统一解析器
+
+**优点:**
+- ✅ 统一处理 `ApiCommonResult<T>` 格式
+- ✅ 自动检查业务状态码(code === 0)
+- ✅ 统一错误消息处理
+- ✅ 支持可空数据
+
+**响应格式:**
+
+```typescript
+interface ApiCommonResult<T> {
+  code: number;    // 业务状态码,0 表示成功
+  data: T;         // 业务数据
+  msg: string;     // 错误消息(失败时)
+}
+```
+
+**使用方式:**
+
+```typescript
+// ApiBaseService 内部自动使用 ApiResponseParser
+// 开发者无需手动调用
+
+// 如果需要手动解析(不推荐):
+const response = await networkManager.post<ApiCommonResult<UserInfo>>(url, data);
+const result = ApiResponseParser.handleResponse(response, "获取用户信息失败");
+```
+
+**核心特性:**
+- ✅ 自动检查 `code === 0`(成功状态码可配置)
+- ✅ 自动提取 `data` 字段
+- ✅ 统一错误消息格式(`msg` 或自定义消息)
+- ✅ 支持可空数据(`handleNullableResponse`)
+
+---
+
+### 3. BasePage 统一解决方案
+
+#### 方案:PageHelper 工具类(组合模式)
+
+**优点:**
+- ✅ 兼容 HarmonyOS `@Component` 装饰器
+- ✅ 不依赖继承,使用组合方式
+- ✅ 提供统一的页面状态管理
+- ✅ 提供统一的通用方法
+
+**使用方式:**
+
+```typescript
+import { PageHelper } from '@xdz/base-common';
+
+@Component
+export struct MyPage {
+  // 1. 定义页面状态(必须实现 PageHelper.PageState 接口)
+  @State loading: boolean = false;
+  @State error: string | null = null;
+  
+  build() {
+    Column() {
+      if (this.loading) {
+        LoadingProgress()
+      } else if (this.error) {
+        Text(this.error)
+      } else {
+        // 页面内容
+        Text('Hello World')
+      }
+    }
+    .onPageShow(() => {
+      PageHelper.onPageShow(this);
+    })
+    .onPageHide(() => {
+      PageHelper.onPageHide(this);
+    })
+  }
+  
+  // 2. 使用 PageHelper 的方法
+  async loadData() {
+    PageHelper.showLoading(this);
+    try {
+      // 加载数据
+      const result = await api.getData();
+      if (result.isSuccess) {
+        // 处理成功
+        PageHelper.hideLoading(this);
+      } else {
+        PageHelper.showError(this, result.exceptionOrNull()?.message || '加载失败');
+      }
+    } catch (error) {
+      PageHelper.showError(this, (error as Error).message);
+    }
+  }
+}
+```
+
+**核心特性:**
+- ✅ `showLoading()` - 显示加载状态
+- ✅ `hideLoading()` - 隐藏加载状态
+- ✅ `showError()` - 显示错误信息(自动显示 Toast)
+- ✅ `clearError()` - 清除错误信息
+- ✅ `showSuccess()` - 显示成功消息
+- ✅ `showToast()` - 显示提示消息
+- ✅ `onPageShow()` - 页面显示生命周期
+- ✅ `onPageHide()` - 页面隐藏生命周期
+- ✅ `onBackPress()` - 页面返回拦截
+
+---
+
+## 📝 完整示例
+
+### API 服务示例
+
+```typescript
+// UserApi.ets
+import { ApiBaseService } from '@xdz/base-common';
+import { Result } from '@xdz/base-common';
+
+export class UserInfo {
+  id: string;
+  name: string;
+  avatar?: string;
+}
+
+export class UserApi extends ApiBaseService {
+  // GET 请求示例
+  async getUserInfo(userId: string): Promise<Result<UserInfo>> {
+    return await this.get<UserInfo>(
+      'user/info',
+      { userId },
+      '获取用户信息失败'
+    );
+  }
+  
+  // POST 请求示例
+  async updateUserInfo(userInfo: UserInfo): Promise<Result<void>> {
+    return await this.post<void>(
+      'user/update',
+      userInfo,
+      '更新用户信息失败'
+    );
+  }
+  
+  // PUT 请求示例
+  async updateAvatar(avatar: string): Promise<Result<string>> {
+    return await this.put<string>(
+      'user/avatar',
+      { avatar },
+      '更新头像失败'
+    );
+  }
+  
+  // DELETE 请求示例
+  async deleteUser(userId: string): Promise<Result<void>> {
+    return await this.delete<void>(
+      'user/delete',
+      { userId },
+      '删除用户失败'
+    );
+  }
+}
+```
+
+### 页面使用示例
+
+```typescript
+// UserProfilePage.ets
+import { PageHelper } from '@xdz/base-common';
+import { UserApi, UserInfo } from '../api/UserApi';
+
+@Component
+export struct UserProfilePage {
+  @State loading: boolean = false;
+  @State error: string | null = null;
+  @State userInfo: UserInfo | null = null;
+  
+  private userApi: UserApi = new UserApi();
+  
+  build() {
+    Column() {
+      if (this.loading) {
+        LoadingProgress()
+          .width('100%')
+          .height('100%')
+      } else if (this.error) {
+        Text(this.error)
+          .fontSize(16)
+          .fontColor(Color.Red)
+      } else if (this.userInfo) {
+        Text(this.userInfo.name)
+          .fontSize(20)
+      }
+    }
+    .width('100%')
+    .height('100%')
+    .onPageShow(() => {
+      this.loadUserInfo();
+    })
+  }
+  
+  async loadUserInfo() {
+    PageHelper.showLoading(this);
+    
+    const result = await this.userApi.getUserInfo('123');
+    
+    if (result.isSuccess) {
+      this.userInfo = result.getOrThrow();
+      PageHelper.hideLoading(this);
+    } else {
+      const error = result.exceptionOrNull();
+      PageHelper.showError(this, error?.message || '加载失败');
+    }
+  }
+}
+```
+
+---
+
+## ✅ 总结
+
+### 统一解决方案的优势
+
+1. **API 服务:**
+   - ✅ 所有 API 服务继承 `ApiBaseService`
+   - ✅ 自动处理 URL、请求头、错误处理
+   - ✅ 代码简洁,无需重复逻辑
+
+2. **错误处理:**
+   - ✅ `ApiResponseParser` 统一解析响应
+   - ✅ 自动处理业务错误码
+   - ✅ 统一错误消息格式
+
+3. **页面基类:**
+   - ✅ `PageHelper` 工具类,兼容 HarmonyOS
+   - ✅ 组合模式,不依赖继承
+   - ✅ 统一的页面状态管理
+
+### 使用建议
+
+1. **所有 API 服务** 继承 `ApiBaseService`
+2. **所有页面** 使用 `PageHelper` 管理状态
+3. **响应解析** 由 `ApiBaseService` 自动处理,无需手动调用 `ApiResponseParser`
+
+---
+
+**文档版本:** v1.0  
+**创建时间:** 2024-12
+

+ 293 - 0
base-common/src/main/ets/common/permission/PermissionHelper.ets

@@ -0,0 +1,293 @@
+import { abilityAccessCtrl, common, Context } from '@kit.AbilityKit';
+import { LogHelper } from '../log/LogHelper';
+import { DialogHelper } from '../dialog/DialogHelper';
+
+const TAG = "PermissionHelper";
+
+// HarmonyOS API 类型定义辅助
+// requestPermissionsFromUser 返回的数据结构
+interface PermissionRequestData {
+  authResults: Array<number>; // GrantStatus 数组
+}
+
+/**
+ * 权限管理封装
+ * 
+ * 统一封装 HarmonyOS 权限请求功能,提供便捷的权限管理方式
+ * 
+ * 使用方式:
+ * ```typescript
+ * // 检查权限(异步方法)
+ * const hasPermission = await PermissionHelper.checkPermission(context, 'ohos.permission.CAMERA');
+ * 
+ * // 请求单个权限
+ * PermissionHelper.requestPermission(context, 'ohos.permission.CAMERA', (granted) => {
+ *   if (granted) {
+ *     // 权限已授予
+ *   }
+ * })
+ * 
+ * // 请求多个权限
+ * PermissionHelper.requestPermissions(context, [
+ *   'ohos.permission.CAMERA',
+ *   'ohos.permission.READ_MEDIA'
+ * ], (permissions) => {
+ *   // 处理权限结果
+ * })
+ * ```
+ */
+export class PermissionHelper {
+  /**
+   * 检查权限是否已授予(异步方法)
+   * 
+   * HarmonyOS 权限检查是异步的,必须使用此方法
+   * 
+   * @param context Context 实例
+   * @param permission 权限名称(如 'ohos.permission.CAMERA')
+   * @return Promise<boolean> true 表示已授予,false 表示未授予
+   */
+  static async checkPermission(context: Context, permission: string): Promise<boolean> {
+    try {
+      const atManager = abilityAccessCtrl.createAtManager();
+      // HarmonyOS 权限检查:使用 checkAccessToken,需要 tokenId 和 permission
+      // tokenId 通过 context 获取,permission 需要转换为正确的类型
+      const tokenId = context.applicationInfo?.accessTokenId ?? 0;
+      if (tokenId === 0) {
+        LogHelper.w(TAG, "无法获取 tokenId,权限检查失败");
+        return false;
+      }
+      // checkAccessToken 接受 permission 参数,需要类型转换
+      // Permissions 类型未导出,使用类型断言处理
+      // 使用函数类型断言绕过类型检查
+      const checkAccessTokenFunc = atManager.checkAccessToken as (
+        tokenId: number,
+        permission: string
+      ) => Promise<abilityAccessCtrl.GrantStatus>;
+      const grantStatus = await checkAccessTokenFunc(tokenId, permission);
+      return grantStatus === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED;
+    } catch (e) {
+      LogHelper.e(TAG, `检查权限失败: ${permission}`, e as Error);
+      return false;
+    }
+  }
+
+  /**
+   * 检查多个权限是否已授予(异步方法)
+   * 
+   * @param context Context 实例
+   * @param permissions 权限名称数组
+   * @return Promise<Map<权限名, 是否授予>>
+   */
+  static async checkPermissions(context: Context, permissions: string[]): Promise<Record<string, boolean>> {
+    const result: Record<string, boolean> = {};
+    for (let i = 0; i < permissions.length; i++) {
+      const permission = permissions[i];
+      result[permission] = await PermissionHelper.checkPermission(context, permission);
+    }
+    return result;
+  }
+  
+  /**
+   * 检查所有权限是否都已授予(异步方法)
+   * 
+   * @param context Context 实例
+   * @param permissions 权限名称数组
+   * @return Promise<boolean> true 表示所有权限都已授予
+   */
+  static async checkAllPermissionsGranted(context: Context, permissions: string[]): Promise<boolean> {
+    const results = await PermissionHelper.checkPermissions(context, permissions);
+    return Object.values(results).every(granted => granted);
+  }
+  
+  /**
+   * 请求单个权限
+   * 
+   * 外部接口与 Android 保持一致,内部使用 HarmonyOS 推荐方式
+   * 
+   * @param context Context 实例(必须是 UIAbilityContext)
+   * @param permission 权限名称
+   * @param onResult 权限请求结果回调(是否授予)
+   */
+  static async requestPermission(
+    context: Context,
+    permission: string,
+    onResult: (granted: boolean) => void
+  ): Promise<void> {
+    try {
+      // 先异步检查权限是否已授予
+      const hasPermission = await PermissionHelper.checkPermission(context, permission);
+      if (hasPermission) {
+        onResult(true);
+        return;
+      }
+      
+      // 请求权限(HarmonyOS 推荐方式)
+      const atManager = abilityAccessCtrl.createAtManager();
+      const permissionsArray: Array<string> = [permission];
+      
+      // HarmonyOS API 类型定义问题:requestPermissionsFromUser 要求 Permissions[] 类型
+      // 但 Permissions 类型未导出,实际运行时接受 string[]
+      // 使用类型断言处理:将 string[] 断言为方法期望的类型
+      // 注意:这是 HarmonyOS API 类型定义的问题,运行时不会有问题
+      // 使用双重类型断言绕过类型检查
+      const requestResult = await (atManager.requestPermissionsFromUser as (
+        context: Context,
+        permissions: Array<string>
+      ) => Promise<PermissionRequestData>)(context, permissionsArray);
+      
+      const grantResults = requestResult.authResults;
+      const grantStatus = grantResults[0];
+      const granted = grantStatus === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED;
+      onResult(granted);
+    } catch (e) {
+      LogHelper.e(TAG, `请求权限异常: ${permission}`, e as Error);
+      onResult(false);
+    }
+  }
+  
+  /**
+   * 请求多个权限
+   * 
+   * 外部接口与 Android 保持一致,内部使用 HarmonyOS 推荐方式
+   * 
+   * @param context Context 实例(必须是 UIAbilityContext)
+   * @param permissions 权限名称数组
+   * @param onResult 权限请求结果回调(Map<权限名, 是否授予>)
+   */
+  static async requestPermissions(
+    context: Context,
+    permissions: string[],
+    onResult: (permissions: Record<string, boolean>) => void
+  ): Promise<void> {
+    try {
+      // 先异步检查已授予的权限
+      const checkedPermissions: Record<string, boolean> = {};
+      const ungrantedPermissions: string[] = [];
+      
+      for (let i = 0; i < permissions.length; i++) {
+        const permission = permissions[i];
+        const hasPermission = await PermissionHelper.checkPermission(context, permission);
+        checkedPermissions[permission] = hasPermission;
+        if (!hasPermission) {
+          ungrantedPermissions.push(permission);
+        }
+      }
+      
+      if (ungrantedPermissions.length === 0) {
+        // 所有权限都已授予
+        onResult(checkedPermissions);
+        return;
+      }
+      
+      // 请求未授予的权限(HarmonyOS 推荐方式)
+      const atManager = abilityAccessCtrl.createAtManager();
+      const permissionsArray: Array<string> = [];
+      for (let i = 0; i < ungrantedPermissions.length; i++) {
+        permissionsArray.push(ungrantedPermissions[i]);
+      }
+      
+      // HarmonyOS API 类型定义问题:requestPermissionsFromUser 要求 Permissions[] 类型
+      // 但 Permissions 类型未导出,实际运行时接受 string[]
+      // 使用函数类型断言绕过类型检查
+      const requestPermissionsFunc = atManager.requestPermissionsFromUser as (
+        context: Context,
+        permissions: Array<string>
+      ) => Promise<PermissionRequestData>;
+      const requestResult = await requestPermissionsFunc(context, permissionsArray);
+      
+      const grantResults = requestResult.authResults;
+      const result: Record<string, boolean> = {};
+      // 复制已检查的权限结果
+      const checkedKeys = Object.keys(checkedPermissions);
+      for (let i = 0; i < checkedKeys.length; i++) {
+        const key = checkedKeys[i];
+        result[key] = checkedPermissions[key];
+      }
+      
+      // 更新请求的权限结果
+      for (let i = 0; i < ungrantedPermissions.length; i++) {
+        const permission = ungrantedPermissions[i];
+        const grantStatus = grantResults[i];
+        result[permission] = grantStatus === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED;
+      }
+      
+      onResult(result);
+    } catch (e) {
+      LogHelper.e(TAG, `请求多个权限异常`, e as Error);
+      // 返回已检查的结果(即使有异常也返回部分结果)
+      const checkedPermissions: Record<string, boolean> = {};
+      for (let i = 0; i < permissions.length; i++) {
+        const permission = permissions[i];
+        try {
+          checkedPermissions[permission] = await PermissionHelper.checkPermission(context, permission);
+        } catch (checkError) {
+          checkedPermissions[permission] = false;
+        }
+      }
+      onResult(checkedPermissions);
+    }
+  }
+  
+  /**
+   * 请求权限(带说明对话框)
+   * 
+   * 外部接口与 Android 保持一致,内部使用 HarmonyOS 推荐方式
+   * 
+   * @param context Context 实例
+   * @param permission 权限名称
+   * @param rationale 权限说明文本
+   * @param onResult 权限请求结果回调
+   */
+  static async requestPermissionWithRationale(
+    context: Context,
+    permission: string,
+    rationale: string,
+    onResult: (granted: boolean) => void
+  ): Promise<void> {
+    // 先异步检查权限是否已授予
+    const hasPermission = await PermissionHelper.checkPermission(context, permission);
+    if (hasPermission) {
+      onResult(true);
+      return;
+    }
+    
+    // HarmonyOS 权限系统与 Android 不同,这里简化处理
+    // 直接显示说明对话框,然后请求权限
+    DialogHelper.showConfirm(
+      context,
+      "权限说明",
+      rationale,
+      "确定",
+      "取消",
+      () => {
+        // 用户确认后请求权限
+        PermissionHelper.requestPermission(context, permission, onResult);
+      },
+      () => {
+        // 用户取消
+        onResult(false);
+      }
+    );
+  }
+  
+  /**
+   * 获取权限说明文本(根据权限类型)
+   * 
+   * @param permission 权限名称
+   * @return 权限说明文本
+   */
+  static getPermissionRationale(permission: string): string {
+    const rationaleMap: Record<string, string> = {
+      'ohos.permission.CAMERA': '需要访问相机以拍摄照片',
+      'ohos.permission.READ_MEDIA': '需要访问媒体文件以选择图片',
+      'ohos.permission.WRITE_MEDIA': '需要保存文件到设备',
+      'ohos.permission.READ_CONTACTS': '需要访问通讯录',
+      'ohos.permission.WRITE_CONTACTS': '需要修改通讯录',
+      'ohos.permission.LOCATION': '需要访问位置信息',
+      'ohos.permission.MICROPHONE': '需要访问麦克风以录制音频',
+    };
+    
+    return rationaleMap[permission] || `需要${permission}权限以完成操作`;
+  }
+}
+

+ 145 - 0
base-common/src/main/ets/common/router/NavigationHelper.ets

@@ -0,0 +1,145 @@
+import { router } from '@kit.ArkUI';
+
+/**
+ * ⚠️ 警告:此文件使用了已弃用的API
+ * 
+ * 已弃用的API:
+ * - router.pushUrl (已弃用,建议使用新API)
+ * - router.back (已弃用,建议使用新API)
+ * - router.replaceUrl (已弃用,建议使用新API)
+ * - router.clear (已弃用,建议使用新API)
+ * 
+ * TODO: 需要迁移到HarmonyOS新版本的Router API
+ * 建议参考HarmonyOS官方文档了解新API的替代方案
+ * 
+ * 风险:
+ * - 这些API可能在未来的HarmonyOS版本中被移除
+ * - 建议尽快迁移到新API以确保兼容性
+ */
+
+/**
+ * 路由导航管理器
+ * 
+ * 统一封装路由跳转,提供便捷的路由调用方式
+ * 
+ * ⚠️ 注意:此工具类使用了已弃用的API,建议迁移到新API
+ * 
+ * 使用方式:
+ * ```typescript
+ * // 基础跳转
+ * NavigationHelper.navigate("pages/UserProfile");
+ * 
+ * // 带参数跳转
+ * NavigationHelper.navigate("pages/UserProfile", {
+ *   userId: "123",
+ *   userName: "张三"
+ * });
+ * 
+ * // 带结果回调跳转
+ * const result = await NavigationHelper.navigateForResult("pages/UserSelect", {
+ *   type: "user"
+ * });
+ * ```
+ */
+export class NavigationHelper {
+  /**
+   * 基础跳转
+   * 
+   * ⚠️ 注意:使用了已弃用的 router.pushUrl API
+   * TODO: 需要迁移到HarmonyOS新版本的Router API
+   * 
+   * @param path 路由路径
+   * @param params 参数(可选)
+   */
+  static navigate(path: string, params?: Record<string, Object>): void {
+    const routerOptions: router.RouterOptions = {
+      url: path,
+      params: params
+    };
+    router.pushUrl(routerOptions).catch((error: Error) => {
+      console.error('NavigationHelper', `跳转失败: ${path}`, error);
+    });
+  }
+  
+  /**
+   * 带结果回调跳转
+   * 
+   * @param path 路由路径
+   * @param params 参数(可选)
+   * @returns Promise<Object> 返回结果
+   */
+  static async navigateForResult(
+    path: string,
+    params?: Record<string, Object>
+  ): Promise<Object> {
+    return new Promise((resolve, reject) => {
+      const routerOptions: router.RouterOptions = {
+        url: path,
+        params: params
+      };
+      // 使用已弃用的API,待迁移
+      router.pushUrl(routerOptions).then(() => {
+        // HarmonyOS 路由暂不支持结果回调,返回空对象
+        interface EmptyResult {
+        }
+        const emptyResult: EmptyResult = {};
+        resolve(emptyResult as Object);
+      }).catch((error: Error) => {
+        console.error('NavigationHelper', `跳转失败: ${path}`, error);
+        reject(error);
+      });
+    });
+  }
+  
+  /**
+   * 返回上一页
+   * 
+   * ⚠️ 注意:使用了已弃用的 router.back API
+   * TODO: 需要迁移到HarmonyOS新版本的Router API
+   * 
+   * @param result 返回结果(可选,HarmonyOS 暂不支持)
+   */
+  static back(result?: Object): void {
+    router.back();
+  }
+  
+  /**
+   * 替换当前页面
+   * 
+   * ⚠️ 注意:使用了已弃用的 router.replaceUrl API
+   * TODO: 需要迁移到HarmonyOS新版本的Router API
+   * 
+   * @param path 路由路径
+   * @param params 参数(可选)
+   */
+  static replace(path: string, params?: Record<string, Object>): void {
+    const routerOptions: router.RouterOptions = {
+      url: path,
+      params: params
+    };
+    router.replaceUrl(routerOptions).catch((error: Error) => {
+      console.error('NavigationHelper', `替换页面失败: ${path}`, error);
+    });
+  }
+  
+  /**
+   * 清空路由栈并跳转
+   * 
+   * ⚠️ 注意:使用了已弃用的 router.clear 和 router.pushUrl API
+   * TODO: 需要迁移到HarmonyOS新版本的Router API
+   * 
+   * @param path 路由路径
+   * @param params 参数(可选)
+   */
+  static clearStack(path: string, params?: Record<string, Object>): void {
+    router.clear();
+    const routerOptions: router.RouterOptions = {
+      url: path,
+      params: params
+    };
+    router.pushUrl(routerOptions).catch((error: Error) => {
+      console.error('NavigationHelper', `清空栈并跳转失败: ${path}`, error);
+    });
+  }
+}
+

+ 173 - 0
base-common/src/main/ets/common/socketio/SocketIOManager.ets

@@ -0,0 +1,173 @@
+import { Context, UIAbility } from '@kit.AbilityKit';
+import { ILog, StorageImpl } from '@xdz/base-core';
+import { SocketIORepositoryFactory } from '@xdz/capability-socketio';
+import { AuthManager } from '../auth/AuthManager';
+
+const TAG = "SocketIOManager";
+
+/**
+ * SocketIO 连接管理器(业务封装层)
+ * 
+ * 与 AuthManager、VersionUpdateManager 类似,提供统一的 Socket.IO 封装
+ * 自动处理连接、重连、Token 刷新等,外部只需要初始化即可
+ * 
+ * 负责自动管理 SocketIO 连接的生命周期:
+ * - App 进入前台时自动重连
+ * - Token 过期时自动刷新并重连
+ * - 监听应用生命周期
+ * 
+ * 使用方式:
+ * ```typescript
+ * // 在 EntryAbility.onCreate() 中初始化
+ * SocketIOManager.init(context, ability)
+ * 
+ * // 在 EntryAbility.onForeground() 中调用
+ * await SocketIOManager.onForeground()
+ * 
+ * // 在 EntryAbility.onBackground() 中调用
+ * SocketIOManager.onBackground()
+ * ```
+ */
+export class SocketIOManager {
+  private static instance: SocketIOManager | null = null;
+  private context: Context | null = null;
+  private initialized: boolean = false;
+  private ability: UIAbility | null = null;
+  
+  private constructor() {
+    // 私有构造函数,单例模式
+  }
+  
+  /**
+   * 获取单例实例
+   */
+  static getInstance(): SocketIOManager {
+    if (!SocketIOManager.instance) {
+      SocketIOManager.instance = new SocketIOManager();
+    }
+    return SocketIOManager.instance;
+  }
+  
+  /**
+   * 初始化 SocketIO 管理器
+   * 
+   * 需要在 EntryAbility.onCreate() 中调用
+   * 会自动注册生命周期监听
+   * 
+   * @param context Application Context 实例
+   * @param ability UIAbility 实例(用于监听生命周期)
+   */
+  static init(context: Context, ability?: UIAbility): void {
+    const instance = SocketIOManager.getInstance();
+    
+    if (instance.initialized) {
+      ILog.w(TAG, "SocketIOManager 已初始化,跳过重复初始化");
+      return;
+    }
+    
+    instance.context = context;
+    instance.ability = ability || null;
+    instance.initialized = true;
+    
+    // 如果提供了 ability,注册生命周期监听
+    if (ability) {
+      // HarmonyOS 的生命周期监听通过重写 ability 的方法实现
+      // 这里我们使用一个包装器来监听生命周期
+      instance.setupLifecycleListener(ability);
+    }
+    
+    ILog.d(TAG, "SocketIOManager 初始化完成(生命周期监听已注册)");
+  }
+  
+  /**
+   * 设置生命周期监听器
+   * 
+   * 注意:HarmonyOS 的生命周期管理需要通过 Ability 的 onForeground/onBackground 方法
+   * 这里提供一个辅助方法,需要在 EntryAbility 中手动调用
+   */
+  private setupLifecycleListener(ability: UIAbility): void {
+    // HarmonyOS 的生命周期监听需要在 EntryAbility 中手动调用
+    // 这里只是保存引用,实际的生命周期回调在 EntryAbility 中调用
+    this.ability = ability;
+  }
+  
+  /**
+   * App 进入前台时调用(需要在 EntryAbility.onForeground() 中手动调用)
+   * 
+   * 检查 SocketIO 连接状态,如果断开则自动重连
+   * 如果连接失败(可能是 Token 过期),会自动刷新 Token 后重连
+   */
+  static async onForeground(): Promise<void> {
+    ILog.d(TAG, "App 进入前台,检查 SocketIO 连接状态");
+    
+    // 检查是否已登录
+    if (!await AuthManager.isLoggedIn()) {
+      ILog.d(TAG, "用户未登录,跳过 SocketIO 重连");
+      return;
+    }
+    
+    // 在后台执行重连逻辑(使用 Promise,不依赖 ExecutorManager)
+    Promise.resolve().then(async () => {
+      try {
+        // 直接获取 SocketIORepository(不使用反射)
+        const socketIORepository = SocketIORepositoryFactory.getInstance();
+        
+        // 检查是否已连接
+        if (socketIORepository.isConnected()) {
+          ILog.d(TAG, "SocketIO 已连接,无需重连");
+          return;
+        }
+        
+        // 检查 token 是否存在
+        const token = await StorageImpl.getInstance().getString("access_token");
+        if (!token || token === '') {
+          ILog.w(TAG, "Token 为空,无法重连 SocketIO");
+          return;
+        }
+        
+        // 先尝试连接(不传参数,让它从存储中获取)
+        ILog.d(TAG, "SocketIO 未连接,开始重连...");
+        const reconnected = await socketIORepository.checkAndReconnect(null, null);
+        
+        if (!reconnected) {
+          // 等待 2 秒,检查连接是否成功
+          await new Promise<void>((resolve) => {
+            setTimeout(() => {
+              resolve();
+            }, 2000);
+          });
+          
+          // 如果连接仍然失败,可能是 Token 过期,尝试刷新 Token 后重连
+          if (!socketIORepository.isConnected()) {
+            ILog.d(TAG, "连接失败,可能是 Token 过期,尝试刷新 Token 后重连");
+            const refreshedToken = await AuthManager.refreshTokenIfNeeded();
+            if (refreshedToken && refreshedToken !== token) {
+              ILog.d(TAG, "Token 已刷新,使用新 Token 重连");
+              await socketIORepository.checkAndReconnect(null, null);
+            } else {
+              ILog.w(TAG, "Token 刷新失败或未刷新,无法重连");
+            }
+          } else {
+            ILog.d(TAG, "SocketIO 重连成功");
+          }
+        }
+      } catch (e) {
+        ILog.e(TAG, "SocketIO 重连失败", e as Error);
+      }
+    });
+  }
+  
+  /**
+   * App 进入后台时调用(需要在 EntryAbility.onBackground() 中手动调用)
+   * 
+   * 注意:通常不断开 SocketIO 连接,因为:
+   * 1. SocketIO 连接是轻量级的
+   * 2. 用户可能需要在后台接收消息
+   * 3. 系统会在内存不足时自动清理
+   */
+  static onBackground(): void {
+    ILog.d(TAG, "App 进入后台");
+    // 不断开连接,保持连接以便接收消息
+  }
+}
+

+ 85 - 0
base-common/src/main/ets/common/storage/StorageManager.ets

@@ -0,0 +1,85 @@
+import { StorageImpl } from '@xdz/base-core';
+
+/**
+ * 存储管理器封装
+ * 
+ * 业务层封装,提供便捷的存储操作
+ * 底层使用 StorageImpl 统一存储
+ */
+export class StorageManager {
+  private static readonly TAG = 'StorageManager';
+  
+  /**
+   * 字符串存储
+   */
+  static async putString(key: string, value: string): Promise<void> {
+    await StorageImpl.getInstance().putString(key, value);
+  }
+  
+  static async getString(key: string, defaultValue: string = ''): Promise<string> {
+    return await StorageImpl.getInstance().getString(key, defaultValue);
+  }
+  
+  /**
+   * 整数存储
+   */
+  static async putInt(key: string, value: number): Promise<void> {
+    await StorageImpl.getInstance().putInt(key, value);
+  }
+  
+  static async getInt(key: string, defaultValue: number = 0): Promise<number> {
+    return await StorageImpl.getInstance().getInt(key, defaultValue);
+  }
+  
+  /**
+   * 长整数存储
+   */
+  static async putLong(key: string, value: number): Promise<void> {
+    await StorageImpl.getInstance().putLong(key, value);
+  }
+  
+  static async getLong(key: string, defaultValue: number = 0): Promise<number> {
+    return await StorageImpl.getInstance().getLong(key, defaultValue);
+  }
+  
+  /**
+   * 布尔值存储
+   */
+  static async putBoolean(key: string, value: boolean): Promise<void> {
+    await StorageImpl.getInstance().putBoolean(key, value);
+  }
+  
+  static async getBoolean(key: string, defaultValue: boolean = false): Promise<boolean> {
+    return await StorageImpl.getInstance().getBoolean(key, defaultValue);
+  }
+  
+  /**
+   * 删除键值
+   */
+  static async remove(key: string): Promise<void> {
+    await StorageImpl.getInstance().remove(key);
+  }
+  
+  /**
+   * 清除所有存储
+   */
+  static async clear(): Promise<void> {
+    await StorageImpl.getInstance().clear();
+  }
+  
+  /**
+   * 文件存储
+   */
+  static async saveFile(path: string, data: Uint8Array): Promise<boolean> {
+    return await StorageImpl.getInstance().saveFile(path, data);
+  }
+  
+  static async readFile(path: string): Promise<Uint8Array | null> {
+    return await StorageImpl.getInstance().readFile(path);
+  }
+  
+  static async deleteFile(path: string): Promise<boolean> {
+    return await StorageImpl.getInstance().deleteFile(path);
+  }
+}
+

+ 40 - 0
base-common/src/main/ets/common/ui/BasePage.ets

@@ -0,0 +1,40 @@
+import { PageHelper, PageState } from './PageHelper';
+
+/**
+ * 页面基类(已废弃,推荐使用 PageHelper)
+ * 
+ * 由于 HarmonyOS 的 @Component 装饰器不支持类继承,
+ * 请使用 PageHelper 工具类代替
+ * 
+ * @deprecated 使用 PageHelper 代替
+ */
+export class BasePage implements PageState {
+  // 保留用于向后兼容,但推荐使用 PageHelper
+  loading: boolean = false;
+  error: string | null = null;
+  
+  showLoading(): void {
+    PageHelper.showLoading(this);
+  }
+  
+  hideLoading(): void {
+    PageHelper.hideLoading(this);
+  }
+  
+  showError(message: string): void {
+    PageHelper.showError(this, message);
+  }
+  
+  clearError(): void {
+    PageHelper.clearError(this);
+  }
+  
+  showSuccess(message: string): void {
+    PageHelper.showSuccess(message);
+  }
+  
+  showToast(message: string): void {
+    PageHelper.showToast(message);
+  }
+}
+

+ 125 - 0
base-common/src/main/ets/common/ui/BaseViewModel.ets

@@ -0,0 +1,125 @@
+import { LogHelper } from '../log/LogHelper';
+
+/**
+ * ViewModel 基类
+ * 
+ * 提供统一的 ViewModel 功能,与 Android 版本保持一致
+ * 注意:MVVM 支持放在 UI 层,与 Android 的 BaseFragment/BaseActivity 位置一致
+ */
+
+/**
+ * UI 状态基类
+ * 
+ * 定义通用的 UI 状态,所有 ViewModel 的状态类应继承此类
+ */
+export class UiState {
+  loading: boolean = false;
+  error: string | null = null;
+  
+  constructor(loading: boolean = false, error: string | null = null) {
+    this.loading = loading;
+    this.error = error;
+  }
+  
+  /**
+   * 创建加载状态
+   */
+  static loading(): UiState {
+    return new UiState(true, null);
+  }
+  
+  /**
+   * 创建错误状态
+   */
+  static error(message: string): UiState {
+    return new UiState(false, message);
+  }
+  
+  /**
+   * 创建成功状态
+   */
+  static success(): UiState {
+    return new UiState(false, null);
+  }
+}
+
+/**
+ * ViewModel 基类
+ * 
+ * 提供统一的 ViewModel 功能,与 Android 版本保持一致
+ * 
+ * 使用方式:
+ * ```typescript
+ * class LoginViewModel extends BaseViewModel {
+ *   @State loginState: LoginState = LoginState.Idle;
+ *   
+ *   async login(mobile: string, password: string) {
+ *     this.loginState = LoginState.Loading;
+ *     try {
+ *       const result = await authRepository.login(mobile, password);
+ *       if (result.isSuccess) {
+ *         this.loginState = LoginState.Success(result.getOrThrow());
+ *       } else {
+ *         this.loginState = LoginState.Error(result.exceptionOrNull()?.message || '登录失败');
+ *       }
+ *     } catch (error) {
+ *       this.loginState = LoginState.Error((error as Error).message);
+ *     }
+ *   }
+ * }
+ * ```
+ */
+export abstract class BaseViewModel {
+  protected readonly tag: string;
+  
+  constructor() {
+    this.tag = this.constructor.name;
+  }
+  
+  /**
+   * ViewModel 初始化(可选)
+   * 
+   * 在页面创建时调用
+   */
+  onInit(): void {
+    // 子类可重写
+  }
+  
+  /**
+   * ViewModel 销毁(可选)
+   * 
+   * 在页面销毁时调用,用于清理资源
+   */
+  onDestroy(): void {
+    // 子类可重写
+  }
+  
+  /**
+   * 显示加载状态
+   */
+  protected setLoading(state: UiState, loading: boolean): void {
+    if (state) {
+      state.loading = loading;
+    }
+  }
+  
+  /**
+   * 显示错误状态
+   */
+  protected setError(state: UiState, error: string): void {
+    if (state) {
+      state.error = error;
+      state.loading = false;
+    }
+  }
+  
+  /**
+   * 清除错误状态
+   */
+  protected clearError(state: UiState): void {
+    if (state) {
+      state.error = null;
+    }
+  }
+}
+

+ 134 - 0
base-common/src/main/ets/common/ui/MessageHelper.ets

@@ -0,0 +1,134 @@
+import { promptAction } from '@kit.ArkUI';
+
+/**
+ * ⚠️ 警告:此文件使用了已弃用的API
+ * 
+ * 已弃用的API:
+ * - promptAction.showToast (已弃用,建议使用新API)
+ * - promptAction.showDialog (已弃用,建议使用新API)
+ * 
+ * TODO: 需要迁移到HarmonyOS新版本的API
+ * 建议参考HarmonyOS官方文档了解新API的替代方案
+ * 
+ * 风险:
+ * - 这些API可能在未来的HarmonyOS版本中被移除
+ * - 建议尽快迁移到新API以确保兼容性
+ */
+
+/**
+ * 对话框按钮接口
+ */
+export interface DialogButton {
+  text: string;
+  color?: string;
+  action?: () => void;
+}
+
+/**
+ * 对话框选项接口
+ */
+export interface DialogOptions {
+  title?: string;
+  message: string;
+  buttons?: Array<DialogButton>;
+}
+
+/**
+ * 消息提示管理器
+ * 
+ * 统一封装消息提示,提供便捷的消息提示方式
+ * 
+ * ⚠️ 注意:此工具类使用了已弃用的API,建议迁移到新API
+ * 
+ * 使用方式:
+ * ```typescript
+ * // Toast 提示
+ * MessageHelper.showToast("操作成功");
+ * MessageHelper.showSuccess("保存成功");
+ * MessageHelper.showError("操作失败");
+ * ```
+ */
+export class MessageHelper {
+  /**
+   * Toast 显示时长(毫秒)
+   */
+  static toastDuration: number = 2000;
+  
+  /**
+   * 显示 Toast 消息
+   * 
+   * ⚠️ 注意:使用了已弃用的 promptAction.showToast API
+   * TODO: 需要迁移到HarmonyOS新版本的Toast API
+   * 
+   * @param message 消息内容
+   */
+  static showToast(message: string): void {
+    // 使用已弃用的API,待迁移
+    promptAction.showToast({
+      message: message,
+      duration: MessageHelper.toastDuration
+    });
+  }
+  
+  /**
+   * 显示成功消息
+   * 
+   * @param message 消息内容
+   */
+  static showSuccess(message: string): void {
+    MessageHelper.showToast(message);
+  }
+  
+  /**
+   * 显示错误消息
+   * 
+   * @param message 消息内容
+   */
+  static showError(message: string): void {
+    MessageHelper.showToast(message);
+  }
+
+  /**
+   * 显示对话框
+   * 
+   * @param options 对话框选项
+   */
+  static async showDialog(options: DialogOptions): Promise<void> {
+    return new Promise((resolve) => {
+      interface PromptButton {
+        text: string;
+        color: string;
+        action: () => void;
+      }
+      
+      const buttons: PromptButton[] = options.buttons?.map(btn => {
+        const promptBtn: PromptButton = {
+          text: btn.text,
+          color: btn.color || '#007DFF',
+          action: () => {
+            if (btn.action) {
+              btn.action();
+            }
+            resolve();
+          }
+        };
+        return promptBtn;
+      }) || [
+        {
+          text: '确定',
+          color: '#007DFF',
+          action: () => resolve()
+        }
+      ];
+      
+      const dialogOptions: promptAction.ShowDialogOptions = {
+        title: options.title,
+        message: options.message,
+        buttons: buttons
+      };
+      
+      promptAction.showDialog(dialogOptions);
+    });
+  }
+}
+

+ 115 - 0
base-common/src/main/ets/common/ui/PageHelper.ets

@@ -0,0 +1,115 @@
+import { MessageHelper } from './MessageHelper';
+
+/**
+ * 页面状态接口
+ */
+export interface PageState {
+  loading: boolean;
+  error: string | null;
+}
+
+/**
+ * 页面辅助工具类
+ * 
+ * HarmonyOS 的 @Component 装饰器不支持类继承,因此使用工具类方式
+ * 提供统一的页面状态管理和通用方法
+ * 
+ * 使用方式:
+ * ```typescript
+ * @Component
+ * export struct MyPage {
+ *   @State loading: boolean = false;
+ *   @State error: string | null = null;
+ *   
+ *   build() {
+ *     Column() {
+ *       if (this.loading) {
+ *         LoadingProgress()
+ *       } else if (this.error) {
+ *         Text(this.error)
+ *       } else {
+ *         // 页面内容
+ *       }
+ *     }
+ *     .onPageShow(() => {
+ *       PageHelper.onPageShow(this);
+ *     })
+ *   }
+ *   
+ *   // 使用 PageHelper 的方法
+ *   showLoading() {
+ *     PageHelper.showLoading(this);
+ *   }
+ * }
+ * ```
+ */
+export class PageHelper {
+  /**
+   * 显示加载状态
+   */
+  static showLoading(page: PageState): void {
+    page.loading = true;
+    page.error = null;
+  }
+  
+  /**
+   * 隐藏加载状态
+   */
+  static hideLoading(page: PageState): void {
+    page.loading = false;
+  }
+  
+  /**
+   * 显示错误信息
+   */
+  static showError(page: PageState, message: string): void {
+    page.error = message;
+    page.loading = false;
+    MessageHelper.showError(message);
+  }
+  
+  /**
+   * 清除错误信息
+   */
+  static clearError(page: PageState): void {
+    page.error = null;
+  }
+  
+  /**
+   * 显示成功消息
+   */
+  static showSuccess(message: string): void {
+    MessageHelper.showSuccess(message);
+  }
+  
+  /**
+   * 显示提示消息
+   */
+  static showToast(message: string): void {
+    MessageHelper.showToast(message);
+  }
+  
+  /**
+   * 页面显示时调用(可选)
+   */
+  static onPageShow(page?: PageState): void {
+    // 子类可重写或扩展
+  }
+  
+  /**
+   * 页面隐藏时调用(可选)
+   */
+  static onPageHide(page?: PageState): void {
+    // 子类可重写或扩展
+  }
+  
+  /**
+   * 页面返回时调用(可选)
+   * 
+   * @returns true 表示拦截返回事件,false 表示允许返回
+   */
+  static onBackPress(): boolean {
+    return false;
+  }
+}
+

+ 104 - 0
base-common/src/main/ets/common/ui/StateFlow.ets

@@ -0,0 +1,104 @@
+/**
+ * StateFlow 的 HarmonyOS 实现
+ * 
+ * 提供类似 Android StateFlow 的功能,用于响应式状态管理
+ * 
+ * 注意:HarmonyOS 的 @State 装饰器已经提供了响应式能力,
+ * 这个类主要用于保持与 Android 版本的 API 一致性
+ * 
+ * 使用方式:
+ * ```typescript
+ * class LoginViewModel extends BaseViewModel {
+ *   private _loginState = new StateFlow<LoginState>(LoginState.Idle);
+ *   loginState: StateFlow<LoginState> = this._loginState;
+ *   
+ *   async login(mobile: string, password: string) {
+ *     this._loginState.value = LoginState.Loading;
+ *     // ... 登录逻辑
+ *     this._loginState.value = LoginState.Success(response);
+ *   }
+ * }
+ * 
+ * // 在页面中使用
+ * @Component
+ * export struct LoginPage {
+ *   @State viewModel: LoginViewModel = new LoginViewModel();
+ *   
+ *   build() {
+ *     Column() {
+ *       // @State 会自动响应 viewModel.loginState.value 的变化
+ *       if (this.viewModel.loginState.value === LoginState.Loading) {
+ *         LoadingProgress()
+ *       }
+ *     }
+ *   }
+ * }
+ * ```
+ */
+export class StateFlow<T> {
+  private _value: T;
+  private listeners: Set<(value: T) => void> = new Set();
+  
+  constructor(initialValue: T) {
+    this._value = initialValue;
+  }
+  
+  /**
+   * 获取当前值
+   */
+  get value(): T {
+    return this._value;
+  }
+  
+  /**
+   * 设置新值(并通知所有监听者)
+   */
+  set value(newValue: T) {
+    if (this._value !== newValue) {
+      this._value = newValue;
+      this.notifyListeners();
+    }
+  }
+  
+  /**
+   * 添加监听者
+   */
+  observe(listener: (value: T) => void): () => void {
+    this.listeners.add(listener);
+    // 立即通知当前值
+    listener(this._value);
+    
+    // 返回取消监听的函数
+    return () => {
+      this.listeners.delete(listener);
+    };
+  }
+  
+  /**
+   * 移除监听者
+   */
+  removeObserver(listener: (value: T) => void): void {
+    this.listeners.delete(listener);
+  }
+  
+  /**
+   * 通知所有监听者
+   */
+  private notifyListeners(): void {
+    this.listeners.forEach(listener => {
+      try {
+        listener(this._value);
+      } catch (error) {
+        console.error('StateFlow listener error:', error);
+      }
+    });
+  }
+  
+  /**
+   * 获取监听者数量(用于调试)
+   */
+  get observerCount(): number {
+    return this.listeners.size;
+  }
+}
+

+ 60 - 0
base-common/src/main/ets/common/ui/ViewModelHelper.ets

@@ -0,0 +1,60 @@
+import { BaseViewModel } from './BaseViewModel';
+
+/**
+ * ViewModel 辅助工具类
+ * 
+ * 帮助页面管理 ViewModel 生命周期
+ * 与 Android 版本的 ViewModelProvider 功能类似
+ * 
+ * 使用方式:
+ * ```typescript
+ * @Component
+ * export struct LoginPage {
+ *   @State viewModel: LoginViewModel = new LoginViewModel();
+ *   
+ *   aboutToAppear() {
+ *     ViewModelHelper.onInit(this.viewModel);
+ *   }
+ *   
+ *   aboutToDisappear() {
+ *     ViewModelHelper.onDestroy(this.viewModel);
+ *   }
+ * }
+ * ```
+ */
+export class ViewModelHelper {
+  /**
+   * ViewModel 初始化
+   * 
+   * 在页面创建时调用(aboutToAppear)
+   */
+  static onInit(viewModel: BaseViewModel): void {
+    viewModel.onInit();
+  }
+  
+  /**
+   * ViewModel 销毁
+   * 
+   * 在页面销毁时调用(aboutToDisappear)
+   */
+  static onDestroy(viewModel: BaseViewModel): void {
+    viewModel.onDestroy();
+  }
+  
+  /**
+   * 观察状态变化(简化版)
+   * 
+   * 由于 HarmonyOS 使用 @State 装饰器自动响应变化,
+   * 不需要像 Android 那样手动观察 StateFlow
+   * 
+   * 如果需要额外的副作用处理,可以使用此方法
+   */
+  static observeState<T>(
+    state: T,
+    callback: (state: T) => void
+  ): void {
+    // HarmonyOS 的 @State 会自动响应变化,这里主要用于兼容性
+    callback(state);
+  }
+}
+

+ 279 - 0
base-common/src/main/ets/common/util/UtilManager.ets

@@ -0,0 +1,279 @@
+import { LogHelper } from '../log/LogHelper';
+
+const TAG = "UtilManager";
+
+/**
+ * 工具管理器
+ * 
+ * 业务层封装,提供便捷的工具方法调用方式
+ * 
+ * 使用方式:
+ * ```typescript
+ * // 时间处理
+ * const timeStr = UtilManager.formatTime(Date.now(), "yyyy-MM-dd HH:mm:ss");
+ * const timestamp = UtilManager.parseTime("2024-01-01 12:00:00", "yyyy-MM-dd HH:mm:ss");
+ * 
+ * // 字符串处理
+ * const md5Hash = UtilManager.md5("原始数据");
+ * 
+ * // 数据转换
+ * const json = UtilManager.toJson(user);
+ * const user = UtilManager.fromJson<User>(json);
+ * ```
+ */
+export class UtilManager {
+  /**
+   * 格式化时间
+   * 
+   * @param timestamp 时间戳(毫秒)
+   * @param pattern 格式模式(如 "yyyy-MM-dd HH:mm:ss")
+   * @return 格式化后的时间字符串
+   */
+  static formatTime(timestamp: number, pattern: string): string {
+    try {
+      const date = new Date(timestamp);
+      const year = date.getFullYear();
+      const month = String(date.getMonth() + 1).padStart(2, '0');
+      const day = String(date.getDate()).padStart(2, '0');
+      const hours = String(date.getHours()).padStart(2, '0');
+      const minutes = String(date.getMinutes()).padStart(2, '0');
+      const seconds = String(date.getSeconds()).padStart(2, '0');
+      
+      return pattern
+        .replace('yyyy', String(year))
+        .replace('MM', month)
+        .replace('dd', day)
+        .replace('HH', hours)
+        .replace('mm', minutes)
+        .replace('ss', seconds);
+    } catch (e) {
+      LogHelper.e(TAG, `格式化时间失败: ${timestamp}, ${pattern}`, e as Error);
+      return "";
+    }
+  }
+  
+  /**
+   * 解析时间字符串
+   * 
+   * @param timeString 时间字符串
+   * @param pattern 格式模式(如 "yyyy-MM-dd HH:mm:ss")
+   * @return 时间戳(毫秒),如果解析失败返回 null
+   */
+  static parseTime(timeString: string, pattern: string): number | null {
+    try {
+      // 简化实现:使用正则表达式解析
+      const yearMatch = timeString.match(/(\d{4})/);
+      const monthMatch = timeString.match(/-(\d{2})-/);
+      const dayMatch = timeString.match(/-(\d{2})\s/);
+      const hourMatch = timeString.match(/\s(\d{2}):/);
+      const minuteMatch = timeString.match(/:(\d{2}):/);
+      const secondMatch = timeString.match(/:(\d{2})$/);
+      
+      if (!yearMatch) {
+        return null;
+      }
+      
+      const year = parseInt(yearMatch[1]);
+      const month = monthMatch ? parseInt(monthMatch[1]) - 1 : 0;
+      const day = dayMatch ? parseInt(dayMatch[1]) : 1;
+      const hours = hourMatch ? parseInt(hourMatch[1]) : 0;
+      const minutes = minuteMatch ? parseInt(minuteMatch[1]) : 0;
+      const seconds = secondMatch ? parseInt(secondMatch[1]) : 0;
+      
+      const date = new Date(year, month, day, hours, minutes, seconds);
+      return date.getTime();
+    } catch (e) {
+      LogHelper.e(TAG, `解析时间失败: ${timeString}, ${pattern}`, e as Error);
+      return null;
+    }
+  }
+  
+  /**
+   * MD5 哈希
+   * 
+   * 注意:HarmonyOS 需要使用 crypto 模块实现
+   * 这里提供基础实现,实际使用时需要引入 crypto 模块
+   * 
+   * @param data 原始数据
+   * @return MD5 哈希值
+   */
+  static md5(data: string): string {
+    // HarmonyOS 需要使用 @kit.CryptoFramework 实现
+    // 这里先返回空字符串,提示需要实现
+    LogHelper.w(TAG, "MD5 功能需要使用 @kit.CryptoFramework 实现");
+    return "";
+  }
+  
+  /**
+   * 对象转 JSON
+   * 
+   * @param obj 对象
+   * @return JSON 字符串
+   */
+  static toJson<T>(obj: T): string {
+    try {
+      return JSON.stringify(obj);
+    } catch (e) {
+      LogHelper.e(TAG, `对象转 JSON 失败`, e as Error);
+      return "";
+    }
+  }
+  
+  /**
+   * JSON 转对象
+   * 
+   * @param json JSON 字符串
+   * @return 对象,如果解析失败返回 null
+   */
+  static fromJson<T>(json: string): T | null {
+    try {
+      return JSON.parse(json) as T;
+    } catch (e) {
+      LogHelper.e(TAG, `JSON 转对象失败: ${json}`, e as Error);
+      return null;
+    }
+  }
+  
+  /**
+   * 字符串加密(简化实现)
+   * 
+   * 注意:实际使用时需要使用加密库
+   * 
+   * @param data 原始数据
+   * @return 加密后的字符串
+   */
+  static encryptString(data: string): string {
+    // HarmonyOS 需要使用 @kit.CryptoFramework 实现 Base64 编码
+    // 这里暂时返回原数据,提示需要实现
+    try {
+      LogHelper.w(TAG, "字符串加密功能需要使用 @kit.CryptoFramework 实现");
+      // TODO: 使用 @kit.CryptoFramework 实现 Base64 编码
+      return data; // 临时返回原数据
+    } catch (e) {
+      LogHelper.e(TAG, `字符串加密失败`, e as Error);
+      return data;
+    }
+  }
+  
+  /**
+   * 字符串解密(简化实现)
+   * 
+   * @param data 加密后的数据
+   * @return 解密后的字符串
+   */
+  static decryptString(data: string): string {
+    // HarmonyOS 需要使用 @kit.CryptoFramework 实现 Base64 解码
+    // 这里暂时返回原数据,提示需要实现
+    try {
+      LogHelper.w(TAG, "字符串解密功能需要使用 @kit.CryptoFramework 实现");
+      // TODO: 使用 @kit.CryptoFramework 实现 Base64 解码
+      return data; // 临时返回原数据
+    } catch (e) {
+      LogHelper.e(TAG, `字符串解密失败`, e as Error);
+      return data;
+    }
+  }
+  
+  /**
+   * 生成 UUID
+   * 
+   * @return UUID 字符串
+   */
+  static generateUUID(): string {
+    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
+      const r = Math.random() * 16 | 0;
+      const v = c === 'x' ? r : (r & 0x3 | 0x8);
+      return v.toString(16);
+    });
+  }
+  
+  /**
+   * 格式化文件大小
+   * 
+   * @param bytes 字节数
+   * @return 格式化后的文件大小字符串(如 "1.5 MB")
+   */
+  static formatFileSize(bytes: number): string {
+    if (bytes === 0) return '0 B';
+    
+    const k = 1024;
+    const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
+    const i = Math.floor(Math.log(bytes) / Math.log(k));
+    
+    return `${(bytes / Math.pow(k, i)).toFixed(2)} ${sizes[i]}`;
+  }
+  
+  /**
+   * 防抖函数
+   * 
+   * 注意:ArkTS 不支持泛型函数参数类型推断,这里使用简化版本
+   * 
+   * @param func 要防抖的函数
+   * @param delay 延迟时间(毫秒)
+   * @return 防抖后的函数
+   */
+  static debounce(
+    func: (...args: Array<object>) => void,
+    delay: number
+  ): (...args: Array<object>) => void {
+    let timeoutId: number | null = null;
+    
+    return (...args: Array<object>) => {
+      if (timeoutId !== null) {
+        clearTimeout(timeoutId);
+      }
+      timeoutId = setTimeout(() => {
+        // 手动调用函数,不使用扩展运算符
+        if (args.length === 0) {
+          func();
+        } else if (args.length === 1) {
+          func(args[0]);
+        } else if (args.length === 2) {
+          func(args[0], args[1]);
+        } else if (args.length === 3) {
+          func(args[0], args[1], args[2]);
+        } else {
+          // 参数过多的情况,只传递前3个
+          func(args[0], args[1], args[2]);
+        }
+      }, delay) as number;
+    };
+  }
+  
+  /**
+   * 节流函数
+   * 
+   * 注意:ArkTS 不支持泛型函数参数类型推断,这里使用简化版本
+   * 
+   * @param func 要节流的函数
+   * @param delay 延迟时间(毫秒)
+   * @return 节流后的函数
+   */
+  static throttle(
+    func: (...args: Array<object>) => void,
+    delay: number
+  ): (...args: Array<object>) => void {
+    let lastCallTime = 0;
+    
+    return (...args: Array<object>) => {
+      const now = Date.now();
+      if (now - lastCallTime >= delay) {
+        lastCallTime = now;
+        // 手动调用函数,不使用扩展运算符
+        if (args.length === 0) {
+          func();
+        } else if (args.length === 1) {
+          func(args[0]);
+        } else if (args.length === 2) {
+          func(args[0], args[1]);
+        } else if (args.length === 3) {
+          func(args[0], args[1], args[2]);
+        } else {
+          // 参数过多的情况,只传递前3个
+          func(args[0], args[1], args[2]);
+        }
+      }
+    };
+  }
+}
+

+ 102 - 0
base-common/src/main/ets/common/version/VersionUpdateManager.ets

@@ -0,0 +1,102 @@
+import { Context } from '@kit.AbilityKit';
+import { bundleManager } from '@kit.AbilityKit';
+import { VersionViewModel } from './viewmodel/VersionViewModel';
+import { LogHelper } from '../log/LogHelper';
+
+/**
+ * 版本更新管理器
+ * 
+ * 封装版本检查的完整逻辑,包括:
+ * - 获取当前版本号
+ * - 检查服务器版本
+ * - 显示更新对话框
+ * - 处理强制更新
+ * 
+ * 使用方式:
+ * ```typescript
+ * // 在 Application 中初始化
+ * VersionUpdateManager.init(context)
+ * 
+ * // 在页面中检查更新(自动获取版本号)
+ * VersionUpdateManager.checkUpdate(context)
+ * 
+ * // 或者手动指定版本号
+ * VersionUpdateManager.checkUpdate(context, platform = 2, versionCode = 100)
+ * ```
+ */
+export class VersionUpdateManager {
+  private static readonly PLATFORM_HARMONYOS = 2; // 平台类型:1-安卓,2-鸿蒙,3-iOS
+  
+  /**
+   * 初始化版本更新管理器
+   * 
+   * 需要在 Application.onCreate() 中调用
+   * 
+   * @param context 上下文
+   * @param platform 平台类型(默认 2-鸿蒙)
+   */
+  static init(context: Context, platform: number = VersionUpdateManager.PLATFORM_HARMONYOS): void {
+    // 初始化逻辑(如果需要)
+    LogHelper.d('VersionUpdateManager', 'VersionUpdateManager initialized');
+  }
+  
+  /**
+   * 获取当前应用的版本号
+   * 
+   * @param context 上下文
+   * @return 版本号,如果获取失败返回 1
+   */
+  static getCurrentVersionCode(context: Context): number {
+    try {
+      // HarmonyOS 获取版本号的方式
+      const bundleInfo = bundleManager.getBundleInfoForSelfSync(0);
+      if (bundleInfo && bundleInfo.versionCode) {
+        return bundleInfo.versionCode;
+      }
+      return 1;
+    } catch (e) {
+      LogHelper.e('VersionUpdateManager', '无法获取版本号', e as Error);
+      return 1; // 默认版本号
+    }
+  }
+  
+  /**
+   * 检查版本更新(自动获取当前版本号)
+   * 
+   * @param context Context 实例(用于获取版本号)
+   * @param platform 平台类型(默认 2-鸿蒙)
+   * @return VersionViewModel 实例,用于在页面中观察状态
+   */
+  static checkUpdate(
+    context: Context,
+    platform: number = VersionUpdateManager.PLATFORM_HARMONYOS
+  ): VersionViewModel {
+    const currentVersionCode = VersionUpdateManager.getCurrentVersionCode(context);
+    return VersionUpdateManager.checkUpdateWithVersion(context, platform, currentVersionCode);
+  }
+  
+  /**
+   * 检查版本更新(手动指定版本号)
+   * 
+   * @param context Context 实例
+   * @param platform 平台类型(默认 2-鸿蒙)
+   * @param currentVersionCode 当前版本号
+   * @return VersionViewModel 实例,用于在页面中观察状态
+   */
+  static checkUpdateWithVersion(
+    context: Context,
+    platform: number,
+    currentVersionCode: number
+  ): VersionViewModel {
+    const viewModel = new VersionViewModel();
+    
+    // 异步检查版本(不阻塞主线程)
+    viewModel.checkVersion(currentVersionCode, platform).catch((error: Error) => {
+      // 版本检查失败不影响应用启动
+      LogHelper.e('VersionUpdateManager', '版本检查失败', error);
+    });
+    
+    return viewModel;
+  }
+}
+

+ 36 - 0
base-common/src/main/ets/common/version/datasource/remote/VersionApi.ets

@@ -0,0 +1,36 @@
+import { ApiBaseService } from '../../../network/ApiBaseService';
+import { Result } from '../../../network/ApiBaseRepository';
+import { VersionResponse } from '../../model/VersionResponse';
+
+/**
+ * 版本检查 API 接口
+ * 
+ * 继承 ApiBaseService,自动获得统一的请求处理能力
+ */
+export class VersionApi extends ApiBaseService {
+  /**
+   * 获取最新版本
+   * 
+   * @param platform 平台类型:1-安卓,2-鸿蒙,3-iOS
+   * @param currentVersionCode 当前版本号(可选,用于判断是否有更新)
+   * @return 版本响应数据
+   */
+  async getLatestVersion(
+    platform: number,
+    currentVersionCode?: number
+  ): Promise<Result<VersionResponse>> {
+    const params: Record<string, string> = {};
+    params.platform = platform.toString();
+    
+    if (currentVersionCode !== undefined) {
+      params.currentVersionCode = currentVersionCode.toString();
+    }
+    
+    return await this.get<VersionResponse>(
+      'version/latest',
+      params,
+      '获取最新版本失败'
+    );
+  }
+}
+

+ 42 - 0
base-common/src/main/ets/common/version/datasource/remote/VersionRemoteDataSource.ets

@@ -0,0 +1,42 @@
+import { ApiBaseRemoteDataSource, Result } from '../../../network/ApiBaseRemoteDataSource';
+import { VersionResponse } from '../../model/VersionResponse';
+import { VersionApi } from './VersionApi';
+
+/**
+ * 版本远程数据源接口
+ */
+export interface IVersionRemoteDataSource {
+  /**
+   * 获取最新版本
+   */
+  getLatestVersion(
+    platform: number,
+    currentVersionCode?: number
+  ): Promise<Result<VersionResponse>>;
+}
+
+/**
+ * 版本远程数据源实现
+ * 
+ * 继承 ApiBaseRemoteDataSource,自动获得:
+ * - 统一的错误处理
+ * - 自动日志记录
+ * - 网络异常友好提示
+ */
+export class VersionRemoteDataSource extends ApiBaseRemoteDataSource implements IVersionRemoteDataSource {
+  private versionApi: VersionApi;
+  
+  constructor() {
+    super();
+    this.versionApi = new VersionApi();
+  }
+  
+  async getLatestVersion(
+    platform: number,
+    currentVersionCode?: number
+  ): Promise<Result<VersionResponse>> {
+    // VersionApi 已经返回 Result<VersionResponse>,直接返回即可
+    return await this.versionApi.getLatestVersion(platform, currentVersionCode);
+  }
+}
+

+ 17 - 0
base-common/src/main/ets/common/version/model/VersionResponse.ets

@@ -0,0 +1,17 @@
+/**
+ * 版本检查响应数据模型
+ * 
+ * 与 Android 版本保持一致
+ */
+export interface VersionResponse {
+  hasUpdate: boolean;           // 是否有新版本
+  forceUpdate: boolean;         // 是否强制更新
+  versionName?: string;         // 版本名称(如:1.0.0)
+  versionCode?: number;         // 版本号(内部版本号)
+  versionDesc?: string;         // 版本描述
+  downloadUrl?: string;         // 下载地址
+  packageSize?: number;         // 包大小(字节)
+  updateLog?: string;           // 更新日志
+  publishTime?: string;          // 发布时间
+}
+

+ 80 - 0
base-common/src/main/ets/common/version/repository/VersionRepository.ets

@@ -0,0 +1,80 @@
+import { ApiBaseRepository, Result } from '../../network/ApiBaseRepository';
+import { VersionResponse } from '../model/VersionResponse';
+import { IVersionRemoteDataSource } from '../datasource/remote/VersionRemoteDataSource';
+import { LogHelper } from '../../log/LogHelper';
+
+/**
+ * 版本管理 Repository
+ * 
+ * 继承 ApiBaseRepository,自动获得:
+ * - 统一的错误处理
+ * - 日志记录
+ * - 数据转换扩展点
+ */
+export class VersionRepository extends ApiBaseRepository {
+  private remoteDataSource: IVersionRemoteDataSource;
+  
+  constructor(remoteDataSource: IVersionRemoteDataSource) {
+    super();
+    this.remoteDataSource = remoteDataSource;
+  }
+  
+  /**
+   * 检查版本更新
+   * 
+   * @param platform 平台类型:1-安卓,2-鸿蒙,3-iOS
+   * @param currentVersionCode 当前版本号
+   * @return 版本信息,如果没有版本或没有更新则返回 null
+   */
+  async checkVersion(
+    platform: number,
+    currentVersionCode: number
+  ): Promise<VersionResponse | null> {
+    const result = await this.remoteDataSource.getLatestVersion(platform, currentVersionCode);
+    
+    if (result.isSuccess) {
+      const versionResponse: VersionResponse = result.getOrThrow();
+      
+      // 如果没有更新,返回 null
+      if (!this.hasUpdate(versionResponse)) {
+        return null;
+      }
+      
+      return versionResponse;
+    } else {
+      // 如果请求失败,记录日志但不抛出异常
+      // 这样客户端可以正常启动,不会因为版本检查失败而阻塞
+      const error: Error | null = result.exceptionOrNull();
+      if (error) {
+        LogHelper.e('VersionRepository', '版本检查失败', error);
+        this.handleError(error);
+      } else {
+        const defaultError = new Error('版本检查失败');
+        LogHelper.e('VersionRepository', '版本检查失败', defaultError);
+        this.handleError(defaultError);
+      }
+      return null;
+    }
+  }
+  
+  /**
+   * 检查版本更新
+   * 
+   * @param versionResponse 版本响应数据
+   * @return 是否需要更新(true 表示需要更新)
+   */
+  hasUpdate(versionResponse: VersionResponse | null): boolean {
+    return versionResponse !== null && versionResponse.hasUpdate;
+  }
+  
+  /**
+   * 判断是否为强制更新
+   * 
+   * @param versionResponse 版本响应数据
+   * @return 是否为强制更新
+   */
+  isForceUpdate(versionResponse: VersionResponse | null): boolean {
+    return versionResponse?.forceUpdate === true;
+  }
+}
+

+ 72 - 0
base-common/src/main/ets/common/version/viewmodel/VersionState.ets

@@ -0,0 +1,72 @@
+import { VersionResponse } from '../model/VersionResponse';
+
+/**
+ * 版本检查状态
+ * 
+ * 与 Android 版本保持一致的状态定义
+ */
+export class VersionState {
+  static readonly Idle = new VersionState('Idle');
+  static readonly Checking = new VersionState('Checking');
+  
+  static Success(versionResponse: VersionResponse | null): VersionState {
+    return new VersionState('Success', versionResponse);
+  }
+  
+  static Error(message: string): VersionState {
+    return new VersionState('Error', undefined, message);
+  }
+  
+  readonly type: 'Idle' | 'Checking' | 'Success' | 'Error';
+  readonly versionResponse?: VersionResponse | null;
+  readonly message?: string;
+  
+  private constructor(type: 'Idle' | 'Checking' | 'Success' | 'Error', versionResponse?: VersionResponse | null, message?: string) {
+    this.type = type;
+    this.versionResponse = versionResponse;
+    this.message = message;
+  }
+  
+  /**
+   * 判断是否为检查中状态
+   */
+  get isChecking(): boolean {
+    return this.type === 'Checking';
+  }
+  
+  /**
+   * 判断是否为成功状态
+   */
+  get isSuccess(): boolean {
+    return this.type === 'Success';
+  }
+  
+  /**
+   * 判断是否为错误状态
+   */
+  get isError(): boolean {
+    return this.type === 'Error';
+  }
+  
+  /**
+   * 判断是否为空闲状态
+   */
+  get isIdle(): boolean {
+    return this.type === 'Idle';
+  }
+  
+  /**
+   * 是否有新版本
+   */
+  get hasUpdate(): boolean {
+    return this.versionResponse?.hasUpdate === true;
+  }
+  
+  /**
+   * 是否强制更新
+   */
+  get isForceUpdate(): boolean {
+    return this.versionResponse?.forceUpdate === true;
+  }
+}
+

+ 86 - 0
base-common/src/main/ets/common/version/viewmodel/VersionViewModel.ets

@@ -0,0 +1,86 @@
+import { BaseViewModel } from '../../ui/BaseViewModel';
+import { StateFlow } from '../../ui/StateFlow';
+import { VersionRepository } from '../repository/VersionRepository';
+import { VersionRemoteDataSource } from '../datasource/remote/VersionRemoteDataSource';
+import { VersionState } from './VersionState';
+import { VersionResponse } from '../model/VersionResponse';
+import { LogHelper } from '../../log/LogHelper';
+
+/**
+ * 版本检查 ViewModel
+ * 
+ * 与 Android 版本保持一致的 API 和结构
+ */
+export class VersionViewModel extends BaseViewModel {
+  private versionRepository: VersionRepository;
+  
+  // 使用 StateFlow 管理状态(与 Android 版本一致)
+  private _versionState = new StateFlow<VersionState>(VersionState.Idle);
+  versionState: StateFlow<VersionState> = this._versionState;
+  
+  private static readonly PLATFORM_HARMONYOS = 2; // 平台类型:1-安卓,2-鸿蒙,3-iOS
+  
+  constructor() {
+    super();
+    // 初始化 Repository
+    this.versionRepository = new VersionRepository(
+      new VersionRemoteDataSource()
+    );
+  }
+  
+  /**
+   * 检查版本更新
+   * 
+   * @param currentVersionCode 当前版本号
+   * @param platform 平台类型(默认 2-鸿蒙)
+   */
+  async checkVersion(
+    currentVersionCode: number,
+    platform: number = VersionViewModel.PLATFORM_HARMONYOS
+  ): Promise<void> {
+    this._versionState.value = VersionState.Checking;
+    
+    try {
+      const versionResponse = await this.versionRepository.checkVersion(
+        platform,
+        currentVersionCode
+      );
+      
+      if (versionResponse !== null) {
+        this._versionState.value = VersionState.Success(versionResponse);
+        LogHelper.d(this.tag, '发现新版本');
+      } else {
+        // 没有新版本,也返回成功状态,但 versionResponse 为 null
+        this._versionState.value = VersionState.Success(null);
+        LogHelper.d(this.tag, '当前已是最新版本');
+      }
+    } catch (error) {
+      this._versionState.value = VersionState.Error(
+        (error as Error).message || '版本检查失败'
+      );
+      LogHelper.e(this.tag, '版本检查失败', error as Error);
+    }
+  }
+  
+  /**
+   * 判断是否有更新
+   */
+  hasUpdate(): boolean {
+    return this.versionRepository.hasUpdate(this._versionState.value.versionResponse || null);
+  }
+  
+  /**
+   * 判断是否为强制更新
+   */
+  isForceUpdate(): boolean {
+    return this.versionRepository.isForceUpdate(this._versionState.value.versionResponse || null);
+  }
+  
+  /**
+   * 获取当前版本响应
+   */
+  getVersionResponse(): VersionResponse | null {
+    return this._versionState.value.versionResponse || null;
+  }
+}
+

+ 202 - 0
base-common/src/main/ets/common/缺失模块清单.md

@@ -0,0 +1,202 @@
+# base-common 模块缺失清单
+
+## 📊 模块对比
+
+### ✅ 已实现的模块
+
+| 模块 | 状态 | 说明 |
+|------|------|------|
+| **auth** | ✅ 完整 | ViewModel、Repository、DataSource、Model、State、Page |
+| **config** | ✅ 完整 | ConfigManager、ServerConfigManager |
+| **log** | ✅ 完整 | LogHelper |
+| **network** | ✅ 完整 | ApiBaseService、ApiResponseParser、NetworkHelper、ApiServiceFactory |
+| **router** | ✅ 部分 | NavigationHelper(功能可能不如 Android 的 RouterHelper 完整) |
+| **storage** | ✅ 完整 | StorageManager |
+| **ui** | ✅ 部分 | MessageHelper、PageHelper、BasePage |
+| **version** | ✅ 完整 | ViewModel、Repository、DataSource、Model、State |
+| **mvvm** | ✅ 完整 | BaseViewModel、StateFlow、ViewModelHelper(HarmonyOS 特有) |
+
+---
+
+### ❌ 缺失的模块
+
+#### 1. **dialog** - 对话框助手
+- **目录状态**: 存在但为空
+- **Android 实现**: `DialogHelper.kt`
+- **功能**: 
+  - 提示对话框
+  - 确认对话框
+  - 输入对话框
+  - 列表选择对话框
+  - 级联选择对话框
+- **优先级**: 🔴 高(UI 常用功能)
+
+#### 2. **permission** - 权限管理
+- **目录状态**: 存在但为空
+- **Android 实现**: `PermissionHelper.kt`
+- **功能**:
+  - 权限检查
+  - 权限请求
+  - 权限说明对话框
+  - 权限请求结果回调
+- **优先级**: 🔴 高(应用必需功能)
+
+#### 3. **socketio** - SocketIO 管理器
+- **目录状态**: 存在但为空
+- **Android 实现**: `SocketIOManager.kt`
+- **功能**:
+  - SocketIO 连接管理
+  - 自动重连
+  - Token 刷新后重连
+  - 生命周期管理
+- **优先级**: 🔴 高(实时通信必需)
+
+#### 4. **launch** - 应用初始化
+- **目录状态**: 存在但为空
+- **Android 实现**: `AppInitializer.kt`、`AppLaunchManager.kt`
+- **功能**:
+  - 统一初始化所有模块
+  - 初始化顺序管理
+  - 模块依赖管理
+- **优先级**: 🔴 高(应用启动必需)
+
+#### 5. **util** - 工具管理器
+- **目录状态**: 存在但为空
+- **Android 实现**: `UtilManager.kt`
+- **功能**:
+  - 时间格式化/解析
+  - 字符串加密/解密
+  - MD5 哈希
+  - JSON 转换
+- **优先级**: 🟡 中(工具方法)
+
+#### 6. **crash** - 崩溃处理
+- **目录状态**: 不存在
+- **Android 实现**: `CrashHelper.kt`
+- **功能**:
+  - 崩溃捕获
+  - 崩溃日志记录
+  - 崩溃上报
+- **优先级**: 🟡 中(调试和监控)
+
+#### 7. **file** - 文件选择器
+- **目录状态**: 不存在
+- **Android 实现**: `FilePickerHelper.kt`
+- **功能**:
+  - 文件选择
+  - 文件类型过滤
+  - 多文件选择
+- **优先级**: 🟢 低(特定功能)
+
+#### 8. **image** - 图片加载器
+- **目录状态**: 不存在
+- **Android 实现**: `ImageLoader.kt`
+- **功能**:
+  - 图片加载
+  - 图片缓存
+  - 图片压缩
+- **优先级**: 🟢 低(可使用第三方库)
+
+#### 9. **camera** - 相机助手
+- **目录状态**: 不存在
+- **Android 实现**: `CameraHelper.kt`
+- **功能**:
+  - 相机调用
+  - 图片拍摄
+  - 图片处理
+- **优先级**: 🟢 低(特定功能)
+
+#### 10. **bridge** - 桥接管理器
+- **目录状态**: 不存在
+- **Android 实现**: `BridgeManager.kt`
+- **功能**:
+  - WebView 与原生通信
+  - JS 桥接
+- **优先级**: 🟢 低(特定功能)
+
+#### 11. **executor** - 执行器管理器
+- **目录状态**: 不存在
+- **Android 实现**: `ExecutorManager.kt`
+- **功能**:
+  - 线程池管理
+  - 任务调度
+- **优先级**: 🟢 低(HarmonyOS 使用 async/await)
+
+---
+
+## 🎯 优先级建议
+
+### 高优先级(必须实现)
+
+1. **dialog** - 对话框助手
+   - 原因: UI 常用功能,几乎所有页面都需要
+   - 工作量: 中等
+
+2. **permission** - 权限管理
+   - 原因: 应用必需功能,HarmonyOS 权限系统与 Android 不同
+   - 工作量: 中等
+
+3. **socketio** - SocketIO 管理器
+   - 原因: 实时通信必需,业务核心功能
+   - 工作量: 较大(需要适配 HarmonyOS WebSocket)
+
+4. **launch** - 应用初始化
+   - 原因: 应用启动必需,统一管理模块初始化
+   - 工作量: 小
+
+### 中优先级(建议实现)
+
+5. **util** - 工具管理器
+   - 原因: 常用工具方法,提高开发效率
+   - 工作量: 小
+
+6. **crash** - 崩溃处理
+   - 原因: 调试和监控必需
+   - 工作量: 中等
+
+### 低优先级(可选实现)
+
+7. **file** - 文件选择器
+8. **image** - 图片加载器
+9. **camera** - 相机助手
+10. **bridge** - 桥接管理器
+11. **executor** - 执行器管理器
+
+---
+
+## 📝 实现建议
+
+### 1. dialog 模块
+- 使用 HarmonyOS 的 `@ohos.promptAction` 和自定义 Dialog
+- 参考 Android 版本的 API 设计,保持一致性
+
+### 2. permission 模块
+- 使用 HarmonyOS 的权限 API(`@kit.AbilityKit`)
+- 适配 HarmonyOS 的权限模型(与 Android 不同)
+
+### 3. socketio 模块
+- 使用 HarmonyOS 的 WebSocket API
+- 或者使用第三方 Socket.IO 库(如果支持 HarmonyOS)
+
+### 4. launch 模块
+- 统一管理所有模块的初始化
+- 确保初始化顺序正确
+
+### 5. util 模块
+- 使用 HarmonyOS 的 API 实现工具方法
+- 保持与 Android 版本的 API 一致性
+
+---
+
+## ✅ 总结
+
+**已实现**: 9 个模块(auth、config、log、network、router、storage、ui、version、mvvm)  
+**缺失**: 11 个模块(dialog、permission、socketio、launch、util、crash、file、image、camera、bridge、executor)
+
+**建议优先实现**: dialog、permission、socketio、launch(高优先级)
+
+---
+
+**文档版本**: v1.0  
+**创建时间**: 2024-12
+

+ 94 - 0
base-common/src/main/ets/index.ets

@@ -0,0 +1,94 @@
+/**
+ * base-common 模块导出入口
+ * 
+ * 统一导出所有业务封装
+ */
+
+// 认证模块
+export { TokenStore } from './common/auth/storage/TokenStore';
+export { AuthManager } from './common/auth/AuthManager';
+export { AuthRepository } from './common/auth/repository/AuthRepository';
+export { AuthRemoteDataSource } from './common/auth/datasource/remote/AuthRemoteDataSource';
+export { AuthLocalDataSource } from './common/auth/datasource/local/AuthLocalDataSource';
+export { AuthLocalDataSourceImpl } from './common/auth/datasource/local/AuthLocalDataSourceImpl';
+export { LoginRequest } from './common/auth/model/LoginRequest';
+export { LoginResponse } from './common/auth/model/LoginResponse';
+export { RegisterRequest } from './common/auth/model/RegisterRequest';
+export { LoginViewModel } from './common/auth/viewmodel/LoginViewModel';
+export { LoginState } from './common/auth/viewmodel/LoginState';
+export { LoginPage } from './common/auth/pages/LoginPage';
+export { RegisterPage } from './common/auth/pages/RegisterPage';
+
+// 配置模块
+export { ConfigManager } from './common/config/ConfigManager';
+export { ServerConfigManager } from './common/config/ServerConfigManager';
+
+// 版本模块
+export { VersionUpdateManager } from './common/version/VersionUpdateManager';
+export { VersionRepository } from './common/version/repository/VersionRepository';
+export { VersionRemoteDataSource } from './common/version/datasource/remote/VersionRemoteDataSource';
+export { VersionApi } from './common/version/datasource/remote/VersionApi';
+export { VersionResponse } from './common/version/model/VersionResponse';
+export { VersionViewModel } from './common/version/viewmodel/VersionViewModel';
+export { VersionState } from './common/version/viewmodel/VersionState';
+
+// 存储模块
+export { StorageManager } from './common/storage/StorageManager';
+// 导出 StorageImpl(从 base-core 重新导出,方便 entry 模块使用)
+export { StorageImpl } from '@xdz/base-core';
+
+// 日志模块
+export { LogHelper } from './common/log/LogHelper';
+
+// 网络模块
+export { NetworkHelper } from './common/network/NetworkHelper';
+export { ApiServiceFactory } from './common/network/ApiServiceFactory';
+export { ApiBaseRepository, Result } from './common/network/ApiBaseRepository';
+export { ApiBaseRemoteDataSource } from './common/network/ApiBaseRemoteDataSource';
+
+// UI 模块(包含 MVVM 支持)
+export { BasePage } from './common/ui/BasePage';
+export { PageHelper } from './common/ui/PageHelper';
+export { MessageHelper } from './common/ui/MessageHelper';
+export { NavigationHelper } from './common/router/NavigationHelper';
+export { BaseViewModel, UiState } from './common/ui/BaseViewModel';
+export { StateFlow } from './common/ui/StateFlow';
+export { ViewModelHelper } from './common/ui/ViewModelHelper';
+
+// 网络模块(统一解决方案)
+export { ApiBaseService } from './common/network/ApiBaseService';
+export { ApiResponseParser, ApiCommonResult } from './common/network/ApiResponseParser';
+
+// Dialog 模块
+export { DialogHelper } from './common/dialog/DialogHelper';
+
+// Permission 模块
+export { PermissionHelper } from './common/permission/PermissionHelper';
+
+// Launch 模块(已迁移到 entry 模块)
+// export { AppInitializer } from './common/launch/AppInitializer';
+
+// Util 模块
+export { UtilManager } from './common/util/UtilManager';
+
+// Crash 模块
+export { CrashHelper } from './common/crash/CrashHelper';
+
+// File 模块
+export { FilePickerHelper } from './common/file/FilePickerHelper';
+
+// Image 模块
+export { ImageLoader } from './common/image/ImageLoader';
+
+// Camera 模块
+export { CameraHelper } from './common/camera/CameraHelper';
+
+// Bridge 模块
+export { BridgeManager } from './common/bridge/BridgeManager';
+
+// Executor 模块
+export { ExecutorManager } from './common/executor/ExecutorManager';
+
+// SocketIO 模块
+export { SocketIOManager } from './common/socketio/SocketIOManager';
+

+ 13 - 0
base-common/src/main/module.json5

@@ -0,0 +1,13 @@
+{
+  "module": {
+    "name": "base_common",
+    "type": "har",
+    "description": "业务封装层 - 封装 base-core 的接口,提供便捷调用",
+    "mainElement": "",
+    "deviceTypes": [
+      "phone",
+      "tablet"
+    ]
+  }
+}
+

+ 30 - 0
base-core/.preview/default/intermediates/merge_profile/default/module.json

@@ -0,0 +1,30 @@
+{
+	"app": {
+		"bundleName": "com.narutohuo.xdz",
+		"debug": true,
+		"versionCode": 1000000,
+		"versionName": "1.0.0",
+		"minAPIVersion": 60001021,
+		"targetAPIVersion": 60001021,
+		"apiReleaseType": "Release",
+		"targetMinorAPIVersion": 0,
+		"targetPatchAPIVersion": 0,
+		"compileSdkVersion": "6.0.1.112",
+		"compileSdkType": "HarmonyOS",
+		"appEnvironments": [],
+		"bundleType": "app",
+		"buildMode": "debug"
+	},
+	"module": {
+		"name": "base_core",
+		"type": "har",
+		"description": "基础设施层 - 定义接口和基础实现",
+		"mainElement": "",
+		"deviceTypes": [
+			"phone",
+			"tablet"
+		],
+		"packageName": "@xdz/base-core",
+		"installationFree": false
+	}
+}

+ 17 - 0
base-core/BuildProfile.ets

@@ -0,0 +1,17 @@
+/**
+ * Use these variables when you tailor your ArkTS code. They must be of the const type.
+ */
+export const HAR_VERSION = '1.0.0';
+export const BUILD_MODE_NAME = 'debug';
+export const DEBUG = true;
+export const TARGET_NAME = 'default';
+
+/**
+ * BuildProfile Class is used only for compatibility purposes.
+ */
+export default class BuildProfile { 
+	static readonly HAR_VERSION = HAR_VERSION;
+	static readonly BUILD_MODE_NAME = BUILD_MODE_NAME;
+	static readonly DEBUG = DEBUG;
+	static readonly TARGET_NAME = TARGET_NAME;
+}

+ 28 - 0
base-core/build-profile.json5

@@ -0,0 +1,28 @@
+{
+  "apiType": "stageMode",
+  "buildOption": {
+    "resOptions": {
+      "copyCodeResource": {
+        "enable": false
+      }
+    }
+  },
+  "buildOptionSet": [
+    {
+      "name": "release",
+      "arkOptions": {
+        "obfuscation": {
+          "ruleOptions": {
+            "enable": false
+          }
+        }
+      }
+    }
+  ],
+  "targets": [
+    {
+      "name": "default"
+    }
+  ]
+}
+

+ 7 - 0
base-core/hvigorfile.ts

@@ -0,0 +1,7 @@
+import { harTasks } from '@ohos/hvigor-ohos-plugin';
+
+export default {
+  system: harTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
+  plugins: []       /* Custom plugin to extend the functionality of Hvigor. */
+}
+

+ 11 - 0
base-core/oh-package.json5

@@ -0,0 +1,11 @@
+{
+  "name": "@xdz/base-core",
+  "version": "1.0.0",
+  "description": "基础设施层 - 定义接口和基础实现",
+  "main": "src/main/ets/index.ets",
+  "dependencies": {
+  },
+  "license": "MIT",
+  "keywords": ["base", "core", "infrastructure"]
+}
+

+ 175 - 0
base-core/src/main/ets/core/log/ILog.ets

@@ -0,0 +1,175 @@
+import { HilogLogger } from './impl/HilogLogger';
+import { NoOpLogger } from './impl/NoOpLogger';
+
+/**
+ * 日志级别枚举
+ */
+export enum LogLevel {
+  DEBUG,    // 调试信息
+  INFO,     // 一般信息
+  WARN,     // 警告信息
+  ERROR     // 错误信息
+}
+
+/**
+ * 日志服务接口
+ * 统一封装日志记录、日志文件管理、日志上传、崩溃收集
+ * 
+ * 实现类:HilogLogger(开发环境)、NoOpLogger(生产环境)
+ */
+export interface ILogger {
+  /**
+   * 调试日志
+   */
+  d(tag: string, message: string): void;
+  
+  /**
+   * 信息日志
+   */
+  i(tag: string, message: string): void;
+  
+  /**
+   * 警告日志
+   */
+  w(tag: string, message: string): void;
+  
+  /**
+   * 错误日志
+   */
+  e(tag: string, message: string, throwable?: Error): void;
+  
+  /**
+   * 按级别记录日志
+   * 
+   * @param level 日志级别
+   * @param tag 标签
+   * @param message 消息
+   * @param throwable 异常(可选)
+   */
+  log(level: LogLevel, tag: string, message: string, throwable?: Error): void;
+  
+  /**
+   * 上传日志文件
+   */
+  uploadLogs(): void;
+  
+  /**
+   * 收集崩溃信息
+   */
+  collectCrash(throwable: Error): void;
+}
+
+/**
+ * 日志工具类(类似 Android Log 类)
+ * 
+ * 所有模块通过静态方法进行日志记录
+ * 
+ * **实现选择**:
+ * - **开发环境**(Debug):使用 HilogLogger(输出详细日志)
+ * - **生产环境**(Release):使用 NoOpLogger(不输出日志,提升性能)
+ * 
+ * **使用示例**:
+ * ```typescript
+ * // 1. 在 Application 中初始化(推荐)
+ * // Debug 版本自动启用日志,Release 版本自动禁用
+ * ILog.init(true);
+ * 
+ * // 2. 静态方法调用(推荐,类似 Android Log.d())
+ * ILog.d("Tag", "调试信息");
+ * ILog.e("Tag", "错误信息", exception);
+ * 
+ * // 3. 手动控制(可选)
+ * ILog.init(false); // 生产环境禁用日志
+ * ILog.init(true);  // 开发环境启用日志
+ * ```
+ */
+export class ILog {
+  private static instance: ILogger | null = null;
+  
+  /**
+   * 初始化日志实现(在 Application 中调用,可选)
+   * 
+   * **自动选择实现**:
+   * - 如果 `enableLogging = true`(默认):使用 HilogLogger(开发环境)
+   * - 如果 `enableLogging = false`:使用 NoOpLogger(生产环境,不输出日志)
+   * 
+   * @param enableLogging 是否启用日志(默认 true)
+   * @param logImpl 自定义日志实现(可选,如果指定则忽略 enableLogging 参数)
+   */
+  static init(enableLogging: boolean = true, logImpl?: ILogger): void {
+    if (logImpl) {
+      ILog.instance = logImpl; // 如果指定了自定义实现,优先使用
+    } else if (enableLogging) {
+      // 启用日志(开发环境)
+      ILog.instance = HilogLogger.getInstance();
+    } else {
+      // 禁用日志(生产环境)
+      ILog.instance = NoOpLogger.getInstance();
+    }
+  }
+  
+  /**
+   * 获取日志实现实例(单例)
+   * 
+   * 如果未初始化,默认使用 HilogLogger(开发环境)
+   * 生产环境建议在 Application 中调用 init() 进行初始化
+   */
+  private static getInstance(): ILogger {
+    if (!ILog.instance) {
+      // 默认使用 HilogLogger(开发环境)
+      // 生产环境建议在 Application 中调用 init(false)
+      ILog.instance = HilogLogger.getInstance();
+    }
+    return ILog.instance;
+  }
+  
+  /**
+   * 调试日志(静态方法)
+   */
+  static d(tag: string, message: string): void {
+    ILog.getInstance().d(tag, message);
+  }
+  
+  /**
+   * 信息日志(静态方法)
+   */
+  static i(tag: string, message: string): void {
+    ILog.getInstance().i(tag, message);
+  }
+  
+  /**
+   * 警告日志(静态方法)
+   */
+  static w(tag: string, message: string): void {
+    ILog.getInstance().w(tag, message);
+  }
+  
+  /**
+   * 错误日志(静态方法)
+   */
+  static e(tag: string, message: string, throwable?: Error): void {
+    ILog.getInstance().e(tag, message, throwable);
+  }
+  
+  /**
+   * 按级别记录日志(静态方法)
+   */
+  static log(level: LogLevel, tag: string, message: string, throwable?: Error): void {
+    ILog.getInstance().log(level, tag, message, throwable);
+  }
+  
+  /**
+   * 上传日志文件(静态方法)
+   */
+  static uploadLogs(): void {
+    ILog.getInstance().uploadLogs();
+  }
+  
+  /**
+   * 收集崩溃信息(静态方法)
+   */
+  static collectCrash(throwable: Error): void {
+    ILog.getInstance().collectCrash(throwable);
+  }
+}
+

+ 68 - 0
base-core/src/main/ets/core/log/impl/HilogLogger.ets

@@ -0,0 +1,68 @@
+import { hilog } from '@kit.PerformanceAnalysisKit';
+import { ILogger, LogLevel } from '../ILog';
+
+const DOMAIN = 0x0000;
+
+/**
+ * 基于 HarmonyOS hilog 的日志实现
+ * 
+ * 开发环境使用,输出详细日志
+ */
+export class HilogLogger implements ILogger {
+  private static instance: HilogLogger | null = null;
+  
+  static getInstance(): HilogLogger {
+    if (!HilogLogger.instance) {
+      HilogLogger.instance = new HilogLogger();
+    }
+    return HilogLogger.instance;
+  }
+  
+  d(tag: string, message: string): void {
+    hilog.debug(DOMAIN, tag, '%{public}s', message);
+  }
+  
+  i(tag: string, message: string): void {
+    hilog.info(DOMAIN, tag, '%{public}s', message);
+  }
+  
+  w(tag: string, message: string): void {
+    hilog.warn(DOMAIN, tag, '%{public}s', message);
+  }
+  
+  e(tag: string, message: string, throwable?: Error): void {
+    if (throwable) {
+      hilog.error(DOMAIN, tag, '%{public}s, error: %{public}s', message, throwable.message || 'Unknown error');
+    } else {
+      hilog.error(DOMAIN, tag, '%{public}s', message);
+    }
+  }
+  
+  log(level: LogLevel, tag: string, message: string, throwable?: Error): void {
+    switch (level) {
+      case LogLevel.DEBUG:
+        this.d(tag, message);
+        break;
+      case LogLevel.INFO:
+        this.i(tag, message);
+        break;
+      case LogLevel.WARN:
+        this.w(tag, message);
+        break;
+      case LogLevel.ERROR:
+        this.e(tag, message, throwable);
+        break;
+    }
+  }
+  
+  uploadLogs(): void {
+    // TODO: 实现日志上传功能
+    hilog.info(DOMAIN, 'HilogLogger', 'uploadLogs: 日志上传功能待实现');
+  }
+  
+  collectCrash(throwable: Error): void {
+    hilog.error(DOMAIN, 'Crash', '崩溃信息: %{public}s', throwable.message || 'Unknown crash');
+    // TODO: 实现崩溃收集功能
+  }
+}
+

+ 46 - 0
base-core/src/main/ets/core/log/impl/NoOpLogger.ets

@@ -0,0 +1,46 @@
+import { ILogger, LogLevel } from '../ILog';
+
+/**
+ * 空日志实现(生产环境使用)
+ * 
+ * 不输出任何日志,提升性能
+ */
+export class NoOpLogger implements ILogger {
+  private static instance: NoOpLogger | null = null;
+  
+  static getInstance(): NoOpLogger {
+    if (!NoOpLogger.instance) {
+      NoOpLogger.instance = new NoOpLogger();
+    }
+    return NoOpLogger.instance;
+  }
+  
+  d(tag: string, message: string): void {
+    // 空实现,不输出日志
+  }
+  
+  i(tag: string, message: string): void {
+    // 空实现,不输出日志
+  }
+  
+  w(tag: string, message: string): void {
+    // 空实现,不输出日志
+  }
+  
+  e(tag: string, message: string, throwable?: Error): void {
+    // 空实现,不输出日志
+  }
+  
+  log(level: LogLevel, tag: string, message: string, throwable?: Error): void {
+    // 空实现,不输出日志
+  }
+  
+  uploadLogs(): void {
+    // 空实现
+  }
+  
+  collectCrash(throwable: Error): void {
+    // 空实现
+  }
+}
+

+ 162 - 0
base-core/src/main/ets/core/network/NetworkManager.ets

@@ -0,0 +1,162 @@
+import { http } from '@kit.NetworkKit';
+import { ILog } from '../log/ILog';
+
+/**
+ * HTTP 请求管理器(单例模式)
+ * 
+ * 基于 HarmonyOS @kit.NetworkKit/http 封装
+ * 提供统一的 HTTP 请求接口
+ * 
+ * 使用方式:
+ * ```typescript
+ * const response = await NetworkManager.getInstance().request<ResponseType>(
+ *   'https://api.example.com/data',
+ *   {
+ *     method: http.RequestMethod.GET,
+ *     header: { 'Content-Type': 'application/json' }
+ *   }
+ * );
+ * ```
+ */
+export class NetworkManager {
+  private static instance: NetworkManager | null = null;
+  private httpRequest: http.HttpRequest | null = null;
+  private readonly TAG = 'NetworkManager';
+  
+  private constructor() {
+    // 私有构造函数,单例模式
+  }
+  
+  /**
+   * 获取单例实例
+   */
+  static getInstance(): NetworkManager {
+    if (!NetworkManager.instance) {
+      NetworkManager.instance = new NetworkManager();
+      NetworkManager.instance.httpRequest = http.createHttp();
+    }
+    return NetworkManager.instance;
+  }
+  
+  /**
+   * 发送 HTTP 请求
+   * 
+   * @param url 请求 URL
+   * @param options 请求选项
+   * @returns Promise<T> 响应数据
+   */
+  async request<T>(url: string, options: http.HttpRequestOptions): Promise<T> {
+    if (!this.httpRequest) {
+      this.httpRequest = http.createHttp();
+    }
+    
+    try {
+      const response: http.HttpResponse = await this.httpRequest.request(url, options);
+      
+      // 检查响应状态
+      if (response.responseCode >= 200 && response.responseCode < 300) {
+        // 解析 JSON 响应
+        if (response.result) {
+          const resultStr = typeof response.result === 'string' 
+            ? response.result 
+            : JSON.stringify(response.result);
+          return JSON.parse(resultStr) as T;
+        }
+        // 返回空对象(需要类型断言)
+        // 注意:如果响应为空,返回 null,调用方需要处理
+        return null as T;
+      } else {
+        const errorMsg = `HTTP ${response.responseCode}: ${response.result}`;
+        const error = new Error(errorMsg);
+        throw error;
+      }
+    } catch (error) {
+      ILog.e(this.TAG, `Request failed: ${url}`, error as Error);
+      if (error instanceof Error) {
+        throw error;
+      } else {
+        throw new Error(String(error));
+      }
+    }
+  }
+  
+  /**
+   * GET 请求
+   */
+  async get<T>(url: string, headers?: Record<string, string>): Promise<T> {
+    const options: http.HttpRequestOptions = {
+      method: http.RequestMethod.GET,
+      header: headers
+    };
+    return this.request<T>(url, options);
+  }
+  
+  /**
+   * POST 请求
+   */
+  async post<T>(url: string, data?: object, headers?: Record<string, string>): Promise<T> {
+    const header: Record<string, string> = {
+      'Content-Type': 'application/json'
+    };
+    if (headers) {
+      const keys = Object.keys(headers);
+      for (let i = 0; i < keys.length; i++) {
+        const key = keys[i];
+        header[key] = headers[key];
+      }
+    }
+    const postOptions: http.HttpRequestOptions = {
+      method: http.RequestMethod.POST,
+      header: header,
+      extraData: data ? JSON.stringify(data) : undefined
+    };
+    return this.request<T>(url, postOptions);
+  }
+  
+  /**
+   * PUT 请求
+   */
+  async put<T>(url: string, data?: object, headers?: Record<string, string>): Promise<T> {
+    const header: Record<string, string> = {
+      'Content-Type': 'application/json'
+    };
+    if (headers) {
+      const keys = Object.keys(headers);
+      for (let i = 0; i < keys.length; i++) {
+        const key = keys[i];
+        header[key] = headers[key];
+      }
+    }
+    const putOptions: http.HttpRequestOptions = {
+      method: http.RequestMethod.PUT,
+      header: header,
+      extraData: data ? JSON.stringify(data) : undefined
+    };
+    return this.request<T>(url, putOptions);
+  }
+  
+  /**
+   * DELETE 请求
+   */
+  async delete<T>(url: string, headers?: Record<string, string>): Promise<T> {
+    const deleteOptions: http.HttpRequestOptions = {
+      method: http.RequestMethod.DELETE,
+      header: headers
+    };
+    return this.request<T>(url, deleteOptions);
+  }
+  
+  /**
+   * 销毁 HTTP 请求实例
+   */
+  destroy(): void {
+    if (this.httpRequest) {
+      this.httpRequest.destroy();
+      this.httpRequest = null;
+    }
+  }
+}
+
+// 导出单例实例,方便使用
+export const networkManager = NetworkManager.getInstance();
+

+ 76 - 0
base-core/src/main/ets/core/push/IPushService.ets

@@ -0,0 +1,76 @@
+import { Context } from '@kit.AbilityKit';
+
+/**
+ * 推送服务接口
+ * 
+ * 用于 base-core 与 push 模块之间的解耦
+ * push 模块需要实现此接口
+ * 
+ * 注意:为了解耦,接口方法使用基本类型,具体类型由实现类处理
+ */
+export interface IPushService {
+  /**
+   * 初始化推送服务
+   * 
+   * @param context Application 上下文
+   * @param appKey 极光推送 AppKey
+   * @param channel 推送渠道(可选,默认为 "developer-default")
+   * @param debugMode 是否开启调试模式
+   */
+  initialize(context: Context, appKey: string, channel?: string, debugMode?: boolean): Promise<void>;
+  
+  /**
+   * 设置别名(用于推送)
+   * 
+   * @param alias 别名(通常是用户ID)
+   */
+  setAlias(alias: string): Promise<void>;
+  
+  /**
+   * 设置标签(用于推送)
+   * 
+   * @param tags 标签列表
+   */
+  setTags(tags: string[]): Promise<void>;
+  
+  /**
+   * 设置消息监听器(自定义消息/透传消息)
+   * 
+   * @param listener 消息接收回调
+   *                 参数:title, content, extras (Record<string, string>), messageId
+   */
+  setMessageListener(listener: (title: string, content: string, extras: Record<string, string>, messageId?: string) => void): void;
+  
+  /**
+   * 设置通知点击监听器(用户点击通知栏通知时触发)
+   * 
+   * @param listener 通知点击回调
+   *                 参数:title, content, extras (Record<string, string>), messageId
+   */
+  setNotificationClickListener(listener?: (title: string, content: string, extras: Record<string, string>, messageId?: string) => void): void;
+  
+  /**
+   * 注册推送(开启推送)
+   */
+  register(): Promise<void>;
+  
+  /**
+   * 注销推送(关闭推送)
+   */
+  unregister(): Promise<void>;
+  
+  /**
+   * 获取注册ID(用于标识设备)
+   * 
+   * @returns 设备注册ID,如果未初始化或获取失败返回 null
+   */
+  getRegistrationId(): Promise<string | null>;
+  
+  /**
+   * 检查推送是否已开启
+   * 
+   * @returns true 表示推送已开启,false 表示推送已停止或未初始化
+   */
+  isPushEnabled(): Promise<boolean>;
+}
+

+ 166 - 0
base-core/src/main/ets/core/share/IShareService.ets

@@ -0,0 +1,166 @@
+import { Context } from '@kit.AbilityKit';
+import { Want } from '@kit.AbilityKit';
+
+/**
+ * 分享服务接口
+ * 
+ * 用于 base-core 与 share 模块之间的解耦
+ * share 模块需要实现此接口
+ * 
+ * 注意:为了解耦,接口方法使用基本类型,具体类型由实现类处理
+ */
+export interface IShareService {
+  /**
+   * 初始化分享服务
+   * 
+   * @param context Application 上下文
+   * @param umengAppKey 友盟 AppKey(可选,如果为空则从资源文件读取)
+   * @param umengChannel 友盟渠道(可选,默认为 "developer-default")
+   * @param weChatAppId 微信 AppID(可选)
+   * @param weChatAppSecret 微信 AppSecret(可选)
+   * @param qqAppId QQ AppID(可选)
+   * @param qqAppKey QQ AppKey(可选)
+   * @param weiboAppKey 微博 AppKey(可选)
+   * @param weiboAppSecret 微博 AppSecret(可选)
+   * @param weiboRedirectUrl 微博回调地址(可选)
+   */
+  initialize(
+    context: Context,
+    umengAppKey?: string,
+    umengChannel?: string,
+    weChatAppId?: string,
+    weChatAppSecret?: string,
+    qqAppId?: string,
+    qqAppKey?: string,
+    weiboAppKey?: string,
+    weiboAppSecret?: string,
+    weiboRedirectUrl?: string
+  ): Promise<void>;
+  
+  /**
+   * 处理分享回调(内部使用)
+   * 
+   * @param want Want 对象(HarmonyOS 的回调方式)
+   */
+  onShareResult(want: Want): void;
+  
+  /**
+   * 统一分享方法(推荐使用)
+   * 
+   * @param context Context 上下文
+   * @param title 分享标题
+   * @param description 分享描述
+   * @param url 分享链接(可选)
+   * @param imageUrl 图片URL(可选)
+   * @param thumbImageUrl 缩略图URL(可选)
+   * @param platform 分享平台(可选,如果为 null 则显示分享弹窗)
+   * @param callback 分享结果回调
+   *                 参数:success (boolean), platform (string?), errorMessage (string?)
+   */
+  share(
+    context: Context,
+    title: string,
+    description: string,
+    url?: string,
+    imageUrl?: string,
+    thumbImageUrl?: string,
+    platform?: string,
+    callback?: (success: boolean, platform?: string, errorMessage?: string) => void
+  ): Promise<void>;
+  
+  /**
+   * 分享到微信
+   */
+  shareToWeChat(
+    context: Context,
+    title: string,
+    description: string,
+    url?: string,
+    imageUrl?: string,
+    thumbImageUrl?: string,
+    callback?: (success: boolean, platform?: string, errorMessage?: string) => void
+  ): Promise<void>;
+  
+  /**
+   * 分享到微信朋友圈
+   */
+  shareToWeChatMoments(
+    context: Context,
+    title: string,
+    description: string,
+    url?: string,
+    imageUrl?: string,
+    thumbImageUrl?: string,
+    callback?: (success: boolean, platform?: string, errorMessage?: string) => void
+  ): Promise<void>;
+  
+  /**
+   * 分享到QQ
+   */
+  shareToQQ(
+    context: Context,
+    title: string,
+    description: string,
+    url?: string,
+    imageUrl?: string,
+    thumbImageUrl?: string,
+    callback?: (success: boolean, platform?: string, errorMessage?: string) => void
+  ): Promise<void>;
+  
+  /**
+   * 分享到QQ空间
+   */
+  shareToQZone(
+    context: Context,
+    title: string,
+    description: string,
+    url?: string,
+    imageUrl?: string,
+    thumbImageUrl?: string,
+    callback?: (success: boolean, platform?: string, errorMessage?: string) => void
+  ): Promise<void>;
+  
+  /**
+   * 分享到微博
+   */
+  shareToWeibo(
+    context: Context,
+    title: string,
+    description: string,
+    url?: string,
+    imageUrl?: string,
+    thumbImageUrl?: string,
+    callback?: (success: boolean, platform?: string, errorMessage?: string) => void
+  ): Promise<void>;
+  
+  /**
+   * 系统分享(调用系统分享菜单)
+   */
+  shareToSystem(
+    context: Context,
+    title: string,
+    description: string,
+    url?: string,
+    imageUrl?: string,
+    thumbImageUrl?: string,
+    callback?: (success: boolean, platform?: string, errorMessage?: string) => void
+  ): Promise<void>;
+}
+
+/**
+ * 分享回调接口
+ * 
+ * 用于 base-core 与 share 模块之间的解耦
+ * base-core 中的 WXEntryAbility 等回调 Ability 通过此接口调用 share 模块的实现
+ * 
+ * share 模块需要实现此接口
+ */
+export interface IShareCallback {
+  /**
+   * 处理微信回调
+   * 
+   * @param want Want 对象(HarmonyOS 的回调方式)
+   */
+  onWeChatCallback(want: Want): void;
+}
+

+ 30 - 0
base-core/src/main/ets/core/storage/IStorage.ets

@@ -0,0 +1,30 @@
+/**
+ * 存储服务接口
+ * 统一封装键值存储、文件存储、数据库存储
+ * 
+ * 实现类:StorageImpl(在 base-core 中提供)
+ * 所有模块都可以直接使用 StorageImpl 进行数据存储
+ */
+export interface IStorage {
+  /**
+   * 键值存储
+   */
+  putString(key: string, value: string): Promise<void>;
+  getString(key: string, defaultValue?: string): Promise<string>;
+  putInt(key: string, value: number): Promise<void>;
+  getInt(key: string, defaultValue?: number): Promise<number>;
+  putLong(key: string, value: number): Promise<void>;
+  getLong(key: string, defaultValue?: number): Promise<number>;
+  putBoolean(key: string, value: boolean): Promise<void>;
+  getBoolean(key: string, defaultValue?: boolean): Promise<boolean>;
+  remove(key: string): Promise<void>;
+  clear(): Promise<void>;
+  
+  /**
+   * 文件存储
+   */
+  saveFile(path: string, data: Uint8Array): Promise<boolean>;
+  readFile(path: string): Promise<Uint8Array | null>;
+  deleteFile(path: string): Promise<boolean>;
+}
+

+ 319 - 0
base-core/src/main/ets/core/storage/StorageImpl.ets

@@ -0,0 +1,319 @@
+import dataPreferences from '@ohos.data.preferences';
+import { Context } from '@kit.AbilityKit';
+import { IStorage } from './IStorage';
+import { fileIo } from '@kit.CoreFileKit';
+
+/**
+ * 存储服务实现类(基于 HarmonyOS preferences)
+ * 
+ * 统一提供键值存储和文件存储功能
+ * 单例模式,需要在 Application 中初始化
+ * 
+ * 使用方式:
+ * ```typescript
+ * // 在 Application 中初始化
+ * await StorageImpl.init(context);
+ * 
+ * // 使用存储
+ * await StorageImpl.putString("key", "value");
+ * const value = await StorageImpl.getString("key");
+ * ```
+ */
+export class StorageImpl implements IStorage {
+  private static instance: StorageImpl | null = null;
+  private static readonly PREFS_NAME = 'xdz_storage_prefs';
+  private dataPreferences: dataPreferences.Preferences | null = null;
+  private context: Context | null = null;
+  private initialized = false;
+  
+  private constructor() {
+    // 私有构造函数,单例模式
+  }
+  
+  /**
+   * 获取单例实例
+   */
+  static getInstance(): StorageImpl {
+    if (!StorageImpl.instance) {
+      StorageImpl.instance = new StorageImpl();
+    }
+    return StorageImpl.instance;
+  }
+  
+  /**
+   * 初始化存储服务
+   * 
+   * 需要在 Application.onCreate() 中调用
+   * 
+   * @param ctx 应用上下文
+   */
+  static async init(ctx: Context): Promise<void> {
+    try {
+      const instance = StorageImpl.getInstance();
+      instance.context = ctx;
+      instance.dataPreferences = await dataPreferences.getPreferences(ctx, StorageImpl.PREFS_NAME);
+      instance.initialized = true;
+    } catch (err) {
+      console.error('StorageImpl初始化失败:', err);
+      if (err instanceof Error) {
+      throw err;
+      } else {
+        throw new Error(String(err));
+      }
+    }
+  }
+  
+  /**
+   * 检查是否已初始化
+   */
+  static isInitialized(): boolean {
+    return StorageImpl.getInstance().initialized;
+  }
+  
+  // ========== 键值存储 ==========
+  
+  async putString(key: string, value: string): Promise<void> {
+    try {
+      if (!this.dataPreferences) {
+        throw new Error('StorageImpl not initialized. Call StorageImpl.init() first.');
+      }
+      await this.dataPreferences.put(key, value);
+      // HarmonyOS preferences 会自动持久化,不需要每次操作都 flush
+      // flush 可以在批量操作后统一调用,或由系统自动处理
+    } catch (err) {
+      console.error('putString操作失败:', err);
+      if (err instanceof Error) {
+      throw err;
+      } else {
+        throw new Error(String(err));
+      }
+    }
+  }
+  
+  async getString(key: string, defaultValue: string = ''): Promise<string> {
+    try {
+      if (!this.dataPreferences) {
+        return defaultValue;
+      }
+      const value = await this.dataPreferences.get(key, defaultValue);
+      return typeof value === 'string' ? value : defaultValue;
+    } catch (err) {
+      console.error('getString操作失败:', err);
+      return defaultValue;
+    }
+  }
+  
+  async putInt(key: string, value: number): Promise<void> {
+    try {
+      if (!this.dataPreferences) {
+        throw new Error('StorageImpl not initialized. Call StorageImpl.init() first.');
+      }
+      await this.dataPreferences.put(key, value);
+      // HarmonyOS preferences 会自动持久化,不需要每次操作都 flush
+    } catch (err) {
+      console.error('putInt操作失败:', err);
+      if (err instanceof Error) {
+      throw err;
+      } else {
+        throw new Error(String(err));
+      }
+    }
+  }
+  
+  async getInt(key: string, defaultValue: number = 0): Promise<number> {
+    try {
+      if (!this.dataPreferences) {
+        return defaultValue;
+      }
+      const value = await this.dataPreferences.get(key, defaultValue);
+      return typeof value === 'number' ? value : defaultValue;
+    } catch (err) {
+      console.error('getInt操作失败:', err);
+      return defaultValue;
+    }
+  }
+  
+  async putLong(key: string, value: number): Promise<void> {
+    try {
+      // HarmonyOS preferences 使用 number 类型,可以存储 Long 值
+      if (!this.dataPreferences) {
+        throw new Error('StorageImpl not initialized. Call StorageImpl.init() first.');
+      }
+      await this.dataPreferences.put(key, value);
+      // HarmonyOS preferences 会自动持久化,不需要每次操作都 flush
+    } catch (err) {
+      console.error('putLong操作失败:', err);
+      if (err instanceof Error) {
+      throw err;
+      } else {
+        throw new Error(String(err));
+      }
+    }
+  }
+  
+  async getLong(key: string, defaultValue: number = 0): Promise<number> {
+    try {
+      if (!this.dataPreferences) {
+        return defaultValue;
+      }
+      const value = await this.dataPreferences.get(key, defaultValue);
+      return typeof value === 'number' ? value : defaultValue;
+    } catch (err) {
+      console.error('getLong操作失败:', err);
+      return defaultValue;
+    }
+  }
+  
+  async putBoolean(key: string, value: boolean): Promise<void> {
+    try {
+      if (!this.dataPreferences) {
+        throw new Error('StorageImpl not initialized. Call StorageImpl.init() first.');
+      }
+      await this.dataPreferences.put(key, value);
+      // HarmonyOS preferences 会自动持久化,不需要每次操作都 flush
+    } catch (err) {
+      console.error('putBoolean操作失败:', err);
+      if (err instanceof Error) {
+      throw err;
+      } else {
+        throw new Error(String(err));
+      }
+    }
+  }
+  
+  async getBoolean(key: string, defaultValue: boolean = false): Promise<boolean> {
+    try {
+      if (!this.dataPreferences) {
+        return defaultValue;
+      }
+      const value = await this.dataPreferences.get(key, defaultValue);
+      return typeof value === 'boolean' ? value : defaultValue;
+    } catch (err) {
+      console.error('getBoolean操作失败:', err);
+      return defaultValue;
+    }
+  }
+  
+  async remove(key: string): Promise<void> {
+    try {
+      if (!this.dataPreferences) {
+        return;
+      }
+      await this.dataPreferences.delete(key);
+      // HarmonyOS preferences 会自动持久化,不需要每次操作都 flush
+    } catch (err) {
+      console.error('remove操作失败:', err);
+    }
+  }
+  
+  async clear(): Promise<void> {
+    try {
+      if (!this.dataPreferences) {
+        return;
+      }
+      await this.dataPreferences.clear();
+      // clear 操作后可以调用 flush 确保立即持久化
+      await this.dataPreferences.flush();
+    } catch (err) {
+      console.error('clear操作失败:', err);
+    }
+  }
+  
+  /**
+   * 手动刷新数据到磁盘(可选方法)
+   * 
+   * 在批量操作后可以调用此方法确保数据立即持久化
+   */
+  async flush(): Promise<void> {
+    try {
+      if (!this.dataPreferences) {
+        return;
+      }
+      await this.dataPreferences.flush();
+    } catch (err) {
+      console.error('flush操作失败:', err);
+    }
+  }
+  
+  // ========== 文件存储 ==========
+  
+  async saveFile(path: string, data: Uint8Array): Promise<boolean> {
+    try {
+      const ctx = this.context;
+      if (!ctx) {
+        return false;
+      }
+      
+      const filesDir = ctx.filesDir;
+      const filePath = `${filesDir}/${path}`;
+      
+      // 确保目录存在
+      const dirPath = filePath.substring(0, filePath.lastIndexOf('/'));
+      await fileIo.mkdir(dirPath, true);
+      
+      // 写入文件
+      const file = await fileIo.open(filePath, fileIo.OpenMode.CREATE | fileIo.OpenMode.WRITE_ONLY);
+      await fileIo.write(file.fd, data.buffer);
+      await fileIo.close(file.fd);
+      
+      return true;
+    } catch (e) {
+      return false;
+    }
+  }
+  
+  async readFile(path: string): Promise<Uint8Array | null> {
+    try {
+      const ctx = this.context;
+      if (!ctx) {
+        return null;
+      }
+      
+      const filePath = `${ctx.filesDir}/${path}`;
+      
+      // 检查文件是否存在
+      const stat = await fileIo.stat(filePath);
+      if (!stat.isFile()) {
+        return null;
+      }
+      
+      // 读取文件
+      const file = await fileIo.open(filePath, fileIo.OpenMode.READ_ONLY);
+      const statInfo = await fileIo.stat(filePath);
+      const buffer = new ArrayBuffer(statInfo.size);
+      await fileIo.read(file.fd, buffer);
+      await fileIo.close(file.fd);
+      
+      return new Uint8Array(buffer);
+    } catch (e) {
+      return null;
+    }
+  }
+  
+  async deleteFile(path: string): Promise<boolean> {
+    try {
+      const ctx = this.context;
+      if (!ctx) {
+        return false;
+      }
+      
+      const filePath = `${ctx.filesDir}/${path}`;
+      
+      // 检查文件是否存在
+      const stat = await fileIo.stat(filePath);
+      if (!stat.isFile()) {
+        return false;
+      }
+      
+      // 删除文件
+      await fileIo.unlink(filePath);
+      return true;
+    } catch (e) {
+      return false;
+    }
+  }
+}
+
+// 导出单例实例,方便使用
+export const storageImpl = StorageImpl.getInstance();
+

+ 201 - 0
base-core/src/main/ets/core/util/JWTUtil.ets

@@ -0,0 +1,201 @@
+/**
+ * JWT Token 工具类
+ * 
+ * 提供 JWT Token 解析和验证功能
+ * 参考 iOS 和 Android 实现
+ * 
+ * 使用方式:
+ * ```typescript
+ * // 检查 Token 是否有效(未过期)
+ * const isValid = JWTUtil.isTokenValid(token);
+ * 
+ * // 获取 Token 过期时间
+ * const expiresAt = JWTUtil.getExpiresAt(token);
+ * ```
+ */
+
+/**
+ * JWT Payload 接口
+ * 
+ * 定义 JWT Token payload 的标准字段
+ * 注意:ArkTS 不支持索引签名和 unknown 类型,因此移除了其他字段的定义
+ */
+interface JwtPayload {
+  exp?: number;  // 过期时间(Unix时间戳,单位:秒)
+  iat?: number;  // 签发时间
+  userId?: string;  // 用户ID
+}
+
+/**
+ * JWT Token 工具类
+ * 
+ * 提供 JWT Token 解析和验证功能
+ */
+export class JWTUtil {
+  /**
+   * Base64URL 解码
+   * 
+   * JWT 使用 Base64URL 编码,需要将 URL 安全的字符转换回标准 Base64
+   * - 将 '-' 替换为 '+'
+   * - 将 '_' 替换为 '/'
+   * - 添加必要的 padding
+   * 
+   * @param base64Url Base64URL 编码的字符串
+   * @returns 解码后的 Uint8Array,如果解码失败返回 null
+   */
+  private static base64UrlDecode(base64Url: string): Uint8Array | null {
+    try {
+      // Base64URL 转 Base64
+      let base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
+      
+      // 添加 padding
+      const padLength = (4 - base64.length % 4) % 4;
+      base64 = base64 + '='.repeat(padLength);
+      
+      // HarmonyOS 使用手动实现的 Base64 解码
+      return JWTUtil.base64Decode(base64);
+    } catch (e) {
+      return null;
+    }
+  }
+  
+  /**
+   * Base64 解码(手动实现)
+   * 
+   * @param base64 Base64 编码的字符串
+   * @returns 解码后的 Uint8Array
+   */
+  private static base64Decode(base64: string): Uint8Array {
+    const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
+    let output = '';
+    
+    base64 = base64.replace(/[^A-Za-z0-9\+\/\=]/g, '');
+    
+    for (let i = 0; i < base64.length; i += 4) {
+      const enc1 = chars.indexOf(base64.charAt(i));
+      const enc2 = chars.indexOf(base64.charAt(i + 1));
+      const enc3 = chars.indexOf(base64.charAt(i + 2));
+      const enc4 = chars.indexOf(base64.charAt(i + 3));
+      
+      const chr1 = (enc1 << 2) | (enc2 >> 4);
+      const chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
+      const chr3 = ((enc3 & 3) << 6) | enc4;
+      
+      output += String.fromCharCode(chr1);
+      
+      if (enc3 !== 64) {
+        output += String.fromCharCode(chr2);
+      }
+      if (enc4 !== 64) {
+        output += String.fromCharCode(chr3);
+      }
+    }
+    
+    const bytes = new Uint8Array(output.length);
+    for (let i = 0; i < output.length; i++) {
+      bytes[i] = output.charCodeAt(i);
+    }
+    return bytes;
+  }
+  
+  /**
+   * 解析 JWT Token 并检查是否过期
+   * 
+   * @param token JWT Token
+   * @returns true 如果 Token 未过期,false 如果过期或无法解析
+   */
+  static isTokenValid(token: string): boolean {
+    if (!token || token === '') {
+      return false;
+    }
+    
+    // JWT 格式:header.payload.signature
+    const parts = token.split('.');
+    if (parts.length !== 3) {
+      return false;
+    }
+    
+    // 解析 payload(第二部分)
+    const payload = parts[1];
+    
+    // Base64URL 解码
+    const payloadData = JWTUtil.base64UrlDecode(payload);
+    if (!payloadData) {
+      return false;
+    }
+    
+    // 转换为 JSON 字符串(手动实现 UTF-8 解码)
+    const payloadString = JWTUtil.uint8ArrayToString(payloadData);
+    
+    try {
+      const payloadJson: JwtPayload = JSON.parse(payloadString) as JwtPayload;
+      const exp = payloadJson.exp;
+      
+      if (typeof exp !== 'number') {
+        return false;
+      }
+      
+      // 检查是否过期(exp 是 Unix 时间戳,单位:秒)
+      const currentTime = Math.floor(Date.now() / 1000);
+      return exp > currentTime;
+    } catch (e) {
+      return false;
+    }
+  }
+  
+  /**
+   * 解析 JWT Token 并获取过期时间
+   * 
+   * @param token JWT Token
+   * @returns 过期时间(Unix 时间戳,单位:秒),如果无法解析返回 null
+   */
+  static getExpiresAt(token: string): number | null {
+    if (!token || token === '') {
+      return null;
+    }
+    
+    // JWT 格式:header.payload.signature
+    const parts = token.split('.');
+    if (parts.length !== 3) {
+      return null;
+    }
+    
+    // 解析 payload(第二部分)
+    const payload = parts[1];
+    
+    // Base64URL 解码
+    const payloadData = JWTUtil.base64UrlDecode(payload);
+    if (!payloadData) {
+      return null;
+    }
+    
+    // 转换为 JSON 字符串(手动实现 UTF-8 解码)
+    const payloadString = JWTUtil.uint8ArrayToString(payloadData);
+    
+    try {
+      const payloadJson: JwtPayload = JSON.parse(payloadString) as JwtPayload;
+      const exp = payloadJson.exp;
+      
+      if (typeof exp === 'number') {
+        return exp;
+      }
+      return null;
+    } catch (e) {
+      return null;
+    }
+  }
+  
+  /**
+   * 将 Uint8Array 转换为 UTF-8 字符串(手动实现)
+   * 
+   * @param bytes Uint8Array
+   * @returns UTF-8 字符串
+   */
+  private static uint8ArrayToString(bytes: Uint8Array): string {
+    let result = '';
+    for (let i = 0; i < bytes.length; i++) {
+      result += String.fromCharCode(bytes[i]);
+    }
+    return result;
+  }
+}

+ 27 - 0
base-core/src/main/ets/index.ets

@@ -0,0 +1,27 @@
+/**
+ * base-core 模块导出入口
+ * 
+ * 统一导出所有核心接口和实现
+ */
+
+// 日志模块
+export { ILog, ILogger, LogLevel } from './core/log/ILog';
+export { HilogLogger } from './core/log/impl/HilogLogger';
+export { NoOpLogger } from './core/log/impl/NoOpLogger';
+
+// 存储模块
+export { IStorage } from './core/storage/IStorage';
+export { StorageImpl, storageImpl } from './core/storage/StorageImpl';
+
+// 网络模块
+export { NetworkManager, networkManager } from './core/network/NetworkManager';
+
+// 推送模块
+export { IPushService } from './core/push/IPushService';
+
+// 分享模块
+export { IShareService, IShareCallback } from './core/share/IShareService';
+
+// 工具模块
+export { JWTUtil } from './core/util/JWTUtil';
+

+ 13 - 0
base-core/src/main/module.json5

@@ -0,0 +1,13 @@
+{
+  "module": {
+    "name": "base_core",
+    "type": "har",
+    "description": "基础设施层 - 定义接口和基础实现",
+    "mainElement": "",
+    "deviceTypes": [
+      "phone",
+      "tablet"
+    ]
+  }
+}
+

+ 152 - 0
build-profile.json5

@@ -0,0 +1,152 @@
+{
+  "app": {
+    "signingConfigs": [
+      {
+        "name": "default",
+        "type": "HarmonyOS",
+        "material": {
+          "certpath": "/Users/Zhuanz/.ohos/config/default_xdz_harmonyos_jZFehHJzNrGqakNEAMUxlW8I1FRp2PB5-LbDEsJxfxs=.cer",
+          "keyAlias": "debugKey",
+          "keyPassword": "0000001BB6238A05D86EA280B8370E117DB08327AC0ECCCEDA1EB677B27BEF0B79F6254D11EBAB02077C74",
+          "profile": "/Users/Zhuanz/.ohos/config/default_xdz_harmonyos_jZFehHJzNrGqakNEAMUxlW8I1FRp2PB5-LbDEsJxfxs=.p7b",
+          "signAlg": "SHA256withECDSA",
+          "storeFile": "/Users/Zhuanz/.ohos/config/default_xdz_harmonyos_jZFehHJzNrGqakNEAMUxlW8I1FRp2PB5-LbDEsJxfxs=.p12",
+          "storePassword": "0000001B3CF203584597C7690A705664A9EEFC3BFFBC477632C20FFE4702EC1510CD38B9156DB735AE1D84"
+        }
+      }
+    ],
+    "products": [
+      {
+        "name": "default",
+        "signingConfig": "default",
+        "targetSdkVersion": "6.0.1(21)",
+        "compatibleSdkVersion": "6.0.1(21)",
+        "runtimeOS": "HarmonyOS",
+        "buildOption": {
+          "strictMode": {
+            "caseSensitiveCheck": true,
+            "useNormalizedOHMUrl": true
+          }
+        }
+      }
+    ],
+    "buildModeSet": [
+      {
+        "name": "debug",
+      },
+      {
+        "name": "release"
+      }
+    ]
+  },
+  "modules": [
+    {
+      "name": "entry",
+      "srcPath": "./entry",
+      "targets": [
+        {
+          "name": "default",
+          "applyToProducts": [
+            "default"
+          ]
+        }
+      ]
+    },
+    {
+      "name": "base_core",
+      "srcPath": "./base-core",
+      "targets": [
+        {
+          "name": "default",
+          "applyToProducts": [
+            "default"
+          ]
+        }
+      ]
+    },
+    {
+      "name": "base_common",
+      "srcPath": "./base-common",
+      "targets": [
+        {
+          "name": "default",
+          "applyToProducts": [
+            "default"
+          ]
+        }
+      ]
+    },
+    {
+      "name": "capability_socketio",
+      "srcPath": "./capability-socketio",
+      "targets": [
+        {
+          "name": "default",
+          "applyToProducts": [
+            "default"
+          ]
+        }
+      ]
+    },
+    {
+      "name": "capability_push",
+      "srcPath": "./capability-push",
+      "targets": [
+        {
+          "name": "default",
+          "applyToProducts": [
+            "default"
+          ]
+        }
+      ]
+    },
+    {
+      "name": "capability_share",
+      "srcPath": "./capability-share",
+      "targets": [
+        {
+          "name": "default",
+          "applyToProducts": [
+            "default"
+          ]
+        }
+      ]
+    },
+    {
+      "name": "capability_qrcode",
+      "srcPath": "./capability-qrcode",
+      "targets": [
+        {
+          "name": "default",
+          "applyToProducts": [
+            "default"
+          ]
+        }
+      ]
+    },
+    {
+      "name": "capability_nfc",
+      "srcPath": "./capability-nfc",
+      "targets": [
+        {
+          "name": "default",
+          "applyToProducts": [
+            "default"
+          ]
+        }
+      ]
+    },
+    {
+      "name": "capability_ble",
+      "srcPath": "./capability-ble",
+      "targets": [
+        {
+          "name": "default",
+          "applyToProducts": [
+            "default"
+          ]
+        }
+      ]
+    }
+  ]
+}

+ 113 - 0
build.sh

@@ -0,0 +1,113 @@
+#!/bin/bash
+
+# ================================================
+# HarmonyOS 项目编译脚本
+# ================================================
+
+# 设置颜色输出
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+YELLOW='\033[1;33m'
+NC='\033[0m' # No Color
+
+echo -e "${GREEN}================================${NC}"
+echo -e "${GREEN}  HarmonyOS 项目编译脚本${NC}"
+echo -e "${GREEN}================================${NC}"
+echo ""
+
+# 1. 检查 Node.js
+echo -e "${YELLOW}[1/6] 检查 Node.js...${NC}"
+if ! command -v node &> /dev/null; then
+    echo -e "${RED}❌ 未找到 Node.js,请先安装 Node.js${NC}"
+    exit 1
+fi
+NODE_VERSION=$(node --version)
+echo -e "${GREEN}✅ Node.js 版本: $NODE_VERSION${NC}"
+echo ""
+
+# 2. 检查 DevEco Studio
+echo -e "${YELLOW}[2/6] 检查 DevEco Studio...${NC}"
+DEVECO_APP="/Applications/DevEco-Studio.app"
+if [ ! -d "$DEVECO_APP" ]; then
+    echo -e "${RED}❌ 未找到 DevEco Studio,请先安装${NC}"
+    exit 1
+fi
+echo -e "${GREEN}✅ DevEco Studio 已安装${NC}"
+echo ""
+
+# 3. 设置环境变量
+echo -e "${YELLOW}[3/6] 设置环境变量...${NC}"
+
+# Node 和 hvigorw 路径
+NODE_BIN="$DEVECO_APP/Contents/tools/node/bin/node"
+HVIGORW_JS="$DEVECO_APP/Contents/tools/hvigor/bin/hvigorw.js"
+
+# SDK 路径(正确的路径)
+export DEVECO_SDK_HOME="$DEVECO_APP/Contents/sdk"
+export HOS_SDK_HOME="$DEVECO_APP/Contents/sdk"
+export OHOS_SDK_HOME="$DEVECO_APP/Contents/sdk"
+
+if [ ! -d "$DEVECO_SDK_HOME" ]; then
+    echo -e "${RED}❌ 未找到 SDK: $DEVECO_SDK_HOME${NC}"
+    echo -e "${YELLOW}提示:在 DevEco Studio 中打开项目,SDK 会自动下载${NC}"
+    exit 1
+fi
+echo -e "${GREEN}✅ SDK 路径: $DEVECO_SDK_HOME${NC}"
+echo ""
+
+# 4. 清理之前的构建
+echo -e "${YELLOW}[4/6] 清理之前的构建...${NC}"
+if [ -d "build" ]; then
+    rm -rf build
+    echo -e "${GREEN}✅ 已清理 build 目录${NC}"
+fi
+echo ""
+
+# 5. 停止之前的 daemon
+echo -e "${YELLOW}[5/6] 停止之前的 hvigor daemon...${NC}"
+"$NODE_BIN" "$HVIGORW_JS" --stop-daemon 2>/dev/null || true
+echo ""
+
+# 6. 开始编译
+echo -e "${YELLOW}[6/6] 开始编译项目...${NC}"
+echo -e "${YELLOW}命令: node hvigorw.js --mode module -p module=entry@default -p product=default -p requiredDeviceType=tablet assembleHap --analyze=normal --parallel --incremental --daemon${NC}"
+echo ""
+
+"$NODE_BIN" "$HVIGORW_JS" \
+  --mode module \
+  -p module=entry@default \
+  -p product=default \
+  -p requiredDeviceType=tablet \
+  assembleHap \
+  --analyze=normal \
+  --parallel \
+  --incremental \
+  --daemon
+
+EXIT_CODE=$?
+
+echo ""
+if [ $EXIT_CODE -eq 0 ]; then
+    echo -e "${GREEN}================================${NC}"
+    echo -e "${GREEN}  ✅ 编译成功!${NC}"
+    echo -e "${GREEN}================================${NC}"
+    echo ""
+    echo -e "${GREEN}输出文件位置:${NC}"
+    find entry/build -name "*.hap" -type f 2>/dev/null | while read file; do
+        size=$(du -h "$file" 2>/dev/null | cut -f1)
+        echo -e "${GREEN}  📦 $file ($size)${NC}"
+    done
+else
+    echo -e "${RED}================================${NC}"
+    echo -e "${RED}  ❌ 编译失败!${NC}"
+    echo -e "${RED}================================${NC}"
+    echo ""
+    echo -e "${YELLOW}故障排查建议:${NC}"
+    echo -e "1. 在 DevEco Studio 中打开项目"
+    echo -e "2. 等待 SDK 自动下载完成"
+    echo -e "3. 在 DevEco Studio 中点击 Build > Build Hap(s)"
+    echo -e "4. 确认可以在 IDE 中编译成功后,再使用脚本编译"
+fi
+
+exit $EXIT_CODE
+

+ 31 - 0
capability-ble/.preview/default/intermediates/merge_profile/default/module.json

@@ -0,0 +1,31 @@
+{
+	"app": {
+		"bundleName": "com.narutohuo.xdz",
+		"debug": true,
+		"versionCode": 1000000,
+		"versionName": "1.0.0",
+		"minAPIVersion": 60001021,
+		"targetAPIVersion": 60001021,
+		"apiReleaseType": "Release",
+		"targetMinorAPIVersion": 0,
+		"targetPatchAPIVersion": 0,
+		"compileSdkVersion": "6.0.1.112",
+		"compileSdkType": "HarmonyOS",
+		"appEnvironments": [],
+		"bundleType": "app",
+		"buildMode": "debug"
+	},
+	"module": {
+		"name": "capability_ble",
+		"type": "har",
+		"description": "蓝牙低功耗(BLE)能力层模块",
+		"mainElement": "",
+		"deviceTypes": [
+			"phone",
+			"tablet",
+			"2in1"
+		],
+		"packageName": "@xdz/capability-ble",
+		"installationFree": false
+	}
+}

+ 17 - 0
capability-ble/BuildProfile.ets

@@ -0,0 +1,17 @@
+/**
+ * Use these variables when you tailor your ArkTS code. They must be of the const type.
+ */
+export const HAR_VERSION = '1.0.0';
+export const BUILD_MODE_NAME = 'debug';
+export const DEBUG = true;
+export const TARGET_NAME = 'default';
+
+/**
+ * BuildProfile Class is used only for compatibility purposes.
+ */
+export default class BuildProfile { 
+	static readonly HAR_VERSION = HAR_VERSION;
+	static readonly BUILD_MODE_NAME = BUILD_MODE_NAME;
+	static readonly DEBUG = DEBUG;
+	static readonly TARGET_NAME = TARGET_NAME;
+}

+ 28 - 0
capability-ble/build-profile.json5

@@ -0,0 +1,28 @@
+{
+  "apiType": "stageMode",
+  "buildOption": {
+    "resOptions": {
+      "copyCodeResource": {
+        "enable": false
+      }
+    }
+  },
+  "buildOptionSet": [
+    {
+      "name": "release",
+      "arkOptions": {
+        "obfuscation": {
+          "ruleOptions": {
+            "enable": false
+          }
+        }
+      }
+    }
+  ],
+  "targets": [
+    {
+      "name": "default"
+    }
+  ]
+}
+

+ 7 - 0
capability-ble/hvigorfile.ts

@@ -0,0 +1,7 @@
+import { harTasks } from '@ohos/hvigor-ohos-plugin';
+
+export default {
+  system: harTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
+  plugins: []       /* Custom plugin to extend the functionality of Hvigor. */
+}
+

+ 19 - 0
capability-ble/oh-package-lock.json5

@@ -0,0 +1,19 @@
+{
+  "meta": {
+    "stableOrder": true,
+    "enableUnifiedLockfile": false
+  },
+  "lockfileVersion": 3,
+  "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.",
+  "specifiers": {
+    "@xdz/base-core@../base-core": "@xdz/base-core@../base-core"
+  },
+  "packages": {
+    "@xdz/base-core@../base-core": {
+      "name": "@xdz/base-core",
+      "version": "1.0.0",
+      "resolved": "../base-core",
+      "registryType": "local"
+    }
+  }
+}

+ 12 - 0
capability-ble/oh-package.json5

@@ -0,0 +1,12 @@
+{
+  "name": "@xdz/capability-ble",
+  "version": "1.0.0",
+  "description": "蓝牙低功耗(BLE)能力层模块 - 提供蓝牙通信能力,可独立打包为 SDK",
+  "main": "src/main/ets/index.ets",
+  "dependencies": {
+    "@xdz/base-core": "file:../base-core"
+  },
+  "license": "MIT",
+  "keywords": ["ble", "bluetooth", "capability"]
+}
+

+ 1 - 0
capability-ble/oh_modules/@xdz/base-core

@@ -0,0 +1 @@
+../../../base-core

+ 258 - 0
capability-ble/src/main/ets/ble/api/BLEService.ets

@@ -0,0 +1,258 @@
+import { Context } from '@kit.AbilityKit';
+import { BLEDevice } from '../model/BLEDevice';
+import { BLEResponse } from '../model/BLEResponse';
+import { BLECommand } from '../model/BLECommand';
+
+/**
+ * BLE服务接口
+ * 
+ * 提供蓝牙低功耗(BLE)通信能力
+ * 封装新大洲本田蓝牙协议,提供高级API供业务模块调用
+ */
+export interface BLEService {
+  // ========== 初始化 ==========
+  
+  /**
+   * 初始化(设置Context)
+   * 
+   * @param context 应用上下文
+   */
+  init(context: Context): void;
+  
+  // ========== 基础连接功能 ==========
+  
+  /**
+   * 开始扫描BLE设备
+   * 
+   * @param callback 扫描结果回调,返回BLEDevice
+   */
+  startScan(callback: (device: BLEDevice) => void): Promise<void>;
+  
+  /**
+   * 停止扫描
+   */
+  stopScan(): Promise<void>;
+  
+  /**
+   * 连接设备(自动完成握手和配对)
+   * 
+   * @param device 要连接的设备
+   * @param userId 用户ID(16字节),用于握手认证
+   * @param userType 用户类型(0x01=最高权限, 0x02=车主, 0x03=分享用户),用于握手认证
+   * @param callback 连接结果回调,连接成功表示已完成握手和配对
+   */
+  connect(device: BLEDevice, userId: Uint8Array, userType: number, callback: (response: BLEResponse) => void): Promise<void>;
+  
+  /**
+   * 断开连接
+   */
+  disconnect(): Promise<void>;
+  
+  /**
+   * 是否已连接
+   */
+  isConnected(): Promise<boolean>;
+  
+  // ========== 协议封装功能(高级API,业务模块直接调用) ==========
+  
+  /**
+   * 发送指令
+   * 
+   * @param command BLE指令(包含功能码、指令类型、应用数据)
+   * @param callback 指令响应回调
+   */
+  sendCommand(command: BLECommand, callback: (response: BLEResponse) => void): Promise<void>;
+  
+  /**
+   * 发送应用控制指令(业务模块常用)
+   * 
+   * @param instructionType 指令类型(如:设撤防、上下电、寻车等)
+   * @param data 指令参数数据
+   * @param callback 响应回调
+   */
+  sendAppControlCommand(instructionType: number, data: Uint8Array, callback: (response: BLEResponse) => void): Promise<void>;
+  
+  /**
+   * 发送系统控制指令(业务模块常用)
+   * 
+   * @param instructionType 指令类型(如:感应解锁、氛围灯等)
+   * @param data 指令参数数据
+   * @param callback 响应回调
+   */
+  sendSystemControlCommand(instructionType: number, data: Uint8Array, callback: (response: BLEResponse) => void): Promise<void>;
+  
+  /**
+   * 查询车辆信息
+   * 
+   * @param callback 响应回调,返回车辆信息数据
+   */
+  queryVehicleInfo(callback: (response: BLEResponse) => void): Promise<void>;
+  
+  // ========== 便捷方法(业务层常用操作) ==========
+  
+  /**
+   * 设防/撤防
+   * 
+   * @param enabled true=设防, false=撤防
+   * @param callback 响应回调
+   */
+  setDefense(enabled: boolean, callback: (response: BLEResponse) => void): Promise<void>;
+  
+  /**
+   * 上电
+   * 
+   * @param callback 响应回调
+   */
+  powerOn(callback: (response: BLEResponse) => void): Promise<void>;
+  
+  /**
+   * 下电
+   * 
+   * @param callback 响应回调
+   */
+  powerOff(callback: (response: BLEResponse) => void): Promise<void>;
+  
+  /**
+   * 寻车
+   * 
+   * @param callback 响应回调
+   */
+  findCar(callback: (response: BLEResponse) => void): Promise<void>;
+  
+  /**
+   * 打开座桶锁
+   * 
+   * @param callback 响应回调
+   */
+  unlockSeat(callback: (response: BLEResponse) => void): Promise<void>;
+  
+  /**
+   * 打开龙头锁
+   * 
+   * @param callback 响应回调
+   */
+  unlockHandlebar(callback: (response: BLEResponse) => void): Promise<void>;
+  
+  /**
+   * 关闭龙头锁
+   * 
+   * @param callback 响应回调
+   */
+  lockHandlebar(callback: (response: BLEResponse) => void): Promise<void>;
+  
+  /**
+   * 打开尾箱锁
+   * 
+   * @param callback 响应回调
+   */
+  unlockTrunk(callback: (response: BLEResponse) => void): Promise<void>;
+  
+  /**
+   * 关闭尾箱锁
+   * 
+   * @param callback 响应回调
+   */
+  lockTrunk(callback: (response: BLEResponse) => void): Promise<void>;
+  
+  /**
+   * 设置感应解锁开关
+   * 
+   * @param enabled true=开启, false=关闭
+   * @param callback 响应回调
+   */
+  setSensorUnlock(enabled: boolean, callback: (response: BLEResponse) => void): Promise<void>;
+  
+  /**
+   * 设置氛围灯开关
+   * 
+   * @param enabled true=开启, false=关闭
+   * @param callback 响应回调
+   */
+  setAmbientLight(enabled: boolean, callback: (response: BLEResponse) => void): Promise<void>;
+  
+  /**
+   * 设置氛围灯颜色
+   * 
+   * @param r 红色分量 (0-255)
+   * @param g 绿色分量 (0-255)
+   * @param b 蓝色分量 (0-255)
+   * @param callback 响应回调
+   */
+  setAmbientLightColor(r: number, g: number, b: number, callback: (response: BLEResponse) => void): Promise<void>;
+  
+  /**
+   * 设置自动下电时间
+   * 
+   * @param timeSeconds 时间(秒),范围:0-60000
+   * @param callback 响应回调
+   */
+  setAutoPowerOffTime(timeSeconds: number, callback: (response: BLEResponse) => void): Promise<void>;
+  
+  /**
+   * 设置蓝牙音箱音量
+   * 
+   * @param volume 音量 (0-100)
+   * @param callback 响应回调
+   */
+  setSpeakerVolume(volume: number, callback: (response: BLEResponse) => void): Promise<void>;
+  
+  /**
+   * 设置自动大灯开关
+   * 
+   * @param enabled true=开启, false=关闭
+   * @param callback 响应回调
+   */
+  setAutoHeadlight(enabled: boolean, callback: (response: BLEResponse) => void): Promise<void>;
+  
+  /**
+   * 设置语音播报开关
+   * 
+   * @param enabled true=开启, false=关闭
+   * @param callback 响应回调
+   */
+  setVoiceBroadcast(enabled: boolean, callback: (response: BLEResponse) => void): Promise<void>;
+  
+  /**
+   * 设置伴我回家
+   * 
+   * @param enabled true=开启, false=关闭
+   * @param callback 响应回调
+   */
+  setFollowMeHome(enabled: boolean, callback: (response: BLEResponse) => void): Promise<void>;
+  
+  /**
+   * 设置ABS(制动防抱死系统)
+   * 
+   * @param enabled true=开启, false=关闭
+   * @param callback 响应回调
+   */
+  setAbs(enabled: boolean, callback: (response: BLEResponse) => void): Promise<void>;
+  
+  /**
+   * 设置TCS(牵引力控制系统)
+   * 
+   * @param enabled true=开启, false=关闭
+   * @param callback 响应回调
+   */
+  setTcs(enabled: boolean, callback: (response: BLEResponse) => void): Promise<void>;
+  
+  // ========== 数据接收监听 ==========
+  
+  /**
+   * 设置数据接收监听器
+   * 
+   * @param listener 接收到的数据回调
+   */
+  setDataReceivedListener(listener: (data: Uint8Array) => void): void;
+  
+  // ========== 底层功能(如果需要直接操作) ==========
+  
+  /**
+   * 发送原始数据(底层API,不推荐业务模块直接使用)
+   * 
+   * @param data 原始数据(二进制)
+   * @param callback 响应回调
+   */
+  writeRawData(data: Uint8Array, callback: (response: BLEResponse) => void): Promise<void>;
+}
+

+ 20 - 0
capability-ble/src/main/ets/ble/factory/BLEServiceFactory.ets

@@ -0,0 +1,20 @@
+import { BLEService } from '../api/BLEService';
+import { BLEServiceImpl } from '../impl/BLEServiceImpl';
+
+/**
+ * BLE服务工厂类
+ * 
+ * 提供统一的获取BLE服务实例的方式
+ * BLE服务是全局单例,多个界面共享同一个服务实例
+ */
+export class BLEServiceFactory {
+  /**
+   * 获取BLE服务实例(单例)
+   * 
+   * @returns BLEService实例(单例)
+   */
+  static getInstance(): BLEService {
+    return BLEServiceImpl.getInstance();
+  }
+}
+

File diff suppressed because it is too large
+ 1218 - 0
capability-ble/src/main/ets/ble/impl/BLEServiceImpl.ets


+ 67 - 0
capability-ble/src/main/ets/ble/model/BLECommand.ets

@@ -0,0 +1,67 @@
+/**
+ * BLE指令模型
+ * 
+ * 封装业务层需要发送的指令
+ */
+export class BLECommand {
+  /**
+   * 功能码
+   * 0x01=握手, 0x02=应用控制, 0x03=系统控制, 0x04=系统查询, 0x05=系统设置
+   */
+  functionCode: number;
+  
+  /**
+   * 指令类型
+   */
+  instructionType: number;
+  
+  /**
+   * 应用数据
+   */
+  applicationData: Uint8Array;
+  
+  constructor(functionCode: number, instructionType: number, applicationData: Uint8Array) {
+    this.functionCode = functionCode;
+    this.instructionType = instructionType;
+    this.applicationData = applicationData;
+  }
+}
+
+/**
+ * 应用控制指令类型
+ */
+export class AppControlInstruction {
+  static readonly SET_DEFENSE = 0x01;      // 设撤防
+  static readonly POWER_ON_OFF = 0x02;     // 上下电
+  static readonly FIND_CAR = 0x03;         // 寻车
+  static readonly SEAT_LOCK = 0x04;        // 座桶锁
+  static readonly HANDLEBAR_LOCK = 0x05;   // 龙头锁
+  static readonly TRUNK_LOCK = 0x06;       // 尾箱锁
+}
+
+/**
+ * 系统控制指令类型
+ */
+export class SystemControlInstruction {
+  static readonly SENSOR_UNLOCK = 0x01;           // 感应解锁开关
+  static readonly RSSI_COLLECTION = 0x02;         // RSSI信号强度采集
+  static readonly REMOVE_SHARE_USER = 0x03;       // 删除分享用户
+  static readonly STOLEN_LOCK = 0x04;             // 被盗锁定开关
+  static readonly SEAT_SENSOR = 0x05;             // 座椅感应开关
+  static readonly SOUND_EFFECT = 0x06;            // 车辆音效开关
+  static readonly AUTO_HEADLIGHT = 0x07;          // 自动大灯开关
+  static readonly AUTO_POWER_OFF_TIME = 0x08;     // 自动下电时间
+  static readonly AUTO_DEFENSE_TIME = 0x09;       // 自动设防时间
+  static readonly AMBIENT_LIGHT = 0x10;           // 氛围灯开关
+  static readonly AMBIENT_LIGHT_COLOR = 0x11;     // 氛围灯颜色
+  static readonly RESET_MILEAGE = 0x12;            // 小计里程清零
+  static readonly VOICE_BROADCAST = 0x13;          // 语音播报开关
+  static readonly WALK_ME_HOME = 0x14;            // 伴我回家
+  static readonly SPEAKER_VOLUME = 0x15;          // 蓝牙音箱
+  static readonly DELAYED_CHARGING = 0x16;         // 延时充电时间
+  static readonly LOW_BATTERY_ALARM = 0x1F;       // 低电量报警阈值
+  static readonly ENTER_P_TIME = 0x20;            // 进入P档时间
+  static readonly ABS = 0x21;                     // ABS
+  static readonly TCS = 0x22;                     // TCS
+}
+

+ 32 - 0
capability-ble/src/main/ets/ble/model/BLEDevice.ets

@@ -0,0 +1,32 @@
+/**
+ * BLE设备模型
+ */
+export class BLEDevice {
+  /**
+   * 设备名称
+   */
+  name: string;
+  
+  /**
+   * 设备地址(MAC地址)
+   */
+  address: string;
+  
+  /**
+   * 信号强度(RSSI)
+   */
+  rssi: number;
+  
+  /**
+   * 是否已连接
+   */
+  connected: boolean;
+  
+  constructor(name: string, address: string, rssi: number, connected: boolean = false) {
+    this.name = name;
+    this.address = address;
+    this.rssi = rssi;
+    this.connected = connected;
+  }
+}
+

+ 45 - 0
capability-ble/src/main/ets/ble/model/BLEEncryptedData.ets

@@ -0,0 +1,45 @@
+/**
+ * 数据加密区内容
+ * 
+ * 按照协议文档,数据加密区包含:
+ * - 时间戳(4字节)
+ * - 功能码(1字节)
+ * - 指令类型(1字节)
+ * - 应用数据(N字节)
+ */
+export class BLEEncryptedData {
+  /**
+   * 时间戳(秒级)
+   */
+  timestamp: number;
+  
+  /**
+   * 功能码
+   * 0x01=握手, 0x02=应用控制, 0x03=系统控制, 0x04=系统查询, 0x05=系统设置, 0x06=MTU查询
+   */
+  functionCode: number;
+  
+  /**
+   * 指令类型
+   * 根据功能码不同,指令类型含义不同
+   */
+  instructionType: number;
+  
+  /**
+   * 应用数据
+   */
+  applicationData: Uint8Array;
+  
+  constructor(
+    timestamp: number,
+    functionCode: number,
+    instructionType: number,
+    applicationData: Uint8Array
+  ) {
+    this.timestamp = timestamp;
+    this.functionCode = functionCode;
+    this.instructionType = instructionType;
+    this.applicationData = applicationData;
+  }
+}
+

+ 60 - 0
capability-ble/src/main/ets/ble/model/BLEResponse.ets

@@ -0,0 +1,60 @@
+/**
+ * BLE响应模型(统一结构)
+ * 
+ * 遵循统一设计:success, data, errorCode, errorMessage, timestamp
+ */
+export class BLEResponse {
+  /**
+   * 是否成功
+   */
+  success: boolean;
+  
+  /**
+   * 响应数据(二进制数据)
+   */
+  data: Uint8Array | null;
+  
+  /**
+   * 错误码(如果有错误)
+   */
+  errorCode: number | null;
+  
+  /**
+   * 错误消息(如果有错误)
+   */
+  errorMessage: string | null;
+  
+  /**
+   * 时间戳
+   */
+  timestamp: number;
+  
+  constructor(
+    success: boolean,
+    data: Uint8Array | null = null,
+    errorCode: number | null = null,
+    errorMessage: string | null = null,
+    timestamp: number = Date.now()
+  ) {
+    this.success = success;
+    this.data = data;
+    this.errorCode = errorCode;
+    this.errorMessage = errorMessage;
+    this.timestamp = timestamp;
+  }
+  
+  /**
+   * 创建成功响应
+   */
+  static success(data: Uint8Array): BLEResponse {
+    return new BLEResponse(true, data);
+  }
+  
+  /**
+   * 创建失败响应
+   */
+  static failure(errorCode: number, errorMessage: string): BLEResponse {
+    return new BLEResponse(false, null, errorCode, errorMessage);
+  }
+}
+

+ 67 - 0
capability-ble/src/main/ets/ble/model/Command.ets

@@ -0,0 +1,67 @@
+/**
+ * 指令数据包模型
+ * 
+ * 解析后的指令数据包结构
+ */
+export class Command {
+  /**
+   * 地址
+   */
+  address: number;
+  
+  /**
+   * 协议版本
+   */
+  protocolVersion: number;
+  
+  /**
+   * 时区
+   */
+  timezone: number;
+  
+  /**
+   * 加密标志
+   */
+  encryptionFlag: number;
+  
+  /**
+   * 操作系统
+   */
+  operatingSystem: number;
+  
+  /**
+   * 数据长度
+   */
+  dataLength: number;
+  
+  /**
+   * 数据区
+   */
+  data: Uint8Array;
+  
+  /**
+   * 校验位
+   */
+  checksum: number;
+  
+  constructor(
+    address: number,
+    protocolVersion: number,
+    timezone: number,
+    encryptionFlag: number,
+    operatingSystem: number,
+    dataLength: number,
+    data: Uint8Array,
+    checksum: number
+  ) {
+    this.address = address;
+    this.protocolVersion = protocolVersion;
+    this.timezone = timezone;
+    this.encryptionFlag = encryptionFlag;
+    this.operatingSystem = operatingSystem;
+    this.dataLength = dataLength;
+    this.data = data;
+    this.checksum = checksum;
+  }
+}
+

+ 0 - 0
capability-ble/src/main/ets/ble/model/FragmentBuffer.ets


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