@ohos-cpf/3rdloop 0.0.3 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/README.md +124 -87
  2. package/lib/cli.js +25 -0
  3. package/lib/config-cmd.js +1 -1
  4. package/lib/serve.js +268 -0
  5. package/lib/update.js +46 -6
  6. package/lib/web-ext.js +454 -0
  7. package/lib/web.js +664 -0
  8. package/package.json +2 -1
  9. package/vendor/Server/Agent/SkillSelector/README.md +11 -11
  10. package/vendor/Server/Agent/SkillSelector/llm/llmClient.js +3 -3
  11. package/vendor/Server/Skills/arkts-code-use/SKILL.md +270 -0
  12. package/vendor/Server/Skills/arkts-code-use/assets/TEMPLATES.md +367 -0
  13. package/vendor/Server/Skills/arkts-code-use/references/API_VERIFICATION.md +144 -0
  14. package/vendor/Server/Skills/arkts-code-use/references/ARKTS_RULES.md +240 -0
  15. package/vendor/Server/Skills/arkts-code-use/references/CODE_PATTERNS.md +431 -0
  16. package/vendor/Server/Skills/arkts-code-use/references/SYNTAX_CHECK_GUIDE.md +164 -0
  17. package/vendor/Server/Skills/arkts-code-use/scripts/verify-arkts.cjs +428 -0
  18. package/vendor/Server/Skills/gitcode-repo-fork/SKILL.md +310 -0
  19. package/vendor/Server/Skills/gitcode-repo-fork/assets/FORK_REPORT_TEMPLATE.md +113 -0
  20. package/vendor/Server/Skills/gitcode-repo-fork/references/FORK_DECISION_GUIDE.md +124 -0
  21. package/vendor/Server/Skills/gitcode-repo-fork/references/GITCODE_FORK_API.md +95 -0
  22. package/vendor/Server/Skills/gitcode-repo-fork/scripts/gitcode-fork.cjs +285 -0
  23. package/vendor/VERSION +3 -3
  24. package/web/css/arktslibrarycheck.css +322 -0
  25. package/web/css/codecheck.css +464 -0
  26. package/web/css/flutterlibrarycheck.css +322 -0
  27. package/web/css/knowledge.css +332 -0
  28. package/web/css/loop.css +578 -0
  29. package/web/css/md-reader.css +240 -0
  30. package/web/css/rnlibrarycheck.css +322 -0
  31. package/web/css/theme.css +702 -0
  32. package/web/index.html +713 -0
  33. package/web/js/arktslibrarycheck.js +1413 -0
  34. package/web/js/codecheck.js +1039 -0
  35. package/web/js/flutterlibrarycheck.js +1364 -0
  36. package/web/js/health.js +69 -0
  37. package/web/js/knowledge.js +358 -0
  38. package/web/js/loop.js +1102 -0
  39. package/web/js/md-reader.js +435 -0
  40. package/web/js/navigation.js +238 -0
  41. package/web/js/rnlibrarycheck.js +1378 -0
  42. package/web/js/stats.js +110 -0
  43. package/web/js/theme.js +46 -0
  44. package/web/js/utils.js +228 -0
  45. package/web/knowledge.html +146 -0
  46. package/web/loop.html +219 -0
