@hzab/list-render 1.10.0-beta1 → 1.10.0-beta4

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 CHANGED
@@ -1,6 +1,34 @@
1
1
  # @hzab/list-render@1.10.0
2
2
 
3
- feat: 表单、分页参数变化时设置到url query,首次进入页面时会使用url query中的参数进行回显、请求
3
+ feat: 支持行内编辑编辑 isEditTable
4
+
5
+ # @hzab/list-render@1.9.16
6
+
7
+ fix: modal 弹窗标题支持配置
8
+
9
+ # @hzab/list-render@1.9.15
10
+
11
+ fix: components 改为外部可配置
12
+
13
+ # @hzab/list-render@1.9.14
14
+
15
+ fix: 拖动列添加 fixed
16
+
17
+ # @hzab/list-render@1.9.13
18
+
19
+ fix: 首次自动请求 onSearch 入参添加 queryFormInitialValues
20
+
21
+ # @hzab/list-render@1.9.12
22
+
23
+ fix: table 添加拖拽排序
24
+
25
+ # @hzab/list-render@1.9.11
26
+
27
+ fix: 修复 model query 被污染 2
28
+
29
+ # @hzab/list-render@1.9.10
30
+
31
+ fix: 修复 model query 被污染
4
32
 
5
33
  # @hzab/list-render@1.9.9
6
34
 
package/README.md CHANGED
@@ -49,60 +49,59 @@ 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 | | 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 置 |
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 |
104
+ | isEditTable | boolean | 否 | | 是否行内编辑表格 |
106
105
 
107
106
  - fetchOnEdit 展示编辑弹框时,是否会调用一次详情接口进行回填(某些场景下,列表接口只返回部分部分字段,只有详情接口会返回全部字段);若为 false,则会使用表格列表接口返回的 row 数据进行回填
108
107
 
