@_tc/template-core 0.2.0-bate.1 → 0.2.0-bate.10
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/.skills/tc-generator/reference/model-schema.md +18 -0
- package/.skills/tc-generator/reference/runtime-extensions.md +20 -0
- package/AGENT_README.md +29 -11
- package/README.md +215 -27
- package/cjs/app/controller/view.js +1 -1
- package/cjs/bundler/buildFE.js +1 -0
- package/cjs/bundler/index.js +1 -1
- package/cjs/bundler/utils.js +1 -1
- package/cjs/packages/common/index.js +1 -1
- package/cjs/packages/common/rafTimer.js +1 -0
- package/esm/app/controller/view.js +4 -1
- package/esm/bundler/buildFE.js +14 -0
- package/esm/bundler/index.js +3 -15
- package/esm/bundler/utils.js +1 -0
- package/esm/packages/common/index.js +3 -2
- package/esm/packages/common/rafTimer.js +47 -0
- package/fe/frontend/apps/dash/Dashboard.js +6 -4
- package/fe/frontend/apps/dash/dash.entry.js +4 -0
- package/fe/frontend/src/common/generateMenuData.d.ts +4 -1
- package/fe/frontend/src/common/generateMenuData.js +3 -3
- package/fe/frontend/src/common/language.d.ts +12 -1
- package/fe/frontend/src/common/language.js +25 -4
- package/fe/frontend/src/common/rafTimer.d.ts +1 -0
- package/fe/frontend/src/common/rafTimer.js +2 -0
- package/fe/frontend/src/common/request.js +1 -0
- package/fe/frontend/src/common/theme.d.ts +7 -0
- package/fe/frontend/src/common/theme.js +33 -0
- package/fe/frontend/src/components/BasePage/HeaderView.js +2 -2
- package/fe/frontend/src/components/LanguageSwitch/LanguageSwitch.js +22 -6
- package/fe/frontend/src/components/ThemeSwitch/ThemeSwitch.d.ts +3 -2
- package/fe/frontend/src/components/ThemeSwitch/ThemeSwitch.js +6 -29
- package/fe/frontend/src/components/ThemeSwitch/index.d.ts +1 -0
- package/fe/frontend/src/components/ThemeSwitch/index.js +3 -2
- package/fe/frontend/src/components/index.js +2 -2
- package/fe/frontend/src/defaultPages/NotFoundPage/index.js +4 -3
- package/fe/frontend/src/defaultPages/SchemaPage/components/CallCom/DetailPanel.js +14 -9
- package/fe/frontend/src/defaultPages/SchemaPage/components/CallCom/PopFrom.js +8 -7
- package/fe/frontend/src/defaultPages/SchemaPage/components/SchemaSearch/index.js +20 -24
- package/fe/frontend/src/defaultPages/SchemaPage/components/SchemaTable/PreviewImage.d.ts +10 -0
- package/fe/frontend/src/defaultPages/SchemaPage/components/SchemaTable/PreviewImage.js +17 -0
- package/fe/frontend/src/defaultPages/SchemaPage/components/SchemaTable/data.d.ts +5 -0
- package/fe/frontend/src/defaultPages/SchemaPage/components/SchemaTable/data.js +8 -0
- package/fe/frontend/src/defaultPages/SchemaPage/components/SchemaTable/index.js +50 -32
- package/fe/frontend/src/defaultPages/SchemaPage/index.css +0 -4
- package/fe/frontend/src/defaultPages/SchemaPage/index.js +5 -3
- package/fe/frontend/src/defaultPages/SlotPage/index.js +6 -3
- package/fe/frontend/src/hooks/useText.d.ts +3 -0
- package/fe/frontend/src/hooks/useText.js +14 -0
- package/fe/frontend/src/index.d.ts +11 -3
- package/fe/frontend/src/index.js +8 -3
- package/fe/frontend/src/language/index.d.ts +0 -2
- package/fe/frontend/src/language/index.js +1 -7
- package/fe/frontend/src/language/resources.d.ts +2 -0
- package/fe/frontend/src/language/resources.js +9 -0
- package/fe/model/types/data/schema.d.ts +24 -2
- package/fe/model/types/index.d.ts +1 -0
- package/fe/packages/common/i18n/default.js +3 -0
- package/fe/packages/common/i18n/en-US.js +5 -2
- package/fe/packages/common/i18n/index.js +13 -0
- package/fe/packages/common/i18n/locales.js +7 -0
- package/fe/packages/common/index.d.ts +1 -0
- package/fe/packages/common/rafTimer.d.ts +7 -0
- package/fe/packages/common/rafTimer.js +168 -0
- package/fe/packages/react/hooks/index.d.ts +9 -0
- package/fe/packages/react/hooks/index.js +8 -0
- package/fe/packages/react/hooks/useRefState.d.ts +4 -12
- package/fe/packages/react/hooks/useRefState.js +18 -8
- package/fe/packages/react/ui/components/DataTable/dataTableWidth.d.ts +12 -0
- package/fe/packages/react/ui/components/DataTable/dataTableWidth.js +33 -0
- package/fe/packages/react/ui/components/DataTable/dataTableWidth.test.js +39 -0
- package/fe/packages/react/ui/components/DataTable/index.d.ts +1 -1
- package/fe/packages/react/ui/components/DataTable/index.js +12 -32
- package/fe/packages/react/ui/components/Textarea/Textarea.d.ts +1 -1
- package/fe/packages/react/ui/components/Textarea/Textarea.js +1 -1
- package/fe/packages/react/ui/components/types/baseType.d.ts +21 -0
- package/fe/packages/react/ui/components/types/baseType.js +0 -0
- package/model/frontend/src/common/language.d.ts +12 -1
- package/model/frontend/src/hooks/useText.d.ts +3 -0
- package/model/frontend/src/language/index.d.ts +0 -2
- package/model/frontend/src/language/resources.d.ts +2 -0
- package/model/model/types/data/schema.d.ts +24 -2
- package/model/model/types/index.d.ts +1 -0
- package/model/packages/common/index.d.ts +1 -0
- package/model/packages/common/rafTimer.d.ts +7 -0
- package/model/packages/react/ui/components/DataTable/dataTableWidth.d.ts +12 -0
- package/model/packages/react/ui/components/DataTable/index.d.ts +1 -1
- package/model/packages/react/ui/components/Textarea/Textarea.d.ts +1 -1
- package/model/packages/react/ui/components/types/baseType.d.ts +21 -0
- package/package.json +5 -5
- package/types/bundler/buildFE.d.ts +2 -0
- package/types/bundler/index.d.ts +1 -2
- package/types/packages/common/i18n/default.d.ts +4 -0
- package/types/packages/common/i18n/en-US.d.ts +6 -2
- package/types/packages/common/i18n/index.d.ts +21 -0
- package/types/packages/common/i18n/locales.d.ts +10 -0
- package/types/packages/common/i18n/types.d.ts +40 -0
- package/types/packages/common/index.d.ts +1 -0
- package/types/packages/common/rafTimer.d.ts +44 -0
|
@@ -210,6 +210,24 @@ Option meaning:
|
|
|
210
210
|
| `editFormOption` | Edit modal form field. Omit to hide from edit. |
|
|
211
211
|
| `detailPanelOption` | Detail drawer field. Omit to hide from detail. |
|
|
212
212
|
|
|
213
|
+
Table cell render components:
|
|
214
|
+
|
|
215
|
+
```js
|
|
216
|
+
cover: {
|
|
217
|
+
type: "string",
|
|
218
|
+
label: "Cover",
|
|
219
|
+
tableOption: {
|
|
220
|
+
renderComponent: "PreviewImage",
|
|
221
|
+
renderComponentProps: {
|
|
222
|
+
width: 48,
|
|
223
|
+
height: 48,
|
|
224
|
+
},
|
|
225
|
+
},
|
|
226
|
+
}
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
Built-in `PreviewImage` accepts the current field value as a string or string array. Project-specific table render components are registered in `frontend/extended/SchemaPage/SchemaTable/data.ts` and referenced by `tableOption.renderComponent`.
|
|
230
|
+
|
|
213
231
|
Common form `comType` values:
|
|
214
232
|
|
|
215
233
|
```text
|
|
@@ -295,6 +295,26 @@ this.success(ctx, [
|
|
|
295
295
|
|
|
296
296
|
For project-specific field types, create `frontend/extended/SchemaForm/data.ts` and default-export a component map keyed by field type.
|
|
297
297
|
|
|
298
|
+
## SchemaTable Render Components
|
|
299
|
+
|
|
300
|
+
Use `tableOption.renderComponent` when a Schema CRUD table column needs a reusable renderer. TemplateCore includes `PreviewImage` for image preview columns:
|
|
301
|
+
|
|
302
|
+
```js
|
|
303
|
+
cover: {
|
|
304
|
+
type: "string",
|
|
305
|
+
label: "Cover",
|
|
306
|
+
tableOption: {
|
|
307
|
+
renderComponent: "PreviewImage",
|
|
308
|
+
renderComponentProps: {
|
|
309
|
+
width: 48,
|
|
310
|
+
height: 48,
|
|
311
|
+
},
|
|
312
|
+
},
|
|
313
|
+
}
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
For project-specific renderers, create `frontend/extended/SchemaPage/SchemaTable/data.ts` and default-export a component map typed as `SchemaTableRenderComponentsMap` from `@_tc/template-core/fe`. Extend `SchemaTableNamespace.RenderComponentPropsMap` from `@_tc/template-core/model` when TypeScript model config should know the renderer props.
|
|
317
|
+
|
|
298
318
|
## SchemaPage CallCom Extensions
|
|
299
319
|
|
|
300
320
|
Use `frontend/extended/SchemaPage/CallCom/data.ts` when model `componentConfig` should open a custom runtime component instead of built-in create/edit/detail components. Custom components can import `schemaEventBus`, `eventsInfo`, and `merge` from `@_tc/template-core/fe` to close panels or refresh Schema tables.
|
package/AGENT_README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# TemplateCore AI 助手速读
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
这份文档由 TemplateCore 框架提供方维护,面向下游消费方项目中的 AI 助手/代码代理。消费方项目通过 `@_tc/template-core` 使用框架能力;AI 可以通过这份速读文档快速理解包的公开入口、约定用法和边界。它是 `README.md` 的面向 Agent 的精简版,按渐进式披露组织:先用下面的最小信息完成常见任务,只有需要深入时再读末尾的参考文档。
|
|
4
4
|
|
|
5
5
|
## 1. 先看结论
|
|
6
6
|
|
|
@@ -11,7 +11,7 @@ TemplateCore 是一个 TypeScript + Koa + React 的后台框架包。它提供
|
|
|
11
11
|
- `model/` 配置驱动的菜单、项目和 CRUD 页面。
|
|
12
12
|
- 前端构建 `buildFE()` 输出服务端可渲染的 `.entry.tpl`,并写入 `FEBuildKey` 供 HTML ETag 缓存失效使用。
|
|
13
13
|
- 消费方 Node/backend 构建 `buildBE()`。
|
|
14
|
-
- 类型扩展机制,用于扩展 SchemaForm 字段、CallCom 组件和 Koa app 类型。
|
|
14
|
+
- 类型扩展机制,用于扩展 SchemaForm 字段、SchemaTable 单元格渲染组件、CallCom 组件和 Koa app 类型。
|
|
15
15
|
|
|
16
16
|
优先使用公开入口,不要从包内部源码路径导入。下面这些入口以 npm 发布产物为准;源码仓库根 `package.json` 的 `exports` 会在构建发布包时生成到 `dist/package.json`。
|
|
17
17
|
|
|
@@ -19,9 +19,11 @@ TemplateCore 是一个 TypeScript + Koa + React 的后台框架包。它提供
|
|
|
19
19
|
| --- | --- |
|
|
20
20
|
| `@_tc/template-core` | `serverStart`、`baseFn`、Koa/Controller/Service 类型。 |
|
|
21
21
|
| `@_tc/template-core/bundler` | `buildFE()`、`buildBE()`。 |
|
|
22
|
-
| `@_tc/template-core/fe` |
|
|
22
|
+
| `@_tc/template-core/fe` | 前端初始化、动态组件渲染辅助、请求方法、Dashboard/Schema 类型、token 工具、RAF 计时器、共享状态、业务前端组件。 |
|
|
23
|
+
| `@_tc/template-core/fe/main` | 前端初始化入口。 |
|
|
23
24
|
| `@_tc/template-core/fe/common/request` | 请求实例、请求方法和请求类型的显式子路径。 |
|
|
24
25
|
| `@_tc/template-core/fe/rc` | React UI 组件和 SchemaForm 组件。 |
|
|
26
|
+
| `@_tc/template-core/fe/rc/hooks` | React hooks 汇总入口。 |
|
|
25
27
|
| `@_tc/template-core/fe/tailwind_ui.css` | 内置前端/UI 全局样式。 |
|
|
26
28
|
| `@_tc/template-core/model` | `ModelDataType` 等 model 配置类型。 |
|
|
27
29
|
|
|
@@ -367,13 +369,24 @@ import '@_tc/template-core/fe/tailwind_ui.css'
|
|
|
367
369
|
|
|
368
370
|
```ts
|
|
369
371
|
import {
|
|
372
|
+
addLanguageResources,
|
|
373
|
+
clearRafTimer,
|
|
370
374
|
api,
|
|
375
|
+
clearAuthToken,
|
|
371
376
|
get,
|
|
377
|
+
getAuthToken,
|
|
378
|
+
localKeyMap,
|
|
372
379
|
post,
|
|
380
|
+
renderImportComponent,
|
|
373
381
|
request,
|
|
382
|
+
rafSetInterval,
|
|
383
|
+
rafSetTimeout,
|
|
374
384
|
schemaEventBus,
|
|
375
385
|
schemaStore,
|
|
386
|
+
setAuthToken,
|
|
387
|
+
setLanguage,
|
|
376
388
|
useSchemaStore,
|
|
389
|
+
useText,
|
|
377
390
|
LanguageSwitch,
|
|
378
391
|
ThemeSwitch,
|
|
379
392
|
} from '@_tc/template-core/fe'
|
|
@@ -401,15 +414,19 @@ import { Button, DataTable, Form, Input, Modal, Select } from '@_tc/template-cor
|
|
|
401
414
|
常用前端能力:
|
|
402
415
|
|
|
403
416
|
- 请求方法:`api`、`request`、`get`、`post`、`put`、`patch`、`del`。
|
|
417
|
+
- RAF 风格计时器:`rafSetTimeout`、`rafSetInterval`、`rafClearTimeout`、`rafClearInterval`、`clearRafTimer`,缺少 RAF 时自动降级到 `setTimeout`。
|
|
404
418
|
- 请求类型:`BaseResponse`、`PageParams`、`PageResponse`、`RequestConfig`、`ResponseConfig`、`AxiosError`。
|
|
405
419
|
- 请求 header:自动添加 `s_t`、`s_sign`、`projk`;存在短 token 时添加 `Authorization: Bearer ${token}`。
|
|
420
|
+
- 默认会先设置 `Content-Type: application/json`;如果是上传文件、`FormData` 或其他内容类型,请在请求配置里显式覆盖。
|
|
421
|
+
- Token 工具:`getAuthToken()`、`setAuthToken()`、`clearAuthToken()`、`localKeyMap`;`getAuthToken()` 是同步函数,读取前无需 `await`。
|
|
406
422
|
- 本地 key:短 token 是 `localStorage.auth_token`,项目 key 是 `localStorage.p_J_k`;刷新 token header 默认名是 `RT`。
|
|
407
|
-
-
|
|
423
|
+
- 组件加载辅助:`renderImportComponent(import('./Page'))` 会用 `React.lazy` + `Suspense` 渲染动态组件。
|
|
408
424
|
- Schema 通信:`schemaEventBus`、`eventsInfo`、`merge`。
|
|
409
425
|
- 共享状态:`modeStore`、`schemaStore`、`apiFreezerStore` 及对应 hooks。
|
|
410
|
-
- 多语言:`
|
|
426
|
+
- 多语言:`addLanguageResources()` 追加或新增某语种文案,`setLanguage()` 切换语言,React render 中用 `useText()`,非 React 工具代码用 `getText()`,配置文案可写 `$i18n::...`。
|
|
411
427
|
- 主题:`ThemeSwitch` 会同步根节点 `dark` class 和 `localStorage`。
|
|
412
428
|
- `Input type="password"` 会自动显示密码显隐按钮;`allowClear` 不作用于密码输入。
|
|
429
|
+
- RAF 风格计时器由 `@tc/common/rafTimer` 提供,浏览器优先使用 RAF,Node/SSR 自动降级到 `setTimeout`。
|
|
413
430
|
|
|
414
431
|
不要直接依赖 `frontend/src/...`、`packages/react/ui/...` 这类包内部路径。
|
|
415
432
|
|
|
@@ -609,13 +626,14 @@ chokidar
|
|
|
609
626
|
|
|
610
627
|
扩展前端类型或组件:
|
|
611
628
|
|
|
612
|
-
1. SchemaForm 字段类型、CallCom 组件、Koa app 类型都支持 TypeScript 声明合并。
|
|
629
|
+
1. SchemaForm 字段类型、SchemaTable 单元格渲染组件、CallCom 组件、Koa app 类型都支持 TypeScript 声明合并。
|
|
613
630
|
2. 运行时组件通常放在业务 `frontend/extended/`。
|
|
614
|
-
3.
|
|
615
|
-
4. `dash/init
|
|
616
|
-
5. `dash/
|
|
617
|
-
6.
|
|
618
|
-
7.
|
|
631
|
+
3. 表格单元格渲染组件注册到 `frontend/extended/SchemaPage/SchemaTable/data.ts`,字段上用 `tableOption.renderComponent` 和 `renderComponentProps`。
|
|
632
|
+
4. Dashboard 扩展点包括 `frontend/extended/dash/init.ts`、`frontend/extended/dash/customRoutes.tsx`、`frontend/extended/dash/components.tsx`、`frontend/extended/dash/routeGuard.ts`。
|
|
633
|
+
5. `dash/init` 在 React 渲染前执行,适合注册 axios 拦截器等全局初始化逻辑;类型是 `DashInit`。
|
|
634
|
+
6. `dash/routeGuard` 用来判断登录。返回登录页 URL 字符串时,Dashboard 用 `window.location.href` 跳转;`DashRouteGuardResult` 是 `string | undefined`,`undefined`(包括已登录分支的隐式返回)会打断 Dashboard 内置重定向,业务方可自行跳转。
|
|
635
|
+
7. 自定义入口的 `initApp` 支持 `beforeRender` / `afterRender`,分别在 React 渲染前和首次渲染提交后触发。
|
|
636
|
+
8. 优先查看公开入口 `.d.ts` 和 npm 包根目录 `README.md`;如果当前环境是源码仓库,再继续读 `docs/type-extension.md` 和 `docs/schema-form.md`。
|
|
619
637
|
|
|
620
638
|
## 8. 继续深入
|
|
621
639
|
|
package/README.md
CHANGED
|
@@ -116,7 +116,7 @@ export default {
|
|
|
116
116
|
}
|
|
117
117
|
```
|
|
118
118
|
|
|
119
|
-
`auth.ATKey` / `auth.RTKey`
|
|
119
|
+
`auth.ATKey` / `auth.RTKey` 用于约定项目鉴权中间件读取短 token 和刷新 token 的 header 名;默认分别为 `Authorization` 和 `RT`。
|
|
120
120
|
|
|
121
121
|
静态资源挂载顺序为:项目 `app/public`、框架 `app/public`、`additionalPublicPaths`。Nunjucks 模板查找顺序为:项目 `app/public/dist`、框架 `app/public/dist`、`additionalPublicPaths/dist`。这些目录由 `app.publicsPath` 统一维护。当 `buildFE` 输出到自定义目录时,可以用 `additionalPublicPaths` 把该目录交给 Koa 提供静态资源访问和模板渲染;如果需要模板查找也命中追加目录,请传绝对路径数组。
|
|
122
122
|
|
|
@@ -127,7 +127,7 @@ buildFE(mode: 'dev' | 'prod', options?: BuildFEOptions)
|
|
|
127
127
|
```
|
|
128
128
|
|
|
129
129
|
**mode**:构建模式
|
|
130
|
-
- `'dev'
|
|
130
|
+
- `'dev'`:开发模式,构建一次并监听项目 `frontend/` 变化后重建
|
|
131
131
|
- `'prod'`:生产模式,构建优化后的静态资源
|
|
132
132
|
|
|
133
133
|
**options.output**:构建输出位置
|
|
@@ -176,20 +176,23 @@ http://localhost:9000/dash?projk=demo
|
|
|
176
176
|
|
|
177
177
|
## 常用公开入口
|
|
178
178
|
|
|
179
|
-
完整 exports 以发布包内 `package.json` 为准,除下表外还包含 `./fe/main`、`./fe/*`、`./fe/rc/*`、`./fe/rc/hooks
|
|
179
|
+
完整 exports 以发布包内 `package.json` 为准,除下表外还包含 `./fe/main`、`./fe/common/request`、`./fe/*`、`./fe/rc/*`、`./fe/rc/hooks` 等子路径。
|
|
180
180
|
|
|
181
181
|
| 入口 | 用途 |
|
|
182
182
|
| --- | --- |
|
|
183
183
|
| `@_tc/template-core` | 服务启动、基础 Controller/Service、Koa 类型 |
|
|
184
184
|
| `@_tc/template-core/bundler` | 构建入口,提供前端资源构建 `buildFE` 和消费方 Node/backend 构建 `buildBE` |
|
|
185
|
-
| `@_tc/template-core/fe` |
|
|
185
|
+
| `@_tc/template-core/fe` | 前端初始化、动态组件渲染辅助、Dash 路由扩展、请求方法、SchemaPage 事件、token 工具、共享状态和内置前端组件 |
|
|
186
|
+
| `@_tc/template-core/fe/main` | 前端初始化入口 |
|
|
187
|
+
| `@_tc/template-core/fe/common/request` | 请求实例、请求方法和请求类型的显式子路径 |
|
|
186
188
|
| `@_tc/template-core/fe/rc` | UI/SchemaForm 组件和类型 |
|
|
189
|
+
| `@_tc/template-core/fe/rc/hooks` | React hooks 汇总入口 |
|
|
187
190
|
| `@_tc/template-core/fe/tailwind_ui.css` | 前端全局样式入口,源码对应 `frontend/src/main.css` |
|
|
188
191
|
| `@_tc/template-core/model` | model 配置类型 |
|
|
189
192
|
|
|
190
193
|
### 后端类型
|
|
191
194
|
|
|
192
|
-
`@_tc/template-core` 会导出常用 Node
|
|
195
|
+
`@_tc/template-core` 会导出常用 Node 侧类型,项目编写 `app/*` 文件时建议优先复用这些类型。
|
|
193
196
|
|
|
194
197
|
| 类型 | 使用场景 |
|
|
195
198
|
| --- | --- |
|
|
@@ -300,7 +303,7 @@ VS Code 建议安装官方 Tailwind CSS IntelliSense 插件,并在工作区 `.
|
|
|
300
303
|
- 内置 UI 组件:提供丰富的 React 组件库,详见下方"内置 UI 组件"章节。
|
|
301
304
|
- API 中间件:错误处理、静态资源、body parser、项目上下文、接口签名、参数校验。
|
|
302
305
|
- 前端构建:扫描框架和项目的 `frontend/**/*.entry.{ts,tsx,js,jsx}`,输出服务端可渲染的 `.entry.tpl`,并写入 `FEBuildKey` 供 HTML ETag 缓存失效使用。
|
|
303
|
-
- 类型扩展:支持扩展 SchemaForm、CallCom、KoaApp。
|
|
306
|
+
- 类型扩展:支持扩展 SchemaForm、SchemaTable 单元格渲染组件、CallCom、KoaApp。
|
|
304
307
|
|
|
305
308
|
## 前端公共能力
|
|
306
309
|
|
|
@@ -310,21 +313,36 @@ VS Code 建议安装官方 Tailwind CSS IntelliSense 插件,并在工作区 `.
|
|
|
310
313
|
import {
|
|
311
314
|
api,
|
|
312
315
|
apiFreezerStore,
|
|
316
|
+
addLanguageResources,
|
|
313
317
|
AsyncSelect,
|
|
318
|
+
clearAuthToken,
|
|
314
319
|
eventsInfo,
|
|
320
|
+
getCurrentLanguage,
|
|
321
|
+
getFallbackLanguage,
|
|
315
322
|
FreezeState,
|
|
316
323
|
get,
|
|
324
|
+
getSupportedLanguages,
|
|
325
|
+
getAuthToken,
|
|
317
326
|
LanguageSwitch,
|
|
327
|
+
localKeyMap,
|
|
318
328
|
merge,
|
|
319
329
|
modeStore,
|
|
320
330
|
post,
|
|
331
|
+
renderImportComponent,
|
|
332
|
+
registerFrontendI18nResources,
|
|
321
333
|
request,
|
|
322
334
|
schemaEventBus,
|
|
323
335
|
schemaStore,
|
|
336
|
+
setFallbackLanguage,
|
|
337
|
+
setLanguage,
|
|
338
|
+
setResources,
|
|
339
|
+
setAuthToken,
|
|
324
340
|
ThemeSwitch,
|
|
341
|
+
t,
|
|
325
342
|
useApiFreezer,
|
|
326
343
|
useModeStore,
|
|
327
344
|
useSchemaStore,
|
|
345
|
+
useText,
|
|
328
346
|
} from '@_tc/template-core/fe'
|
|
329
347
|
|
|
330
348
|
import type {
|
|
@@ -340,6 +358,8 @@ import type {
|
|
|
340
358
|
PageResponse,
|
|
341
359
|
RequestConfig,
|
|
342
360
|
ResponseConfig,
|
|
361
|
+
SchemaTableRenderComponent,
|
|
362
|
+
SchemaTableRenderComponentsMap,
|
|
343
363
|
SchemaFormComponentsMap,
|
|
344
364
|
SchemaFormNamespace,
|
|
345
365
|
SelectProps,
|
|
@@ -352,30 +372,50 @@ import type {
|
|
|
352
372
|
| --- | --- |
|
|
353
373
|
| 应用启动 | `initApp` |
|
|
354
374
|
| 内置前端组件 | `AsyncSelect`、`LanguageSwitch`、`ThemeSwitch` |
|
|
375
|
+
| 组件加载辅助 | `renderImportComponent` |
|
|
355
376
|
| Dash 扩展类型 | `DashRoutesExtender`、`DashRoutesContext`、`DashComponentsMap`、`DashHeaderUserAreaProps`、`DashRouteGuard` |
|
|
356
|
-
| SchemaPage 类型 | `CallComComponentsMap`、`CallComRenderer` |
|
|
377
|
+
| SchemaPage 类型 | `CallComComponentsMap`、`CallComRenderer`、`SchemaTableRenderComponent`、`SchemaTableRenderComponentsMap` |
|
|
357
378
|
| SchemaForm 类型 | `FormFieldSchema`、`SchemaFormComponentsMap`、`SchemaFormNamespace`、`SelectProps` |
|
|
358
379
|
| 请求方法 | `api`、`request`、`get`、`post`、`put`、`patch`、`del` |
|
|
359
380
|
| 请求类型 | `BaseResponse`、`PageParams`、`PageResponse`、`RequestConfig`、`ResponseConfig`、`AxiosError` |
|
|
381
|
+
| RAF 风格计时器 | `rafSetTimeout`、`rafSetInterval`、`rafClearTimeout`、`rafClearInterval`、`clearRafTimer`、`RafTimerId`、`RafTimerCallback` |
|
|
382
|
+
| Token 工具 | `getAuthToken`、`setAuthToken`、`clearAuthToken`、`localKeyMap` |
|
|
383
|
+
| 多语言工具 | `useText`、`getText`、`t`、`registerFrontendI18nResources`、`addLanguageResources`、`setLanguage`、`setFallbackLanguage`、`setResources`、`getCurrentLanguage`、`getFallbackLanguage`、`getSupportedLanguages` |
|
|
360
384
|
| 请求冻结 | `apiFreezerStore`、`useApiFreezer`、`FreezeState`、`ApiFreezerRequestMatcher` |
|
|
361
385
|
| 事件工具 | `eventsInfo`、`merge` |
|
|
362
386
|
| 共享状态 | `modeStore`、`useModeStore`、`schemaStore`、`useSchemaStore`、`schemaEventBus` |
|
|
363
387
|
|
|
364
388
|
`modeStore` 管项目模型和当前项目数据,`schemaStore` 管当前 Schema 页面的 schema/cache,`schemaEventBus` 用来在 Search、Table、CallCom 之间通信。
|
|
365
389
|
|
|
390
|
+
`renderImportComponent` 封装了 `React.lazy` + `Suspense`,默认会用页面骨架屏作为 fallback。`getAuthToken()`、`setAuthToken()` 和 `clearAuthToken()` 用于读写或清理本地短 token,`localKeyMap` 暴露对应的本地存储 key 常量。
|
|
391
|
+
|
|
366
392
|
只使用请求层时,也可以从 `@_tc/template-core/fe/common/request` 导入 `api`、请求方法和请求类型;这是发布包显式子路径,不要下钻到 `frontend/src/common/request`。
|
|
367
393
|
|
|
368
394
|
### 前端多语言
|
|
369
395
|
|
|
370
|
-
TemplateCore 前端通过 `@_tc/template-core/fe` 暴露 i18n
|
|
396
|
+
TemplateCore 前端通过 `@_tc/template-core/fe` 暴露 i18n 能力。框架内置中文、英文资源,但不会在普通自定义页面 import 前端入口时自动注册,避免非 Dashboard 页面把框架文案整包带入运行时资源。
|
|
397
|
+
|
|
398
|
+
默认 Dashboard 入口会自动调用 `registerFrontendI18nResources()`,所以 Dashboard、Schema CRUD、内置页头、语言切换等框架页面可以直接使用框架内置文案。自定义入口如果也要复用这些框架文案,需要在渲染前手动注册:
|
|
399
|
+
|
|
400
|
+
```ts
|
|
401
|
+
import { initApp, registerFrontendI18nResources } from '@_tc/template-core/fe'
|
|
402
|
+
|
|
403
|
+
initApp(App, {
|
|
404
|
+
beforeRender: async () => {
|
|
405
|
+
await registerFrontendI18nResources()
|
|
406
|
+
},
|
|
407
|
+
})
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
项目可以继续追加自己的资源或新增语种。
|
|
371
411
|
|
|
372
412
|
**追加自定义语言资源**:
|
|
373
413
|
|
|
374
414
|
```ts
|
|
375
|
-
import {
|
|
415
|
+
import { addLanguageResources } from '@_tc/template-core/fe'
|
|
376
416
|
|
|
377
|
-
|
|
378
|
-
|
|
417
|
+
addLanguageResources('zh-CN', {
|
|
418
|
+
app: {
|
|
379
419
|
product: {
|
|
380
420
|
menu: '商品管理',
|
|
381
421
|
name: '商品名称',
|
|
@@ -385,8 +425,8 @@ i18nStore.getState().addResources('zh-CN', {
|
|
|
385
425
|
},
|
|
386
426
|
})
|
|
387
427
|
|
|
388
|
-
|
|
389
|
-
|
|
428
|
+
addLanguageResources('en-US', {
|
|
429
|
+
app: {
|
|
390
430
|
product: {
|
|
391
431
|
menu: 'Products',
|
|
392
432
|
name: 'Product name',
|
|
@@ -397,17 +437,49 @@ i18nStore.getState().addResources('en-US', {
|
|
|
397
437
|
})
|
|
398
438
|
```
|
|
399
439
|
|
|
440
|
+
**新增语种并切换**:
|
|
441
|
+
|
|
442
|
+
```ts
|
|
443
|
+
import { addLanguageResources, setLanguage } from '@_tc/template-core/fe'
|
|
444
|
+
|
|
445
|
+
addLanguageResources('ja-JP', {
|
|
446
|
+
app: {
|
|
447
|
+
product: {
|
|
448
|
+
menu: '商品管理',
|
|
449
|
+
},
|
|
450
|
+
},
|
|
451
|
+
})
|
|
452
|
+
|
|
453
|
+
setLanguage('ja-JP')
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
`addLanguageResources()` 用于追加或新增某个语种的文案,默认会深合并同语种资源;传 `{ merge: false }` 可以替换该语种资源。`setResources(resources, { merge: true })` 可批量合并多语种资源。`LanguageSwitch` 默认会把已注册语种加入选项;需要自定义展示文案时仍可传入 `options`。
|
|
457
|
+
|
|
458
|
+
React 组件 render 中使用 `useText()` 读取文案。它会订阅语言和资源变化,调用 `setLanguage()` 后组件会自动重渲染:
|
|
459
|
+
|
|
460
|
+
```tsx
|
|
461
|
+
import { useText } from '@_tc/template-core/fe'
|
|
462
|
+
|
|
463
|
+
function ProductTitle() {
|
|
464
|
+
const text = useText()
|
|
465
|
+
|
|
466
|
+
return <h1>{text('$i18n::app.product.menu')}</h1>
|
|
467
|
+
}
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
`getText()` 是普通函数,适合请求错误、日志、校验工具或事件回调等非 React 场景;它不会主动触发 React 组件重渲染。
|
|
471
|
+
|
|
400
472
|
资源注册时不写 `$i18n::` 前缀,配置中使用时才写:
|
|
401
473
|
|
|
402
474
|
```ts
|
|
403
|
-
const title = '$i18n::
|
|
475
|
+
const title = '$i18n::app.product.createTitle'
|
|
404
476
|
```
|
|
405
477
|
|
|
406
478
|
**在 model / Schema 配置中使用**:
|
|
407
479
|
|
|
408
480
|
```ts
|
|
409
481
|
{
|
|
410
|
-
name: '$i18n::
|
|
482
|
+
name: '$i18n::app.product.menu',
|
|
411
483
|
moduleType: 'schema',
|
|
412
484
|
schemaConfig: {
|
|
413
485
|
schema: {
|
|
@@ -415,7 +487,7 @@ const title = '$i18n::business.product.createTitle'
|
|
|
415
487
|
properties: {
|
|
416
488
|
name: {
|
|
417
489
|
type: 'string',
|
|
418
|
-
label: '$i18n::
|
|
490
|
+
label: '$i18n::app.product.name',
|
|
419
491
|
minLength: 2,
|
|
420
492
|
createFormOption: {
|
|
421
493
|
comType: 'input',
|
|
@@ -429,7 +501,7 @@ const title = '$i18n::business.product.createTitle'
|
|
|
429
501
|
tableConfig: {
|
|
430
502
|
headerButtons: [
|
|
431
503
|
{
|
|
432
|
-
label: '$i18n::
|
|
504
|
+
label: '$i18n::app.product.create',
|
|
433
505
|
eventKey: 'callComponent',
|
|
434
506
|
eventOption: { comName: 'createForm' },
|
|
435
507
|
},
|
|
@@ -437,7 +509,7 @@ const title = '$i18n::business.product.createTitle'
|
|
|
437
509
|
},
|
|
438
510
|
componentConfig: {
|
|
439
511
|
createForm: {
|
|
440
|
-
title: '$i18n::
|
|
512
|
+
title: '$i18n::app.product.createTitle',
|
|
441
513
|
saveBtnText: '$i18n::common.submit',
|
|
442
514
|
},
|
|
443
515
|
},
|
|
@@ -502,7 +574,7 @@ export function Toolbar() {
|
|
|
502
574
|
}
|
|
503
575
|
```
|
|
504
576
|
|
|
505
|
-
`ThemeSwitch` 会切换 `document.documentElement` 上的 `dark` class,并同步 `color-scheme`。默认写入 localStorage,key 是 `tc_theme`。刷新页面后会优先读取本地主题;没有本地主题时,读取当前根节点是否已有 `dark` class
|
|
577
|
+
`ThemeSwitch` 会切换 `document.documentElement` 上的 `dark` class,并同步 `color-scheme`。默认写入 localStorage,key 是 `tc_theme`。刷新页面后会优先读取本地主题;没有本地主题时,读取当前根节点是否已有 `dark` class。默认 Dashboard 会在渲染前调用 `initThemeMode()`,让已保存主题尽早生效。
|
|
506
578
|
|
|
507
579
|
常用参数:
|
|
508
580
|
|
|
@@ -514,6 +586,21 @@ export function Toolbar() {
|
|
|
514
586
|
| `persist` | 是否写入 localStorage,默认 `true`。 |
|
|
515
587
|
| `storageKey` | 自定义本地存储 key,默认 `tc_theme`。 |
|
|
516
588
|
|
|
589
|
+
如需在自定义入口或组件外手动初始化/切换主题,可以从 `@_tc/template-core/fe` 导入主题工具:
|
|
590
|
+
|
|
591
|
+
```ts
|
|
592
|
+
import { applyThemeMode, getCurrentThemeMode, initThemeMode, themeSwitchStorageKey } from '@_tc/template-core/fe'
|
|
593
|
+
|
|
594
|
+
initThemeMode()
|
|
595
|
+
applyThemeMode('dark', true)
|
|
596
|
+
```
|
|
597
|
+
|
|
598
|
+
RAF 风格计时器由 `@tc/common/rafTimer` 提供,浏览器优先使用 `requestAnimationFrame`,缺少 RAF 时自动降级到 `setTimeout`。
|
|
599
|
+
|
|
600
|
+
`@_tc/template-core/fe/rc` 和 `@_tc/template-core/fe/rc/hooks` 也会随发布包提供对应 UI 与 hooks 入口;hooks 汇总入口包含 `useBreadcrumb`、`useExecuteOnce`、`useInit`、`useLanguage`、`usePagination`、`useRefState`、`useWatch`。
|
|
601
|
+
|
|
602
|
+
`useRefState` 支持可选的 `delayTiming` 参数,传入大于 0 的值时会延迟 state 提交,并复用 `@tc/common/rafTimer` 的浏览器优先、Node/SSR 自动降级计时器实现。
|
|
603
|
+
|
|
517
604
|
### 前端请求封装详解
|
|
518
605
|
|
|
519
606
|
框架内置的请求封装基于 `@tc/common/http`,底层使用原生 `fetch` API,实现了类似 Axios 的接口和拦截器机制,提供了签名、鉴权、错误处理等能力。
|
|
@@ -523,6 +610,7 @@ export function Toolbar() {
|
|
|
523
610
|
- `timeout`:15000ms(15秒)
|
|
524
611
|
- `credentials`:`'include'`,支持跨域携带 cookie
|
|
525
612
|
- `window._signKey`:由服务端页面模板从 `app.config.signKey` 注入
|
|
613
|
+
- 默认会先设置 `Content-Type: application/json`;如果是上传文件、`FormData` 或其他内容类型,请在请求配置里显式覆盖
|
|
526
614
|
|
|
527
615
|
**请求拦截器**:
|
|
528
616
|
|
|
@@ -879,7 +967,7 @@ const unsafeUsers = app.extends.db.queryDB(
|
|
|
879
967
|
)
|
|
880
968
|
```
|
|
881
969
|
|
|
882
|
-
|
|
970
|
+
项目可以用自己的 `app/extends/db.ts` 覆盖默认实现。建议保留同一组方法名,这样 controller/service 调用方不用调整。
|
|
883
971
|
|
|
884
972
|
```ts
|
|
885
973
|
// app/extends/db.ts
|
|
@@ -995,7 +1083,7 @@ export default (app: KoaApp, router: Router) => {
|
|
|
995
1083
|
- 每个 `app/router/*.ts` 文件都会获得独立的 `koa-router` 实例。
|
|
996
1084
|
- 可以通过 `router.level = number` 控制挂载顺序,数值越小越早挂载。
|
|
997
1085
|
- 默认 `level` 是 `0`,框架兜底 router 是 `99`。
|
|
998
|
-
- 通配、兜底、重定向类路由建议设置较大的 `level
|
|
1086
|
+
- 通配、兜底、重定向类路由建议设置较大的 `level`,避免抢先匹配项目 API。
|
|
999
1087
|
|
|
1000
1088
|
```ts
|
|
1001
1089
|
import type { KoaApp, Router } from '@_tc/template-core'
|
|
@@ -1284,7 +1372,7 @@ DELETE {api} -> 删除
|
|
|
1284
1372
|
|
|
1285
1373
|
### 服务端兜底路由守卫
|
|
1286
1374
|
|
|
1287
|
-
|
|
1375
|
+
项目可以创建 `app/router-guard.ts` 或 `app/router-guard.js`。它只在所有正常 `app/router/*` 路由都没有命中时执行。
|
|
1288
1376
|
|
|
1289
1377
|
```ts
|
|
1290
1378
|
import type { Ctx, KoaApp } from '@_tc/template-core'
|
|
@@ -1309,7 +1397,7 @@ export default (_app: KoaApp) => {
|
|
|
1309
1397
|
|
|
1310
1398
|
### 扩展 Dashboard 顶部用户区域
|
|
1311
1399
|
|
|
1312
|
-
|
|
1400
|
+
项目可以创建 `frontend/extended/dash/components.tsx`,通过组件映射填充内置 Dashboard 页头右侧区域。
|
|
1313
1401
|
|
|
1314
1402
|
```tsx
|
|
1315
1403
|
// frontend/extended/dash/components.tsx
|
|
@@ -1330,7 +1418,7 @@ export default components
|
|
|
1330
1418
|
|
|
1331
1419
|
### 扩展 Dashboard 登录守卫
|
|
1332
1420
|
|
|
1333
|
-
|
|
1421
|
+
项目可以创建 `frontend/extended/dash/routeGuard.ts`,用于在 Dashboard 内置 `homePage` / 首菜单重定向前做登录判断。
|
|
1334
1422
|
|
|
1335
1423
|
```ts
|
|
1336
1424
|
// frontend/extended/dash/routeGuard.ts
|
|
@@ -1346,9 +1434,9 @@ export default dashRouteGuard
|
|
|
1346
1434
|
返回值规则:
|
|
1347
1435
|
|
|
1348
1436
|
- 返回 `string`:框架使用 `window.location.href` 跳转,登录页不需要在 Dash 路由下。
|
|
1349
|
-
- 返回非 `string`:中断 Dashboard
|
|
1437
|
+
- 返回非 `string`:中断 Dashboard 内置重定向,使用方可自行跳转或处理提示。
|
|
1350
1438
|
- `DashRouteGuardResult` 是 `string | undefined`;`undefined`(包括已登录分支的隐式返回)也会打断 Dashboard 内置重定向。
|
|
1351
|
-
-
|
|
1439
|
+
- 没有自定义 `routeGuard` 文件时,框架使用兜底空对象,不影响默认 Dashboard 重定向。
|
|
1352
1440
|
|
|
1353
1441
|
### 扩展 SchemaForm 字段组件
|
|
1354
1442
|
|
|
@@ -1518,6 +1606,90 @@ remark: {
|
|
|
1518
1606
|
}
|
|
1519
1607
|
```
|
|
1520
1608
|
|
|
1609
|
+
### 扩展 SchemaTable 单元格渲染组件
|
|
1610
|
+
|
|
1611
|
+
SchemaPage 表格列支持通过 `tableOption.renderComponent` 使用内置或自定义注册的渲染组件。内置组件:
|
|
1612
|
+
|
|
1613
|
+
- `PreviewImage`:把当前单元格值渲染成图片预览;值是数组时直接作为图片列表,值是单个字符串时自动转成单图数组。
|
|
1614
|
+
|
|
1615
|
+
直接使用内置组件:
|
|
1616
|
+
|
|
1617
|
+
```ts
|
|
1618
|
+
cover: {
|
|
1619
|
+
type: 'string',
|
|
1620
|
+
label: '封面',
|
|
1621
|
+
tableOption: {
|
|
1622
|
+
renderComponent: 'PreviewImage',
|
|
1623
|
+
renderComponentProps: {
|
|
1624
|
+
width: 48,
|
|
1625
|
+
height: 48,
|
|
1626
|
+
},
|
|
1627
|
+
},
|
|
1628
|
+
}
|
|
1629
|
+
```
|
|
1630
|
+
|
|
1631
|
+
自定义渲染组件时,先声明 props 类型:
|
|
1632
|
+
|
|
1633
|
+
```ts
|
|
1634
|
+
// typing/template-core.d.ts
|
|
1635
|
+
import '@_tc/template-core/model'
|
|
1636
|
+
|
|
1637
|
+
declare module '@_tc/template-core/model' {
|
|
1638
|
+
export namespace SchemaTableNamespace {
|
|
1639
|
+
interface RenderComponentPropsMap {
|
|
1640
|
+
PriceCell: {
|
|
1641
|
+
value?: unknown
|
|
1642
|
+
record?: Record<string, unknown>
|
|
1643
|
+
rowIndex?: number
|
|
1644
|
+
fieldKey?: string
|
|
1645
|
+
currency?: string
|
|
1646
|
+
}
|
|
1647
|
+
}
|
|
1648
|
+
}
|
|
1649
|
+
}
|
|
1650
|
+
```
|
|
1651
|
+
|
|
1652
|
+
注册运行时组件:
|
|
1653
|
+
|
|
1654
|
+
```ts
|
|
1655
|
+
// frontend/extended/SchemaPage/SchemaTable/data.ts
|
|
1656
|
+
import { lazy } from 'react'
|
|
1657
|
+
import type { SchemaTableRenderComponentsMap } from '@_tc/template-core/fe'
|
|
1658
|
+
|
|
1659
|
+
const componentsMap = {
|
|
1660
|
+
PriceCell: lazy(() => import('../../components/PriceCell')),
|
|
1661
|
+
} satisfies SchemaTableRenderComponentsMap
|
|
1662
|
+
|
|
1663
|
+
export default componentsMap
|
|
1664
|
+
```
|
|
1665
|
+
|
|
1666
|
+
组件会收到 `value`、`record`、`rowIndex`、`fieldKey`,以及 `renderComponentProps` 中的自定义参数:
|
|
1667
|
+
|
|
1668
|
+
```tsx
|
|
1669
|
+
// frontend/components/PriceCell.tsx
|
|
1670
|
+
export default function PriceCell(props: {
|
|
1671
|
+
value?: unknown
|
|
1672
|
+
currency?: string
|
|
1673
|
+
}) {
|
|
1674
|
+
return <span>{props.currency ?? '¥'}{Number(props.value ?? 0).toFixed(2)}</span>
|
|
1675
|
+
}
|
|
1676
|
+
```
|
|
1677
|
+
|
|
1678
|
+
model 中使用:
|
|
1679
|
+
|
|
1680
|
+
```ts
|
|
1681
|
+
price: {
|
|
1682
|
+
type: 'number',
|
|
1683
|
+
label: '价格',
|
|
1684
|
+
tableOption: {
|
|
1685
|
+
renderComponent: 'PriceCell',
|
|
1686
|
+
renderComponentProps: {
|
|
1687
|
+
currency: '¥',
|
|
1688
|
+
},
|
|
1689
|
+
},
|
|
1690
|
+
}
|
|
1691
|
+
```
|
|
1692
|
+
|
|
1521
1693
|
## 如何配置类型扩展
|
|
1522
1694
|
|
|
1523
1695
|
### tsconfig
|
|
@@ -1617,6 +1789,22 @@ declare module '@_tc/template-core/model' {
|
|
|
1617
1789
|
- `OptionMap` 对应字段上的 `xxxOption`。
|
|
1618
1790
|
- 运行时组件注册在 `frontend/extended/SchemaPage/CallCom/data.ts`。
|
|
1619
1791
|
|
|
1792
|
+
### SchemaTable 渲染组件类型扩展
|
|
1793
|
+
|
|
1794
|
+
扩展目标:
|
|
1795
|
+
|
|
1796
|
+
```ts
|
|
1797
|
+
declare module '@_tc/template-core/model' {
|
|
1798
|
+
export namespace SchemaTableNamespace {
|
|
1799
|
+
interface RenderComponentPropsMap {}
|
|
1800
|
+
}
|
|
1801
|
+
}
|
|
1802
|
+
```
|
|
1803
|
+
|
|
1804
|
+
- `RenderComponentPropsMap` 的 key 对应 `tableOption.renderComponent`。
|
|
1805
|
+
- 运行时组件注册在 `frontend/extended/SchemaPage/SchemaTable/data.ts`。
|
|
1806
|
+
- 组件运行时会自动收到 `value`、`record`、`rowIndex`、`fieldKey`;`renderComponentProps` 只配置自定义参数。
|
|
1807
|
+
|
|
1620
1808
|
### KoaApp 类型扩展
|
|
1621
1809
|
|
|
1622
1810
|
使用方推荐增强根包 `@_tc/template-core`:
|
|
@@ -1970,6 +2158,6 @@ await buildBE({
|
|
|
1970
2158
|
- `model` 数组合并依赖稳定 `key`。
|
|
1971
2159
|
- Dashboard 默认需要 URL 带 `?projk=项目key`。
|
|
1972
2160
|
- Dashboard 登录守卫放在 `frontend/extended/dash/routeGuard.ts`;登录页通常不在 Dash 路由下,返回登录页 URL 即可。
|
|
1973
|
-
-
|
|
2161
|
+
- 服务端兜底守卫放在项目根目录的 `app/router-guard.ts|js`。
|
|
1974
2162
|
- 前端入口必须命名为 `.entry.tsx`、`.entry.ts`、`.entry.jsx` 或 `.entry.js`。
|
|
1975
2163
|
- 入口同目录的 `.html` 只能作为插槽文件使用,不能写完整 HTML 文档;页面外壳始终由 `app/view/entry.tpl` 生成。
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const e=require(`../../packages/common/string/index.js`);var t=e=>JSON.stringify(e).replace(/</g,`\\u003c`).replace(/>/g,`\\u003e`).replace(/&/g,`\\u0026`).replace(/\u2028/g,`\\u2028`).replace(/\u2029/g,`\\u2029`),n=(n=>class{async renderPage(r,i){let a=r.path;if(n.extends.localCacheHtmlEtag.keepFreshFEBuildKey(),a.includes(`${n.options.apiPrefix}/`))await i();else{n.extends.logger.log(` - render page: `+r.params.page);try{let i=r.query.projk;Array.isArray(i)&&(i=e.joinStr(...i));let a={projKey:i??``,name:n.options?.name??``,env:n.envs.get(),basePath:t(`${n.options.pageBasePage}${r.params.page}`),projKeyJson:t(String(r.query.projk??``)),signKey:t(n.config.signKey),options:t(n.options)},o=n.extends.renderView(`${r.params.page}.entry.tpl`,r,a),s=e.joinStr(a.basePath,a.name,a.env,a.projKey);if(!n.extends.localCacheHtmlEtag.hasEtag(s)){let e=n.extends.crypto.hmacSign(o);n.extends.localCacheHtmlEtag.setEtag(s,e)}let c=n.extends.localCacheHtmlEtag.getEtag(s);c||console.log(`---- etag 缓存异常 请检查服务 ----`),r.etag=c??Date.now()
|
|
1
|
+
const e=require(`../../packages/common/string/index.js`);var t=e=>JSON.stringify(e).replace(/</g,`\\u003c`).replace(/>/g,`\\u003e`).replace(/&/g,`\\u0026`).replace(/\u2028/g,`\\u2028`).replace(/\u2029/g,`\\u2029`),n=(n=>class{async renderPage(r,i){let a=r.path;if(n.extends.localCacheHtmlEtag.keepFreshFEBuildKey(),a.includes(`${n.options.apiPrefix}/`))await i();else{n.extends.logger.log(` - render page: `+r.params.page);try{let i=r.query.projk;Array.isArray(i)&&(i=e.joinStr(...i));let a={projKey:i??``,name:n.options?.name??``,env:n.envs.get(),basePath:t(`${n.options.pageBasePage}${r.params.page}`),projKeyJson:t(String(r.query.projk??``)),signKey:t(n.config.signKey),options:t(n.options)},o=n.extends.renderView(`${r.params.page}.entry.tpl`,r,a),s=e.joinStr(a.basePath,a.name,a.env,a.projKey);if(!n.extends.localCacheHtmlEtag.hasEtag(s)){let e=n.extends.crypto.hmacSign(o);n.extends.localCacheHtmlEtag.setEtag(s,e)}let c=n.extends.localCacheHtmlEtag.getEtag(s);if(c||console.log(`---- etag 缓存异常 请检查服务 ----`),r.etag=c??Date.now()+``,r.fresh){r.status=304;return}}catch(e){console.log(`-------------- render view error --------------`),console.log(e),n.extends.generateErrorMessage(`template not found`,{status:404,showError:!0,code:0})}}}});module.exports=n;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`../packages/common/log/index.js`),t=require(`./state.js`),n=require(`./dev.js`),r=require(`./prod.js`);var i=(i,a)=>{switch(t.setBuildFEOptions(a),i){case`dev`:return n.dev();case`prod`:return r.prod();default:return e.logRed(`Usage: npx tsx scripts/index.ts [dev|prod]`),Promise.resolve()}};exports.buildFE=i;
|
package/cjs/bundler/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./buildBE.js`),t=require(`./buildFE.js`);exports.buildBE=e.buildBE,exports.buildFE=t.buildFE;
|