@_tc/template-core 0.2.0-bate.5 → 0.2.0-bate.7

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.
@@ -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
- 这份文档给在消费方项目中协助开发的 AI 助手/代码代理阅读。项目本身才是 `@_tc/template-core` 的使用方;AI 通过这份速读文档快速理解包的用法和边界。它是 `README.md` 的精简版,按渐进式披露组织:先用下面的最小信息完成常见任务,只有需要深入时再读末尾的参考文档。
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
 
@@ -415,6 +415,7 @@ import { Button, DataTable, Form, Input, Modal, Select } from '@_tc/template-cor
415
415
  - RAF 计时器:`rafSetTimeout`、`rafSetInterval`、`rafClearTimeout`、`rafClearInterval`、`clearRafTimer`。
416
416
  - 请求类型:`BaseResponse`、`PageParams`、`PageResponse`、`RequestConfig`、`ResponseConfig`、`AxiosError`。
417
417
  - 请求 header:自动添加 `s_t`、`s_sign`、`projk`;存在短 token 时添加 `Authorization: Bearer ${token}`。
418
+ - 默认会先设置 `Content-Type: application/json`;如果是上传文件、`FormData` 或其他内容类型,请在请求配置里显式覆盖。
418
419
  - Token 工具:`getAuthToken()`、`setAuthToken()`、`clearAuthToken()`、`localKeyMap`;`getAuthToken()` 是同步函数,读取前无需 `await`。
419
420
  - 本地 key:短 token 是 `localStorage.auth_token`,项目 key 是 `localStorage.p_J_k`;刷新 token header 默认名是 `RT`。
420
421
  - 组件加载辅助:`renderImportComponent(import('./Page'))` 会用 `React.lazy` + `Suspense` 渲染动态组件。
@@ -623,13 +624,14 @@ chokidar
623
624
 
624
625
  扩展前端类型或组件:
625
626
 
626
- 1. SchemaForm 字段类型、CallCom 组件、Koa app 类型都支持 TypeScript 声明合并。
627
+ 1. SchemaForm 字段类型、SchemaTable 单元格渲染组件、CallCom 组件、Koa app 类型都支持 TypeScript 声明合并。
627
628
  2. 运行时组件通常放在业务 `frontend/extended/`。
628
- 3. Dashboard 扩展点包括 `frontend/extended/dash/init.ts`、`frontend/extended/dash/customRoutes.tsx`、`frontend/extended/dash/components.tsx`、`frontend/extended/dash/routeGuard.ts`。
629
- 4. `dash/init` 在 React 渲染前执行,适合注册 axios 拦截器等全局初始化逻辑;类型是 `DashInit`。
630
- 5. `dash/routeGuard` 用来判断登录。返回登录页 URL 字符串时,Dashboard `window.location.href` 跳转;`DashRouteGuardResult` 是 `string | undefined`,`undefined`(包括已登录分支的隐式返回)会打断 Dashboard 内置重定向,业务方可自行跳转。
631
- 6. 自定义入口的 `initApp` 支持 `beforeRender` / `afterRender`,分别在 React 渲染前和首次渲染提交后触发。
632
- 7. 优先查看公开入口 `.d.ts` npm 包根目录 `README.md`;如果当前环境是源码仓库,再继续读 `docs/type-extension.md` `docs/schema-form.md`。
629
+ 3. 表格单元格渲染组件注册到 `frontend/extended/SchemaPage/SchemaTable/data.ts`,字段上用 `tableOption.renderComponent` 和 `renderComponentProps`。
630
+ 4. Dashboard 扩展点包括 `frontend/extended/dash/init.ts`、`frontend/extended/dash/customRoutes.tsx`、`frontend/extended/dash/components.tsx`、`frontend/extended/dash/routeGuard.ts`。
631
+ 5. `dash/init` React 渲染前执行,适合注册 axios 拦截器等全局初始化逻辑;类型是 `DashInit`。
632
+ 6. `dash/routeGuard` 用来判断登录。返回登录页 URL 字符串时,Dashboard 用 `window.location.href` 跳转;`DashRouteGuardResult` `string | undefined`,`undefined`(包括已登录分支的隐式返回)会打断 Dashboard 内置重定向,业务方可自行跳转。
633
+ 7. 自定义入口的 `initApp` 支持 `beforeRender` / `afterRender`,分别在 React 渲染前和首次渲染提交后触发。
634
+ 8. 优先查看公开入口 `.d.ts` 和 npm 包根目录 `README.md`;如果当前环境是源码仓库,再继续读 `docs/type-extension.md` 和 `docs/schema-form.md`。
633
635
 
634
636
  ## 8. 继续深入
635
637
 