@@ -119,6 +118,9 @@ const listDM = useMemo(
119
118
  | orderColWidth | string/number | | - | 序号列 width 的参数 |
120
119
  | tableEmptyValue | string/number | | undefined | table 列表空值展示数 |
121
120
  | isTableSortXIdex | Boolean | | undefined | table 列表列排序是否按照 x-index 排序 |
121
+ | dragColConf | Object | | undefined | 拖拽列的配置 |
122
+ | isDargTable | Boolean | | undefined | 是否开启表格拖拽排序 |
123
+ | dargEndBack | function | | undefined | 拖拽结束后返回表格数据 |
122
124
 
123
125
  ##### tableConf.colConf[xxx]
124
126
 
@@ -155,6 +157,29 @@ const listDM = useMemo(
155
157
  | queryMap | Function | | - | query 数据提交前的处理函数 |
156
158
  | beforeQuerySearch | Function | Promise\<boolean> | | - | 点击搜索按钮前触发的函数 |
157
159
 
160
+ #### modalConf |
161
+
162
+ | 属性名称 | 属性类型 | 必须 | 默认值 | 描述 |
163
+ | ------------ | ------------- | ---- | ------ | ----------------------------------------------- |
164
+ | width | number/string | 否 | 720 | 弹窗宽度 |
165
+ | okText | string | 否 | | 弹窗底部确定按钮文案 |
166
+ | cancelText | string | 否 | | 弹窗底部取消按钮文案 |
167
+ | footer | Array | 否 | | 自定义弹窗底部按钮 |
168
+ | beforeSubmit | Function | 否 | | 提交前的回调, return false; 表示拦截,不进行请 |
169
+ | 求。 |
170
+ | title | Object | 否 | | 配置弹窗标题 |
171
+
172
+ #### modalConf.title
173
+
174
+ | 属性名称 | 属性类型 | 必须 | 默认值 | 描述 |
175
+ | ---------- | -------- | ---- | ------ | ---------------------------------------------- |
176
+ | createText | string | 否 | | 新增弹窗标题 |
177
+ | createKey | string | 否 | | 新增弹窗标题 key,取自初始值 formInitialValues |
178
+ | editText | string | 否 | | 编辑弹窗标题 |
179
+ | editKey | string | 否 | | 编辑弹窗标题 key,取自当前选中行的 key 的对应值 |
180
+ | detailText | string | 否 | | 详情弹窗标题 |
181
+ | detailKey | string | 否 | | 详情弹窗标题 key,取自当前选中行的 key 的对应值 |
182
+
158
183
  #### model
159
184
 
160
185
  | 属性名称 | 属性类型 | 必须 | 默认值 | 描述 |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hzab/list-render",
3
- "version": "1.10.0-beta1",
3
+ "version": "1.10.0-beta4",
4
4
  "description": "",
5
5
  "main": "src",
6
6
  "scripts": {
@@ -24,6 +24,7 @@
24
24
  "@hzab/data-model": "^1.7.4",
25
25
  "@hzab/form-render": "^1.6.12",
26
26
  "@hzab/formily-result-utils": "^1.2.0",
27
+ "@hzab/permissions": "^1.0.0",
27
28
  "@hzab/schema-descriptions": "^1.3.0",
28
29
  "@hzab/webpack-config": "^0.7.2",
29
30
  "@types/react": "^17.0.62",
@@ -31,6 +32,8 @@
31
32
  "antd": "^4.24.12",
32
33
  "axios": "^1.4.0",
33
34
  "eslint": "^8.30.0",
35
+ "mobx": "^6.7.0",
36
+ "mobx-react": "^7.6.0",
34
37
  "less": "^4.1.3",
35
38
  "lodash": "^4.17.21",
36
39
  "react": "^17.0.2",
@@ -55,5 +58,9 @@
55
58
  },
56
59
  "directories": {
57
60
  "lib": "lib"
61
+ },
62
+ "dependencies": {
63
+ "array-move": "^4.0.0",
64
+ "react-sortable-hoc": "^2.0.0"
58
65
  }
59
66
  }
@@ -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,61 +1,6 @@
1
1
  import _ from "lodash";
2
2
  import { getFieldMap } from "./utils";
3
3
  import { isRunStr, handleSchemaStrVal, isScopeKey as formIsScopeKey, getScopeKeyVal } from '@hzab/form-render/src/common/schema-handler';
4
- import { URL_PARAM_NAME } from "./constant";
5
-
6
- // ===================== 类型定义 =====================
7
-
8
- type AntdDateComponent = 'DatePicker' | 'DatePicker.RangePicker';
9
-
10
- interface XComponentProps {
11
- isSplitTimes?: boolean;
12
- startKey?: string;
13
- endKey?: string;
14
- [k: string]: unknown;
15
- }
16
-
17
- interface FormilyField {
18
- type?: string;
19
- title?: string;
20
- 'x-decorator'?: string;
21
- 'x-component'?: string;
22
- 'x-validator'?: unknown[];
23
- 'x-component-props'?: XComponentProps;
24
- 'x-decorator-props'?: Record<string, unknown>;
25
- 'x-designable-id'?: string;
26
- 'x-index'?: number;
27
- [k: string]: unknown;
28
- }
29
-
30
- interface FormilyV1SchemaNode {
31
- type?: string;
32
- properties?: Record<string, FormilyField>;
33
- [k: string]: unknown;
34
- }
35
-
36
- interface FormilyV1Schema {
37
- form?: Record<string, unknown>;
38
- schema: FormilyV1SchemaNode;
39
- }
40
-
41
- type URLQueryObject = Record<string, any> | null | undefined;
42
-
43
- interface ExtractOptions {
44
- /** 分拆开关字段名,位于 x-component-props;默认 'isSplitTimes' */
45
- splitFlag?: string;
46
- /** 分拆开关的期望值;默认 true */
47
- splitFlagExpectedValue?: unknown;
48
- /** 默认开始/结束键名(当 schema 未显式配置时),默认 'startTime' / 'endTime' */
49
- defaultStartKey?: string;
50
- defaultEndKey?: string;
51
- /** 认为是 antd 日期组件的名单,默认 DatePicker / DatePicker.RangePicker */
52
- antdDateComponents?: readonly AntdDateComponent[];
53
- /**
54
- * 命中并成功赋值后,是否从返回对象中删除对应的 startKey / endKey
55
- * 默认 true(删除)
56
- */
57
- removeMatchedKeys?: boolean;
58
- }
59
4
 
60
5
  export const handleQuerySchema = (opt) => {
61
6
  const { schema, search, filters, onSearch, replaceComList, schemaScope } = opt || {};
@@ -354,174 +299,4 @@ export const getValByScope = (strKey, schemaScope = {}) => {
354
299
  }
355
300
  };
356
301
 
357
- /**
358
- * 将对象序列化后写入 URL query 中
359
- * @param obj 要存储的对象(保持原始类型)
360
- * @param paramName query 参数名
361
- */
362
- export function setURLObjectQueryParam<T extends object>(obj: T, paramName = URL_PARAM_NAME): void {
363
- try {
364
- if (typeof window === "undefined") return;
365
-
366
- const href = window.location.href;
367
- const [origin, hash = ""] = href.split("#");
368
- const [path, queryString = ""] = hash.split("?");
369
- const searchParams = new URLSearchParams(queryString);
370
- const encoded = encodeURIComponent(JSON.stringify(obj));
371
-
372
- searchParams.set(paramName, encoded);
373
-
374
- const newHash = `${path}?${searchParams.toString()}`;
375
-
376
- window.history.replaceState({}, "", `${origin}#${newHash}`);
377
- } catch (e) {
378
- console.error(`[setURLObjectQueryParam] 设置失败:`, e);
379
- }
380
- }
381
-
382
- /**
383
- * 从当前URL中删除指定的查询参数(不刷新页面)
384
- * 专门处理哈希路由中的查询参数
385
- * @param key 要删除的查询参数名称
386
- */
387
- export function removeURLObjectQueryParam(key: string): void {
388
- if (typeof window === "undefined") return;
389
-
390
- try {
391
- const href = window.location.href;
392
- const [origin, hash = ""] = href.split("#");
393
- const [hashPath, queryString = ""] = hash.split("?");
394
- const searchParams = new URLSearchParams(queryString);
395
-
396
- searchParams.delete(key);
397
-
398
- // 重建哈希部分
399
- let newHash = hashPath;
400
- if (searchParams.toString()) {
401
- newHash += `?${searchParams.toString()}`;
402
- }
403
-
404
- const newUrl = `${origin}${newHash ? `#${newHash}` : ''}`;
405
-
406
- window.history.replaceState({}, "", newUrl);
407
- } catch (e) {
408
- console.error(`[removeURLObjectQueryParam] 删除失败:`, e);
409
- }
410
- }
411
- /**
412
- * 从 URL 中解析序列化的对象
413
- * @param paramName query 参数名
414
- * @returns 还原的对象(如果不存在返回 null)
415
- */
416
- export function getURLObjectQueryParam<T = any>(paramName = URL_PARAM_NAME): T | Record<string, any> {
417
- // 返回空对象是为了防止在合并对象时报错导致页面空白
418
- if (typeof window === "undefined") return {};
419
-
420
- const href = window.location.href;
421
- const [, hash = ""] = href.split("#");
422
- const [, queryString = ""] = hash.split("?");
423
- const searchParams = new URLSearchParams(queryString);
424
- const encoded = searchParams.get(paramName);
425
-
426
- if (!encoded) return null;
427
-
428
- try {
429
- return JSON.parse(decodeURIComponent(encoded)) as T;
430
- } catch (e) {
431
- console.error(`[getURLObjectQueryParam] 解析失败:`, e);
432
- return {};
433
- }
434
- }
435
-
436
-
437
- // ===================== 辅助函数 =====================
438
-
439
- const pickFormilyProperties = (schema: FormilyV1Schema): Record<string, FormilyField> =>
440
- (schema?.schema?.properties ?? {});
441
-
442
- const isAntdDateComponent = (comp: unknown, whitelist: readonly string[]) =>
443
- typeof comp === 'string' && whitelist.includes(comp);
444
-
445
- const filterKeys = (props: Record<string, FormilyField>, filters: readonly string[]) => {
446
- const filterSet = new Set(filters);
447
- return Object.entries(props).filter(([k]) => filterSet.has(k));
448
- };
449
-
450
- const matchSplitFlag = (field: FormilyField, splitFlag: string, expected: unknown) =>
451
- field?.['x-component-props']?.[splitFlag] === expected;
452
-
453
- /** 两个值都缺失则返回 undefined;否则返回二元组 */
454
- const getRangeTupleOrUndefined = (
455
- urlObj: URLQueryObject,
456
- startKey: string,
457
- endKey: string
458
- ): [any, any] | undefined => {
459
- const obj = (urlObj ?? {}) as Record<string, any>;
460
- const hasStart = Object.prototype.hasOwnProperty.call(obj, startKey);
461
- const hasEnd = Object.prototype.hasOwnProperty.call(obj, endKey);
462
- if (!hasStart && !hasEnd) return undefined;
463
- return [obj[startKey], obj[endKey]];
464
- };
465
-
466
- // ===================== 主函数 =====================
467
- /**
468
- * 根据formilySchema配置逆解析表单key并将url query赋值
469
- * 三层筛选:根据filters + splitFlag + antdDateComponents 提取formilySchema配置项然后通过配置的key赋值并返回
470
- * */
471
- export function extractSplitDateRanges(
472
- filters: string[],
473
- formilySchema: FormilyV1Schema,
474
- urlObj: URLQueryObject,
475
- options: ExtractOptions = {}
476
- ): Record<string, any> {
477
- const {
478
- splitFlag = 'isSplitTimes',
479
- splitFlagExpectedValue = true,
480
- defaultStartKey = 'startTime',
481
- defaultEndKey = 'endTime',
482
- antdDateComponents = ['DatePicker', 'DatePicker.RangePicker'],
483
- removeMatchedKeys = true,
484
- } = options;
485
-
486
- const properties = pickFormilyProperties(formilySchema);
487
- const candidates = filterKeys(properties, filters);
488
-
489
- // 保持不变性
490
- const base = _.cloneDeep(urlObj) as Record<string, any>;
491
-
492
- // 统一延迟删除,避免顺序影响
493
- const keysToDelete = new Set<string>();
494
-
495
- for (const [fieldKey, field] of candidates) {
496
- // 未命中则直接跳过本次循环
497
- if (!isAntdDateComponent(field?.['x-component'], antdDateComponents)) continue;
498
- if (!matchSplitFlag(field, splitFlag, splitFlagExpectedValue)) continue;
499
-
500
- const props = field?.['x-component-props'] ?? {};
501
- const startKey = (props?.startKey as string) || defaultStartKey;
502
- const endKey = (props?.endKey as string) || defaultEndKey;
503
-
504
- const tuple = getRangeTupleOrUndefined(base, startKey, endKey);
505
- if (!tuple) continue; // 两个值都没有则不赋值、不删除
506
-
507
- // 命中,给 fieldKey 赋值
508
- base[fieldKey] = tuple;
509
-
510
- // 按需记录要删除的键(只删除“命中的”)
511
- if (removeMatchedKeys) {
512
- if (Object.prototype.hasOwnProperty.call(base, startKey)) keysToDelete.add(startKey);
513
- if (Object.prototype.hasOwnProperty.call(base, endKey)) keysToDelete.add(endKey);
514
- }
515
- }
516
-
517
- // 统一执行删除,保证无顺序副作用
518
- if (removeMatchedKeys) {
519
- for (const k of keysToDelete) {
520
- delete base[k];
521
- }
522
- }
523
-
524
- return base;
525
- }
526
-
527
302
  export default handleQuerySchema;
@@ -0,0 +1,180 @@
1
+ import React, { useState, useCallback, useRef } from "react";
2
+ import { Card, Slider, Rate, Form, Button } from "antd";
3
+ import { createSchemaField, FormProvider, FormConsumer } from "@formily/react";
4
+ import { cloneDeep } from "lodash";
5
+
6
+ import { antdComponents, customComponents } from "@hzab/form-render";
7
+
8
+ export interface Item {
9
+ key: string;
10
+ name: string;
11
+ age: number;
12
+ address: string;
13
+ }
14
+
15
+ export interface EditableCellProps extends React.HTMLAttributes<HTMLElement> {
16
+ SchemaField: any;
17
+ field: {
18
+ type: string;
19
+ name: string;
20
+ };
21
+ editing: boolean;
22
+ dataIndex: string;
23
+ title: any;
24
+ inputType: "number" | "text";
25
+ record: Item;
26
+ index: number;
27
+ children: React.ReactNode;
28
+ }
29
+
30
+ export const EditableCell: React.FC<EditableCellProps> = ({
31
+ SchemaField,
32
+ field,
33
+ editing,
34
+ dataIndex,
35
+ title,
36
+ inputType,
37
+ record,
38
+ index,
39
+ children,
40
+ ...restProps
41
+ }) => {
42
+ // 使用 Schema 渲染模式
43
+ return (
44
+ <td {...restProps}>
45
+ {editing ? (
46
+ <SchemaField
47
+ schema={{
48
+ type: "object",
49
+ properties: {
50
+ [field.name]: { ...field, title: "" },
51
+ },
52
+ }}
53
+ />
54
+ ) : (
55
+ children
56
+ )}
57
+ </td>
58
+ );
59
+ };
60
+
61
+ export const useEditTable = (props) => {
62
+ const { schema: _schema, idKey, columns, onEditSubmit, formRender } = props;
63
+
64
+ const schema = _schema?.schema || _schema || {};
65
+ // 创建 formily 表单相关参数
66
+ /** schema scope 解决父级无 schema Scope 导致 scope 对象刷新的问题 */
67
+ const schemaScopeRef = useRef<{ _$tempData: Object }>();
68
+ if (props.schemaScope && !schemaScopeRef.current) {
69
+ schemaScopeRef.current = props.schemaScope;
70
+ } else if (!schemaScopeRef.current) {
71
+ schemaScopeRef.current = { _$tempData: {} };
72
+ }
73
+ if (!schemaScopeRef.current?._$tempData) {
74
+ schemaScopeRef.current._$tempData = {};
75
+ }
76
+ const SchemaField = useCallback(
77
+ createSchemaField({
78
+ components: {
79
+ // Upload,
80
+ Card,
81
+ Slider,
82
+ Rate,
83
+ ...antdComponents,
84
+ ...customComponents,
85
+ ...props.components,
86
+ },
87
+ scope: schemaScopeRef.current,
88
+ }),
89
+ [],
90
+ );
91
+
92
+ // 是否可编辑状态逻辑处理
93
+ const [editingKey, setEditingKey] = useState("");
94
+ /** 判断当前单元格是否处于编辑状态 */
95
+ const isEditing = (record: Item) => record[idKey] === editingKey;
96
+
97
+ /**
98
+ * 点击编辑按钮
99
+ * @param record
100
+ */
101
+ const onEdit = async (record: Partial<Item> & { key: React.Key }) => {
102
+ const value = await (props.onEdit && props.onEdit(record));
103
+ formRender?.setValues(value);
104
+ setEditingKey(record[idKey]);
105
+ };
106
+
107
+ const onCancel = () => {
108
+ setEditingKey("");
109
+ };
110
+
111
+ /**
112
+ * 保存数据
113
+ */
114
+ const onSave = async () => {
115
+ try {
116
+ // 点击保存,数据抛出
117
+ (await formRender?.validate()) as Item;
118
+ onEditSubmit && onEditSubmit(formRender.values);
119
+ // 清除编辑目标
120
+ setEditingKey("");
121
+ } catch (errInfo) {
122
+ console.error("Validate Failed:", errInfo);
123
+ }
124
+ };
125
+
126
+ const mergedColumns = cloneDeep(columns)?.map((col) => {
127
+ if (!col.editable) {
128
+ return col;
129
+ }
130
+ const isActions = col.key === "_$actions";
131
+ const resCol = {
132
+ ...col,
133
+ onCell: (record: Item, ...args) => ({
134
+ ...(col.onCell ? col.onCell(record, ...args) : {}),
135
+ record,
136
+ SchemaField,
137
+ field: col.field,
138
+ dataIndex: col.dataIndex,
139
+ title: col.title,
140
+ editing: isActions ? false : isEditing(record),
141
+ }),
142
+ };
143
+ // 操作列编辑态改成保存、取消按钮
144
+ if (isActions) {
145
+ resCol.render = (record, index) => {
146
+ // 编辑态操作栏变成保存和取消按钮
147
+ if (record[idKey] === editingKey) {
148
+ return (
149
+ <div className="edit-table-actions">
150
+ <Button type="link" onClick={onSave}>
151
+ 保存
152
+ </Button>
153
+ <Button type="text" onClick={onCancel}>
154
+ 取消
155
+ </Button>
156
+ </div>
157
+ );
158
+ }
159
+ return col.render(record, index);
160
+ };
161
+ }
162
+ return resCol;
163
+ });
164
+
165
+ return {
166
+ onEdit,
167
+ SchemaField,
168
+ formRender,
169
+ mergedColumns,
170
+ Form: (props) => {
171
+ return (
172
+ <FormProvider form={formRender}>
173
+ <Form layout={schema?.form?.layout}>
174
+ <FormConsumer>{() => props.children}</FormConsumer>
175
+ </Form>
176
+ </FormProvider>
177
+ );
178
+ },
179
+ };
180
+ };
@@ -21,6 +21,7 @@ export const FormilyField = memo(function (props: formilyFieldPropsT) {
21
21
  const { fields, fieldSchemas } = formilyRef.current || {};
22
22
  const SchemaField = useCallback(
23
23
  createSchemaField({
24
+ // @ts-ignore
24
25
  components: {
25
26
  ...antdComponents,
26
27
  ...customComponents,
@@ -38,7 +39,7 @@ export const FormilyField = memo(function (props: formilyFieldPropsT) {
38
39
  },
39
40
  },
40
41
  scope: { ...schemaScope },
41
- } as any),
42
+ }),
42
43
  [],
43
44
  );
44
45
 
@@ -15,8 +15,6 @@ import FormModal from "./FormModal";
15
15
  import DetailModal from "./DetailModal";
16
16
 
17
17
  import { objToFormData } from "./common/utils";
18
- import { setURLObjectQueryParam, getURLObjectQueryParam, removeURLObjectQueryParam, extractSplitDateRanges } from "./common/handleQuerySchema";
19
- import { URL_PARAM_NAME } from "./common/constant";
20
18
 
21
19
  import "./index.less";
22
20
 
@@ -45,16 +43,6 @@ const ListRender = forwardRef(function (props, parentRef) {
45
43
  * 表单提交是否使用 FormData 格式
46
44
  */
47
45
  useFormData: _useFormData,
48
-
49
- /**
50
- * 筛选条件改变时是否将参数(对象形式)设置到url query中
51
- * */
52
- appendUrlQuery = true,
53
-
54
- /**
55
- * 自定义设置url query对象参数的key
56
- * */
57
- appendUrlQueryKey = URL_PARAM_NAME
58
46
  } = props;
59
47
  const pageSizeOptions = props.paginationConf?.pageSizeOptions || pageSizeOptionMap[props.layout] || [10, 20, 50, 100];
60
48
  // const [pageSizeOptions, setPageSizeOptions] = useState(
@@ -89,7 +77,7 @@ const ListRender = forwardRef(function (props, parentRef) {
89
77
  onDel,
90
78
  }));
91
79
 
92
- const { schema = {}, config = {}, model = {}, msgConf = {}, filters } = props;
80
+ const { schema = {}, config = {}, model = {}, msgConf = {} } = props;
93
81
 
94
82
  // useEffect(() => {
95
83
  // const list = props.paginationConf?.pageSizeOptions || pageSizeOptionMap[props.layout] || [10, 20, 50, 100];
@@ -98,34 +86,20 @@ const ListRender = forwardRef(function (props, parentRef) {
98
86
  // }, [layout]);
99
87
 
100
88
  useEffect(() => {
101
- const getUrlQuery = appendUrlQuery ? getURLObjectQueryParam(appendUrlQueryKey) : {};
102
-
103
89
  if (model) {
104
90
  if (!model.query) {
105
91
  model.query = {};
106
92
  } else {
107
- model.query.pageNum = 1;
108
-
109
93
  modelQueryRef.current = model?.query;
110
94
  paginationQueryRef.current = {
111
- pageNum: getUrlQuery?.pageNum || model?.query?.pageNum || paginationQueryRef.current?.pageNum,
112
- pageSize: getUrlQuery?.pageSize || model?.query?.pageSize || paginationQueryRef.current?.pageSize,
95
+ pageNum: model?.query?.pageNum ?? paginationQueryRef.current?.pageNum,
96
+ pageSize: model?.query?.pageSize ?? paginationQueryRef.current?.pageSize,
113
97
  };
114
98
  }
99
+ model.query.pageNum = 1;
115
100
  }
116
-
117
- // 延迟获取表单实例
118
- Promise.resolve().then(() => {
119
- if (queryRef.current && queryRef.current?.formRef?.current.formRender) {
120
- const extractValues = extractSplitDateRanges(filters, schema, getUrlQuery);
121
-
122
- queryRef.current.formRef.current.formRender?.setValues(extractValues)
123
-
124
- formQueryRef.current = _.cloneDeep(getUrlQuery)
125
- }
126
- })
127
-
128
- !props.closeAutoRequest && getList({ ...(modelQueryRef.current || {}), ...getUrlQuery });
101
+ // 首次自动请求,取 筛选表单的默认值 进行请求
102
+ !props.closeAutoRequest && onSearch(queryFormInitialValues);
129
103
  }, []);
130
104
 
131
105
  useEffect(() => {
@@ -182,6 +156,7 @@ const ListRender = forwardRef(function (props, parentRef) {
182
156
  }
183
157
 
184
158
  // model.query = mergedQueries;
159
+
185
160
  // 取消上一次请求
186
161
  getListSourceRef.current?.cancel({ code: 601, message: "取消上一次请求" });
187
162
 
@@ -221,19 +196,11 @@ const ListRender = forwardRef(function (props, parentRef) {
221
196
  // model.query.pageNum = page;
222
197
  // model.query.pageSize = size;
223
198
  paginationQueryRef.current = { pageNum: page, pageSize: size };
224
-
225
- if (appendUrlQuery) {
226
- const getUrlQuery = getURLObjectQueryParam(appendUrlQueryKey);
227
- setURLObjectQueryParam({ ...getUrlQuery, ...paginationQueryRef.current }, appendUrlQueryKey)
228
- }
229
199
  getList();
230
200
  }
231
201
 
232
- function onSearch(quer, source, isReset = false) {
202
+ function onSearch(quer, source) {
233
203
  const query = source === "queryRender" ? { ...quer } : { ...formQueryRef.current, ...quer };
234
- // 重置操作时不赋值
235
- if (source === "queryRender" && !isReset && appendUrlQuery) setURLObjectQueryParam(query, appendUrlQueryKey);
236
-
237
204
  if (model && !model.query) {
238
205
  model.query = {};
239
206
  }
@@ -244,21 +211,18 @@ const ListRender = forwardRef(function (props, parentRef) {
244
211
  model.query.pageSize = pageSizeOptions[0];
245
212
  }
246
213
  formQueryRef.current = query;
247
- model.query = Object.assign(model.query, query);
214
+ // model.query = Object.assign(model.query, query);
248
215
  getList(query);
249
216
  }
250
217
 
251
- function handleFormReset() {
252
- appendUrlQuery && removeURLObjectQueryParam(appendUrlQueryKey)
253
- }
254
-
255
218
  function forceUpdate() {
256
219
  setList((l) => _.cloneDeep(l));
257
220
  }
258
221
 
259
222
  function onCreate() {
260
223
  setFormState("create");
261
- formModalRef.current.show();
224
+ let title = props.formInitialValues?.[modalConf?.title?.createKey] || modalConf?.title?.createText || "新增";
225
+ formModalRef.current.show(props.formInitialValues, title);
262
226
  }
263
227
 
264
228
  async function onCreateSubmit(data) {
@@ -305,10 +269,12 @@ const ListRender = forwardRef(function (props, parentRef) {
305
269
 
306
270
  function handleDetail(data, id) {
307
271
  setRowId(id);
308
- detailModalRef.current.show(data);
272
+ let title = data[modalConf?.title?.detailKey] || modalConf?.title?.detailText || "详情";
273
+ detailModalRef.current.show(data, title);
309
274
  }
310
275
 
311
276
  function onEdit(row, idx) {
277
+ const { isEditTable } = props;
312
278
  if (props.fetchOnEdit !== false) {
313
279
  const getQuery = {};
314
280
  if (props.fetchById !== false) {
@@ -316,10 +282,10 @@ const ListRender = forwardRef(function (props, parentRef) {
316
282
  } else {
317
283
  getQuery[idKey] = row[idKey];
318
284
  }
319
- model
285
+ return model
320
286
  .get(getQuery)
321
287
  .then((res) => {
322
- handleEdit(res, row[idKey]);
288
+ !isEditTable && handleEdit(res, row[idKey]);
323
289
  })
324
290
  .catch((err) => {
325
291
  console.error("err", err);
@@ -327,14 +293,16 @@ const ListRender = forwardRef(function (props, parentRef) {
327
293
  return Promise.reject(err);
328
294
  });
329
295
  } else {
330
- handleEdit(row, row[idKey]);
296
+ !isEditTable && handleEdit(row, row[idKey]);
297
+ return Promise.resolve(row);
331
298
  }
332
299
  }
333
300
 
334
301
  function handleEdit(data, id) {
335
302
  setRowId(id);
336
303
  setFormState("edit");
337
- formModalRef.current.show(data, "编辑", "edit");
304
+ let title = data[modalConf?.title?.editKey] || modalConf?.title?.editText || "编辑";
305
+ formModalRef.current.show(data, title, "edit");
338
306
  }
339
307
 
340
308
  async function onEditSubmit(data) {
@@ -401,12 +369,15 @@ const ListRender = forwardRef(function (props, parentRef) {
401
369
  search={props.search}
402
370
  filters={props.filters}
403
371
  config={props.queryConf}
404
- queryFormInitialValues={{
405
- ...queryFormInitialValues,
406
- ...(queryFormIsExtendModelQuery ? model.query : {}),
407
- }}
372
+ queryFormInitialValues={
373
+ queryFormIsExtendModelQuery
374
+ ? {
375
+ ...queryFormInitialValues,
376
+ ...model.query,
377
+ }
378
+ : queryFormInitialValues
379
+ }
408
380
  onSearch={onSearch}
409
- onReset={handleFormReset}
410
381
  schemaScope={props.schemaScope}
411
382
  components={props.components}
412
383
  i18n={i18n}
@@ -462,6 +433,7 @@ const ListRender = forwardRef(function (props, parentRef) {
462
433
  Slots={props.Slots}
463
434
  onEdit={onEdit}
464
435
  onDel={onDel}
436
+ setList={setList}
465
437
  onDetail={onDetail}
466
438
  onSearch={onSearch}
467
439
  getList={getList}
@@ -472,6 +444,8 @@ const ListRender = forwardRef(function (props, parentRef) {
472
444
  components={props.components}
473
445
  schemaScope={props.schemaScope}
474
446
  i18n={i18n}
447
+ onEditSubmit={onEditSubmit}
448
+ isEditTable={props.isEditTable}
475
449
  />
476
450
  ) : null}
477
451
 
@@ -54,11 +54,9 @@ function QueryRender(props, parentRef) {
54
54
 
55
55
  function onReset() {
56
56
  formRef.current?.formRender?.reset();
57
- props.onReset?.();
58
- props.onSearch && props.onSearch(_.cloneDeep(formRef?.current?.formRender?.values), "queryRender", true);
57
+ props.onSearch && props.onSearch(_.cloneDeep(formRef?.current?.formRender?.values), "queryRender");
59
58
  }
60
59
 
61
-
62
60
  return (
63
61
  <div className="query-render">
64
62
  {Object.keys(schema?.schema?.properties || {}).length > 0 ? (
@@ -1,8 +1,13 @@
1
- import { useEffect, useState, useMemo, useCallback, useRef } from "react";
2
- import { Table, Button, Popconfirm, Tooltip, Checkbox, Popover } from "antd";
3
- import { QuestionCircleOutlined, FilterOutlined, SettingOutlined } from "@ant-design/icons";
1
+ import { useEffect, useState, useMemo, useRef } from "react";
2
+ import { Form, Table, Button, Popconfirm, Tooltip, Checkbox, Popover } from "antd";
3
+ import { QuestionCircleOutlined, FilterOutlined, SettingOutlined, MenuOutlined } from "@ant-design/icons";
4
+ import { SortableContainer, SortableElement, SortableHandle } from "react-sortable-hoc";
5
+ import { arrayMoveImmutable } from "array-move";
4
6
  import _ from "lodash";
5
7
 
8
+ import { FormProvider, FormConsumer } from "@formily/react";
9
+ import { createForm, onFormValuesChange, onFieldValueChange } from "@formily/core";
10
+
6
11
  import EnumRender from "@hzab/formily-result-utils/src/components/EnumRender";
7
12
  import { SHOW_MODE_TYPES } from "@hzab/formily-result-utils/src/common/constant";
8
13
  import { FormilyField } from "../components/Formily/FormilyField";
@@ -11,14 +16,19 @@ import { getColRender } from "../common/formily-utils";
11
16
  import { getVal, getFieldList } from "../common/utils";
12
17
  import { handleReactions } from "../common/handleReactions";
13
18
 
19
+ import { useEditTable, EditableCell } from "../components/Formily/FormilyEditTable";
20
+
14
21
  import "./index.less";
15
22
 
16
23
  const scenario = "table-render";
17
24
 
18
25
  function TableRender(props) {
19
- const { config = {}, query = {}, i18n } = props;
26
+ const { isEditTable, config = {}, query = {}, i18n, setList } = props;
20
27
  const { tableDel = "删除", tableEdit = "编辑", tableDelTip = "确认删除该项?", tableDetail = "详情" } = i18n || {};
21
28
  const {
29
+ dragColConf = {},
30
+ isDargTable,
31
+ dargEndBack,
22
32
  orderColType,
23
33
  orderColWidth,
24
34
  tableEmptyValue,
@@ -28,12 +38,58 @@ function TableRender(props) {
28
38
 
29
39
  const [columns, setColumns] = useState([]);
30
40
  const [columnList, setColumnList] = useState([]);
41
+ const DragHandle = SortableHandle(() => <MenuOutlined style={{ cursor: "grab", color: "#999" }} />);
42
+
43
+ const SortableItem = SortableElement((props) => <tr {...props} />);
44
+ const SortableBody = SortableContainer((props) => <tbody {...props} />);
45
+
46
+ const onSortEnd = ({ oldIndex, newIndex }) => {
47
+ if (oldIndex !== newIndex) {
48
+ const newData = arrayMoveImmutable(props.list.slice(), oldIndex, newIndex).filter((el) => !!el);
49
+ setList([...newData]);
50
+ dargEndBack && dargEndBack(newData, query);
51
+ }
52
+ };
53
+
54
+ const DraggableContainer = (props) => (
55
+ <SortableBody useDragHandle disableAutoscroll helperClass="row-dragging" onSortEnd={onSortEnd} {...props} />
56
+ );
57
+
58
+ const DraggableBodyRow = ({ className, style, ...restProps }) => {
59
+ // function findIndex base on Table rowKey props and should always be a right array index
60
+ const index = props.list.findIndex((x) => x[props.idKey || "id"] === restProps["data-row-key"]);
61
+ return <SortableItem index={index} {...restProps} />;
62
+ };
31
63
 
32
64
  const formilyRef = useRef({
33
65
  fields: {},
34
66
  fieldSchemas: {},
35
67
  });
36
68
 
69
+ const formRender = useMemo(
70
+ () =>
71
+ createForm({
72
+ initialValues: props.initialValues,
73
+ // 禁用状态(注意,自定义组件组件自行获取对应的状态)
74
+ readOnly: props.readOnly,
75
+ disabled: props.disabled,
76
+ ...(props.formOptions || {}),
77
+ effects(...args) {
78
+ props.onFormValuesChange && onFormValuesChange(props.onFormValuesChange);
79
+ props.onFieldValueChange && onFieldValueChange("*", props.onFieldValueChange);
80
+ props.formOptions?.effects && props.formOptions?.effects(...args);
81
+ },
82
+ }),
83
+ [],
84
+ );
85
+ const { onEdit: onEditByTable, mergedColumns } = useEditTable({
86
+ idKey: props.idKey,
87
+ columns,
88
+ onEdit: props.onEdit,
89
+ onEditSubmit: props.onEditSubmit,
90
+ formRender,
91
+ });
92
+
37
93
  useEffect(() => {
38
94
  if (!(props.schema && props.schema.properties)) {
39
95
  return;
@@ -154,6 +210,8 @@ function TableRender(props) {
154
210
  }
155
211
 
156
212
  columns.push({
213
+ field,
214
+ editable: true,
157
215
  ..._colConf,
158
216
  onCell: (record, rowIndex) =>
159
217
  _colConf?.onCell?.({ ...record, _field: { ...field, ...(fieldSchemas?.[name] || {}) } }, rowIndex) || {},
@@ -172,6 +230,7 @@ function TableRender(props) {
172
230
 
173
231
  columns.push({
174
232
  ..._colConf,
233
+ editable: isEditTable,
175
234
  title: "操作",
176
235
  key: "_$actions",
177
236
  render: getColRender(function (text, record, index) {
@@ -213,6 +272,10 @@ function TableRender(props) {
213
272
  <Button
214
273
  type="link"
215
274
  onClick={() => {
275
+ // 可编辑表格使用对应回调
276
+ if (isEditTable) {
277
+ return onEditByTable && onEditByTable(record, index);
278
+ }
216
279
  props.onEdit && props.onEdit(record, index);
217
280
  }}
218
281
  >
@@ -240,6 +303,16 @@ function TableRender(props) {
240
303
  });
241
304
  }
242
305
 
306
+ if (isDargTable) {
307
+ columns.unshift({
308
+ title: "",
309
+ dataIndex: "sort",
310
+ width: 60,
311
+ fixed: "left",
312
+ render: () => <DragHandle />,
313
+ ...dragColConf,
314
+ });
315
+ }
243
316
  setColumns(columns);
244
317
  setColumnList(columns);
245
318
  }, [props.schema, props.config]);
@@ -260,6 +333,39 @@ function TableRender(props) {
260
333
  }
261
334
  };
262
335
 
336
+ const tableProps = {
337
+ className: "table-render",
338
+ rowKey: props.idKey || "id",
339
+ rowSelection: config?.rowSelection,
340
+ columns: columns,
341
+ dataSource: props.list,
342
+ pagination: false,
343
+ scroll: config.scroll,
344
+ expandable: config.expandable,
345
+ loading: props.loading,
346
+ onRow: config?.onRow,
347
+ ...props.tableProps,
348
+ };
349
+
350
+ if (isDargTable) {
351
+ tableProps.components = {
352
+ body: {
353
+ wrapper: DraggableContainer,
354
+ row: DraggableBodyRow,
355
+ },
356
+ };
357
+ }
358
+
359
+ if (isEditTable) {
360
+ tableProps.columns = mergedColumns;
361
+ tableProps.components = {
362
+ body: {
363
+ ...tableProps?.components?.body,
364
+ cell: EditableCell,
365
+ },
366
+ };
367
+ }
368
+
263
369
  return (
264
370
  <div className="table-render-wrap">
265
371
  {isShowTableFilter ? (
@@ -302,19 +408,15 @@ function TableRender(props) {
302
408
  </Popover>
303
409
  </div>
304
410
  ) : null}
305
- <Table
306
- className="table-render"
307
- rowKey={props.idKey || "id"}
308
- rowSelection={config?.rowSelection}
309
- columns={columns}
310
- dataSource={props.list}
311
- pagination={false}
312
- scroll={config.scroll}
313
- expandable={config.expandable}
314
- loading={props.loading}
315
- onRow={config?.onRow}
316
- {...props.tableProps}
317
- />
411
+ {isEditTable ? (
412
+ <FormProvider form={formRender}>
413
+ <Form layout="vertical">
414
+ <FormConsumer>{() => <Table {...tableProps} />}</FormConsumer>
415
+ </Form>
416
+ </FormProvider>
417
+ ) : (
418
+ <Table {...tableProps} />
419
+ )}
318
420
  <FormilyField
319
421
  schema={props.schema}
320
422
  formilyRef={formilyRef}
@@ -5,37 +5,62 @@
5
5
  justify-content: flex-end;
6
6
  align-items: center;
7
7
  margin-bottom: 12px;
8
+
8
9
  .table-filter {
9
10
  font-size: 16px;
10
11
  cursor: pointer;
12
+
11
13
  .table-filter-icon {
12
14
  margin: 0 4px 0 10px;
13
15
  cursor: pointer;
14
16
  }
15
17
  }
16
18
  }
19
+
17
20
  .inline-block-max-w {
18
21
  display: inline-block;
19
22
  max-width: 100%;
20
23
  }
24
+
21
25
  .col-title-tooltip-icon {
22
26
  margin-left: 8px;
23
27
  }
28
+
24
29
  .table-render {
25
30
  border-top: 1px solid #f0f0f0;
26
31
  }
32
+
27
33
  .table-cell-ellipsis {
28
34
  overflow: hidden;
29
35
  white-space: nowrap;
30
36
  text-overflow: ellipsis;
31
37
  }
38
+
32
39
  }
40
+
41
+ .row-dragging {
42
+ background: #FFF;
43
+ border: 1px solid #ccc;
44
+ display: flex;
45
+ justify-content: space-between;
46
+ align-items: center;
47
+ }
48
+
49
+ .row-dragging td {
50
+ padding: 16px;
51
+ }
52
+
53
+ .row-dragging .drag-visible {
54
+ visibility: visible;
55
+ }
56
+
33
57
  .table-popover-content {
34
58
  max-width: 400px;
35
59
  display: flex;
36
60
  flex-direction: column;
61
+
37
62
  .ant-checkbox-wrapper {
38
63
  margin-bottom: 8px;
39
64
  margin-left: 0 !important;
40
65
  }
41
- }
66
+ }
@@ -1,2 +0,0 @@
1
- // 设置url query参数时默认key名称
2
- export const URL_PARAM_NAME = "defaultSearchParams";