@microi.net/cli 5.8.5 → 5.8.6
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/.codebuddy-plugin/marketplace.json +2 -2
- package/.codebuddy-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/.mcp.json +1 -1
- package/.workbuddy-plugin/marketplace.json +2 -2
- package/.workbuddy-plugin/plugin.json +1 -1
- package/LICENSE +21 -21
- package/README.md +71 -71
- package/assets/build-meta.json +6 -6
- package/assets/feature-matrix.json +138 -138
- package/assets/logo.svg +4 -4
- package/cordis.patch.yml +1 -1
- package/package.json +1 -1
- package/scripts/codex-marketplace.json +20 -20
- package/scripts/mcp-codex-stdio-adapter.js +189 -189
- package/scripts/mcp-trae-windows-launcher.cmd +21 -21
- package/scripts/microi-cli-mcp.js +7 -7
- package/scripts/microi-cli.js +66 -65
- package/scripts/microi-codex-broker.js +450 -450
- package/scripts/microi-codex-router.js +618 -618
- package/scripts/microi-skills.meta.json +384 -384
- package/skills/.microi-skills-version.json +2 -2
- package/skills/.progressive-disclosure-manifest.json +3566 -3566
- package/skills/README.md +287 -287
- package/skills/ai-engine/SKILL.md +269 -265
- package/skills/ai-engine/agents/openai.yaml +4 -4
- package/skills/ai-engine/references/ai-employees.md +48 -48
- package/skills/ai-engine/references/self-hosted-digital-human.md +59 -59
- package/skills/ai-platform-governance/SKILL.md +177 -177
- package/skills/ai-platform-governance/references/progressive-01-/345/212/237/350/203/275/345/274/200/345/205/263.md +190 -190
- package/skills/app-store/SKILL.md +525 -525
- package/skills/app-store/agents/openai.yaml +4 -4
- package/skills/business-blueprint/SKILL.md +193 -193
- package/skills/datasource-engine/SKILL.md +93 -93
- package/skills/datasource-engine/agents/openai.yaml +4 -4
- package/skills/dos-orm/SKILL.md +97 -97
- package/skills/dos-orm/references/api-reference.md +229 -229
- package/skills/email-engine/SKILL.md +81 -81
- package/skills/email-engine/references/v8-email.md +34 -34
- package/skills/job-engine/SKILL.md +176 -176
- package/skills/job-engine/agents/openai.yaml +4 -4
- package/skills/message-notification/SKILL.md +156 -156
- package/skills/message-notification/agents/openai.yaml +5 -5
- package/skills/message-notification/references/contracts.md +102 -102
- package/skills/microi/SKILL.md +14 -14
- package/skills/microi-ai-app-auth.js +652 -652
- package/skills/microi-ai-application/SKILL.md +115 -115
- package/skills/microi-ai-application/agents/openai.yaml +4 -4
- package/skills/microi-ai-application/references/frontend-baseline.md +164 -164
- package/skills/microi-client-frontend/SKILL.md +244 -244
- package/skills/microi-client-frontend/references/progressive-01-3-/345/212/250/346/200/201/346/214/211/351/222/256/347/263/273/347/273/237.md +144 -144
- package/skills/microi-client-frontend/references/progressive-02-8-/350/277/220/350/241/214/346/227/266/351/253/230/351/242/221/345/235/221/345/244/215/347/233/230.md +196 -196
- package/skills/microi-client-frontend/references/progressive-03-vue3-/345/211/215/347/253/257/345/276/256/346/234/215/345/212/241/345/256/277/344/270/273/350/247/204/345/210/231.md +167 -167
- package/skills/microi-codex/SKILL.md +102 -102
- package/skills/microi-codex-installer/SKILL.md +231 -231
- package/skills/microi-codex-installer/agents/openai.yaml +7 -7
- package/skills/microi-datasource-mapping/SKILL.md +122 -122
- package/skills/microi-db-schema/SKILL.md +175 -175
- package/skills/microi-db-schema/agents/openai.yaml +4 -4
- package/skills/microi-db-schema/references/core-tables.md +695 -695
- package/skills/microi-db-schema/references/form-component-options.md +256 -256
- package/skills/microi-db-schema/references/schema-overview.md +202 -202
- package/skills/microi-db-schema/references/schema.md +646 -646
- package/skills/microi-db-schema/references/table-catalog.md +1599 -1599
- package/skills/microi-deployment/SKILL.md +221 -221
- package/skills/microi-deployment/references/deployment-matrix.md +109 -109
- package/skills/microi-docs-coverage/SKILL.md +133 -133
- package/skills/microi-docs-coverage/references/capability-map.md +91 -91
- package/skills/microi-docs-coverage/scripts/audit-doc-skill-coverage.mjs +894 -894
- package/skills/microi-form-engine/SKILL.md +333 -333
- package/skills/microi-form-engine/references/component-catalog.md +218 -218
- package/skills/microi-form-engine/references/data-source-events.md +124 -124
- package/skills/microi-form-layout/SKILL.md +205 -205
- package/skills/microi-form-layout/references/progressive-01-3-/344/270/211/347/247/215/345/210/206/347/273/204/347/232/204/345/255/230/345/202/250/344/270/216/351/205/215/347/275/256.md +235 -235
- package/skills/microi-frontend-sdk/SKILL.md +194 -194
- package/skills/microi-frontend-sdk/references/progressive-01-token-/345/275/223/345/211/215/347/231/273/345/275/225/347/224/250/346/210/267/344/270/216/345/275/223/345/211/215/347/273/210/347/253/257/347/231/273/345/275/225/345/215/217/350/256/256.md +176 -176
- package/skills/microi-left-right-layout/SKILL.md +141 -141
- package/skills/microi-microservice/SKILL.md +326 -324
- package/skills/microi-microservice/references/runtime-delivery.md +278 -278
- package/skills/microi-mobile-app-quality/SKILL.md +185 -185
- package/skills/microi-mobile-app-quality/references/progressive-01-4-/351/207/215/350/246/201/346/214/211/351/222/256/345/277/205/351/241/273/345/270/246/345/233/276/346/240/207.md +213 -213
- package/skills/microi-mobile-app-quality/references/progressive-02-9-/344/270/273/351/242/230/345/210/207/346/215/242/345/277/205/351/241/273/347/234/237/345/256/236/344/270/224/345/205/250/345/261/200/347/224/237/346/225/210.md +128 -128
- package/skills/microi-solution-quotation/SKILL.md +78 -78
- package/skills/microi-solution-quotation/agents/openai.yaml +4 -4
- package/skills/microi-solution-quotation/scripts/build_solution_quote.py +296 -296
- package/skills/microi-sso/SKILL.md +92 -92
- package/skills/microi-sso/references/acceptance.md +49 -49
- package/skills/microi-sso/references/configuration-and-security.md +53 -53
- package/skills/microi-sso/references/inbound.md +53 -53
- package/skills/microi-sso/references/outbound.md +39 -39
- package/skills/microi-system-delivery/SKILL.md +137 -137
- package/skills/microi-system-delivery/references/progressive-01-/346/240/207/345/207/206/345/267/245/344/275/234/346/265/201.md +193 -193
- package/skills/microi-system-delivery/references/progressive-02-/350/207/252/345/212/250/345/214/226/346/265/213/350/257/225/345/277/205/351/241/273/350/246/206/347/233/226/347/232/204/345/235/221.md +217 -217
- package/skills/microi-ui/SKILL.md +192 -192
- package/skills/microi-ui/references/progressive-01-/347/247/273/345/212/250/347/253/257/345/234/272/346/231/257/350/223/235/345/233/276.md +183 -183
- package/skills/microi-uniapp-frontend/SKILL.md +193 -193
- package/skills/microi-uniapp-frontend/references/progressive-01-/347/247/273/345/212/250/347/253/257/345/210/206/347/261/273-/345/217/214/346/240/217/345/210/227/350/241/250/347/213/254/347/253/213/346/273/232/345/212/250.md +225 -225
- package/skills/microi-uniapp-frontend/references/progressive-02-/345/205/263/351/224/256/344/270/232/345/212/241/350/265/204/344/272/247/344/270/215/345/276/227/351/273/230/350/256/244/351/200/211/344/270/255.md +154 -154
- package/skills/microi.v8.js +1921 -1921
- package/skills/module-engine/SKILL.md +255 -255
- package/skills/module-engine/references/module-config.md +204 -204
- package/skills/ocr-engine/SKILL.md +113 -113
- package/skills/ocr-engine/agents/openai.yaml +4 -4
- package/skills/page-engine/SKILL.md +206 -206
- package/skills/page-engine/examples/compact-dashboard.json +1444 -1444
- package/skills/page-engine/references/progressive-01-/346/211/200/346/234/211/347/273/204/344/273/266/347/261/273/345/236/213.md +234 -234
- package/skills/page-engine/references/progressive-02-/347/211/210/346/234/254/345/216/206/345/217/262-/345/271/266/345/217/221/344/277/235/345/255/230/344/270/216/345/233/236/346/273/232.md +60 -60
- package/skills/performance-testing/SKILL.md +221 -221
- package/skills/playwright-e2e/SKILL.md +196 -196
- package/skills/playwright-e2e/references/progressive-01-/345/205/250/350/207/252/345/212/250/347/231/273/345/275/225-/345/205/215/351/252/214/350/257/201/347/240/201-/344/275/206/344/270/215/345/205/215/345/257/206/347/240/201-/345/277/205/350/257/273.md +173 -173
- package/skills/playwright-e2e/references/progressive-02-/346/226/207/345/255/227/345/257/271/346/257/224/345/272/246/344/270/216/345/217/257/350/257/273/346/200/247/350/207/252/345/212/250/345/214/226/346/243/200/346/237/245-/345/277/205/345/201/232.md +183 -183
- package/skills/playwright-e2e/references/progressive-03-microi-helper-/346/250/241/346/235/277.md +221 -221
- package/skills/playwright-e2e/references/progressive-04-ci-/345/273/272/350/256/256.md +115 -115
- package/skills/print-engine/SKILL.md +259 -259
- package/skills/production-readonly-audit/SKILL.md +41 -41
- package/skills/report-engine/SKILL.md +71 -71
- package/skills/report-engine/agents/openai.yaml +4 -4
- package/skills/scripts/optimize-progressive-disclosure.mjs +204 -204
- package/skills/scripts/refresh-progressive-disclosure.mjs +64 -64
- package/skills/scripts/sync-embedded-skills.mjs +46 -46
- package/skills/scripts/validate-progressive-disclosure.mjs +57 -57
- package/skills/search-engine/SKILL.md +75 -75
- package/skills/search-engine/agents/openai.yaml +4 -4
- package/skills/spider-engine/SKILL.md +190 -190
- package/skills/system-observability/SKILL.md +248 -248
- package/skills/system-observability/references/memory-incident-triage.md +77 -77
- package/skills/translate-engine/SKILL.md +140 -140
- package/skills/translate-engine/agents/openai.yaml +4 -4
- package/skills/ui-design/SKILL.md +223 -223
- package/skills/ui-design/assets/pattern-showcase/app.js +54 -54
- package/skills/ui-design/assets/pattern-showcase/index.html +163 -163
- package/skills/ui-design/assets/pattern-showcase/styles.css +311 -311
- package/skills/ui-design/assets/templates/MCI-DESIGN.md +206 -206
- package/skills/ui-design/references/design-pattern-library.md +184 -184
- package/skills/ui-design/references/mci-design-contract.md +163 -163
- package/skills/ui-design/references/motion-and-media.md +78 -78
- package/skills/ui-design/references/product-flow-recipes.md +94 -94
- package/skills/ui-design/references/progressive-01-/351/242/234/350/211/262/344/275/223/347/263/273-css-variables-/346/224/257/346/214/201/344/270/273/351/242/230/345/210/207/346/215/242.md +218 -218
- package/skills/ui-design/references/progressive-02-/345/255/227/344/275/223.md +164 -164
- package/skills/ui-design/references/progressive-03-/345/212/250/346/225/210/350/247/204/350/214/203-/344/270/260/345/257/214/344/275/206/344/270/215/345/215/241.md +235 -235
- package/skills/ui-design/references/progressive-04-/347/273/204/344/273/266/351/243/216/346/240/274/351/200/237/346/237/245.md +152 -152
- package/skills/ui-design/references/progressive-05-/347/247/273/345/212/250/347/253/257/344/270/223/347/224/250/350/247/204/350/214/203.md +238 -238
- package/skills/ui-design/references/progressive-06-/344/270/273/351/242/230/345/210/207/346/215/242/345/256/236/347/216/260.md +194 -194
- package/skills/ui-design/references/progressive-07-/351/200/237/346/237/245-/344/273/216/345/244/264/346/220/255/345/273/272/344/270/200/344/270/252/347/247/273/345/212/250/347/253/257/351/241/265/351/235/242.md +207 -207
- package/skills/ui-design/references/progressive-08-/350/241/250/345/215/225/345/210/206/347/273/204/350/247/204/350/214/203-tabs-vs-collapsegroup-/345/274/272/345/210/266.md +142 -142
- package/skills/uniapp-mall-assets/SKILL.md +176 -176
- package/skills/unity-integration/SKILL.md +171 -171
- package/skills/unity-integration/agents/openai.yaml +4 -4
- package/skills/unity-integration/references/ai-app-delivery.md +119 -119
- package/skills/unity-integration/references/sdk-api.md +82 -82
- package/skills/unity-integration/references/toolbox-migration.md +66 -66
- package/skills/unity-integration/references/webgl-hosting.md +57 -57
- package/skills/v8-api-config/SKILL.md +388 -388
- package/skills/v8-cache-pattern/SKILL.md +312 -312
- package/skills/v8-crud-api/SKILL.md +178 -178
- package/skills/v8-crud-api/references/progressive-01-/346/237/245/350/257/242/345/210/227/350/241/250-/345/210/206/351/241/265.md +226 -226
- package/skills/v8-crud-api/references/progressive-02-where-/346/235/241/344/273/266/350/257/255/346/263/225/351/200/237/346/237/245.md +49 -49
- package/skills/v8-debugging/SKILL.md +284 -284
- package/skills/v8-explorer-tree/SKILL.md +228 -228
- package/skills/v8-export-import/SKILL.md +219 -219
- package/skills/v8-export-import/references/progressive-01-excellayout-/351/253/230/347/272/247/350/207/252/347/224/261/345/270/203/345/261/200.md +211 -211
- package/skills/v8-export-import/references/progressive-02-powerpoint-/345/257/274/345/207/272.md +202 -202
- package/skills/v8-export-import/references/progressive-03-/345/256/211/345/205/250-/346/200/247/350/203/275/346/263/250/346/204/217.md +42 -42
- package/skills/v8-file-upload/SKILL.md +284 -284
- package/skills/v8-file-upload/references/progressive-01-/345/205/254/346/234/211/346/241/266-vs-/347/247/201/346/234/211/346/241/266.md +263 -263
- package/skills/v8-file-upload/references/progressive-02-office-/346/226/207/344/273/266/345/234/250/347/272/277/347/274/226/350/276/221/347/211/210/346/234/254/345/217/267/350/247/204/345/210/231.md +161 -161
- package/skills/v8-formengine-http/SKILL.md +238 -238
- package/skills/v8-frontend-events/SKILL.md +180 -180
- package/skills/v8-frontend-events/references/bluetooth-print-api.md +135 -135
- package/skills/v8-frontend-events/references/bluetooth-print.md +258 -258
- package/skills/v8-frontend-events/references/progressive-01-/345/210/227/350/241/250/344/272/213/344/273/266.md +219 -219
- package/skills/v8-http-integration/SKILL.md +182 -182
- package/skills/v8-http-integration/references/progressive-01-get-/350/257/267/346/261/202.md +220 -220
- package/skills/v8-http-integration/references/progressive-02-/351/224/231/350/257/257/345/244/204/347/220/206/346/250/241/345/274/217.md +44 -44
- package/skills/v8-image-processing/SKILL.md +190 -190
- package/skills/v8-image-processing/agents/openai.yaml +4 -4
- package/skills/v8-image-processing/references/api-reference.md +623 -623
- package/skills/v8-menu-buttons/SKILL.md +186 -186
- package/skills/v8-menu-buttons/references/progressive-01-2-/346/214/211/351/222/256/345/257/271/350/261/241-schema.md +222 -222
- package/skills/v8-menu-buttons/references/progressive-02-8-/346/250/241/345/274/217-f-/345/220/216/345/217/260/344/273/273/345/212/241/346/214/211/351/222/256-/351/225/277/344/273/273/345/212/241.md +228 -228
- package/skills/v8-menu-buttons/references/progressive-03-10-/345/217/215/346/250/241/345/274/217-/351/201/277/345/205/215.md +104 -104
- package/skills/v8-mongodb/SKILL.md +200 -200
- package/skills/v8-mq-mqtt/SKILL.md +176 -176
- package/skills/v8-mq-mqtt/references/mqtt-production.md +342 -342
- package/skills/v8-mq-mqtt/references/progressive-01-v8-mqtt-iot-/347/211/251/350/201/224/347/275/221.md +181 -181
- package/skills/v8-mq-mqtt/scripts/check-mqtt-skill-coverage.mjs +203 -203
- package/skills/v8-saas-multi-tenant/SKILL.md +305 -305
- package/skills/v8-security/SKILL.md +210 -210
- package/skills/v8-security/references/progressive-01-2-/346/235/203/351/231/220/346/240/241/351/252/214.md +200 -200
- package/skills/v8-security/references/progressive-02-7-/346/227/245/345/277/227/350/256/260/345/275/225.md +160 -160
- package/skills/v8-sql-query/SKILL.md +302 -302
- package/skills/v8-table-event/SKILL.md +176 -176
- package/skills/v8-table-event/references/progressive-01-informv8-js-/350/241/250/345/215/225/346/211/223/345/274/200/344/272/213/344/273/266.md +216 -216
- package/skills/v8-table-event/references/progressive-02-/345/211/215/347/253/257/344/272/213/344/273/266/345/220/215-v8-eventname-/345/217/257/350/203/275/347/232/204/345/200/274.md +46 -46
- package/skills/v8-tcp-integration/SKILL.md +147 -147
- package/skills/v8-tcp-integration/agents/openai.yaml +4 -4
- package/skills/v8-template-engine/SKILL.md +167 -167
- package/skills/v8-utilities/SKILL.md +104 -104
- package/skills/v8-utilities/references/client-api-index.md +143 -143
- package/skills/v8-utilities/references/platform-http-routes.md +83 -83
- package/skills/v8-utilities/references/server-api-index.md +188 -188
- package/skills/v8-workflow/SKILL.md +252 -252
- package/skills/v8-workflow/references/progressive-01-/350/212/202/347/202/271/345/274/200/345/247/213-v8-/344/272/213/344/273/266.md +180 -180
- package/skills/v8-workflow/references/workflow-configuration.md +49 -49
- package/skills/vision-engine/SKILL.md +160 -160
- package/skills/vision-engine/agents/openai.yaml +4 -4
- package/skills/vision-engine/references/architecture-and-acceptance.md +194 -194
- package/skills/workspace-conventions/SKILL.md +273 -273
- package/skills/workspace-conventions/references/progressive-01-/347/211/210/346/234/254/346/233/264/346/226/260/346/227/245/345/277/227/344/277/235/346/212/244/350/247/204/345/210/231-/345/274/272/345/210/266.md +209 -209
- package/skills/workspace-conventions/references/progressive-02-microi-net-api-/346/234/254/345/234/260/345/220/257/345/212/250/347/272/246/345/256/232.md +217 -217
- package/skills/workspace-conventions/references/progressive-03-cli-/344/270/216-ide-/346/217/222/344/273/266/351/224/231/347/211/210/345/205/261/345/255/230/347/272/246/345/256/232.md +27 -27
|
@@ -1,258 +1,258 @@
|
|
|
1
|
-
# V8.Print 蓝牙打印运行指南(GP-M322 / ZICOX CC4)
|
|
2
|
-
|
|
3
|
-
本参考用于 Microi 前端 V8 的 BLE/SPP 标签和小票打印。运行时事实源为
|
|
4
|
-
`Microi.Client/src/utils/v8-print.js`,型号与协议适配事实源为
|
|
5
|
-
`Microi.Client/src/utils/ble/printer-compatibility.js`,指令方法事实源见
|
|
6
|
-
[`bluetooth-print-api.md`](bluetooth-print-api.md)。官网旧业务示例不能作为当前连接语义。
|
|
7
|
-
|
|
8
|
-
## 目录
|
|
9
|
-
|
|
10
|
-
- [前端挂载范围](#前端挂载范围)
|
|
11
|
-
- [微服务中的平台普通打印桥](#微服务中的平台普通打印桥)
|
|
12
|
-
- [运行环境与能力判断](#运行环境与能力判断)
|
|
13
|
-
- [双型号兼容契约](#双型号兼容契约)
|
|
14
|
-
- [连接与发送语义](#连接与发送语义)
|
|
15
|
-
- [最小安全流程](#最小安全流程)
|
|
16
|
-
- [批量打印与恢复](#批量打印与恢复)
|
|
17
|
-
- [兼容性与当前限制](#兼容性与当前限制)
|
|
18
|
-
- [安全边界](#安全边界)
|
|
19
|
-
- [实机验收](#实机验收)
|
|
20
|
-
|
|
21
|
-
## 前端挂载范围
|
|
22
|
-
|
|
23
|
-
当前主前端有三层真实挂载,均调用幂等的 `initV8Print(V8)`:
|
|
24
|
-
|
|
25
|
-
| 源码位置 | 覆盖的 V8 场景 |
|
|
26
|
-
|---|---|
|
|
27
|
-
| `src/utils/diy.common.js` | 通用前端 V8 基础对象和常规按钮流程 |
|
|
28
|
-
| `src/views/form-engine/diy-form.vue` | 表单、字段及表单按钮 V8 |
|
|
29
|
-
| `src/views/form-engine/diy-table.vue` | 列表、菜单按钮、行按钮等表格 V8 |
|
|
30
|
-
|
|
31
|
-
因此不要再从租户脚本导入 `tsc.js`、`esc.js` 或自行挂载 `V8.Print`。这些能力只在
|
|
32
|
-
Microi 浏览器/5+App 前端 V8 中可用,不属于后端接口引擎、后端表单事件或微信小程序
|
|
33
|
-
原生 BLE API。
|
|
34
|
-
|
|
35
|
-
三个入口都会取得同一个应用级 `Print` 单例。分包游标、打印份数和连接引用仍是可变状态,
|
|
36
|
-
但 `prepareSend` 已把所有前端 V8 上下文排进同一条运行时发送队列。业务代码仍应逐次
|
|
37
|
-
`await` 保持明确的结果顺序,不能认为不同按钮或不同 V8 对象彼此隔离。
|
|
38
|
-
|
|
39
|
-
PC/平板顶部导航和移动端【我的】页的蓝牙入口也使用该单例:它们展示实时连接状态和设备名,
|
|
40
|
-
点击后复用 `OpenBluetoothPage()`,因此用户可以先在全局入口连接,再进入任意模块执行 V8 打印。
|
|
41
|
-
|
|
42
|
-
## 微服务中的平台普通打印桥
|
|
43
|
-
|
|
44
|
-
隔离运行的 MicroService 不能直接访问父页面 `V8.Print`、Vue 组件或打印弹窗。微服务页面需要
|
|
45
|
-
提供“普通打印”时,调用 `microi.host.v1` 的 `openPlatformPrint` 宿主动作;参数为当前租户
|
|
46
|
-
`mic_print.Id`、标题,以及当前 `apiBase` 同源、路径以 `/apiengine/` 开头并明确携带同一
|
|
47
|
-
`OsClient` 的绝对数据地址。禁止把 Token、帐号密码或其它凭据放进 URL。
|
|
48
|
-
|
|
49
|
-
`openPlatformPrint` 只打开 Print Engine 预览,不发送 TSPL/CPCL/ESC-POS;它不是蓝牙代理,
|
|
50
|
-
也不发送 BLE/SPP 字节。
|
|
51
|
-
宿主返回 `accepted:true` 只表示预览已打开,不代表浏览器已打印或打印机已出纸。独立运行没有
|
|
52
|
-
宿主能力时应隐藏/禁用该入口。完整调用示例与结果协议见
|
|
53
|
-
`../../microi-microservice/references/runtime-delivery.md` 的“微服务调用平台普通打印”。
|
|
54
|
-
|
|
55
|
-
## 运行环境与能力判断
|
|
56
|
-
|
|
57
|
-
| 运行环境 | 当前引擎 | 结论 |
|
|
58
|
-
|---|---|---|
|
|
59
|
-
| Android 5+App | `plus.bluetooth` + `plus.android` | BLE;ZICOX CC4 可回退到已配对 RFCOMM/SPP;Android 12+ 需要附近设备权限 |
|
|
60
|
-
| iOS 5+App | `plus.bluetooth` | BLE,不使用 Android SPP |
|
|
61
|
-
| 存在 `navigator.bluetooth.requestDevice` 的浏览器 | Web Bluetooth | 支持;通常要求安全上下文和用户手势 |
|
|
62
|
-
| 其它普通 H5/浏览器 | 无 | `V8.Print` 仍可能存在,但连接页会提示能力不可用 |
|
|
63
|
-
| 微信小程序原生 BLE | 不属于此模块 | 需要小程序/UniApp 侧专用实现 |
|
|
64
|
-
|
|
65
|
-
不要用 `V8.ClientType === 'PC'` 判断蓝牙能力,也不要只检查
|
|
66
|
-
`BLEInformation.deviceId`。正确顺序是检查 `V8.Print`、调用 `isConnected()`,再在
|
|
67
|
-
用户点击事件中 `await OpenBluetoothPage()`。
|
|
68
|
-
|
|
69
|
-
Android 12+ 宿主必须启用 DCloud Bluetooth 模块并声明 `BLUETOOTH_SCAN`、
|
|
70
|
-
`BLUETOOTH_CONNECT`。运行时只在用户主动点击“搜索”时申请,不得在页面初始化或自动重连
|
|
71
|
-
时弹授权框;拒绝或永久拒绝要引导用户进入系统“附近的设备”权限设置。
|
|
72
|
-
|
|
73
|
-
浏览器模板、PDF、A4 单据和 Print Engine JSON 属于 `print-engine`;TSC/TSPL 或
|
|
74
|
-
CPCL/ESC/POS 原生字节通过 BLE/SPP 写入才属于 `V8.Print`。
|
|
75
|
-
|
|
76
|
-
## 双型号兼容契约
|
|
77
|
-
|
|
78
|
-
| 型号 | 标签协议 | 传输 | 兼容承诺 |
|
|
79
|
-
|---|---|---|---|
|
|
80
|
-
| 佳博 GP-M322 | TSPL | BLE | `createNew().getData()` 原字节发送,协议适配层不得改写 |
|
|
81
|
-
| ZICOX CC4 | CPCL | BLE 优先,Android SPP 兜底 | 同一份标准 TSC 高层调用在首包写入前转换为 CPCL |
|
|
82
|
-
| 其它 TSPL | TSPL | BLE | 保持原字节路径 |
|
|
83
|
-
|
|
84
|
-
`createNewESC()` 在 CC4 上也原样发送,因为厂家声明 CC4 支持 ESC/POS。不要根据厂家 Demo
|
|
85
|
-
里存在测试字符串就擅自宣称其它协议;以产品页、准确手册和实机固件为准。
|
|
86
|
-
|
|
87
|
-
TSC 构建器给字节数组附加不可枚举的操作元数据,因此 GP 字节值、长度与数组枚举完全不变。
|
|
88
|
-
CC4 必须直接收到同一次 `getData()` 返回值;`Array.from`、展开、JSON 序列化等复制会丢失
|
|
89
|
-
元数据并失败关闭。适配器先完成整份转换和校验,再开始分包;不支持的命令不得产生半张输出。
|
|
90
|
-
|
|
91
|
-
CC4 可转换:纸张尺寸、速度、浓度、间隙/黑标、前后走纸、方向 0/1、参考点、线/框/反相、
|
|
92
|
-
文字、条码、二维码、位图及单次 `setPagePrint`。`init`/`setCls` 无需输出。原始 `addCommand`、
|
|
93
|
-
国家/代码页、`setFromfeed`、`setHome`、蜂鸣、限位、擦除和未知方法没有足够等价语义,必须
|
|
94
|
-
在首包写入前拒绝。扩展白名单前要同时增加协议单测和两台目标机回归。
|
|
95
|
-
|
|
96
|
-
Android SPP 与厂家 Demo 一致,优先 RFCOMM 通道 1,再以标准 UUID
|
|
97
|
-
`00001101-0000-1000-8000-00805F9B34FB` 兜底。自动模式只显示名称可识别为 CC4 的已配对
|
|
98
|
-
经典设备;广播名不规范时,用户先手工选择 `zicox-cc4`。Web Bluetooth 不能访问 SPP。
|
|
99
|
-
|
|
100
|
-
## 连接与发送语义
|
|
101
|
-
|
|
102
|
-
| API | 当前真实语义 |
|
|
103
|
-
|---|---|
|
|
104
|
-
| `createNew()` | 新建 TSC/TSPL 标签指令构建器 |
|
|
105
|
-
| `createNewESC()` | 新建 ESC/POS 小票指令构建器 |
|
|
106
|
-
| `OpenBluetoothPage()` | 返回 `Promise<boolean>`;在连接弹窗关闭时解析,重复打开复用同一个 Promise |
|
|
107
|
-
| `isConnected()` | Web 端检查实时 GATT 与写特征;5+App 结合连接事件在线标记与设备/写特征 ID |
|
|
108
|
-
| `reconnect()` | 使用已记住的设备 ID 或浏览器保留的设备授权重连,不弹选择框 |
|
|
109
|
-
| `getConnectionState()` | 返回可展示的连接、记忆、设备、错误和重连状态快照 |
|
|
110
|
-
| `subscribeConnection(listener)` | 立即回调当前快照并持续通知状态变化,返回取消订阅函数 |
|
|
111
|
-
| `getPrinterProfile()` | 返回最终型号、标签指令和传输偏好;普通业务无需调用 |
|
|
112
|
-
| `setPrinterProfile(mode)` | 手工选 `gprinter-gp-m322`、`zicox-cc4`、`generic-tspl`,或恢复 `auto` |
|
|
113
|
-
| `prepareSend(bytes)` | 先恢复连接、完成型号协议适配,再进入应用级队列按包串行写入 |
|
|
114
|
-
| `Send(bytes)` | 依赖 `prepareSend` 已设置的内部游标,属于内部状态机入口,业务代码不要直接调用 |
|
|
115
|
-
| `setOneTimeData(bytes)` | 设置 BLE 包长;只接受 1–512 整数,连接页候选 20–190,默认 20 |
|
|
116
|
-
| `setPrinterNum(num)` | 重复发送同一缓冲区;只接受 1–99 整数,连接页候选 1–9 |
|
|
117
|
-
| `disconnect()` | 主动断开、停止自动重连并忘记当前设备 |
|
|
118
|
-
| `BLEInformation` | 最近设备/型号/通道/服务/特征元数据,只用于诊断,不代表实时连接或打印回执 |
|
|
119
|
-
|
|
120
|
-
`getConnectionState()` 额外含 `transport`、`profileMode`、`profileId`、`profileName`、
|
|
121
|
-
`commandLanguage`;前端展示可以使用,打印判断仍使用 `isConnected()`。
|
|
122
|
-
|
|
123
|
-
`OpenBluetoothPage()` 不是“连接成功事件”;用户连上设备后仍要关闭弹窗,调用方才能继续。
|
|
124
|
-
设备元数据会写入 `localStorage` 与兼容用 `sessionStorage`。应用初始化、页面恢复、重新获得
|
|
125
|
-
焦点和意外断线时会做有限次数自动重连:5+App 使用设备 ID;Web 端只有浏览器保留授权且
|
|
126
|
-
支持 `navigator.bluetooth.getDevices()` 时才可无弹窗恢复。系统蓝牙、浏览器权限、设备电源、
|
|
127
|
-
休眠、距离等仍会造成真实断线;重试结束后必须让用户从全局入口重新选择。
|
|
128
|
-
|
|
129
|
-
## 最小安全流程
|
|
130
|
-
|
|
131
|
-
```javascript
|
|
132
|
-
function cleanCommandText(value, maxLength) {
|
|
133
|
-
return String(value == null ? '' : value)
|
|
134
|
-
.replace(/[\r\n"\x00-\x1f]/g, ' ')
|
|
135
|
-
.slice(0, maxLength || 120);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
async function ensurePrinterConnected() {
|
|
139
|
-
if (!V8.Print) throw new Error('当前前端未加载蓝牙打印能力');
|
|
140
|
-
if (V8.Print.isConnected()) return;
|
|
141
|
-
|
|
142
|
-
var connected = await V8.Print.reconnect();
|
|
143
|
-
if (!connected) connected = await V8.Print.OpenBluetoothPage();
|
|
144
|
-
if (!connected || !V8.Print.isConnected()) {
|
|
145
|
-
throw new Error('未连接蓝牙打印机');
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
async function printLabel(order) {
|
|
150
|
-
await ensurePrinterConnected();
|
|
151
|
-
|
|
152
|
-
var cmd = V8.Print.createNew();
|
|
153
|
-
cmd.setSize(60, 40);
|
|
154
|
-
cmd.setGap(2);
|
|
155
|
-
cmd.setSpeed(4);
|
|
156
|
-
cmd.setDensity(8);
|
|
157
|
-
cmd.setDirection(1);
|
|
158
|
-
cmd.setCls();
|
|
159
|
-
cmd.setText(20, 20, 'TSS24.BF2', 1, 1, cleanCommandText(order.Name, 40));
|
|
160
|
-
cmd.setBarCode(20, 80, '128', 60, 1, 2, 2, cleanCommandText(order.Code, 40));
|
|
161
|
-
cmd.setQR(340, 30, 'L', 5, 'A', cleanCommandText(order.Id, 120));
|
|
162
|
-
cmd.setPagePrint();
|
|
163
|
-
|
|
164
|
-
await V8.Print.prepareSend(cmd.getData());
|
|
165
|
-
}
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
同一段标签代码在 GP-M322 上保持 TSPL,在 CC4 上转换为 CPCL。ESC/POS 小票使用
|
|
169
|
-
`createNewESC()`,完整顺序和 25 个真实方法见
|
|
170
|
-
[`bluetooth-print-api.md`](bluetooth-print-api.md)。发送成功只表示 BLE/SPP 写调用完成,不能
|
|
171
|
-
写成“打印机已走纸”或“物理打印成功”。当前源码虽发现 read/notify 特征,但没有订阅状态
|
|
172
|
-
通知,也没有消费 ACK、缺纸或故障回执。
|
|
173
|
-
|
|
174
|
-
## 批量打印与恢复
|
|
175
|
-
|
|
176
|
-
```javascript
|
|
177
|
-
async function printBatch(rows, startIndex) {
|
|
178
|
-
var list = Array.isArray(rows) ? rows : [];
|
|
179
|
-
var begin = Math.max(0, Number(startIndex || 0));
|
|
180
|
-
var limit = Math.min(list.length, begin + 100);
|
|
181
|
-
|
|
182
|
-
for (var i = begin; i < limit; i++) {
|
|
183
|
-
try {
|
|
184
|
-
await printLabel(list[i]);
|
|
185
|
-
V8.Tips('已发送 ' + (i + 1) + '/' + list.length, true);
|
|
186
|
-
} catch (error) {
|
|
187
|
-
return {
|
|
188
|
-
Code: 0,
|
|
189
|
-
Msg: '第 ' + (i + 1) + ' 条发送失败:' + (error.message || error),
|
|
190
|
-
NextIndex: i
|
|
191
|
-
};
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
return { Code: 1, Data: { NextIndex: limit, HasMore: limit < list.length } };
|
|
196
|
-
}
|
|
197
|
-
```
|
|
198
|
-
|
|
199
|
-
- 不用固定 `setTimeout(3000)` 猜测上一张是否完成。
|
|
200
|
-
- 不用 `Promise.all` 表达同一设备的并行打印。运行时会把同时到达的调用排队,但业务仍应逐条
|
|
201
|
-
`await`,以便准确记录哪一条成功或失败。
|
|
202
|
-
- 大批次分段并持久化 `NextIndex`;页面关闭、断连或写失败后从失败位置人工确认再恢复。
|
|
203
|
-
- `setPrinterNum(n)` 只适合同一缓冲区重复发送,不适合每张内容不同的批次。
|
|
204
|
-
- 业务落库与蓝牙打印不是原子事务。用稳定业务单号支持受控重打,不重复执行业务写入。
|
|
205
|
-
|
|
206
|
-
## 兼容性与当前限制
|
|
207
|
-
|
|
208
|
-
- Web Bluetooth 仅把四个常见服务 UUID 传入 `optionalServices`:`18f0`、`ff00`、
|
|
209
|
-
`49535343-fe7d-4ae5-8fa9-9fafd205e455`、`e7810a71-73ae-499d-8c15-faa9aef0c3f2`。
|
|
210
|
-
当前没有公开的自定义服务配置,并选择枚举到的第一个可写特征;其它型号可能需要扩展源码。
|
|
211
|
-
CC4 固件若只开放 SPP 或使用其它私有 UUID,Web 端不可连接;Android 5+App 使用已配对 SPP,
|
|
212
|
-
或先取得厂家准确 BLE UUID 再扩展源码,禁止猜 UUID。
|
|
213
|
-
- `prepareSend` 默认每包 20 字节;Android 5+ 的佳博 GP-M322 在特征支持时优先使用同一
|
|
214
|
-
`plus.bluetooth` 连接的 `writeNoResponse`,逐包 await API 回调并保留约 8ms 的 GATT 保护窗口;
|
|
215
|
-
即使协商出 180 字节有效载荷也只采用 100 字节稳定档。不支持无响应写时保留 `write` 兼容路径。其它型号、iOS、Web 与 SPP
|
|
216
|
-
保留约 20ms,同一缓冲区多份间约 100ms。5+ BLE 的连接、服务发现和写入统一使用 `plus.bluetooth`,
|
|
217
|
-
禁止用 `uni.writeBLECharacteristicValue` 写入由 `plus.bluetooth` 建立的连接。
|
|
218
|
-
这是写节奏,不是物理走纸确认。5+ BLE 同时受本次连接的 `maxWriteBytes` 和更保守的
|
|
219
|
-
`recommendedPacketSize` 限制;未知 MTU 为 20。
|
|
220
|
-
- 5+ 佳博在服务发现后协商 MTU,最多等待 1.5 秒,`getConnectionState()` 返回 `mtu`、
|
|
221
|
-
`maxWriteBytes`、`recommendedPacketSize`(20/100)、`writeType`、`packetIntervalMs`。
|
|
222
|
-
必须读取真实回调的 `mtu`;空成功、失败、超时或缺 API 不可按请求值升档,迟到回调不得提升能力,
|
|
223
|
-
断开时清除能力。自定义微服务需按这些字段判断,不能只允许 `engine === 'web'`。
|
|
224
|
-
`microi.app` 在线壳更新远程前端即可获取本修复;WebView 缺少 Web Bluetooth 时不增加无效切换选项。
|
|
225
|
-
- 当前分包公式使用 `Math.ceil(length / packetSize)`,长度恰好整除时不会产生 0 字节末包;
|
|
226
|
-
空数据、非法包长和非法份数会直接抛错。合法数值仍须按目标打印机实测。
|
|
227
|
-
- TSC 与 ESC 文本使用仓库内置 `encoding.js` + `encoding-indexes.js` 转为 GB18030,运行时
|
|
228
|
-
不请求网络。编码成功不等于打印机字体、代码页和固件支持全部字符;Emoji 等仍需实机验证。
|
|
229
|
-
- `setBitmap` 接受 ImageData 风格 `{ width, height, data }` RGBA 数据。当前黑白转换较简单,
|
|
230
|
-
大图可能产生大缓冲区;先缩放、二值化并用小图测试。
|
|
231
|
-
- `V8.Print` 使用应用级共享发送队列,跨 V8 上下文不会再并发覆盖 `currentTime`、`looptime`、
|
|
232
|
-
`lastData` 等共享状态。队列只保证写入顺序,不提供打印机 ACK、业务事务或自动重打语义。
|
|
233
|
-
- CC4 遇到不支持的方法、复制后丢失元数据、缺少或重复 `setPagePrint()` 时应零写入失败;不要
|
|
234
|
-
在业务层捕获后把原 TSPL 盲目重发给 CC4。
|
|
235
|
-
|
|
236
|
-
## 安全边界
|
|
237
|
-
|
|
238
|
-
- TSC 的 `setText`、`setQR`、`setBarCode` 和 `addCommand` 会拼协议文本。移除引号、换行、
|
|
239
|
-
NUL/控制字符并限制长度;`addCommand` 只接受固定、受审查的命令。
|
|
240
|
-
- 蓝牙设备名称、ID 和服务特征均是外部输入。不要拼入 `innerHTML`,展示时做文本转义;不要
|
|
241
|
-
记录或上传完整 `BLEInformation`,以免泄露终端指纹。
|
|
242
|
-
- 金额、数量、坐标、纸张尺寸、包长和份数先做类型/范围校验,避免无限循环或超大缓冲区。
|
|
243
|
-
- 打印内容含个人信息、票据或密钥时,不写控制台、系统日志或异常上报正文。
|
|
244
|
-
- 浏览器权限拒绝、用户取消、GATT 断开、找不到服务/特征和写包失败都必须可理解地提示。
|
|
245
|
-
- 搜索不到设备的头号原因是残留 GATT 连接:BLE 外设在已连接期间停止广播,上一次连接被并发流程打断或 App 重启后系统仍保留旧链路时,打印机“没在用”但也搜不到。平台在开始发现前会先 `getConnectedBluetoothDevices` 并关闭应用未持有的连接,被断开/重连事件接管时也会显式关闭自己建立的链路;排查顺序据此固定为“清理残留连接 → 打印机重新上电 → 系统蓝牙忽略设备 → 再搜索”,不要先去改包长、MTU 或指令集。
|
|
246
|
-
|
|
247
|
-
## 实机验收
|
|
248
|
-
|
|
249
|
-
至少记录:
|
|
250
|
-
|
|
251
|
-
1. GP-M322 与 CC4 的固件、纸张规格、服务/写特征 UUID 或 SPP、指令集。
|
|
252
|
-
2. 5+App 或浏览器版本;首次授权/配对、自动/手工选型、再次连接、主动断开、页面刷新和断线重连。
|
|
253
|
-
3. 中文、数字、特殊字符、二维码、条码、长文本、图片和边界金额。
|
|
254
|
-
4. 默认 20 字节与目标包长;同时覆盖“长度恰好整除包长”。
|
|
255
|
-
5. 连续 20 张严格串行发送,无乱序、丢包、重复或任务状态互相污染。
|
|
256
|
-
6. 中途关机、缺纸、离开范围、权限撤销后的失败位置与恢复行为。
|
|
257
|
-
7. 两种设备交替连接,证明 GP 原 TSPL 不变、CC4 收到 CPCL/ESC-POS;CC4 分别记录 BLE 与 SPP。
|
|
258
|
-
8. 页面只确认“数据已发送”;若业务要求确认物理结果,另接状态回读或人工确认。
|
|
1
|
+
# V8.Print 蓝牙打印运行指南(GP-M322 / ZICOX CC4)
|
|
2
|
+
|
|
3
|
+
本参考用于 Microi 前端 V8 的 BLE/SPP 标签和小票打印。运行时事实源为
|
|
4
|
+
`Microi.Client/src/utils/v8-print.js`,型号与协议适配事实源为
|
|
5
|
+
`Microi.Client/src/utils/ble/printer-compatibility.js`,指令方法事实源见
|
|
6
|
+
[`bluetooth-print-api.md`](bluetooth-print-api.md)。官网旧业务示例不能作为当前连接语义。
|
|
7
|
+
|
|
8
|
+
## 目录
|
|
9
|
+
|
|
10
|
+
- [前端挂载范围](#前端挂载范围)
|
|
11
|
+
- [微服务中的平台普通打印桥](#微服务中的平台普通打印桥)
|
|
12
|
+
- [运行环境与能力判断](#运行环境与能力判断)
|
|
13
|
+
- [双型号兼容契约](#双型号兼容契约)
|
|
14
|
+
- [连接与发送语义](#连接与发送语义)
|
|
15
|
+
- [最小安全流程](#最小安全流程)
|
|
16
|
+
- [批量打印与恢复](#批量打印与恢复)
|
|
17
|
+
- [兼容性与当前限制](#兼容性与当前限制)
|
|
18
|
+
- [安全边界](#安全边界)
|
|
19
|
+
- [实机验收](#实机验收)
|
|
20
|
+
|
|
21
|
+
## 前端挂载范围
|
|
22
|
+
|
|
23
|
+
当前主前端有三层真实挂载,均调用幂等的 `initV8Print(V8)`:
|
|
24
|
+
|
|
25
|
+
| 源码位置 | 覆盖的 V8 场景 |
|
|
26
|
+
|---|---|
|
|
27
|
+
| `src/utils/diy.common.js` | 通用前端 V8 基础对象和常规按钮流程 |
|
|
28
|
+
| `src/views/form-engine/diy-form.vue` | 表单、字段及表单按钮 V8 |
|
|
29
|
+
| `src/views/form-engine/diy-table.vue` | 列表、菜单按钮、行按钮等表格 V8 |
|
|
30
|
+
|
|
31
|
+
因此不要再从租户脚本导入 `tsc.js`、`esc.js` 或自行挂载 `V8.Print`。这些能力只在
|
|
32
|
+
Microi 浏览器/5+App 前端 V8 中可用,不属于后端接口引擎、后端表单事件或微信小程序
|
|
33
|
+
原生 BLE API。
|
|
34
|
+
|
|
35
|
+
三个入口都会取得同一个应用级 `Print` 单例。分包游标、打印份数和连接引用仍是可变状态,
|
|
36
|
+
但 `prepareSend` 已把所有前端 V8 上下文排进同一条运行时发送队列。业务代码仍应逐次
|
|
37
|
+
`await` 保持明确的结果顺序,不能认为不同按钮或不同 V8 对象彼此隔离。
|
|
38
|
+
|
|
39
|
+
PC/平板顶部导航和移动端【我的】页的蓝牙入口也使用该单例:它们展示实时连接状态和设备名,
|
|
40
|
+
点击后复用 `OpenBluetoothPage()`,因此用户可以先在全局入口连接,再进入任意模块执行 V8 打印。
|
|
41
|
+
|
|
42
|
+
## 微服务中的平台普通打印桥
|
|
43
|
+
|
|
44
|
+
隔离运行的 MicroService 不能直接访问父页面 `V8.Print`、Vue 组件或打印弹窗。微服务页面需要
|
|
45
|
+
提供“普通打印”时,调用 `microi.host.v1` 的 `openPlatformPrint` 宿主动作;参数为当前租户
|
|
46
|
+
`mic_print.Id`、标题,以及当前 `apiBase` 同源、路径以 `/apiengine/` 开头并明确携带同一
|
|
47
|
+
`OsClient` 的绝对数据地址。禁止把 Token、帐号密码或其它凭据放进 URL。
|
|
48
|
+
|
|
49
|
+
`openPlatformPrint` 只打开 Print Engine 预览,不发送 TSPL/CPCL/ESC-POS;它不是蓝牙代理,
|
|
50
|
+
也不发送 BLE/SPP 字节。
|
|
51
|
+
宿主返回 `accepted:true` 只表示预览已打开,不代表浏览器已打印或打印机已出纸。独立运行没有
|
|
52
|
+
宿主能力时应隐藏/禁用该入口。完整调用示例与结果协议见
|
|
53
|
+
`../../microi-microservice/references/runtime-delivery.md` 的“微服务调用平台普通打印”。
|
|
54
|
+
|
|
55
|
+
## 运行环境与能力判断
|
|
56
|
+
|
|
57
|
+
| 运行环境 | 当前引擎 | 结论 |
|
|
58
|
+
|---|---|---|
|
|
59
|
+
| Android 5+App | `plus.bluetooth` + `plus.android` | BLE;ZICOX CC4 可回退到已配对 RFCOMM/SPP;Android 12+ 需要附近设备权限 |
|
|
60
|
+
| iOS 5+App | `plus.bluetooth` | BLE,不使用 Android SPP |
|
|
61
|
+
| 存在 `navigator.bluetooth.requestDevice` 的浏览器 | Web Bluetooth | 支持;通常要求安全上下文和用户手势 |
|
|
62
|
+
| 其它普通 H5/浏览器 | 无 | `V8.Print` 仍可能存在,但连接页会提示能力不可用 |
|
|
63
|
+
| 微信小程序原生 BLE | 不属于此模块 | 需要小程序/UniApp 侧专用实现 |
|
|
64
|
+
|
|
65
|
+
不要用 `V8.ClientType === 'PC'` 判断蓝牙能力,也不要只检查
|
|
66
|
+
`BLEInformation.deviceId`。正确顺序是检查 `V8.Print`、调用 `isConnected()`,再在
|
|
67
|
+
用户点击事件中 `await OpenBluetoothPage()`。
|
|
68
|
+
|
|
69
|
+
Android 12+ 宿主必须启用 DCloud Bluetooth 模块并声明 `BLUETOOTH_SCAN`、
|
|
70
|
+
`BLUETOOTH_CONNECT`。运行时只在用户主动点击“搜索”时申请,不得在页面初始化或自动重连
|
|
71
|
+
时弹授权框;拒绝或永久拒绝要引导用户进入系统“附近的设备”权限设置。
|
|
72
|
+
|
|
73
|
+
浏览器模板、PDF、A4 单据和 Print Engine JSON 属于 `print-engine`;TSC/TSPL 或
|
|
74
|
+
CPCL/ESC/POS 原生字节通过 BLE/SPP 写入才属于 `V8.Print`。
|
|
75
|
+
|
|
76
|
+
## 双型号兼容契约
|
|
77
|
+
|
|
78
|
+
| 型号 | 标签协议 | 传输 | 兼容承诺 |
|
|
79
|
+
|---|---|---|---|
|
|
80
|
+
| 佳博 GP-M322 | TSPL | BLE | `createNew().getData()` 原字节发送,协议适配层不得改写 |
|
|
81
|
+
| ZICOX CC4 | CPCL | BLE 优先,Android SPP 兜底 | 同一份标准 TSC 高层调用在首包写入前转换为 CPCL |
|
|
82
|
+
| 其它 TSPL | TSPL | BLE | 保持原字节路径 |
|
|
83
|
+
|
|
84
|
+
`createNewESC()` 在 CC4 上也原样发送,因为厂家声明 CC4 支持 ESC/POS。不要根据厂家 Demo
|
|
85
|
+
里存在测试字符串就擅自宣称其它协议;以产品页、准确手册和实机固件为准。
|
|
86
|
+
|
|
87
|
+
TSC 构建器给字节数组附加不可枚举的操作元数据,因此 GP 字节值、长度与数组枚举完全不变。
|
|
88
|
+
CC4 必须直接收到同一次 `getData()` 返回值;`Array.from`、展开、JSON 序列化等复制会丢失
|
|
89
|
+
元数据并失败关闭。适配器先完成整份转换和校验,再开始分包;不支持的命令不得产生半张输出。
|
|
90
|
+
|
|
91
|
+
CC4 可转换:纸张尺寸、速度、浓度、间隙/黑标、前后走纸、方向 0/1、参考点、线/框/反相、
|
|
92
|
+
文字、条码、二维码、位图及单次 `setPagePrint`。`init`/`setCls` 无需输出。原始 `addCommand`、
|
|
93
|
+
国家/代码页、`setFromfeed`、`setHome`、蜂鸣、限位、擦除和未知方法没有足够等价语义,必须
|
|
94
|
+
在首包写入前拒绝。扩展白名单前要同时增加协议单测和两台目标机回归。
|
|
95
|
+
|
|
96
|
+
Android SPP 与厂家 Demo 一致,优先 RFCOMM 通道 1,再以标准 UUID
|
|
97
|
+
`00001101-0000-1000-8000-00805F9B34FB` 兜底。自动模式只显示名称可识别为 CC4 的已配对
|
|
98
|
+
经典设备;广播名不规范时,用户先手工选择 `zicox-cc4`。Web Bluetooth 不能访问 SPP。
|
|
99
|
+
|
|
100
|
+
## 连接与发送语义
|
|
101
|
+
|
|
102
|
+
| API | 当前真实语义 |
|
|
103
|
+
|---|---|
|
|
104
|
+
| `createNew()` | 新建 TSC/TSPL 标签指令构建器 |
|
|
105
|
+
| `createNewESC()` | 新建 ESC/POS 小票指令构建器 |
|
|
106
|
+
| `OpenBluetoothPage()` | 返回 `Promise<boolean>`;在连接弹窗关闭时解析,重复打开复用同一个 Promise |
|
|
107
|
+
| `isConnected()` | Web 端检查实时 GATT 与写特征;5+App 结合连接事件在线标记与设备/写特征 ID |
|
|
108
|
+
| `reconnect()` | 使用已记住的设备 ID 或浏览器保留的设备授权重连,不弹选择框 |
|
|
109
|
+
| `getConnectionState()` | 返回可展示的连接、记忆、设备、错误和重连状态快照 |
|
|
110
|
+
| `subscribeConnection(listener)` | 立即回调当前快照并持续通知状态变化,返回取消订阅函数 |
|
|
111
|
+
| `getPrinterProfile()` | 返回最终型号、标签指令和传输偏好;普通业务无需调用 |
|
|
112
|
+
| `setPrinterProfile(mode)` | 手工选 `gprinter-gp-m322`、`zicox-cc4`、`generic-tspl`,或恢复 `auto` |
|
|
113
|
+
| `prepareSend(bytes)` | 先恢复连接、完成型号协议适配,再进入应用级队列按包串行写入 |
|
|
114
|
+
| `Send(bytes)` | 依赖 `prepareSend` 已设置的内部游标,属于内部状态机入口,业务代码不要直接调用 |
|
|
115
|
+
| `setOneTimeData(bytes)` | 设置 BLE 包长;只接受 1–512 整数,连接页候选 20–190,默认 20 |
|
|
116
|
+
| `setPrinterNum(num)` | 重复发送同一缓冲区;只接受 1–99 整数,连接页候选 1–9 |
|
|
117
|
+
| `disconnect()` | 主动断开、停止自动重连并忘记当前设备 |
|
|
118
|
+
| `BLEInformation` | 最近设备/型号/通道/服务/特征元数据,只用于诊断,不代表实时连接或打印回执 |
|
|
119
|
+
|
|
120
|
+
`getConnectionState()` 额外含 `transport`、`profileMode`、`profileId`、`profileName`、
|
|
121
|
+
`commandLanguage`;前端展示可以使用,打印判断仍使用 `isConnected()`。
|
|
122
|
+
|
|
123
|
+
`OpenBluetoothPage()` 不是“连接成功事件”;用户连上设备后仍要关闭弹窗,调用方才能继续。
|
|
124
|
+
设备元数据会写入 `localStorage` 与兼容用 `sessionStorage`。应用初始化、页面恢复、重新获得
|
|
125
|
+
焦点和意外断线时会做有限次数自动重连:5+App 使用设备 ID;Web 端只有浏览器保留授权且
|
|
126
|
+
支持 `navigator.bluetooth.getDevices()` 时才可无弹窗恢复。系统蓝牙、浏览器权限、设备电源、
|
|
127
|
+
休眠、距离等仍会造成真实断线;重试结束后必须让用户从全局入口重新选择。
|
|
128
|
+
|
|
129
|
+
## 最小安全流程
|
|
130
|
+
|
|
131
|
+
```javascript
|
|
132
|
+
function cleanCommandText(value, maxLength) {
|
|
133
|
+
return String(value == null ? '' : value)
|
|
134
|
+
.replace(/[\r\n"\x00-\x1f]/g, ' ')
|
|
135
|
+
.slice(0, maxLength || 120);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
async function ensurePrinterConnected() {
|
|
139
|
+
if (!V8.Print) throw new Error('当前前端未加载蓝牙打印能力');
|
|
140
|
+
if (V8.Print.isConnected()) return;
|
|
141
|
+
|
|
142
|
+
var connected = await V8.Print.reconnect();
|
|
143
|
+
if (!connected) connected = await V8.Print.OpenBluetoothPage();
|
|
144
|
+
if (!connected || !V8.Print.isConnected()) {
|
|
145
|
+
throw new Error('未连接蓝牙打印机');
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
async function printLabel(order) {
|
|
150
|
+
await ensurePrinterConnected();
|
|
151
|
+
|
|
152
|
+
var cmd = V8.Print.createNew();
|
|
153
|
+
cmd.setSize(60, 40);
|
|
154
|
+
cmd.setGap(2);
|
|
155
|
+
cmd.setSpeed(4);
|
|
156
|
+
cmd.setDensity(8);
|
|
157
|
+
cmd.setDirection(1);
|
|
158
|
+
cmd.setCls();
|
|
159
|
+
cmd.setText(20, 20, 'TSS24.BF2', 1, 1, cleanCommandText(order.Name, 40));
|
|
160
|
+
cmd.setBarCode(20, 80, '128', 60, 1, 2, 2, cleanCommandText(order.Code, 40));
|
|
161
|
+
cmd.setQR(340, 30, 'L', 5, 'A', cleanCommandText(order.Id, 120));
|
|
162
|
+
cmd.setPagePrint();
|
|
163
|
+
|
|
164
|
+
await V8.Print.prepareSend(cmd.getData());
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
同一段标签代码在 GP-M322 上保持 TSPL,在 CC4 上转换为 CPCL。ESC/POS 小票使用
|
|
169
|
+
`createNewESC()`,完整顺序和 25 个真实方法见
|
|
170
|
+
[`bluetooth-print-api.md`](bluetooth-print-api.md)。发送成功只表示 BLE/SPP 写调用完成,不能
|
|
171
|
+
写成“打印机已走纸”或“物理打印成功”。当前源码虽发现 read/notify 特征,但没有订阅状态
|
|
172
|
+
通知,也没有消费 ACK、缺纸或故障回执。
|
|
173
|
+
|
|
174
|
+
## 批量打印与恢复
|
|
175
|
+
|
|
176
|
+
```javascript
|
|
177
|
+
async function printBatch(rows, startIndex) {
|
|
178
|
+
var list = Array.isArray(rows) ? rows : [];
|
|
179
|
+
var begin = Math.max(0, Number(startIndex || 0));
|
|
180
|
+
var limit = Math.min(list.length, begin + 100);
|
|
181
|
+
|
|
182
|
+
for (var i = begin; i < limit; i++) {
|
|
183
|
+
try {
|
|
184
|
+
await printLabel(list[i]);
|
|
185
|
+
V8.Tips('已发送 ' + (i + 1) + '/' + list.length, true);
|
|
186
|
+
} catch (error) {
|
|
187
|
+
return {
|
|
188
|
+
Code: 0,
|
|
189
|
+
Msg: '第 ' + (i + 1) + ' 条发送失败:' + (error.message || error),
|
|
190
|
+
NextIndex: i
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return { Code: 1, Data: { NextIndex: limit, HasMore: limit < list.length } };
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
- 不用固定 `setTimeout(3000)` 猜测上一张是否完成。
|
|
200
|
+
- 不用 `Promise.all` 表达同一设备的并行打印。运行时会把同时到达的调用排队,但业务仍应逐条
|
|
201
|
+
`await`,以便准确记录哪一条成功或失败。
|
|
202
|
+
- 大批次分段并持久化 `NextIndex`;页面关闭、断连或写失败后从失败位置人工确认再恢复。
|
|
203
|
+
- `setPrinterNum(n)` 只适合同一缓冲区重复发送,不适合每张内容不同的批次。
|
|
204
|
+
- 业务落库与蓝牙打印不是原子事务。用稳定业务单号支持受控重打,不重复执行业务写入。
|
|
205
|
+
|
|
206
|
+
## 兼容性与当前限制
|
|
207
|
+
|
|
208
|
+
- Web Bluetooth 仅把四个常见服务 UUID 传入 `optionalServices`:`18f0`、`ff00`、
|
|
209
|
+
`49535343-fe7d-4ae5-8fa9-9fafd205e455`、`e7810a71-73ae-499d-8c15-faa9aef0c3f2`。
|
|
210
|
+
当前没有公开的自定义服务配置,并选择枚举到的第一个可写特征;其它型号可能需要扩展源码。
|
|
211
|
+
CC4 固件若只开放 SPP 或使用其它私有 UUID,Web 端不可连接;Android 5+App 使用已配对 SPP,
|
|
212
|
+
或先取得厂家准确 BLE UUID 再扩展源码,禁止猜 UUID。
|
|
213
|
+
- `prepareSend` 默认每包 20 字节;Android 5+ 的佳博 GP-M322 在特征支持时优先使用同一
|
|
214
|
+
`plus.bluetooth` 连接的 `writeNoResponse`,逐包 await API 回调并保留约 8ms 的 GATT 保护窗口;
|
|
215
|
+
即使协商出 180 字节有效载荷也只采用 100 字节稳定档。不支持无响应写时保留 `write` 兼容路径。其它型号、iOS、Web 与 SPP
|
|
216
|
+
保留约 20ms,同一缓冲区多份间约 100ms。5+ BLE 的连接、服务发现和写入统一使用 `plus.bluetooth`,
|
|
217
|
+
禁止用 `uni.writeBLECharacteristicValue` 写入由 `plus.bluetooth` 建立的连接。
|
|
218
|
+
这是写节奏,不是物理走纸确认。5+ BLE 同时受本次连接的 `maxWriteBytes` 和更保守的
|
|
219
|
+
`recommendedPacketSize` 限制;未知 MTU 为 20。
|
|
220
|
+
- 5+ 佳博在服务发现后协商 MTU,最多等待 1.5 秒,`getConnectionState()` 返回 `mtu`、
|
|
221
|
+
`maxWriteBytes`、`recommendedPacketSize`(20/100)、`writeType`、`packetIntervalMs`。
|
|
222
|
+
必须读取真实回调的 `mtu`;空成功、失败、超时或缺 API 不可按请求值升档,迟到回调不得提升能力,
|
|
223
|
+
断开时清除能力。自定义微服务需按这些字段判断,不能只允许 `engine === 'web'`。
|
|
224
|
+
`microi.app` 在线壳更新远程前端即可获取本修复;WebView 缺少 Web Bluetooth 时不增加无效切换选项。
|
|
225
|
+
- 当前分包公式使用 `Math.ceil(length / packetSize)`,长度恰好整除时不会产生 0 字节末包;
|
|
226
|
+
空数据、非法包长和非法份数会直接抛错。合法数值仍须按目标打印机实测。
|
|
227
|
+
- TSC 与 ESC 文本使用仓库内置 `encoding.js` + `encoding-indexes.js` 转为 GB18030,运行时
|
|
228
|
+
不请求网络。编码成功不等于打印机字体、代码页和固件支持全部字符;Emoji 等仍需实机验证。
|
|
229
|
+
- `setBitmap` 接受 ImageData 风格 `{ width, height, data }` RGBA 数据。当前黑白转换较简单,
|
|
230
|
+
大图可能产生大缓冲区;先缩放、二值化并用小图测试。
|
|
231
|
+
- `V8.Print` 使用应用级共享发送队列,跨 V8 上下文不会再并发覆盖 `currentTime`、`looptime`、
|
|
232
|
+
`lastData` 等共享状态。队列只保证写入顺序,不提供打印机 ACK、业务事务或自动重打语义。
|
|
233
|
+
- CC4 遇到不支持的方法、复制后丢失元数据、缺少或重复 `setPagePrint()` 时应零写入失败;不要
|
|
234
|
+
在业务层捕获后把原 TSPL 盲目重发给 CC4。
|
|
235
|
+
|
|
236
|
+
## 安全边界
|
|
237
|
+
|
|
238
|
+
- TSC 的 `setText`、`setQR`、`setBarCode` 和 `addCommand` 会拼协议文本。移除引号、换行、
|
|
239
|
+
NUL/控制字符并限制长度;`addCommand` 只接受固定、受审查的命令。
|
|
240
|
+
- 蓝牙设备名称、ID 和服务特征均是外部输入。不要拼入 `innerHTML`,展示时做文本转义;不要
|
|
241
|
+
记录或上传完整 `BLEInformation`,以免泄露终端指纹。
|
|
242
|
+
- 金额、数量、坐标、纸张尺寸、包长和份数先做类型/范围校验,避免无限循环或超大缓冲区。
|
|
243
|
+
- 打印内容含个人信息、票据或密钥时,不写控制台、系统日志或异常上报正文。
|
|
244
|
+
- 浏览器权限拒绝、用户取消、GATT 断开、找不到服务/特征和写包失败都必须可理解地提示。
|
|
245
|
+
- 搜索不到设备的头号原因是残留 GATT 连接:BLE 外设在已连接期间停止广播,上一次连接被并发流程打断或 App 重启后系统仍保留旧链路时,打印机“没在用”但也搜不到。平台在开始发现前会先 `getConnectedBluetoothDevices` 并关闭应用未持有的连接,被断开/重连事件接管时也会显式关闭自己建立的链路;排查顺序据此固定为“清理残留连接 → 打印机重新上电 → 系统蓝牙忽略设备 → 再搜索”,不要先去改包长、MTU 或指令集。
|
|
246
|
+
|
|
247
|
+
## 实机验收
|
|
248
|
+
|
|
249
|
+
至少记录:
|
|
250
|
+
|
|
251
|
+
1. GP-M322 与 CC4 的固件、纸张规格、服务/写特征 UUID 或 SPP、指令集。
|
|
252
|
+
2. 5+App 或浏览器版本;首次授权/配对、自动/手工选型、再次连接、主动断开、页面刷新和断线重连。
|
|
253
|
+
3. 中文、数字、特殊字符、二维码、条码、长文本、图片和边界金额。
|
|
254
|
+
4. 默认 20 字节与目标包长;同时覆盖“长度恰好整除包长”。
|
|
255
|
+
5. 连续 20 张严格串行发送,无乱序、丢包、重复或任务状态互相污染。
|
|
256
|
+
6. 中途关机、缺纸、离开范围、权限撤销后的失败位置与恢复行为。
|
|
257
|
+
7. 两种设备交替连接,证明 GP 原 TSPL 不变、CC4 收到 CPCL/ESC-POS;CC4 分别记录 BLE 与 SPP。
|
|
258
|
+
8. 页面只确认“数据已发送”;若业务要求确认物理结果,另接状态回读或人工确认。
|