@hzab/list-render 1.9.15-beta → 1.9.16
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/CHANGELOG.md +8 -0
- package/README.md +45 -47
- package/package.json +1 -1
- package/src/DetailModal/index.jsx +5 -2
- package/src/common/handleQuerySchema.ts +2 -276
- package/src/components/Formily/FormilyField.tsx +1 -1
- package/src/list-render.jsx +22 -77
- package/src/query-render/index.jsx +1 -4
- package/src/table-render/index.jsx +10 -6
- package/src/common/constant.ts +0 -4
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -49,60 +49,58 @@ const listDM = useMemo(
|
|
|
49
49
|
|
|
50
50
|
### InfoPanel Attributes
|
|
51
51
|
|
|
52
|
-
| 属性名称 | 属性类型
|
|
53
|
-
| ---------------------------
|
|
52
|
+
| 属性名称 | 属性类型 | 必须 | 默认值 | 描述 |
|
|
53
|
+
| --------------------------- | ---------------- | ---- | --------------- | -------------------------------------------------------------------------------------------------------------- |
|
|
54
54
|
| layout | string | 否 | default | 列表渲染类型格式 |
|
|
55
55
|
| className | string | 否 | - | 外层 div className |
|
|
56
56
|
| idKey | string | 否 | id | 唯一值字段的 key |
|
|
57
57
|
| schema | Object | 是 | - | 字段描述文件,包含各个字段的信息 |
|
|
58
58
|
| model | Object | 是 | - | 数据模型,包含 CURD 接口信息,传入 DataModel 的实例 |
|
|
59
59
|
| isPatchUpdate | boolean | 否 | false | 编辑提交接口是否使用 patch 发起请求 |
|
|
60
|
-
| list | Array |
|
|
61
|
-
| closeAutoRequest | Boolean |
|
|
62
|
-
| hasQuery | Boolean |
|
|
63
|
-
| verticalHeader | Boolean |
|
|
64
|
-
| search | String |
|
|
65
|
-
| filters | Array |
|
|
66
|
-
| queryConf | Object |
|
|
67
|
-
| createText | String/ReactNote |
|
|
68
|
-
| hasCreate | Boolean |
|
|
69
|
-
| hasAction | Boolean |
|
|
70
|
-
| hasEdit | Boolean/Function |
|
|
71
|
-
| hasDel | Boolean/Function |
|
|
72
|
-
| hasDetail | Boolean/Function |
|
|
73
|
-
| hasDelTips | String/Function |
|
|
74
|
-
| tableConf | Object |
|
|
75
|
-
| tableProps | Object |
|
|
76
|
-
| cardConf | Object |
|
|
77
|
-
| cardProps | Object |
|
|
78
|
-
| fetchOnEdit | Boolean |
|
|
79
|
-
| fetchById | Boolean |
|
|
80
|
-
| modalMode | string |
|
|
81
|
-
| modalConf | Object |
|
|
82
|
-
| modalDetailProps | Object |
|
|
83
|
-
| modalFormProps | Object |
|
|
84
|
-
| modalProps | Object |
|
|
85
|
-
| schemaScope | Object |
|
|
86
|
-
| components | Object |
|
|
87
|
-
| detailComponents | Object |
|
|
88
|
-
| hasPagination | Boolean |
|
|
89
|
-
| paginationConf | Object |
|
|
90
|
-
| formInitialValues | Object |
|
|
91
|
-
| Slots | Object |
|
|
92
|
-
| getFieldListOpt | Object |
|
|
93
|
-
| onGetListEnd | Function |
|
|
94
|
-
| onCreateSuc | Function |
|
|
95
|
-
| onEditSuc | Function |
|
|
96
|
-
| onDelSuc | Function |
|
|
97
|
-
| onFormModalClose | Function |
|
|
98
|
-
| modalFormMount | Function |
|
|
99
|
-
| msgConf | Object |
|
|
100
|
-
| i18n | Object |
|
|
101
|
-
| queryFormInitialValues | Object |
|
|
102
|
-
| queryFormIsExtendModelQuery | Boolean |
|
|
60
|
+
| list | Array | | - | 本地数据源 |
|
|
61
|
+
| closeAutoRequest | Boolean | | false | 是否关闭加载完毕后自动发起请求。true 时组件 didMount 不自动发起请求 |
|
|
62
|
+
| hasQuery | Boolean | | true | 是否包含搜索、筛选框、搜索按钮等 |
|
|
63
|
+
| verticalHeader | Boolean | | false | 搜索项和新增按钮是否处于不同的行等 |
|
|
64
|
+
| search | String | | - | 传入空字符串时,不包含搜索框;传入非空字符串时,显示搜索框,同时传入的字符串作为搜索框的占位符 |
|
|
65
|
+
| filters | Array | | [] | 字符串数组,可以包含要筛选的字段 key 值(schema 中的 name),或者字符串 '$timerange'(时间范围筛选专用) |
|
|
66
|
+
| queryConf | Object | | {} | 设置 query 参数的 key |
|
|
67
|
+
| createText | String/ReactNote | | 新增 | 新增按钮文案 |
|
|
68
|
+
| hasCreate | Boolean | | true | 是否显示新增按钮 |
|
|
69
|
+
| hasAction | Boolean | | true | 是否在表格的最右增加一个“操作”列;hasAction 为 true 时,下面的 hasEdit/hasDel 才会生效 |
|
|
70
|
+
| hasEdit | Boolean/Function | | true | 是否显示编辑按钮,可传入回调控制当前行是否显示 |
|
|
71
|
+
| hasDel | Boolean/Function | | true | 是否显示删除按钮,可传入回调控制当前行是否显示 |
|
|
72
|
+
| hasDetail | Boolean/Function | | true | 是否显示详情按钮,可传入回调控制当前行是否显示 |
|
|
73
|
+
| hasDelTips | String/Function | | "确认删除该项?" | 删除按钮自定义提示,可传入回调根据当前行数据显示对应提示 |
|
|
74
|
+
| tableConf | Object | | {} | Table 相关配置 |
|
|
75
|
+
| tableProps | Object | | {} | 直接传给 Table 的 props,相关 API 可直接参考 antd table 组件 |
|
|
76
|
+
| cardConf | Object | | {} | Card 相关配置 |
|
|
77
|
+
| cardProps | Object | | {} | 直接传给 cardRender 的 props,因内部渲染使用的的是详情组件,相关 API 可直接参考 @hzab/schema-descriptions 组件 |
|
|
78
|
+
| fetchOnEdit | Boolean | | true | 展示编辑弹框时,是否会调用一次详情接口进行回填;若为 false,则会使用表格列表接口返回的 row 数据进行回填 |
|
|
79
|
+
| fetchById | Boolean | | true | 编辑中的详情请求,是否使用 id 作为入参的 key |
|
|
80
|
+
| modalMode | string | | dialog | 新增/编辑表单、详情 展示模式: dialog drawer |
|
|
81
|
+
| modalConf | Object | | {} | modal/Drawer 配置对象 |
|
|
82
|
+
| modalDetailProps | Object | | {} | modal descriptions 配置对象 |
|
|
83
|
+
| modalFormProps | Object | | {} | modal/drawer fromRender 配置对象 |
|
|
84
|
+
| modalProps | Object | | {} | modal/drawer 配置对象 |
|
|
85
|
+
| schemaScope | Object | | {} | formRender schemaScope props |
|
|
86
|
+
| components | Object | | {} | formRender components props 自定义组件 |
|
|
87
|
+
| detailComponents | Object | | {} | descriptions components props 自定义组件 |
|
|
88
|
+
| hasPagination | Boolean | | true | 是否显示分页 |
|
|
89
|
+
| paginationConf | Object | | {} | 可自定义 Pagination props,进行 pagination 相关设置 |
|
|
90
|
+
| formInitialValues | Object | | {} | 给新增、编辑对话框中的表单增加默认值 |
|
|
91
|
+
| Slots | Object | | {} | 组件插槽 |
|
|
92
|
+
| getFieldListOpt | Object | | {} | getFieldList opt 参数 |
|
|
93
|
+
| onGetListEnd | Function | | - | 请求列表成功返回的回调 |
|
|
94
|
+
| onCreateSuc | Function | | - | 新增成功返回的回调 |
|
|
95
|
+
| onEditSuc | Function | | - | 编辑成功返回的回调 |
|
|
96
|
+
| onDelSuc | Function | | - | 删除成功返回的回调 |
|
|
97
|
+
| onFormModalClose | Function | | - | 表单弹窗关闭回调 |
|
|
98
|
+
| modalFormMount | Function | | - | 新增、编辑弹窗 Form 渲染完成回调 |
|
|
99
|
+
| msgConf | Object | | {} | 新增、编辑、删除、列表查询,详情查询的报错 msg 提示设置 |
|
|
100
|
+
| i18n | Object | | {} | 文案配置 |
|
|
101
|
+
| queryFormInitialValues | Object | | {} | 列表上方查询 Form 默认值 |
|
|
102
|
+
| queryFormIsExtendModelQuery | Boolean | | false | 列表上方查询 Form 默认值是否继承 data-model.query 置 |
|
|
103
103
|
| useFormData | boolean | 否 | | 是否使用 form data 提交数据 |
|
|
104
|
-
| appendUrlQuery | boolean | 否 | true | 筛选条件改变时是否将参数(对象形式)设置到url query中 |
|
|
105
|
-
| appendUrlQueryKey | string | 否 | URL_PARAM_NAME = "defaultSearchParams" | 自定义设置url query对象参数的key |
|
|
106
104
|
|
|
107
105
|
- fetchOnEdit 展示编辑弹框时,是否会调用一次详情接口进行回填(某些场景下,列表接口只返回部分部分字段,只有详情接口会返回全部字段);若为 false,则会使用表格列表接口返回的 row 数据进行回填
|
|
108
106
|
|
package/package.json
CHANGED
|
@@ -11,11 +11,14 @@ function DetailModal(props, parentRef) {
|
|
|
11
11
|
const { modalMode, Slots = {}, modalConf = {}, modalProps = {} } = props;
|
|
12
12
|
const [open, setOpen] = useState(false);
|
|
13
13
|
const [data, setData] = useState({});
|
|
14
|
+
const [title, setTitle] = useState("详情");
|
|
15
|
+
|
|
14
16
|
const formRef = useRef();
|
|
15
|
-
function show(formData = props.formInitialValues) {
|
|
17
|
+
function show(formData = props.formInitialValues, title) {
|
|
16
18
|
setOpen(true);
|
|
17
19
|
// 处理 formRef.current 为 undefined 的问题
|
|
18
20
|
setData(formData);
|
|
21
|
+
setTitle(title || '详情')
|
|
19
22
|
}
|
|
20
23
|
|
|
21
24
|
function close() {
|
|
@@ -72,7 +75,7 @@ function DetailModal(props, parentRef) {
|
|
|
72
75
|
const _modalProps = {
|
|
73
76
|
className: "detail-modal",
|
|
74
77
|
wrapClassName: "detail-modal",
|
|
75
|
-
title:
|
|
78
|
+
title: title,
|
|
76
79
|
visible: open,
|
|
77
80
|
open: open,
|
|
78
81
|
onClose: close,
|
|
@@ -1,66 +1,6 @@
|
|
|
1
1
|
import _ from "lodash";
|
|
2
2
|
import { getFieldMap } from "./utils";
|
|
3
|
-
import {
|
|
4
|
-
isRunStr,
|
|
5
|
-
handleSchemaStrVal,
|
|
6
|
-
isScopeKey as formIsScopeKey,
|
|
7
|
-
getScopeKeyVal,
|
|
8
|
-
} from "@hzab/form-render/src/common/schema-handler";
|
|
9
|
-
import { URL_PARAM_NAME } from "./constant";
|
|
10
|
-
|
|
11
|
-
// ===================== 类型定义 =====================
|
|
12
|
-
|
|
13
|
-
type AntdDateComponent = "DatePicker" | "DatePicker.RangePicker";
|
|
14
|
-
|
|
15
|
-
interface XComponentProps {
|
|
16
|
-
isSplitTimes?: boolean;
|
|
17
|
-
startKey?: string;
|
|
18
|
-
endKey?: string;
|
|
19
|
-
[k: string]: unknown;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
interface FormilyField {
|
|
23
|
-
type?: string;
|
|
24
|
-
title?: string;
|
|
25
|
-
"x-decorator"?: string;
|
|
26
|
-
"x-component"?: string;
|
|
27
|
-
"x-validator"?: unknown[];
|
|
28
|
-
"x-component-props"?: XComponentProps;
|
|
29
|
-
"x-decorator-props"?: Record<string, unknown>;
|
|
30
|
-
"x-designable-id"?: string;
|
|
31
|
-
"x-index"?: number;
|
|
32
|
-
[k: string]: unknown;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
interface FormilyV1SchemaNode {
|
|
36
|
-
type?: string;
|
|
37
|
-
properties?: Record<string, FormilyField>;
|
|
38
|
-
[k: string]: unknown;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
interface FormilyV1Schema {
|
|
42
|
-
form?: Record<string, unknown>;
|
|
43
|
-
schema: FormilyV1SchemaNode;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
type URLQueryObject = Record<string, any> | null | undefined;
|
|
47
|
-
|
|
48
|
-
interface ExtractOptions {
|
|
49
|
-
/** 分拆开关字段名,位于 x-component-props;默认 'isSplitTimes' */
|
|
50
|
-
splitFlag?: string;
|
|
51
|
-
/** 分拆开关的期望值;默认 true */
|
|
52
|
-
splitFlagExpectedValue?: unknown;
|
|
53
|
-
/** 默认开始/结束键名(当 schema 未显式配置时),默认 'startTime' / 'endTime' */
|
|
54
|
-
defaultStartKey?: string;
|
|
55
|
-
defaultEndKey?: string;
|
|
56
|
-
/** 认为是 antd 日期组件的名单,默认 DatePicker / DatePicker.RangePicker */
|
|
57
|
-
antdDateComponents?: readonly AntdDateComponent[];
|
|
58
|
-
/**
|
|
59
|
-
* 命中并成功赋值后,是否从返回对象中删除对应的 startKey / endKey
|
|
60
|
-
* 默认 true(删除)
|
|
61
|
-
*/
|
|
62
|
-
removeMatchedKeys?: boolean;
|
|
63
|
-
}
|
|
3
|
+
import { isRunStr, handleSchemaStrVal, isScopeKey as formIsScopeKey, getScopeKeyVal } from '@hzab/form-render/src/common/schema-handler';
|
|
64
4
|
|
|
65
5
|
export const handleQuerySchema = (opt) => {
|
|
66
6
|
const { schema, search, filters, onSearch, replaceComList, schemaScope } = opt || {};
|
|
@@ -274,6 +214,7 @@ export const handleHoc = (source, cb, opt) => {
|
|
|
274
214
|
|
|
275
215
|
let res = null;
|
|
276
216
|
if (isRunStr(source)) {
|
|
217
|
+
|
|
277
218
|
_source = handleSchemaStrVal(source, schemaScope);
|
|
278
219
|
}
|
|
279
220
|
if (formIsScopeKey(source, schemaScope)) {
|
|
@@ -358,219 +299,4 @@ export const getValByScope = (strKey, schemaScope = {}) => {
|
|
|
358
299
|
}
|
|
359
300
|
};
|
|
360
301
|
|
|
361
|
-
function removeEmptyValues(obj) {
|
|
362
|
-
return _.pickBy(obj, (value) => {
|
|
363
|
-
// 排除 undefined 和 null
|
|
364
|
-
if (value == null) return false;
|
|
365
|
-
|
|
366
|
-
// 排除空字符串
|
|
367
|
-
if (_.isString(value) && value.trim() === "") return false;
|
|
368
|
-
|
|
369
|
-
// 排除空数组
|
|
370
|
-
if (_.isArray(value) && value.length === 0) return false;
|
|
371
|
-
|
|
372
|
-
// 保留其他值(包括 0、false、非空对象等)
|
|
373
|
-
return true;
|
|
374
|
-
});
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
/**
|
|
378
|
-
* 将对象序列化后写入 URL query 中
|
|
379
|
-
* @param obj 要存储的对象(保持原始类型)
|
|
380
|
-
* @param paramName query 参数名
|
|
381
|
-
*/
|
|
382
|
-
export function setURLObjectQueryParam<T extends object>(obj: T, paramName = URL_PARAM_NAME): void {
|
|
383
|
-
try {
|
|
384
|
-
if (typeof window === "undefined") return;
|
|
385
|
-
|
|
386
|
-
const href = window.location.href;
|
|
387
|
-
const [origin, hash = ""] = href.split("#");
|
|
388
|
-
const [path, queryString = ""] = hash.split("?");
|
|
389
|
-
const searchParams = new URLSearchParams(queryString);
|
|
390
|
-
// 指定的空值不设置
|
|
391
|
-
const copyObj = _.cloneDeep(removeEmptyValues(obj));
|
|
392
|
-
|
|
393
|
-
const encoded = encodeURIComponent(JSON.stringify(copyObj));
|
|
394
|
-
|
|
395
|
-
searchParams.set(paramName, encoded);
|
|
396
|
-
|
|
397
|
-
const newHash = `${path}?${searchParams.toString()}`;
|
|
398
|
-
|
|
399
|
-
window.history.replaceState({}, "", `${origin}#${newHash}`);
|
|
400
|
-
} catch (e) {
|
|
401
|
-
console.error(`[setURLObjectQueryParam] 设置失败:`, e);
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
/**
|
|
406
|
-
* 从哈希路由的查询参数中,删除某个“对象型参数”下的指定属性(不刷新页面)
|
|
407
|
-
* @param parentKey 父级对象参数名
|
|
408
|
-
* @param childKey 要删除的对象属性名
|
|
409
|
-
*/
|
|
410
|
-
export function removeURLObjectQueryParam(parentKey: string, childKey: string, reset?: boolean): void {
|
|
411
|
-
if (typeof window === "undefined") return;
|
|
412
|
-
|
|
413
|
-
try {
|
|
414
|
-
const href = window.location.href;
|
|
415
|
-
const [origin, hash = ""] = href.split("#");
|
|
416
|
-
const [hashPath, queryString = ""] = hash.split("?");
|
|
417
|
-
const searchParams = new URLSearchParams(queryString);
|
|
418
|
-
|
|
419
|
-
const raw = searchParams.get(parentKey);
|
|
420
|
-
if (raw == null) return;
|
|
421
|
-
|
|
422
|
-
// URLSearchParams.get 已自动做了百分号解码,但是可能会遇到编码两次的情况,因此这里再尝试解码一次
|
|
423
|
-
let obj: unknown;
|
|
424
|
-
try {
|
|
425
|
-
obj = JSON.parse(decodeURIComponent(raw));
|
|
426
|
-
} catch {
|
|
427
|
-
// 若不是合法 JSON,就不处理该参数
|
|
428
|
-
console.error(`[removeURLObjectQueryParam] 序列化URL参数错误`);
|
|
429
|
-
return;
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
// 如果是重置,直接清空整个parentKey
|
|
433
|
-
if (reset && parentKey) searchParams.delete(parentKey);
|
|
434
|
-
else {
|
|
435
|
-
if (obj && typeof obj === "object" && !Array.isArray(obj)) {
|
|
436
|
-
const record = obj as Record<string, unknown>;
|
|
437
|
-
// 删除空值key
|
|
438
|
-
if (childKey || record[childKey] === "" || record[childKey] === undefined || record[childKey] === null)
|
|
439
|
-
delete record[childKey];
|
|
440
|
-
|
|
441
|
-
// 如果对象被删空,则移除整个 parentKey;否则写回
|
|
442
|
-
if (Object.keys(record).length === 0) {
|
|
443
|
-
searchParams.delete(parentKey);
|
|
444
|
-
} else {
|
|
445
|
-
searchParams.set(parentKey, encodeURIComponent(JSON.stringify(record)));
|
|
446
|
-
}
|
|
447
|
-
} else {
|
|
448
|
-
// parentKey 的值不是对象,安全起见不处理
|
|
449
|
-
return;
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
// 重建哈希部分
|
|
454
|
-
let newHash = hashPath;
|
|
455
|
-
const qs = searchParams.toString();
|
|
456
|
-
if (qs) newHash += `?${qs}`;
|
|
457
|
-
|
|
458
|
-
const newUrl = `${origin}${newHash ? `#${newHash}` : ""}`;
|
|
459
|
-
window.history.replaceState({}, "", newUrl);
|
|
460
|
-
} catch (e) {
|
|
461
|
-
console.error(`[removeURLObjectQueryParam] 删除失败:`, e);
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
/**
|
|
466
|
-
* 从 URL 中解析序列化的对象
|
|
467
|
-
* @param paramName query 参数名
|
|
468
|
-
* @returns 还原的对象(如果不存在返回 null)
|
|
469
|
-
*/
|
|
470
|
-
export function getURLObjectQueryParam<T = any>(paramName = URL_PARAM_NAME): T | Record<string, any> {
|
|
471
|
-
// 返回空对象是为了防止在合并对象时报错导致页面空白
|
|
472
|
-
if (typeof window === "undefined") return {};
|
|
473
|
-
|
|
474
|
-
const href = window.location.href;
|
|
475
|
-
const [, hash = ""] = href.split("#");
|
|
476
|
-
const [, queryString = ""] = hash.split("?");
|
|
477
|
-
const searchParams = new URLSearchParams(queryString);
|
|
478
|
-
const encoded = searchParams.get(paramName);
|
|
479
|
-
|
|
480
|
-
if (!encoded) return null;
|
|
481
|
-
|
|
482
|
-
try {
|
|
483
|
-
return JSON.parse(decodeURIComponent(encoded)) as T;
|
|
484
|
-
} catch (e) {
|
|
485
|
-
console.error(`[getURLObjectQueryParam] 解析失败:`, e);
|
|
486
|
-
return {};
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
// ===================== 辅助函数 =====================
|
|
491
|
-
|
|
492
|
-
const pickFormilyProperties = (schema: FormilyV1Schema): Record<string, FormilyField> =>
|
|
493
|
-
schema?.schema?.properties ?? {};
|
|
494
|
-
|
|
495
|
-
const isAntdDateComponent = (comp: unknown, whitelist: readonly string[]) =>
|
|
496
|
-
typeof comp === "string" && whitelist.includes(comp);
|
|
497
|
-
|
|
498
|
-
const filterKeys = (props: Record<string, FormilyField>, filters: readonly string[]) => {
|
|
499
|
-
const filterSet = new Set(filters);
|
|
500
|
-
return Object.entries(props).filter(([k]) => filterSet.has(k));
|
|
501
|
-
};
|
|
502
|
-
|
|
503
|
-
const matchSplitFlag = (field: FormilyField, splitFlag: string, expected: unknown) =>
|
|
504
|
-
field?.["x-component-props"]?.[splitFlag] === expected;
|
|
505
|
-
|
|
506
|
-
/** 两个值都缺失则返回 undefined;否则返回二元组 */
|
|
507
|
-
const getRangeTupleOrUndefined = (urlObj: URLQueryObject, startKey: string, endKey: string): [any, any] | undefined => {
|
|
508
|
-
const obj = (urlObj ?? {}) as Record<string, any>;
|
|
509
|
-
const hasStart = Object.prototype.hasOwnProperty.call(obj, startKey);
|
|
510
|
-
const hasEnd = Object.prototype.hasOwnProperty.call(obj, endKey);
|
|
511
|
-
if (!hasStart && !hasEnd) return undefined;
|
|
512
|
-
return [obj[startKey], obj[endKey]];
|
|
513
|
-
};
|
|
514
|
-
|
|
515
|
-
// ===================== 主函数 =====================
|
|
516
|
-
/**
|
|
517
|
-
* 根据formilySchema配置逆解析表单key并将url query赋值
|
|
518
|
-
* 三层筛选:根据filters + splitFlag + antdDateComponents 提取formilySchema配置项然后通过配置的key赋值并返回
|
|
519
|
-
* */
|
|
520
|
-
export function extractSplitDateRanges(
|
|
521
|
-
filters: string[],
|
|
522
|
-
formilySchema: FormilyV1Schema,
|
|
523
|
-
urlObj: URLQueryObject,
|
|
524
|
-
options: ExtractOptions = {},
|
|
525
|
-
): Record<string, any> {
|
|
526
|
-
const {
|
|
527
|
-
splitFlag = "isSplitTimes",
|
|
528
|
-
splitFlagExpectedValue = true,
|
|
529
|
-
defaultStartKey = "startTime",
|
|
530
|
-
defaultEndKey = "endTime",
|
|
531
|
-
antdDateComponents = ["DatePicker", "DatePicker.RangePicker"],
|
|
532
|
-
removeMatchedKeys = true,
|
|
533
|
-
} = options;
|
|
534
|
-
|
|
535
|
-
const properties = pickFormilyProperties(formilySchema);
|
|
536
|
-
const candidates = filterKeys(properties, filters);
|
|
537
|
-
|
|
538
|
-
// 保持不变性
|
|
539
|
-
const base = _.cloneDeep(urlObj) as Record<string, any>;
|
|
540
|
-
|
|
541
|
-
// 统一延迟删除,避免顺序影响
|
|
542
|
-
const keysToDelete = new Set<string>();
|
|
543
|
-
|
|
544
|
-
for (const [fieldKey, field] of candidates) {
|
|
545
|
-
// 未命中则直接跳过本次循环
|
|
546
|
-
if (!isAntdDateComponent(field?.["x-component"], antdDateComponents)) continue;
|
|
547
|
-
if (!matchSplitFlag(field, splitFlag, splitFlagExpectedValue)) continue;
|
|
548
|
-
|
|
549
|
-
const props = field?.["x-component-props"] ?? {};
|
|
550
|
-
const startKey = (props?.startKey as string) || defaultStartKey;
|
|
551
|
-
const endKey = (props?.endKey as string) || defaultEndKey;
|
|
552
|
-
|
|
553
|
-
const tuple = getRangeTupleOrUndefined(base, startKey, endKey);
|
|
554
|
-
if (!tuple) continue; // 两个值都没有则不赋值、不删除
|
|
555
|
-
|
|
556
|
-
// 命中,给 fieldKey 赋值
|
|
557
|
-
base[fieldKey] = tuple;
|
|
558
|
-
|
|
559
|
-
// 按需记录要删除的键(只删除“命中的”)
|
|
560
|
-
if (removeMatchedKeys) {
|
|
561
|
-
if (Object.prototype.hasOwnProperty.call(base, startKey)) keysToDelete.add(startKey);
|
|
562
|
-
if (Object.prototype.hasOwnProperty.call(base, endKey)) keysToDelete.add(endKey);
|
|
563
|
-
}
|
|
564
|
-
}
|
|
565
|
-
|
|
566
|
-
// 统一执行删除,保证无顺序副作用
|
|
567
|
-
if (removeMatchedKeys) {
|
|
568
|
-
for (const k of keysToDelete) {
|
|
569
|
-
delete base[k];
|
|
570
|
-
}
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
return base;
|
|
574
|
-
}
|
|
575
|
-
|
|
576
302
|
export default handleQuerySchema;
|
package/src/list-render.jsx
CHANGED
|
@@ -15,13 +15,6 @@ import FormModal from "./FormModal";
|
|
|
15
15
|
import DetailModal from "./DetailModal";
|
|
16
16
|
|
|
17
17
|
import { objToFormData } from "./common/utils";
|
|
18
|
-
import {
|
|
19
|
-
setURLObjectQueryParam,
|
|
20
|
-
getURLObjectQueryParam,
|
|
21
|
-
removeURLObjectQueryParam,
|
|
22
|
-
extractSplitDateRanges,
|
|
23
|
-
} from "./common/handleQuerySchema";
|
|
24
|
-
import { CLEAR_LIST, URL_PARAM_NAME } from "./common/constant";
|
|
25
18
|
|
|
26
19
|
import "./index.less";
|
|
27
20
|
|
|
@@ -50,16 +43,6 @@ const ListRender = forwardRef(function (props, parentRef) {
|
|
|
50
43
|
* 表单提交是否使用 FormData 格式
|
|
51
44
|
*/
|
|
52
45
|
useFormData: _useFormData,
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* 筛选条件改变时是否将参数(对象形式)设置到url query中
|
|
56
|
-
* */
|
|
57
|
-
appendUrlQuery = false,
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* 自定义设置url query对象参数的key
|
|
61
|
-
* */
|
|
62
|
-
appendUrlQueryKey = URL_PARAM_NAME,
|
|
63
46
|
} = props;
|
|
64
47
|
const pageSizeOptions = props.paginationConf?.pageSizeOptions || pageSizeOptionMap[props.layout] || [10, 20, 50, 100];
|
|
65
48
|
// const [pageSizeOptions, setPageSizeOptions] = useState(
|
|
@@ -94,7 +77,7 @@ const ListRender = forwardRef(function (props, parentRef) {
|
|
|
94
77
|
onDel,
|
|
95
78
|
}));
|
|
96
79
|
|
|
97
|
-
const { schema = {}, config = {}, model = {}, msgConf = {}
|
|
80
|
+
const { schema = {}, config = {}, model = {}, msgConf = {} } = props;
|
|
98
81
|
|
|
99
82
|
// useEffect(() => {
|
|
100
83
|
// const list = props.paginationConf?.pageSizeOptions || pageSizeOptionMap[props.layout] || [10, 20, 50, 100];
|
|
@@ -103,34 +86,20 @@ const ListRender = forwardRef(function (props, parentRef) {
|
|
|
103
86
|
// }, [layout]);
|
|
104
87
|
|
|
105
88
|
useEffect(() => {
|
|
106
|
-
const getUrlQuery = appendUrlQuery ? getURLObjectQueryParam(appendUrlQueryKey) : {};
|
|
107
|
-
|
|
108
89
|
if (model) {
|
|
109
90
|
if (!model.query) {
|
|
110
91
|
model.query = {};
|
|
111
92
|
} else {
|
|
112
|
-
model.query.pageNum = 1;
|
|
113
|
-
|
|
114
93
|
modelQueryRef.current = model?.query;
|
|
115
94
|
paginationQueryRef.current = {
|
|
116
|
-
pageNum:
|
|
117
|
-
pageSize:
|
|
95
|
+
pageNum: model?.query?.pageNum ?? paginationQueryRef.current?.pageNum,
|
|
96
|
+
pageSize: model?.query?.pageSize ?? paginationQueryRef.current?.pageSize,
|
|
118
97
|
};
|
|
119
98
|
}
|
|
99
|
+
model.query.pageNum = 1;
|
|
120
100
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
Promise.resolve().then(() => {
|
|
124
|
-
if (queryRef.current && queryRef.current?.formRef?.current.formRender) {
|
|
125
|
-
const extractValues = extractSplitDateRanges(filters, schema, getUrlQuery);
|
|
126
|
-
|
|
127
|
-
queryRef.current.formRef.current.formRender?.setValues(extractValues);
|
|
128
|
-
|
|
129
|
-
formQueryRef.current = _.cloneDeep(getUrlQuery);
|
|
130
|
-
}
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
!props.closeAutoRequest && getList({ ...(modelQueryRef.current || {}), ...getUrlQuery });
|
|
101
|
+
// 首次自动请求,取 筛选表单的默认值 进行请求
|
|
102
|
+
!props.closeAutoRequest && onSearch(queryFormInitialValues);
|
|
134
103
|
}, []);
|
|
135
104
|
|
|
136
105
|
useEffect(() => {
|
|
@@ -187,6 +156,7 @@ const ListRender = forwardRef(function (props, parentRef) {
|
|
|
187
156
|
}
|
|
188
157
|
|
|
189
158
|
// model.query = mergedQueries;
|
|
159
|
+
|
|
190
160
|
// 取消上一次请求
|
|
191
161
|
getListSourceRef.current?.cancel({ code: 601, message: "取消上一次请求" });
|
|
192
162
|
|
|
@@ -226,19 +196,11 @@ const ListRender = forwardRef(function (props, parentRef) {
|
|
|
226
196
|
// model.query.pageNum = page;
|
|
227
197
|
// model.query.pageSize = size;
|
|
228
198
|
paginationQueryRef.current = { pageNum: page, pageSize: size };
|
|
229
|
-
|
|
230
|
-
if (appendUrlQuery) {
|
|
231
|
-
const getUrlQuery = getURLObjectQueryParam(appendUrlQueryKey);
|
|
232
|
-
setURLObjectQueryParam({ ...getUrlQuery, ...paginationQueryRef.current }, appendUrlQueryKey);
|
|
233
|
-
}
|
|
234
199
|
getList();
|
|
235
200
|
}
|
|
236
201
|
|
|
237
|
-
function onSearch(quer, source
|
|
202
|
+
function onSearch(quer, source) {
|
|
238
203
|
const query = source === "queryRender" ? { ...quer } : { ...formQueryRef.current, ...quer };
|
|
239
|
-
// 重置操作时不赋值
|
|
240
|
-
if (source === "queryRender" && !isReset && appendUrlQuery) setURLObjectQueryParam(query, appendUrlQueryKey);
|
|
241
|
-
|
|
242
204
|
if (model && !model.query) {
|
|
243
205
|
model.query = {};
|
|
244
206
|
}
|
|
@@ -253,35 +215,14 @@ const ListRender = forwardRef(function (props, parentRef) {
|
|
|
253
215
|
getList(query);
|
|
254
216
|
}
|
|
255
217
|
|
|
256
|
-
function handleFormReset() {
|
|
257
|
-
appendUrlQuery && removeURLObjectQueryParam(appendUrlQueryKey, "", true);
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
function handleFieldValueChange(filed, form) {
|
|
261
|
-
// props?.onFieldValueChange?.(filed, form);
|
|
262
|
-
|
|
263
|
-
if (!appendUrlQuery) return;
|
|
264
|
-
|
|
265
|
-
try {
|
|
266
|
-
const { componentType, value, path } = filed;
|
|
267
|
-
if (CLEAR_LIST.includes(componentType)) {
|
|
268
|
-
if (value === "" || value?.length === 0 || value === undefined) {
|
|
269
|
-
const key = path.entire;
|
|
270
|
-
key && removeURLObjectQueryParam(appendUrlQueryKey, key);
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
} catch (e) {
|
|
274
|
-
console.error("url参数清除失败", e);
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
|
|
278
218
|
function forceUpdate() {
|
|
279
219
|
setList((l) => _.cloneDeep(l));
|
|
280
220
|
}
|
|
281
221
|
|
|
282
222
|
function onCreate() {
|
|
283
223
|
setFormState("create");
|
|
284
|
-
|
|
224
|
+
let title = props.formInitialValues?.[modalConf?.title?.createKey] || modalConf?.title?.createText || '新增'
|
|
225
|
+
formModalRef.current.show(props.formInitialValues, title);
|
|
285
226
|
}
|
|
286
227
|
|
|
287
228
|
async function onCreateSubmit(data) {
|
|
@@ -328,7 +269,8 @@ const ListRender = forwardRef(function (props, parentRef) {
|
|
|
328
269
|
|
|
329
270
|
function handleDetail(data, id) {
|
|
330
271
|
setRowId(id);
|
|
331
|
-
|
|
272
|
+
let title = data[modalConf?.title?.detailKey] || modalConf?.title?.detailText || '详情'
|
|
273
|
+
detailModalRef.current.show(data, title);
|
|
332
274
|
}
|
|
333
275
|
|
|
334
276
|
function onEdit(row, idx) {
|
|
@@ -357,7 +299,8 @@ const ListRender = forwardRef(function (props, parentRef) {
|
|
|
357
299
|
function handleEdit(data, id) {
|
|
358
300
|
setRowId(id);
|
|
359
301
|
setFormState("edit");
|
|
360
|
-
|
|
302
|
+
let title = data[modalConf?.title?.editKey] || modalConf?.title?.editText || '编辑'
|
|
303
|
+
formModalRef.current.show(data, title, "edit");
|
|
361
304
|
}
|
|
362
305
|
|
|
363
306
|
async function onEditSubmit(data) {
|
|
@@ -424,15 +367,17 @@ const ListRender = forwardRef(function (props, parentRef) {
|
|
|
424
367
|
search={props.search}
|
|
425
368
|
filters={props.filters}
|
|
426
369
|
config={props.queryConf}
|
|
427
|
-
queryFormInitialValues={
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
370
|
+
queryFormInitialValues={
|
|
371
|
+
queryFormIsExtendModelQuery
|
|
372
|
+
? {
|
|
373
|
+
...queryFormInitialValues,
|
|
374
|
+
...model.query,
|
|
375
|
+
}
|
|
376
|
+
: queryFormInitialValues
|
|
377
|
+
}
|
|
431
378
|
onSearch={onSearch}
|
|
432
|
-
onReset={handleFormReset}
|
|
433
379
|
schemaScope={props.schemaScope}
|
|
434
380
|
components={props.components}
|
|
435
|
-
onFieldValueChange={handleFieldValueChange}
|
|
436
381
|
i18n={i18n}
|
|
437
382
|
/>
|
|
438
383
|
) : (
|
|
@@ -7,7 +7,6 @@ import FormRender from "@hzab/form-render";
|
|
|
7
7
|
import { handleQuerySchema } from "../common/handleQuerySchema";
|
|
8
8
|
|
|
9
9
|
import "./index.less";
|
|
10
|
-
import { onFieldValueChange } from "@formily/core";
|
|
11
10
|
|
|
12
11
|
function QueryRender(props, parentRef) {
|
|
13
12
|
const [schema, setSchema] = useState({});
|
|
@@ -55,8 +54,7 @@ function QueryRender(props, parentRef) {
|
|
|
55
54
|
|
|
56
55
|
function onReset() {
|
|
57
56
|
formRef.current?.formRender?.reset();
|
|
58
|
-
props.
|
|
59
|
-
props.onSearch && props.onSearch(_.cloneDeep(formRef?.current?.formRender?.values), "queryRender", true);
|
|
57
|
+
props.onSearch && props.onSearch(_.cloneDeep(formRef?.current?.formRender?.values), "queryRender");
|
|
60
58
|
}
|
|
61
59
|
|
|
62
60
|
return (
|
|
@@ -69,7 +67,6 @@ function QueryRender(props, parentRef) {
|
|
|
69
67
|
schema={schema}
|
|
70
68
|
schemaScope={{ scenario: "query", ...(props.schemaScope || {}) }}
|
|
71
69
|
initialValues={props.queryFormInitialValues}
|
|
72
|
-
onFieldValueChange={props.onFieldValueChange}
|
|
73
70
|
Slots={() => {
|
|
74
71
|
return (
|
|
75
72
|
<div className="query-operation">
|
|
@@ -350,13 +350,17 @@ function TableRender(props) {
|
|
|
350
350
|
expandable={config.expandable}
|
|
351
351
|
loading={props.loading}
|
|
352
352
|
onRow={config?.onRow}
|
|
353
|
+
components={
|
|
354
|
+
isDargTable
|
|
355
|
+
? {
|
|
356
|
+
body: {
|
|
357
|
+
wrapper: DraggableContainer,
|
|
358
|
+
row: DraggableBodyRow,
|
|
359
|
+
},
|
|
360
|
+
}
|
|
361
|
+
: undefined
|
|
362
|
+
}
|
|
353
363
|
{...props.tableProps}
|
|
354
|
-
components={{
|
|
355
|
-
body: {
|
|
356
|
-
wrapper: DraggableContainer,
|
|
357
|
-
row: DraggableBodyRow,
|
|
358
|
-
},
|
|
359
|
-
}}
|
|
360
364
|
/>
|
|
361
365
|
<FormilyField
|
|
362
366
|
schema={props.schema}
|
package/src/common/constant.ts
DELETED