@talknote/create-talknote-h5 0.0.2 → 0.0.3

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 CHANGED
@@ -1,54 +1,165 @@
1
- # create-talknote-h5
1
+ <h1 align="center">Alita Pro</h1>
2
2
 
3
- 用于创建 Talknote Alita H5 项目的脚手架。
3
+ 帮助你快速使用 alita,基于Umi.js 的移动端框架
4
4
 
5
- ## 使用方式
5
+ ```
6
+ yarn
7
+ yarn dev
8
+ ```
6
9
 
7
- 发布到 npm 后执行:
10
+ ### 首页
8
11
 
9
- ```bash
10
- yarn create @talknote/talknote-h5 my-project
11
- ```
12
+ ![image](https://user-images.githubusercontent.com/11746742/179654827-2ca22b45-0ec9-471e-8238-9bfa56d864a0.png)
12
13
 
13
- 其中 `my-project` 是必填的项目名称。项目名称只允许小写字母、数字、点号、下划线和连字符,并且必须以小写字母或数字开头。
14
+ ### 列表页
14
15
 
15
- 生成完成后执行:
16
+ 列表页支持滚动加载更多,固定头部,状态保持
16
17
 
17
- ```bash
18
- cd my-project
19
- yarn
20
- yarn start
21
- ```
18
+ ![image](https://user-images.githubusercontent.com/11746742/179654907-585061f1-02cc-464e-ac75-c6ae12b2c666.png)
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
- 脚手架不会自动安装依赖,也不会初始化 Git 仓库。
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
- ```bash
30
- npm test
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
- ```bash
36
- node bin/create-talknote-h5.js my-project
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
- 生成项目的全部内容位于 `template/`。修改模板时,不要把 `node_modules`、构建产物或 Git 数据放入该目录。
142
+ > 关闭 app.ts 中已经配置好的 Tab ,上述 remove 配置改为 remove: true
42
143
 
43
- 模板中的 `_gitignore` 和 `_npmrc` 会在生成项目时分别恢复为 `.gitignore` 和 `.npmrc`。
144
+ ### 格式化
44
145
 
45
- ## 发布
146
+ ```
147
+ yarn format
148
+ ```
46
149
 
47
- 确认包名和版本后,由维护者自行登录 npm 并发布:
150
+ ### 构建
48
151
 
49
- ```bash
50
- npm login
51
- npm publish
52
152
  ```
153
+ yarn build
154
+ ```
155
+
156
+ ### 调试工具
53
157
 
54
- 发布完成后即可使用 `yarn create talknote-h5 my-project`。
158
+ 在 `config/config.ts` 中增加配置
159
+
160
+ ```
161
+ aconsole: {
162
+ console: {},
163
+ inspx: {},
164
+ },
165
+ ```
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "access": "public",
5
5
  "registry": "https://registry.npmjs.org/"
6
6
  },
7
- "version": "0.0.2",
7
+ "version": "0.0.3",
8
8
  "description": "Create a Talknote Alita H5 project.",
9
9
  "license": "MIT",
10
10
  "private": false,
@@ -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 是否包含开发依赖,应以项目实际扫描配置和报告为准。
@@ -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
- // router.goBack();
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[] = [