package/README.md CHANGED
@@ -301,7 +301,7 @@ VS Code 建议安装官方 Tailwind CSS IntelliSense 插件,并在工作区 `.
301
301
  - 内置 UI 组件:提供丰富的 React 组件库,详见下方"内置 UI 组件"章节。
302
302
  - API 中间件:错误处理、静态资源、body parser、项目上下文、接口签名、参数校验。
303
303
  - 前端构建:扫描框架和项目的 `frontend/**/*.entry.{ts,tsx,js,jsx}`,输出服务端可渲染的 `.entry.tpl`,并写入 `FEBuildKey` 供 HTML ETag 缓存失效使用。
304
- - 类型扩展:支持扩展 SchemaForm、CallCom、KoaApp。
304
+ - 类型扩展:支持扩展 SchemaForm、SchemaTable 单元格渲染组件、CallCom、KoaApp。
305
305
 
306
306
  ## 前端公共能力
307
307
 
@@ -356,6 +356,8 @@ import type {
356
356
  PageResponse,
357
357
  RequestConfig,
358
358
  ResponseConfig,
359
+ SchemaTableRenderComponent,
360
+ SchemaTableRenderComponentsMap,
359
361
  SchemaFormComponentsMap,
360
362
  SchemaFormNamespace,
361
363
  SelectProps,
@@ -370,7 +372,7 @@ import type {
370
372
  | 内置前端组件 | `AsyncSelect`、`LanguageSwitch`、`ThemeSwitch` |
371
373
  | 组件加载辅助 | `renderImportComponent` |
372
374
  | Dash 扩展类型 | `DashRoutesExtender`、`DashRoutesContext`、`DashComponentsMap`、`DashHeaderUserAreaProps`、`DashRouteGuard` |
373
- | SchemaPage 类型 | `CallComComponentsMap`、`CallComRenderer` |
375
+ | SchemaPage 类型 | `CallComComponentsMap`、`CallComRenderer`、`SchemaTableRenderComponent`、`SchemaTableRenderComponentsMap` |
374
376
  | SchemaForm 类型 | `FormFieldSchema`、`SchemaFormComponentsMap`、`SchemaFormNamespace`、`SelectProps` |
375
377
  | 请求方法 | `api`、`request`、`get`、`post`、`put`、`patch`、`del` |
376
378
  | 请求类型 | `BaseResponse`、`PageParams`、`PageResponse`、`RequestConfig`、`ResponseConfig`、`AxiosError` |
@@ -573,6 +575,7 @@ applyThemeMode('dark', true)
573
575
  - `timeout`:15000ms(15秒)
574
576
  - `credentials`:`'include'`,支持跨域携带 cookie
575
577
  - `window._signKey`:由服务端页面模板从 `app.config.signKey` 注入
578
+ - 默认会先设置 `Content-Type: application/json`;如果是上传文件、`FormData` 或其他内容类型,请在请求配置里显式覆盖
576
579
 
577
580
  **请求拦截器**:
578
581
 
@@ -1568,6 +1571,90 @@ remark: {
1568
1571
  }
1569
1572
  ```
1570
1573
 
1574
+ ### 扩展 SchemaTable 单元格渲染组件
1575
+
1576
+ SchemaPage 表格列支持通过 `tableOption.renderComponent` 使用内置或业务注册的渲染组件。内置组件:
1577
+
1578
+ - `PreviewImage`:把当前单元格值渲染成图片预览;值是数组时直接作为图片列表,值是单个字符串时自动转成单图数组。
1579
+
1580
+ 直接使用内置组件:
1581
+
1582
+ ```ts
1583
+ cover: {
1584
+ type: 'string',
1585
+ label: '封面',
1586
+ tableOption: {
1587
+ renderComponent: 'PreviewImage',
1588
+ renderComponentProps: {
1589
+ width: 48,
1590
+ height: 48,
1591
+ },
1592
+ },
1593
+ }
1594
+ ```
1595
+
1596
+ 自定义渲染组件时,先声明 props 类型:
1597
+
1598
+ ```ts
1599
+ // typing/template-core.d.ts
1600
+ import '@_tc/template-core/model'
1601
+
1602
+ declare module '@_tc/template-core/model' {
1603
+ export namespace SchemaTableNamespace {
1604
+ interface RenderComponentPropsMap {
1605
+ PriceCell: {
1606
+ value?: unknown
1607
+ record?: Record<string, unknown>
1608
+ rowIndex?: number
1609
+ fieldKey?: string
1610
+ currency?: string
1611
+ }
1612
+ }
1613
+ }
1614
+ }
1615
+ ```
1616
+
1617
+ 注册运行时组件:
1618
+
1619
+ ```ts
1620
+ // frontend/extended/SchemaPage/SchemaTable/data.ts
1621
+ import { lazy } from 'react'
1622
+ import type { SchemaTableRenderComponentsMap } from '@_tc/template-core/fe'
1623
+
1624
+ const componentsMap = {
1625
+ PriceCell: lazy(() => import('../../components/PriceCell')),
1626
+ } satisfies SchemaTableRenderComponentsMap
1627
+
1628
+ export default componentsMap
1629
+ ```
1630
+
1631
+ 组件会收到 `value`、`record`、`rowIndex`、`fieldKey`,以及 `renderComponentProps` 中的业务参数:
1632
+
1633
+ ```tsx
1634
+ // frontend/components/PriceCell.tsx
1635
+ export default function PriceCell(props: {
1636
+ value?: unknown
1637
+ currency?: string
1638
+ }) {
1639
+ return <span>{props.currency ?? '¥'}{Number(props.value ?? 0).toFixed(2)}</span>
1640
+ }
1641
+ ```
1642
+
1643
+ model 中使用:
1644
+
1645
+ ```ts
1646
+ price: {
1647
+ type: 'number',
1648
+ label: '价格',
1649
+ tableOption: {
1650
+ renderComponent: 'PriceCell',
1651
+ renderComponentProps: {
1652
+ currency: '¥',
1653
+ },
1654
+ },
1655
+ }
1656
+ ```
1657
+
1571
1658
  ## 如何配置类型扩展
1572
1659
 
1573
1660
  ### tsconfig
