@ohos-cpf/3rdloop 0.0.4 → 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.
- package/README.md +119 -128
- package/lib/cli.js +25 -0
- package/lib/serve.js +268 -0
- package/lib/update.js +46 -6
- package/lib/web-ext.js +454 -0
- package/lib/web.js +664 -0
- package/package.json +2 -1
- package/vendor/Server/Skills/arkts-code-use/SKILL.md +270 -0
- package/vendor/Server/Skills/arkts-code-use/assets/TEMPLATES.md +367 -0
- package/vendor/Server/Skills/arkts-code-use/references/API_VERIFICATION.md +144 -0
- package/vendor/Server/Skills/arkts-code-use/references/ARKTS_RULES.md +240 -0
- package/vendor/Server/Skills/arkts-code-use/references/CODE_PATTERNS.md +431 -0
- package/vendor/Server/Skills/arkts-code-use/references/SYNTAX_CHECK_GUIDE.md +164 -0
- package/vendor/Server/Skills/arkts-code-use/scripts/verify-arkts.cjs +428 -0
- package/vendor/Server/Skills/gitcode-repo-fork/SKILL.md +310 -0
- package/vendor/Server/Skills/gitcode-repo-fork/assets/FORK_REPORT_TEMPLATE.md +113 -0
- package/vendor/Server/Skills/gitcode-repo-fork/references/FORK_DECISION_GUIDE.md +124 -0
- package/vendor/Server/Skills/gitcode-repo-fork/references/GITCODE_FORK_API.md +95 -0
- package/vendor/Server/Skills/gitcode-repo-fork/scripts/gitcode-fork.cjs +285 -0
- package/vendor/VERSION +3 -3
- package/web/css/arktslibrarycheck.css +322 -0
- package/web/css/codecheck.css +464 -0
- package/web/css/flutterlibrarycheck.css +322 -0
- package/web/css/knowledge.css +332 -0
- package/web/css/loop.css +578 -0
- package/web/css/md-reader.css +240 -0
- package/web/css/rnlibrarycheck.css +322 -0
- package/web/css/theme.css +702 -0
- package/web/index.html +713 -0
- package/web/js/arktslibrarycheck.js +1413 -0
- package/web/js/codecheck.js +1039 -0
- package/web/js/flutterlibrarycheck.js +1364 -0
- package/web/js/health.js +69 -0
- package/web/js/knowledge.js +358 -0
- package/web/js/loop.js +1102 -0
- package/web/js/md-reader.js +435 -0
- package/web/js/navigation.js +238 -0
- package/web/js/rnlibrarycheck.js +1378 -0
- package/web/js/stats.js +110 -0
- package/web/js/theme.js +46 -0
- package/web/js/utils.js +228 -0
- package/web/knowledge.html +146 -0
- package/web/loop.html +219 -0
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: arkts-code-use
|
|
3
|
+
description: 根据需求编写鸿蒙原生 ArkTS 代码(页面/自定义组件/工具类/服务类),严格遵循 ArkTS 语法约束与华为编码规范,先通过官方文档查证 API(import 路径、方法签名、权限、API Level),再使用 deveco-cli(devecocli build / verify-arkts.cjs)编译验证,确保生成代码零语法错误。当需要为鸿蒙应用或三方库编写、补全、重构 ArkTS 代码,或将功能需求转化为符合规范的 ArkTS 实现时使用。
|
|
4
|
+
license: Apache-2.0
|
|
5
|
+
compatibility: 需要 Node.js、deveco-cli(devecocli 命令:工程脚手架/编译验证/文档检索)及 DevEco Studio + OHOS SDK 构建环境;可选 MCP Gateway 运行中(script_deveco_docs 文档查证、kb_search 知识库)
|
|
6
|
+
metadata:
|
|
7
|
+
author: LoopEngine
|
|
8
|
+
version: "1.0.0"
|
|
9
|
+
category: code-generation
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# ArkTS Code Use — 鸿蒙原生 ArkTS 代码编写
|
|
13
|
+
|
|
14
|
+
本技能用于**根据需求编写符合规范的鸿蒙原生 ArkTS 代码**。核心流程:理解需求 → 查证 API → 编写代码 → 编译验证 → 交付。
|
|
15
|
+
|
|
16
|
+
> ⚠️ **核心原则:所有生成的代码必须同时满足三条底线——① 零语法错误(必须通过 deveco-cli 编译验证,BUILD SUCCESSFUL);② 符合 ArkTS 语法约束与华为编码规范(禁止 `any`/`ESObject`/动态属性访问等);③ API 使用有据可查(import 路径、签名、权限、API Level 均经官方文档查证,禁止凭记忆臆造 API)。**
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## 任务参数
|
|
21
|
+
|
|
22
|
+
| 参数 | 类型 | 必填 | 说明 |
|
|
23
|
+
|------|------|------|------|
|
|
24
|
+
| `requirement` | string | ✅ | 功能需求描述(自然语言或接口定义) |
|
|
25
|
+
| `targetProject` | string | ❌ | 目标鸿蒙工程路径。提供则代码写入该工程并在其中验证;不提供则独立生成,用临时工程完成语法验证 |
|
|
26
|
+
| `outputPath` | string | ❌ | 生成文件/目录位置。默认:有工程时为工程内对应模块目录;无工程时为当前工作目录 |
|
|
27
|
+
| `apiLevel` | number | ❌ | 目标 API Level(默认取工程 `build-profile.json5` 配置;独立生成时默认 12+) |
|
|
28
|
+
| `codeType` | string | ❌ | 代码类型提示:`page`(页面)/ `component`(自定义组件)/ `util`(工具类)/ `service`(业务服务类)。不提供则从需求推断 |
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## 输入依赖
|
|
33
|
+
|
|
34
|
+
无前置SKILL。可作为独立任务调用。若需求涉及已有工程,需目标工程可访问且结构完整(含 `build-profile.json5`)。
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## 工作流程概览
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
Phase 1: 需求理解与场景识别
|
|
42
|
+
↓
|
|
43
|
+
Phase 2: API 查证(官方文档)
|
|
44
|
+
↓
|
|
45
|
+
Phase 3: 代码编写(遵循 ArkTS 约束与编码规范)
|
|
46
|
+
↓
|
|
47
|
+
Phase 4: 编译验证与修复循环(deveco-cli)
|
|
48
|
+
↓
|
|
49
|
+
Phase 5: 规范自检与交付
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Phase 1:需求理解与场景识别
|
|
55
|
+
|
|
56
|
+
### 1.1 解析需求
|
|
57
|
+
|
|
58
|
+
从 `requirement` 中提取:
|
|
59
|
+
- **功能点列表**:拆分为可实现、可验证的具体功能点
|
|
60
|
+
- **代码类型**:`page` / `component` / `util` / `service`(依据 `codeType` 参数或推断)
|
|
61
|
+
- **技术领域**:网络 / 存储 / UI / 多媒体 / 硬件 / 加密 / 并发等(用于 Phase 2 检索)
|
|
62
|
+
- **涉及的系统资源**:HTTP 连接、文件句柄、订阅、Timer、Worker 等(用于 Phase 3 资源管理设计)
|
|
63
|
+
|
|
64
|
+
### 1.2 探查目标工程(如提供 `targetProject`)
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
1. 列出工程根目录,识别 entry/、library/ 等模块
|
|
68
|
+
2. 读取 build-profile.json5,确认 compatibleSdkVersion / 编译 SDK 版本(即目标 API Level)
|
|
69
|
+
3. 读取目标模块 src/main/ets/ 现有源文件与 index.ets 导出,了解代码惯例
|
|
70
|
+
4. 读取 module.json5,了解已声明权限
|
|
71
|
+
5. 若新增页面,确认 src/main/resources/base/profile/main_pages.json 的注册方式
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
> 无 `targetProject` 时跳过本步,采用独立生成模式(Phase 4.2 临时工程验证)。
|
|
75
|
+
|
|
76
|
+
### 1.3 明确交付边界
|
|
77
|
+
|
|
78
|
+
| 场景 | 处理方式 |
|
|
79
|
+
|------|---------|
|
|
80
|
+
| 需求可实现 | 进入 Phase 2 |
|
|
81
|
+
| 需求依赖设备能力(蓝牙/NFC等) | 代码中加 `canIUse()` 守卫,缺能力时降级 |
|
|
82
|
+
| 需求依赖不存在的系统 API | 明确告知用户不可行及原因,提供最接近的替代方案 |
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Phase 2:API 查证(官方文档)
|
|
87
|
+
|
|
88
|
+
> **目标:所有系统 API 的 import 路径、方法签名、参数/返回值、权限、API Level 必须有据可查,禁止凭记忆臆造。**
|
|
89
|
+
|
|
90
|
+
### 2.1 查证工具(按优先级)
|
|
91
|
+
|
|
92
|
+
| 优先级 | 工具 | 适用 |
|
|
93
|
+
|--------|------|------|
|
|
94
|
+
| 1 | MCP Gateway `script_deveco_docs`(action=search / read) | MCP 可用时,检索+精读 HarmonyOS 官方 API 参考 |
|
|
95
|
+
| 2 | `devecocli docs search <关键词>` / `devecocli docs read <documentId>` | 终端直接查证 |
|
|
96
|
+
| 3 | MCP Gateway `kb_search` / `kb-server_search_knowledge` | 补充最佳实践、平台陷阱等经验知识 |
|
|
97
|
+
|
|
98
|
+
### 2.2 查证要点(每个用到的系统 API 均须确认)
|
|
99
|
+
|
|
100
|
+
| 查证项 | 说明 |
|
|
101
|
+
|--------|------|
|
|
102
|
+
| import 路径 | `@ohos.*` 模块名或 `@kit.*`(优先 Kit 聚合导入) |
|
|
103
|
+
| 方法签名 | 参数名、类型、可选性、返回值/Promise/callback 形式 |
|
|
104
|
+
| 权限 | 是否需在 `module.json5` 声明 `ohos.permission.*`,是否运行时申请 |
|
|
105
|
+
| API Level | `since` 版本;高于目标 API Level 时须加版本守卫或换用旧接口 |
|
|
106
|
+
| 废弃标注 | `deprecated` 接口禁止使用,查替代方案 |
|
|
107
|
+
|
|
108
|
+
> 查证工具的调用参数、领域关键词速查表、三步查询法参见 [API 查证指南](references/API_VERIFICATION.md)。
|
|
109
|
+
|
|
110
|
+
### 2.3 输出查证结论
|
|
111
|
+
|
|
112
|
+
以表格形式记录(作为 Phase 3 编写依据):
|
|
113
|
+
|
|
114
|
+
| 功能点 | API(import 路径) | 关键签名 | 权限 | since | 结论 |
|
|
115
|
+
|--------|-------------------|---------|------|-------|------|
|
|
116
|
+
| ... | ... | ... | ... | ... | ✅ 可用 / ⚠️ 需守卫 / ❌ 不可用 |
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## Phase 3:代码编写
|
|
121
|
+
|
|
122
|
+
> 📐 本阶段生成的全部代码须符合华为 ArkTS 编程规范与 ArkTS 语法约束。
|
|
123
|
+
|
|
124
|
+
### 3.1 强制约束(编译必查)
|
|
125
|
+
|
|
126
|
+
核心禁止项(完整清单与修复方案见 [ArkTS 规范与约束](references/ARKTS_RULES.md)):
|
|
127
|
+
|
|
128
|
+
- 禁止 `any`、`unknown`、`ESObject`、`Object` 作通用类型 → 改用具体类型或泛型 `T`
|
|
129
|
+
- 禁止动态属性访问 `obj['key']` → 类型安全访问
|
|
130
|
+
- 禁止内联匿名对象类型 / 未类型化对象字面量 → 定义命名 `interface` 或 `class`
|
|
131
|
+
- 禁止 `prototype` 扩展、`delete` 运算符、`arguments` 对象、`for...in`、`eval()`
|
|
132
|
+
- 禁止 `catch (e)` 中直接 `throw e`(`arkts-limited-throw`)→ 封装为 `Error` 实例后抛出
|
|
133
|
+
- 禁止结构型类型匹配 → 使用显式 `interface` 继承或 `class implements`
|
|
134
|
+
- 禁止在主线程执行阻塞操作 → `async/await + Promise` 或 `taskpool`
|
|
135
|
+
|
|
136
|
+
### 3.2 编码规范
|
|
137
|
+
|
|
138
|
+
- **命名**:PascalCase 类/接口/枚举/struct,camelCase 方法/变量,UPPER_SNAKE_CASE 常量
|
|
139
|
+
- **格式**:2 空格缩进、行尾分号、单文件 ≤ 400 行(超过拆分)
|
|
140
|
+
- **类型**:所有变量/参数/返回值显式标注类型;公共类型必须 `export`
|
|
141
|
+
- **日志**:功能模块使用 `hilog`,敏感数据用 `%{private}s`
|
|
142
|
+
- **资源管理**:`create/open/on/connect` 类资源必须存在对称的 `destroy/close/off/disconnect` 释放路径,置于 `try/finally` 或组件销毁回调
|
|
143
|
+
|
|
144
|
+
### 3.3 按代码类型选择模板
|
|
145
|
+
|
|
146
|
+
按 Phase 1.1 识别的类型,从 [代码模板](assets/TEMPLATES.md) 选取对应模板起步:
|
|
147
|
+
|
|
148
|
+
| 代码类型 | 模板 | 要点 |
|
|
149
|
+
|---------|------|------|
|
|
150
|
+
| `page` | @Entry 页面模板 | 注册到 main_pages.json;aboutToDisappear 清理资源 |
|
|
151
|
+
| `component` | @Component 模板 | @Prop/@Link/@Builder 状态管理;通用 UI 单位用 vp/fp |
|
|
152
|
+
| `util` | 工具类模板 | 静态方法或单例;无状态依赖 |
|
|
153
|
+
| `service` | 业务服务类模板 | 状态机 + async 方法 + hilog + 资源生命周期 |
|
|
154
|
+
|
|
155
|
+
### 3.4 采用成熟代码模式
|
|
156
|
+
|
|
157
|
+
异步封装、taskpool 并发、BusinessError 错误处理、事件订阅、权限申请、HTTP/文件资源清理等标准写法,参见 [ArkTS 代码模式](references/CODE_PATTERNS.md)。
|
|
158
|
+
|
|
159
|
+
### 3.5 落盘规则
|
|
160
|
+
|
|
161
|
+
- 有 `targetProject`:新文件放入目标模块 `src/main/ets/` 对应子目录(pages/components/utils/service);新导出同步到 `index.ets`;新页面注册到 `main_pages.json`;新权限写入 `module.json5`
|
|
162
|
+
- 无 `targetProject`:输出到 `outputPath`(或当前目录),保持单文件自包含或按 `utils/`、`components/` 子目录组织,相对导入路径正确
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## Phase 4:编译验证与修复循环(deveco-cli)
|
|
167
|
+
|
|
168
|
+
> **目标:BUILD SUCCESSFUL 是交付的硬性前置条件。仅有 lint 通过或"看起来没问题"不算通过。**
|
|
169
|
+
|
|
170
|
+
> ⚠️ **验证机制**:hvigor 只编译**构建图可达**的文件(被页面/入口 import 链引用的文件)。未被引用的 .ets 文件不参与编译,不报错——因此验证前必须确保新代码已接入 import 链(或使用 verify-arkts.cjs 自动接线)。详细说明参见 [语法验证指南](references/SYNTAX_CHECK_GUIDE.md)。
|
|
171
|
+
|
|
172
|
+
### 4.1 工程模式(提供了 targetProject)
|
|
173
|
+
|
|
174
|
+
```
|
|
175
|
+
1. 确认新代码已接入构建图:
|
|
176
|
+
- 新页面:文件在 pages/ 下且已注册 main_pages.json
|
|
177
|
+
- 新类/组件:已被页面 import(直接或经由 index.ets)
|
|
178
|
+
2. 执行:devecocli build(在 targetProject 目录下)
|
|
179
|
+
3. 解析输出,只处理 ERROR(WARNING 记录但不阻断)
|
|
180
|
+
4. 按错误码修复 → 重新构建,循环直到 BUILD SUCCESSFUL
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### 4.2 独立模式(无 targetProject)
|
|
184
|
+
|
|
185
|
+
使用本SKILL自带脚本自动完成"脚手架临时工程 → 接线 import → 编译验证 → 回显错误":
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
node {本SKILL目录}/scripts/verify-arkts.cjs --files <生成的.ets文件...> [--work-dir <目录>] [--keep]
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
脚本行为:自动 `devecocli create` 临时工程 → 将文件复制到 `entry/src/main/ets/verify/` 并在入口页生成 side-effect import 接入构建图 → `devecocli build` → 将错误按 `规则 (文件:行:列)` 回显并映射回源文件 → 清理临时工程(`--keep` 保留)。
|
|
192
|
+
|
|
193
|
+
- 退出码 0 = 验证通过;1 = 存在编译错误;2 = 环境问题
|
|
194
|
+
- 多文件间的相对导入会按原目录结构保留,支持批量验证
|
|
195
|
+
|
|
196
|
+
### 4.3 错误修复速查
|
|
197
|
+
|
|
198
|
+
| 错误关键词 / 规则 | 修复方案 |
|
|
199
|
+
|-----------------|---------|
|
|
200
|
+
| `arkts-no-any-unknown` | 替换为具体类型或泛型 `T` |
|
|
201
|
+
| `arkts-no-untyped-obj-literals` | 对象字面量须对应显式 class/interface;先声明类型再赋值 |
|
|
202
|
+
| `arkts-no-obj-literals-as-types` | 内联匿名对象类型改为命名 `interface` |
|
|
203
|
+
| `arkts-limited-throw` | `catch (e)` 中改 `throw e instanceof Error ? e : new Error(String(e))` |
|
|
204
|
+
| `arkts-no-dynamic-property` | `obj['key']` 改为 `obj.key` |
|
|
205
|
+
| `arkts-no-structural-typing` | 类型须显式继承/implements,禁止鸭子类型赋值 |
|
|
206
|
+
| `Cannot find module` | 检查 import 路径大小写与相对层级;`@ohos.*` 拼写以文档为准 |
|
|
207
|
+
| `has been deprecated` | 查官方文档替代 API |
|
|
208
|
+
| `Page ... does not exist` | main_pages.json 与实际文件对齐 |
|
|
209
|
+
| `Permission denied` | module.json5 声明权限(Phase 2 已查证的权限清单) |
|
|
210
|
+
|
|
211
|
+
> 完整验证策略、verify-arkts.cjs 参数、`devecocli check lint` / `check compat` 辅助用法参见 [语法验证指南](references/SYNTAX_CHECK_GUIDE.md)。
|
|
212
|
+
|
|
213
|
+
### 4.4 修复循环纪律
|
|
214
|
+
|
|
215
|
+
```
|
|
216
|
+
LOOP(上限 5 轮):
|
|
217
|
+
1. 构建验证(4.1 或 4.2)
|
|
218
|
+
2. 收集全部 ERROR(一次修复全部已知错误,避免逐个重跑)
|
|
219
|
+
3. 按速查表修复;速查表未覆盖的错误用 script_deveco_docs 查证 API 正确用法
|
|
220
|
+
4. 重新验证
|
|
221
|
+
5. BUILD SUCCESSFUL → 进入 Phase 5
|
|
222
|
+
超过 5 轮未通过:停止并向用户报告当前错误清单与已尝试方案
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
## Phase 5:规范自检与交付
|
|
228
|
+
|
|
229
|
+
### 5.1 交付前自查清单
|
|
230
|
+
|
|
231
|
+
**编译与正确性**
|
|
232
|
+
- [ ] `devecocli build` 输出 `BUILD SUCCESSFUL`(工程模式)或 verify-arkts.cjs 退出码 0(独立模式)
|
|
233
|
+
- [ ] 新代码已接入构建图(import 链可达 / 页面已注册)
|
|
234
|
+
- [ ] 所有系统 API 均经文档查证,无臆造 API,无 deprecated 接口
|
|
235
|
+
|
|
236
|
+
**ArkTS 约束**
|
|
237
|
+
- [ ] 无 `any` / `unknown` / `ESObject` / `Object` 通用类型;无 `as unknown as T` 双重转型
|
|
238
|
+
- [ ] 无动态属性访问、内联匿名类型、`prototype` 扩展、`delete`、`arguments`、`for...in`、`eval`
|
|
239
|
+
- [ ] `catch (e)` 重抛已封装为 `Error` 实例
|
|
240
|
+
- [ ] 耗时操作使用 `async/await` 或 `taskpool`,主线程无阻塞调用
|
|
241
|
+
|
|
242
|
+
**编码规范**
|
|
243
|
+
- [ ] 命名(PascalCase/camelCase/UPPER_SNAKE_CASE)、2 空格缩进、行尾分号
|
|
244
|
+
- [ ] 所有变量/参数/返回值显式类型标注;公共类型已 export
|
|
245
|
+
- [ ] 功能模块有 hilog 日志,敏感数据使用 `%{private}s`
|
|
246
|
+
|
|
247
|
+
**资源与安全**
|
|
248
|
+
- [ ] `create/open/on/connect` 类资源均有对称释放(`try/finally` 或 `aboutToDisappear`)
|
|
249
|
+
- [ ] 外部输入已校验;SQL 参数化;文件路径校验沙箱边界
|
|
250
|
+
- [ ] since > 目标 API Level 的接口有 `canIUse()` / `deviceInfo.sdkApiVersion` 守卫;硬件能力先检测再调用
|
|
251
|
+
- [ ] 所需权限已在 module.json5 声明(工程模式)
|
|
252
|
+
|
|
253
|
+
### 5.2 输出交付物
|
|
254
|
+
|
|
255
|
+
- 生成的 .ets 源文件(含新建/修改的 index.ets、main_pages.json、module.json5 变更说明)
|
|
256
|
+
- API 查证结论表(Phase 2.3)
|
|
257
|
+
- 验证结果:构建命令、最终状态(BUILD SUCCESSFUL / 退出码)、验证模式(工程/独立临时工程)
|
|
258
|
+
- 未实现或降级处理的功能点说明(如有)
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
## 参考资料
|
|
263
|
+
|
|
264
|
+
- [ArkTS 规范与约束](references/ARKTS_RULES.md) — 禁止项完整清单(错误码+修复方案)、类型系统约束、命名与格式规范、日志规范
|
|
265
|
+
- [ArkTS 代码模式](references/CODE_PATTERNS.md) — 异步/taskpool 并发、BusinessError 错误处理、事件订阅、权限申请、资源生命周期管理、UI 状态管理模式
|
|
266
|
+
- [API 查证指南](references/API_VERIFICATION.md) — script_deveco_docs / devecocli docs 用法、领域关键词速查、API Level 对照、三步查询法
|
|
267
|
+
- [语法验证指南](references/SYNTAX_CHECK_GUIDE.md) — 构建图可达性机制、verify-arkts.cjs 完整用法、错误输出解析、check lint / check compat 辅助检查
|
|
268
|
+
- [代码模板](assets/TEMPLATES.md) — 页面/自定义组件/工具类/服务类标准模板
|
|
269
|
+
- [华为 ArkTS 编程规范](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-coding-style-guide) — 官方编码标准
|
|
270
|
+
- [ArkTS 语法约束(TypeScript 到 ArkTS 适配)](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/typescript-to-arkts-migration-guide) — 官方语法约束说明
|
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
# ArkTS 代码模板
|
|
2
|
+
|
|
3
|
+
> 按代码类型选择模板起步,替换占位内容后按需扩展。所有模板均符合 ArkTS 严格模式与华为编码规范,可通过 `devecocli build` 编译验证。
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 一、工具类模板(codeType: util)
|
|
8
|
+
|
|
9
|
+
无状态、可复用的纯逻辑封装。文件:`utils/StringValidator.ets`
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
import hilog from '@ohos.hilog';
|
|
13
|
+
|
|
14
|
+
const DOMAIN: number = 0x0001;
|
|
15
|
+
const TAG: string = 'MyApp_StringValidator';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* 字符串校验工具类(纯静态方法,禁止实例化)
|
|
19
|
+
*/
|
|
20
|
+
export class StringValidator {
|
|
21
|
+
private constructor() {
|
|
22
|
+
// 工具类禁止实例化
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* 校验字符串非空且长度不超上限
|
|
27
|
+
* @param value - 待校验字符串
|
|
28
|
+
* @param maxLen - 最大长度,默认 256
|
|
29
|
+
* @returns 是否合法
|
|
30
|
+
*/
|
|
31
|
+
static isValidText(value: string | null | undefined, maxLen: number = 256): boolean {
|
|
32
|
+
if (value === null || value === undefined) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
return value.length > 0 && value.length <= maxLen;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* 校验字符串是否匹配正则
|
|
40
|
+
* @param value - 待校验字符串
|
|
41
|
+
* @param pattern - 正则表达式
|
|
42
|
+
* @returns 是否匹配
|
|
43
|
+
*/
|
|
44
|
+
static matches(value: string, pattern: RegExp): boolean {
|
|
45
|
+
const matched: boolean = pattern.test(value);
|
|
46
|
+
hilog.debug(DOMAIN, TAG, 'matches result=%{public}s', String(matched));
|
|
47
|
+
return matched;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## 二、业务服务类模板(codeType: service)
|
|
55
|
+
|
|
56
|
+
有状态、含异步操作与资源生命周期管理。文件:`service/ConfigService.ets`
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
import hilog from '@ohos.hilog';
|
|
60
|
+
|
|
61
|
+
const DOMAIN: number = 0x0001;
|
|
62
|
+
const TAG: string = 'MyApp_ConfigService';
|
|
63
|
+
|
|
64
|
+
/** 服务配置 */
|
|
65
|
+
export interface ConfigServiceOptions {
|
|
66
|
+
/** 请求超时(毫秒) */
|
|
67
|
+
timeoutMs: number;
|
|
68
|
+
/** 最大重试次数 */
|
|
69
|
+
maxRetries: number;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** 默认配置 */
|
|
73
|
+
const DEFAULT_OPTIONS: ConfigServiceOptions = {
|
|
74
|
+
timeoutMs: 5000,
|
|
75
|
+
maxRetries: 3,
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
/** 服务状态 */
|
|
79
|
+
export const enum ServiceState {
|
|
80
|
+
IDLE = 0,
|
|
81
|
+
RUNNING = 1,
|
|
82
|
+
FINISHED = 2,
|
|
83
|
+
FAILED = 3,
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* 配置加载服务:管理状态机、异步操作与日志
|
|
88
|
+
*/
|
|
89
|
+
export class ConfigService {
|
|
90
|
+
private readonly options: ConfigServiceOptions;
|
|
91
|
+
private state: ServiceState = ServiceState.IDLE;
|
|
92
|
+
|
|
93
|
+
constructor(options: ConfigServiceOptions = DEFAULT_OPTIONS) {
|
|
94
|
+
this.options = options;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** 获取当前状态 */
|
|
98
|
+
getState(): ServiceState {
|
|
99
|
+
return this.state;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* 执行业务操作(示例骨架,替换为实际逻辑)
|
|
104
|
+
* @param input - 输入参数
|
|
105
|
+
* @returns 处理结果
|
|
106
|
+
*/
|
|
107
|
+
async execute(input: string): Promise<string> {
|
|
108
|
+
hilog.info(DOMAIN, TAG, 'execute start, input length=%{public}d', input.length);
|
|
109
|
+
this.state = ServiceState.RUNNING;
|
|
110
|
+
try {
|
|
111
|
+
// TODO: 替换为实际业务逻辑(系统 API 须经文档查证,见 API_VERIFICATION.md)
|
|
112
|
+
const result: string = input.trim();
|
|
113
|
+
this.state = ServiceState.FINISHED;
|
|
114
|
+
hilog.info(DOMAIN, TAG, 'execute success');
|
|
115
|
+
return result;
|
|
116
|
+
} catch (e) {
|
|
117
|
+
this.state = ServiceState.FAILED;
|
|
118
|
+
const err: Error = e instanceof Error ? e : new Error(String(e));
|
|
119
|
+
hilog.error(DOMAIN, TAG, 'execute failed: %{public}s', err.message);
|
|
120
|
+
throw err;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## 三、页面模板(codeType: page)
|
|
129
|
+
|
|
130
|
+
文件:`pages/ExamplePage.ets`(须注册到 `resources/base/profile/main_pages.json`)
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
import hilog from '@ohos.hilog';
|
|
134
|
+
import { ConfigService } from '../service/ConfigService';
|
|
135
|
+
|
|
136
|
+
const DOMAIN: number = 0x0001;
|
|
137
|
+
const TAG: string = 'MyApp_ExamplePage';
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* 示例页面:演示状态驱动 UI 与资源清理
|
|
141
|
+
*/
|
|
142
|
+
@Entry
|
|
143
|
+
@Component
|
|
144
|
+
struct ExamplePage {
|
|
145
|
+
@State message: string = 'ready';
|
|
146
|
+
@State isLoading: boolean = false;
|
|
147
|
+
private service: ConfigService = new ConfigService();
|
|
148
|
+
private timerId: number = -1;
|
|
149
|
+
|
|
150
|
+
aboutToAppear(): void {
|
|
151
|
+
hilog.info(DOMAIN, TAG, 'page appear');
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
aboutToDisappear(): void {
|
|
155
|
+
// 清理页面持有的 Timer / 订阅等资源
|
|
156
|
+
if (this.timerId >= 0) {
|
|
157
|
+
clearInterval(this.timerId);
|
|
158
|
+
this.timerId = -1;
|
|
159
|
+
}
|
|
160
|
+
hilog.info(DOMAIN, TAG, 'page disappear');
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
private async onRunClicked(): Promise<void> {
|
|
164
|
+
this.isLoading = true;
|
|
165
|
+
try {
|
|
166
|
+
const result: string = await this.service.execute(' demo input ');
|
|
167
|
+
this.message = `result: ${result}`;
|
|
168
|
+
} catch (e) {
|
|
169
|
+
this.message = `failed: ${(e as Error).message}`;
|
|
170
|
+
} finally {
|
|
171
|
+
this.isLoading = false;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
build() {
|
|
176
|
+
Column({ space: 12 }) {
|
|
177
|
+
Text(this.message)
|
|
178
|
+
.fontSize(16)
|
|
179
|
+
.width('90%')
|
|
180
|
+
.textAlign(TextAlign.Center)
|
|
181
|
+
|
|
182
|
+
if (this.isLoading) {
|
|
183
|
+
LoadingProgress()
|
|
184
|
+
.width(36)
|
|
185
|
+
.height(36)
|
|
186
|
+
} else {
|
|
187
|
+
Button('run')
|
|
188
|
+
.width('60%')
|
|
189
|
+
.onClick(() => {
|
|
190
|
+
this.onRunClicked();
|
|
191
|
+
})
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
.width('100%')
|
|
195
|
+
.height('100%')
|
|
196
|
+
.justifyContent(FlexAlign.Center)
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## 四、自定义组件模板(codeType: component)
|
|
204
|
+
|
|
205
|
+
文件:`components/StatusCard.ets`
|
|
206
|
+
|
|
207
|
+
```typescript
|
|
208
|
+
/**
|
|
209
|
+
* 状态卡片组件:父组件传 @Prop 单向数据,@Link 双向同步计数
|
|
210
|
+
*/
|
|
211
|
+
@Component
|
|
212
|
+
export struct StatusCard {
|
|
213
|
+
@Prop title: string = '';
|
|
214
|
+
@Link count: number;
|
|
215
|
+
private onCountChanged: ((count: number) => void) | null = null;
|
|
216
|
+
|
|
217
|
+
build() {
|
|
218
|
+
Column({ space: 8 }) {
|
|
219
|
+
Text(this.title)
|
|
220
|
+
.fontSize(16)
|
|
221
|
+
.fontWeight(FontWeight.Medium)
|
|
222
|
+
|
|
223
|
+
Text(`count: ${this.count}`)
|
|
224
|
+
.fontSize(20)
|
|
225
|
+
|
|
226
|
+
Row({ space: 12 }) {
|
|
227
|
+
Button('+')
|
|
228
|
+
.width(44)
|
|
229
|
+
.height(44)
|
|
230
|
+
.onClick(() => {
|
|
231
|
+
this.count += 1;
|
|
232
|
+
if (this.onCountChanged !== null) {
|
|
233
|
+
this.onCountChanged(this.count);
|
|
234
|
+
}
|
|
235
|
+
})
|
|
236
|
+
Button('-')
|
|
237
|
+
.width(44)
|
|
238
|
+
.height(44)
|
|
239
|
+
.onClick(() => {
|
|
240
|
+
this.count -= 1;
|
|
241
|
+
if (this.onCountChanged !== null) {
|
|
242
|
+
this.onCountChanged(this.count);
|
|
243
|
+
}
|
|
244
|
+
})
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
.padding(12)
|
|
248
|
+
.borderRadius(12)
|
|
249
|
+
.backgroundColor('#F1F3F5')
|
|
250
|
+
.width('90%')
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
> 组件内回调属性(如 `onCountChanged`)须显式声明类型;父组件使用:`StatusCard({ title: 'demo', count: $count, onCountChanged: (c: number) => {} })`
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
## 五、HTTP 服务类模板(网络场景常用)
|
|
260
|
+
|
|
261
|
+
文件:`service/HttpService.ets`。须在 `module.json5` 声明 `ohos.permission.INTERNET`。
|
|
262
|
+
|
|
263
|
+
```typescript
|
|
264
|
+
import { http } from '@kit.NetworkKit';
|
|
265
|
+
import hilog from '@ohos.hilog';
|
|
266
|
+
|
|
267
|
+
const DOMAIN: number = 0x0001;
|
|
268
|
+
const TAG: string = 'MyApp_HttpService';
|
|
269
|
+
|
|
270
|
+
/** 请求配置 */
|
|
271
|
+
export interface HttpServiceOptions {
|
|
272
|
+
connectTimeoutMs: number;
|
|
273
|
+
readTimeoutMs: number;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/** 响应封装 */
|
|
277
|
+
export interface ApiResponse {
|
|
278
|
+
statusCode: number;
|
|
279
|
+
body: string;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
const MAX_RESPONSE_BYTES: number = 5 * 1024 * 1024;
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* HTTP 服务:每次请求独立 HttpRequest,try/finally 释放
|
|
286
|
+
*/
|
|
287
|
+
export class HttpService {
|
|
288
|
+
private readonly options: HttpServiceOptions;
|
|
289
|
+
|
|
290
|
+
constructor(options: HttpServiceOptions) {
|
|
291
|
+
this.options = options;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* 发起 GET 请求
|
|
296
|
+
* @param url - 目标地址(https 优先)
|
|
297
|
+
* @returns 状态码与响应体
|
|
298
|
+
*/
|
|
299
|
+
async get(url: string): Promise<ApiResponse> {
|
|
300
|
+
const httpRequest: http.HttpRequest = http.createHttp();
|
|
301
|
+
try {
|
|
302
|
+
const response: http.HttpResponse = await httpRequest.request(url, {
|
|
303
|
+
method: http.RequestMethod.GET,
|
|
304
|
+
connectTimeout: this.options.connectTimeoutMs,
|
|
305
|
+
readTimeout: this.options.readTimeoutMs,
|
|
306
|
+
});
|
|
307
|
+
if (typeof response.result !== 'string') {
|
|
308
|
+
throw new Error('unexpected response type');
|
|
309
|
+
}
|
|
310
|
+
if (response.result.length > MAX_RESPONSE_BYTES) {
|
|
311
|
+
throw new Error(`response too large: ${response.result.length} bytes`);
|
|
312
|
+
}
|
|
313
|
+
hilog.info(DOMAIN, TAG, 'GET %{public}s -> %{public}d', url, response.responseCode);
|
|
314
|
+
return { statusCode: response.responseCode, body: response.result };
|
|
315
|
+
} finally {
|
|
316
|
+
httpRequest.destroy();
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
## 六、模块导出模板(index.ets)
|
|
325
|
+
|
|
326
|
+
```typescript
|
|
327
|
+
// library/src/main/ets/index.ets 或模块入口
|
|
328
|
+
export { StringValidator } from './utils/StringValidator';
|
|
329
|
+
export { ConfigService } from './service/ConfigService';
|
|
330
|
+
export type { ConfigServiceOptions } from './service/ConfigService';
|
|
331
|
+
export { ServiceState } from './service/ConfigService';
|
|
332
|
+
export { HttpService } from './service/HttpService';
|
|
333
|
+
export type { HttpServiceOptions, ApiResponse } from './service/HttpService';
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
> 仅 `export` 的符号对外可见;`interface`/`type` 导出用 `export type`。
|
|
337
|
+
|
|
338
|
+
---
|
|
339
|
+
|
|
340
|
+
## 七、main_pages.json 注册模板
|
|
341
|
+
|
|
342
|
+
`entry/src/main/resources/base/profile/main_pages.json`:
|
|
343
|
+
|
|
344
|
+
```json
|
|
345
|
+
{
|
|
346
|
+
"src": [
|
|
347
|
+
"pages/Index",
|
|
348
|
+
"pages/ExamplePage"
|
|
349
|
+
]
|
|
350
|
+
}
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
## 八、module.json5 权限声明模板
|
|
354
|
+
|
|
355
|
+
`entry/src/main/module.json5`(module 节点内):
|
|
356
|
+
|
|
357
|
+
```json
|
|
358
|
+
{
|
|
359
|
+
"module": {
|
|
360
|
+
"requestPermissions": [
|
|
361
|
+
{ "name": "ohos.permission.INTERNET" }
|
|
362
|
+
]
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
> user_grant 级权限(如 LOCATION)声明后还须运行时申请,参见 [代码模式 §五](../references/CODE_PATTERNS.md)。
|