cj-tauri 2.0.0 → 2.1.1
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 +206 -139
- package/bin/cj-tauri.js +287 -287
- package/cjpm.toml +63 -52
- package/cli/cjpm.toml +22 -22
- package/cli/src/doctor.cj +308 -306
- package/cli/src/main.cj +129 -129
- package/cli/src/manifest.cj +643 -558
- package/cli/src/manifest_test.cj +87 -0
- package/cli/src/project.cj +770 -770
- package/cli/src/resolve.cj +348 -348
- package/cli/src/scaffold.cj +369 -369
- package/cli/src/sync.cj +638 -526
- package/cli/src/util.cj +168 -168
- package/cli/templates/app/README.md +51 -48
- package/cli/templates/app/assets/capabilities/default.json +7 -7
- package/cli/templates/app/assets/ui/index.html +120 -118
- package/cli/templates/app/cj-tauri.toml +32 -22
- package/cli/templates/app/cjpm.toml +34 -34
- package/cli/templates/app/src/main.cj +101 -90
- package/cli/templates/app-react/README.md +56 -56
- package/cli/templates/app-react/assets/capabilities/default.json +7 -7
- package/cli/templates/app-react/assets/ui/index.html +25 -25
- package/cli/templates/app-react/assets/ui/package.json +19 -19
- package/cli/templates/app-react/assets/ui/src/App.css +67 -67
- package/cli/templates/app-react/assets/ui/src/App.jsx +124 -124
- package/cli/templates/app-react/assets/ui/src/main.jsx +6 -6
- package/cli/templates/app-react/assets/ui/vite.config.js +24 -24
- package/cli/templates/app-react/cj-tauri.toml +33 -23
- package/cli/templates/app-react/cjpm.toml +34 -34
- package/cli/templates/app-react/src/main.cj +91 -91
- package/cli/templates/app-vue/README.md +56 -56
- package/cli/templates/app-vue/assets/capabilities/default.json +7 -7
- package/cli/templates/app-vue/assets/ui/index.html +25 -25
- package/cli/templates/app-vue/assets/ui/package.json +18 -18
- package/cli/templates/app-vue/assets/ui/src/App.vue +176 -176
- package/cli/templates/app-vue/assets/ui/src/main.js +4 -4
- package/cli/templates/app-vue/assets/ui/vite.config.js +24 -24
- package/cli/templates/app-vue/cj-tauri.toml +33 -23
- package/cli/templates/app-vue/cjpm.toml +34 -34
- package/cli/templates/app-vue/src/main.cj +91 -91
- package/cli/templates/ohos-skeleton/AppScope/app.json5 +13 -13
- package/cli/templates/ohos-skeleton/AppScope/resources/base/element/string.json +8 -8
- package/cli/templates/ohos-skeleton/AppScope/resources/base/media/layered_image.json +6 -6
- package/cli/templates/ohos-skeleton/README.md +84 -79
- package/cli/templates/ohos-skeleton/build-hap.sh +15 -0
- package/cli/templates/ohos-skeleton/build-profile.json5 +46 -46
- package/cli/templates/ohos-skeleton/entry/build-profile.json5 +26 -26
- package/cli/templates/ohos-skeleton/entry/cjpm.toml +51 -43
- package/cli/templates/ohos-skeleton/entry/hvigorfile.ts +6 -6
- package/cli/templates/ohos-skeleton/entry/oh-package.json5 +9 -9
- package/cli/templates/ohos-skeleton/entry/src/main/cangjie/ability_stage.cj +17 -17
- package/cli/templates/ohos-skeleton/entry/src/main/cangjie/app_host.cj +94 -94
- package/cli/templates/ohos-skeleton/entry/src/main/cangjie/dialog_host.cj +217 -0
- package/cli/templates/ohos-skeleton/entry/src/main/cangjie/index.cj +527 -167
- package/cli/templates/ohos-skeleton/entry/src/main/cangjie/main_ability.cj +139 -139
- package/cli/templates/ohos-skeleton/entry/src/main/module.json5 +57 -49
- package/cli/templates/ohos-skeleton/entry/src/main/resources/base/element/color.json +8 -8
- package/cli/templates/ohos-skeleton/entry/src/main/resources/base/element/string.json +16 -16
- package/cli/templates/ohos-skeleton/entry/src/main/resources/base/media/layered_image.json +6 -6
- package/cli/templates/ohos-skeleton/entry/src/main/resources/base/profile/main_pages.json +2 -2
- package/cli/templates/ohos-skeleton/entry/src/main/resources/rawfile/capabilities.json +6 -6
- package/cli/templates/ohos-skeleton/entry/src/main/resources/rawfile/index.html +92 -92
- package/cli/templates/ohos-skeleton/hvigor/hvigor-config.json5 +5 -5
- package/cli/templates/ohos-skeleton/hvigorfile.ts +6 -6
- package/cli/templates/ohos-skeleton/oh-package.json5 +10 -10
- package/native/build_win.bat +62 -62
- package/native/core/bridge_core.c +1681 -1626
- package/native/core/bridge_core.h +675 -618
- package/native/core/bridge_js.h +108 -108
- package/native/platforms/harmonyos/README.md +115 -6
- package/native/platforms/linux/bridge_linux.c +2787 -2485
- package/native/platforms/windows/bridge_win.c +3745 -3248
- package/native/tests/gtk_threading_probe.c +143 -143
- package/native/tests/test_bridge_core.c +1339 -1228
- package/package.json +53 -53
- package/src/api_system.cj +67 -67
- package/src/app.cj +335 -969
- package/src/app_events.cj +166 -0
- package/src/app_host_ops.cj +287 -0
- package/src/app_run.cj +283 -0
- package/src/app_spec.cj +76 -76
- package/src/arkweb_menu.cj +216 -0
- package/src/arkweb_script.cj +142 -142
- package/src/capability.cj +409 -409
- package/src/clipboard_bridge.cj +178 -0
- package/src/dialog_spec.cj +79 -0
- package/src/dragdrop.cj +26 -26
- package/src/embedded_assets.cj +98 -98
- package/src/host.cj +752 -607
- package/src/host_arkweb.cj +924 -778
- package/src/host_webkit.cj +663 -570
- package/src/host_webview2.cj +663 -570
- package/src/hotkey.cj +66 -66
- package/src/ipc_hub.cj +401 -337
- package/src/ipc_message.cj +286 -286
- package/src/launch.cj +62 -62
- package/src/logging.cj +127 -127
- package/src/menu.cj +197 -197
- package/src/platform/platform_app_context.cj +77 -77
- package/src/platform/platform_assets.cj +33 -33
- package/src/platform/platform_discover.cj +176 -176
- package/src/platform/platform_env.cj +29 -29
- package/src/platform/platform_feature.cj +31 -31
- package/src/platform/platform_page_source.cj +87 -87
- package/src/platform/platform_target_info.cj +32 -32
- package/src/platform_host_provider.cj +87 -87
- package/src/plugin.cj +333 -333
- package/src/plugins/clipboard/plugin_clipboard.cj +152 -152
- package/src/plugins/dialog/plugin_dialog.cj +209 -209
- package/src/plugins/fs/plugin_fs.cj +105 -1
- package/src/plugins/http/http_backend.cj +131 -0
- package/src/plugins/http/http_desktop.cj +195 -0
- package/src/plugins/http/http_ohos.cj +204 -0
- package/src/plugins/http/plugin_http.cj +310 -459
- package/src/plugins/log/plugin_log.cj +105 -105
- package/src/plugins/menu/plugin_menu.cj +158 -158
- package/src/plugins/notification/plugin_notification.cj +154 -154
- package/src/plugins/serial/plugin_serial.cj +458 -454
- package/src/plugins/serial/serial_bridge.cj +194 -194
- package/src/plugins/serial/serial_manager_ohos.cj +92 -0
- package/src/plugins/serial/serial_ohos.cj +529 -0
- package/src/plugins/shell/plugin_shell.cj +258 -258
- package/src/plugins/sqlite/plugin_sqlite.cj +705 -710
- package/src/plugins/sqlite/sqlite_ffi.cj +206 -211
- package/src/plugins/ws/plugin_ws.cj +488 -470
- package/src/process_hidden.cj +174 -174
- package/src/scope.cj +391 -391
- package/src/shell_event.cj +69 -69
- package/src/tests/app_spec_test.cj +130 -127
- package/src/tests/capability_test.cj +243 -243
- package/src/tests/dialog_spec_test.cj +73 -0
- package/src/tests/fake_host.cj +201 -201
- package/src/tests/ipc_hub_test.cj +563 -487
- package/src/tests/logging_test.cj +62 -62
- package/src/tests/platform_contract_test.cj +264 -251
- package/src/tests/plugin_clipboard_test.cj +222 -222
- package/src/tests/plugin_dialog_test.cj +237 -237
- package/src/tests/plugin_fs_test.cj +207 -0
- package/src/tests/plugin_http_test.cj +124 -124
- package/src/tests/plugin_notification_test.cj +205 -205
- package/src/tests/plugin_serial_test.cj +48 -0
- package/src/tests/plugin_test.cj +605 -585
- package/src/tests/plugin_ws_test.cj +40 -40
- package/src/tests/process_hidden_test.cj +129 -129
- package/src/tests/scope_test.cj +350 -350
- package/src/tests/system_host_test.cj +99 -81
- package/src/tests/urlutil_test.cj +53 -53
- package/src/tests/version_test.cj +75 -75
- package/src/tests/window_registry_test.cj +123 -123
- package/src/tray.cj +90 -90
- package/src/urlutil.cj +159 -159
- package/src/version.cj +44 -44
- package/src/window.cj +51 -51
- package/src/window_registry.cj +116 -116
- package/prebuilt/win32-x64/cj-tauri.exe +0 -0
- package/src/plugins/serial/serial_ohos_stub.cj +0 -61
- package/src/plugins/sqlite/sqlite_ohos_stub.cj +0 -91
|
@@ -1,91 +1,91 @@
|
|
|
1
|
-
package {{PACKAGE_NAME}}
|
|
2
|
-
|
|
3
|
-
import cjTauri.*
|
|
4
|
-
import cjTauri.plugins.menu.*
|
|
5
|
-
import stdx.encoding.json.*
|
|
6
|
-
import std.collection.*
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* greet 命令(对标 tauri command)
|
|
10
|
-
* 前端:tauri.invoke("greet", { name: "..." })
|
|
11
|
-
*/
|
|
12
|
-
public class GreetCommand <: CommandHandler {
|
|
13
|
-
public init() {}
|
|
14
|
-
|
|
15
|
-
public func handle(cmd: String, args: JsonObject, ipc: IpcContext): JsonValue {
|
|
16
|
-
var name = "world"
|
|
17
|
-
if (let Some(n) <- args.get("name")) {
|
|
18
|
-
match (n.kind()) {
|
|
19
|
-
case JsonKind.JsString => name = n.asString().getValue()
|
|
20
|
-
case _ => ()
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
return JsonString("Hello, ${name}! 来自仓颉后端")
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* 定时器命令:启动后台线程,每秒向前端推一个 tick 事件(验证 仓颉 → JS 通道)
|
|
29
|
-
* 前端:tauri.listen("tick", cb) + tauri.invoke("timer")
|
|
30
|
-
*/
|
|
31
|
-
public class TimerCommand <: CommandHandler {
|
|
32
|
-
private var counter: Int64 = 0
|
|
33
|
-
private var started: Bool = false
|
|
34
|
-
|
|
35
|
-
public init() {}
|
|
36
|
-
|
|
37
|
-
public func handle(cmd: String, args: JsonObject, ipc: IpcContext): JsonValue {
|
|
38
|
-
if (!this.started) {
|
|
39
|
-
this.started = true
|
|
40
|
-
spawn {
|
|
41
|
-
while (true) {
|
|
42
|
-
sleep(Duration.second)
|
|
43
|
-
this.counter += 1
|
|
44
|
-
var payload = JsonObject()
|
|
45
|
-
payload.put("n", JsonInt(this.counter))
|
|
46
|
-
ipc.emit("tick", payload)
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
return JsonString("timer started")
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* 演示菜单:一个普通项 + 一个带勾选项的子菜单
|
|
56
|
-
*
|
|
57
|
-
* 两个方向都在页面上看得到:
|
|
58
|
-
* 菜单 → 页面:点「打个招呼」,宿主把事件推给前端(页面 listen("menu:click") 显示 id)
|
|
59
|
-
* 页面 → 菜单:勾选页面上的复选框,走 menu 插件改「侧边栏」这一项的勾选状态
|
|
60
|
-
*/
|
|
61
|
-
func demoMenu(): MenuModel {
|
|
62
|
-
var view = ArrayList<MenuItem>()
|
|
63
|
-
view.add(MenuItem.checkbox("view.sidebar", "侧边栏", true))
|
|
64
|
-
var items = ArrayList<MenuItem>()
|
|
65
|
-
items.add(MenuItem.normal("file.hello", "打个招呼"))
|
|
66
|
-
items.add(MenuItem.submenu("视图", view))
|
|
67
|
-
return MenuModel(items)
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* 业务装配点(RFC-002 §4.1):骨架的 launcher(targets/ 下各目标的 src)调用它取 AppSpec。
|
|
72
|
-
*
|
|
73
|
-
* 零平台知识:不碰宿主、不知道页面文件路径、不知道能力目录——那些由清单
|
|
74
|
-
* (cj-tauri.toml)决定,launcher 按清单覆盖(page/window/assets/capabilities)。
|
|
75
|
-
* dev 模式页面来自 Vite dev server(框架按 CJ_TAURI_DEV_URL 自动改写),
|
|
76
|
-
* 发布构建加载 assets/ui/dist 的单文件产物——两种跑法业务代码完全一致。
|
|
77
|
-
*/
|
|
78
|
-
public func build(): AppSpec {
|
|
79
|
-
return AppSpec()
|
|
80
|
-
.window(WindowConfig("{{PROJECT_NAME}}", 1000, 700))
|
|
81
|
-
// menu 插件:给前端挂 window.__CJ_TAURI__.menu.setEnabled / setChecked
|
|
82
|
-
// (插件只声明「我提供什么」,**不自动放行**——要能调,就在 capabilities 里引用
|
|
83
|
-
// permissions: ["menu:state"],或逐条写 commands)
|
|
84
|
-
.plugin(MenuPlugin())
|
|
85
|
-
.wire({ app =>
|
|
86
|
-
app.register("greet", GreetCommand())
|
|
87
|
-
app.register("timer", TimerCommand())
|
|
88
|
-
// 菜单栏必须在 run 之前挂:预置类宿主能力要赶在页面加载前定稿
|
|
89
|
-
app.setMenu(demoMenu())
|
|
90
|
-
})
|
|
91
|
-
}
|
|
1
|
+
package {{PACKAGE_NAME}}
|
|
2
|
+
|
|
3
|
+
import cjTauri.*
|
|
4
|
+
import cjTauri.plugins.menu.*
|
|
5
|
+
import stdx.encoding.json.*
|
|
6
|
+
import std.collection.*
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* greet 命令(对标 tauri command)
|
|
10
|
+
* 前端:tauri.invoke("greet", { name: "..." })
|
|
11
|
+
*/
|
|
12
|
+
public class GreetCommand <: CommandHandler {
|
|
13
|
+
public init() {}
|
|
14
|
+
|
|
15
|
+
public func handle(cmd: String, args: JsonObject, ipc: IpcContext): JsonValue {
|
|
16
|
+
var name = "world"
|
|
17
|
+
if (let Some(n) <- args.get("name")) {
|
|
18
|
+
match (n.kind()) {
|
|
19
|
+
case JsonKind.JsString => name = n.asString().getValue()
|
|
20
|
+
case _ => ()
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return JsonString("Hello, ${name}! 来自仓颉后端")
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* 定时器命令:启动后台线程,每秒向前端推一个 tick 事件(验证 仓颉 → JS 通道)
|
|
29
|
+
* 前端:tauri.listen("tick", cb) + tauri.invoke("timer")
|
|
30
|
+
*/
|
|
31
|
+
public class TimerCommand <: CommandHandler {
|
|
32
|
+
private var counter: Int64 = 0
|
|
33
|
+
private var started: Bool = false
|
|
34
|
+
|
|
35
|
+
public init() {}
|
|
36
|
+
|
|
37
|
+
public func handle(cmd: String, args: JsonObject, ipc: IpcContext): JsonValue {
|
|
38
|
+
if (!this.started) {
|
|
39
|
+
this.started = true
|
|
40
|
+
spawn {
|
|
41
|
+
while (true) {
|
|
42
|
+
sleep(Duration.second)
|
|
43
|
+
this.counter += 1
|
|
44
|
+
var payload = JsonObject()
|
|
45
|
+
payload.put("n", JsonInt(this.counter))
|
|
46
|
+
ipc.emit("tick", payload)
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return JsonString("timer started")
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* 演示菜单:一个普通项 + 一个带勾选项的子菜单
|
|
56
|
+
*
|
|
57
|
+
* 两个方向都在页面上看得到:
|
|
58
|
+
* 菜单 → 页面:点「打个招呼」,宿主把事件推给前端(页面 listen("menu:click") 显示 id)
|
|
59
|
+
* 页面 → 菜单:勾选页面上的复选框,走 menu 插件改「侧边栏」这一项的勾选状态
|
|
60
|
+
*/
|
|
61
|
+
func demoMenu(): MenuModel {
|
|
62
|
+
var view = ArrayList<MenuItem>()
|
|
63
|
+
view.add(MenuItem.checkbox("view.sidebar", "侧边栏", true))
|
|
64
|
+
var items = ArrayList<MenuItem>()
|
|
65
|
+
items.add(MenuItem.normal("file.hello", "打个招呼"))
|
|
66
|
+
items.add(MenuItem.submenu("视图", view))
|
|
67
|
+
return MenuModel(items)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* 业务装配点(RFC-002 §4.1):骨架的 launcher(targets/ 下各目标的 src)调用它取 AppSpec。
|
|
72
|
+
*
|
|
73
|
+
* 零平台知识:不碰宿主、不知道页面文件路径、不知道能力目录——那些由清单
|
|
74
|
+
* (cj-tauri.toml)决定,launcher 按清单覆盖(page/window/assets/capabilities)。
|
|
75
|
+
* dev 模式页面来自 Vite dev server(框架按 CJ_TAURI_DEV_URL 自动改写),
|
|
76
|
+
* 发布构建加载 assets/ui/dist 的单文件产物——两种跑法业务代码完全一致。
|
|
77
|
+
*/
|
|
78
|
+
public func build(): AppSpec {
|
|
79
|
+
return AppSpec()
|
|
80
|
+
.window(WindowConfig("{{PROJECT_NAME}}", 1000, 700))
|
|
81
|
+
// menu 插件:给前端挂 window.__CJ_TAURI__.menu.setEnabled / setChecked
|
|
82
|
+
// (插件只声明「我提供什么」,**不自动放行**——要能调,就在 capabilities 里引用
|
|
83
|
+
// permissions: ["menu:state"],或逐条写 commands)
|
|
84
|
+
.plugin(MenuPlugin())
|
|
85
|
+
.wire({ app =>
|
|
86
|
+
app.register("greet", GreetCommand())
|
|
87
|
+
app.register("timer", TimerCommand())
|
|
88
|
+
// 菜单栏必须在 run 之前挂:预置类宿主能力要赶在页面加载前定稿
|
|
89
|
+
app.setMenu(demoMenu())
|
|
90
|
+
})
|
|
91
|
+
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
{
|
|
2
|
-
"app": {
|
|
3
|
-
/* bundleName 是应用在设备上的唯一 ID:两个应用写同一个 bundleName 会互相覆盖安装。
|
|
4
|
-
改它必须重新签名——DevEco 的「自动签名」会按新包名重新申请 profile。 */
|
|
5
|
-
"bundleName": "{{BUNDLE_NAME}}",
|
|
6
|
-
"vendor": "{{PROJECT_NAME}}",
|
|
7
|
-
"versionCode": 1000000,
|
|
8
|
-
"versionName": "1.0.0",
|
|
9
|
-
"buildVersion": "1",
|
|
10
|
-
"icon": "$media:layered_image",
|
|
11
|
-
"label": "$string:app_name"
|
|
12
|
-
}
|
|
13
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"app": {
|
|
3
|
+
/* bundleName 是应用在设备上的唯一 ID:两个应用写同一个 bundleName 会互相覆盖安装。
|
|
4
|
+
改它必须重新签名——DevEco 的「自动签名」会按新包名重新申请 profile。 */
|
|
5
|
+
"bundleName": "{{BUNDLE_NAME}}",
|
|
6
|
+
"vendor": "{{PROJECT_NAME}}",
|
|
7
|
+
"versionCode": 1000000,
|
|
8
|
+
"versionName": "1.0.0",
|
|
9
|
+
"buildVersion": "1",
|
|
10
|
+
"icon": "$media:layered_image",
|
|
11
|
+
"label": "$string:app_name"
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
{
|
|
2
|
-
"string": [
|
|
3
|
-
{
|
|
4
|
-
"name": "app_name",
|
|
5
|
-
"value": "{{APP_LABEL}}"
|
|
6
|
-
}
|
|
7
|
-
]
|
|
8
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"string": [
|
|
3
|
+
{
|
|
4
|
+
"name": "app_name",
|
|
5
|
+
"value": "{{APP_LABEL}}"
|
|
6
|
+
}
|
|
7
|
+
]
|
|
8
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
{
|
|
2
|
-
"layered-image": {
|
|
3
|
-
"background": "$media:background",
|
|
4
|
-
"foreground": "$media:foreground"
|
|
5
|
-
}
|
|
6
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"layered-image": {
|
|
3
|
+
"background": "$media:background",
|
|
4
|
+
"foreground": "$media:foreground"
|
|
5
|
+
}
|
|
6
|
+
}
|
|
@@ -1,79 +1,84 @@
|
|
|
1
|
-
# {{PROJECT_NAME}} — 仓颉 + ArkWeb 鸿蒙 PC 应用
|
|
2
|
-
|
|
3
|
-
用 [cj-tauri](https://atomgit.com/qq8864/cj-tauri) 生成的鸿蒙 PC(2in1)应用工程:
|
|
4
|
-
**仓颉后端(静态编译)+ 系统 ArkWeb 前端(HTML/CSS/JS)**,IPC、能力校验、命令分发与桌面版同一套框架代码。
|
|
5
|
-
|
|
6
|
-
## 目录
|
|
7
|
-
|
|
8
|
-
```
|
|
9
|
-
{{PROJECT_NAME}}/
|
|
10
|
-
├─ AppScope/app.json5 应用级配置(bundleName = {{BUNDLE_NAME}})
|
|
11
|
-
├─ build-profile.json5 工程级构建配置(签名留空,见下)
|
|
12
|
-
├─ build-hap.sh 构建入口(编 hap / 装到设备)
|
|
13
|
-
├─ entry/
|
|
14
|
-
│ ├─ cjpm.toml cjTauri 依赖 + aarch64-linux-ohos 目标段
|
|
15
|
-
│ ├─ build-profile.json5 cangjieOptions.checkDeviceTypes=false(放行 2in1)
|
|
16
|
-
│ └─ src/main/
|
|
17
|
-
│ ├─ module.json5 deviceTypes: 2in1 / tablet / phone
|
|
18
|
-
│ ├─ cangjie/
|
|
19
|
-
│ │ ├─ ability_stage.cj AbilityStage
|
|
20
|
-
│ │ ├─ main_ability.cj UIAbility:沙箱、rawfile 读取、窗口尺寸、loadContent
|
|
21
|
-
│ │ ├─ index.cj ArkWeb 宿主组件(javaScriptProxy 双向桥)
|
|
22
|
-
│ │ └─ app_host.cj 框架装配 + demo 命令(greet / timer)
|
|
23
|
-
│ └─ resources/rawfile/
|
|
24
|
-
│ ├─ index.html 页面(改这里)
|
|
25
|
-
│ └─ capabilities.json 能力清单(改这里)
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
页面与能力清单是 **hap 里的真文件**(rawfile),运行期由 Ability 读成字符串交给框架——
|
|
29
|
-
所以 DevEco 里直接点 Build 也能编过,不需要先跑生成脚本。
|
|
30
|
-
|
|
31
|
-
## 构建 / 装到设备
|
|
32
|
-
|
|
33
|
-
```bash
|
|
34
|
-
# 1) 鸿蒙版 stdx(构建期要链它)
|
|
35
|
-
export CANGJIE_STDX_OHOS=<stdx>/linux_ohos_aarch64_cjnative/dynamic/stdx
|
|
36
|
-
|
|
37
|
-
# 2) DevEco 安装根(脚本会自动探测几个常见位置,探测不到就自己给)
|
|
38
|
-
export DEVECO_WIN='D:\Program Files\Huawei\DevEco Studio'
|
|
39
|
-
|
|
40
|
-
# 3) 编 hap
|
|
41
|
-
bash build-hap.sh
|
|
42
|
-
|
|
43
|
-
# 4) 编完装到设备并拉起(需要设备已连上、应用已签名)
|
|
44
|
-
bash build-hap.sh --install
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
改了鸿蒙侧仓颉代码却没生效时:`bash build-hap.sh --clean`(hvigor 与框架 cjpm 各有一份增量缓存)。
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
-
|
|
63
|
-
|
|
64
|
-
`
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
1
|
+
# {{PROJECT_NAME}} — 仓颉 + ArkWeb 鸿蒙 PC 应用
|
|
2
|
+
|
|
3
|
+
用 [cj-tauri](https://atomgit.com/qq8864/cj-tauri) 生成的鸿蒙 PC(2in1)应用工程:
|
|
4
|
+
**仓颉后端(静态编译)+ 系统 ArkWeb 前端(HTML/CSS/JS)**,IPC、能力校验、命令分发与桌面版同一套框架代码。
|
|
5
|
+
|
|
6
|
+
## 目录
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
{{PROJECT_NAME}}/
|
|
10
|
+
├─ AppScope/app.json5 应用级配置(bundleName = {{BUNDLE_NAME}})
|
|
11
|
+
├─ build-profile.json5 工程级构建配置(签名留空,见下)
|
|
12
|
+
├─ build-hap.sh 构建入口(编 hap / 装到设备)
|
|
13
|
+
├─ entry/
|
|
14
|
+
│ ├─ cjpm.toml cjTauri 依赖 + aarch64-linux-ohos 目标段
|
|
15
|
+
│ ├─ build-profile.json5 cangjieOptions.checkDeviceTypes=false(放行 2in1)
|
|
16
|
+
│ └─ src/main/
|
|
17
|
+
│ ├─ module.json5 deviceTypes: 2in1 / tablet / phone
|
|
18
|
+
│ ├─ cangjie/
|
|
19
|
+
│ │ ├─ ability_stage.cj AbilityStage
|
|
20
|
+
│ │ ├─ main_ability.cj UIAbility:沙箱、rawfile 读取、窗口尺寸、loadContent
|
|
21
|
+
│ │ ├─ index.cj ArkWeb 宿主组件(javaScriptProxy 双向桥)
|
|
22
|
+
│ │ └─ app_host.cj 框架装配 + demo 命令(greet / timer)
|
|
23
|
+
│ └─ resources/rawfile/
|
|
24
|
+
│ ├─ index.html 页面(改这里)
|
|
25
|
+
│ └─ capabilities.json 能力清单(改这里)
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
页面与能力清单是 **hap 里的真文件**(rawfile),运行期由 Ability 读成字符串交给框架——
|
|
29
|
+
所以 DevEco 里直接点 Build 也能编过,不需要先跑生成脚本。
|
|
30
|
+
|
|
31
|
+
## 构建 / 装到设备
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
# 1) 鸿蒙版 stdx(构建期要链它)
|
|
35
|
+
export CANGJIE_STDX_OHOS=<stdx>/linux_ohos_aarch64_cjnative/dynamic/stdx
|
|
36
|
+
|
|
37
|
+
# 2) DevEco 安装根(脚本会自动探测几个常见位置,探测不到就自己给)
|
|
38
|
+
export DEVECO_WIN='D:\Program Files\Huawei\DevEco Studio'
|
|
39
|
+
|
|
40
|
+
# 3) 编 hap
|
|
41
|
+
bash build-hap.sh
|
|
42
|
+
|
|
43
|
+
# 4) 编完装到设备并拉起(需要设备已连上、应用已签名)
|
|
44
|
+
bash build-hap.sh --install
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
改了鸿蒙侧仓颉代码却没生效时:`bash build-hap.sh --clean`(hvigor 与框架 cjpm 各有一份增量缓存)。
|
|
48
|
+
|
|
49
|
+
**DevEco IDE 内点 Build 不经过 build-hap.sh**:assets 自动同步段(工程根 assets/ → rawfile)在
|
|
50
|
+
命令行入口里,IDE 构建不会执行——在 IDE 里改了 `assets/ui` 或 `assets/capabilities` 后,
|
|
51
|
+
要么回命令行跑一次 `bash build-hap.sh`,要么重跑 `cj-tauri sync ohos`;直接 IDE 构建装出来的是旧页
|
|
52
|
+
(判据:hap 内 `unzip -p *.hap resources/rawfile/ui/index.html` 不含你的改动)。
|
|
53
|
+
|
|
54
|
+
## 签名
|
|
55
|
+
|
|
56
|
+
模板**不带证书**(调试证书由每台机器的 DevEco 本机生成、与华为账号绑定,不该入库)。
|
|
57
|
+
首次打开请在 DevEco 里 File → Project Structure → Signing Configs,
|
|
58
|
+
勾上「Automatically generate signature」。不签名也能编(产物是 `*-unsigned.hap`),但装不进设备。
|
|
59
|
+
|
|
60
|
+
## 改应用
|
|
61
|
+
|
|
62
|
+
- **加命令**:在 `app_host.cj` 里写 `CommandHandler` → `.register("名字", XxxCommand())` →
|
|
63
|
+
在 `entry/src/main/resources/rawfile/capabilities.json` 的 `commands` 里声明。三处缺一处就用不了
|
|
64
|
+
(只缺注册 → `command not registered`;只缺清单 → `command not allowed`)。
|
|
65
|
+
- **改页面**:`entry/src/main/resources/rawfile/index.html`,前端只经 `window.__CJ_TAURI__`
|
|
66
|
+
的 `invoke` / `listen`,并且要**等桥出现**(ArkWeb 没有 document-start 注入)。
|
|
67
|
+
- **联网**:`module.json5` 已声明 `ohos.permission.INTERNET`;用不到就删掉。
|
|
68
|
+
- **窗口尺寸**:`main_ability.cj` **默认不动窗口**——鸿蒙 PC 按桌面形态给的那扇窗(本机 3120×2080 屏上
|
|
69
|
+
`2090×1394 px`,约屏宽 2/3)就是合适的大小,`logDefaultWindowRect()` 只把它读出来打一行 hilog 当凭证。
|
|
70
|
+
别在 `onWindowStageCreate` 里 `resize()`:系统先按默认尺寸建窗、你的 resize 紧接着改它,用户看到的是
|
|
71
|
+
「先弹一个尺寸、随即变成另一个」,观感就是窗口莫名跳一下(这是本模板撤掉两版自定尺寸的原因)。
|
|
72
|
+
**真要固定尺寸**就自己调 `windowStage.getMainWindow().resize(w, h)`,两个坑记着:`resize()` 收的是**像素**
|
|
73
|
+
不是 vp(写 vp 量级会得到一扇很小的窗);`densityPixels` 是 **Float32**,跟 `Float64` 直接相乘编不过,
|
|
74
|
+
先化成整数百分比再算。
|
|
75
|
+
上述「系统给的就是桌面窗」的前提是 `entry/build-profile.json5` 的 `deviceTypes` 为 `2in1` 且
|
|
76
|
+
`cangjieOptions.checkDeviceTypes=false`——写成 phone/tablet 时系统按手机应用塞进竖屏兼容窗(约 600 宽)。
|
|
77
|
+
|
|
78
|
+
## 已知边界
|
|
79
|
+
|
|
80
|
+
- 只做了单窗口:`index.cj` 的 `EntryView` 挂一扇窗(label = `main`)。多窗口要按 label 各挂一个宿主。
|
|
81
|
+
- 鸿蒙侧 `javaScriptProxy` 的**返回值传不回页面**,回投靠页面心跳 + `runJavaScript` 推送
|
|
82
|
+
(已在 `index.cj` 的 `onProxyPost` 里做好,业务代码不用管)。
|
|
83
|
+
- `app.run(html)` 的 `quit()` 只置退出意图,进程仍归系统管(需要真退就 `hdc shell aa force-stop`)。
|
|
84
|
+
- 更多平台细节与踩坑:`docs/鸿蒙ArkWeb接入踩坑.md`(框架仓库内)。
|
|
@@ -154,6 +154,21 @@ if [ "$do_clean" = "1" ]; then
|
|
|
154
154
|
rm -rf "$ROOT_DIR/entry/build"
|
|
155
155
|
fi
|
|
156
156
|
|
|
157
|
+
# assets 同步:唯一真相在工程根 assets/(RFC-002 §7),构建前拷进骨架 rawfile——
|
|
158
|
+
# 页面与能力清单是 hap 的 rawfile 真文件,只改 assets 不 sync 直接构建会装出**旧页**:
|
|
159
|
+
# 页面自检照跑、改动静默丢失(2026-10-25 真机实测,探针行全无、又无失败行)。
|
|
160
|
+
# 有 sync 生成的工程根(cj-tauri.toml 在上三级)才做这一步;手工工程自行维护 rawfile。
|
|
161
|
+
APP_ROOT="$ROOT_DIR/../.."
|
|
162
|
+
if [ -f "$APP_ROOT/cj-tauri.toml" ] && [ -d "$APP_ROOT/assets" ]; then
|
|
163
|
+
RAWFILE="$ROOT_DIR/entry/src/main/resources/rawfile"
|
|
164
|
+
mkdir -p "$RAWFILE/ui" "$RAWFILE/capabilities"
|
|
165
|
+
# 先清再拷:cp -r src dst 在 dst 已存在时会把 src 拷成 dst/ui/ui/(嵌套目录),页面静默变旧
|
|
166
|
+
rm -rf "$RAWFILE/ui" "$RAWFILE/capabilities"
|
|
167
|
+
cp -r "$APP_ROOT/assets/ui" "$RAWFILE/ui"
|
|
168
|
+
cp -r "$APP_ROOT/assets/capabilities" "$RAWFILE/capabilities"
|
|
169
|
+
echo "[ohos] assets 已从工程根同步到 rawfile(ui/ + capabilities/)"
|
|
170
|
+
fi
|
|
171
|
+
|
|
157
172
|
# **必须 `--no-daemon`**:hvigor 的常驻 daemon 里 CompileCangjie 用的是它启动时那份 env,
|
|
158
173
|
# 本脚本 export 的 PATH / CANGJIE_HOME 根本进不去(表现是「手跑 cjpm 成功、hvigor 一跑就 opt 崩」)。
|
|
159
174
|
mkdir -p .buildlog
|
|
@@ -1,46 +1,46 @@
|
|
|
1
|
-
{
|
|
2
|
-
"app": {
|
|
3
|
-
/* 签名留空:模板不随包分发证书(调试证书由每台机器的 DevEco 本机生成、与华为账号绑定,
|
|
4
|
-
既不该入库也无法跨机器通用)。
|
|
5
|
-
在 DevEco 里 File → Project Structure → Signing Configs 勾上
|
|
6
|
-
「Automatically generate signature」,那一步会把 signingConfigs 填满。
|
|
7
|
-
不签名也能 `assembleHap`(产物是 *-unsigned.hap),但装不进设备。 */
|
|
8
|
-
"signingConfigs": [],
|
|
9
|
-
"products": [
|
|
10
|
-
{
|
|
11
|
-
"name": "default",
|
|
12
|
-
"targetSdkVersion": "6.1.1(24)",
|
|
13
|
-
"compatibleSdkVersion": "6.1.1(24)",
|
|
14
|
-
"runtimeOS": "HarmonyOS",
|
|
15
|
-
"buildOption": {
|
|
16
|
-
"strictMode": {
|
|
17
|
-
"caseSensitiveCheck": true,
|
|
18
|
-
"useNormalizedOHMUrl": true
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
],
|
|
23
|
-
"buildModeSet": [
|
|
24
|
-
{
|
|
25
|
-
"name": "debug",
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
"name": "release"
|
|
29
|
-
}
|
|
30
|
-
]
|
|
31
|
-
},
|
|
32
|
-
"modules": [
|
|
33
|
-
{
|
|
34
|
-
"name": "entry",
|
|
35
|
-
"srcPath": "./entry",
|
|
36
|
-
"targets": [
|
|
37
|
-
{
|
|
38
|
-
"name": "default",
|
|
39
|
-
"applyToProducts": [
|
|
40
|
-
"default"
|
|
41
|
-
]
|
|
42
|
-
}
|
|
43
|
-
]
|
|
44
|
-
}
|
|
45
|
-
]
|
|
46
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"app": {
|
|
3
|
+
/* 签名留空:模板不随包分发证书(调试证书由每台机器的 DevEco 本机生成、与华为账号绑定,
|
|
4
|
+
既不该入库也无法跨机器通用)。
|
|
5
|
+
在 DevEco 里 File → Project Structure → Signing Configs 勾上
|
|
6
|
+
「Automatically generate signature」,那一步会把 signingConfigs 填满。
|
|
7
|
+
不签名也能 `assembleHap`(产物是 *-unsigned.hap),但装不进设备。 */
|
|
8
|
+
"signingConfigs": [],
|
|
9
|
+
"products": [
|
|
10
|
+
{
|
|
11
|
+
"name": "default",
|
|
12
|
+
"targetSdkVersion": "6.1.1(24)",
|
|
13
|
+
"compatibleSdkVersion": "6.1.1(24)",
|
|
14
|
+
"runtimeOS": "HarmonyOS",
|
|
15
|
+
"buildOption": {
|
|
16
|
+
"strictMode": {
|
|
17
|
+
"caseSensitiveCheck": true,
|
|
18
|
+
"useNormalizedOHMUrl": true
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
],
|
|
23
|
+
"buildModeSet": [
|
|
24
|
+
{
|
|
25
|
+
"name": "debug",
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"name": "release"
|
|
29
|
+
}
|
|
30
|
+
]
|
|
31
|
+
},
|
|
32
|
+
"modules": [
|
|
33
|
+
{
|
|
34
|
+
"name": "entry",
|
|
35
|
+
"srcPath": "./entry",
|
|
36
|
+
"targets": [
|
|
37
|
+
{
|
|
38
|
+
"name": "default",
|
|
39
|
+
"applyToProducts": [
|
|
40
|
+
"default"
|
|
41
|
+
]
|
|
42
|
+
}
|
|
43
|
+
]
|
|
44
|
+
}
|
|
45
|
+
]
|
|
46
|
+
}
|
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
{
|
|
2
|
-
"apiType": "stageMode",
|
|
3
|
-
"buildOption": {
|
|
4
|
-
"cangjieOptions": {
|
|
5
|
-
"path": "./cjpm.toml",
|
|
6
|
-
/* 关掉「deviceTypes 只能写 phone/tablet」这条门禁(DevEco 仓颉插件的
|
|
7
|
-
cangjie-pre-build.js 里 `cangjieOptions?.checkDeviceTypes !== false` 才校验)。
|
|
8
|
-
不关的话 module.json5 写 "2in1" 会直接判 01103012(Only phone and tablet devices
|
|
9
|
-
are supported)——而只有声明 2in1,鸿蒙 PC 才按桌面应用开窗,否则塞进手机形态的
|
|
10
|
-
竖屏兼容窗(实测约 600 宽)。 */
|
|
11
|
-
"checkDeviceTypes": false
|
|
12
|
-
},
|
|
13
|
-
"nativeLib": {
|
|
14
|
-
"filter": {
|
|
15
|
-
"enableOverride": true
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
},
|
|
19
|
-
"buildOptionSet": [
|
|
20
|
-
],
|
|
21
|
-
"targets": [
|
|
22
|
-
{
|
|
23
|
-
"name": "default"
|
|
24
|
-
}
|
|
25
|
-
]
|
|
26
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"apiType": "stageMode",
|
|
3
|
+
"buildOption": {
|
|
4
|
+
"cangjieOptions": {
|
|
5
|
+
"path": "./cjpm.toml",
|
|
6
|
+
/* 关掉「deviceTypes 只能写 phone/tablet」这条门禁(DevEco 仓颉插件的
|
|
7
|
+
cangjie-pre-build.js 里 `cangjieOptions?.checkDeviceTypes !== false` 才校验)。
|
|
8
|
+
不关的话 module.json5 写 "2in1" 会直接判 01103012(Only phone and tablet devices
|
|
9
|
+
are supported)——而只有声明 2in1,鸿蒙 PC 才按桌面应用开窗,否则塞进手机形态的
|
|
10
|
+
竖屏兼容窗(实测约 600 宽)。 */
|
|
11
|
+
"checkDeviceTypes": false
|
|
12
|
+
},
|
|
13
|
+
"nativeLib": {
|
|
14
|
+
"filter": {
|
|
15
|
+
"enableOverride": true
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"buildOptionSet": [
|
|
20
|
+
],
|
|
21
|
+
"targets": [
|
|
22
|
+
{
|
|
23
|
+
"name": "default"
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
}
|