@@ -1667,6 +1754,22 @@ declare module '@_tc/template-core/model' {
1667
1754
  - `OptionMap` 对应字段上的 `xxxOption`。
1668
1755
  - 运行时组件注册在 `frontend/extended/SchemaPage/CallCom/data.ts`。
1669
1756
 
1757
+ ### SchemaTable 渲染组件类型扩展
1758
+
1759
+ 扩展目标:
1760
+
1761
+ ```ts
1762
+ declare module '@_tc/template-core/model' {
1763
+ export namespace SchemaTableNamespace {
1764
+ interface RenderComponentPropsMap {}
1765
+ }
1766
+ }
1767
+ ```
1768
+
1769
+ - `RenderComponentPropsMap` 的 key 对应 `tableOption.renderComponent`。
1770
+ - 运行时组件注册在 `frontend/extended/SchemaPage/SchemaTable/data.ts`。
1771
+ - 组件运行时会自动收到 `value`、`record`、`rowIndex`、`fieldKey`;`renderComponentProps` 只配置业务参数。
1772
+
1670
1773
  ### KoaApp 类型扩展
1671
1774
 
1672
1775
  使用方推荐增强根包 `@_tc/template-core`:
@@ -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;
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`../packages/common/log/index.js`),t=require(`./buildBE.js`),n=require(`./state.js`),r=require(`./dev.js`),i=require(`./prod.js`);var a=(t,a)=>{switch(n.setBuildFEOptions(a),t){case`dev`:return r.dev();case`prod`:return i.prod();default:return e.logRed(`Usage: npx tsx scripts/index.ts [dev|prod]`),Promise.resolve()}};exports.buildBE=t.buildBE,exports.buildFE=a;
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;
@@ -1,3 +1,3 @@
1
1
  Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`../_virtual/_rolldown/runtime.js`),t=require(`../packages/common/log/index.js`),n=require(`../packages/utils/path.js`);require(`../packages/utils/index.js`);const r=require(`./state.js`);let i=require(`fs`),a=require(`path`);a=e.__toESM(a);let o=require(`glob`);o=e.__toESM(o);let s=require(`vite`),c=require(`@tailwindcss/vite`);c=e.__toESM(c);let l=require(`module`),u=require(`url`);var d=typeof __filename==`string`?__filename:(0,u.fileURLToPath)({}.url),f=a.default.dirname(d),p=process.cwd(),m=(0,l.createRequire)(d),h=a.default.resolve(f,`../../`),g=a.default.resolve(f,`../`),_=a.default.resolve(h,`./fe/frontend`),v=a.default.resolve(p,`.`),y=a.default.resolve(v,`./frontend`),b=e=>a.default.dirname(m.resolve(`${e}/package.json`)),x=a.default.join(v,`.tc-entry-html`),S=`<!-- {{InsertScript}} -->`,C={head:`<!-- TC_HEAD_SLOT -->`,bodyBeforeRoot:`<!-- TC_BODY_BEFORE_ROOT_SLOT -->`,bodyAfterRoot:`<!-- TC_BODY_AFTER_ROOT_SLOT -->`},w=[`head`,`body-before-root`,`body-after-root`],T=()=>({head:``,"body-before-root":``,"body-after-root":``}),E=e=>e.trim().replace(/<!--(?!\s*(?:tc-slot:|\/tc-slot:))[\s\S]*?-->/g,``).replace(/>\s+</g,`><`),D=e=>{let t=[],n=e.replace(/<(script|style|textarea|pre)\b[\s\S]*?<\/\1>/gi,e=>{let n=`__TC_HTML_PRESERVED_${t.length}__`;return t.push(e),n}).replace(/<!--(?!\s*(?:tc-slot:|\/tc-slot:|\{\{InsertScript\}\}|TC_))[\s\S]*?-->/g,``).replace(/>\s+</g,`><`).trim();return t.reduce((e,t,n)=>e.replace(`__TC_HTML_PRESERVED_${n}__`,t),n)},O=e=>e.split(a.default.sep).join(`/`),k=e=>{let t=O(e);return t.startsWith(`.`)||t.startsWith(`/`)?t:`./${t}`},A=e=>/<html[\s>]/i.test(e)&&e.includes(`window['_basePath']`)&&/<div\s+id=["']root["']\s*><\/div>/i.test(e),j=e=>{let n=T(),r=(0,i.readFileSync)(e,`utf-8`),a=/<!--\s*tc-slot:([\w-]+)\s*-->([\s\S]*?)<!--\s*\/tc-slot:\1\s*-->/g,o=!1,s=r;if(r.replace(a,(t,r,i)=>{if(o=!0,!w.includes(r))throw Error(`Invalid html slot "${r}" in ${e}. Allowed slots: ${w.join(`, `)}.`);return n[r]+=i.trim()?`${i}\n`:``,s=s.replace(t,``),t}),s.trim()){if(A(r))return t.logYellow(`ignored legacy generated entry html: ${e}`),T();throw Error([`Invalid custom entry html: ${e}.`,`Custom entry html can only contain tc-slot blocks, for example:`,`<!-- tc-slot:head -->`,`<meta name="description" content="..." />`,`<!-- /tc-slot:head -->`].join(`
2
2
  `))}return o&&t.logYellow(`using custom entry html slots: ${e}`),n},M=(e,t)=>{let r=a.default.basename(e),s=[a.default.join(e,`${t}.html`),a.default.join(e,`${r}.html`)].find(e=>(0,i.existsSync)(e));if(s)return s;if(o.sync(n.resolve(e,`*.html`)).length)throw Error([`Entry html filename is not supported in ${e}.`,`Use ${t}.html or ${r}.html as a tc-slot file.`].join(`
3
- `))},N=(e,t)=>e.replace(C.head,E(t.head)).replace(C.bodyBeforeRoot,E(t[`body-before-root`])).replace(C.bodyAfterRoot,E(t[`body-after-root`])),P=(e=new Date)=>{let t=(e,t=2)=>e.toString().padStart(t,`0`);return[e.getFullYear(),t(e.getMonth()+1),t(e.getDate()),t(e.getHours())].join(`/`)+`:${t(e.getMinutes())}:${t(e.getSeconds())}:${t(e.getMilliseconds(),3)}`},F=(e,t,n,r)=>{let o=a.default.join(x,`${n}.html`),s=k(a.default.relative(a.default.dirname(o),t));return(0,i.writeFileSync)(o,N(e,r).replace(S,`<script type="module" src="${s}"><\/script>`)),o};function I(){t.logWhite(`frameFEPath: `+_),t.logWhite(`runFEPath: `+y);let e=[_,y].reduce((e,t)=>{let r=[`js`,`jsx`,`ts`,`tsx`].map(e=>n.resolve(t,`/**`,`/*.`+e)),i=o.sync(r).filter(e=>e.includes(`.entry.`)).filter(e=>!e.includes(`.d.ts`));return[...e,...i]},[]),r={};if(!e.length)return r;(0,i.rmSync)(x,{recursive:!0,force:!0}),(0,i.mkdirSync)(x,{recursive:!0});let s=(0,i.readFileSync)(a.default.resolve(g,`./app/view/entry.tpl`),`utf-8`);for(let t=0;t<e.length;t++){let n=e[t],i=a.default.resolve(n,`../`),o=M(i,a.default.basename(n).replace(/\.entry\.[^.]+$/,``)),c=o?a.default.basename(o,`.html`):i.split(a.default.sep).at(-1);r[c]=F(s,n,c,o?j(o):T())}return r}function L(){let e=r.buildFESharedState.options.output??`frame`;return e!==`frame`&&t.logRed(`Please pay attention to the build output.`),e===`run`?a.default.join(v,`./app/public/dist`):typeof e==`function`?e():a.default.join(g,`./app/public/dist`)}var R=async e=>{let n=(await import(`chokidar`)).watch(y,{ignored:/(^|[\/\\])\../,persistent:!0,ignoreInitial:!0}),r=!1;n.on(`change`,async n=>{if(!r){r=!0,t.logYellow(`changed: ${n}`);try{await e?.()}catch(e){t.logRed(e)}finally{r=!1}}}),t.logYellow(`watching ${y}/...`)};function z(){return{name:`flatten-html`,apply:`build`,closeBundle(){let e=L(),t=P();(0,i.writeFileSync)(n.resolve(e,`./FEBuildKey`),t)}}}function B(e=`.html`){let n=[...new Set(Array.isArray(e)?e:[e])];return{name:`flatten-html`,apply:`build`,closeBundle(){let e=L();if(!(0,i.existsSync)(e))return;let s=r.buildFESharedState.options.minifyHtml??!1,c=o.sync(`**/*.html`,{cwd:e,dot:!0});for(let t of c){let r=a.default.join(e,t),o=(0,i.readFileSync)(r,`utf-8`),c=s?D(o):o,l=a.default.basename(t,`.html`),u=`.entry`;l.indexOf(u)===-1&&(l+=u);for(let t of n){let n=l+t,o=a.default.join(e,n);r===o?s&&(0,i.writeFileSync)(o,c):(0,i.writeFileSync)(o,c)}n.some(t=>r===a.default.join(e,l+t))||(0,i.unlinkSync)(r)}let l=[...new Set(c.map(e=>a.default.dirname(e)))].sort().reverse(),u=e=>{if(!((0,i.existsSync)(e)?(0,i.readdirSync)(e):[1]).length){(0,i.rmdirSync)(e);let t=e.split(a.default.sep).slice(0,-1);t.length&&u(t.join(a.default.sep))}};for(let t of l)t&&t!==`.`&&u(a.default.join(e,t));let d=n.flatMap(t=>o.sync(`**/*`+t,{cwd:e,dot:!0}));for(let e of d)t.logYellow(`final file path -----> `+e)}}}function V(e){let t=[``,`.ts`,`.tsx`,`.js`,`.jsx`];return e.reduce((e,[n,r,o=y,s=`./defaultAlias`])=>{let c=t.map(e=>a.default.resolve(o,r+e)).find(e=>(0,i.existsSync)(e)),l=a.default.resolve(f,s);return c&&(l=c),e[n]=l,e},{})}var H=(...e)=>new RegExp(e.join(`[\\/]`)),U=e=>`_${e}_tcC`,W=async(e,n)=>{try{await(0,s.build)({configFile:!1,base:`/dist`,plugins:[(await import(`@vitejs/plugin-react`)).default(),B([`.tpl`]),z(),(0,c.default)()],build:{outDir:L(),emptyOutDir:!0,sourcemap:n===`dev`?`inline`:`hidden`,rolldownOptions:{input:e,output:{codeSplitting:{groups:[{name:U(`__nm`),test:H(`node_modules`),maxSize:5e5,minShareCount:2,priority:1},{name:U(`r`),test:H(`node_modules`,`react`),minShareCount:2,maxSize:5e5,priority:5},{name:U(`r-d`),test:H(`node_modules`,`react-dom`),minShareCount:2,maxSize:2e5,priority:10},{name:U(`r-r-d`),test:H(`node_modules`,`react-router-dom`),minShareCount:2,maxSize:5e5,priority:10},{name:U(`ajv`),test:H(`node_modules`,`ajv`),minShareCount:2,maxSize:2e5,priority:10},{name:U(`ui-lib`),test:H(`components`),minShareCount:2,maxSize:2e5,priority:5},{name:U(`ui-f-lib`),test:H(`components`,`.*?[Ff]orm.*?`),minShareCount:2,maxSize:5e4,priority:10}]}}}},resolve:{alias:{react:b(`react`),"react-dom":b(`react-dom`),"@tc/ui-react/hooks":a.default.resolve(f,`../../fe/packages/react/hooks/`),"@tc/ui-react":a.default.resolve(f,`../../fe/packages/react/ui/`),...V([[`@tc/scalability/SchemaForm/frameData`,`./extended/SchemaForm/data`,_],[`@tc/scalability/SchemaForm/data`,`./extended/SchemaForm/data`],[`@tc/scalability/SchemaPage/CallCom/data`,`./extended/SchemaPage/CallCom/data`],[`@tc/scalability/dash/customRoutes`,`./extended/dash/customRoutes`],[`@tc/scalability/dash/init`,`./extended/dash/init`],[`@tc/scalability/dash/components`,`./extended/dash/components`],[`@tc/scalability/dash/routeGuard`,`./extended/dash/routeGuard`,void 0,`./defaultRouteGuard`]])}}}),t.logJoinColorized(t.colorize(`builded`,`green`),t.colorize(` -> `,`white`),t.colorize(`time: `,`cyan`),t.colorize(new Date,`pink`))}catch(e){if(t.logRed(e),n!==`dev`)throw e}};exports.VBuildFE=W,exports.entries=I,exports.generateBuildKeyPlugin=z,exports.outDir=L,exports.watchFiles=R;
3
+ `))},N=(e,t)=>e.replace(C.head,E(t.head)).replace(C.bodyBeforeRoot,E(t[`body-before-root`])).replace(C.bodyAfterRoot,E(t[`body-after-root`])),P=(e=new Date)=>{let t=(e,t=2)=>e.toString().padStart(t,`0`);return[e.getFullYear(),t(e.getMonth()+1),t(e.getDate()),t(e.getHours())].join(`/`)+`:${t(e.getMinutes())}:${t(e.getSeconds())}:${t(e.getMilliseconds(),3)}`},F=(e,t,n,r)=>{let o=a.default.join(x,`${n}.html`),s=k(a.default.relative(a.default.dirname(o),t));return(0,i.writeFileSync)(o,N(e,r).replace(S,`<script type="module" src="${s}"><\/script>`)),o};function I(){t.logWhite(`frameFEPath: `+_),t.logWhite(`runFEPath: `+y);let e=[_,y].reduce((e,t)=>{let r=[`js`,`jsx`,`ts`,`tsx`].map(e=>n.resolve(t,`/**`,`/*.`+e)),i=o.sync(r).filter(e=>e.includes(`.entry.`)).filter(e=>!e.includes(`.d.ts`));return[...e,...i]},[]),r={};if(!e.length)return r;(0,i.rmSync)(x,{recursive:!0,force:!0}),(0,i.mkdirSync)(x,{recursive:!0});let s=(0,i.readFileSync)(a.default.resolve(g,`./app/view/entry.tpl`),`utf-8`);for(let t=0;t<e.length;t++){let n=e[t],i=a.default.resolve(n,`../`),o=M(i,a.default.basename(n).replace(/\.entry\.[^.]+$/,``)),c=o?a.default.basename(o,`.html`):i.split(a.default.sep).at(-1);r[c]=F(s,n,c,o?j(o):T())}return r}function L(){let e=r.buildFESharedState.options.output??`frame`;return e!==`frame`&&t.logRed(`Please pay attention to the build output.`),e===`run`?a.default.join(v,`./app/public/dist`):typeof e==`function`?e():a.default.join(g,`./app/public/dist`)}var R=async e=>{let n=(await import(`chokidar`)).watch(y,{ignored:/(^|[\/\\])\../,persistent:!0,ignoreInitial:!0}),r=!1;n.on(`change`,async n=>{if(!r){r=!0,t.logYellow(`changed: ${n}`);try{await e?.()}catch(e){t.logRed(e)}finally{r=!1}}}),t.logYellow(`watching ${y}/...`)};function z(){return{name:`flatten-html`,apply:`build`,closeBundle(){let e=L(),t=P();(0,i.writeFileSync)(n.resolve(e,`./FEBuildKey`),t)}}}function B(e=`.html`){let n=[...new Set(Array.isArray(e)?e:[e])];return{name:`flatten-html`,apply:`build`,closeBundle(){let e=L();if(!(0,i.existsSync)(e))return;let s=r.buildFESharedState.options.minifyHtml??!1,c=o.sync(`**/*.html`,{cwd:e,dot:!0});for(let t of c){let r=a.default.join(e,t),o=(0,i.readFileSync)(r,`utf-8`),c=s?D(o):o,l=a.default.basename(t,`.html`),u=`.entry`;l.indexOf(u)===-1&&(l+=u);for(let t of n){let n=l+t,o=a.default.join(e,n);r===o?s&&(0,i.writeFileSync)(o,c):(0,i.writeFileSync)(o,c)}n.some(t=>r===a.default.join(e,l+t))||(0,i.unlinkSync)(r)}let l=[...new Set(c.map(e=>a.default.dirname(e)))].sort().reverse(),u=e=>{if(!((0,i.existsSync)(e)?(0,i.readdirSync)(e):[1]).length){(0,i.rmdirSync)(e);let t=e.split(a.default.sep).slice(0,-1);t.length&&u(t.join(a.default.sep))}};for(let t of l)t&&t!==`.`&&u(a.default.join(e,t));let d=n.flatMap(t=>o.sync(`**/*`+t,{cwd:e,dot:!0}));for(let e of d)t.logYellow(`final file path -----> `+e)}}}function V(e){let t=[``,`.ts`,`.tsx`,`.js`,`.jsx`];return e.reduce((e,[n,r,o=y,s=`./defaultAlias`])=>{let c=t.map(e=>a.default.resolve(o,r+e)).find(e=>(0,i.existsSync)(e)),l=a.default.resolve(f,s);return c&&(l=c),e[n]=l,e},{})}var H=(...e)=>new RegExp(e.join(`[\\/]`)),U=e=>`_${e}_tcC`,W=async(e,n)=>{try{await(0,s.build)({configFile:!1,base:`/dist`,plugins:[(await import(`@vitejs/plugin-react`)).default(),B([`.tpl`]),z(),(0,c.default)()],build:{outDir:L(),emptyOutDir:!0,sourcemap:n===`dev`?`inline`:`hidden`,rolldownOptions:{input:e,output:{codeSplitting:{groups:[{name:U(`__nm`),test:H(`node_modules`),maxSize:5e5,minShareCount:2,priority:1},{name:U(`r`),test:H(`node_modules`,`react`),minShareCount:2,maxSize:5e5,priority:5},{name:U(`r-d`),test:H(`node_modules`,`react-dom`),minShareCount:2,maxSize:2e5,priority:10},{name:U(`r-r-d`),test:H(`node_modules`,`react-router-dom`),minShareCount:2,maxSize:5e5,priority:10},{name:U(`ajv`),test:H(`node_modules`,`ajv`),minShareCount:2,maxSize:2e5,priority:10},{name:U(`ui-lib`),test:H(`components`),minShareCount:2,maxSize:2e5,priority:5},{name:U(`ui-f-lib`),test:H(`components`,`.*?[Ff]orm.*?`),minShareCount:2,maxSize:5e4,priority:10}]}}}},resolve:{alias:{react:b(`react`),"react-dom":b(`react-dom`),"@tc/ui-react/hooks":a.default.resolve(f,`../../fe/packages/react/hooks/`),"@tc/ui-react":a.default.resolve(f,`../../fe/packages/react/ui/`),...V([[`@tc/scalability/SchemaForm/frameData`,`./extended/SchemaForm/data`,_],[`@tc/scalability/SchemaForm/data`,`./extended/SchemaForm/data`],[`@tc/scalability/SchemaPage/CallCom/data`,`./extended/SchemaPage/CallCom/data`],[`@tc/scalability/SchemaPage/SchemaTable/data`,`./extended/SchemaPage/SchemaTable/data`],[`@tc/scalability/dash/customRoutes`,`./extended/dash/customRoutes`],[`@tc/scalability/dash/init`,`./extended/dash/init`],[`@tc/scalability/dash/components`,`./extended/dash/components`],[`@tc/scalability/dash/routeGuard`,`./extended/dash/routeGuard`,void 0,`./defaultRouteGuard`]])}}}),t.logJoinColorized(t.colorize(`builded`,`green`),t.colorize(` -> `,`white`),t.colorize(`time: `,`cyan`),t.colorize(new Date,`pink`))}catch(e){if(t.logRed(e),n!==`dev`)throw e}};exports.VBuildFE=W,exports.entries=I,exports.generateBuildKeyPlugin=z,exports.outDir=L,exports.watchFiles=R;
@@ -0,0 +1,14 @@
1
+ import { logRed as e } from "../packages/common/log/index.js";
2
+ import { setBuildFEOptions as t } from "./state.js";
3
+ import { dev as n } from "./dev.js";
4
+ import { prod as r } from "./prod.js";
5
+ //#region bundler/buildFE.ts
6
+ var i = (i, a) => {
7
+ switch (t(a), i) {
8
+ case "dev": return n();
9
+ case "prod": return r();
10
+ default: return e("Usage: npx tsx scripts/index.ts [dev|prod]"), Promise.resolve();
11
+ }
12
+ };
13
+ //#endregion
14
+ export { i as buildFE };
@@ -1,15 +1,3 @@
1
- import { logRed as e } from "../packages/common/log/index.js";
2
- import { buildBE as t } from "./buildBE.js";
3
- import { setBuildFEOptions as n } from "./state.js";
4
- import { dev as r } from "./dev.js";
5
- import { prod as i } from "./prod.js";
6
- //#region bundler/index.ts
7
- var a = (t, a) => {
8
- switch (n(a), t) {
9
- case "dev": return r();
10
- case "prod": return i();
11
- default: return e("Usage: npx tsx scripts/index.ts [dev|prod]"), Promise.resolve();
12
- }
13
- };
14
- //#endregion
15
- export { t as buildBE, a as buildFE };
1
+ import { buildBE as e } from "./buildBE.js";
2
+ import { buildFE as t } from "./buildFE.js";
3
+ export { e as buildBE, t as buildFE };
@@ -252,6 +252,7 @@ var Q = (...e) => new RegExp(e.join("[\\/]")), $ = (e) => `_${e}_tcC`, ee = asyn
252
252
  ],
253
253
  ["@tc/scalability/SchemaForm/data", "./extended/SchemaForm/data"],
254
254
  ["@tc/scalability/SchemaPage/CallCom/data", "./extended/SchemaPage/CallCom/data"],
255
+ ["@tc/scalability/SchemaPage/SchemaTable/data", "./extended/SchemaPage/SchemaTable/data"],
255
256
  ["@tc/scalability/dash/customRoutes", "./extended/dash/customRoutes"],
256
257
  ["@tc/scalability/dash/init", "./extended/dash/init"],
257
258
  ["@tc/scalability/dash/components", "./extended/dash/components"],
@@ -100,6 +100,7 @@ api.interceptors.request.use(async (config) => {
100
100
  const aauto = getApiAuth();
101
101
  const time = (/* @__PURE__ */ new Date()).getTime();
