imean-service-engine-htmx-plugin 2.6.0 → 2.8.0
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 +397 -27
- package/dist/index.d.ts +397 -27
- package/dist/index.js +878 -625
- package/dist/index.mjs +866 -626
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4,6 +4,7 @@ var jsxRuntime = require('hono/jsx/jsx-runtime');
|
|
|
4
4
|
var fs = require('fs');
|
|
5
5
|
var imeanServiceEngine = require('imean-service-engine');
|
|
6
6
|
var path = require('path');
|
|
7
|
+
var zod = require('zod');
|
|
7
8
|
var cookie = require('hono/cookie');
|
|
8
9
|
var html = require('hono/html');
|
|
9
10
|
|
|
@@ -423,6 +424,212 @@ var PageModel = class {
|
|
|
423
424
|
}
|
|
424
425
|
};
|
|
425
426
|
|
|
427
|
+
// src/utils/schema-utils.ts
|
|
428
|
+
function parseSchemaToFields(schema) {
|
|
429
|
+
const def = schema._def;
|
|
430
|
+
const shape = typeof def.shape === "function" ? def.shape() : def.shape;
|
|
431
|
+
if (!shape || typeof shape !== "object") {
|
|
432
|
+
return [];
|
|
433
|
+
}
|
|
434
|
+
const fields = [];
|
|
435
|
+
for (const [fieldName, fieldSchema] of Object.entries(shape)) {
|
|
436
|
+
if (["id", "createdAt", "updatedAt"].includes(fieldName)) {
|
|
437
|
+
continue;
|
|
438
|
+
}
|
|
439
|
+
const field = parseFieldSchema(fieldName, fieldSchema);
|
|
440
|
+
if (field) {
|
|
441
|
+
fields.push(field);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
return fields;
|
|
445
|
+
}
|
|
446
|
+
function parseFieldSchema(fieldName, fieldSchema) {
|
|
447
|
+
if (!fieldSchema || !fieldSchema._def) {
|
|
448
|
+
return null;
|
|
449
|
+
}
|
|
450
|
+
const label = getFieldDescription(fieldSchema) || fieldName;
|
|
451
|
+
const { type, required, options, innerSchema, step } = analyzeFieldType(fieldSchema);
|
|
452
|
+
return {
|
|
453
|
+
name: fieldName,
|
|
454
|
+
label,
|
|
455
|
+
type,
|
|
456
|
+
required,
|
|
457
|
+
options,
|
|
458
|
+
step,
|
|
459
|
+
schema: innerSchema || fieldSchema
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
function getFieldDescription(schema) {
|
|
463
|
+
if (schema?.description) {
|
|
464
|
+
return schema.description;
|
|
465
|
+
}
|
|
466
|
+
const schemaDef = schema._def;
|
|
467
|
+
if (schemaDef?.description) {
|
|
468
|
+
return schemaDef.description;
|
|
469
|
+
}
|
|
470
|
+
if (schemaDef?.innerType) {
|
|
471
|
+
return getFieldDescription(schemaDef.innerType);
|
|
472
|
+
}
|
|
473
|
+
return void 0;
|
|
474
|
+
}
|
|
475
|
+
function analyzeFieldType(schema) {
|
|
476
|
+
const def = schema._def;
|
|
477
|
+
const typeName = def?.type || def?.typeName;
|
|
478
|
+
if (typeName === "optional" || typeName === "ZodOptional") {
|
|
479
|
+
const inner = analyzeFieldType(def.innerType);
|
|
480
|
+
return {
|
|
481
|
+
...inner,
|
|
482
|
+
required: false,
|
|
483
|
+
innerSchema: def.innerType
|
|
484
|
+
};
|
|
485
|
+
}
|
|
486
|
+
if (typeName === "nullable" || typeName === "ZodNullable") {
|
|
487
|
+
const inner = analyzeFieldType(def.innerType);
|
|
488
|
+
return {
|
|
489
|
+
...inner,
|
|
490
|
+
innerSchema: def.innerType
|
|
491
|
+
};
|
|
492
|
+
}
|
|
493
|
+
if (typeName === "enum" || typeName === "ZodEnum") {
|
|
494
|
+
const options = extractEnumValues(def);
|
|
495
|
+
return {
|
|
496
|
+
type: "select",
|
|
497
|
+
required: true,
|
|
498
|
+
options,
|
|
499
|
+
innerSchema: schema
|
|
500
|
+
};
|
|
501
|
+
}
|
|
502
|
+
if (typeName === "nativeEnum" || typeName === "ZodNativeEnum") {
|
|
503
|
+
const options = extractNativeEnumValues(def);
|
|
504
|
+
return {
|
|
505
|
+
type: "select",
|
|
506
|
+
required: true,
|
|
507
|
+
options,
|
|
508
|
+
innerSchema: schema
|
|
509
|
+
};
|
|
510
|
+
}
|
|
511
|
+
if (typeName === "string" || typeName === "ZodString") {
|
|
512
|
+
let fieldType = "text";
|
|
513
|
+
if (def?.checks) {
|
|
514
|
+
const hasEmailCheck = def.checks.some(
|
|
515
|
+
(check) => check.format === "email" || check.constructor?.name === "ZodEmail" || check._zod?.def?.format === "email"
|
|
516
|
+
);
|
|
517
|
+
if (hasEmailCheck) {
|
|
518
|
+
fieldType = "email";
|
|
519
|
+
} else {
|
|
520
|
+
const maxLengthCheck = def.checks.find(
|
|
521
|
+
(check) => check.constructor?.name === "$ZodCheckMaxLength" || check._zod?.def?.check === "max_length" || check._zod?.def?.maximum !== void 0
|
|
522
|
+
);
|
|
523
|
+
if (maxLengthCheck) {
|
|
524
|
+
const maxLength = maxLengthCheck._zod?.def?.maximum ?? maxLengthCheck.value ?? maxLengthCheck.maximum;
|
|
525
|
+
if (maxLength !== void 0 && maxLength > 50) {
|
|
526
|
+
fieldType = "textarea";
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
return {
|
|
532
|
+
type: fieldType,
|
|
533
|
+
required: true,
|
|
534
|
+
innerSchema: schema
|
|
535
|
+
};
|
|
536
|
+
}
|
|
537
|
+
if (typeName === "number" || typeName === "ZodNumber") {
|
|
538
|
+
let step = void 0;
|
|
539
|
+
if (def?.checks) {
|
|
540
|
+
const hasIntCheck = def.checks.some(
|
|
541
|
+
(check) => check.isInt === true || check.format === "safeint" || check.def?.format === "safeint" || check.kind === "int" || check.constructor?.name === "ZodInt" || check._zod?.def?.check === "int" || check._zod?.def?.kind === "int"
|
|
542
|
+
);
|
|
543
|
+
if (!hasIntCheck) {
|
|
544
|
+
step = "any";
|
|
545
|
+
}
|
|
546
|
+
} else {
|
|
547
|
+
step = "any";
|
|
548
|
+
}
|
|
549
|
+
return {
|
|
550
|
+
type: "number",
|
|
551
|
+
required: true,
|
|
552
|
+
innerSchema: schema,
|
|
553
|
+
step
|
|
554
|
+
};
|
|
555
|
+
}
|
|
556
|
+
if (typeName === "date" || typeName === "ZodDate") {
|
|
557
|
+
return {
|
|
558
|
+
type: "date",
|
|
559
|
+
required: true,
|
|
560
|
+
innerSchema: schema
|
|
561
|
+
};
|
|
562
|
+
}
|
|
563
|
+
if (typeName === "boolean" || typeName === "ZodBoolean") {
|
|
564
|
+
return {
|
|
565
|
+
type: "checkbox",
|
|
566
|
+
required: true,
|
|
567
|
+
innerSchema: schema
|
|
568
|
+
};
|
|
569
|
+
}
|
|
570
|
+
return {
|
|
571
|
+
type: "text",
|
|
572
|
+
required: true,
|
|
573
|
+
innerSchema: schema
|
|
574
|
+
};
|
|
575
|
+
}
|
|
576
|
+
function extractEnumValues(def) {
|
|
577
|
+
let values;
|
|
578
|
+
if (def?.values && Array.isArray(def.values)) {
|
|
579
|
+
values = def.values;
|
|
580
|
+
} else if (def?.entries && typeof def.entries === "object") {
|
|
581
|
+
values = Object.keys(def.entries);
|
|
582
|
+
}
|
|
583
|
+
if (values && values.length > 0) {
|
|
584
|
+
return values.map((value) => ({
|
|
585
|
+
value,
|
|
586
|
+
label: String(value)
|
|
587
|
+
}));
|
|
588
|
+
}
|
|
589
|
+
return void 0;
|
|
590
|
+
}
|
|
591
|
+
function extractNativeEnumValues(def) {
|
|
592
|
+
const enumValues = def.values || def._def?.values || {};
|
|
593
|
+
if (enumValues && typeof enumValues === "object") {
|
|
594
|
+
return Object.entries(enumValues).filter(
|
|
595
|
+
([_, value]) => typeof value === "string" || typeof value === "number"
|
|
596
|
+
).map(([key, value]) => ({
|
|
597
|
+
value,
|
|
598
|
+
label: key
|
|
599
|
+
}));
|
|
600
|
+
}
|
|
601
|
+
return void 0;
|
|
602
|
+
}
|
|
603
|
+
function filterFieldsByNames(fields, fieldNames) {
|
|
604
|
+
if (fieldNames === void 0) {
|
|
605
|
+
return fields;
|
|
606
|
+
}
|
|
607
|
+
if (fieldNames.length === 0) {
|
|
608
|
+
return [];
|
|
609
|
+
}
|
|
610
|
+
return fields.filter((field) => fieldNames.includes(field.name));
|
|
611
|
+
}
|
|
612
|
+
function modelFieldsToFormFields(fields) {
|
|
613
|
+
return fields.map((field) => ({
|
|
614
|
+
name: field.name,
|
|
615
|
+
type: field.type,
|
|
616
|
+
label: field.label,
|
|
617
|
+
required: field.required,
|
|
618
|
+
options: field.options,
|
|
619
|
+
step: field.step
|
|
620
|
+
}));
|
|
621
|
+
}
|
|
622
|
+
function getFieldNamesFromFields(fields) {
|
|
623
|
+
return fields.map((field) => field.name);
|
|
624
|
+
}
|
|
625
|
+
function getFieldByName(fields, fieldName) {
|
|
626
|
+
return fields.find((field) => field.name === fieldName);
|
|
627
|
+
}
|
|
628
|
+
function getFieldLabelFromFields(fields, fieldName) {
|
|
629
|
+
const field = getFieldByName(fields, fieldName);
|
|
630
|
+
return field?.label || fieldName;
|
|
631
|
+
}
|
|
632
|
+
|
|
426
633
|
// src/features/base-feature.ts
|
|
427
634
|
var BaseFeature = class {
|
|
428
635
|
/** Feature 名称 */
|
|
@@ -436,15 +643,19 @@ var BaseFeature = class {
|
|
|
436
643
|
/** 是否允许点击遮罩区域关闭弹窗(默认 true,设置为 false 时只能通过关闭按钮关闭) */
|
|
437
644
|
closeOnBackdropClick;
|
|
438
645
|
/** Schema(可选,由子类在构造函数中设置) */
|
|
439
|
-
schema;
|
|
646
|
+
schema = zod.z.object({});
|
|
440
647
|
/** 解析后的字段列表(可选,由子类在构造函数中设置) */
|
|
441
|
-
fields;
|
|
648
|
+
fields = [];
|
|
442
649
|
constructor(options) {
|
|
443
650
|
this.name = options.name;
|
|
444
651
|
this.type = options.type;
|
|
445
652
|
this.permission = options.permission;
|
|
446
653
|
this.dialogSize = options.dialogSize;
|
|
447
654
|
this.closeOnBackdropClick = options.closeOnBackdropClick;
|
|
655
|
+
this.schema = options.schema || zod.z.object({});
|
|
656
|
+
if (this.schema) {
|
|
657
|
+
this.fields = parseSchemaToFields(this.schema);
|
|
658
|
+
}
|
|
448
659
|
}
|
|
449
660
|
/**
|
|
450
661
|
* 获取动态标题(默认实现:返回 PageMetadata 的 title)
|
|
@@ -476,26 +687,6 @@ var BaseFeature = class {
|
|
|
476
687
|
return await this.render?.(context) ?? null;
|
|
477
688
|
}
|
|
478
689
|
};
|
|
479
|
-
function getFieldValue(field, initialData) {
|
|
480
|
-
if (initialData && Object.prototype.hasOwnProperty.call(initialData, field.name)) {
|
|
481
|
-
const value = initialData[field.name];
|
|
482
|
-
if (value === null || value === void 0) {
|
|
483
|
-
return "";
|
|
484
|
-
}
|
|
485
|
-
if (typeof value === "object") {
|
|
486
|
-
if (value instanceof Date) {
|
|
487
|
-
return value.toISOString();
|
|
488
|
-
}
|
|
489
|
-
try {
|
|
490
|
-
return JSON.stringify(value);
|
|
491
|
-
} catch (e) {
|
|
492
|
-
return "";
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
return String(value);
|
|
496
|
-
}
|
|
497
|
-
return "";
|
|
498
|
-
}
|
|
499
690
|
function isJsonString(value) {
|
|
500
691
|
if (!value || typeof value !== "string") {
|
|
501
692
|
return false;
|
|
@@ -515,7 +706,9 @@ function formatJsonString(value) {
|
|
|
515
706
|
}
|
|
516
707
|
}
|
|
517
708
|
function renderFormField(field, initialData, formFieldRenderers) {
|
|
518
|
-
const value =
|
|
709
|
+
const value = initialData?.[field.name];
|
|
710
|
+
field.label || field.name;
|
|
711
|
+
const fieldSchema = field.schema;
|
|
519
712
|
const customRenderer = formFieldRenderers?.[field.name];
|
|
520
713
|
if (customRenderer) {
|
|
521
714
|
let parsedValue = null;
|
|
@@ -549,10 +742,10 @@ function renderFormField(field, initialData, formFieldRenderers) {
|
|
|
549
742
|
/* @__PURE__ */ jsxRuntime.jsx("div", { children: customRenderer({
|
|
550
743
|
field,
|
|
551
744
|
value: parsedValue,
|
|
552
|
-
item: initialData,
|
|
553
|
-
name: field.name
|
|
554
|
-
|
|
555
|
-
|
|
745
|
+
item: initialData || {},
|
|
746
|
+
name: field.name,
|
|
747
|
+
label: field.label
|
|
748
|
+
}) })
|
|
556
749
|
]
|
|
557
750
|
},
|
|
558
751
|
field.name
|
|
@@ -560,41 +753,38 @@ function renderFormField(field, initialData, formFieldRenderers) {
|
|
|
560
753
|
}
|
|
561
754
|
if (field.type === "checkbox") {
|
|
562
755
|
const isChecked = value === "true" || value === "1" || value === "on" || String(value).toLowerCase() === "true";
|
|
563
|
-
return /* @__PURE__ */ jsxRuntime.
|
|
756
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
564
757
|
"div",
|
|
565
758
|
{
|
|
566
759
|
className: "space-y-2",
|
|
567
760
|
"data-testid": `field-${field.name}`,
|
|
568
|
-
children:
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
),
|
|
596
|
-
field.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-500 ml-8", children: field.description })
|
|
597
|
-
]
|
|
761
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
762
|
+
"label",
|
|
763
|
+
{
|
|
764
|
+
htmlFor: field.name,
|
|
765
|
+
className: "flex items-center gap-3 cursor-pointer group py-2.5 px-3 rounded-lg hover:bg-gray-50 transition-colors border border-transparent hover:border-gray-200",
|
|
766
|
+
"data-testid": `label-${field.name}`,
|
|
767
|
+
children: [
|
|
768
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
769
|
+
"input",
|
|
770
|
+
{
|
|
771
|
+
type: "checkbox",
|
|
772
|
+
id: field.name,
|
|
773
|
+
name: field.name,
|
|
774
|
+
value: "true",
|
|
775
|
+
checked: isChecked,
|
|
776
|
+
required: field.required,
|
|
777
|
+
className: "w-5 h-5 text-blue-600 border-gray-300 rounded focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 cursor-pointer transition-all flex-shrink-0",
|
|
778
|
+
"data-testid": `input-${field.name}`
|
|
779
|
+
}
|
|
780
|
+
),
|
|
781
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm font-semibold text-gray-700 select-none flex-1", children: [
|
|
782
|
+
field.label,
|
|
783
|
+
field.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-red-500 ml-1", children: "*" })
|
|
784
|
+
] })
|
|
785
|
+
]
|
|
786
|
+
}
|
|
787
|
+
)
|
|
598
788
|
},
|
|
599
789
|
field.name
|
|
600
790
|
);
|
|
@@ -624,7 +814,7 @@ function renderFormField(field, initialData, formFieldRenderers) {
|
|
|
624
814
|
id: field.name,
|
|
625
815
|
name: field.name,
|
|
626
816
|
required: field.required,
|
|
627
|
-
placeholder:
|
|
817
|
+
placeholder: fieldSchema.description || (isJsonString(value) ? "JSON \u683C\u5F0F\u6570\u636E" : ""),
|
|
628
818
|
rows: isJsonString(value) ? Math.max(10, value.split("\n").length) : Math.max(5, Math.ceil(value.length / 100)),
|
|
629
819
|
className: "w-full px-4 py-2.5 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all duration-200 resize-y font-mono text-sm",
|
|
630
820
|
"data-testid": `input-${field.name}`,
|
|
@@ -664,7 +854,7 @@ function renderFormField(field, initialData, formFieldRenderers) {
|
|
|
664
854
|
id: field.name,
|
|
665
855
|
name: field.name,
|
|
666
856
|
required: field.required,
|
|
667
|
-
placeholder:
|
|
857
|
+
placeholder: fieldSchema.description || "",
|
|
668
858
|
step: field.type === "number" ? field.step ?? void 0 : void 0,
|
|
669
859
|
className: "w-full px-4 py-2.5 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all duration-200",
|
|
670
860
|
value,
|
|
@@ -672,7 +862,7 @@ function renderFormField(field, initialData, formFieldRenderers) {
|
|
|
672
862
|
},
|
|
673
863
|
`${field.name}-${value}`
|
|
674
864
|
),
|
|
675
|
-
|
|
865
|
+
fieldSchema.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-500 mt-1", children: fieldSchema.description })
|
|
676
866
|
]
|
|
677
867
|
},
|
|
678
868
|
field.name
|
|
@@ -680,7 +870,6 @@ function renderFormField(field, initialData, formFieldRenderers) {
|
|
|
680
870
|
}
|
|
681
871
|
function FormPage(props) {
|
|
682
872
|
const {
|
|
683
|
-
fields,
|
|
684
873
|
groups,
|
|
685
874
|
submitUrl,
|
|
686
875
|
method = "post",
|
|
@@ -690,12 +879,6 @@ function FormPage(props) {
|
|
|
690
879
|
formFieldRenderers
|
|
691
880
|
} = props;
|
|
692
881
|
const finalFormId = formId || `form-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
693
|
-
if (process.env.NODE_ENV === "development" && initialData) {
|
|
694
|
-
const fieldNames = fields ? fields.map((f) => f.name).join(", ") : groups ? groups.map((g) => g.fields.map((f) => f.name).join(", ")).join(" | ") : "";
|
|
695
|
-
console.log(
|
|
696
|
-
`[FormPage] initialData: ${JSON.stringify(initialData)}, fields: ${fieldNames}`
|
|
697
|
-
);
|
|
698
|
-
}
|
|
699
882
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
700
883
|
"div",
|
|
701
884
|
{
|
|
@@ -743,7 +926,7 @@ function FormPage(props) {
|
|
|
743
926
|
]
|
|
744
927
|
}
|
|
745
928
|
),
|
|
746
|
-
groups && groups.length >
|
|
929
|
+
groups && groups.length > 1 ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
747
930
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
748
931
|
"div",
|
|
749
932
|
{
|
|
@@ -795,26 +978,25 @@ function FormPage(props) {
|
|
|
795
978
|
)) }) })
|
|
796
979
|
}
|
|
797
980
|
)
|
|
798
|
-
] }) : (
|
|
799
|
-
/*
|
|
981
|
+
] }) : groups && groups.length === 1 ? (
|
|
982
|
+
/* 平铺模式 - 单个分组时不显示 Tab */
|
|
800
983
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
801
984
|
"form",
|
|
802
985
|
{
|
|
803
986
|
id: finalFormId,
|
|
804
987
|
method: method === "put" ? "post" : method,
|
|
805
988
|
action: submitUrl,
|
|
806
|
-
"hx-
|
|
807
|
-
"hx-trigger": "click from:#form-submit-button",
|
|
808
|
-
...method === "put" ? { "hx-put": submitUrl } : {},
|
|
989
|
+
...method === "put" ? { "hx-put": submitUrl } : { "hx-post": submitUrl },
|
|
809
990
|
"hx-indicator": "#form-loading-indicator",
|
|
991
|
+
"hx-sync": "this:abort",
|
|
810
992
|
className: "space-y-6",
|
|
811
993
|
"data-testid": "form",
|
|
812
|
-
children:
|
|
994
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-white rounded-lg border border-gray-200 shadow-sm", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-6 space-y-6", children: groups[0].fields.map(
|
|
813
995
|
(field) => renderFormField(field, initialData, formFieldRenderers)
|
|
814
996
|
) }) })
|
|
815
997
|
}
|
|
816
998
|
)
|
|
817
|
-
)
|
|
999
|
+
) : null
|
|
818
1000
|
]
|
|
819
1001
|
}
|
|
820
1002
|
);
|
|
@@ -1000,180 +1182,52 @@ function compressArrays(obj, arrayIndicesMap) {
|
|
|
1000
1182
|
}
|
|
1001
1183
|
|
|
1002
1184
|
// src/utils/form-data-processor.ts
|
|
1003
|
-
function
|
|
1004
|
-
return
|
|
1005
|
-
}
|
|
1006
|
-
function preprocessFormData(data, zodSchema) {
|
|
1007
|
-
if (!zodSchema) {
|
|
1008
|
-
return data;
|
|
1009
|
-
}
|
|
1010
|
-
const processed = { ...data };
|
|
1011
|
-
const def = zodSchema._zod?.def || zodSchema._def;
|
|
1012
|
-
const shape = typeof def.shape === "function" ? def.shape() : def.shape;
|
|
1013
|
-
if (!shape || typeof shape !== "object") {
|
|
1014
|
-
return processed;
|
|
1015
|
-
}
|
|
1016
|
-
for (const [fieldName, fieldSchema] of Object.entries(shape)) {
|
|
1017
|
-
const value = processed[fieldName];
|
|
1018
|
-
if (value === void 0) {
|
|
1019
|
-
continue;
|
|
1020
|
-
}
|
|
1021
|
-
if (value === null) {
|
|
1022
|
-
processed[fieldName] = void 0;
|
|
1023
|
-
continue;
|
|
1024
|
-
}
|
|
1025
|
-
if (value === "") {
|
|
1026
|
-
processed[fieldName] = void 0;
|
|
1027
|
-
continue;
|
|
1028
|
-
}
|
|
1029
|
-
const fieldDef = fieldSchema._zod?.def || fieldSchema._def;
|
|
1030
|
-
let typeName = fieldDef?.type;
|
|
1031
|
-
let actualSchema = fieldSchema;
|
|
1032
|
-
if (typeName === "optional") {
|
|
1033
|
-
const innerType = fieldDef?.innerType;
|
|
1034
|
-
if (innerType) {
|
|
1035
|
-
actualSchema = innerType;
|
|
1036
|
-
const innerDef = innerType._zod?.def || innerType._def;
|
|
1037
|
-
typeName = innerDef?.type;
|
|
1038
|
-
}
|
|
1039
|
-
}
|
|
1040
|
-
if (typeName === "number" || typeName === "int") {
|
|
1041
|
-
if (typeof value === "string") {
|
|
1042
|
-
const trimmed = value.trim();
|
|
1043
|
-
if (trimmed !== "") {
|
|
1044
|
-
const numValue = Number(trimmed);
|
|
1045
|
-
if (!isNaN(numValue)) {
|
|
1046
|
-
processed[fieldName] = numValue;
|
|
1047
|
-
}
|
|
1048
|
-
}
|
|
1049
|
-
} else if (typeof value === "number") {
|
|
1050
|
-
processed[fieldName] = value;
|
|
1051
|
-
}
|
|
1052
|
-
}
|
|
1053
|
-
if (typeName === "boolean") {
|
|
1054
|
-
if (typeof value === "string") {
|
|
1055
|
-
const trimmed = value.trim().toLowerCase();
|
|
1056
|
-
if (trimmed === "true" || trimmed === "1" || trimmed === "on") {
|
|
1057
|
-
processed[fieldName] = true;
|
|
1058
|
-
} else if (trimmed === "false" || trimmed === "0" || trimmed === "off" || trimmed === "") {
|
|
1059
|
-
processed[fieldName] = false;
|
|
1060
|
-
}
|
|
1061
|
-
} else if (typeof value === "boolean") {
|
|
1062
|
-
processed[fieldName] = value;
|
|
1063
|
-
}
|
|
1064
|
-
}
|
|
1065
|
-
if (typeName === "array") {
|
|
1066
|
-
if (Array.isArray(value)) {
|
|
1067
|
-
const arraySchema = actualSchema;
|
|
1068
|
-
const arrayDef = arraySchema._zod?.def || arraySchema._def;
|
|
1069
|
-
let elementType = arrayDef?.element;
|
|
1070
|
-
if (!elementType) {
|
|
1071
|
-
processed[fieldName] = value;
|
|
1072
|
-
} else {
|
|
1073
|
-
const elementDef = elementType._zod?.def || elementType._def;
|
|
1074
|
-
let elementTypeName = elementDef?.type;
|
|
1075
|
-
if (elementTypeName === "optional") {
|
|
1076
|
-
const innerElementType = elementDef?.innerType;
|
|
1077
|
-
if (innerElementType) {
|
|
1078
|
-
elementType = innerElementType;
|
|
1079
|
-
const innerElementDef = innerElementType._zod?.def || innerElementType._def;
|
|
1080
|
-
elementTypeName = innerElementDef?.type;
|
|
1081
|
-
}
|
|
1082
|
-
}
|
|
1083
|
-
processed[fieldName] = value.map((item) => {
|
|
1084
|
-
if (typeof item === "object" && item !== null && !Array.isArray(item)) {
|
|
1085
|
-
if (elementTypeName === "object") {
|
|
1086
|
-
const processedItem = preprocessFormData(
|
|
1087
|
-
item,
|
|
1088
|
-
elementType
|
|
1089
|
-
);
|
|
1090
|
-
return { ...item, ...processedItem };
|
|
1091
|
-
}
|
|
1092
|
-
return item;
|
|
1093
|
-
}
|
|
1094
|
-
if (typeof item === "string") {
|
|
1095
|
-
return convertValueByType(item, elementType);
|
|
1096
|
-
}
|
|
1097
|
-
if (Array.isArray(item)) {
|
|
1098
|
-
const elementDef2 = elementType._zod?.def || elementType._def;
|
|
1099
|
-
const nestedInnerType = elementDef2?.element;
|
|
1100
|
-
if (nestedInnerType) {
|
|
1101
|
-
return item.map((subItem) => {
|
|
1102
|
-
if (typeof subItem === "string") {
|
|
1103
|
-
return convertValueByType(subItem, nestedInnerType);
|
|
1104
|
-
}
|
|
1105
|
-
if (typeof subItem === "object" && subItem !== null) {
|
|
1106
|
-
const subItemDef = nestedInnerType._zod?.def || nestedInnerType._def;
|
|
1107
|
-
if (subItemDef?.type === "object") {
|
|
1108
|
-
return preprocessFormData(
|
|
1109
|
-
subItem,
|
|
1110
|
-
nestedInnerType
|
|
1111
|
-
);
|
|
1112
|
-
}
|
|
1113
|
-
}
|
|
1114
|
-
return subItem;
|
|
1115
|
-
});
|
|
1116
|
-
}
|
|
1117
|
-
return item;
|
|
1118
|
-
}
|
|
1119
|
-
return item;
|
|
1120
|
-
});
|
|
1121
|
-
}
|
|
1122
|
-
} else if (typeof value === "string") {
|
|
1123
|
-
const trimmed = value.trim();
|
|
1124
|
-
if (trimmed.startsWith("[") && trimmed.endsWith("]")) {
|
|
1125
|
-
try {
|
|
1126
|
-
const parsed = JSON.parse(trimmed);
|
|
1127
|
-
processed[fieldName] = parsed;
|
|
1128
|
-
} catch (e) {
|
|
1129
|
-
}
|
|
1130
|
-
} else {
|
|
1131
|
-
const parts = trimmed.split(",").map((p) => p.trim()).filter((p) => p.length > 0);
|
|
1132
|
-
processed[fieldName] = parts;
|
|
1133
|
-
}
|
|
1134
|
-
}
|
|
1135
|
-
}
|
|
1136
|
-
if (typeName === "object") {
|
|
1137
|
-
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
1138
|
-
const objectSchema = actualSchema;
|
|
1139
|
-
processed[fieldName] = preprocessFormData(value, objectSchema);
|
|
1140
|
-
} else if (typeof value === "string" && value.trim() !== "") {
|
|
1141
|
-
try {
|
|
1142
|
-
const trimmed = value.trim();
|
|
1143
|
-
if (trimmed.startsWith("{") && trimmed.endsWith("}")) {
|
|
1144
|
-
const parsed = JSON.parse(trimmed);
|
|
1145
|
-
processed[fieldName] = parsed;
|
|
1146
|
-
}
|
|
1147
|
-
} catch (e) {
|
|
1148
|
-
}
|
|
1149
|
-
}
|
|
1150
|
-
}
|
|
1151
|
-
if (typeName === "any" || typeName === "unknown") {
|
|
1152
|
-
if (typeof value === "string" && value.trim() !== "") {
|
|
1153
|
-
try {
|
|
1154
|
-
const trimmed = value.trim();
|
|
1155
|
-
if (trimmed.startsWith("{") && trimmed.endsWith("}") || trimmed.startsWith("[") && trimmed.endsWith("]")) {
|
|
1156
|
-
const parsed = JSON.parse(trimmed);
|
|
1157
|
-
processed[fieldName] = parsed;
|
|
1158
|
-
}
|
|
1159
|
-
} catch (e) {
|
|
1160
|
-
}
|
|
1161
|
-
}
|
|
1162
|
-
}
|
|
1163
|
-
}
|
|
1164
|
-
return processed;
|
|
1185
|
+
function getZodDef(schema) {
|
|
1186
|
+
return schema._zod?.def || schema._def;
|
|
1165
1187
|
}
|
|
1166
|
-
function
|
|
1167
|
-
|
|
1188
|
+
function resolveZodType(schema) {
|
|
1189
|
+
let currentSchema = schema;
|
|
1190
|
+
let isOptional = false;
|
|
1191
|
+
let def = getZodDef(currentSchema);
|
|
1168
1192
|
let typeName = def?.type;
|
|
1169
1193
|
if (typeName === "optional") {
|
|
1194
|
+
isOptional = true;
|
|
1170
1195
|
const innerType = def?.innerType;
|
|
1171
1196
|
if (innerType) {
|
|
1172
|
-
|
|
1173
|
-
|
|
1197
|
+
currentSchema = innerType;
|
|
1198
|
+
def = getZodDef(innerType);
|
|
1199
|
+
typeName = def?.type;
|
|
1174
1200
|
}
|
|
1175
1201
|
}
|
|
1176
|
-
if (typeName === "
|
|
1202
|
+
if (typeName === "default" || typeName === "ZodDefault") {
|
|
1203
|
+
const innerType = def?.innerType;
|
|
1204
|
+
if (innerType) {
|
|
1205
|
+
currentSchema = innerType;
|
|
1206
|
+
def = getZodDef(innerType);
|
|
1207
|
+
typeName = def?.type;
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1210
|
+
while (typeName === "refinement" || typeName === "ZodEffects") {
|
|
1211
|
+
const innerType = def?.schema || def?.innerType;
|
|
1212
|
+
if (innerType) {
|
|
1213
|
+
currentSchema = innerType;
|
|
1214
|
+
def = getZodDef(innerType);
|
|
1215
|
+
typeName = def?.type;
|
|
1216
|
+
} else {
|
|
1217
|
+
break;
|
|
1218
|
+
}
|
|
1219
|
+
}
|
|
1220
|
+
return {
|
|
1221
|
+
typeName: typeName || "any",
|
|
1222
|
+
actualSchema: currentSchema,
|
|
1223
|
+
isOptional
|
|
1224
|
+
};
|
|
1225
|
+
}
|
|
1226
|
+
function parseNestedFormData2(flatData) {
|
|
1227
|
+
return parseNestedFormData(flatData);
|
|
1228
|
+
}
|
|
1229
|
+
function convertNumber(value) {
|
|
1230
|
+
if (typeof value === "string") {
|
|
1177
1231
|
const trimmed = value.trim();
|
|
1178
1232
|
if (trimmed !== "") {
|
|
1179
1233
|
const numValue = Number(trimmed);
|
|
@@ -1182,222 +1236,172 @@ function convertValueByType(value, schema) {
|
|
|
1182
1236
|
}
|
|
1183
1237
|
}
|
|
1184
1238
|
return value;
|
|
1185
|
-
}
|
|
1239
|
+
}
|
|
1240
|
+
if (typeof value === "number") {
|
|
1241
|
+
return value;
|
|
1242
|
+
}
|
|
1243
|
+
return value;
|
|
1244
|
+
}
|
|
1245
|
+
function convertBoolean(value) {
|
|
1246
|
+
if (typeof value === "string") {
|
|
1186
1247
|
const trimmed = value.trim().toLowerCase();
|
|
1187
1248
|
if (trimmed === "true" || trimmed === "1" || trimmed === "on") {
|
|
1188
1249
|
return true;
|
|
1189
|
-
}
|
|
1250
|
+
}
|
|
1251
|
+
if (trimmed === "false" || trimmed === "0" || trimmed === "off" || trimmed === "") {
|
|
1190
1252
|
return false;
|
|
1191
1253
|
}
|
|
1192
1254
|
return value;
|
|
1193
1255
|
}
|
|
1256
|
+
if (typeof value === "boolean") {
|
|
1257
|
+
return value;
|
|
1258
|
+
}
|
|
1194
1259
|
return value;
|
|
1195
1260
|
}
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
for (const [fieldName, fieldSchema] of Object.entries(shape)) {
|
|
1206
|
-
if (["id", "createdAt", "updatedAt"].includes(fieldName)) {
|
|
1207
|
-
continue;
|
|
1208
|
-
}
|
|
1209
|
-
const field = parseFieldSchema(fieldName, fieldSchema);
|
|
1210
|
-
if (field) {
|
|
1211
|
-
fields.push(field);
|
|
1261
|
+
function processArrayElement(item, elementType) {
|
|
1262
|
+
if (typeof item === "object" && item !== null && !Array.isArray(item)) {
|
|
1263
|
+
const { typeName } = resolveZodType(elementType);
|
|
1264
|
+
if (typeName === "object") {
|
|
1265
|
+
const processedItem = preprocessFormData(
|
|
1266
|
+
item,
|
|
1267
|
+
elementType
|
|
1268
|
+
);
|
|
1269
|
+
return { ...item, ...processedItem };
|
|
1212
1270
|
}
|
|
1271
|
+
return item;
|
|
1213
1272
|
}
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
function parseFieldSchema(fieldName, fieldSchema) {
|
|
1217
|
-
if (!fieldSchema || !fieldSchema._def) {
|
|
1218
|
-
return null;
|
|
1219
|
-
}
|
|
1220
|
-
const label = getFieldDescription(fieldSchema) || fieldName;
|
|
1221
|
-
const { type, required, options, innerSchema, step } = analyzeFieldType(fieldSchema);
|
|
1222
|
-
return {
|
|
1223
|
-
name: fieldName,
|
|
1224
|
-
label,
|
|
1225
|
-
type,
|
|
1226
|
-
required,
|
|
1227
|
-
options,
|
|
1228
|
-
step,
|
|
1229
|
-
schema: innerSchema || fieldSchema
|
|
1230
|
-
};
|
|
1231
|
-
}
|
|
1232
|
-
function getFieldDescription(schema) {
|
|
1233
|
-
if (schema?.description) {
|
|
1234
|
-
return schema.description;
|
|
1235
|
-
}
|
|
1236
|
-
const schemaDef = schema._def;
|
|
1237
|
-
if (schemaDef?.description) {
|
|
1238
|
-
return schemaDef.description;
|
|
1239
|
-
}
|
|
1240
|
-
if (schemaDef?.innerType) {
|
|
1241
|
-
return getFieldDescription(schemaDef.innerType);
|
|
1242
|
-
}
|
|
1243
|
-
return void 0;
|
|
1244
|
-
}
|
|
1245
|
-
function analyzeFieldType(schema) {
|
|
1246
|
-
const def = schema._def;
|
|
1247
|
-
const typeName = def?.type || def?.typeName;
|
|
1248
|
-
if (typeName === "optional" || typeName === "ZodOptional") {
|
|
1249
|
-
const inner = analyzeFieldType(def.innerType);
|
|
1250
|
-
return {
|
|
1251
|
-
...inner,
|
|
1252
|
-
required: false,
|
|
1253
|
-
innerSchema: def.innerType
|
|
1254
|
-
};
|
|
1255
|
-
}
|
|
1256
|
-
if (typeName === "nullable" || typeName === "ZodNullable") {
|
|
1257
|
-
const inner = analyzeFieldType(def.innerType);
|
|
1258
|
-
return {
|
|
1259
|
-
...inner,
|
|
1260
|
-
innerSchema: def.innerType
|
|
1261
|
-
};
|
|
1262
|
-
}
|
|
1263
|
-
if (typeName === "enum" || typeName === "ZodEnum") {
|
|
1264
|
-
const options = extractEnumValues(def);
|
|
1265
|
-
return {
|
|
1266
|
-
type: "select",
|
|
1267
|
-
required: true,
|
|
1268
|
-
options,
|
|
1269
|
-
innerSchema: schema
|
|
1270
|
-
};
|
|
1271
|
-
}
|
|
1272
|
-
if (typeName === "nativeEnum" || typeName === "ZodNativeEnum") {
|
|
1273
|
-
const options = extractNativeEnumValues(def);
|
|
1274
|
-
return {
|
|
1275
|
-
type: "select",
|
|
1276
|
-
required: true,
|
|
1277
|
-
options,
|
|
1278
|
-
innerSchema: schema
|
|
1279
|
-
};
|
|
1273
|
+
if (typeof item === "string") {
|
|
1274
|
+
return convertValueByType(item, elementType);
|
|
1280
1275
|
}
|
|
1281
|
-
if (
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
(
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
fieldType = "textarea";
|
|
1276
|
+
if (Array.isArray(item)) {
|
|
1277
|
+
const elementDef = getZodDef(elementType);
|
|
1278
|
+
const nestedInnerType = elementDef?.element;
|
|
1279
|
+
if (nestedInnerType) {
|
|
1280
|
+
return item.map((subItem) => {
|
|
1281
|
+
if (typeof subItem === "string") {
|
|
1282
|
+
return convertValueByType(subItem, nestedInnerType);
|
|
1283
|
+
}
|
|
1284
|
+
if (typeof subItem === "object" && subItem !== null) {
|
|
1285
|
+
const subItemDef = getZodDef(nestedInnerType);
|
|
1286
|
+
if (subItemDef?.type === "object") {
|
|
1287
|
+
return preprocessFormData(
|
|
1288
|
+
subItem,
|
|
1289
|
+
nestedInnerType
|
|
1290
|
+
);
|
|
1297
1291
|
}
|
|
1298
1292
|
}
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
return {
|
|
1302
|
-
type: fieldType,
|
|
1303
|
-
required: true,
|
|
1304
|
-
innerSchema: schema
|
|
1305
|
-
};
|
|
1306
|
-
}
|
|
1307
|
-
if (typeName === "number" || typeName === "ZodNumber") {
|
|
1308
|
-
let step = void 0;
|
|
1309
|
-
if (def?.checks) {
|
|
1310
|
-
const hasIntCheck = def.checks.some(
|
|
1311
|
-
(check) => check.isInt === true || check.format === "safeint" || check.def?.format === "safeint" || check.kind === "int" || check.constructor?.name === "ZodInt" || check._zod?.def?.check === "int" || check._zod?.def?.kind === "int"
|
|
1312
|
-
);
|
|
1313
|
-
if (!hasIntCheck) {
|
|
1314
|
-
step = "any";
|
|
1315
|
-
}
|
|
1316
|
-
} else {
|
|
1317
|
-
step = "any";
|
|
1293
|
+
return subItem;
|
|
1294
|
+
});
|
|
1318
1295
|
}
|
|
1319
|
-
return
|
|
1320
|
-
type: "number",
|
|
1321
|
-
required: true,
|
|
1322
|
-
innerSchema: schema,
|
|
1323
|
-
step
|
|
1324
|
-
};
|
|
1325
|
-
}
|
|
1326
|
-
if (typeName === "date" || typeName === "ZodDate") {
|
|
1327
|
-
return {
|
|
1328
|
-
type: "date",
|
|
1329
|
-
required: true,
|
|
1330
|
-
innerSchema: schema
|
|
1331
|
-
};
|
|
1332
|
-
}
|
|
1333
|
-
if (typeName === "boolean" || typeName === "ZodBoolean") {
|
|
1334
|
-
return {
|
|
1335
|
-
type: "checkbox",
|
|
1336
|
-
required: true,
|
|
1337
|
-
innerSchema: schema
|
|
1338
|
-
};
|
|
1339
|
-
}
|
|
1340
|
-
return {
|
|
1341
|
-
type: "text",
|
|
1342
|
-
required: true,
|
|
1343
|
-
innerSchema: schema
|
|
1344
|
-
};
|
|
1345
|
-
}
|
|
1346
|
-
function extractEnumValues(def) {
|
|
1347
|
-
let values;
|
|
1348
|
-
if (def?.values && Array.isArray(def.values)) {
|
|
1349
|
-
values = def.values;
|
|
1350
|
-
} else if (def?.entries && typeof def.entries === "object") {
|
|
1351
|
-
values = Object.keys(def.entries);
|
|
1352
|
-
}
|
|
1353
|
-
if (values && values.length > 0) {
|
|
1354
|
-
return values.map((value) => ({
|
|
1355
|
-
value,
|
|
1356
|
-
label: String(value)
|
|
1357
|
-
}));
|
|
1358
|
-
}
|
|
1359
|
-
return void 0;
|
|
1360
|
-
}
|
|
1361
|
-
function extractNativeEnumValues(def) {
|
|
1362
|
-
const enumValues = def.values || def._def?.values || {};
|
|
1363
|
-
if (enumValues && typeof enumValues === "object") {
|
|
1364
|
-
return Object.entries(enumValues).filter(
|
|
1365
|
-
([_, value]) => typeof value === "string" || typeof value === "number"
|
|
1366
|
-
).map(([key, value]) => ({
|
|
1367
|
-
value,
|
|
1368
|
-
label: key
|
|
1369
|
-
}));
|
|
1296
|
+
return item;
|
|
1370
1297
|
}
|
|
1371
|
-
return
|
|
1298
|
+
return item;
|
|
1372
1299
|
}
|
|
1373
|
-
function
|
|
1374
|
-
if (
|
|
1375
|
-
|
|
1300
|
+
function processArrayType(value, actualSchema) {
|
|
1301
|
+
if (Array.isArray(value)) {
|
|
1302
|
+
const arrayDef = getZodDef(actualSchema);
|
|
1303
|
+
let elementType = arrayDef?.element;
|
|
1304
|
+
if (!elementType) {
|
|
1305
|
+
return value;
|
|
1306
|
+
}
|
|
1307
|
+
const { actualSchema: resolvedElementType } = resolveZodType(elementType);
|
|
1308
|
+
return value.map((item) => processArrayElement(item, resolvedElementType));
|
|
1376
1309
|
}
|
|
1377
|
-
if (
|
|
1378
|
-
|
|
1310
|
+
if (typeof value === "string") {
|
|
1311
|
+
const trimmed = value.trim();
|
|
1312
|
+
if (trimmed.startsWith("[") && trimmed.endsWith("]")) {
|
|
1313
|
+
try {
|
|
1314
|
+
return JSON.parse(trimmed);
|
|
1315
|
+
} catch {
|
|
1316
|
+
}
|
|
1317
|
+
} else {
|
|
1318
|
+
return trimmed.split(",").map((p) => p.trim()).filter((p) => p.length > 0);
|
|
1319
|
+
}
|
|
1379
1320
|
}
|
|
1380
|
-
return
|
|
1321
|
+
return value;
|
|
1381
1322
|
}
|
|
1382
|
-
function
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1323
|
+
function processObjectType(value, actualSchema) {
|
|
1324
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
1325
|
+
return preprocessFormData(value, actualSchema);
|
|
1326
|
+
}
|
|
1327
|
+
if (typeof value === "string" && value.trim() !== "") {
|
|
1328
|
+
const trimmed = value.trim();
|
|
1329
|
+
if (trimmed.startsWith("{") && trimmed.endsWith("}")) {
|
|
1330
|
+
try {
|
|
1331
|
+
return JSON.parse(trimmed);
|
|
1332
|
+
} catch {
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1335
|
+
}
|
|
1336
|
+
return value;
|
|
1391
1337
|
}
|
|
1392
|
-
function
|
|
1393
|
-
|
|
1338
|
+
function processAnyType(value) {
|
|
1339
|
+
if (typeof value === "string" && value.trim() !== "") {
|
|
1340
|
+
const trimmed = value.trim();
|
|
1341
|
+
if (trimmed.startsWith("{") && trimmed.endsWith("}") || trimmed.startsWith("[") && trimmed.endsWith("]")) {
|
|
1342
|
+
try {
|
|
1343
|
+
return JSON.parse(trimmed);
|
|
1344
|
+
} catch {
|
|
1345
|
+
}
|
|
1346
|
+
}
|
|
1347
|
+
}
|
|
1348
|
+
return value;
|
|
1394
1349
|
}
|
|
1395
|
-
function
|
|
1396
|
-
|
|
1350
|
+
function preprocessFormData(data, zodSchema) {
|
|
1351
|
+
if (!zodSchema) {
|
|
1352
|
+
return data;
|
|
1353
|
+
}
|
|
1354
|
+
const processed = { ...data };
|
|
1355
|
+
const def = getZodDef(zodSchema);
|
|
1356
|
+
const shape = typeof def.shape === "function" ? def.shape() : def.shape;
|
|
1357
|
+
if (!shape || typeof shape !== "object") {
|
|
1358
|
+
return processed;
|
|
1359
|
+
}
|
|
1360
|
+
for (const [fieldName, fieldSchema] of Object.entries(shape)) {
|
|
1361
|
+
const value = processed[fieldName];
|
|
1362
|
+
if (value === void 0) {
|
|
1363
|
+
continue;
|
|
1364
|
+
}
|
|
1365
|
+
if (value === null || value === "") {
|
|
1366
|
+
processed[fieldName] = void 0;
|
|
1367
|
+
continue;
|
|
1368
|
+
}
|
|
1369
|
+
const { typeName, actualSchema } = resolveZodType(
|
|
1370
|
+
fieldSchema
|
|
1371
|
+
);
|
|
1372
|
+
switch (typeName) {
|
|
1373
|
+
case "number":
|
|
1374
|
+
case "int":
|
|
1375
|
+
processed[fieldName] = convertNumber(value);
|
|
1376
|
+
break;
|
|
1377
|
+
case "boolean":
|
|
1378
|
+
processed[fieldName] = convertBoolean(value);
|
|
1379
|
+
break;
|
|
1380
|
+
case "array":
|
|
1381
|
+
processed[fieldName] = processArrayType(value, actualSchema);
|
|
1382
|
+
break;
|
|
1383
|
+
case "object":
|
|
1384
|
+
processed[fieldName] = processObjectType(value, actualSchema);
|
|
1385
|
+
break;
|
|
1386
|
+
case "any":
|
|
1387
|
+
case "unknown":
|
|
1388
|
+
processed[fieldName] = processAnyType(value);
|
|
1389
|
+
break;
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1392
|
+
return processed;
|
|
1397
1393
|
}
|
|
1398
|
-
function
|
|
1399
|
-
const
|
|
1400
|
-
|
|
1394
|
+
function convertValueByType(value, schema) {
|
|
1395
|
+
const { typeName } = resolveZodType(schema);
|
|
1396
|
+
switch (typeName) {
|
|
1397
|
+
case "number":
|
|
1398
|
+
case "int":
|
|
1399
|
+
return convertNumber(value);
|
|
1400
|
+
case "boolean":
|
|
1401
|
+
return convertBoolean(value);
|
|
1402
|
+
default:
|
|
1403
|
+
return value;
|
|
1404
|
+
}
|
|
1401
1405
|
}
|
|
1402
1406
|
var BaseFormFeature = class extends BaseFeature {
|
|
1403
1407
|
titleGetter;
|
|
@@ -1421,7 +1425,8 @@ var BaseFormFeature = class extends BaseFeature {
|
|
|
1421
1425
|
type: options.type,
|
|
1422
1426
|
permission: options.permission,
|
|
1423
1427
|
dialogSize: options.dialogSize,
|
|
1424
|
-
closeOnBackdropClick: options.closeOnBackdropClick
|
|
1428
|
+
closeOnBackdropClick: options.closeOnBackdropClick,
|
|
1429
|
+
schema: options.schema
|
|
1425
1430
|
});
|
|
1426
1431
|
this.titleGetter = options.getTitle;
|
|
1427
1432
|
this.descriptionGetter = options.getDescription;
|
|
@@ -1434,7 +1439,7 @@ var BaseFormFeature = class extends BaseFeature {
|
|
|
1434
1439
|
if (this.getFormAction() === "edit") {
|
|
1435
1440
|
try {
|
|
1436
1441
|
const initialData = await this.getInitialData(context);
|
|
1437
|
-
if (initialData
|
|
1442
|
+
if (initialData) {
|
|
1438
1443
|
return await this.titleGetter(context, initialData);
|
|
1439
1444
|
}
|
|
1440
1445
|
} catch (error) {
|
|
@@ -1454,7 +1459,7 @@ var BaseFormFeature = class extends BaseFeature {
|
|
|
1454
1459
|
if (this.getFormAction() === "edit") {
|
|
1455
1460
|
try {
|
|
1456
1461
|
const initialData = await this.getInitialData(context);
|
|
1457
|
-
if (initialData
|
|
1462
|
+
if (initialData) {
|
|
1458
1463
|
return await this.descriptionGetter(context, initialData);
|
|
1459
1464
|
}
|
|
1460
1465
|
} catch (error) {
|
|
@@ -1478,17 +1483,13 @@ var BaseFormFeature = class extends BaseFeature {
|
|
|
1478
1483
|
* 处理请求
|
|
1479
1484
|
*/
|
|
1480
1485
|
async handle(context) {
|
|
1481
|
-
|
|
1482
|
-
this.currentFormId = void 0;
|
|
1483
|
-
if (ctx.req.method === "GET") {
|
|
1486
|
+
if (context.ctx.req.method === "GET") {
|
|
1484
1487
|
return this.render(context);
|
|
1485
|
-
}
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
throw new Error("Schema is required for form validation");
|
|
1491
|
-
}
|
|
1488
|
+
}
|
|
1489
|
+
const formData = this.preprocessFormData(context.body);
|
|
1490
|
+
const nestedData = parseNestedFormData2(formData);
|
|
1491
|
+
let data = this.preprocessFormData(nestedData);
|
|
1492
|
+
if (this.schema) {
|
|
1492
1493
|
const parseResult = this.schema.safeParse(data);
|
|
1493
1494
|
if (!parseResult.success) {
|
|
1494
1495
|
const issues = parseResult.error.issues || [];
|
|
@@ -1497,35 +1498,33 @@ var BaseFormFeature = class extends BaseFeature {
|
|
|
1497
1498
|
const errorMessage = firstError.message;
|
|
1498
1499
|
const errorText = fieldName ? `${fieldName}: ${errorMessage}` : errorMessage;
|
|
1499
1500
|
context.sendError("\u9A8C\u8BC1\u5931\u8D25", errorText);
|
|
1500
|
-
return
|
|
1501
|
-
}
|
|
1502
|
-
const item = await this.handleSubmit(
|
|
1503
|
-
context,
|
|
1504
|
-
parseResult.data
|
|
1505
|
-
);
|
|
1506
|
-
if (!item) {
|
|
1507
|
-
context.sendError(
|
|
1508
|
-
this.getFormAction() === "create" ? "\u521B\u5EFA\u5931\u8D25" : "\u66F4\u65B0\u5931\u8D25",
|
|
1509
|
-
"\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5"
|
|
1510
|
-
);
|
|
1511
|
-
return this.render(context, originalData);
|
|
1501
|
+
return null;
|
|
1512
1502
|
}
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1503
|
+
data = parseResult.data;
|
|
1504
|
+
}
|
|
1505
|
+
const item = await this.handleSubmit(context, data);
|
|
1506
|
+
if (!item) {
|
|
1507
|
+
context.sendError(
|
|
1508
|
+
this.getFormAction() === "create" ? "\u521B\u5EFA\u5931\u8D25" : "\u66F4\u65B0\u5931\u8D25",
|
|
1509
|
+
"\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5"
|
|
1517
1510
|
);
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1511
|
+
return null;
|
|
1512
|
+
}
|
|
1513
|
+
const actionText = this.getFormAction() === "create" ? "\u521B\u5EFA" : "\u66F4\u65B0";
|
|
1514
|
+
context.sendSuccess(
|
|
1515
|
+
`${actionText}\u6210\u529F`,
|
|
1516
|
+
`${context.model.getMetadata().title}\u5DF2\u6210\u529F${actionText}`
|
|
1517
|
+
);
|
|
1518
|
+
if (context.isDialog) {
|
|
1519
|
+
context.setRefresh(true);
|
|
1520
|
+
if (context.redirectUrl) {
|
|
1521
|
+
context.redirectUrl = void 0;
|
|
1528
1522
|
}
|
|
1523
|
+
return null;
|
|
1524
|
+
} else {
|
|
1525
|
+
const redirectUrl = this.getSuccessRedirectUrl(context, item);
|
|
1526
|
+
context.redirect(redirectUrl);
|
|
1527
|
+
return null;
|
|
1529
1528
|
}
|
|
1530
1529
|
}
|
|
1531
1530
|
formFieldNames;
|
|
@@ -1534,15 +1533,9 @@ var BaseFormFeature = class extends BaseFeature {
|
|
|
1534
1533
|
* 渲染表单页面
|
|
1535
1534
|
*/
|
|
1536
1535
|
async render(context, initialData) {
|
|
1537
|
-
let formData;
|
|
1538
|
-
if (
|
|
1539
|
-
|
|
1540
|
-
formData = initialData;
|
|
1541
|
-
} else {
|
|
1542
|
-
formData = await this.getInitialData(context);
|
|
1543
|
-
}
|
|
1544
|
-
} else {
|
|
1545
|
-
formData = initialData;
|
|
1536
|
+
let formData = initialData;
|
|
1537
|
+
if (!initialData) {
|
|
1538
|
+
formData = await this.getInitialData(context);
|
|
1546
1539
|
}
|
|
1547
1540
|
let submitUrl = this.getSubmitUrl(context);
|
|
1548
1541
|
if (context.isDialog) {
|
|
@@ -1552,12 +1545,9 @@ var BaseFormFeature = class extends BaseFeature {
|
|
|
1552
1545
|
}
|
|
1553
1546
|
const method = this.getFormAction() === "create" ? "post" : "put";
|
|
1554
1547
|
const formId = this.getFormId(context);
|
|
1548
|
+
let formGroups = [];
|
|
1555
1549
|
if (this.groups && this.groups.length > 0) {
|
|
1556
|
-
|
|
1557
|
-
throw new Error("Schema is required when using groups");
|
|
1558
|
-
}
|
|
1559
|
-
const schema = this.schema;
|
|
1560
|
-
const groupSchemas = this.groups.map((group) => {
|
|
1550
|
+
formGroups = this.groups.map((group) => {
|
|
1561
1551
|
const pickObject = group.fields.reduce(
|
|
1562
1552
|
(acc, fieldName) => {
|
|
1563
1553
|
acc[fieldName] = true;
|
|
@@ -1567,39 +1557,27 @@ var BaseFormFeature = class extends BaseFeature {
|
|
|
1567
1557
|
);
|
|
1568
1558
|
return {
|
|
1569
1559
|
label: group.label,
|
|
1570
|
-
schema: schema.pick(pickObject),
|
|
1571
|
-
fields: group.fields
|
|
1560
|
+
schema: this.schema.pick(pickObject),
|
|
1561
|
+
fields: group.fields.map((name) => {
|
|
1562
|
+
const field = this.fields.find((f) => f.name === name);
|
|
1563
|
+
return field;
|
|
1564
|
+
})
|
|
1572
1565
|
};
|
|
1573
1566
|
});
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
const formFields = modelFieldsToFormFields(groupFields2);
|
|
1578
|
-
return {
|
|
1579
|
-
label,
|
|
1580
|
-
fields: formFields
|
|
1581
|
-
};
|
|
1582
|
-
}
|
|
1583
|
-
);
|
|
1584
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1585
|
-
FormPage,
|
|
1567
|
+
} else {
|
|
1568
|
+
const formFields = !this.formFieldNames ? this.fields : this.fields.filter((f) => this.formFieldNames?.includes(f.name));
|
|
1569
|
+
formGroups = [
|
|
1586
1570
|
{
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
initialData: formData,
|
|
1591
|
-
formId,
|
|
1592
|
-
isDialog: context.isDialog,
|
|
1593
|
-
formFieldRenderers: this.formFieldRenderers
|
|
1571
|
+
label: "\u9ED8\u8BA4\u5206\u7EC4",
|
|
1572
|
+
fields: formFields,
|
|
1573
|
+
schema: this.schema
|
|
1594
1574
|
}
|
|
1595
|
-
|
|
1575
|
+
];
|
|
1596
1576
|
}
|
|
1597
|
-
const filteredFields = this.formFieldNames ? filterFieldsByNames(this.fields || [], this.formFieldNames) : this.fields || [];
|
|
1598
|
-
const fields = modelFieldsToFormFields(filteredFields);
|
|
1599
1577
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1600
1578
|
FormPage,
|
|
1601
1579
|
{
|
|
1602
|
-
|
|
1580
|
+
groups: formGroups,
|
|
1603
1581
|
submitUrl,
|
|
1604
1582
|
method,
|
|
1605
1583
|
initialData: formData,
|
|
@@ -1800,90 +1778,259 @@ function Card(props) {
|
|
|
1800
1778
|
}
|
|
1801
1779
|
);
|
|
1802
1780
|
}
|
|
1803
|
-
function
|
|
1781
|
+
function renderEmptyValue() {
|
|
1782
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-400", children: "-" });
|
|
1783
|
+
}
|
|
1784
|
+
function renderBoolean(value) {
|
|
1785
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1786
|
+
"span",
|
|
1787
|
+
{
|
|
1788
|
+
className: `px-2 py-1 rounded text-sm font-medium ${value ? "bg-green-100 text-green-800" : "bg-gray-100 text-gray-600"}`,
|
|
1789
|
+
children: value ? "\u662F" : "\u5426"
|
|
1790
|
+
}
|
|
1791
|
+
);
|
|
1792
|
+
}
|
|
1793
|
+
function renderNumber(value) {
|
|
1794
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { children: value.toLocaleString() });
|
|
1795
|
+
}
|
|
1796
|
+
function renderDate(value) {
|
|
1797
|
+
const date = value instanceof Date ? value : new Date(value);
|
|
1798
|
+
if (isNaN(date.getTime())) {
|
|
1799
|
+
return renderEmptyValue();
|
|
1800
|
+
}
|
|
1801
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { children: date.toLocaleString() });
|
|
1802
|
+
}
|
|
1803
|
+
function renderSimpleArray(value) {
|
|
1804
|
+
if (value.length === 0) {
|
|
1805
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-400", children: "\u6682\u65E0\u6570\u636E" });
|
|
1806
|
+
}
|
|
1807
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-2", children: value.map((item, index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1808
|
+
"span",
|
|
1809
|
+
{
|
|
1810
|
+
className: "px-2 py-1 bg-gray-100 text-gray-700 rounded text-sm",
|
|
1811
|
+
children: String(item)
|
|
1812
|
+
},
|
|
1813
|
+
index
|
|
1814
|
+
)) });
|
|
1815
|
+
}
|
|
1816
|
+
function renderObjectArray(value) {
|
|
1817
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-gray-600", children: [
|
|
1818
|
+
"\u5305\u542B ",
|
|
1819
|
+
value.length,
|
|
1820
|
+
" \u9879\uFF08\u5BF9\u8C61\u6570\u7EC4\uFF0C\u5EFA\u8BAE\u4F7F\u7528\u81EA\u5B9A\u4E49\u6E32\u67D3\uFF09"
|
|
1821
|
+
] });
|
|
1822
|
+
}
|
|
1823
|
+
function renderObject(value) {
|
|
1824
|
+
return /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "bg-gray-50 border border-gray-200 rounded p-3 text-xs overflow-x-auto", children: JSON.stringify(value, null, 2) });
|
|
1825
|
+
}
|
|
1826
|
+
function DetailFieldRenderer(props) {
|
|
1827
|
+
const { value, field } = props;
|
|
1804
1828
|
if (value === null || value === void 0) {
|
|
1805
|
-
return
|
|
1829
|
+
return renderEmptyValue();
|
|
1830
|
+
}
|
|
1831
|
+
if (field) {
|
|
1832
|
+
switch (field.type) {
|
|
1833
|
+
case "checkbox":
|
|
1834
|
+
if (typeof value === "boolean") {
|
|
1835
|
+
return renderBoolean(value);
|
|
1836
|
+
}
|
|
1837
|
+
if (value === "true" || value === "1" || value === "on" || String(value).toLowerCase() === "true") {
|
|
1838
|
+
return renderBoolean(true);
|
|
1839
|
+
}
|
|
1840
|
+
if (value === "false" || value === "0" || String(value).toLowerCase() === "false") {
|
|
1841
|
+
return renderBoolean(false);
|
|
1842
|
+
}
|
|
1843
|
+
break;
|
|
1844
|
+
case "number":
|
|
1845
|
+
if (typeof value === "number") {
|
|
1846
|
+
return renderNumber(value);
|
|
1847
|
+
}
|
|
1848
|
+
const numValue = Number(value);
|
|
1849
|
+
if (!isNaN(numValue)) {
|
|
1850
|
+
return renderNumber(numValue);
|
|
1851
|
+
}
|
|
1852
|
+
break;
|
|
1853
|
+
case "date":
|
|
1854
|
+
if (value instanceof Date) {
|
|
1855
|
+
return renderDate(value);
|
|
1856
|
+
}
|
|
1857
|
+
if (typeof value === "string") {
|
|
1858
|
+
return renderDate(value);
|
|
1859
|
+
}
|
|
1860
|
+
break;
|
|
1861
|
+
case "email":
|
|
1862
|
+
case "url":
|
|
1863
|
+
if (typeof value === "string" && value.trim()) {
|
|
1864
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1865
|
+
"a",
|
|
1866
|
+
{
|
|
1867
|
+
href: value,
|
|
1868
|
+
target: "_blank",
|
|
1869
|
+
rel: "noopener noreferrer",
|
|
1870
|
+
className: "text-blue-600 hover:text-blue-800 hover:underline",
|
|
1871
|
+
children: value
|
|
1872
|
+
}
|
|
1873
|
+
);
|
|
1874
|
+
}
|
|
1875
|
+
break;
|
|
1876
|
+
case "select":
|
|
1877
|
+
if (field.options && field.options.length > 0) {
|
|
1878
|
+
const option = field.options.find(
|
|
1879
|
+
(opt) => String(opt.value) === String(value)
|
|
1880
|
+
);
|
|
1881
|
+
if (option) {
|
|
1882
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { children: option.label });
|
|
1883
|
+
}
|
|
1884
|
+
}
|
|
1885
|
+
break;
|
|
1886
|
+
}
|
|
1806
1887
|
}
|
|
1807
1888
|
if (Array.isArray(value)) {
|
|
1808
1889
|
if (value.length === 0) {
|
|
1809
|
-
return
|
|
1890
|
+
return renderEmptyValue();
|
|
1810
1891
|
}
|
|
1811
1892
|
if (value.length > 0 && typeof value[0] === "object" && value[0] !== null) {
|
|
1812
|
-
return
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1893
|
+
return renderObjectArray(value);
|
|
1894
|
+
}
|
|
1895
|
+
return renderSimpleArray(value);
|
|
1896
|
+
}
|
|
1897
|
+
if (typeof value === "object") {
|
|
1898
|
+
if (value instanceof Date) {
|
|
1899
|
+
return renderDate(value);
|
|
1900
|
+
}
|
|
1901
|
+
return renderObject(value);
|
|
1902
|
+
}
|
|
1903
|
+
if (typeof value === "boolean") {
|
|
1904
|
+
return renderBoolean(value);
|
|
1905
|
+
}
|
|
1906
|
+
if (typeof value === "number") {
|
|
1907
|
+
return renderNumber(value);
|
|
1908
|
+
}
|
|
1909
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { children: String(value) });
|
|
1910
|
+
}
|
|
1911
|
+
function ColumnRenderer(value, field) {
|
|
1912
|
+
if (value === null || value === void 0) {
|
|
1913
|
+
return renderEmptyValue();
|
|
1914
|
+
}
|
|
1915
|
+
if (field) {
|
|
1916
|
+
switch (field.type) {
|
|
1917
|
+
case "checkbox":
|
|
1918
|
+
if (typeof value === "boolean") {
|
|
1919
|
+
return renderBoolean(value);
|
|
1920
|
+
}
|
|
1921
|
+
if (value === "true" || value === "1" || value === "on" || String(value).toLowerCase() === "true") {
|
|
1922
|
+
return renderBoolean(true);
|
|
1923
|
+
}
|
|
1924
|
+
if (value === "false" || value === "0" || String(value).toLowerCase() === "false") {
|
|
1925
|
+
return renderBoolean(false);
|
|
1926
|
+
}
|
|
1927
|
+
break;
|
|
1928
|
+
case "number":
|
|
1929
|
+
if (typeof value === "number") {
|
|
1930
|
+
return renderNumber(value);
|
|
1931
|
+
}
|
|
1932
|
+
const numValue = Number(value);
|
|
1933
|
+
if (!isNaN(numValue)) {
|
|
1934
|
+
return renderNumber(numValue);
|
|
1935
|
+
}
|
|
1936
|
+
break;
|
|
1937
|
+
case "date":
|
|
1938
|
+
if (value instanceof Date) {
|
|
1939
|
+
return renderDate(value);
|
|
1940
|
+
}
|
|
1941
|
+
if (typeof value === "string") {
|
|
1942
|
+
return renderDate(value);
|
|
1943
|
+
}
|
|
1944
|
+
break;
|
|
1945
|
+
case "email":
|
|
1946
|
+
case "url":
|
|
1947
|
+
if (typeof value === "string" && value.trim()) {
|
|
1948
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-blue-600", children: value });
|
|
1949
|
+
}
|
|
1950
|
+
break;
|
|
1951
|
+
case "select":
|
|
1952
|
+
if (field.options && field.options.length > 0) {
|
|
1953
|
+
const option = field.options.find(
|
|
1954
|
+
(opt) => String(opt.value) === String(value)
|
|
1955
|
+
);
|
|
1956
|
+
if (option) {
|
|
1957
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { children: option.label });
|
|
1958
|
+
}
|
|
1959
|
+
}
|
|
1960
|
+
break;
|
|
1961
|
+
case "textarea":
|
|
1962
|
+
if (typeof value === "string" && value.length > 50) {
|
|
1963
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("span", { title: value, className: "truncate max-w-xs block", children: [
|
|
1964
|
+
value.substring(0, 50),
|
|
1965
|
+
"..."
|
|
1966
|
+
] });
|
|
1967
|
+
}
|
|
1968
|
+
break;
|
|
1969
|
+
}
|
|
1970
|
+
}
|
|
1971
|
+
if (Array.isArray(value)) {
|
|
1972
|
+
if (value.length === 0) {
|
|
1973
|
+
return renderEmptyValue();
|
|
1974
|
+
}
|
|
1975
|
+
if (value.length > 0 && typeof value[0] !== "object") {
|
|
1976
|
+
const displayItems = value.slice(0, 3).map(String);
|
|
1977
|
+
const remaining = value.length - 3;
|
|
1978
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm", children: [
|
|
1979
|
+
displayItems.join(", "),
|
|
1980
|
+
remaining > 0 && ` +${remaining}`
|
|
1816
1981
|
] });
|
|
1817
1982
|
}
|
|
1818
|
-
return /* @__PURE__ */ jsxRuntime.
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
children: String(item)
|
|
1823
|
-
},
|
|
1824
|
-
index
|
|
1825
|
-
)) });
|
|
1983
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-gray-600", children: [
|
|
1984
|
+
value.length,
|
|
1985
|
+
" \u9879"
|
|
1986
|
+
] });
|
|
1826
1987
|
}
|
|
1827
1988
|
if (typeof value === "object") {
|
|
1828
1989
|
if (value instanceof Date) {
|
|
1829
|
-
return
|
|
1990
|
+
return renderDate(value);
|
|
1830
1991
|
}
|
|
1831
|
-
return /* @__PURE__ */ jsxRuntime.jsx("
|
|
1992
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-500 text-sm", children: "[\u5BF9\u8C61]" });
|
|
1832
1993
|
}
|
|
1833
1994
|
if (typeof value === "boolean") {
|
|
1834
|
-
return
|
|
1835
|
-
"span",
|
|
1836
|
-
{
|
|
1837
|
-
className: `px-2 py-1 rounded text-sm font-medium ${value ? "bg-green-100 text-green-800" : "bg-gray-100 text-gray-600"}`,
|
|
1838
|
-
children: value ? "\u662F" : "\u5426"
|
|
1839
|
-
}
|
|
1840
|
-
);
|
|
1995
|
+
return renderBoolean(value);
|
|
1841
1996
|
}
|
|
1842
1997
|
if (typeof value === "number") {
|
|
1843
|
-
return
|
|
1998
|
+
return renderNumber(value);
|
|
1999
|
+
}
|
|
2000
|
+
if (typeof value === "string" && value.length > 50) {
|
|
2001
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("span", { title: value, className: "truncate max-w-xs block", children: [
|
|
2002
|
+
value.substring(0, 50),
|
|
2003
|
+
"..."
|
|
2004
|
+
] });
|
|
1844
2005
|
}
|
|
1845
2006
|
return /* @__PURE__ */ jsxRuntime.jsx("span", { children: String(value) });
|
|
1846
2007
|
}
|
|
1847
|
-
function
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
} else {
|
|
1856
|
-
content = rendered;
|
|
2008
|
+
function getFieldLabel(fieldName, fieldLabels) {
|
|
2009
|
+
return fieldLabels?.[fieldName] || fieldName;
|
|
2010
|
+
}
|
|
2011
|
+
function getFieldRenderer(fieldName, fieldRenderers, fieldDefinitions) {
|
|
2012
|
+
if (fieldRenderers) {
|
|
2013
|
+
const customRenderer = fieldRenderers[fieldName];
|
|
2014
|
+
if (customRenderer) {
|
|
2015
|
+
return customRenderer;
|
|
1857
2016
|
}
|
|
1858
|
-
} else {
|
|
1859
|
-
content = renderDefaultValue(value);
|
|
1860
2017
|
}
|
|
1861
|
-
return
|
|
1862
|
-
|
|
1863
|
-
{
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
"dd",
|
|
1875
|
-
{
|
|
1876
|
-
className: "\r\n text-sm sm:text-base text-gray-900\r\n break-words\r\n leading-relaxed\r\n min-w-0\r\n ",
|
|
1877
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-0", children: content })
|
|
1878
|
-
}
|
|
1879
|
-
)
|
|
1880
|
-
]
|
|
1881
|
-
},
|
|
1882
|
-
field.key
|
|
1883
|
-
);
|
|
2018
|
+
return ((props) => {
|
|
2019
|
+
const field = fieldDefinitions?.[fieldName];
|
|
2020
|
+
return DetailFieldRenderer({ ...props, field });
|
|
2021
|
+
});
|
|
2022
|
+
}
|
|
2023
|
+
function renderFieldValue(rendered) {
|
|
2024
|
+
if (rendered === null || rendered === void 0) {
|
|
2025
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-400", children: "-" });
|
|
2026
|
+
}
|
|
2027
|
+
if (typeof rendered === "string" || typeof rendered === "number" || typeof rendered === "boolean") {
|
|
2028
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { children: String(rendered) });
|
|
2029
|
+
}
|
|
2030
|
+
return rendered;
|
|
1884
2031
|
}
|
|
1885
2032
|
function DetailPage(props) {
|
|
1886
|
-
const { item, fields, groups } = props;
|
|
2033
|
+
const { item, fields, groups, fieldLabels, fieldDefinitions, fieldRenderers } = props;
|
|
1887
2034
|
if (groups && groups.length > 0) {
|
|
1888
2035
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-6", children: groups.map((group, groupIndex) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1889
2036
|
Card,
|
|
@@ -1892,18 +2039,78 @@ function DetailPage(props) {
|
|
|
1892
2039
|
shadow: true,
|
|
1893
2040
|
bordered: true,
|
|
1894
2041
|
noPadding: true,
|
|
1895
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("dl", { className: "divide-y divide-gray-100", children: group.fields.map((
|
|
1896
|
-
const value = group.values[
|
|
1897
|
-
|
|
2042
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("dl", { className: "divide-y divide-gray-100", children: group.fields.map((fieldName) => {
|
|
2043
|
+
const value = group.values[fieldName];
|
|
2044
|
+
const label = getFieldLabel(fieldName, fieldLabels);
|
|
2045
|
+
const Renderer = getFieldRenderer(fieldName, fieldRenderers, fieldDefinitions);
|
|
2046
|
+
const rendered = Renderer({
|
|
2047
|
+
value,
|
|
2048
|
+
item,
|
|
2049
|
+
name: fieldName,
|
|
2050
|
+
label
|
|
2051
|
+
});
|
|
2052
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2053
|
+
"div",
|
|
2054
|
+
{
|
|
2055
|
+
className: "\r\n px-4 py-4 sm:px-6 sm:py-5\r\n flex flex-col\r\n hover:bg-gray-50/50 transition-colors duration-150\r\n group\r\n gap-1.5\r\n ",
|
|
2056
|
+
children: [
|
|
2057
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2058
|
+
"dt",
|
|
2059
|
+
{
|
|
2060
|
+
className: "\r\n text-xs sm:text-sm font-semibold text-gray-600 sm:text-gray-700\r\n flex items-start\r\n leading-tight sm:leading-5\r\n tracking-wide\r\n ",
|
|
2061
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 uppercase sm:normal-case", children: label })
|
|
2062
|
+
}
|
|
2063
|
+
),
|
|
2064
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2065
|
+
"dd",
|
|
2066
|
+
{
|
|
2067
|
+
className: "\r\n text-sm sm:text-base text-gray-900\r\n break-words\r\n leading-relaxed\r\n min-w-0\r\n ",
|
|
2068
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-0", children: renderFieldValue(rendered) })
|
|
2069
|
+
}
|
|
2070
|
+
)
|
|
2071
|
+
]
|
|
2072
|
+
},
|
|
2073
|
+
fieldName
|
|
2074
|
+
);
|
|
1898
2075
|
}) })
|
|
1899
2076
|
},
|
|
1900
2077
|
groupIndex
|
|
1901
2078
|
)) });
|
|
1902
2079
|
}
|
|
1903
2080
|
if (fields && fields.length > 0) {
|
|
1904
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-white border border-gray-200 rounded-lg shadow-sm overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx("dl", { className: "divide-y divide-gray-100", children: fields.map((
|
|
1905
|
-
const value = item[
|
|
1906
|
-
|
|
2081
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-white border border-gray-200 rounded-lg shadow-sm overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx("dl", { className: "divide-y divide-gray-100", children: fields.map((fieldName) => {
|
|
2082
|
+
const value = item[fieldName];
|
|
2083
|
+
const label = getFieldLabel(fieldName, fieldLabels);
|
|
2084
|
+
const Renderer = getFieldRenderer(fieldName, fieldRenderers, fieldDefinitions);
|
|
2085
|
+
const rendered = Renderer({
|
|
2086
|
+
value,
|
|
2087
|
+
item,
|
|
2088
|
+
name: fieldName,
|
|
2089
|
+
label
|
|
2090
|
+
});
|
|
2091
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2092
|
+
"div",
|
|
2093
|
+
{
|
|
2094
|
+
className: "\r\n px-4 py-4 sm:px-6 sm:py-5\r\n flex flex-col\r\n hover:bg-gray-50/50 transition-colors duration-150\r\n group\r\n gap-1.5\r\n ",
|
|
2095
|
+
children: [
|
|
2096
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2097
|
+
"dt",
|
|
2098
|
+
{
|
|
2099
|
+
className: "\r\n text-xs sm:text-sm font-semibold text-gray-600 sm:text-gray-700\r\n flex items-start\r\n leading-tight sm:leading-5\r\n tracking-wide\r\n ",
|
|
2100
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 uppercase sm:normal-case", children: label })
|
|
2101
|
+
}
|
|
2102
|
+
),
|
|
2103
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2104
|
+
"dd",
|
|
2105
|
+
{
|
|
2106
|
+
className: "\r\n text-sm sm:text-base text-gray-900\r\n break-words\r\n leading-relaxed\r\n min-w-0\r\n ",
|
|
2107
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-0", children: renderFieldValue(rendered) })
|
|
2108
|
+
}
|
|
2109
|
+
)
|
|
2110
|
+
]
|
|
2111
|
+
},
|
|
2112
|
+
fieldName
|
|
2113
|
+
);
|
|
1907
2114
|
}) }) });
|
|
1908
2115
|
}
|
|
1909
2116
|
return null;
|
|
@@ -1980,28 +2187,35 @@ var DefaultDetailFeature = class extends BaseFeature {
|
|
|
1980
2187
|
fields: group.fields
|
|
1981
2188
|
};
|
|
1982
2189
|
});
|
|
1983
|
-
const
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2190
|
+
const fieldLabels2 = {};
|
|
2191
|
+
const fieldDefinitions2 = {};
|
|
2192
|
+
(this.fields || []).forEach((field) => {
|
|
2193
|
+
fieldLabels2[field.name] = field.label;
|
|
2194
|
+
fieldDefinitions2[field.name] = field;
|
|
2195
|
+
});
|
|
2196
|
+
const groupFields = groupSchemas.map(({ label, fields: fieldNames }) => {
|
|
2197
|
+
return {
|
|
2198
|
+
label,
|
|
2199
|
+
fields: fieldNames,
|
|
2200
|
+
values: fieldNames.reduce(
|
|
2201
|
+
(acc, fieldName) => {
|
|
2202
|
+
acc[fieldName] = item[fieldName];
|
|
2203
|
+
return acc;
|
|
2204
|
+
},
|
|
2205
|
+
{}
|
|
2206
|
+
)
|
|
2207
|
+
};
|
|
2208
|
+
});
|
|
2209
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2210
|
+
DetailPage,
|
|
2211
|
+
{
|
|
2212
|
+
item,
|
|
2213
|
+
groups: groupFields,
|
|
2214
|
+
fieldLabels: fieldLabels2,
|
|
2215
|
+
fieldDefinitions: fieldDefinitions2,
|
|
2216
|
+
fieldRenderers: this.fieldRenderers
|
|
2002
2217
|
}
|
|
2003
2218
|
);
|
|
2004
|
-
return /* @__PURE__ */ jsxRuntime.jsx(DetailPage, { item, groups: groupFields });
|
|
2005
2219
|
}
|
|
2006
2220
|
const detailFields = this.detailFieldNames ? filterFieldsByNames(this.fields || [], this.detailFieldNames) : this.fields || [];
|
|
2007
2221
|
if (this.detailFieldNames) {
|
|
@@ -2019,13 +2233,25 @@ var DefaultDetailFeature = class extends BaseFeature {
|
|
|
2019
2233
|
}
|
|
2020
2234
|
}
|
|
2021
2235
|
const detailFieldNames = getFieldNamesFromFields(detailFields);
|
|
2022
|
-
const
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2236
|
+
const fieldLabels = {};
|
|
2237
|
+
const fieldDefinitions = {};
|
|
2238
|
+
detailFieldNames.forEach((fieldName) => {
|
|
2239
|
+
fieldLabels[fieldName] = getFieldLabelFromFields(this.fields || [], fieldName) || fieldName;
|
|
2240
|
+
const field = detailFields.find((f) => f.name === fieldName);
|
|
2241
|
+
if (field) {
|
|
2242
|
+
fieldDefinitions[fieldName] = field;
|
|
2243
|
+
}
|
|
2244
|
+
});
|
|
2245
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2246
|
+
DetailPage,
|
|
2247
|
+
{
|
|
2248
|
+
item,
|
|
2249
|
+
fields: detailFieldNames,
|
|
2250
|
+
fieldLabels,
|
|
2251
|
+
fieldDefinitions,
|
|
2252
|
+
fieldRenderers: this.fieldRenderers
|
|
2253
|
+
}
|
|
2254
|
+
);
|
|
2029
2255
|
}
|
|
2030
2256
|
async getActions(context) {
|
|
2031
2257
|
const id = context.params.id;
|
|
@@ -2084,6 +2310,7 @@ var DefaultEditFeature = class extends BaseFormFeature {
|
|
|
2084
2310
|
permission: options.permission || `${options.permissionPrefix}.edit`,
|
|
2085
2311
|
dialogSize: options.dialogSize,
|
|
2086
2312
|
closeOnBackdropClick: options.closeOnBackdropClick,
|
|
2313
|
+
schema: options.schema,
|
|
2087
2314
|
getTitle: options.getTitle ? (context, item) => {
|
|
2088
2315
|
if (item) {
|
|
2089
2316
|
return options.getTitle(item, context);
|
|
@@ -2097,8 +2324,6 @@ var DefaultEditFeature = class extends BaseFormFeature {
|
|
|
2097
2324
|
return void 0;
|
|
2098
2325
|
} : void 0
|
|
2099
2326
|
});
|
|
2100
|
-
this.schema = options.schema;
|
|
2101
|
-
this.fields = parseSchemaToFields(options.schema);
|
|
2102
2327
|
this.getItem = options.getItem;
|
|
2103
2328
|
this.updateItem = options.updateItem;
|
|
2104
2329
|
this.formFieldNames = options.formFieldNames;
|
|
@@ -2171,7 +2396,7 @@ function FilterForm(props) {
|
|
|
2171
2396
|
listPath,
|
|
2172
2397
|
currentFilters = {}
|
|
2173
2398
|
} = props;
|
|
2174
|
-
function
|
|
2399
|
+
function getFieldValue(field) {
|
|
2175
2400
|
const value = currentFilters[field.name];
|
|
2176
2401
|
if (value === null || value === void 0 || value === "") {
|
|
2177
2402
|
return "";
|
|
@@ -2208,10 +2433,10 @@ function FilterForm(props) {
|
|
|
2208
2433
|
className: "w-full px-4 py-2.5 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all duration-200 bg-white",
|
|
2209
2434
|
"data-testid": `filter-select-${field.name}`,
|
|
2210
2435
|
children: [
|
|
2211
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "", selected:
|
|
2436
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "", selected: getFieldValue(field) === "", children: "\u5168\u90E8" }),
|
|
2212
2437
|
field.options?.map((option) => {
|
|
2213
2438
|
const optionValue = String(option.value);
|
|
2214
|
-
const isSelected =
|
|
2439
|
+
const isSelected = getFieldValue(field) === optionValue;
|
|
2215
2440
|
return /* @__PURE__ */ jsxRuntime.jsx("option", { value: optionValue, selected: isSelected, children: option.label }, optionValue);
|
|
2216
2441
|
})
|
|
2217
2442
|
]
|
|
@@ -2222,7 +2447,7 @@ function FilterForm(props) {
|
|
|
2222
2447
|
id: `filter-${field.name}`,
|
|
2223
2448
|
name: field.name,
|
|
2224
2449
|
type: "date",
|
|
2225
|
-
value:
|
|
2450
|
+
value: getFieldValue(field),
|
|
2226
2451
|
className: "w-full px-4 py-2.5 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all duration-200 bg-white",
|
|
2227
2452
|
"data-testid": `filter-input-${field.name}`
|
|
2228
2453
|
}
|
|
@@ -2232,7 +2457,7 @@ function FilterForm(props) {
|
|
|
2232
2457
|
id: `filter-${field.name}`,
|
|
2233
2458
|
name: field.name,
|
|
2234
2459
|
type: "number",
|
|
2235
|
-
value:
|
|
2460
|
+
value: getFieldValue(field),
|
|
2236
2461
|
placeholder: field.placeholder || `\u8BF7\u8F93\u5165${field.label}`,
|
|
2237
2462
|
className: "w-full px-4 py-2.5 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all duration-200 bg-white",
|
|
2238
2463
|
"data-testid": `filter-input-${field.name}`
|
|
@@ -2243,7 +2468,7 @@ function FilterForm(props) {
|
|
|
2243
2468
|
id: `filter-${field.name}`,
|
|
2244
2469
|
name: field.name,
|
|
2245
2470
|
type: "text",
|
|
2246
|
-
value:
|
|
2471
|
+
value: getFieldValue(field),
|
|
2247
2472
|
placeholder: field.placeholder || `\u8BF7\u8F93\u5165${field.label}`,
|
|
2248
2473
|
className: "w-full px-4 py-2.5 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all duration-200 bg-white",
|
|
2249
2474
|
"data-testid": `filter-input-${field.name}`
|
|
@@ -2741,12 +2966,26 @@ var DefaultListFeature = class extends BaseFeature {
|
|
|
2741
2966
|
const listFields = this.listFieldNames ? filterFieldsByNames(this.fields || [], this.listFieldNames) : this.fields || [];
|
|
2742
2967
|
const listFieldNames = getFieldNamesFromFields(listFields);
|
|
2743
2968
|
const filterFields = this.filterSchema ? modelFieldsToFormFields(parseSchemaToFields(this.filterSchema)) : [];
|
|
2744
|
-
const columns = listFieldNames.map((fieldName) =>
|
|
2745
|
-
|
|
2746
|
-
label
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2969
|
+
const columns = listFieldNames.map((fieldName) => {
|
|
2970
|
+
const field = this.fields?.find((f) => f.name === fieldName);
|
|
2971
|
+
const label = getFieldLabelFromFields(this.fields || [], fieldName);
|
|
2972
|
+
const customRenderer = this.columnRenderers?.[fieldName];
|
|
2973
|
+
return {
|
|
2974
|
+
key: fieldName,
|
|
2975
|
+
label,
|
|
2976
|
+
render: (value, item) => {
|
|
2977
|
+
if (customRenderer) {
|
|
2978
|
+
return customRenderer({
|
|
2979
|
+
value,
|
|
2980
|
+
item,
|
|
2981
|
+
name: fieldName,
|
|
2982
|
+
label
|
|
2983
|
+
});
|
|
2984
|
+
}
|
|
2985
|
+
return ColumnRenderer(value, field);
|
|
2986
|
+
}
|
|
2987
|
+
};
|
|
2988
|
+
});
|
|
2750
2989
|
const model = context.model;
|
|
2751
2990
|
const prefix = context.prefix || "";
|
|
2752
2991
|
const basePath = `${prefix}/${model.modelName}`;
|
|
@@ -3809,11 +4048,11 @@ function SortableList(props) {
|
|
|
3809
4048
|
function StringArrayEditor(props) {
|
|
3810
4049
|
const {
|
|
3811
4050
|
value,
|
|
3812
|
-
name,
|
|
3813
4051
|
placeholder = "\u8BF7\u8F93\u5165\u5185\u5BB9",
|
|
3814
4052
|
allowEmpty = false,
|
|
3815
4053
|
rows = 1
|
|
3816
4054
|
} = props;
|
|
4055
|
+
const name = props.name;
|
|
3817
4056
|
const initialItems = value || [];
|
|
3818
4057
|
const initialDataJson = JSON.stringify({
|
|
3819
4058
|
items: initialItems.map((item) => item || ""),
|
|
@@ -3980,7 +4219,8 @@ function ArrayItem({
|
|
|
3980
4219
|
] });
|
|
3981
4220
|
}
|
|
3982
4221
|
function TagsEditor(props) {
|
|
3983
|
-
const { value,
|
|
4222
|
+
const { value, placeholder = "\u8F93\u5165\u6807\u7B7E\u540E\u6309\u56DE\u8F66\u6DFB\u52A0" } = props;
|
|
4223
|
+
const name = props.name;
|
|
3984
4224
|
const initialTags = value || [];
|
|
3985
4225
|
const initialDataJson = JSON.stringify({
|
|
3986
4226
|
tags: initialTags.map((tag) => tag || ""),
|
|
@@ -4264,7 +4504,7 @@ function ObjectEditor(props) {
|
|
|
4264
4504
|
const initialValueJson = JSON.stringify(initialObject);
|
|
4265
4505
|
JSON.stringify(fields.map((f) => f.name));
|
|
4266
4506
|
const generateField = (field) => {
|
|
4267
|
-
const fieldId = `${name}-${field.name}`;
|
|
4507
|
+
const fieldId = `${String(name)}-${field.name}`;
|
|
4268
4508
|
const fieldValue = initialObject[field.name];
|
|
4269
4509
|
const fieldValueStr = fieldValue === void 0 || fieldValue === null ? "" : typeof fieldValue === "object" ? JSON.stringify(fieldValue) : String(fieldValue);
|
|
4270
4510
|
const requiredAttr = field.required ? "required" : "";
|
|
@@ -5334,20 +5574,33 @@ var HtmxAdminPlugin = class {
|
|
|
5334
5574
|
};
|
|
5335
5575
|
|
|
5336
5576
|
exports.BaseFeature = BaseFeature;
|
|
5577
|
+
exports.BaseFormFeature = BaseFormFeature;
|
|
5578
|
+
exports.Breadcrumb = Breadcrumb;
|
|
5579
|
+
exports.Button = Button;
|
|
5580
|
+
exports.Card = Card;
|
|
5581
|
+
exports.ColumnRenderer = ColumnRenderer;
|
|
5337
5582
|
exports.CustomFeature = CustomFeature;
|
|
5338
5583
|
exports.DefaultCreateFeature = DefaultCreateFeature;
|
|
5339
5584
|
exports.DefaultDeleteFeature = DefaultDeleteFeature;
|
|
5340
5585
|
exports.DefaultDetailFeature = DefaultDetailFeature;
|
|
5341
5586
|
exports.DefaultEditFeature = DefaultEditFeature;
|
|
5342
5587
|
exports.DefaultListFeature = DefaultListFeature;
|
|
5588
|
+
exports.DetailFieldRenderer = DetailFieldRenderer;
|
|
5343
5589
|
exports.Dialog = Dialog;
|
|
5590
|
+
exports.EmptyState = EmptyState;
|
|
5344
5591
|
exports.ErrorAlert = ErrorAlert;
|
|
5592
|
+
exports.FilterForm = FilterForm;
|
|
5593
|
+
exports.Header = Header;
|
|
5345
5594
|
exports.HtmxAdminPlugin = HtmxAdminPlugin;
|
|
5346
5595
|
exports.LoadingBar = LoadingBar;
|
|
5347
5596
|
exports.ObjectEditor = ObjectEditor;
|
|
5348
5597
|
exports.PageModel = PageModel;
|
|
5598
|
+
exports.Pagination = Pagination;
|
|
5599
|
+
exports.PermissionDeniedContent = PermissionDeniedContent;
|
|
5600
|
+
exports.PermissionDeniedPage = PermissionDeniedPage;
|
|
5349
5601
|
exports.SortableList = SortableList;
|
|
5350
5602
|
exports.StringArrayEditor = StringArrayEditor;
|
|
5603
|
+
exports.Table = Table;
|
|
5351
5604
|
exports.TagsEditor = TagsEditor;
|
|
5352
5605
|
exports.checkUserPermission = checkUserPermission;
|
|
5353
5606
|
exports.getUserInfo = getUserInfo;
|