@talknote/create-talknote-h5 0.0.2 → 0.0.4
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 +142 -31
- package/package.json +1 -1
- package/template/config/config.ts +2 -0
- package/template/config/proxy.ts +39 -0
- package/template/h5-bridge.md +297 -0
- package/template/logo.png +0 -0
- package/template/src/app.tsx +10 -1
- package/template/src/favicon.ico +0 -0
package/README.md
CHANGED
|
@@ -1,54 +1,165 @@
|
|
|
1
|
-
|
|
1
|
+
<h1 align="center">Alita Pro</h1>
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
帮助你快速使用 alita,基于Umi.js 的移动端框架
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
```
|
|
6
|
+
yarn
|
|
7
|
+
yarn dev
|
|
8
|
+
```
|
|
6
9
|
|
|
7
|
-
|
|
10
|
+
### 首页
|
|
8
11
|
|
|
9
|
-
|
|
10
|
-
yarn create @talknote/talknote-h5 my-project
|
|
11
|
-
```
|
|
12
|
+

|
|
12
13
|
|
|
13
|
-
|
|
14
|
+
### 列表页
|
|
14
15
|
|
|
15
|
-
|
|
16
|
+
列表页支持滚动加载更多,固定头部,状态保持
|
|
16
17
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+

|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
### 关于尺寸标注
|
|
22
|
+
|
|
23
|
+
100% 宽为 750px,可在蓝湖等工具中将标准改为 750px,这样可以直接使用标注的尺寸用于 caa class 中的尺寸,最终运行会根据手机适配,将 px 自动转为对应的 rem 值。
|
|
24
|
+
|
|
25
|
+
值得注意的是,写在内联样式 style 中的 px 值不会被转化,需要手动写明 rem 单位,直接将 px 值除于 100 即可,如 750px,在 style 中应该写为 7.5rem
|
|
26
|
+
|
|
27
|
+
### 关于路由
|
|
22
28
|
|
|
23
|
-
|
|
29
|
+
采用约定式路由,只有 `src/pages/**/index.tsx` 会被识别成路由,可使用 npx alita g pages name 来新增页面。
|
|
24
30
|
|
|
25
|
-
|
|
31
|
+
> Q: 为什么仅 index.tsx 会被识别成路由?如果我想要嵌套的路由,如 hello/hero 我该怎么办?
|
|
32
|
+
> A: 仅 index.tsx 被识别成路由,会让整个文件结构变得很干净,在移动端上不需要嵌套路由,一般短位链接优势更大
|
|
26
33
|
|
|
27
|
-
|
|
34
|
+
### 自带头部
|
|
28
35
|
|
|
29
|
-
|
|
30
|
-
|
|
36
|
+
可在 `src/app.tsx#L24` 中配置
|
|
37
|
+
|
|
38
|
+
```tsx
|
|
39
|
+
const titleList: TitleListItem[] = [
|
|
40
|
+
{
|
|
41
|
+
pagePath: '/',
|
|
42
|
+
title: '首页',
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
pagePath: '/list',
|
|
46
|
+
title: '列表',
|
|
47
|
+
},
|
|
48
|
+
];
|
|
31
49
|
```
|
|
50
|
+
可全局配置隐藏
|
|
51
|
+
```tsx
|
|
52
|
+
const navBar: NavBarProps = {
|
|
53
|
+
navList,
|
|
54
|
+
fixed: false,
|
|
55
|
+
//默认导航栏显示
|
|
56
|
+
hideNavBar: false,
|
|
57
|
+
onLeftClick: () => {
|
|
58
|
+
// router.goBack();
|
|
59
|
+
},
|
|
60
|
+
};
|
|
32
61
|
|
|
33
|
-
|
|
62
|
+
```
|
|
63
|
+
也可以在页面中独立配置
|
|
64
|
+
|
|
65
|
+
```tsx
|
|
66
|
+
import { setPageNavBar, useLocation } from 'alita';
|
|
67
|
+
import { LeftOutline } from 'antd-mobile-icons';
|
|
68
|
+
import { useEffect } from 'react';
|
|
69
|
+
|
|
70
|
+
const location = useLocation();
|
|
71
|
+
useEffect(() => {
|
|
72
|
+
setPageNavBar({
|
|
73
|
+
pagePath: location.pathname,
|
|
74
|
+
navBar: {
|
|
75
|
+
mode: 'dark',
|
|
76
|
+
pageTitle: '首页动态标题',
|
|
77
|
+
pageBackground: '#fff',
|
|
78
|
+
back: '返回',
|
|
79
|
+
icon: <LeftOutline />,
|
|
80
|
+
leftContent: <div>首页</div>,
|
|
81
|
+
rightContent: <div>详情</div>,
|
|
82
|
+
onLeftClick: (navigate) => {
|
|
83
|
+
navigate(-1);
|
|
84
|
+
},
|
|
85
|
+
hideNavBar: false,
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
}, []);
|
|
89
|
+
```
|
|
34
90
|
|
|
35
|
-
|
|
36
|
-
|
|
91
|
+
> 关闭默认 NavBar 上述 hideNavBar 配置改为 hideNavBar: true
|
|
92
|
+
|
|
93
|
+
### 底部 Tabs
|
|
94
|
+
|
|
95
|
+
可在 `src/app.tsx#L42` 中配置
|
|
96
|
+
|
|
97
|
+
```tsx
|
|
98
|
+
const tabList: TabBarListItem[] = [
|
|
99
|
+
{
|
|
100
|
+
pagePath: '/',
|
|
101
|
+
text: '首页',
|
|
102
|
+
iconPath: HomeGary,
|
|
103
|
+
selectedIconPath: HomeBlue,
|
|
104
|
+
title: '首页',
|
|
105
|
+
iconSize: '',
|
|
106
|
+
badge: '',
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
pagePath: '/list',
|
|
110
|
+
text: '列表',
|
|
111
|
+
iconPath: ListGary,
|
|
112
|
+
selectedIconPath: ListBlue,
|
|
113
|
+
title: '列表',
|
|
114
|
+
iconSize: '',
|
|
115
|
+
badge: '',
|
|
116
|
+
},
|
|
117
|
+
];
|
|
37
118
|
```
|
|
38
119
|
|
|
39
|
-
|
|
120
|
+
也可以在页面中独立配置
|
|
121
|
+
|
|
122
|
+
```tsx
|
|
123
|
+
import { setTabBarList, useLocation } from 'alita';
|
|
124
|
+
import { useEffect } from 'react';
|
|
125
|
+
|
|
126
|
+
const location = useLocation();
|
|
127
|
+
useEffect(() => {
|
|
128
|
+
setTabBarList({
|
|
129
|
+
pagePath: location.pathname,
|
|
130
|
+
text: '首页',
|
|
131
|
+
iconSize: '18px',
|
|
132
|
+
badge: '12',
|
|
133
|
+
onPress: () => {
|
|
134
|
+
navigate(location.pathname, { replace: true });
|
|
135
|
+
return '';
|
|
136
|
+
},
|
|
137
|
+
remove: false,
|
|
138
|
+
});
|
|
139
|
+
}, []);
|
|
140
|
+
```
|
|
40
141
|
|
|
41
|
-
|
|
142
|
+
> 关闭 app.ts 中已经配置好的 Tab ,上述 remove 配置改为 remove: true
|
|
42
143
|
|
|
43
|
-
|
|
144
|
+
### 格式化
|
|
44
145
|
|
|
45
|
-
|
|
146
|
+
```
|
|
147
|
+
yarn format
|
|
148
|
+
```
|
|
46
149
|
|
|
47
|
-
|
|
150
|
+
### 构建
|
|
48
151
|
|
|
49
|
-
```bash
|
|
50
|
-
npm login
|
|
51
|
-
npm publish
|
|
52
152
|
```
|
|
153
|
+
yarn build
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### 调试工具
|
|
53
157
|
|
|
54
|
-
|
|
158
|
+
在 `config/config.ts` 中增加配置
|
|
159
|
+
|
|
160
|
+
```
|
|
161
|
+
aconsole: {
|
|
162
|
+
console: {},
|
|
163
|
+
inspx: {},
|
|
164
|
+
},
|
|
165
|
+
```
|
package/package.json
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { defineConfig } from 'alita';
|
|
2
|
+
import proxy from './proxy';
|
|
2
3
|
|
|
3
4
|
export default defineConfig({
|
|
4
5
|
appType: 'h5',
|
|
@@ -7,6 +8,7 @@ export default defineConfig({
|
|
|
7
8
|
console: {},
|
|
8
9
|
inspx: {},
|
|
9
10
|
},
|
|
11
|
+
proxy,
|
|
10
12
|
mobileLayout: 'mobile5',
|
|
11
13
|
mfsu: {},
|
|
12
14
|
hash: false,
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
const BASE_URL = 'http://172.21.72.205:10000/';
|
|
2
|
+
|
|
3
|
+
const DEV_URL = process.env.BASE_URL || `${BASE_URL}`;
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
'/portal': {
|
|
7
|
+
target: BASE_URL,
|
|
8
|
+
changeOrigin: true,
|
|
9
|
+
},
|
|
10
|
+
'/server': {
|
|
11
|
+
target: DEV_URL,
|
|
12
|
+
changeOrigin: true,
|
|
13
|
+
pathRewrite: { '^/server': '' },
|
|
14
|
+
},
|
|
15
|
+
'/app': {
|
|
16
|
+
target: DEV_URL,
|
|
17
|
+
changeOrigin: true,
|
|
18
|
+
// pathRewrite: { '^/app': '' },
|
|
19
|
+
},
|
|
20
|
+
'/login': {
|
|
21
|
+
target: DEV_URL,
|
|
22
|
+
changeOrigin: true,
|
|
23
|
+
// pathRewrite: { '^/login': '' },
|
|
24
|
+
},
|
|
25
|
+
'/lcdp': {
|
|
26
|
+
target: `${DEV_URL}`,
|
|
27
|
+
changeOrigin: true,
|
|
28
|
+
},
|
|
29
|
+
'/img': {
|
|
30
|
+
target: BASE_URL,
|
|
31
|
+
changeOrigin: true,
|
|
32
|
+
pathRewrite: { '^/img': '' },
|
|
33
|
+
},
|
|
34
|
+
'/engine': {
|
|
35
|
+
target: BASE_URL,
|
|
36
|
+
changeOrigin: true,
|
|
37
|
+
pathRewrite: { '^/engine': 'engine' },
|
|
38
|
+
},
|
|
39
|
+
};
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
# @talknote/h5-bridge
|
|
2
|
+
|
|
3
|
+
TalkNote App 内嵌 WebView 的第三方 H5 SDK。它把现有 `window.TalkNoteBridge` 消息协议封装为带类型、可测试的语义化 API。
|
|
4
|
+
|
|
5
|
+
- TypeScript 源码与完整 `.d.ts`
|
|
6
|
+
- ESM、CommonJS、CDN UMD 三种入口
|
|
7
|
+
- 发布包运行时依赖为 0
|
|
8
|
+
- Father 仅用于开发构建,不进入 H5 运行时
|
|
9
|
+
- 兼容当前 iOS、Android 注入的 `window.TalkNoteBridge`
|
|
10
|
+
|
|
11
|
+
## 安装
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install @talknote/h5-bridge
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
yarn add @talknote/h5-bridge
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### 安装 AI Skill(可选)
|
|
22
|
+
|
|
23
|
+
`npm install` 不会自动修改当前项目。需要让 Codex 获得 TalkNote H5 Bridge 专用工作流时,显式执行:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npx talknote-h5-bridge install-skill
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Skill 会安装到 `.agents/skills/talknote-h5-bridge/`。如果同名 Skill 已存在,命令会直接覆盖,但不会修改其他 Skill。升级 npm 包后需重新执行该命令才能更新 Skill。
|
|
30
|
+
|
|
31
|
+
## 使用
|
|
32
|
+
|
|
33
|
+
### ES Module
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
import TalkNoteH5Bridge, { TalkNoteBridgeError } from '@talknote/h5-bridge';
|
|
37
|
+
|
|
38
|
+
const userInfo = await TalkNoteH5Bridge.getUserInfo();
|
|
39
|
+
renderUserProfile(userInfo);
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### CommonJS
|
|
43
|
+
|
|
44
|
+
```js
|
|
45
|
+
const TalkNoteH5Bridge = require('@talknote/h5-bridge');
|
|
46
|
+
|
|
47
|
+
TalkNoteH5Bridge.goBack();
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### CDN
|
|
51
|
+
|
|
52
|
+
```html
|
|
53
|
+
<script src="https://cdn.jsdelivr.net/npm/@talknote/h5-bridge@0.1.0/dist/umd/talknote-h5-bridge.min.js"></script>
|
|
54
|
+
<script>
|
|
55
|
+
if (window.TalkNoteH5Bridge.isAvailable()) {
|
|
56
|
+
window.TalkNoteH5Bridge.getLocaleInfo().then(updateLocaleUI);
|
|
57
|
+
}
|
|
58
|
+
</script>
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
CDN 全局对象是 `window.TalkNoteH5Bridge`。SDK 不会覆盖客户端注入的 `window.TalkNoteBridge`。
|
|
62
|
+
|
|
63
|
+
## 环境检测
|
|
64
|
+
|
|
65
|
+
原生能力只在 TalkNote App 支持的内嵌 WebView 中可用。系统浏览器中应提供降级逻辑:
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
if (!TalkNoteH5Bridge.isAvailable()) {
|
|
69
|
+
showOpenInAppGuide();
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
`isAvailable()` 只表示存在 Bridge 传输通道。调用具体能力前使用 `supports()`;`getCapabilities()` 可用于诊断客户端协议版本和能力来源:
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
if (!TalkNoteH5Bridge.supports('downloadFile')) {
|
|
78
|
+
showUpgradeAppGuide();
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const capabilities = TalkNoteH5Bridge.getCapabilities();
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
新客户端以原生 `capabilities` 为准;旧客户端只回退历史能力,两个文件能力不会被推断为可用。协议机器可读事实源是 [`contract/bridge-contract.json`](./contract/bridge-contract.json)。
|
|
86
|
+
|
|
87
|
+
## 常用能力
|
|
88
|
+
|
|
89
|
+
### 导航
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
TalkNoteH5Bridge.navigateTo({
|
|
93
|
+
key: 'MembershipScreen',
|
|
94
|
+
mode: 'push',
|
|
95
|
+
props: { from: 'third-party-h5' },
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
TalkNoteH5Bridge.goBack();
|
|
99
|
+
TalkNoteH5Bridge.goToRoot({ tab: 'home' });
|
|
100
|
+
TalkNoteH5Bridge.setPopGestureEnabled(false);
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### 获取请求基础信息
|
|
104
|
+
|
|
105
|
+
```ts
|
|
106
|
+
const { baseUrl, headers = {} } = await TalkNoteH5Bridge.getRequestBaseInfo();
|
|
107
|
+
|
|
108
|
+
const response = await fetch(`${baseUrl}/your/api`, {
|
|
109
|
+
headers: {
|
|
110
|
+
...headers,
|
|
111
|
+
'Content-Type': 'application/json',
|
|
112
|
+
},
|
|
113
|
+
});
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
不要打印或持久化 `token`、`Authorization` 等敏感信息。
|
|
117
|
+
|
|
118
|
+
### 图片选择
|
|
119
|
+
|
|
120
|
+
```ts
|
|
121
|
+
const result = await TalkNoteH5Bridge.pickImages({
|
|
122
|
+
mediaTypes: 'Images',
|
|
123
|
+
allowsMultipleSelection: true,
|
|
124
|
+
selectionLimit: 9,
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
if (!result.canceled) {
|
|
128
|
+
uploadSelectedAssets(result.assets ?? []);
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### 文档选择
|
|
133
|
+
|
|
134
|
+
```ts
|
|
135
|
+
const result = await TalkNoteH5Bridge.documentPicker({
|
|
136
|
+
type: ['application/pdf'],
|
|
137
|
+
copyToCacheDirectory: true,
|
|
138
|
+
multiple: false,
|
|
139
|
+
});
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### 下载并保存文件
|
|
143
|
+
|
|
144
|
+
`downloadFile` 接收远程 `http/https` 地址,客户端下载完成后会立即打开系统保存面板:
|
|
145
|
+
|
|
146
|
+
```ts
|
|
147
|
+
if (!TalkNoteH5Bridge.supports('downloadFile')) {
|
|
148
|
+
showUpgradeAppGuide();
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const result = await TalkNoteH5Bridge.downloadFile({
|
|
153
|
+
url: 'https://example.com/report.pdf',
|
|
154
|
+
fileName: '报告.pdf',
|
|
155
|
+
mimeType: 'application/pdf',
|
|
156
|
+
headers: { Authorization: 'Bearer xxx' },
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
if (result.canceled) {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (!result.success) {
|
|
164
|
+
showError(result.error || '文件保存失败');
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
SDK 不会自动注入 App token。只有下载地址确实需要鉴权时,才由 H5 显式传入 `headers`,并且不要记录这些请求头。
|
|
169
|
+
|
|
170
|
+
### 将本地文件另存到系统目录
|
|
171
|
+
|
|
172
|
+
`saveFileToSystem` 接收 App 已可读取的本地 URI,例如图片选择、文档选择或其他原生能力返回的 `file://` URI:
|
|
173
|
+
|
|
174
|
+
```ts
|
|
175
|
+
if (!TalkNoteH5Bridge.supports('saveFileToSystem')) {
|
|
176
|
+
showUpgradeAppGuide();
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const result = await TalkNoteH5Bridge.saveFileToSystem({
|
|
181
|
+
localUri: 'file:///path/to/report.pdf',
|
|
182
|
+
fileName: '报告.pdf',
|
|
183
|
+
mimeType: 'application/pdf',
|
|
184
|
+
});
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
该方法不会下载网络文件;需要保存远程 URL 时使用 `downloadFile`。两种方法都会要求用户在 iOS“文件”App 或 Android 系统文件选择器中确认保存位置,取消时返回 `canceled: true`。
|
|
188
|
+
|
|
189
|
+
文件操作不会受 SDK 通用 30 秒超时限制,会一直等待下载和系统保存面板完成。单次远程下载最大 200MB;超过限制时返回 `error: 'file_too_large'`。如果下载发生跨源重定向,SDK 传入的自定义请求头不会转发到新的源站。
|
|
190
|
+
|
|
191
|
+
### 实名认证
|
|
192
|
+
|
|
193
|
+
```ts
|
|
194
|
+
const result = await TalkNoteH5Bridge.startRealNameAuth({ authUrl });
|
|
195
|
+
if (!result.opened) {
|
|
196
|
+
showError(result.error || '无法打开支付宝');
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### 页面重新聚焦
|
|
201
|
+
|
|
202
|
+
```ts
|
|
203
|
+
const unsubscribe = TalkNoteH5Bridge.onWebViewScreenFocus(event => {
|
|
204
|
+
refreshPageData(event.data?.timestamp);
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
// 页面销毁时取消监听
|
|
208
|
+
unsubscribe();
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
## 错误处理
|
|
212
|
+
|
|
213
|
+
```ts
|
|
214
|
+
import TalkNoteH5Bridge, { TalkNoteBridgeError } from '@talknote/h5-bridge';
|
|
215
|
+
|
|
216
|
+
try {
|
|
217
|
+
await TalkNoteH5Bridge.getUserInfo();
|
|
218
|
+
} catch (error) {
|
|
219
|
+
if (error instanceof TalkNoteBridgeError) {
|
|
220
|
+
switch (error.code) {
|
|
221
|
+
case 'UNSUPPORTED_CAPABILITY':
|
|
222
|
+
showUpgradeAppGuide();
|
|
223
|
+
break;
|
|
224
|
+
case 'BRIDGE_UNAVAILABLE':
|
|
225
|
+
showOpenInAppGuide();
|
|
226
|
+
break;
|
|
227
|
+
case 'BRIDGE_TIMEOUT':
|
|
228
|
+
showRetryMessage();
|
|
229
|
+
break;
|
|
230
|
+
case 'INVALID_ARGUMENT':
|
|
231
|
+
case 'BRIDGE_SEND_FAILED':
|
|
232
|
+
reportNonSensitiveError(error.code);
|
|
233
|
+
break;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
| 错误码 | 含义 |
|
|
240
|
+
| ---------------------------- | -------------------------------------- |
|
|
241
|
+
| `UNSUPPORTED_CAPABILITY` | 当前客户端未声明支持该具体能力 |
|
|
242
|
+
| `BRIDGE_UNAVAILABLE` | 当前环境不存在所需 Bridge 传输能力 |
|
|
243
|
+
| `INVALID_ARGUMENT` | SDK 入参不符合公开契约 |
|
|
244
|
+
| `BRIDGE_TIMEOUT` | 异步调用超过等待时间 |
|
|
245
|
+
| `BRIDGE_SEND_FAILED` | 序列化或底层 Bridge 调用失败 |
|
|
246
|
+
|
|
247
|
+
原生返回的 `{ error }` 属于业务结果,仍会通过 Promise resolve 返回,不会自动转换为 reject。
|
|
248
|
+
|
|
249
|
+
## 通用协议入口
|
|
250
|
+
|
|
251
|
+
优先使用语义化方法。客户端将来新增指令而 SDK 尚未升级时,可使用:
|
|
252
|
+
|
|
253
|
+
```ts
|
|
254
|
+
TalkNoteH5Bridge.send('newOneWayCommand', { value: 1 });
|
|
255
|
+
|
|
256
|
+
const result = await TalkNoteH5Bridge.invoke(
|
|
257
|
+
'newAsyncCommand',
|
|
258
|
+
{ value: 1 },
|
|
259
|
+
{
|
|
260
|
+
timeout: 10_000,
|
|
261
|
+
}
|
|
262
|
+
);
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
不要直接使用 `_callbacks`、`_callbackId` 或 `_onCallback`,它们属于客户端内部实现。
|
|
266
|
+
|
|
267
|
+
## API 文档
|
|
268
|
+
|
|
269
|
+
- [完整 API](./docs/API.md)
|
|
270
|
+
- [AI Coding 上下文](./docs/AI-CODING.md)
|
|
271
|
+
- [llms.txt](./llms.txt)
|
|
272
|
+
|
|
273
|
+
## 客户端兼容
|
|
274
|
+
|
|
275
|
+
SDK 不修改底层消息字段,仍发送:
|
|
276
|
+
|
|
277
|
+
```json
|
|
278
|
+
{
|
|
279
|
+
"type": "getUserInfo",
|
|
280
|
+
"data": {}
|
|
281
|
+
}
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
异步回调继续由客户端现有的 `window.TalkNoteBridge.invoke()` 和 `_onCallback()` 完成。SDK 返回类型按当前客户端字段建模,客户端未来可以增加字段而不破坏现有调用。
|
|
285
|
+
|
|
286
|
+
仓库级 AI Skill 会指导接入与扩展流程,但不替代 `contract/bridge-contract.json`、公开 `.d.ts` 和原生实现;发生冲突时以机器契约和类型声明为准。
|
|
287
|
+
|
|
288
|
+
## 本地开发
|
|
289
|
+
|
|
290
|
+
```bash
|
|
291
|
+
cd packages/h5Bridge
|
|
292
|
+
npm install
|
|
293
|
+
npm run build
|
|
294
|
+
npm test
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
构建工具固定为 `father@4.6.33`。Father 是开发依赖,其依赖树不进入发布包;Black Duck 是否包含开发依赖,应以项目实际扫描配置和报告为准。
|
package/template/logo.png
CHANGED
|
Binary file
|
package/template/src/app.tsx
CHANGED
|
@@ -10,6 +10,8 @@ import type {
|
|
|
10
10
|
TabBarProps,
|
|
11
11
|
TitleListItem,
|
|
12
12
|
} from 'alita';
|
|
13
|
+
import routeProps from './.umi/core/routeProps';
|
|
14
|
+
import TalkNoteH5Bridge from '@talknote/h5-bridge';
|
|
13
15
|
|
|
14
16
|
export const request = {
|
|
15
17
|
prefix: '/api',
|
|
@@ -35,8 +37,15 @@ const navList: NavBarListItem[] = [];
|
|
|
35
37
|
const navBar: NavBarProps = {
|
|
36
38
|
navList,
|
|
37
39
|
fixed: false,
|
|
40
|
+
//默认顶部导航栏隐藏
|
|
41
|
+
hideNavBar: true,
|
|
38
42
|
onLeftClick: () => {
|
|
39
|
-
//
|
|
43
|
+
// 判断是否能够返回,如果不能返回调用 @talknote/h5-bridge goBack
|
|
44
|
+
if (window.history.length > 1) {
|
|
45
|
+
window.history.back(); // 有历史记录,浏览器返回
|
|
46
|
+
} else {
|
|
47
|
+
TalkNoteH5Bridge.goBack(); // 没有历史记录,交给原生端处理
|
|
48
|
+
}
|
|
40
49
|
},
|
|
41
50
|
};
|
|
42
51
|
const tabList: TabBarListItem[] = [
|
package/template/src/favicon.ico
CHANGED
|
Binary file
|