@@ -0,0 +1,240 @@
1
+ # ArkTS 规范与约束速查
2
+
3
+ > ArkTS 是 TypeScript 的扩展集,在 TS 基础上施加了更严格的静态类型约束(强制静态类型、禁止运行时改变对象布局),以获得更好的运行性能。本文档汇总编码时必须遵守的约束,**违反即编译报错**。
4
+
5
+ ---
6
+
7
+ ## 一、禁止项清单(编译必查)
8
+
9
+ 以下是 ArkTS 严格模式下最常见的编译阻断项,生成代码必须全部规避:
10
+
11
+ | # | 禁止项 | 错误码/规则 | 正确替代方式 |
12
+ |---|--------|------------|------------|
13
+ | 1 | `any` / `unknown` 类型 | `arkts-no-any-unknown` | 使用具体类型或泛型 `T` |
14
+ | 2 | `ESObject` / `Object` 通用类型 | `arkts-no-esobj` | 使用 `interface` 或具体类型 |
15
+ | 3 | 动态属性访问 `obj['key']` | `arkts-no-dynamic-property` | `obj.key` 类型安全访问 |
16
+ | 4 | 未类型化对象字面量 `let o = {}` | `arkts-no-untyped-obj-literals` | 先声明 class/interface 再赋值 |
17
+ | 5 | 内联匿名对象类型参数 | `arkts-no-obj-literals-as-types` | 定义命名 `interface` |
18
+ | 6 | `prototype` 扩展 | `arkts-no-prototype-assignment` | 类继承或组合 |
19
+ | 7 | `delete` 操作符 | `arkts-no-delete` | 将属性设为 `undefined` 或重构数据结构 |
20
+ | 8 | `arguments` 对象 | `arkts-no-arguments` | 使用展开参数 `...args: T[]` |
21
+ | 9 | 双重类型转换 `as unknown as T` | `arkts-no-unsafe-cast` | 定义正确的类型,单次合法转型 |
22
+ | 10 | `for...in` 遍历 | `arkts-no-for-in` | `Object.keys()` + `for...of` / `forEach` |
23
+ | 11 | `eval()` / `new Function()` | `arkts-no-eval` | 禁止使用,无合法替代 |
24
+ | 12 | catch 块直接 `throw e` | `arkts-limited-throw` | `throw e instanceof Error ? e : new Error(String(e))` |
25
+ | 13 | 结构型类型(鸭子类型)匹配 | `arkts-no-structural-typing` | 显式 `extends` / `implements` |
26
+ | 14 | 函数类型不一致赋值 | `arkts-strict-function-types` | 参数/返回值类型完全一致 |
27
+ | 15 | 泛型函数非箭头定义 | `arkts-no-functional-constructors` | 使用 `function` 声明或箭头函数 |
28
+ | 16 | `Object.assign` 修改对象布局 | `arkts-no-object-assign` | 逐属性赋值(类型已声明) |
29
+ | 17 | 运行时修改 class 布局 | `arkts-no-runtime-change-layout` | 类型声明保持静态 |
30
+ | 18 | `Symbol()` API | `arkts-no-symbol` | 不使用 Symbol |
31
+ | 19 | `as any` / 类型断言到 any | `arkts-no-any` | 明确的目标类型断言 |
32
+ | 20 | `void` 返回值以外使用 `undefined` 检查歧义 | — | 显式 `T \| undefined` |
33
+
34
+ > 完整规则见官方文档 [从 TypeScript 到 ArkTS 的适配规则](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/typescript-to-arkts-migration-guide)。
35
+
36
+ ---
37
+
38
+ ## 二、高频错误正误对照
39
+
40
+ ### 2.1 类型安全(规则 1/2/4/5)
41
+
42
+ ```typescript
43
+ // ❌ 错误:any + 未类型化字面量
44
+ function parse(json: string): any {
45
+ return JSON.parse(json);
46
+ }
47
+ let config = { timeout: 5000, retries: 3 };
48
+
49
+ // ✅ 正确:显式类型
50
+ interface Config {
51
+ timeout: number;
52
+ retries: number;
53
+ }
54
+ function parseConfig(json: string): Config {
55
+ return JSON.parse(json) as Config; // 单次断言到具体类型是允许的
56
+ }
57
+ const config: Config = { timeout: 5000, retries: 3 };
58
+ ```
59
+
60
+ ### 2.2 catch 重抛(规则 12,最高频报错之一)
61
+
62
+ ```typescript
63
+ // ❌ 错误:e 为 unknown,直接 throw 违反 arkts-limited-throw
64
+ try {
65
+ await doWork();
66
+ } catch (e) {
67
+ throw e;
68
+ }
69
+
70
+ // ✅ 正确:确保抛出 Error 实例
71
+ try {
72
+ await doWork();
73
+ } catch (e) {
74
+ throw e instanceof Error ? e : new Error(String(e));
75
+ }
76
+ ```
77
+
78
+ ### 2.3 对象字面量必须对应显式类型(规则 4/5)
79
+
80
+ ```typescript
81
+ // ❌ 错误:内联匿名类型 + 裸字面量
82
+ function fetchData(url: string, cb: (resp: { code: number }) => void): void {}
83
+ let resp = { code: 200 };
84
+
85
+ // ✅ 正确:命名 interface
86
+ interface Response {
87
+ code: number;
88
+ }
89
+ function fetchData(url: string, cb: (resp: Response) => void): void {}
90
+ const resp: Response = { code: 200 };
91
+ ```
92
+
93
+ ### 2.4 结构型类型禁用(规则 13)
94
+
95
+ ```typescript
96
+ // ❌ 错误:鸭子类型赋值(字段相同也不能赋值)
97
+ interface A { x: number }
98
+ class B { x: number = 1 }
99
+ const a: A = new B(); // 编译报错 arkts-no-structural-typing
100
+
101
+ // ✅ 正确:显式实现
102
+ class C implements A { x: number = 1 }
103
+ const a2: A = new C();
104
+ ```
105
+
106
+ ### 2.5 遍历(规则 10)
107
+
108
+ ```typescript
109
+ // ❌ 错误
110
+ for (const key in obj) { console.log(key); }
111
+
112
+ // ✅ 正确
113
+ const keys: string[] = Object.keys(obj);
114
+ for (const key of keys) {
115
+ console.log(key);
116
+ }
117
+ ```
118
+
119
+ ---
120
+
121
+ ## 三、类型系统约束
122
+
123
+ | 约束 | 说明 |
124
+ |------|------|
125
+ | 显式类型标注 | 所有变量、参数、返回值建议显式标注;字面量初始化可省略 |
126
+ | 联合类型 | `string \| null` 合法;禁止用 `any` 模拟联合 |
127
+ | 泛型 | 完整支持;优先泛型而非 any/Object 传参 |
128
+ | 字面量联合 | `mode: 'sync' \| 'async'` 合法,简单场景优先于枚举 |
129
+ | 可选属性 | `timeout?: number` 合法;访问时用 `?.` 或显式判空 |
130
+ | Record 类型 | `Record<string, string>` 用于键值对场景 |
131
+ | 函数类型 | 箭头函数与 function 声明均可;回调参数类型必须显式 |
132
+
133
+ ---
134
+
135
+ ## 四、命名与格式规范(华为 ArkTS 编程规范)
136
+
137
+ ### 4.1 命名约定
138
+
139
+ | 元素 | 风格 | 示例 |
140
+ |------|------|------|
141
+ | 类 / 接口 / 枚举 / struct / 装饰器类 | PascalCase | `HttpClient`、`RetryPolicy`、`LoadState` |
142
+ | 方法 / 变量 / 参数 | camelCase | `sendRequest`、`maxRetries` |
143
+ | 常量 | UPPER_SNAKE_CASE | `const MAX_SIZE: number = 1024` |
144
+ | 枚举成员 | UPPER_SNAKE_CASE 或 PascalCase(全工程统一) | `enum Status { IDLE, RUNNING }` |
145
+ | 布尔变量/方法 | is/has/can 前缀 | `isValid`、`hasData` |
146
+ | 私有成员 | `private` 修饰符(不加 `_` 前缀) | `private count: number` |
147
+ | 文件名 | PascalCase.ets | `HttpClient.ets`、`Index.ets` |
148
+
149
+ ### 4.2 代码格式
150
+
151
+ - 缩进 **2 空格**,禁止 Tab
152
+ - 语句行尾**分号**(`.ets` 源文件中必写)
153
+ - 单行长度建议 ≤ 120 字符
154
+ - 单文件 ≤ 400 行,超出按职责拆分
155
+ - import 顺序:`@ohos.*` / `@kit.*` → 第三方库 → 相对路径模块
156
+
157
+ ### 4.3 注释规范
158
+
159
+ - 公共接口必须有 JSDoc:功能、`@param`、`@returns`
160
+ - 复杂逻辑块行内注释说明"为什么"而非"是什么"
161
+ - 禁止提交注释掉的死代码
162
+
163
+ ```typescript
164
+ /**
165
+ * 重试策略配置
166
+ */
167
+ export interface RetryPolicy {
168
+ /** 最大重试次数,默认 3 */
169
+ maxRetries: number;
170
+ /** 重试间隔基数(毫秒),按指数退避递增 */
171
+ baseIntervalMs: number;
172
+ }
173
+
174
+ /**
175
+ * 按指数退避执行重试
176
+ * @param fn - 要执行的异步操作
177
+ * @param policy - 重试策略
178
+ * @returns 操作结果
179
+ */
180
+ async function withRetry<T>(fn: () => Promise<T>, policy: RetryPolicy): Promise<T> {
181
+ // ...实现
182
+ }
183
+ ```
184
+
185
+ ---
186
+
187
+ ## 五、日志规范
188
+
189
+ ### 5.1 初始化
190
+
191
+ ```typescript
192
+ import hilog from '@ohos.hilog';
193
+
194
+ // 域值 0x0000~0xFFFF,按模块分配
195
+ const DOMAIN: number = 0x0001;
196
+ // 标签 ≤ 31 字符,格式:模块名_功能名
197
+ const TAG: string = 'MyApp_HttpClient';
198
+ ```
199
+
200
+ ### 5.2 级别使用
201
+
202
+ | 级别 | 场景 |
203
+ |------|------|
204
+ | `debug` | 方法进出、中间状态(禁止用于高频循环) |
205
+ | `info` | 关键流程节点、状态变更、操作成功 |
206
+ | `warn` | 可恢复异常、参数降级处理 |
207
+ | `error` | 操作失败、异常捕获 |
208
+
209
+ ### 5.3 隐私保护(强制)
210
+
211
+ ```typescript
212
+ // ✅ 敏感数据使用 %{private}s
213
+ hilog.info(DOMAIN, TAG, 'login, account: %{private}s', account);
214
+
215
+ // ❌ 禁止密码/Token/手机号使用 %{public}s
216
+ ```
217
+
218
+ ---
219
+
220
+ ## 六、ArkUI 声明式 UI 约束
221
+
222
+ | 约束 | 说明 |
223
+ |------|------|
224
+ | 状态变量必须加装饰器 | `@State` / `@Prop` / `@Link` / `@Provide` / `@Consume` 等 |
225
+ | 组件内状态修改触发刷新 | 只能通过状态变量驱动 UI,禁止命令式操作 |
226
+ | build() 内禁止修改状态 | 只做声明;状态修改放事件回调和生命周期 |
227
+ | 尺寸单位 | 布局用 `vp`、字体用 `fp`,禁止硬编码 px 假设 |
228
+ | 资源引用 | `$r('app.string.xxx')`;string 避免硬编码 |
229
+ | 条件渲染 | `if/else` 分支中组件结构须完整闭合 |
230
+ | 列表性能 | 大数据量列表用 `LazyForEach` + `IDataSource` |
231
+
232
+ ---
233
+
234
+ ## 七、依赖与导入约束
235
+
236
+ - `@ohos.*` 模块导入:`import http from '@ohos.net.http';`
237
+ - Kit 聚合导入(优先):`import { http } from '@kit.NetworkKit';`
238
+ - 相对导入必须带文件名(无扩展名):`import { Config } from './Config';`
239
+ - import 路径大小写敏感(macOS 不敏感、构建机 Linux 敏感,必须按实际文件名大小写书写)
240
+ - 三方依赖通过 `oh-package.json5` 声明,`ohpm install` 安装,禁止直接引用未声明依赖
@@ -0,0 +1,431 @@
1
+ # ArkTS 代码模式
2
+
3
+ > 编写鸿蒙原生 ArkTS 代码时的标准实现模式:异步编程、并发、错误处理、事件、权限、资源生命周期、UI 状态管理。所有模式均已通过 ArkTS 严格模式编译验证。
4
+
5
+ ---
6
+
7
+ ## 一、异步编程模式
8
+
9
+ ### 1.1 Promise + async/await(默认选择)
10
+
11
+ ```typescript
12
+ import fs from '@ohos.file.fs';
13
+ import hilog from '@ohos.hilog';
14
+
15
+ const DOMAIN: number = 0x0001;
16
+ const TAG: string = 'MyApp_Async';
17
+
18
+ /** 将回调式 API 封装为 Promise */
19
+ function readTextAsync(filePath: string): Promise<string> {
20
+ return new Promise<string>((resolve: (value: string) => void,
21
+ reject: (reason: Error) => void) => {
22
+ fs.readText(filePath, (err: Error, data: string) => {
23
+ if (err) {
24
+ reject(err instanceof Error ? err : new Error(String(err)));
25
+ return;
26
+ }
27
+ resolve(data);
28
+ });
29
+ });
30
+ }
31
+
32
+ /** 调用方:async/await + try/catch/finally */
33
+ async function processFile(filePath: string): Promise<string> {
34
+ try {
35
+ const content: string = await readTextAsync(filePath);
36
+ hilog.info(DOMAIN, TAG, 'read ok, length=%{public}d', content.length);
37
+ return content;
38
+ } catch (e) {
39
+ hilog.error(DOMAIN, TAG, 'read failed: %{public}s', (e as Error).message);
40
+ throw e instanceof Error ? e : new Error(String(e));
41
+ }
42
+ }
43
+ ```
44
+
45
+ ### 1.2 超时控制(Promise.race)
46
+
47
+ ```typescript
48
+ function withTimeout<T>(task: Promise<T>, timeoutMs: number): Promise<T> {
49
+ const timer: Promise<never> = new Promise<never>(
50
+ (_resolve: (value: never) => void, reject: (reason: Error) => void) => {
51
+ setTimeout(() => {
52
+ reject(new Error(`timeout after ${timeoutMs}ms`));
53
+ }, timeoutMs);
54
+ });
55
+ return Promise.race<T>([task, timer]);
56
+ }
57
+ ```
58
+
59
+ ---
60
+
61
+ ## 二、并发模式(taskpool / worker)
62
+
63
+ > 阻塞 IO、大量计算禁止在主线程执行。优先 taskpool(轻量任务池),长生命周期后台线程用 worker。
64
+
65
+ ### 2.1 taskpool 耗时计算
66
+
67
+ ```typescript
68
+ import taskpool from '@ohos.taskpool';
69
+
70
+ // @Concurrent 函数必须是独立函数,不能捕获外部变量(可序列化参数传入)
71
+ @Concurrent
72
+ function computeChecksum(input: number[]): number {
73
+ let sum: number = 0;
74
+ for (const value of input) {
75
+ sum += value * 31;
76
+ }
77
+ return sum;
78
+ }
79
+
80
+ async function runInBackground(input: number[]): Promise<number> {
81
+ const task: taskpool.Task = new taskpool.Task(computeChecksum, input);
82
+ return await taskpool.execute(task) as number;
83
+ }
84
+ ```
85
+
86
+ ### 2.2 worker 生命周期(必须 terminate)
87
+
88
+ ```typescript
89
+ import worker from '@ohos.worker';
90
+
91
+ class WorkerHost {
92
+ private threadWorker: worker.ThreadWorker | null = null;
93
+
94
+ start(): void {
95
+ // 脚本路径相对模块 src/main/ets
96
+ this.threadWorker = new worker.ThreadWorker('entry/ets/workers/MyWorker.ets');
97
+ this.threadWorker.onmessage = (event: MessageEvents): void => {
98
+ // 处理子线程结果
99
+ };
100
+ this.threadWorker.postMessage({ type: 'start' });
101
+ }
102
+
103
+ /** 必须在确定生命周期节点调用,防止线程泄露 */
104
+ stop(): void {
105
+ if (this.threadWorker !== null) {
106
+ this.threadWorker.terminate();
107
+ this.threadWorker = null;
108
+ }
109
+ }
110
+ }
111
+ ```
112
+
113
+ ---
114
+
115
+ ## 三、错误处理模式
116
+
117
+ ### 3.1 BusinessError(系统 API 标准错误)
118
+
119
+ ```typescript
120
+ import { BusinessError } from '@ohos.base';
121
+
122
+ async function callSystemApi(): Promise<void> {
123
+ try {
124
+ // await someSystemApi();
125
+ } catch (error) {
126
+ // 系统 API 错误统一转型为 BusinessError 读取 code
127
+ const err: BusinessError = error as BusinessError;
128
+ hilog.error(0x0001, 'MyApp', 'code=%{public}d, msg=%{public}s', err.code, err.message);
129
+ throw err instanceof Error ? err : new Error(String(err));
130
+ }
131
+ }
132
+ ```
133
+
134
+ ### 3.2 参数防御性校验
135
+
136
+ ```typescript
137
+ class ValidationError extends Error {
138
+ constructor(message: string) {
139
+ super(message);
140
+ this.name = 'ValidationError';
141
+ }
142
+ }
143
+
144
+ function validateInput(value: string | null | undefined, fieldName: string,
145
+ maxLen: number = 256): string {
146
+ if (value === null || value === undefined || value.length === 0) {
147
+ throw new ValidationError(`${fieldName} must not be empty`);
148
+ }
149
+ if (value.length > maxLen) {
150
+ throw new ValidationError(`${fieldName} exceeds max length ${maxLen}`);
151
+ }
152
+ return value;
153
+ }
154
+ ```
155
+
156
+ ### 3.3 统一 Result 类型(避免异常控制流蔓延)
157
+
158
+ ```typescript
159
+ export interface Result<T> {
160
+ success: boolean;
161
+ value?: T;
162
+ error?: string;
163
+ }
164
+
165
+ export class Ok<T> implements Result<T> {
166
+ success: boolean = true;
167
+ constructor(public value: T) {}
168
+ }
169
+
170
+ export class Fail<T> implements Result<T> {
171
+ success: boolean = false;
172
+ constructor(public error: string) {}
173
+ }
174
+ ```
175
+
176
+ ---
177
+
178
+ ## 四、事件模式(emitter)
179
+
180
+ ```typescript
181
+ import emitter from '@ohos.events.emitter';
182
+
183
+ // 事件常量集中定义
184
+ export const enum AppEvent {
185
+ DATA_UPDATED = 1001,
186
+ SYNC_FAILED = 1002,
187
+ }
188
+
189
+ class EventBus {
190
+ private static subscriptionCount: number = 0;
191
+
192
+ static subscribe(eventId: number, callback: (data: emitter.EventData) => void): void {
193
+ emitter.on({ eventId: eventId }, callback);
194
+ EventBus.subscriptionCount += 1;
195
+ }
196
+
197
+ static emit(eventId: number, data: Record<string, Object>): void {
198
+ emitter.emit({ eventId: eventId }, { data: data });
199
+ }
200
+
201
+ /** 取消订阅必须与 on 配对 */
202
+ static unsubscribe(eventId: number): void {
203
+ emitter.off(eventId);
204
+ }
205
+ }
206
+ ```
207
+
208
+ ---
209
+
210
+ ## 五、权限申请模式
211
+
212
+ ```typescript
213
+ import abilityAccessCtrl, { Permissions } from '@ohos.abilityAccessCtrl';
214
+ import { common } from '@kit.AbilityKit';
215
+
216
+ async function requestPermissions(context: common.UIAbilityContext,
217
+ permissions: Permissions[]): Promise<boolean> {
218
+ const atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
219
+ const result: abilityAccessCtrl.PermissionRequestResult =
220
+ await atManager.requestPermissionsFromUser(context, permissions);
221
+ return result.authResults.every((status: number) =>
222
+ status === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED);
223
+ }
224
+ ```
225
+
226
+ > normal 级权限仅声明即生效;user_grant 级权限须声明 + 运行时申请两步缺一不可。
227
+
228
+ ---
229
+
230
+ ## 六、资源生命周期管理(防泄露)
231
+
232
+ > **规则**:凡是 `create/open/on/connect` 获取的资源,必须存在对称的 `destroy/close/off/disconnect` 释放路径,置于 `try/finally` 或组件销毁回调中。
233
+
234
+ | 资源 | 获取 | 释放 | 位置 |
235
+ |------|------|------|------|
236
+ | HTTP 连接 | `http.createHttp()` | `httpRequest.destroy()` | `try/finally` |
237
+ | 文件句柄 | `fs.openSync()` | `fs.closeSync(fd)` | `try/finally` |
238
+ | RDB 存储 | `getRdbStore()` | `close()` | 模块卸载 |
239
+ | Worker | `new ThreadWorker()` | `terminate()` | 任务完成/销毁 |
240
+ | Timer | `setInterval()` | `clearInterval(id)` | `aboutToDisappear` |
241
+ | emitter 订阅 | `emitter.on()` | `emitter.off(id)` | `aboutToDisappear` |
242
+ | 传感器 | `sensor.on()` | `sensor.off(type)` | 页面隐藏/销毁 |
243
+ | AVPlayer | `createAVPlayer()` | `release()` | 播放结束/销毁 |
244
+
245
+ ### 6.1 HTTP 请求标准范式(最常见泄露点)
246
+
247
+ ```typescript
248
+ import { http } from '@kit.NetworkKit';
249
+
250
+ const MAX_RESPONSE_BYTES: number = 5 * 1024 * 1024;
251
+
252
+ async function httpGet(url: string): Promise<string> {
253
+ const httpRequest: http.HttpRequest = http.createHttp();
254
+ try {
255
+ const response: http.HttpResponse = await httpRequest.request(url, {
256
+ method: http.RequestMethod.GET,
257
+ connectTimeout: 10_000,
258
+ readTimeout: 15_000,
259
+ expectMaxDuration: 20_000,
260
+ });
261
+ if (typeof response.result !== 'string') {
262
+ throw new Error('unexpected response type');
263
+ }
264
+ if (response.result.length > MAX_RESPONSE_BYTES) {
265
+ throw new Error(`response too large: ${response.result.length}`);
266
+ }
267
+ return response.result;
268
+ } finally {
269
+ // ✅ 成功失败均释放
270
+ httpRequest.destroy();
271
+ }
272
+ }
273
+ ```
274
+
275
+ ### 6.2 文件读写标准范式
276
+
277
+ ```typescript
278
+ import fs from '@ohos.file.fs';
279
+
280
+ function readFileSafely(filePath: string): string {
281
+ let fd: number = -1;
282
+ try {
283
+ const file: fs.File = fs.openSync(filePath, fs.OpenMode.READ_ONLY);
284
+ fd = file.fd;
285
+ const stat: fs.Stat = fs.statSync(filePath);
286
+ const buffer: ArrayBuffer = new ArrayBuffer(stat.size);
287
+ fs.readSync(fd, buffer);
288
+ return String.fromCharCode(...new Uint8Array(buffer));
289
+ } finally {
290
+ if (fd >= 0) {
291
+ fs.closeSync(fd);
292
+ }
293
+ }
294
+ }
295
+ ```
296
+
297
+ ### 6.3 组件内订阅/Timer 清理
298
+
299
+ ```typescript
300
+ @Component
301
+ struct PollingComponent {
302
+ @State message: string = '';
303
+ private timerId: number = -1;
304
+
305
+ aboutToAppear(): void {
306
+ this.timerId = setInterval(() => {
307
+ this.message = `tick ${Date.now()}`;
308
+ }, 1000);
309
+ }
310
+
311
+ aboutToDisappear(): void {
312
+ if (this.timerId >= 0) {
313
+ clearInterval(this.timerId);
314
+ this.timerId = -1;
315
+ }
316
+ }
317
+
318
+ build() {
319
+ Text(this.message)
320
+ }
321
+ }
322
+ ```
323
+
324
+ ---
325
+
326
+ ## 七、UI 状态管理模式
327
+
328
+ ### 7.1 父子组件通信
329
+
330
+ ```typescript
331
+ // 子组件:单向输入 @Prop,双向绑定 @Link
332
+ @Component
333
+ struct CounterCard {
334
+ @Prop title: string = '';
335
+ @Link count: number;
336
+
337
+ build() {
338
+ Column({ space: 8 }) {
339
+ Text(this.title)
340
+ .fontSize(16)
341
+ Text(`count: ${this.count}`)
342
+ .fontSize(20)
343
+ Button('+1')
344
+ .onClick(() => {
345
+ this.count += 1;
346
+ })
347
+ }
348
+ .padding(12)
349
+ }
350
+ }
351
+
352
+ @Entry
353
+ @Component
354
+ struct Index {
355
+ @State count: number = 0;
356
+
357
+ build() {
358
+ Column({ space: 12 }) {
359
+ CounterCard({ title: 'demo', count: $count }) // @Link 用 $ 传引用
360
+ }
361
+ }
362
+ }
363
+ ```
364
+
365
+ ### 7.2 @Provide/@Consume 跨层级
366
+
367
+ ```typescript
368
+ // 祖先组件
369
+ @Entry
370
+ @Component
371
+ struct GrandParent {
372
+ @Provide themeColor: string = '#007DFF';
373
+
374
+ build() { /* 包含后代组件 */ }
375
+ }
376
+
377
+ // 任意后代组件(无需逐层传递)
378
+ @Component
379
+ struct DeepChild {
380
+ @Consume themeColor: string;
381
+
382
+ build() {
383
+ Text('themed').fontColor(this.themeColor)
384
+ }
385
+ }
386
+ ```
387
+
388
+ ### 7.3 @Builder 复用 + @BuilderParam 插槽
389
+
390
+ ```typescript
391
+ @Builder
392
+ function LoadingView(text: string) {
393
+ Column({ space: 8 }) {
394
+ LoadingProgress().width(48).height(48)
395
+ Text(text).fontSize(14)
396
+ }
397
+ .width('100%')
398
+ .justifyContent(FlexAlign.Center)
399
+ }
400
+ ```
401
+
402
+ ---
403
+
404
+ ## 八、兼容性守卫模式
405
+
406
+ ```typescript
407
+ import deviceInfo from '@ohos.deviceInfo';
408
+
409
+ // 硬件能力检测:调用蓝牙/NFC/摄像头前必须
410
+ function ensureBluetooth(): boolean {
411
+ return canIUse('SystemCapability.Communication.Bluetooth.Core');
412
+ }
413
+
414
+ // API Level 守卫:使用 since 高于目标版本的接口前必须
415
+ function getSdkApiLevel(): number {
416
+ return deviceInfo.sdkApiVersion;
417
+ }
418
+ ```
419
+
420
+ ---
421
+
422
+ ## 九、典型平台陷阱速查
423
+
424
+ | 陷阱 | 正确做法 |
425
+ |------|---------|
426
+ | 沙箱路径 | 用 `context.filesDir` / `context.cacheDir`;禁止硬编码 `/data/local/tmp` |
427
+ | rawfile 资源 | 不可直接路径访问;用 `resourceManager.getRawFileContentSync()` / `getRawFdSync()` |
428
+ | `file://` 前缀 | 拼接为 `file://` + 绝对路径(两斜杠),媒体 URL 不用三斜杠 |
429
+ | fs.writeSync 传 Uint8Array | 必须传 `uint8array.buffer`(ArrayBuffer) |
430
+ | 高频 hilog.debug | 禁止每帧/每秒多次打印,影响性能 |
431
+ | 阻塞主线程 | `Thread.sleep` 类同步等待不存在;用 `await new Promise` + setTimeout 或 taskpool |