imean-service-engine 2.2.0 → 2.2.2
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/dist/index.d.mts +7 -4
- package/dist/index.d.ts +7 -4
- package/dist/index.js +179 -148
- package/dist/index.mjs +179 -148
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -1499,7 +1499,7 @@ declare class PathHelper {
|
|
|
1499
1499
|
detail(id: string | number, dialog?: boolean): string;
|
|
1500
1500
|
/**
|
|
1501
1501
|
* 编辑页动作
|
|
1502
|
-
* 生成路径: {basePath}/{id}
|
|
1502
|
+
* 生成路径: {basePath}/edit/{id}
|
|
1503
1503
|
* @param dialog 是否在对话框中打开
|
|
1504
1504
|
*/
|
|
1505
1505
|
edit(id: string | number, dialog?: boolean): string;
|
|
@@ -1767,13 +1767,11 @@ declare abstract class DetailPageModule<T = any> extends PageModule {
|
|
|
1767
1767
|
* 可以重写 render 方法来自定义渲染,否则使用默认的表单渲染逻辑
|
|
1768
1768
|
*/
|
|
1769
1769
|
declare abstract class FormPageModule<T = any> extends PageModule {
|
|
1770
|
-
/** 数据源 */
|
|
1771
|
-
protected datasource: FormDatasource<T>;
|
|
1772
1770
|
/** ID 字段名(默认 "id") */
|
|
1773
1771
|
protected idField: string;
|
|
1774
1772
|
/** Zod Schema(可选,如果提供则自动生成表单字段和校验) */
|
|
1775
1773
|
protected schema?: z.ZodObject<any>;
|
|
1776
|
-
constructor(
|
|
1774
|
+
constructor(schema?: z.ZodObject<any>);
|
|
1777
1775
|
/**
|
|
1778
1776
|
* 获取数据源(抽象方法,必须实现)
|
|
1779
1777
|
* 子类必须实现此方法来提供数据源
|
|
@@ -1910,6 +1908,11 @@ declare abstract class ListPageModule<T extends {
|
|
|
1910
1908
|
* 删除数据(可选,如果数据源支持删除)
|
|
1911
1909
|
*/
|
|
1912
1910
|
deleteItem(id: string | number): Promise<boolean>;
|
|
1911
|
+
/**
|
|
1912
|
+
* 获取字段标签(可选)
|
|
1913
|
+
* 子类可以重写此方法来自定义字段的中文标签
|
|
1914
|
+
*/
|
|
1915
|
+
getFieldLabel?(field: string): string;
|
|
1913
1916
|
/**
|
|
1914
1917
|
* 自定义列渲染(可选)
|
|
1915
1918
|
* 子类可以重写此方法来自定义列的渲染逻辑
|
package/dist/index.d.ts
CHANGED
|
@@ -1499,7 +1499,7 @@ declare class PathHelper {
|
|
|
1499
1499
|
detail(id: string | number, dialog?: boolean): string;
|
|
1500
1500
|
/**
|
|
1501
1501
|
* 编辑页动作
|
|
1502
|
-
* 生成路径: {basePath}/{id}
|
|
1502
|
+
* 生成路径: {basePath}/edit/{id}
|
|
1503
1503
|
* @param dialog 是否在对话框中打开
|
|
1504
1504
|
*/
|
|
1505
1505
|
edit(id: string | number, dialog?: boolean): string;
|
|
@@ -1767,13 +1767,11 @@ declare abstract class DetailPageModule<T = any> extends PageModule {
|
|
|
1767
1767
|
* 可以重写 render 方法来自定义渲染,否则使用默认的表单渲染逻辑
|
|
1768
1768
|
*/
|
|
1769
1769
|
declare abstract class FormPageModule<T = any> extends PageModule {
|
|
1770
|
-
/** 数据源 */
|
|
1771
|
-
protected datasource: FormDatasource<T>;
|
|
1772
1770
|
/** ID 字段名(默认 "id") */
|
|
1773
1771
|
protected idField: string;
|
|
1774
1772
|
/** Zod Schema(可选,如果提供则自动生成表单字段和校验) */
|
|
1775
1773
|
protected schema?: z.ZodObject<any>;
|
|
1776
|
-
constructor(
|
|
1774
|
+
constructor(schema?: z.ZodObject<any>);
|
|
1777
1775
|
/**
|
|
1778
1776
|
* 获取数据源(抽象方法,必须实现)
|
|
1779
1777
|
* 子类必须实现此方法来提供数据源
|
|
@@ -1910,6 +1908,11 @@ declare abstract class ListPageModule<T extends {
|
|
|
1910
1908
|
* 删除数据(可选,如果数据源支持删除)
|
|
1911
1909
|
*/
|
|
1912
1910
|
deleteItem(id: string | number): Promise<boolean>;
|
|
1911
|
+
/**
|
|
1912
|
+
* 获取字段标签(可选)
|
|
1913
|
+
* 子类可以重写此方法来自定义字段的中文标签
|
|
1914
|
+
*/
|
|
1915
|
+
getFieldLabel?(field: string): string;
|
|
1913
1916
|
/**
|
|
1914
1917
|
* 自定义列渲染(可选)
|
|
1915
1918
|
* 子类可以重写此方法来自定义列的渲染逻辑
|
package/dist/index.js
CHANGED
|
@@ -3908,7 +3908,7 @@ var Button = (props) => {
|
|
|
3908
3908
|
if (hxConfirm) htmxAttrs["hx-confirm"] = hxConfirm;
|
|
3909
3909
|
if (hxHeaders) htmxAttrs["hx-headers"] = hxHeaders;
|
|
3910
3910
|
const Tag = hxGet || hxPost || hxPut || hxDelete ? "a" : "button";
|
|
3911
|
-
const href =
|
|
3911
|
+
const href = rest.href ?? hxGet ?? "#";
|
|
3912
3912
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3913
3913
|
Tag,
|
|
3914
3914
|
{
|
|
@@ -4090,11 +4090,11 @@ var PathHelper = class {
|
|
|
4090
4090
|
}
|
|
4091
4091
|
/**
|
|
4092
4092
|
* 编辑页动作
|
|
4093
|
-
* 生成路径: {basePath}/{id}
|
|
4093
|
+
* 生成路径: {basePath}/edit/{id}
|
|
4094
4094
|
* @param dialog 是否在对话框中打开
|
|
4095
4095
|
*/
|
|
4096
4096
|
edit(id, dialog = false) {
|
|
4097
|
-
const url = `${this.basePath}/${id}
|
|
4097
|
+
const url = `${this.basePath}/edit/${id}`;
|
|
4098
4098
|
return dialog ? `${url}?dialog=true` : url;
|
|
4099
4099
|
}
|
|
4100
4100
|
/**
|
|
@@ -4777,25 +4777,20 @@ function validateFormDataWithSchema(schema, data) {
|
|
|
4777
4777
|
}
|
|
4778
4778
|
}
|
|
4779
4779
|
var FormPageModule = class extends PageModule {
|
|
4780
|
-
/** 数据源 */
|
|
4781
|
-
datasource;
|
|
4782
4780
|
/** ID 字段名(默认 "id") */
|
|
4783
4781
|
idField = "id";
|
|
4784
4782
|
/** Zod Schema(可选,如果提供则自动生成表单字段和校验) */
|
|
4785
4783
|
schema;
|
|
4786
|
-
constructor(
|
|
4784
|
+
constructor(schema) {
|
|
4787
4785
|
super();
|
|
4788
|
-
this.datasource = datasource;
|
|
4789
4786
|
this.schema = schema;
|
|
4790
4787
|
}
|
|
4791
4788
|
/**
|
|
4792
4789
|
* 获取单条数据(编辑时使用)
|
|
4793
4790
|
*/
|
|
4794
4791
|
async getItem(id) {
|
|
4795
|
-
|
|
4796
|
-
|
|
4797
|
-
}
|
|
4798
|
-
return await this.datasource.getItem(id);
|
|
4792
|
+
const datasource = this.getDatasource();
|
|
4793
|
+
return await datasource.getItem?.(id) || null;
|
|
4799
4794
|
}
|
|
4800
4795
|
/**
|
|
4801
4796
|
* 获取字段标签(可选)
|
|
@@ -4938,7 +4933,9 @@ var FormPageModule = class extends PageModule {
|
|
|
4938
4933
|
return await this.renderFormPage(adminContext, null, false, body);
|
|
4939
4934
|
}
|
|
4940
4935
|
try {
|
|
4941
|
-
const newItem = await this.
|
|
4936
|
+
const newItem = await this.getDatasource().createItem?.(
|
|
4937
|
+
body
|
|
4938
|
+
);
|
|
4942
4939
|
const basePath = this.context.moduleMetadata.basePath;
|
|
4943
4940
|
const hasDetail = this.context.moduleMetadata.hasDetail;
|
|
4944
4941
|
const hasList = this.context.moduleMetadata.hasList;
|
|
@@ -5272,6 +5269,127 @@ var Pagination = (props) => {
|
|
|
5272
5269
|
] })
|
|
5273
5270
|
] });
|
|
5274
5271
|
};
|
|
5272
|
+
var STYLES = {
|
|
5273
|
+
header: {
|
|
5274
|
+
container: "px-6 py-4 border-b border-gray-200 flex items-center justify-between",
|
|
5275
|
+
title: "text-lg font-semibold text-gray-900",
|
|
5276
|
+
actions: "flex gap-2"
|
|
5277
|
+
},
|
|
5278
|
+
table: {
|
|
5279
|
+
container: "overflow-x-auto",
|
|
5280
|
+
table: "min-w-full divide-y divide-gray-200",
|
|
5281
|
+
thead: "bg-gray-50",
|
|
5282
|
+
th: {
|
|
5283
|
+
base: "px-6 py-3 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider whitespace-nowrap",
|
|
5284
|
+
stickyLeft: "sticky left-0 z-20 bg-gray-50 border-r border-gray-200 whitespace-nowrap",
|
|
5285
|
+
stickyRight: "sticky right-0 z-20 bg-gray-50 border-l border-gray-200 whitespace-nowrap"
|
|
5286
|
+
},
|
|
5287
|
+
tbody: "bg-white divide-y divide-gray-200",
|
|
5288
|
+
tr: "group hover:bg-gray-50 transition-colors",
|
|
5289
|
+
td: {
|
|
5290
|
+
base: "px-6 py-4 whitespace-nowrap text-sm text-gray-900",
|
|
5291
|
+
stickyLeft: "sticky left-0 z-10 bg-white group-hover:bg-gray-50 transition-colors border-r border-gray-200",
|
|
5292
|
+
stickyRight: "sticky right-0 z-10 bg-white group-hover:bg-gray-50 transition-colors border-l border-gray-200"
|
|
5293
|
+
}
|
|
5294
|
+
},
|
|
5295
|
+
actionLink: {
|
|
5296
|
+
container: "flex gap-3",
|
|
5297
|
+
base: "text-sm hover:underline",
|
|
5298
|
+
default: "text-blue-600 hover:text-blue-800",
|
|
5299
|
+
delete: "text-red-600 hover:text-red-800"
|
|
5300
|
+
},
|
|
5301
|
+
actionButton: "flex gap-2 flex-wrap"
|
|
5302
|
+
};
|
|
5303
|
+
function TableHeader(props) {
|
|
5304
|
+
const { title, tableActions } = props;
|
|
5305
|
+
const showHeader = title && title.trim() || tableActions && tableActions.length > 0;
|
|
5306
|
+
if (!showHeader) return null;
|
|
5307
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: STYLES.header.container, children: [
|
|
5308
|
+
title && title.trim() ? /* @__PURE__ */ jsxRuntime.jsx("h3", { className: STYLES.header.title, children: title }) : /* @__PURE__ */ jsxRuntime.jsx("div", {}),
|
|
5309
|
+
tableActions && tableActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: STYLES.header.actions, children: tableActions.map((action, idx) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
5310
|
+
Button,
|
|
5311
|
+
{
|
|
5312
|
+
variant: action.variant || "secondary",
|
|
5313
|
+
href: action.href,
|
|
5314
|
+
hxGet: action.hxGet,
|
|
5315
|
+
hxPost: action.hxPost,
|
|
5316
|
+
hxDelete: action.hxDelete,
|
|
5317
|
+
hxConfirm: action.hxConfirm,
|
|
5318
|
+
children: action.label
|
|
5319
|
+
},
|
|
5320
|
+
idx
|
|
5321
|
+
)) })
|
|
5322
|
+
] });
|
|
5323
|
+
}
|
|
5324
|
+
function TableHeaderRow(props) {
|
|
5325
|
+
const { idColumn, otherColumns, hasActions } = props;
|
|
5326
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
5327
|
+
idColumn && /* @__PURE__ */ jsxRuntime.jsx("th", { className: `${STYLES.table.th.base} ${STYLES.table.th.stickyLeft}`, children: idColumn.label }),
|
|
5328
|
+
otherColumns.map((col) => /* @__PURE__ */ jsxRuntime.jsx("th", { className: STYLES.table.th.base, children: col.label }, col.key)),
|
|
5329
|
+
hasActions && /* @__PURE__ */ jsxRuntime.jsx(
|
|
5330
|
+
"th",
|
|
5331
|
+
{
|
|
5332
|
+
className: `${STYLES.table.th.base} ${STYLES.table.th.stickyRight}`,
|
|
5333
|
+
children: "\u64CD\u4F5C"
|
|
5334
|
+
}
|
|
5335
|
+
)
|
|
5336
|
+
] });
|
|
5337
|
+
}
|
|
5338
|
+
function TableCell(props) {
|
|
5339
|
+
const { column, item, isSticky, stickyClass } = props;
|
|
5340
|
+
const value = item[column.key];
|
|
5341
|
+
const content = column.render ? safeRender(column.render(value, item)) : String(value || "");
|
|
5342
|
+
const className = isSticky ? `${STYLES.table.td.base} ${stickyClass || ""}` : STYLES.table.td.base;
|
|
5343
|
+
return /* @__PURE__ */ jsxRuntime.jsx("td", { className, children: content });
|
|
5344
|
+
}
|
|
5345
|
+
function ActionLink(props) {
|
|
5346
|
+
const { action, item } = props;
|
|
5347
|
+
const hrefValue = action.href(item);
|
|
5348
|
+
const isDelete = action.method === "delete";
|
|
5349
|
+
const className = `${STYLES.actionLink.base} ${isDelete ? STYLES.actionLink.delete : STYLES.actionLink.default}`;
|
|
5350
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5351
|
+
"a",
|
|
5352
|
+
{
|
|
5353
|
+
href: hrefValue,
|
|
5354
|
+
className,
|
|
5355
|
+
"hx-get": !isDelete ? hrefValue : void 0,
|
|
5356
|
+
"hx-delete": isDelete ? hrefValue : void 0,
|
|
5357
|
+
"hx-confirm": isDelete ? "\u786E\u5B9A\u5220\u9664\u5417\uFF1F" : void 0,
|
|
5358
|
+
children: action.label
|
|
5359
|
+
}
|
|
5360
|
+
);
|
|
5361
|
+
}
|
|
5362
|
+
function ActionCell(props) {
|
|
5363
|
+
const { actions, item, actionStyle } = props;
|
|
5364
|
+
if (!actions || actions.length === 0) return null;
|
|
5365
|
+
return /* @__PURE__ */ jsxRuntime.jsx("td", { className: `${STYLES.table.td.base} ${STYLES.table.td.stickyRight}`, children: actionStyle === "link" ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: STYLES.actionLink.container, children: actions.map((action, idx) => /* @__PURE__ */ jsxRuntime.jsx(ActionLink, { action, item }, idx)) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: STYLES.actionButton, children: actions.map((action, idx) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
5366
|
+
ActionButton,
|
|
5367
|
+
{
|
|
5368
|
+
label: action.label,
|
|
5369
|
+
href: action.href,
|
|
5370
|
+
method: action.method,
|
|
5371
|
+
className: action.class,
|
|
5372
|
+
item
|
|
5373
|
+
},
|
|
5374
|
+
idx
|
|
5375
|
+
)) }) });
|
|
5376
|
+
}
|
|
5377
|
+
function TableRow(props) {
|
|
5378
|
+
const { item, idColumn, otherColumns, actions, actionStyle } = props;
|
|
5379
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: STYLES.table.tr, children: [
|
|
5380
|
+
idColumn && /* @__PURE__ */ jsxRuntime.jsx(
|
|
5381
|
+
TableCell,
|
|
5382
|
+
{
|
|
5383
|
+
column: idColumn,
|
|
5384
|
+
item,
|
|
5385
|
+
isSticky: true,
|
|
5386
|
+
stickyClass: STYLES.table.td.stickyLeft
|
|
5387
|
+
}
|
|
5388
|
+
),
|
|
5389
|
+
otherColumns.map((col) => /* @__PURE__ */ jsxRuntime.jsx(TableCell, { column: col, item }, col.key)),
|
|
5390
|
+
actions && actions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(ActionCell, { actions, item, actionStyle })
|
|
5391
|
+
] });
|
|
5392
|
+
}
|
|
5275
5393
|
var Table = (props) => {
|
|
5276
5394
|
const {
|
|
5277
5395
|
items,
|
|
@@ -5284,119 +5402,28 @@ var Table = (props) => {
|
|
|
5284
5402
|
} = props;
|
|
5285
5403
|
const idColumn = columns.find((col) => col.key === "id");
|
|
5286
5404
|
const otherColumns = columns.filter((col) => col.key !== "id");
|
|
5287
|
-
const
|
|
5288
|
-
const actionsColumnMinWidth = actions && actions.length > 0 ? actions.length * 30 + 48 + (actions.length - 1) * 8 : 0;
|
|
5289
|
-
const showHeader = title && title.trim() || tableActions && tableActions.length > 0;
|
|
5290
|
-
const hasTitle = title && title.trim();
|
|
5405
|
+
const hasActions = Boolean(actions && actions.length > 0);
|
|
5291
5406
|
return /* @__PURE__ */ jsxRuntime.jsxs(Card, { shadow: true, noPadding: true, className: "overflow-hidden", children: [
|
|
5292
|
-
|
|
5293
|
-
hasTitle ? /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold text-gray-900", children: title }) : /* @__PURE__ */ jsxRuntime.jsx("div", {}),
|
|
5294
|
-
tableActions && tableActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex gap-2", children: tableActions.map((action, idx) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
5295
|
-
Button,
|
|
5296
|
-
{
|
|
5297
|
-
variant: action.variant || "secondary",
|
|
5298
|
-
href: action.href,
|
|
5299
|
-
hxGet: action.hxGet,
|
|
5300
|
-
hxPost: action.hxPost,
|
|
5301
|
-
hxDelete: action.hxDelete,
|
|
5302
|
-
hxConfirm: action.hxConfirm,
|
|
5303
|
-
children: action.label
|
|
5304
|
-
},
|
|
5305
|
-
idx
|
|
5306
|
-
)) })
|
|
5307
|
-
] }),
|
|
5407
|
+
/* @__PURE__ */ jsxRuntime.jsx(TableHeader, { title, tableActions }),
|
|
5308
5408
|
items.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(EmptyState, { message: "\u6682\u65E0\u6570\u636E" }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
5309
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className:
|
|
5310
|
-
/* @__PURE__ */ jsxRuntime.jsx("thead", { className:
|
|
5311
|
-
|
|
5312
|
-
"th",
|
|
5313
|
-
{
|
|
5314
|
-
className: "px-6 py-3 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider sticky left-0 z-20 bg-gray-50 border-r border-gray-200",
|
|
5315
|
-
style: {
|
|
5316
|
-
minWidth: `${idColumnWidth}px`,
|
|
5317
|
-
maxWidth: `${idColumnWidth}px`
|
|
5318
|
-
},
|
|
5319
|
-
children: idColumn.label
|
|
5320
|
-
}
|
|
5321
|
-
),
|
|
5322
|
-
otherColumns.map((col) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
5323
|
-
"th",
|
|
5324
|
-
{
|
|
5325
|
-
className: "px-6 py-3 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider",
|
|
5326
|
-
children: col.label
|
|
5327
|
-
},
|
|
5328
|
-
col.key
|
|
5329
|
-
)),
|
|
5330
|
-
actions && actions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
5331
|
-
"th",
|
|
5332
|
-
{
|
|
5333
|
-
className: "px-6 py-3 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider sticky right-0 z-20 bg-gray-50 border-l border-gray-200 whitespace-nowrap",
|
|
5334
|
-
style: { minWidth: `${actionsColumnMinWidth}px` },
|
|
5335
|
-
children: "\u64CD\u4F5C"
|
|
5336
|
-
}
|
|
5337
|
-
)
|
|
5338
|
-
] }) }),
|
|
5339
|
-
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "bg-white divide-y divide-gray-200", children: items.map((item, rowIndex) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5340
|
-
"tr",
|
|
5409
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: STYLES.table.container, children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: STYLES.table.table, children: [
|
|
5410
|
+
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: STYLES.table.thead, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5411
|
+
TableHeaderRow,
|
|
5341
5412
|
{
|
|
5342
|
-
|
|
5343
|
-
|
|
5344
|
-
|
|
5345
|
-
|
|
5346
|
-
|
|
5347
|
-
|
|
5348
|
-
|
|
5349
|
-
|
|
5350
|
-
|
|
5351
|
-
|
|
5352
|
-
|
|
5353
|
-
|
|
5354
|
-
|
|
5355
|
-
|
|
5356
|
-
),
|
|
5357
|
-
otherColumns.map((col) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
5358
|
-
"td",
|
|
5359
|
-
{
|
|
5360
|
-
className: "px-6 py-4 whitespace-nowrap text-sm text-gray-900",
|
|
5361
|
-
children: col.render ? safeRender(col.render(item[col.key], item)) : String(item[col.key] || "")
|
|
5362
|
-
},
|
|
5363
|
-
col.key
|
|
5364
|
-
)),
|
|
5365
|
-
actions && actions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
5366
|
-
"td",
|
|
5367
|
-
{
|
|
5368
|
-
className: "px-6 py-4 whitespace-nowrap text-sm sticky right-0 z-10 bg-white group-hover:bg-gray-50 transition-colors border-l border-gray-200",
|
|
5369
|
-
style: { minWidth: `${actionsColumnMinWidth}px` },
|
|
5370
|
-
children: actionStyle === "link" ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex gap-3", children: actions.map((action, idx) => {
|
|
5371
|
-
const hrefValue = typeof action.href === "function" ? action.href(item) : action.href;
|
|
5372
|
-
const isDelete = action.method === "delete";
|
|
5373
|
-
action.dialog || hrefValue.includes("dialog=true");
|
|
5374
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5375
|
-
"a",
|
|
5376
|
-
{
|
|
5377
|
-
href: hrefValue,
|
|
5378
|
-
className: `text-sm ${isDelete ? "text-red-600 hover:text-red-800" : "text-blue-600 hover:text-blue-800"} hover:underline`,
|
|
5379
|
-
"hx-get": !isDelete ? hrefValue : void 0,
|
|
5380
|
-
"hx-delete": isDelete ? hrefValue : void 0,
|
|
5381
|
-
"hx-confirm": isDelete ? "\u786E\u5B9A\u5220\u9664\u5417\uFF1F" : void 0,
|
|
5382
|
-
children: action.label
|
|
5383
|
-
},
|
|
5384
|
-
idx
|
|
5385
|
-
);
|
|
5386
|
-
}) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex gap-2 flex-wrap", children: actions.map((action, idx) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
5387
|
-
ActionButton,
|
|
5388
|
-
{
|
|
5389
|
-
label: action.label,
|
|
5390
|
-
href: action.href,
|
|
5391
|
-
method: action.method,
|
|
5392
|
-
className: action.class,
|
|
5393
|
-
item
|
|
5394
|
-
},
|
|
5395
|
-
idx
|
|
5396
|
-
)) })
|
|
5397
|
-
}
|
|
5398
|
-
)
|
|
5399
|
-
]
|
|
5413
|
+
columns,
|
|
5414
|
+
idColumn,
|
|
5415
|
+
otherColumns,
|
|
5416
|
+
hasActions
|
|
5417
|
+
}
|
|
5418
|
+
) }),
|
|
5419
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: STYLES.table.tbody, children: items.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
5420
|
+
TableRow,
|
|
5421
|
+
{
|
|
5422
|
+
item,
|
|
5423
|
+
idColumn,
|
|
5424
|
+
otherColumns,
|
|
5425
|
+
actions,
|
|
5426
|
+
actionStyle
|
|
5400
5427
|
},
|
|
5401
5428
|
item.id
|
|
5402
5429
|
)) })
|
|
@@ -5528,6 +5555,13 @@ var ListPageModule = class extends PageModule {
|
|
|
5528
5555
|
}
|
|
5529
5556
|
return false;
|
|
5530
5557
|
}
|
|
5558
|
+
/**
|
|
5559
|
+
* 获取字段标签(可选)
|
|
5560
|
+
* 子类可以重写此方法来自定义字段的中文标签
|
|
5561
|
+
*/
|
|
5562
|
+
getFieldLabel(field) {
|
|
5563
|
+
return field;
|
|
5564
|
+
}
|
|
5531
5565
|
/**
|
|
5532
5566
|
* 自定义列渲染(可选)
|
|
5533
5567
|
* 子类可以重写此方法来自定义列的渲染逻辑
|
|
@@ -5607,7 +5641,7 @@ var ListPageModule = class extends PageModule {
|
|
|
5607
5641
|
const tableTitle = this.getTableTitle ? this.getTableTitle() : pageTitle;
|
|
5608
5642
|
const columns = result.items.length > 0 ? Object.keys(result.items[0]).map((key) => ({
|
|
5609
5643
|
key,
|
|
5610
|
-
label: key,
|
|
5644
|
+
label: this.getFieldLabel ? this.getFieldLabel(key) : key,
|
|
5611
5645
|
render: this.renderColumn ? (value, item) => this.renderColumn(key, value, item) : void 0
|
|
5612
5646
|
})) : [];
|
|
5613
5647
|
const actions = this.getActions && result.items.length > 0 ? this.getActions(result.items[0]) : [];
|
|
@@ -6610,6 +6644,9 @@ var HtmxAdminPlugin = class {
|
|
|
6610
6644
|
* 检查并注册模块
|
|
6611
6645
|
*/
|
|
6612
6646
|
checkAndRegisterModules(modules) {
|
|
6647
|
+
modules = modules.filter(
|
|
6648
|
+
(module) => module.clazz instanceof PageModule || module.clazz.prototype instanceof PageModule
|
|
6649
|
+
);
|
|
6613
6650
|
for (const module of modules) {
|
|
6614
6651
|
const options = module.options;
|
|
6615
6652
|
const moduleClass = module.clazz;
|
|
@@ -6688,31 +6725,25 @@ var HtmxAdminPlugin = class {
|
|
|
6688
6725
|
description: moduleInfo.options.description ?? ""
|
|
6689
6726
|
}
|
|
6690
6727
|
});
|
|
6691
|
-
|
|
6692
|
-
|
|
6693
|
-
|
|
6694
|
-
|
|
6695
|
-
|
|
6696
|
-
|
|
6697
|
-
|
|
6698
|
-
|
|
6699
|
-
|
|
6700
|
-
|
|
6701
|
-
|
|
6702
|
-
|
|
6703
|
-
|
|
6704
|
-
|
|
6705
|
-
|
|
6706
|
-
|
|
6707
|
-
|
|
6708
|
-
|
|
6709
|
-
this.hono.
|
|
6710
|
-
return routeHandler.handle(ctx);
|
|
6711
|
-
});
|
|
6712
|
-
} else if (type === "custom") {
|
|
6713
|
-
this.hono.get(basePath, async (ctx) => {
|
|
6714
|
-
return routeHandler.handle(ctx);
|
|
6715
|
-
});
|
|
6728
|
+
const routeConfig = {
|
|
6729
|
+
list: [{ method: "get", path: `${basePath}/list` }],
|
|
6730
|
+
detail: [{ method: "get", path: `${basePath}/detail/:id` }],
|
|
6731
|
+
form: [
|
|
6732
|
+
{ method: "get", path: `${basePath}/new` },
|
|
6733
|
+
{ method: "get", path: `${basePath}/edit/:id` },
|
|
6734
|
+
{ method: "post", path: basePath },
|
|
6735
|
+
{ method: "put", path: `${basePath}/:id` },
|
|
6736
|
+
{ method: "delete", path: `${basePath}/:id` }
|
|
6737
|
+
],
|
|
6738
|
+
custom: [{ method: "get", path: basePath }]
|
|
6739
|
+
};
|
|
6740
|
+
const routes = routeConfig[type];
|
|
6741
|
+
for (const route of routes) {
|
|
6742
|
+
logger_default.info(
|
|
6743
|
+
`[HtmxAdminPlugin] Registering ${type} route: ${route.method.toUpperCase()} ${route.path}`
|
|
6744
|
+
);
|
|
6745
|
+
const handler = async (ctx) => routeHandler.handle(ctx);
|
|
6746
|
+
this.hono[route.method](route.path, handler);
|
|
6716
6747
|
}
|
|
6717
6748
|
}
|
|
6718
6749
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -3883,7 +3883,7 @@ var Button = (props) => {
|
|
|
3883
3883
|
if (hxConfirm) htmxAttrs["hx-confirm"] = hxConfirm;
|
|
3884
3884
|
if (hxHeaders) htmxAttrs["hx-headers"] = hxHeaders;
|
|
3885
3885
|
const Tag = hxGet || hxPost || hxPut || hxDelete ? "a" : "button";
|
|
3886
|
-
const href =
|
|
3886
|
+
const href = rest.href ?? hxGet ?? "#";
|
|
3887
3887
|
return /* @__PURE__ */ jsx(
|
|
3888
3888
|
Tag,
|
|
3889
3889
|
{
|
|
@@ -4065,11 +4065,11 @@ var PathHelper = class {
|
|
|
4065
4065
|
}
|
|
4066
4066
|
/**
|
|
4067
4067
|
* 编辑页动作
|
|
4068
|
-
* 生成路径: {basePath}/{id}
|
|
4068
|
+
* 生成路径: {basePath}/edit/{id}
|
|
4069
4069
|
* @param dialog 是否在对话框中打开
|
|
4070
4070
|
*/
|
|
4071
4071
|
edit(id, dialog = false) {
|
|
4072
|
-
const url = `${this.basePath}/${id}
|
|
4072
|
+
const url = `${this.basePath}/edit/${id}`;
|
|
4073
4073
|
return dialog ? `${url}?dialog=true` : url;
|
|
4074
4074
|
}
|
|
4075
4075
|
/**
|
|
@@ -4752,25 +4752,20 @@ function validateFormDataWithSchema(schema, data) {
|
|
|
4752
4752
|
}
|
|
4753
4753
|
}
|
|
4754
4754
|
var FormPageModule = class extends PageModule {
|
|
4755
|
-
/** 数据源 */
|
|
4756
|
-
datasource;
|
|
4757
4755
|
/** ID 字段名(默认 "id") */
|
|
4758
4756
|
idField = "id";
|
|
4759
4757
|
/** Zod Schema(可选,如果提供则自动生成表单字段和校验) */
|
|
4760
4758
|
schema;
|
|
4761
|
-
constructor(
|
|
4759
|
+
constructor(schema) {
|
|
4762
4760
|
super();
|
|
4763
|
-
this.datasource = datasource;
|
|
4764
4761
|
this.schema = schema;
|
|
4765
4762
|
}
|
|
4766
4763
|
/**
|
|
4767
4764
|
* 获取单条数据(编辑时使用)
|
|
4768
4765
|
*/
|
|
4769
4766
|
async getItem(id) {
|
|
4770
|
-
|
|
4771
|
-
|
|
4772
|
-
}
|
|
4773
|
-
return await this.datasource.getItem(id);
|
|
4767
|
+
const datasource = this.getDatasource();
|
|
4768
|
+
return await datasource.getItem?.(id) || null;
|
|
4774
4769
|
}
|
|
4775
4770
|
/**
|
|
4776
4771
|
* 获取字段标签(可选)
|
|
@@ -4913,7 +4908,9 @@ var FormPageModule = class extends PageModule {
|
|
|
4913
4908
|
return await this.renderFormPage(adminContext, null, false, body);
|
|
4914
4909
|
}
|
|
4915
4910
|
try {
|
|
4916
|
-
const newItem = await this.
|
|
4911
|
+
const newItem = await this.getDatasource().createItem?.(
|
|
4912
|
+
body
|
|
4913
|
+
);
|
|
4917
4914
|
const basePath = this.context.moduleMetadata.basePath;
|
|
4918
4915
|
const hasDetail = this.context.moduleMetadata.hasDetail;
|
|
4919
4916
|
const hasList = this.context.moduleMetadata.hasList;
|
|
@@ -5247,6 +5244,127 @@ var Pagination = (props) => {
|
|
|
5247
5244
|
] })
|
|
5248
5245
|
] });
|
|
5249
5246
|
};
|
|
5247
|
+
var STYLES = {
|
|
5248
|
+
header: {
|
|
5249
|
+
container: "px-6 py-4 border-b border-gray-200 flex items-center justify-between",
|
|
5250
|
+
title: "text-lg font-semibold text-gray-900",
|
|
5251
|
+
actions: "flex gap-2"
|
|
5252
|
+
},
|
|
5253
|
+
table: {
|
|
5254
|
+
container: "overflow-x-auto",
|
|
5255
|
+
table: "min-w-full divide-y divide-gray-200",
|
|
5256
|
+
thead: "bg-gray-50",
|
|
5257
|
+
th: {
|
|
5258
|
+
base: "px-6 py-3 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider whitespace-nowrap",
|
|
5259
|
+
stickyLeft: "sticky left-0 z-20 bg-gray-50 border-r border-gray-200 whitespace-nowrap",
|
|
5260
|
+
stickyRight: "sticky right-0 z-20 bg-gray-50 border-l border-gray-200 whitespace-nowrap"
|
|
5261
|
+
},
|
|
5262
|
+
tbody: "bg-white divide-y divide-gray-200",
|
|
5263
|
+
tr: "group hover:bg-gray-50 transition-colors",
|
|
5264
|
+
td: {
|
|
5265
|
+
base: "px-6 py-4 whitespace-nowrap text-sm text-gray-900",
|
|
5266
|
+
stickyLeft: "sticky left-0 z-10 bg-white group-hover:bg-gray-50 transition-colors border-r border-gray-200",
|
|
5267
|
+
stickyRight: "sticky right-0 z-10 bg-white group-hover:bg-gray-50 transition-colors border-l border-gray-200"
|
|
5268
|
+
}
|
|
5269
|
+
},
|
|
5270
|
+
actionLink: {
|
|
5271
|
+
container: "flex gap-3",
|
|
5272
|
+
base: "text-sm hover:underline",
|
|
5273
|
+
default: "text-blue-600 hover:text-blue-800",
|
|
5274
|
+
delete: "text-red-600 hover:text-red-800"
|
|
5275
|
+
},
|
|
5276
|
+
actionButton: "flex gap-2 flex-wrap"
|
|
5277
|
+
};
|
|
5278
|
+
function TableHeader(props) {
|
|
5279
|
+
const { title, tableActions } = props;
|
|
5280
|
+
const showHeader = title && title.trim() || tableActions && tableActions.length > 0;
|
|
5281
|
+
if (!showHeader) return null;
|
|
5282
|
+
return /* @__PURE__ */ jsxs("div", { className: STYLES.header.container, children: [
|
|
5283
|
+
title && title.trim() ? /* @__PURE__ */ jsx("h3", { className: STYLES.header.title, children: title }) : /* @__PURE__ */ jsx("div", {}),
|
|
5284
|
+
tableActions && tableActions.length > 0 && /* @__PURE__ */ jsx("div", { className: STYLES.header.actions, children: tableActions.map((action, idx) => /* @__PURE__ */ jsx(
|
|
5285
|
+
Button,
|
|
5286
|
+
{
|
|
5287
|
+
variant: action.variant || "secondary",
|
|
5288
|
+
href: action.href,
|
|
5289
|
+
hxGet: action.hxGet,
|
|
5290
|
+
hxPost: action.hxPost,
|
|
5291
|
+
hxDelete: action.hxDelete,
|
|
5292
|
+
hxConfirm: action.hxConfirm,
|
|
5293
|
+
children: action.label
|
|
5294
|
+
},
|
|
5295
|
+
idx
|
|
5296
|
+
)) })
|
|
5297
|
+
] });
|
|
5298
|
+
}
|
|
5299
|
+
function TableHeaderRow(props) {
|
|
5300
|
+
const { idColumn, otherColumns, hasActions } = props;
|
|
5301
|
+
return /* @__PURE__ */ jsxs("tr", { children: [
|
|
5302
|
+
idColumn && /* @__PURE__ */ jsx("th", { className: `${STYLES.table.th.base} ${STYLES.table.th.stickyLeft}`, children: idColumn.label }),
|
|
5303
|
+
otherColumns.map((col) => /* @__PURE__ */ jsx("th", { className: STYLES.table.th.base, children: col.label }, col.key)),
|
|
5304
|
+
hasActions && /* @__PURE__ */ jsx(
|
|
5305
|
+
"th",
|
|
5306
|
+
{
|
|
5307
|
+
className: `${STYLES.table.th.base} ${STYLES.table.th.stickyRight}`,
|
|
5308
|
+
children: "\u64CD\u4F5C"
|
|
5309
|
+
}
|
|
5310
|
+
)
|
|
5311
|
+
] });
|
|
5312
|
+
}
|
|
5313
|
+
function TableCell(props) {
|
|
5314
|
+
const { column, item, isSticky, stickyClass } = props;
|
|
5315
|
+
const value = item[column.key];
|
|
5316
|
+
const content = column.render ? safeRender(column.render(value, item)) : String(value || "");
|
|
5317
|
+
const className = isSticky ? `${STYLES.table.td.base} ${stickyClass || ""}` : STYLES.table.td.base;
|
|
5318
|
+
return /* @__PURE__ */ jsx("td", { className, children: content });
|
|
5319
|
+
}
|
|
5320
|
+
function ActionLink(props) {
|
|
5321
|
+
const { action, item } = props;
|
|
5322
|
+
const hrefValue = action.href(item);
|
|
5323
|
+
const isDelete = action.method === "delete";
|
|
5324
|
+
const className = `${STYLES.actionLink.base} ${isDelete ? STYLES.actionLink.delete : STYLES.actionLink.default}`;
|
|
5325
|
+
return /* @__PURE__ */ jsx(
|
|
5326
|
+
"a",
|
|
5327
|
+
{
|
|
5328
|
+
href: hrefValue,
|
|
5329
|
+
className,
|
|
5330
|
+
"hx-get": !isDelete ? hrefValue : void 0,
|
|
5331
|
+
"hx-delete": isDelete ? hrefValue : void 0,
|
|
5332
|
+
"hx-confirm": isDelete ? "\u786E\u5B9A\u5220\u9664\u5417\uFF1F" : void 0,
|
|
5333
|
+
children: action.label
|
|
5334
|
+
}
|
|
5335
|
+
);
|
|
5336
|
+
}
|
|
5337
|
+
function ActionCell(props) {
|
|
5338
|
+
const { actions, item, actionStyle } = props;
|
|
5339
|
+
if (!actions || actions.length === 0) return null;
|
|
5340
|
+
return /* @__PURE__ */ jsx("td", { className: `${STYLES.table.td.base} ${STYLES.table.td.stickyRight}`, children: actionStyle === "link" ? /* @__PURE__ */ jsx("div", { className: STYLES.actionLink.container, children: actions.map((action, idx) => /* @__PURE__ */ jsx(ActionLink, { action, item }, idx)) }) : /* @__PURE__ */ jsx("div", { className: STYLES.actionButton, children: actions.map((action, idx) => /* @__PURE__ */ jsx(
|
|
5341
|
+
ActionButton,
|
|
5342
|
+
{
|
|
5343
|
+
label: action.label,
|
|
5344
|
+
href: action.href,
|
|
5345
|
+
method: action.method,
|
|
5346
|
+
className: action.class,
|
|
5347
|
+
item
|
|
5348
|
+
},
|
|
5349
|
+
idx
|
|
5350
|
+
)) }) });
|
|
5351
|
+
}
|
|
5352
|
+
function TableRow(props) {
|
|
5353
|
+
const { item, idColumn, otherColumns, actions, actionStyle } = props;
|
|
5354
|
+
return /* @__PURE__ */ jsxs("tr", { className: STYLES.table.tr, children: [
|
|
5355
|
+
idColumn && /* @__PURE__ */ jsx(
|
|
5356
|
+
TableCell,
|
|
5357
|
+
{
|
|
5358
|
+
column: idColumn,
|
|
5359
|
+
item,
|
|
5360
|
+
isSticky: true,
|
|
5361
|
+
stickyClass: STYLES.table.td.stickyLeft
|
|
5362
|
+
}
|
|
5363
|
+
),
|
|
5364
|
+
otherColumns.map((col) => /* @__PURE__ */ jsx(TableCell, { column: col, item }, col.key)),
|
|
5365
|
+
actions && actions.length > 0 && /* @__PURE__ */ jsx(ActionCell, { actions, item, actionStyle })
|
|
5366
|
+
] });
|
|
5367
|
+
}
|
|
5250
5368
|
var Table = (props) => {
|
|
5251
5369
|
const {
|
|
5252
5370
|
items,
|
|
@@ -5259,119 +5377,28 @@ var Table = (props) => {
|
|
|
5259
5377
|
} = props;
|
|
5260
5378
|
const idColumn = columns.find((col) => col.key === "id");
|
|
5261
5379
|
const otherColumns = columns.filter((col) => col.key !== "id");
|
|
5262
|
-
const
|
|
5263
|
-
const actionsColumnMinWidth = actions && actions.length > 0 ? actions.length * 30 + 48 + (actions.length - 1) * 8 : 0;
|
|
5264
|
-
const showHeader = title && title.trim() || tableActions && tableActions.length > 0;
|
|
5265
|
-
const hasTitle = title && title.trim();
|
|
5380
|
+
const hasActions = Boolean(actions && actions.length > 0);
|
|
5266
5381
|
return /* @__PURE__ */ jsxs(Card, { shadow: true, noPadding: true, className: "overflow-hidden", children: [
|
|
5267
|
-
|
|
5268
|
-
hasTitle ? /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-gray-900", children: title }) : /* @__PURE__ */ jsx("div", {}),
|
|
5269
|
-
tableActions && tableActions.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex gap-2", children: tableActions.map((action, idx) => /* @__PURE__ */ jsx(
|
|
5270
|
-
Button,
|
|
5271
|
-
{
|
|
5272
|
-
variant: action.variant || "secondary",
|
|
5273
|
-
href: action.href,
|
|
5274
|
-
hxGet: action.hxGet,
|
|
5275
|
-
hxPost: action.hxPost,
|
|
5276
|
-
hxDelete: action.hxDelete,
|
|
5277
|
-
hxConfirm: action.hxConfirm,
|
|
5278
|
-
children: action.label
|
|
5279
|
-
},
|
|
5280
|
-
idx
|
|
5281
|
-
)) })
|
|
5282
|
-
] }),
|
|
5382
|
+
/* @__PURE__ */ jsx(TableHeader, { title, tableActions }),
|
|
5283
5383
|
items.length === 0 ? /* @__PURE__ */ jsx(EmptyState, { message: "\u6682\u65E0\u6570\u636E" }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5284
|
-
/* @__PURE__ */ jsx("div", { className:
|
|
5285
|
-
/* @__PURE__ */ jsx("thead", { className:
|
|
5286
|
-
|
|
5287
|
-
"th",
|
|
5288
|
-
{
|
|
5289
|
-
className: "px-6 py-3 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider sticky left-0 z-20 bg-gray-50 border-r border-gray-200",
|
|
5290
|
-
style: {
|
|
5291
|
-
minWidth: `${idColumnWidth}px`,
|
|
5292
|
-
maxWidth: `${idColumnWidth}px`
|
|
5293
|
-
},
|
|
5294
|
-
children: idColumn.label
|
|
5295
|
-
}
|
|
5296
|
-
),
|
|
5297
|
-
otherColumns.map((col) => /* @__PURE__ */ jsx(
|
|
5298
|
-
"th",
|
|
5299
|
-
{
|
|
5300
|
-
className: "px-6 py-3 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider",
|
|
5301
|
-
children: col.label
|
|
5302
|
-
},
|
|
5303
|
-
col.key
|
|
5304
|
-
)),
|
|
5305
|
-
actions && actions.length > 0 && /* @__PURE__ */ jsx(
|
|
5306
|
-
"th",
|
|
5307
|
-
{
|
|
5308
|
-
className: "px-6 py-3 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider sticky right-0 z-20 bg-gray-50 border-l border-gray-200 whitespace-nowrap",
|
|
5309
|
-
style: { minWidth: `${actionsColumnMinWidth}px` },
|
|
5310
|
-
children: "\u64CD\u4F5C"
|
|
5311
|
-
}
|
|
5312
|
-
)
|
|
5313
|
-
] }) }),
|
|
5314
|
-
/* @__PURE__ */ jsx("tbody", { className: "bg-white divide-y divide-gray-200", children: items.map((item, rowIndex) => /* @__PURE__ */ jsxs(
|
|
5315
|
-
"tr",
|
|
5384
|
+
/* @__PURE__ */ jsx("div", { className: STYLES.table.container, children: /* @__PURE__ */ jsxs("table", { className: STYLES.table.table, children: [
|
|
5385
|
+
/* @__PURE__ */ jsx("thead", { className: STYLES.table.thead, children: /* @__PURE__ */ jsx(
|
|
5386
|
+
TableHeaderRow,
|
|
5316
5387
|
{
|
|
5317
|
-
|
|
5318
|
-
|
|
5319
|
-
|
|
5320
|
-
|
|
5321
|
-
|
|
5322
|
-
|
|
5323
|
-
|
|
5324
|
-
|
|
5325
|
-
|
|
5326
|
-
|
|
5327
|
-
|
|
5328
|
-
|
|
5329
|
-
|
|
5330
|
-
|
|
5331
|
-
),
|
|
5332
|
-
otherColumns.map((col) => /* @__PURE__ */ jsx(
|
|
5333
|
-
"td",
|
|
5334
|
-
{
|
|
5335
|
-
className: "px-6 py-4 whitespace-nowrap text-sm text-gray-900",
|
|
5336
|
-
children: col.render ? safeRender(col.render(item[col.key], item)) : String(item[col.key] || "")
|
|
5337
|
-
},
|
|
5338
|
-
col.key
|
|
5339
|
-
)),
|
|
5340
|
-
actions && actions.length > 0 && /* @__PURE__ */ jsx(
|
|
5341
|
-
"td",
|
|
5342
|
-
{
|
|
5343
|
-
className: "px-6 py-4 whitespace-nowrap text-sm sticky right-0 z-10 bg-white group-hover:bg-gray-50 transition-colors border-l border-gray-200",
|
|
5344
|
-
style: { minWidth: `${actionsColumnMinWidth}px` },
|
|
5345
|
-
children: actionStyle === "link" ? /* @__PURE__ */ jsx("div", { className: "flex gap-3", children: actions.map((action, idx) => {
|
|
5346
|
-
const hrefValue = typeof action.href === "function" ? action.href(item) : action.href;
|
|
5347
|
-
const isDelete = action.method === "delete";
|
|
5348
|
-
action.dialog || hrefValue.includes("dialog=true");
|
|
5349
|
-
return /* @__PURE__ */ jsx(
|
|
5350
|
-
"a",
|
|
5351
|
-
{
|
|
5352
|
-
href: hrefValue,
|
|
5353
|
-
className: `text-sm ${isDelete ? "text-red-600 hover:text-red-800" : "text-blue-600 hover:text-blue-800"} hover:underline`,
|
|
5354
|
-
"hx-get": !isDelete ? hrefValue : void 0,
|
|
5355
|
-
"hx-delete": isDelete ? hrefValue : void 0,
|
|
5356
|
-
"hx-confirm": isDelete ? "\u786E\u5B9A\u5220\u9664\u5417\uFF1F" : void 0,
|
|
5357
|
-
children: action.label
|
|
5358
|
-
},
|
|
5359
|
-
idx
|
|
5360
|
-
);
|
|
5361
|
-
}) }) : /* @__PURE__ */ jsx("div", { className: "flex gap-2 flex-wrap", children: actions.map((action, idx) => /* @__PURE__ */ jsx(
|
|
5362
|
-
ActionButton,
|
|
5363
|
-
{
|
|
5364
|
-
label: action.label,
|
|
5365
|
-
href: action.href,
|
|
5366
|
-
method: action.method,
|
|
5367
|
-
className: action.class,
|
|
5368
|
-
item
|
|
5369
|
-
},
|
|
5370
|
-
idx
|
|
5371
|
-
)) })
|
|
5372
|
-
}
|
|
5373
|
-
)
|
|
5374
|
-
]
|
|
5388
|
+
columns,
|
|
5389
|
+
idColumn,
|
|
5390
|
+
otherColumns,
|
|
5391
|
+
hasActions
|
|
5392
|
+
}
|
|
5393
|
+
) }),
|
|
5394
|
+
/* @__PURE__ */ jsx("tbody", { className: STYLES.table.tbody, children: items.map((item) => /* @__PURE__ */ jsx(
|
|
5395
|
+
TableRow,
|
|
5396
|
+
{
|
|
5397
|
+
item,
|
|
5398
|
+
idColumn,
|
|
5399
|
+
otherColumns,
|
|
5400
|
+
actions,
|
|
5401
|
+
actionStyle
|
|
5375
5402
|
},
|
|
5376
5403
|
item.id
|
|
5377
5404
|
)) })
|
|
@@ -5503,6 +5530,13 @@ var ListPageModule = class extends PageModule {
|
|
|
5503
5530
|
}
|
|
5504
5531
|
return false;
|
|
5505
5532
|
}
|
|
5533
|
+
/**
|
|
5534
|
+
* 获取字段标签(可选)
|
|
5535
|
+
* 子类可以重写此方法来自定义字段的中文标签
|
|
5536
|
+
*/
|
|
5537
|
+
getFieldLabel(field) {
|
|
5538
|
+
return field;
|
|
5539
|
+
}
|
|
5506
5540
|
/**
|
|
5507
5541
|
* 自定义列渲染(可选)
|
|
5508
5542
|
* 子类可以重写此方法来自定义列的渲染逻辑
|
|
@@ -5582,7 +5616,7 @@ var ListPageModule = class extends PageModule {
|
|
|
5582
5616
|
const tableTitle = this.getTableTitle ? this.getTableTitle() : pageTitle;
|
|
5583
5617
|
const columns = result.items.length > 0 ? Object.keys(result.items[0]).map((key) => ({
|
|
5584
5618
|
key,
|
|
5585
|
-
label: key,
|
|
5619
|
+
label: this.getFieldLabel ? this.getFieldLabel(key) : key,
|
|
5586
5620
|
render: this.renderColumn ? (value, item) => this.renderColumn(key, value, item) : void 0
|
|
5587
5621
|
})) : [];
|
|
5588
5622
|
const actions = this.getActions && result.items.length > 0 ? this.getActions(result.items[0]) : [];
|
|
@@ -6585,6 +6619,9 @@ var HtmxAdminPlugin = class {
|
|
|
6585
6619
|
* 检查并注册模块
|
|
6586
6620
|
*/
|
|
6587
6621
|
checkAndRegisterModules(modules) {
|
|
6622
|
+
modules = modules.filter(
|
|
6623
|
+
(module) => module.clazz instanceof PageModule || module.clazz.prototype instanceof PageModule
|
|
6624
|
+
);
|
|
6588
6625
|
for (const module of modules) {
|
|
6589
6626
|
const options = module.options;
|
|
6590
6627
|
const moduleClass = module.clazz;
|
|
@@ -6663,31 +6700,25 @@ var HtmxAdminPlugin = class {
|
|
|
6663
6700
|
description: moduleInfo.options.description ?? ""
|
|
6664
6701
|
}
|
|
6665
6702
|
});
|
|
6666
|
-
|
|
6667
|
-
|
|
6668
|
-
|
|
6669
|
-
|
|
6670
|
-
|
|
6671
|
-
|
|
6672
|
-
|
|
6673
|
-
|
|
6674
|
-
|
|
6675
|
-
|
|
6676
|
-
|
|
6677
|
-
|
|
6678
|
-
|
|
6679
|
-
|
|
6680
|
-
|
|
6681
|
-
|
|
6682
|
-
|
|
6683
|
-
|
|
6684
|
-
this.hono.
|
|
6685
|
-
return routeHandler.handle(ctx);
|
|
6686
|
-
});
|
|
6687
|
-
} else if (type === "custom") {
|
|
6688
|
-
this.hono.get(basePath, async (ctx) => {
|
|
6689
|
-
return routeHandler.handle(ctx);
|
|
6690
|
-
});
|
|
6703
|
+
const routeConfig = {
|
|
6704
|
+
list: [{ method: "get", path: `${basePath}/list` }],
|
|
6705
|
+
detail: [{ method: "get", path: `${basePath}/detail/:id` }],
|
|
6706
|
+
form: [
|
|
6707
|
+
{ method: "get", path: `${basePath}/new` },
|
|
6708
|
+
{ method: "get", path: `${basePath}/edit/:id` },
|
|
6709
|
+
{ method: "post", path: basePath },
|
|
6710
|
+
{ method: "put", path: `${basePath}/:id` },
|
|
6711
|
+
{ method: "delete", path: `${basePath}/:id` }
|
|
6712
|
+
],
|
|
6713
|
+
custom: [{ method: "get", path: basePath }]
|
|
6714
|
+
};
|
|
6715
|
+
const routes = routeConfig[type];
|
|
6716
|
+
for (const route of routes) {
|
|
6717
|
+
logger_default.info(
|
|
6718
|
+
`[HtmxAdminPlugin] Registering ${type} route: ${route.method.toUpperCase()} ${route.path}`
|
|
6719
|
+
);
|
|
6720
|
+
const handler = async (ctx) => routeHandler.handle(ctx);
|
|
6721
|
+
this.hono[route.method](route.path, handler);
|
|
6691
6722
|
}
|
|
6692
6723
|
}
|
|
6693
6724
|
}
|