@fe-free/core 2.7.0 → 2.7.1

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,5 +1,12 @@
1
1
  # @fe-free/core
2
2
 
3
+ ## 2.7.1
4
+
5
+ ### Patch Changes
6
+
7
+ - feat: record
8
+ - @fe-free/tool@2.7.1
9
+
3
10
  ## 2.7.0
4
11
 
5
12
  ### Minor Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fe-free/core",
3
- "version": "2.7.0",
3
+ "version": "2.7.1",
4
4
  "description": "",
5
5
  "main": "./src/index.ts",
6
6
  "author": "",
@@ -41,7 +41,7 @@
41
41
  "remark-gfm": "^4.0.1",
42
42
  "vanilla-jsoneditor": "^0.23.1",
43
43
  "zustand": "^4.5.4",
44
- "@fe-free/tool": "2.7.0"
44
+ "@fe-free/tool": "2.7.1"
45
45
  },
46
46
  "peerDependencies": {
47
47
  "@ant-design/pro-components": "2.8.9",
@@ -244,11 +244,15 @@ export const ProFormRecordComponent: Story = {
244
244
  name="record1"
245
245
  label="record1"
246
246
  fieldProps={{
247
- defaultItems: [
247
+ labels: [
248
248
  { key: 'username', label: '用户名' },
249
249
  { key: 'password', label: '密码' },
250
250
  ],
251
251
  }}
252
+ initialValue={{
253
+ username: '',
254
+ password: '',
255
+ }}
252
256
  />
253
257
  <ProFormRecord name="record2" label="record2" />
254
258
  </ProFormBase>
@@ -262,11 +266,15 @@ export const ProFormRecordArrayComponent: Story = {
262
266
  name="recordArray1"
263
267
  label="recordArray1"
264
268
  fieldProps={{
265
- defaultItems: [
269
+ labels: [
266
270
  { key: 'username', label: '用户名' },
267
271
  { key: 'password', label: '密码' },
268
272
  ],
269
273
  }}
274
+ initialValue={[
275
+ { key: 'username', value: undefined },
276
+ { key: 'password', value: undefined },
277
+ ]}
270
278
  />
271
279
  <ProFormRecordArray name="recordArray2" label="recordArray2" />
272
280
  </ProFormBase>
@@ -1,5 +1,6 @@
1
1
  import { DeleteOutlined, PlusOutlined } from '@ant-design/icons';
2
2
  import { Button } from 'antd';
3
+ import classNames from 'classnames';
3
4
 
4
5
  interface ProFormListHelperProps<T> {
5
6
  value?: T[];
@@ -12,7 +13,10 @@ interface ProFormListHelperProps<T> {
12
13
  }) => React.ReactNode;
13
14
  addText?: string;
14
15
  getAdd: () => T;
16
+ disabledAdd?: boolean;
17
+ disabledDelete?: boolean;
15
18
  readOnly?: boolean;
19
+ className?: string;
16
20
  }
17
21
 
18
22
  const emptyArr = [];
@@ -20,7 +24,7 @@ function ProFormListHelper<T = any>(props: ProFormListHelperProps<T>) {
20
24
  const options = props.value || emptyArr;
21
25
 
22
26
  return (
23
- <div className="flex flex-col gap-2">
27
+ <div className={classNames('flex flex-col gap-2', props.className)}>
24
28
  <div className="flex flex-col gap-2">
25
29
  {options.map((item, index) => {
26
30
  return (
@@ -37,7 +41,7 @@ function ProFormListHelper<T = any>(props: ProFormListHelperProps<T>) {
37
41
  },
38
42
  })}
39
43
  </div>
40
- {!props.readOnly && (
44
+ {!props.readOnly && !props.disabledDelete && (
41
45
  <Button
42
46
  icon={<DeleteOutlined />}
43
47
  type="text"
@@ -52,7 +56,7 @@ function ProFormListHelper<T = any>(props: ProFormListHelperProps<T>) {
52
56
  );
53
57
  })}
54
58
  </div>
55
- {!props.readOnly && (
59
+ {!props.readOnly && !props.disabledAdd && (
56
60
  <div className="flex justify-center">
57
61
  <Button
58
62
  size="small"
@@ -7,7 +7,22 @@ function ProFormRecord(props: ProFormItemProps<RecordProps>) {
7
7
  const { fieldProps, ...rest } = props;
8
8
 
9
9
  return (
10
- <ProForm.Item {...rest}>
10
+ <ProForm.Item
11
+ {...rest}
12
+ rules={[
13
+ ...(props.rules || []),
14
+ {
15
+ validator: async (_, value) => {
16
+ const values = Object.values(value || {});
17
+ if (values.length && values.filter(Boolean).length !== values.length) {
18
+ return Promise.reject('选项不能为空');
19
+ }
20
+
21
+ return Promise.resolve();
22
+ },
23
+ },
24
+ ]}
25
+ >
11
26
  <Record {...(fieldProps as RecordProps)} />
12
27
  </ProForm.Item>
13
28
  );
@@ -17,7 +32,22 @@ function ProFormRecordArray(props: ProFormItemProps<RecordArrayProps>) {
17
32
  const { fieldProps, ...rest } = props;
18
33
 
19
34
  return (
20
- <ProForm.Item {...rest}>
35
+ <ProForm.Item
36
+ {...rest}
37
+ rules={[
38
+ ...(props.rules || []),
39
+ {
40
+ validator: async (_, value) => {
41
+ console.log('value', value);
42
+ if (value?.some((item) => item.value === undefined || item.key === undefined)) {
43
+ return Promise.reject('选项不能为空');
44
+ }
45
+
46
+ return Promise.resolve();
47
+ },
48
+ },
49
+ ]}
50
+ >
21
51
  <RecordArray {...(fieldProps as RecordArrayProps)} />
22
52
  </ProForm.Item>
23
53
  );
@@ -1,6 +1,7 @@
1
- import { Button, Divider, Input } from 'antd';
1
+ import { Divider, Input } from 'antd';
2
2
  import classNames from 'classnames';
3
- import { Fragment, useCallback, useMemo, useState } from 'react';
3
+ import { useCallback, useMemo } from 'react';
4
+ import { ProFormListHelper } from '../form';
4
5
 
5
6
  function Item({
6
7
  value,
@@ -8,7 +9,7 @@ function Item({
8
9
  onChange,
9
10
  }: {
10
11
  value?: string;
11
- label: string;
12
+ label?: string;
12
13
  onChange: (value: string) => void;
13
14
  }) {
14
15
  return (
@@ -31,20 +32,20 @@ function Item({
31
32
  interface RecordItem {
32
33
  value?: { key?: string; value?: string };
33
34
  onChange: (value: { key?: string; value?: string }) => void;
34
- item: { key?: string; label?: string; placeholder?: string };
35
+ label?: string;
35
36
  }
36
37
 
37
38
  function RecordItem(props: RecordItem) {
38
- const { value, onChange, item } = props;
39
+ const { value, onChange, label } = props;
39
40
 
40
- // 如果提供了 key
41
- if (item.key) {
41
+ // 如果提供了 label
42
+ if (label) {
42
43
  return (
43
44
  <Item
44
45
  value={value?.value}
45
- label={item.label || item.key}
46
+ label={label || value?.key}
46
47
  onChange={(v) => {
47
- onChange({ key: item.key, value: v });
48
+ onChange({ key: value?.key, value: v });
48
49
  }}
49
50
  />
50
51
  );
@@ -73,45 +74,42 @@ function RecordItem(props: RecordItem) {
73
74
  interface RecordArrayProps {
74
75
  value?: { key?: string; value?: string }[];
75
76
  onChange: (value: { key?: string; value?: string }[]) => void;
76
- defaultItems?: { key: string; label: string }[];
77
+ labels?: { key?: string; label?: string }[];
77
78
  className?: string;
78
79
  }
79
80
 
80
81
  function RecordArray(props: RecordArrayProps) {
81
- const { value, onChange, defaultItems, className } = props;
82
- const [items, setItems] = useState<{ name?: string; label?: string }[]>(defaultItems || [{}]);
82
+ const { value, onChange, labels, className } = props;
83
+
84
+ const isFixed = !!labels?.length;
83
85
 
84
86
  return (
85
- <div className={classNames('c-bg flex flex-col gap-2 rounded p-2', className)}>
86
- {(items || [{}])?.map((item, index) => {
87
- const v = value?.[index] || {};
87
+ <ProFormListHelper
88
+ className={classNames('c-bg rounded p-2', className)}
89
+ value={value}
90
+ onChange={onChange}
91
+ getAdd={() => ({
92
+ key: undefined,
93
+ value: undefined,
94
+ })}
95
+ disabledDelete={isFixed}
96
+ disabledAdd={isFixed}
97
+ >
98
+ {({ item, index, onItemChange }) => {
88
99
  return (
89
- <Fragment key={index}>
100
+ <>
90
101
  <RecordItem
91
- item={item}
92
- value={v}
102
+ value={item}
103
+ label={labels?.[index]?.label}
93
104
  onChange={(v) => {
94
- const newValues = [...(value || [])];
95
- newValues[index] = v || {};
96
- onChange(newValues);
105
+ onItemChange(v);
97
106
  }}
98
107
  />
99
- {!defaultItems && <Divider className="my-2" />}
100
- </Fragment>
108
+ {!isFixed && <Divider className="mb-2" />}
109
+ </>
101
110
  );
102
- })}
103
- {!defaultItems && (
104
- <div className="flex flex-col items-center">
105
- <Button
106
- onClick={() => {
107
- setItems((v) => [...v, {}]);
108
- }}
109
- >
110
- 添加
111
- </Button>
112
- </div>
113
- )}
114
- </div>
111
+ }}
112
+ </ProFormListHelper>
115
113
  );
116
114
  }
117
115
 
@@ -121,8 +119,9 @@ interface RecordProps extends Omit<RecordArrayProps, 'value' | 'onChange'> {
121
119
  }
122
120
 
123
121
  function Record(props: RecordProps) {
124
- const { value, onChange, defaultItems, className } = props;
122
+ const { value, onChange, ...rest } = props;
125
123
 
124
+ // obj 和 arr 的转换
126
125
  const newValue = useMemo(() => {
127
126
  return Object.keys(value || {}).map((key) => ({
128
127
  key,
@@ -130,13 +129,13 @@ function Record(props: RecordProps) {
130
129
  }));
131
130
  }, [value]);
132
131
 
132
+ // obj 和 arr 的转换
133
133
  const newOnChange = useCallback(
134
134
  (newV: { key?: string; value?: string }[]) => {
135
135
  const newValues = {};
136
- newV.forEach((item) => {
137
- if (item.key) {
138
- newValues[item.key] = item.value;
139
- }
136
+ newV.forEach((item, index) => {
137
+ // 确保有值
138
+ newValues[item.key || index] = item.value;
140
139
  });
141
140
 
142
141
  onChange(newValues);
@@ -144,14 +143,7 @@ function Record(props: RecordProps) {
144
143
  [onChange],
145
144
  );
146
145
 
147
- return (
148
- <RecordArray
149
- value={newValue}
150
- onChange={newOnChange}
151
- defaultItems={defaultItems}
152
- className={className}
153
- />
154
- );
146
+ return <RecordArray value={newValue} onChange={newOnChange} {...rest} />;
155
147
  }
156
148
 
157
149
  export { Record, RecordArray };