best-lowcode-runtime 0.2.6 → 0.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -0
- package/dist/dev.js +38 -11
- package/dist/dev.js.map +2 -2
- package/dist/index.js +285 -88
- package/dist/index.js.map +3 -3
- package/dist/lowcode/BestCrudPage.d.ts.map +1 -1
- package/dist/lowcode/dev.d.ts.map +1 -1
- package/dist/lowcode/index.d.ts +1 -1
- package/dist/lowcode/index.d.ts.map +1 -1
- package/dist/lowcode/schema.d.ts +46 -2
- package/dist/lowcode/schema.d.ts.map +1 -1
- package/dist/lowcode/validate.d.ts.map +1 -1
- package/dist/runtime/BestProvider.d.ts +4 -0
- package/dist/runtime/BestProvider.d.ts.map +1 -1
- package/dist/runtime/index.d.ts +2 -2
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/ui/BestDetail.d.ts +30 -1
- package/dist/ui/BestDetail.d.ts.map +1 -1
- package/dist/ui/BestOverlay.d.ts +4 -2
- package/dist/ui/BestOverlay.d.ts.map +1 -1
- package/dist/ui/index.d.ts +1 -1
- package/dist/ui/index.d.ts.map +1 -1
- package/dist/ui/types.d.ts +7 -0
- package/dist/ui/types.d.ts.map +1 -1
- package/package.json +7 -8
package/dist/index.js
CHANGED
|
@@ -34,12 +34,12 @@ function createBestCrudAdapter(options = {}) {
|
|
|
34
34
|
|
|
35
35
|
// src/lowcode/BestCrudPage.tsx
|
|
36
36
|
import { Button as Button4, Modal as Modal2, message } from "antd";
|
|
37
|
-
import
|
|
38
|
-
import { useCallback, useEffect as useEffect3, useLayoutEffect, useMemo as useMemo5, useRef as useRef3, useState as
|
|
37
|
+
import dayjs6 from "dayjs";
|
|
38
|
+
import { useCallback as useCallback2, useEffect as useEffect3, useLayoutEffect, useMemo as useMemo5, useRef as useRef3, useState as useState4 } from "react";
|
|
39
39
|
|
|
40
40
|
// src/runtime/BestProvider.tsx
|
|
41
41
|
import { ConfigProvider } from "antd";
|
|
42
|
-
import { createContext, useContext, useMemo } from "react";
|
|
42
|
+
import { createContext, useCallback, useContext, useMemo, useState } from "react";
|
|
43
43
|
import { jsx } from "react/jsx-runtime";
|
|
44
44
|
var emptyRegistry = {
|
|
45
45
|
listServices: {},
|
|
@@ -57,6 +57,7 @@ var defaultTheme = {
|
|
|
57
57
|
}
|
|
58
58
|
};
|
|
59
59
|
var BestRuntimeContext = createContext(emptyRegistry);
|
|
60
|
+
var BestDictionaryActionsContext = createContext(null);
|
|
60
61
|
function composeBestRegistry(...layers) {
|
|
61
62
|
const result = {
|
|
62
63
|
listServices: {},
|
|
@@ -87,12 +88,20 @@ function createBestRegistry(registry = {}) {
|
|
|
87
88
|
return composeBestRegistry(registry);
|
|
88
89
|
}
|
|
89
90
|
function BestProvider({ children, registry, theme }) {
|
|
90
|
-
const
|
|
91
|
+
const [dictionaryUpdates, setDictionaryUpdates] = useState({});
|
|
92
|
+
const setDictionary = useCallback((key, items) => {
|
|
93
|
+
setDictionaryUpdates((current) => ({ ...current, [key]: items }));
|
|
94
|
+
}, []);
|
|
95
|
+
const value = useMemo(() => {
|
|
96
|
+
const next = createBestRegistry(registry);
|
|
97
|
+
Object.assign(next.dictionaries, dictionaryUpdates);
|
|
98
|
+
return next;
|
|
99
|
+
}, [dictionaryUpdates, registry]);
|
|
91
100
|
const mergedTheme = useMemo(
|
|
92
101
|
() => ({ ...defaultTheme, ...theme, token: { ...defaultTheme.token, ...theme?.token } }),
|
|
93
102
|
[theme]
|
|
94
103
|
);
|
|
95
|
-
return /* @__PURE__ */ jsx(BestRuntimeContext.Provider, { value, children: /* @__PURE__ */ jsx(ConfigProvider, { theme: mergedTheme, children }) });
|
|
104
|
+
return /* @__PURE__ */ jsx(BestRuntimeContext.Provider, { value, children: /* @__PURE__ */ jsx(ConfigProvider, { theme: mergedTheme, children: /* @__PURE__ */ jsx(BestDictionaryActionsContext.Provider, { value: { setDictionary }, children }) }) });
|
|
96
105
|
}
|
|
97
106
|
function useBestRegistry() {
|
|
98
107
|
return useContext(BestRuntimeContext);
|
|
@@ -113,6 +122,11 @@ function useBestDictionary(key) {
|
|
|
113
122
|
const dictionaries = useBestRegistry().dictionaries;
|
|
114
123
|
return key ? dictionaries[key] ?? [] : [];
|
|
115
124
|
}
|
|
125
|
+
function useBestDictionaryActions() {
|
|
126
|
+
const actions = useContext(BestDictionaryActionsContext);
|
|
127
|
+
if (!actions) throw new Error("useBestDictionaryActions \u5FC5\u987B\u5728 BestProvider \u5185\u4F7F\u7528");
|
|
128
|
+
return actions;
|
|
129
|
+
}
|
|
116
130
|
function useBestAction(key) {
|
|
117
131
|
const action = useBestRegistry().actions[key];
|
|
118
132
|
if (!action) throw new Error(`\u672A\u6CE8\u518C\u52A8\u4F5C\uFF1A${key}`);
|
|
@@ -121,7 +135,7 @@ function useBestAction(key) {
|
|
|
121
135
|
|
|
122
136
|
// src/ui/BestBatchInput.tsx
|
|
123
137
|
import { Input } from "antd";
|
|
124
|
-
import { useImperativeHandle, useMemo as useMemo2, useState } from "react";
|
|
138
|
+
import { useImperativeHandle, useMemo as useMemo2, useState as useState2 } from "react";
|
|
125
139
|
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
126
140
|
function parse(value, separator) {
|
|
127
141
|
const escaped = separator.replace(/[\\\]\-^]/g, "\\$&");
|
|
@@ -136,7 +150,7 @@ function BestBatchInput({
|
|
|
136
150
|
onChange,
|
|
137
151
|
...props
|
|
138
152
|
}) {
|
|
139
|
-
const [innerValue, setInnerValue] =
|
|
153
|
+
const [innerValue, setInnerValue] = useState2(String(defaultValue ?? ""));
|
|
140
154
|
const currentValue = value == null ? innerValue : String(value);
|
|
141
155
|
const parsed = useMemo2(() => parse(currentValue, separator), [currentValue, separator]);
|
|
142
156
|
useImperativeHandle(ref, () => ({ getParsedValue: () => parsed }), [parsed]);
|
|
@@ -155,15 +169,66 @@ function BestBatchInput({
|
|
|
155
169
|
}
|
|
156
170
|
|
|
157
171
|
// src/ui/BestDetail.tsx
|
|
158
|
-
import { Descriptions } from "antd";
|
|
159
|
-
import
|
|
160
|
-
|
|
161
|
-
|
|
172
|
+
import { Descriptions, Empty, Table, Typography } from "antd";
|
|
173
|
+
import dayjs2 from "dayjs";
|
|
174
|
+
import { jsx as jsx3, jsxs } from "react/jsx-runtime";
|
|
175
|
+
function BestDetail({ fields, record = {}, column = 2, sections, sectionColumns, sectionGap = 20 }) {
|
|
176
|
+
const content = sections?.length ? /* @__PURE__ */ jsx3("div", { style: { display: "grid", gridTemplateColumns: `repeat(${sectionColumns ?? 1}, minmax(0, 1fr))`, gap: sectionGap }, children: sections.map((section) => {
|
|
177
|
+
const card = section.variant === "card";
|
|
178
|
+
return /* @__PURE__ */ jsxs("section", { style: { gridColumn: section.span ? `span ${section.span}` : void 0, marginBottom: 0, border: card ? "1px solid #f0f0f0" : void 0, borderRadius: card ? 6 : void 0, overflow: card ? "hidden" : void 0, background: card ? "#fff" : void 0 }, children: [
|
|
179
|
+
section.title ? /* @__PURE__ */ jsx3("div", { style: { padding: card ? "8px 12px" : void 0, background: card ? "#fafafa" : void 0, borderBottom: card ? "1px solid #f0f0f0" : void 0 }, children: /* @__PURE__ */ jsx3(Typography.Title, { level: 5, style: { margin: 0 }, children: section.title }) }) : null,
|
|
180
|
+
/* @__PURE__ */ jsxs("div", { style: { padding: card ? 12 : void 0 }, children: [
|
|
181
|
+
section.description ? /* @__PURE__ */ jsx3(Typography.Paragraph, { type: "secondary", children: section.description }) : null,
|
|
182
|
+
section.content,
|
|
183
|
+
section.fields ? /* @__PURE__ */ jsx3(FieldDescriptions, { fields: section.fields, record, column: section.columns ?? column }) : null,
|
|
184
|
+
section.table ? /* @__PURE__ */ jsx3(DetailTable, { table: section.table }) : null
|
|
185
|
+
] })
|
|
186
|
+
] }, section.key);
|
|
187
|
+
}) }) : /* @__PURE__ */ jsx3(FieldDescriptions, { fields, record, column });
|
|
188
|
+
return content;
|
|
189
|
+
}
|
|
190
|
+
function FieldDescriptions({ fields, record, column }) {
|
|
191
|
+
const visibleFields = fields.filter((field) => field.visible !== false);
|
|
192
|
+
return /* @__PURE__ */ jsx3(Descriptions, { bordered: true, column, size: "small", children: visibleFields.map((field) => {
|
|
162
193
|
const value = getPathValue(record, field.field);
|
|
163
|
-
const display = field.render ? field.render(value, record) : field.valueEnum?.[String(value)] ?? (value
|
|
194
|
+
const display = field.render ? field.render(value, record) : field.valueEnum?.[String(value)] ?? formatValue(value, field.format, field.emptyText);
|
|
164
195
|
return /* @__PURE__ */ jsx3(Descriptions.Item, { label: field.label, span: field.span, children: display }, field.field);
|
|
165
196
|
}) });
|
|
166
197
|
}
|
|
198
|
+
function DetailTable({ table }) {
|
|
199
|
+
if (!table.data.length) return /* @__PURE__ */ jsx3(Empty, { image: Empty.PRESENTED_IMAGE_SIMPLE, description: "\u6682\u65E0\u6570\u636E" });
|
|
200
|
+
return /* @__PURE__ */ jsx3(
|
|
201
|
+
Table,
|
|
202
|
+
{
|
|
203
|
+
size: "small",
|
|
204
|
+
bordered: true,
|
|
205
|
+
pagination: false,
|
|
206
|
+
rowKey: table.rowKey,
|
|
207
|
+
dataSource: table.data,
|
|
208
|
+
scroll: table.scrollX ? { x: table.scrollX } : void 0,
|
|
209
|
+
columns: table.columns.map((column) => ({ ...column, dataIndex: column.dataIndex ?? column.key }))
|
|
210
|
+
}
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
function formatValue(value, format, emptyText = "-") {
|
|
214
|
+
if (value == null || value === "") return emptyText;
|
|
215
|
+
const type = typeof format === "object" ? format.type : format;
|
|
216
|
+
if (!type || type === "text") return String(value);
|
|
217
|
+
if (type === "number") {
|
|
218
|
+
const number = Number(value);
|
|
219
|
+
if (!Number.isFinite(number)) return String(value);
|
|
220
|
+
const precision = typeof format === "object" ? format.precision : void 0;
|
|
221
|
+
return number.toLocaleString("zh-CN", precision === void 0 ? void 0 : { minimumFractionDigits: precision, maximumFractionDigits: precision });
|
|
222
|
+
}
|
|
223
|
+
if (type === "money") {
|
|
224
|
+
const number = Number(value);
|
|
225
|
+
return Number.isFinite(number) ? number.toLocaleString("zh-CN", { minimumFractionDigits: 2, maximumFractionDigits: 2 }) : String(value);
|
|
226
|
+
}
|
|
227
|
+
if (type === "boolean") return value ? "\u662F" : "\u5426";
|
|
228
|
+
if (type === "json") return typeof value === "string" ? value : JSON.stringify(value);
|
|
229
|
+
const date = dayjs2(value);
|
|
230
|
+
return date.isValid() ? date.format(type === "date" ? "YYYY-MM-DD" : "YYYY-MM-DD HH:mm:ss") : String(value);
|
|
231
|
+
}
|
|
167
232
|
function getPathValue(values, path) {
|
|
168
233
|
if (Object.hasOwn(values, path)) return values[path];
|
|
169
234
|
return path.split(".").reduce((current, part) => {
|
|
@@ -175,8 +240,8 @@ function getPathValue(values, path) {
|
|
|
175
240
|
}
|
|
176
241
|
|
|
177
242
|
// src/ui/BestFilePreview.tsx
|
|
178
|
-
import { Button, Image, List, Typography } from "antd";
|
|
179
|
-
import { jsx as jsx4, jsxs } from "react/jsx-runtime";
|
|
243
|
+
import { Button, Image, List, Typography as Typography2 } from "antd";
|
|
244
|
+
import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
180
245
|
function isImage(file) {
|
|
181
246
|
return file.mimeType?.startsWith("image/") || /\.(avif|bmp|gif|jpe?g|png|svg|webp)(?:$|[?#])/i.test(file.url);
|
|
182
247
|
}
|
|
@@ -185,7 +250,7 @@ function BestFilePreview({ files, onDownload }) {
|
|
|
185
250
|
List,
|
|
186
251
|
{
|
|
187
252
|
dataSource: files,
|
|
188
|
-
renderItem: (file) => /* @__PURE__ */
|
|
253
|
+
renderItem: (file) => /* @__PURE__ */ jsxs2(
|
|
189
254
|
List.Item,
|
|
190
255
|
{
|
|
191
256
|
actions: [
|
|
@@ -193,7 +258,7 @@ function BestFilePreview({ files, onDownload }) {
|
|
|
193
258
|
],
|
|
194
259
|
children: [
|
|
195
260
|
isImage(file) ? /* @__PURE__ */ jsx4(Image, { alt: file.name ?? "\u6587\u4EF6\u9884\u89C8", height: 48, preview: true, src: file.url, width: 48 }) : null,
|
|
196
|
-
/* @__PURE__ */ jsx4(
|
|
261
|
+
/* @__PURE__ */ jsx4(Typography2.Text, { ellipsis: true, style: { marginInlineStart: isImage(file) ? 12 : 0 }, children: file.name ?? file.url })
|
|
197
262
|
]
|
|
198
263
|
}
|
|
199
264
|
)
|
|
@@ -203,9 +268,9 @@ function BestFilePreview({ files, onDownload }) {
|
|
|
203
268
|
|
|
204
269
|
// src/ui/BestForm.tsx
|
|
205
270
|
import { Button as Button2, DatePicker, Form, Input as Input2, InputNumber, Select, Space } from "antd";
|
|
206
|
-
import
|
|
207
|
-
import { useEffect, useMemo as useMemo3, useRef, useState as
|
|
208
|
-
import { Fragment, jsx as jsx5, jsxs as
|
|
271
|
+
import dayjs3 from "dayjs";
|
|
272
|
+
import { useEffect, useMemo as useMemo3, useRef, useState as useState3 } from "react";
|
|
273
|
+
import { Fragment, jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
209
274
|
function toNamePath(path) {
|
|
210
275
|
return path === void 0 ? [] : Array.isArray(path) ? path : [path];
|
|
211
276
|
}
|
|
@@ -216,7 +281,7 @@ function isRecord(value) {
|
|
|
216
281
|
if (!value || typeof value !== "object" || Array.isArray(value) || value instanceof Date) {
|
|
217
282
|
return false;
|
|
218
283
|
}
|
|
219
|
-
if (
|
|
284
|
+
if (dayjs3.isDayjs(value)) return false;
|
|
220
285
|
const prototype = Object.getPrototypeOf(value);
|
|
221
286
|
return prototype === Object.prototype || prototype === null;
|
|
222
287
|
}
|
|
@@ -238,17 +303,17 @@ function resolveFieldDisabled(field, values, mode) {
|
|
|
238
303
|
return field.disabled || Boolean(field.disabledWhen && evaluateCondition(field.disabledWhen, values, mode));
|
|
239
304
|
}
|
|
240
305
|
function toDayjsValue(value) {
|
|
241
|
-
if (
|
|
242
|
-
if (value instanceof Date) return
|
|
306
|
+
if (dayjs3.isDayjs(value)) return value;
|
|
307
|
+
if (value instanceof Date) return dayjs3(value);
|
|
243
308
|
if (typeof value === "number") {
|
|
244
309
|
const normalized = Math.abs(value) >= 1e12 ? value : value * 1e3;
|
|
245
|
-
const parsed =
|
|
310
|
+
const parsed = dayjs3(normalized);
|
|
246
311
|
return parsed.isValid() ? parsed : null;
|
|
247
312
|
}
|
|
248
313
|
if (typeof value === "string") {
|
|
249
314
|
const trimmed = value.trim();
|
|
250
315
|
if (!trimmed) return null;
|
|
251
|
-
const parsed =
|
|
316
|
+
const parsed = dayjs3(trimmed);
|
|
252
317
|
return parsed.isValid() ? parsed : null;
|
|
253
318
|
}
|
|
254
319
|
return null;
|
|
@@ -342,7 +407,7 @@ function FormControl({
|
|
|
342
407
|
value: toDatePickerValue(value),
|
|
343
408
|
onChange: (date, dateString) => onChange?.(serializeDatePickerValue(date, dateString)),
|
|
344
409
|
disabled: field.disabled,
|
|
345
|
-
disabledDate: (current) => field.maxDate === "today" && current.isAfter(
|
|
410
|
+
disabledDate: (current) => field.maxDate === "today" && current.isAfter(dayjs3(), "day"),
|
|
346
411
|
style: { width: "100%" }
|
|
347
412
|
}
|
|
348
413
|
);
|
|
@@ -354,7 +419,7 @@ function FormControl({
|
|
|
354
419
|
value: toDateRangePickerValue(value),
|
|
355
420
|
onChange: (dates, dateStrings) => onChange?.(serializeDateRangePickerValue(dates, dateStrings)),
|
|
356
421
|
disabled: field.disabled,
|
|
357
|
-
disabledDate: (current) => field.maxDate === "today" && current.isAfter(
|
|
422
|
+
disabledDate: (current) => field.maxDate === "today" && current.isAfter(dayjs3(), "day"),
|
|
358
423
|
style: { width: "100%" }
|
|
359
424
|
}
|
|
360
425
|
);
|
|
@@ -413,7 +478,7 @@ function RepeatableField({
|
|
|
413
478
|
values
|
|
414
479
|
}) {
|
|
415
480
|
const listName = namePath ?? field.field;
|
|
416
|
-
return /* @__PURE__ */ jsx5(Form.List, { name: listName, children: (items, { add, remove }) => /* @__PURE__ */
|
|
481
|
+
return /* @__PURE__ */ jsx5(Form.List, { name: listName, children: (items, { add, remove }) => /* @__PURE__ */ jsxs3(Fragment, { children: [
|
|
417
482
|
items.map((item) => /* @__PURE__ */ jsx5(
|
|
418
483
|
RepeatableFieldRow,
|
|
419
484
|
{
|
|
@@ -463,7 +528,7 @@ function RepeatableFieldRow({
|
|
|
463
528
|
}
|
|
464
529
|
});
|
|
465
530
|
}, [field.itemFields, form, itemPath, mode, scopeValues, values]);
|
|
466
|
-
return /* @__PURE__ */
|
|
531
|
+
return /* @__PURE__ */ jsxs3(Space, { align: "start", children: [
|
|
467
532
|
field.itemFields?.map((itemField) => {
|
|
468
533
|
if (!isFieldVisible(itemField, scopeValues, mode)) return null;
|
|
469
534
|
const nextPath = appendNamePath(itemPath, itemField.field);
|
|
@@ -571,10 +636,10 @@ function RemoteSelect({
|
|
|
571
636
|
onChange,
|
|
572
637
|
registry
|
|
573
638
|
}) {
|
|
574
|
-
const [keywordOptions, setKeywordOptions] =
|
|
575
|
-
const [selectedOptions, setSelectedOptions] =
|
|
576
|
-
const [loading, setLoading] =
|
|
577
|
-
const [keyword, setKeyword] =
|
|
639
|
+
const [keywordOptions, setKeywordOptions] = useState3([]);
|
|
640
|
+
const [selectedOptions, setSelectedOptions] = useState3([]);
|
|
641
|
+
const [loading, setLoading] = useState3(false);
|
|
642
|
+
const [keyword, setKeyword] = useState3("");
|
|
578
643
|
const keywordRequestId = useRef(0);
|
|
579
644
|
const selectedRequestId = useRef(0);
|
|
580
645
|
const service = field.remoteService ? registry.services[field.remoteService] : void 0;
|
|
@@ -729,9 +794,9 @@ function BestFormBody({
|
|
|
729
794
|
onCancel
|
|
730
795
|
}) {
|
|
731
796
|
const [form] = Form.useForm();
|
|
732
|
-
return /* @__PURE__ */
|
|
797
|
+
return /* @__PURE__ */ jsxs3(Form, { form, initialValues, layout: "vertical", onFinish: onSubmit, children: [
|
|
733
798
|
/* @__PURE__ */ jsx5(FormFields, { fields, form, initialValues, mode }),
|
|
734
|
-
/* @__PURE__ */
|
|
799
|
+
/* @__PURE__ */ jsxs3(Space, { children: [
|
|
735
800
|
/* @__PURE__ */ jsx5(Button2, { htmlType: "submit", loading, type: "primary", children: submitText }),
|
|
736
801
|
onCancel ? /* @__PURE__ */ jsx5(Button2, { onClick: onCancel, children: "\u53D6\u6D88" }) : null,
|
|
737
802
|
extra
|
|
@@ -793,7 +858,7 @@ function evaluateCondition(condition, values, mode) {
|
|
|
793
858
|
}
|
|
794
859
|
|
|
795
860
|
// src/ui/BestLightTable.tsx
|
|
796
|
-
import { Table } from "antd";
|
|
861
|
+
import { Table as Table2 } from "antd";
|
|
797
862
|
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
798
863
|
function BestLightTable({
|
|
799
864
|
columns,
|
|
@@ -808,7 +873,7 @@ function BestLightTable({
|
|
|
808
873
|
render: column.render
|
|
809
874
|
}));
|
|
810
875
|
return /* @__PURE__ */ jsx6(
|
|
811
|
-
|
|
876
|
+
Table2,
|
|
812
877
|
{
|
|
813
878
|
columns: tableColumns,
|
|
814
879
|
dataSource: data,
|
|
@@ -822,18 +887,18 @@ function BestLightTable({
|
|
|
822
887
|
// src/ui/BestOverlay.tsx
|
|
823
888
|
import { Drawer, Modal } from "antd";
|
|
824
889
|
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
825
|
-
function BestDrawer({ children, open, title, onClose }) {
|
|
826
|
-
return /* @__PURE__ */ jsx7(Drawer, { destroyOnHidden: true, open, title, width: 640, onClose, children });
|
|
890
|
+
function BestDrawer({ children, open, title, onClose, width, footer }) {
|
|
891
|
+
return /* @__PURE__ */ jsx7(Drawer, { destroyOnHidden: true, open, title, width: width ?? 640, footer, onClose, children });
|
|
827
892
|
}
|
|
828
|
-
function BestModal({ children, open, title, onClose }) {
|
|
829
|
-
return /* @__PURE__ */ jsx7(Modal, { destroyOnHidden: true, footer: null, open, title, onCancel: onClose, children });
|
|
893
|
+
function BestModal({ children, open, title, onClose, width, footer }) {
|
|
894
|
+
return /* @__PURE__ */ jsx7(Modal, { destroyOnHidden: true, footer: footer ?? null, open, title, width, onCancel: onClose, children });
|
|
830
895
|
}
|
|
831
896
|
|
|
832
897
|
// src/ui/BestSearch.tsx
|
|
833
898
|
import { Button as Button3, Col, DatePicker as DatePicker2, Form as Form2, Input as Input3, InputNumber as InputNumber2, Row, Select as Select2 } from "antd";
|
|
834
|
-
import
|
|
899
|
+
import dayjs4 from "dayjs";
|
|
835
900
|
import { useEffect as useEffect2, useMemo as useMemo4, useRef as useRef2 } from "react";
|
|
836
|
-
import { jsx as jsx8, jsxs as
|
|
901
|
+
import { jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
837
902
|
function searchFormSignature(fields, initialValues) {
|
|
838
903
|
return JSON.stringify([
|
|
839
904
|
fields.map((field) => ({
|
|
@@ -898,7 +963,7 @@ function FieldControl({ field, value, onChange, ...controlProps }) {
|
|
|
898
963
|
value: toDatePickerValue(value),
|
|
899
964
|
onChange: (date, dateString) => onChange?.(serializeDatePickerValue(date, dateString)),
|
|
900
965
|
disabled: field.disabled,
|
|
901
|
-
disabledDate: (current) => field.maxDate === "today" && current.isAfter(
|
|
966
|
+
disabledDate: (current) => field.maxDate === "today" && current.isAfter(dayjs4(), "day"),
|
|
902
967
|
placeholder: field.placeholder,
|
|
903
968
|
style: { width: "100%" }
|
|
904
969
|
}
|
|
@@ -911,7 +976,7 @@ function FieldControl({ field, value, onChange, ...controlProps }) {
|
|
|
911
976
|
value: toDateRangePickerValue(value),
|
|
912
977
|
onChange: (dates, dateStrings) => onChange?.(serializeDateRangePickerValue(dates, dateStrings)),
|
|
913
978
|
disabled: field.disabled,
|
|
914
|
-
disabledDate: (current) => field.maxDate === "today" && current.isAfter(
|
|
979
|
+
disabledDate: (current) => field.maxDate === "today" && current.isAfter(dayjs4(), "day"),
|
|
915
980
|
style: { width: "100%" }
|
|
916
981
|
}
|
|
917
982
|
);
|
|
@@ -1013,9 +1078,9 @@ function BestSearchBody({
|
|
|
1013
1078
|
onFinish: (values) => onSearch(values),
|
|
1014
1079
|
onValuesChange: (_, values) => onChange?.(values),
|
|
1015
1080
|
className: "best-lowcode-search",
|
|
1016
|
-
children: /* @__PURE__ */
|
|
1081
|
+
children: /* @__PURE__ */ jsxs4(Row, { gutter: 16, align: "bottom", children: [
|
|
1017
1082
|
fields.filter((field) => !field.hidden).map((field) => /* @__PURE__ */ jsx8(Col, { span: field.span ?? 6, children: /* @__PURE__ */ jsx8(Form2.Item, { label: field.label, name: field.field, rules: toAntRules(field.rules), children: /* @__PURE__ */ jsx8(FieldControl, { field }) }) }, field.field)),
|
|
1018
|
-
/* @__PURE__ */ jsx8(Col, { children: /* @__PURE__ */
|
|
1083
|
+
/* @__PURE__ */ jsx8(Col, { children: /* @__PURE__ */ jsxs4(Form2.Item, { children: [
|
|
1019
1084
|
/* @__PURE__ */ jsx8(Button3, { htmlType: "submit", loading, type: "primary", children: submitText }),
|
|
1020
1085
|
/* @__PURE__ */ jsx8(
|
|
1021
1086
|
Button3,
|
|
@@ -1038,13 +1103,13 @@ function BestSearchBody({
|
|
|
1038
1103
|
}
|
|
1039
1104
|
|
|
1040
1105
|
// src/ui/BestStates.tsx
|
|
1041
|
-
import { Empty, Result, Spin } from "antd";
|
|
1106
|
+
import { Empty as Empty2, Result, Spin } from "antd";
|
|
1042
1107
|
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
1043
1108
|
function BestLoading({ description = "\u52A0\u8F7D\u4E2D" }) {
|
|
1044
1109
|
return /* @__PURE__ */ jsx9("div", { style: { display: "grid", minHeight: 160, placeItems: "center" }, children: /* @__PURE__ */ jsx9(Spin, { tip: description }) });
|
|
1045
1110
|
}
|
|
1046
1111
|
function BestEmpty({ description = "\u6682\u65E0\u6570\u636E" }) {
|
|
1047
|
-
return /* @__PURE__ */ jsx9(
|
|
1112
|
+
return /* @__PURE__ */ jsx9(Empty2, { description });
|
|
1048
1113
|
}
|
|
1049
1114
|
function BestError({ description = "\u52A0\u8F7D\u5931\u8D25" }) {
|
|
1050
1115
|
return /* @__PURE__ */ jsx9(Result, { status: "error", title: description });
|
|
@@ -1095,9 +1160,9 @@ function BestTable({
|
|
|
1095
1160
|
}
|
|
1096
1161
|
|
|
1097
1162
|
// src/lowcode/runtime.ts
|
|
1098
|
-
import
|
|
1163
|
+
import dayjs5 from "dayjs";
|
|
1099
1164
|
import utc from "dayjs/plugin/utc.js";
|
|
1100
|
-
|
|
1165
|
+
dayjs5.extend(utc);
|
|
1101
1166
|
function toBestListQuery(params, sort) {
|
|
1102
1167
|
const { current, pageSize, ...filters } = params;
|
|
1103
1168
|
const normalizedSort = Object.fromEntries(
|
|
@@ -1130,7 +1195,7 @@ function formatCrudValue(value, format) {
|
|
|
1130
1195
|
const numericValue = typeof value === "number" ? value : Number(value.trim());
|
|
1131
1196
|
timestamp = Number.isFinite(numericValue) && numericValue !== 0 ? Math.abs(numericValue) >= 1e12 ? numericValue : numericValue * 1e3 : value;
|
|
1132
1197
|
}
|
|
1133
|
-
const date =
|
|
1198
|
+
const date = dayjs5.utc(timestamp);
|
|
1134
1199
|
if (!date.isValid()) return String(value);
|
|
1135
1200
|
return date.format(format === "date" ? "YYYY-MM-DD" : "YYYY-MM-DD HH:mm:ss");
|
|
1136
1201
|
}
|
|
@@ -1205,9 +1270,11 @@ var builtInEffects = /* @__PURE__ */ new Set([
|
|
|
1205
1270
|
"openEdit",
|
|
1206
1271
|
"remove",
|
|
1207
1272
|
"runAction",
|
|
1208
|
-
"slot"
|
|
1273
|
+
"slot",
|
|
1274
|
+
"closeDetail"
|
|
1209
1275
|
]);
|
|
1210
1276
|
var columnFormats = /* @__PURE__ */ new Set(["date", "datetime", "money", "text"]);
|
|
1277
|
+
var detailFormats = /* @__PURE__ */ new Set(["text", "number", "money", "date", "datetime", "boolean", "json"]);
|
|
1211
1278
|
function push(diagnostics, path, code, message2) {
|
|
1212
1279
|
diagnostics.push({ path, code, message: message2 });
|
|
1213
1280
|
}
|
|
@@ -1254,6 +1321,14 @@ function validateCondition(condition, path, diagnostics) {
|
|
|
1254
1321
|
}
|
|
1255
1322
|
push(diagnostics, path, "condition.operator", `\u4E0D\u652F\u6301\u7684\u6761\u4EF6\uFF1A${condition.operator}`);
|
|
1256
1323
|
}
|
|
1324
|
+
function validateDetailField(field, path, registry, diagnostics) {
|
|
1325
|
+
if (field.visibleWhen) validateCondition(field.visibleWhen, `${path}/visibleWhen`, diagnostics);
|
|
1326
|
+
if (field.slot && registry && !registry.slots[field.slot])
|
|
1327
|
+
push(diagnostics, `${path}/slot`, "registry.slot", `\u672A\u6CE8\u518C\u63D2\u69FD\uFF1A${field.slot}`);
|
|
1328
|
+
const format = typeof field.format === "object" ? field.format.type : field.format;
|
|
1329
|
+
if (format && !detailFormats.has(format))
|
|
1330
|
+
push(diagnostics, `${path}/format`, "detail.format", `\u4E0D\u652F\u6301\u7684\u8BE6\u60C5\u683C\u5F0F\uFF1A${format}`);
|
|
1331
|
+
}
|
|
1257
1332
|
function validateFields(fields, path, registry, diagnostics) {
|
|
1258
1333
|
const seen = /* @__PURE__ */ new Set();
|
|
1259
1334
|
fields?.forEach((field, index) => {
|
|
@@ -1407,17 +1482,26 @@ function validateCrudPageSchema(schema, registry) {
|
|
|
1407
1482
|
}
|
|
1408
1483
|
});
|
|
1409
1484
|
if (schema.detail !== void 0) {
|
|
1410
|
-
if (!schema.detail || typeof schema.detail !== "object" || !Array.isArray(schema.detail.fields)) {
|
|
1411
|
-
push(diagnostics, "/detail", "detail.type", "detail \u5FC5\u987B\u5305\u542B fields \
|
|
1485
|
+
if (!schema.detail || typeof schema.detail !== "object" || schema.detail.fields !== void 0 && !Array.isArray(schema.detail.fields) || schema.detail.sections !== void 0 && !Array.isArray(schema.detail.sections)) {
|
|
1486
|
+
push(diagnostics, "/detail", "detail.type", "detail \u5FC5\u987B\u5305\u542B fields \u6216 sections \u6570\u7EC4");
|
|
1412
1487
|
} else {
|
|
1413
|
-
schema.detail.fields
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
);
|
|
1488
|
+
schema.detail.fields?.forEach((field, index) => validateDetailField(field, `/detail/fields/${index}`, registry, diagnostics));
|
|
1489
|
+
schema.detail.sections?.forEach((section, index) => {
|
|
1490
|
+
if (section.visibleWhen) validateCondition(section.visibleWhen, `/detail/sections/${index}/visibleWhen`, diagnostics);
|
|
1491
|
+
if (!section.key) push(diagnostics, `/detail/sections/${index}/key`, "detail.section.key", "\u8BE6\u60C5\u533A\u5757\u5FC5\u987B\u6307\u5B9A key");
|
|
1492
|
+
if (section.span !== void 0 && (!Number.isInteger(section.span) || section.span < 1))
|
|
1493
|
+
push(diagnostics, `/detail/sections/${index}/span`, "detail.section.span", "\u8BE6\u60C5\u533A\u5757 span \u5FC5\u987B\u662F\u6B63\u6574\u6570");
|
|
1494
|
+
if (section.columns !== void 0 && (!Number.isInteger(section.columns) || section.columns < 1))
|
|
1495
|
+
push(diagnostics, `/detail/sections/${index}/columns`, "detail.section.columns", "\u8BE6\u60C5\u5B57\u6BB5 columns \u5FC5\u987B\u662F\u6B63\u6574\u6570");
|
|
1496
|
+
if (section.layout === "slot" && !section.slot)
|
|
1497
|
+
push(diagnostics, `/detail/sections/${index}/slot`, "detail.slot", "slot \u533A\u5757\u5FC5\u987B\u6307\u5B9A slot");
|
|
1498
|
+
if (section.layout === "table" && !section.table)
|
|
1499
|
+
push(diagnostics, `/detail/sections/${index}/table`, "detail.table", "table \u533A\u5757\u5FC5\u987B\u6307\u5B9A table");
|
|
1500
|
+
if (section.table && typeof section.table.data !== "string")
|
|
1501
|
+
push(diagnostics, `/detail/sections/${index}/table/data`, "detail.table.data", "\u8BE6\u60C5\u8868\u683C data \u5FC5\u987B\u662F\u5B57\u6BB5\u8DEF\u5F84");
|
|
1502
|
+
if (section.slot && registry && !registry.slots[section.slot])
|
|
1503
|
+
push(diagnostics, `/detail/sections/${index}/slot`, "registry.slot", `\u672A\u6CE8\u518C\u63D2\u69FD\uFF1A${section.slot}`);
|
|
1504
|
+
section.fields?.forEach((field, fieldIndex) => validateDetailField(field, `/detail/sections/${index}/fields/${fieldIndex}`, registry, diagnostics));
|
|
1421
1505
|
});
|
|
1422
1506
|
}
|
|
1423
1507
|
}
|
|
@@ -1435,6 +1519,13 @@ function validateCrudPageSchema(schema, registry) {
|
|
|
1435
1519
|
Boolean(schema.dataSource?.remove),
|
|
1436
1520
|
diagnostics
|
|
1437
1521
|
);
|
|
1522
|
+
validateActions(
|
|
1523
|
+
schema.detail?.footer,
|
|
1524
|
+
"/detail/footer",
|
|
1525
|
+
registry,
|
|
1526
|
+
Boolean(schema.dataSource?.remove),
|
|
1527
|
+
diagnostics
|
|
1528
|
+
);
|
|
1438
1529
|
return { valid: diagnostics.length === 0, diagnostics };
|
|
1439
1530
|
}
|
|
1440
1531
|
function assertValidCrudPageSchema(schema, registry) {
|
|
@@ -1486,7 +1577,7 @@ ${message2}`);
|
|
|
1486
1577
|
}
|
|
1487
1578
|
|
|
1488
1579
|
// src/lowcode/BestCrudPage.tsx
|
|
1489
|
-
import { Fragment as Fragment2, jsx as jsx11, jsxs as
|
|
1580
|
+
import { Fragment as Fragment2, jsx as jsx11, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1490
1581
|
function pickRowKeyValues(record, rowKey) {
|
|
1491
1582
|
if (!record) return {};
|
|
1492
1583
|
const keys = Array.isArray(rowKey) ? rowKey : [rowKey];
|
|
@@ -1559,7 +1650,7 @@ function useFields(fields = []) {
|
|
|
1559
1650
|
const registry = useBestRegistry();
|
|
1560
1651
|
return fields.map((field) => toFieldDefinition(field, registry.dictionaries, registry.slots));
|
|
1561
1652
|
}
|
|
1562
|
-
function toDetailField(field, dictionary, slots) {
|
|
1653
|
+
function toDetailField(field, dictionary, slots, record = {}) {
|
|
1563
1654
|
const slot = field.slot;
|
|
1564
1655
|
const valueEnum = field.dict ? Object.fromEntries(
|
|
1565
1656
|
(dictionary[field.dict] ?? []).map((item) => [String(item.value), item.label])
|
|
@@ -1568,10 +1659,50 @@ function toDetailField(field, dictionary, slots) {
|
|
|
1568
1659
|
field: field.field,
|
|
1569
1660
|
label: field.label,
|
|
1570
1661
|
span: field.span,
|
|
1662
|
+
format: field.format,
|
|
1663
|
+
emptyText: field.emptyText,
|
|
1664
|
+
visible: !field.visibleWhen || evaluateCondition(field.visibleWhen, record, "detail"),
|
|
1571
1665
|
valueEnum,
|
|
1572
|
-
render: slot ? (value,
|
|
1666
|
+
render: slot ? (value, record2) => slots[slot]?.({ field: field.field, record: record2, value }) ?? "-" : void 0
|
|
1573
1667
|
};
|
|
1574
1668
|
}
|
|
1669
|
+
function getPathValue3(values, path) {
|
|
1670
|
+
if (Object.hasOwn(values, path)) return values[path];
|
|
1671
|
+
return path.split(".").reduce((current, part) => {
|
|
1672
|
+
if (current && typeof current === "object") return current[part];
|
|
1673
|
+
return void 0;
|
|
1674
|
+
}, values);
|
|
1675
|
+
}
|
|
1676
|
+
function toDetailSection(section, record, dictionaries, slots) {
|
|
1677
|
+
if (section.visibleWhen && !evaluateCondition(section.visibleWhen, record, "detail")) return null;
|
|
1678
|
+
const fields = section.fields?.map((field) => toDetailField(field, dictionaries, slots, record));
|
|
1679
|
+
const table = section.table ? {
|
|
1680
|
+
key: section.key,
|
|
1681
|
+
data: getPathValue3(record, section.table.data) ?? [],
|
|
1682
|
+
rowKey: section.table.rowKey,
|
|
1683
|
+
scrollX: section.table.scrollX,
|
|
1684
|
+
columns: section.table.columns.map((column) => ({
|
|
1685
|
+
key: column.field,
|
|
1686
|
+
title: column.title,
|
|
1687
|
+
dataIndex: column.field,
|
|
1688
|
+
width: column.width,
|
|
1689
|
+
fixed: column.fixed,
|
|
1690
|
+
render: (value, row) => {
|
|
1691
|
+
if (column.slot) return slots[column.slot]?.({ field: column.field, record: row, value }) ?? "-";
|
|
1692
|
+
if (column.dict) {
|
|
1693
|
+
const item = (dictionaries[column.dict] ?? []).find((candidate) => candidate.value === value);
|
|
1694
|
+
if (item) return item.label;
|
|
1695
|
+
}
|
|
1696
|
+
const format = column.format;
|
|
1697
|
+
if (format === "date" || format === "datetime") return formatCrudValue(value, format);
|
|
1698
|
+
if (format === "money") return formatCrudValue(value, format);
|
|
1699
|
+
return value == null || value === "" ? "-" : String(value);
|
|
1700
|
+
}
|
|
1701
|
+
}))
|
|
1702
|
+
} : void 0;
|
|
1703
|
+
const content = section.layout === "slot" && section.slot ? slots[section.slot]?.({ record }) : void 0;
|
|
1704
|
+
return { key: section.key, title: section.title, description: section.description, columns: section.columns, span: section.span, variant: section.variant, fields, table, content };
|
|
1705
|
+
}
|
|
1575
1706
|
function toTableColumn(column, dictionary, slots) {
|
|
1576
1707
|
const slot = column.slot;
|
|
1577
1708
|
const valueEnum = column.dict ? Object.fromEntries(
|
|
@@ -1617,7 +1748,7 @@ function toProTableSearchColumn(field, dictionary) {
|
|
|
1617
1748
|
initialValue: field.defaultValue,
|
|
1618
1749
|
fieldProps: {
|
|
1619
1750
|
...options ? { options } : {},
|
|
1620
|
-
...field.maxDate === "today" ? { disabledDate: (current) => current.isAfter(
|
|
1751
|
+
...field.maxDate === "today" ? { disabledDate: (current) => current.isAfter(dayjs6(), "day") } : {}
|
|
1621
1752
|
}
|
|
1622
1753
|
};
|
|
1623
1754
|
}
|
|
@@ -1637,7 +1768,7 @@ function BestCrudPage({ adapter, className, schema }) {
|
|
|
1637
1768
|
assertValidCrudPageSchema(schema, registry);
|
|
1638
1769
|
const registeredListService = useBestListService(schema.dataSource.list);
|
|
1639
1770
|
if (!registeredListService) throw new Error(`\u672A\u6CE8\u518C\u5217\u8868\u670D\u52A1\uFF1A${schema.dataSource.list}`);
|
|
1640
|
-
const listService =
|
|
1771
|
+
const listService = useCallback2(
|
|
1641
1772
|
async (query2, options) => {
|
|
1642
1773
|
const response = await registeredListService(query2, options);
|
|
1643
1774
|
return adapter?.fromList ? { ...response, items: adapter.fromList(response.items) } : response;
|
|
@@ -1663,22 +1794,52 @@ function BestCrudPage({ adapter, className, schema }) {
|
|
|
1663
1794
|
),
|
|
1664
1795
|
[searchFields]
|
|
1665
1796
|
);
|
|
1666
|
-
const [query, setQuery] =
|
|
1797
|
+
const [query, setQuery] = useState4(searchDefaultValues);
|
|
1667
1798
|
const queryRef = useRef3(searchDefaultValues);
|
|
1668
1799
|
const queryStateRef = useRef3({
|
|
1669
1800
|
schemaId: schema.id,
|
|
1670
1801
|
searchSchemaSignature,
|
|
1671
1802
|
userTouched: false
|
|
1672
1803
|
});
|
|
1673
|
-
const [drawer, setDrawer] =
|
|
1674
|
-
const [
|
|
1804
|
+
const [drawer, setDrawer] = useState4({ mode: "closed" });
|
|
1805
|
+
const [detailState, setDetailState] = useState4({ loading: false });
|
|
1806
|
+
const detailRequestRef = useRef3(void 0);
|
|
1807
|
+
const [submitting, setSubmitting] = useState4(false);
|
|
1675
1808
|
const submittingRef = useRef3(false);
|
|
1676
|
-
const handleAction =
|
|
1809
|
+
const handleAction = useCallback2(
|
|
1677
1810
|
async (action, record) => {
|
|
1678
1811
|
if (action.access && !registry.access(action.access)) return;
|
|
1812
|
+
if (action.effect === "closeDetail") {
|
|
1813
|
+
detailRequestRef.current?.abort();
|
|
1814
|
+
setDrawer({ mode: "closed" });
|
|
1815
|
+
setDetailState({ loading: false });
|
|
1816
|
+
return;
|
|
1817
|
+
}
|
|
1679
1818
|
if (action.effect !== "remove" && !await confirmBeforeAction(action.confirm, confirmAction))
|
|
1680
1819
|
return;
|
|
1681
|
-
if (action.effect === "openDetail")
|
|
1820
|
+
if (action.effect === "openDetail") {
|
|
1821
|
+
detailRequestRef.current?.abort();
|
|
1822
|
+
const controller = new AbortController();
|
|
1823
|
+
detailRequestRef.current = controller;
|
|
1824
|
+
setDrawer({ mode: "detail", record });
|
|
1825
|
+
setDetailState({ loading: Boolean(schema.dataSource.detail), record });
|
|
1826
|
+
if (schema.dataSource.detail) {
|
|
1827
|
+
const detailService = registry.services[schema.dataSource.detail];
|
|
1828
|
+
if (!detailService) {
|
|
1829
|
+
setDetailState({ loading: false, error: new Error(`\u672A\u6CE8\u518C\u670D\u52A1\uFF1A${schema.dataSource.detail}`), record });
|
|
1830
|
+
return;
|
|
1831
|
+
}
|
|
1832
|
+
try {
|
|
1833
|
+
const detail = await detailService(record ?? {}, { signal: controller.signal });
|
|
1834
|
+
if (controller.signal.aborted) return;
|
|
1835
|
+
const normalized = isRecord2(detail) ? adapter?.fromDetail ? adapter.fromDetail(detail) : detail : record ?? {};
|
|
1836
|
+
setDetailState({ loading: false, record: normalized });
|
|
1837
|
+
setDrawer({ mode: "detail", record: normalized });
|
|
1838
|
+
} catch (error) {
|
|
1839
|
+
if (!controller.signal.aborted) setDetailState({ loading: false, error, record });
|
|
1840
|
+
}
|
|
1841
|
+
}
|
|
1842
|
+
}
|
|
1682
1843
|
if (action.effect === "openEdit") {
|
|
1683
1844
|
let editRecord = record;
|
|
1684
1845
|
if (schema.dataSource.detail) {
|
|
@@ -1781,7 +1942,7 @@ function BestCrudPage({ adapter, className, schema }) {
|
|
|
1781
1942
|
[listService, schema.title]
|
|
1782
1943
|
);
|
|
1783
1944
|
const rowKey = schema.table.rowKey;
|
|
1784
|
-
const request =
|
|
1945
|
+
const request = useCallback2(
|
|
1785
1946
|
(params, sort) => pageRequest.request(
|
|
1786
1947
|
toBestListQuery({ ...params, ...useBestSearch ? queryRef.current : {} }, sort)
|
|
1787
1948
|
),
|
|
@@ -1804,7 +1965,7 @@ function BestCrudPage({ adapter, className, schema }) {
|
|
|
1804
1965
|
};
|
|
1805
1966
|
}, [schema.id, searchDefaultValues, searchFieldNames, searchSchemaSignature]);
|
|
1806
1967
|
useEffect3(() => () => pageRequest.abort(), [pageRequest]);
|
|
1807
|
-
const submitForm =
|
|
1968
|
+
const submitForm = useCallback2(
|
|
1808
1969
|
async (values) => {
|
|
1809
1970
|
if (submittingRef.current) return;
|
|
1810
1971
|
const serviceKey = drawer.mode === "edit" ? schema.dataSource.update : schema.dataSource.create;
|
|
@@ -1844,7 +2005,7 @@ function BestCrudPage({ adapter, className, schema }) {
|
|
|
1844
2005
|
schema.dataSource.update
|
|
1845
2006
|
]
|
|
1846
2007
|
);
|
|
1847
|
-
return /* @__PURE__ */
|
|
2008
|
+
return /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
1848
2009
|
useBestSearch && searchFields.length ? /* @__PURE__ */ jsx11(
|
|
1849
2010
|
BestSearch,
|
|
1850
2011
|
{
|
|
@@ -1879,22 +2040,41 @@ function BestCrudPage({ adapter, className, schema }) {
|
|
|
1879
2040
|
toolBarRender: () => schema.toolbar?.map((action) => /* @__PURE__ */ jsx11(ActionButton, { action, onExecute: handleAction }, action.id)) ?? []
|
|
1880
2041
|
}
|
|
1881
2042
|
),
|
|
1882
|
-
/* @__PURE__ */
|
|
2043
|
+
drawer.mode === "detail" && schema.detail?.mode === "inline" ? /* @__PURE__ */ jsx11(DetailContent, { state: detailState, record: drawer.record }) : null,
|
|
2044
|
+
drawer.mode !== "closed" && (schema.detail?.mode !== "inline" || drawer.mode !== "detail") && schema.detail?.mode === "drawer" ? /* @__PURE__ */ jsxs5(
|
|
2045
|
+
BestDrawer,
|
|
2046
|
+
{
|
|
2047
|
+
open: true,
|
|
2048
|
+
width: schema.detail.width,
|
|
2049
|
+
title: drawer.mode === "detail" ? `${schema.title}\u8BE6\u60C5` : drawer.mode === "edit" ? `\u7F16\u8F91${schema.title}` : `\u65B0\u5EFA${schema.title}`,
|
|
2050
|
+
footer: drawer.mode === "detail" && schema.detail.footer?.length ? /* @__PURE__ */ jsx11("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8 }, children: schema.detail.footer.map((action) => /* @__PURE__ */ jsx11(ActionButton, { action, record: drawer.record, onExecute: handleAction }, action.id)) }) : void 0,
|
|
2051
|
+
onClose: () => {
|
|
2052
|
+
detailRequestRef.current?.abort();
|
|
2053
|
+
setDrawer({ mode: "closed" });
|
|
2054
|
+
setDetailState({ loading: false });
|
|
2055
|
+
},
|
|
2056
|
+
children: [
|
|
2057
|
+
drawer.mode === "detail" ? /* @__PURE__ */ jsx11(DetailContent, { state: detailState, record: drawer.record }) : null,
|
|
2058
|
+
drawer.mode === "edit" || drawer.mode === "create" ? /* @__PURE__ */ jsx11(BestForm, { fields: formFields, initialValues: drawer.record, loading: submitting, mode: drawer.mode, onCancel: () => setDrawer({ mode: "closed" }), onSubmit: (values) => {
|
|
2059
|
+
void submitForm(values);
|
|
2060
|
+
} }) : null
|
|
2061
|
+
]
|
|
2062
|
+
}
|
|
2063
|
+
) : null,
|
|
2064
|
+
drawer.mode !== "closed" && (schema.detail?.mode !== "inline" || drawer.mode !== "detail") && schema.detail?.mode !== "drawer" ? /* @__PURE__ */ jsxs5(
|
|
1883
2065
|
BestModal,
|
|
1884
2066
|
{
|
|
1885
|
-
open:
|
|
2067
|
+
open: true,
|
|
1886
2068
|
title: drawer.mode === "detail" ? `${schema.title}\u8BE6\u60C5` : drawer.mode === "edit" ? `\u7F16\u8F91${schema.title}` : `\u65B0\u5EFA${schema.title}`,
|
|
1887
|
-
|
|
2069
|
+
width: schema.detail?.width,
|
|
2070
|
+
footer: drawer.mode === "detail" && schema.detail?.footer?.length ? /* @__PURE__ */ jsx11("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8 }, children: schema.detail.footer.map((action) => /* @__PURE__ */ jsx11(ActionButton, { action, record: drawer.record, onExecute: handleAction }, action.id)) }) : void 0,
|
|
2071
|
+
onClose: () => {
|
|
2072
|
+
detailRequestRef.current?.abort();
|
|
2073
|
+
setDrawer({ mode: "closed" });
|
|
2074
|
+
setDetailState({ loading: false });
|
|
2075
|
+
},
|
|
1888
2076
|
children: [
|
|
1889
|
-
drawer.mode === "detail" ? /* @__PURE__ */ jsx11(
|
|
1890
|
-
BestDetail,
|
|
1891
|
-
{
|
|
1892
|
-
fields: schema.detail?.fields.map(
|
|
1893
|
-
(field) => toDetailField(field, registry.dictionaries, registry.slots)
|
|
1894
|
-
) ?? [],
|
|
1895
|
-
record: drawer.record
|
|
1896
|
-
}
|
|
1897
|
-
) : null,
|
|
2077
|
+
drawer.mode === "detail" ? /* @__PURE__ */ jsx11(DetailContent, { state: detailState, record: drawer.record }) : null,
|
|
1898
2078
|
drawer.mode === "edit" || drawer.mode === "create" ? /* @__PURE__ */ jsx11(
|
|
1899
2079
|
BestForm,
|
|
1900
2080
|
{
|
|
@@ -1910,8 +2090,24 @@ function BestCrudPage({ adapter, className, schema }) {
|
|
|
1910
2090
|
) : null
|
|
1911
2091
|
]
|
|
1912
2092
|
}
|
|
1913
|
-
)
|
|
2093
|
+
) : null
|
|
1914
2094
|
] });
|
|
2095
|
+
function DetailContent({ state, record }) {
|
|
2096
|
+
if (state.loading) return /* @__PURE__ */ jsx11(BestLoading, {});
|
|
2097
|
+
if (state.error) return /* @__PURE__ */ jsx11(BestError, { description: errorMessage(state.error, `${schema.title}\u8BE6\u60C5\u52A0\u8F7D\u5931\u8D25`) });
|
|
2098
|
+
if (!record) return /* @__PURE__ */ jsx11(BestEmpty, {});
|
|
2099
|
+
const sections = schema.detail?.sections?.map((section) => toDetailSection(section, record, registry.dictionaries, registry.slots)).filter(Boolean);
|
|
2100
|
+
return /* @__PURE__ */ jsx11(
|
|
2101
|
+
BestDetail,
|
|
2102
|
+
{
|
|
2103
|
+
fields: schema.detail?.fields?.map((field) => toDetailField(field, registry.dictionaries, registry.slots, record)) ?? [],
|
|
2104
|
+
sections,
|
|
2105
|
+
sectionColumns: schema.detail?.columns,
|
|
2106
|
+
sectionGap: schema.detail?.gap,
|
|
2107
|
+
record
|
|
2108
|
+
}
|
|
2109
|
+
);
|
|
2110
|
+
}
|
|
1915
2111
|
function ActionButton({
|
|
1916
2112
|
action,
|
|
1917
2113
|
record,
|
|
@@ -1979,6 +2175,7 @@ export {
|
|
|
1979
2175
|
useBestAccess,
|
|
1980
2176
|
useBestAction,
|
|
1981
2177
|
useBestDictionary,
|
|
2178
|
+
useBestDictionaryActions,
|
|
1982
2179
|
useBestListService,
|
|
1983
2180
|
useBestRegistry,
|
|
1984
2181
|
useBestService,
|