102
102
  config.headers = {
103
+ "Content-Type": "application/json",
103
104
  ...config.headers,
104
105
  s_t: time + "",
105
106
  s_sign: md5(`${window["_signKey"]}_${time}`),
@@ -0,0 +1,10 @@
1
+ import type { PreviewImageProps as BasePreviewImageProps } from "../../../../../../packages/react/ui/index";
2
+ export type SchemaTablePreviewImageProps = Omit<BasePreviewImageProps, 'images'> & {
3
+ value?: unknown;
4
+ record?: Record<string, unknown>;
5
+ rowIndex?: number;
6
+ fieldKey?: string;
7
+ images?: BasePreviewImageProps['images'];
8
+ valueToImages?: (value: unknown, record?: Record<string, unknown>, rowIndex?: number, fieldKey?: string) => BasePreviewImageProps['images'];
9
+ };
10
+ export declare function PreviewImage({ value, record, rowIndex, fieldKey, images, valueToImages: customValueToImages, ...props }: SchemaTablePreviewImageProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,17 @@
1
+ import { PreviewImage as PreviewImage$1 } from "../../../../../../packages/react/ui/components/ImagePreview/PreviewImage.js";
2
+ import "../../../../../../packages/react/ui/index.js";
3
+ import { jsx } from "react/jsx-runtime";
4
+ //#region frontend/src/defaultPages/SchemaPage/components/SchemaTable/PreviewImage.tsx
5
+ var valueToImages = (value) => {
6
+ if (Array.isArray(value)) return value;
7
+ if (value === void 0 || value === null || value === "") return [];
8
+ return [value];
9
+ };
10
+ function PreviewImage({ value, record, rowIndex, fieldKey, images, valueToImages: customValueToImages, ...props }) {
11
+ return /* @__PURE__ */ jsx(PreviewImage$1, {
12
+ ...props,
13
+ images: images ?? (customValueToImages ?? valueToImages)(value, record, rowIndex, fieldKey)
14
+ });
15
+ }
16
+ //#endregion
17
+ export { PreviewImage };
@@ -0,0 +1,5 @@
1
+ import type { SchemaTableRenderComponentPropsMap } from "../../../../../../model/types/data/schema";
2
+ import type { ComponentType, LazyExoticComponent } from "react";
3
+ export type SchemaTableRenderComponent = ComponentType<any> | LazyExoticComponent<ComponentType<any>>;
4
+ export type SchemaTableRenderComponentsMap = Partial<Record<Extract<keyof SchemaTableRenderComponentPropsMap, string>, SchemaTableRenderComponent>>;
5
+ export declare const schemaTableRenderComponentMap: SchemaTableRenderComponentsMap;
@@ -0,0 +1,8 @@
1
+ import { PreviewImage } from "./PreviewImage.js";
2
+ import consumerRenderComponentMap from "@tc/scalability/SchemaPage/SchemaTable/data";
3
+ var schemaTableRenderComponentMap = {
4
+ PreviewImage,
5
+ ...consumerRenderComponentMap
6
+ };
7
+ //#endregion
8
+ export { schemaTableRenderComponentMap };
@@ -12,9 +12,10 @@ import { handlingRequestErrors } from "../../../../common/fetchErrorShow.js";
12
12
  import useExecuteOnce from "../../../../../../packages/react/hooks/useExecuteOnce.js";
13
13
  import { eventsInfo } from "../../data/eventInfo.js";
14
14
  import { merge } from "../../utils/permissions.js";
15
+ import { schemaTableRenderComponentMap } from "./data.js";
15
16
  import useRefState from "../../../../../../packages/react/hooks/useRefState.js";
16
17
  import useWatch from "../../../../../../packages/react/hooks/useWatch.js";
17
- import { memo, useCallback, useImperativeHandle, useMemo, useState, useTransition } from "react";
18
+ import { Suspense, memo, useCallback, useImperativeHandle, useMemo, useState, useTransition } from "react";
18
19
  import { jsx, jsxs } from "react/jsx-runtime";
19
20
  import { useShallow } from "zustand/react/shallow";
20
21
  import { produce } from "immer";
@@ -26,11 +27,27 @@ var generateColumns = (config) => {
26
27
  keys.forEach((k) => {
27
28
  const fieldInfo = config[k];
28
29
  if (fieldInfo?.option) {
29
- const { ...fieldProps } = fieldInfo.option;
30
+ const { render: customRender, renderComponent, renderComponentProps, ...fieldProps } = fieldInfo.option;
30
31
  columns.push({
31
32
  title: getText(fieldInfo.label),
32
33
  key: k,
33
- ...fieldProps
34
+ ...fieldProps,
35
+ render(v, d, index) {
36
+ if (renderComponent) {
37
+ const Component = schemaTableRenderComponentMap[renderComponent];
38
+ if (Component) return /* @__PURE__ */ jsx(Suspense, {
39
+ fallback: null,
40
+ children: /* @__PURE__ */ jsx(Component, {
41
+ ...renderComponentProps,
42
+ value: v,
43
+ record: d,
44
+ rowIndex: index,
45
+ fieldKey: k
46
+ })
47
+ });
48
+ }
49
+ return customRender ? customRender(v, d, index) : v;
50
+ }
34
51
  });
35
52
  }
36
53
  });
@@ -50,7 +67,7 @@ var generateRowActions = (btnConfigs, rowData, api) => {
50
67
  case "remove":
51
68
  if (api) {
52
69
  const apiParams = Object.entries(eventOption.params).reduce((o, [k, v]) => {
53
- if (("" + v).includes(VALUE_KEY)) o[k] = rowData[("" + v).split(VALUE_KEY)[1]];
70
+ if (("" + v).indexOf(VALUE_KEY) === 0) o[k] = rowData[("" + v).split(VALUE_KEY)[1]];
54
71
  else o[k] = v;
55
72
  return o;
56
73
  }, {});
@@ -2,6 +2,7 @@ import "./typing/scalability";
2
2
  export type * from "../apps/dash/types";
3
3
  export * from "./main";
4
4
  export type { CallComComponentsMap, CallComRenderer } from "./defaultPages/SchemaPage/schemaType";
5
+ export type { SchemaTableRenderComponent, SchemaTableRenderComponentsMap, } from "./defaultPages/SchemaPage/components/SchemaTable/data";
5
6
  export * from "./components/index";
6
7
  export type { FormFieldSchema, SchemaFormComponentsMap, SchemaFormNamespace, SelectProps } from "../../packages/react/ui/index";
7
8
  export { renderImportComponent } from "./common/importComponent";
@@ -1,11 +1,33 @@
1
- import { TableColumnDef } from "../../../packages/react/ui/index";
1
+ import type { PreviewImageProps, TableColumnDef } from "../../../packages/react/ui/index";
2
2
  import type { JSONSchema7 } from "json-schema";
3
3
  import { MOmit } from "../../../typings/type";
4
4
  import { BaseButton } from "./button";
5
5
  import { ComponentConfig, ComponentNames, ComponentsOption } from "./component";
6
6
  import { SearchOption } from "./search";
7
+ export declare namespace SchemaTableNamespace {
8
+ interface RenderComponentPropsMap {
9
+ }
10
+ }
11
+ export type BuiltInSchemaTableRenderComponentPropsMap = {
12
+ PreviewImage: Omit<PreviewImageProps, 'images'> & {
13
+ value?: unknown;
14
+ record?: Record<string, unknown>;
15
+ rowIndex?: number;
16
+ fieldKey?: string;
17
+ images?: PreviewImageProps['images'];
18
+ valueToImages?: (value: unknown, record?: Record<string, unknown>, rowIndex?: number, fieldKey?: string) => PreviewImageProps['images'];
19
+ };
20
+ };
21
+ export type SchemaTableRenderComponentPropsMap = BuiltInSchemaTableRenderComponentPropsMap & SchemaTableNamespace.RenderComponentPropsMap;
22
+ export type SchemaTableRenderComponentName = Extract<keyof SchemaTableRenderComponentPropsMap, string>;
23
+ export type SchemaTableRenderComponentOption = {
24
+ [K in SchemaTableRenderComponentName]: {
25
+ renderComponent?: K;
26
+ renderComponentProps?: Partial<Omit<SchemaTableRenderComponentPropsMap[K], 'value' | 'record' | 'rowIndex' | 'fieldKey'>>;
27
+ };
28
+ }[SchemaTableRenderComponentName];
7
29
  export type TableColumnsSchema = {
8
- tableOption?: MOmit<TableColumnDef, 'key' | 'title'> & {
30
+ tableOption?: MOmit<TableColumnDef, 'key' | 'title'> & SchemaTableRenderComponentOption & {
9
31
  visible?: boolean;
10
32
  toFixed?: number;
11
33
  };
@@ -1,2 +1,3 @@
1
1
  export type { MBMenuType, ModelDataType, ModelMode, ModelModeMap } from "./model";
2
2
  export type { BuiltInCallComConfigMap, BuiltInCallComNames, BuiltInCallComOptionMap, CallComNamespace, ComponentConfig, ComponentFieldOption, ComponentNames, ComponentsOption, } from "./data/component";
3
+ export type { BuiltInSchemaTableRenderComponentPropsMap, SchemaTableNamespace, SchemaTableRenderComponentName, SchemaTableRenderComponentOption, SchemaTableRenderComponentPropsMap, } from "./data/schema";
@@ -0,0 +1,21 @@
1
+ export type ColumnDefForKey<T> = {
2
+ [K in keyof T]: {
3
+ key: K;
4
+ title: string;
5
+ dataIndex?: string;
6
+ width?: string;
7
+ isAction?: boolean;
8
+ render?: (value: T[K], record: T, index: number) => React.ReactNode;
9
+ renderExport?: (value: T[K], record: T, index: number) => React.ReactNode;
10
+ };
11
+ }[keyof T];
12
+ export type ColumnDefAction<T> = {
13
+ key: 'action';
14
+ title: string;
15
+ dataIndex?: string;
16
+ width?: string;
17
+ isAction?: boolean;
18
+ render?: (value: unknown, record: T, index: number) => React.ReactNode;
19
+ renderExport?: (value: unknown, record: T, index: number) => React.ReactNode;
20
+ };
21
+ export type ColumnDef<T = Record<string, unknown>> = ColumnDefForKey<T> | ColumnDefAction<T>;
@@ -1,11 +1,33 @@
1
- import { TableColumnDef } from "../../../../fe/packages/react/ui/index";
1
+ import type { PreviewImageProps, TableColumnDef } from "../../../../fe/packages/react/ui/index";
2
2
  import type { JSONSchema7 } from "json-schema";
3
3
  import { MOmit } from "../../../../types/typings/type";
4
4
  import { BaseButton } from "./button";
5
5
  import { ComponentConfig, ComponentNames, ComponentsOption } from "./component";
6
6
  import { SearchOption } from "./search";
7
+ export declare namespace SchemaTableNamespace {
8
+ interface RenderComponentPropsMap {
9
+ }
10
+ }
11
+ export type BuiltInSchemaTableRenderComponentPropsMap = {
12
+ PreviewImage: Omit<PreviewImageProps, 'images'> & {
13
+ value?: unknown;
14
+ record?: Record<string, unknown>;
15
+ rowIndex?: number;
16
+ fieldKey?: string;
17
+ images?: PreviewImageProps['images'];
18
+ valueToImages?: (value: unknown, record?: Record<string, unknown>, rowIndex?: number, fieldKey?: string) => PreviewImageProps['images'];
19
+ };
20
+ };
21
+ export type SchemaTableRenderComponentPropsMap = BuiltInSchemaTableRenderComponentPropsMap & SchemaTableNamespace.RenderComponentPropsMap;
22
+ export type SchemaTableRenderComponentName = Extract<keyof SchemaTableRenderComponentPropsMap, string>;
23
+ export type SchemaTableRenderComponentOption = {
24
+ [K in SchemaTableRenderComponentName]: {
25
+ renderComponent?: K;
26
+ renderComponentProps?: Partial<Omit<SchemaTableRenderComponentPropsMap[K], 'value' | 'record' | 'rowIndex' | 'fieldKey'>>;
27
+ };
28
+ }[SchemaTableRenderComponentName];
7
29
  export type TableColumnsSchema = {
8
- tableOption?: MOmit<TableColumnDef, 'key' | 'title'> & {
30
+ tableOption?: MOmit<TableColumnDef, 'key' | 'title'> & SchemaTableRenderComponentOption & {
9
31
  visible?: boolean;
10
32
  toFixed?: number;
11
33
  };
@@ -1,2 +1,3 @@
1
1
  export type { MBMenuType, ModelDataType, ModelMode, ModelModeMap } from "./model";
2
2
  export type { BuiltInCallComConfigMap, BuiltInCallComNames, BuiltInCallComOptionMap, CallComNamespace, ComponentConfig, ComponentFieldOption, ComponentNames, ComponentsOption, } from "./data/component";
3
+ export type { BuiltInSchemaTableRenderComponentPropsMap, SchemaTableNamespace, SchemaTableRenderComponentName, SchemaTableRenderComponentOption, SchemaTableRenderComponentPropsMap, } from "./data/schema";
@@ -0,0 +1,21 @@
1
+ export type ColumnDefForKey<T> = {
2
+ [K in keyof T]: {
3
+ key: K;
4
+ title: string;
5
+ dataIndex?: string;
6
+ width?: string;
7
+ isAction?: boolean;
8
+ render?: (value: T[K], record: T, index: number) => React.ReactNode;
9
+ renderExport?: (value: T[K], record: T, index: number) => React.ReactNode;
10
+ };
11
+ }[keyof T];
12
+ export type ColumnDefAction<T> = {
13
+ key: 'action';
14
+ title: string;
15
+ dataIndex?: string;
16
+ width?: string;
17
+ isAction?: boolean;
18
+ render?: (value: unknown, record: T, index: number) => React.ReactNode;
19
+ renderExport?: (value: unknown, record: T, index: number) => React.ReactNode;
20
+ };
21
+ export type ColumnDef<T = Record<string, unknown>> = ColumnDefForKey<T> | ColumnDefAction<T>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@_tc/template-core",
3
- "version": "0.2.0-bate.5",
3
+ "version": "0.2.0-bate.7",
4
4
  "description": "A full-stack TypeScript admin framework powered by Koa, React, and Vite - monorepo root",
5
5
  "types": "./types/index.d.ts",
6
6
  "exports": {
@@ -0,0 +1,2 @@
1
+ import type { BuildFEOptions } from "./state";
2
+ export declare const buildFE: (mode: "dev" | "prod", options?: BuildFEOptions) => Promise<void>;
@@ -1,4 +1,3 @@
1
- import type { BuildFEOptions } from "./state";
2
1
  export { buildBE } from "./buildBE";
3
2
  export type { BuildBEAlias, BuildBEFormat, BuildBEOptions, BuildBEResult } from "./buildBE";
4
- export declare const buildFE: (mode: "dev" | "prod", options?: BuildFEOptions) => Promise<void>;
3
+ export { buildFE } from "./buildFE";