@hzab/form-render-mobile 0.3.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/lib/index.js +1 -1
  2. package/package.json +1 -1
  3. package/src/components/LocationPicker/Map/AMap/common/loader.ts +1 -1
  4. package/src/components/LocationPicker/Map/AMap/common/utils.ts +15 -4
  5. package/src/components/LocationPicker/Map/AMap/index.jsx +3 -2
  6. package/src/components/LocationPicker/README.md +31 -22
  7. package/src/components/LocationPicker/assets/svg-icon.js +86 -0
  8. package/src/components/LocationPicker/common/utils.ts +2 -9
  9. package/src/components/LocationPicker/components/ModalContent/index.less +18 -4
  10. package/src/components/LocationPicker/components/ModalContent/index.tsx +45 -62
  11. package/src/components/LocationPicker/components/Notice/index.tsx +1 -1
  12. package/src/components/LocationPicker/components/ResInfo/index.less +9 -10
  13. package/src/components/LocationPicker/components/ResInfo/index.tsx +20 -18
  14. package/src/components/LocationPicker/index.tsx +24 -72
  15. package/src/components/LocationPicker/servers/index.ts +54 -26
  16. package/src/components/TreeSelect/SelectList/index.tsx +59 -25
  17. package/src/components/TreeSelect/common/data-handler.ts +158 -3
  18. package/src/components/TreeSelect/index.less +1 -0
  19. package/src/components/TreeSelect/index.tsx +8 -1
  20. package/src/index.less +5 -2
  21. package/lib/static/imgs/marker-icon_ab8bbcc8cb.svg +0 -4
  22. package/lib/static/imgs/picker-icon_24d725ef02.svg +0 -5
  23. package/lib/static/imgs/position-icon_5bcb8a742e.svg +0 -6
  24. package/lib/static/imgs/reset-icon_9edad62306.svg +0 -5
  25. package/src/components/LocationPicker/assets/marker-icon.svg +0 -4
  26. package/src/components/LocationPicker/assets/picker-icon.svg +0 -5
  27. package/src/components/LocationPicker/assets/position-icon.svg +0 -6
  28. package/src/components/LocationPicker/assets/reset-icon.svg +0 -5
@@ -1,17 +1,18 @@
1
1
  import { useEffect, useRef, useState } from "react";
2
2
  import { Popup, Button } from "antd-mobile";
3
- import { useField, useFieldSchema } from "@formily/react";
3
+ import { observer } from "@formily/react";
4
4
 
5
5
  import ResInfo from "./components/ResInfo";
6
6
  import ModalContent from "./components/ModalContent";
7
7
 
8
8
  import { MapUtils } from "./Map/AMap/common/utils";
9
9
  import { getCurrentPosition } from "../../common/location-utils";
10
- import { getParentValue, getPropsValue } from "./common/utils";
10
+ import { getPropsValue } from "./common/utils";
11
+ import { getAddress } from "./servers";
11
12
 
12
13
  import "./index.less";
13
14
 
14
- export function LocationPicker(props) {
15
+ export const LocationPicker = observer(function (props: any) {
15
16
  const {
16
17
  /**
17
18
  * 地图显示类型:
@@ -33,47 +34,32 @@ export function LocationPicker(props) {
33
34
  * 展示获取经纬度的按钮
34
35
  */
35
36
  showGetPositionBtn = true,
36
- /**
37
- *
38
- isObjectRes
39
- true: 把所有数据存放在一个对象中(该对象和其他表单项平级),对象 key 为当前项的 name
40
- false: 所有数据打平放到当前的 data 中,和其他表单项平级
41
- */
42
- isObjectRes = true,
43
37
  /**
44
38
  * 打开地图时是否根据经纬度自动修正已填的地址
45
39
  */
46
40
  isAutoFixAddr = false,
47
- /**
48
- * 改变经纬度等数据的触发模式
49
- * 移动地图 move
50
- * 点击地图 click
51
- */
52
- changeMode = "move",
53
41
  lonKey = "longitude",
54
42
  latKey = "latitude",
55
43
  addrKey = "address",
56
44
  value,
57
45
  // 搜索框是否自动搜索
58
46
  isAutoSearch = true,
47
+ icons = {},
59
48
  } = props;
60
- const field: any = useField();
61
- const fieldSchema = useFieldSchema();
62
49
 
63
- const [loading, setLoading] = useState(true);
64
50
  const [defaultLocation, setDefaultLocation] = useState({
65
51
  lon: 120.168893,
66
52
  lat: 30.225404,
67
53
  addr: "浙江省杭州市上城区南星街道杭州西湖风景名胜区",
68
54
  });
55
+ const [loading, setLoading] = useState(false);
69
56
  const [visible, setVisible] = useState(false);
70
57
 
71
58
  const mapUtilsRef = useRef<MapUtils>();
72
59
  const pickInfoRef = useRef(defaultLocation);
73
60
 
74
61
  useEffect(() => {
75
- const propsVal = getPropsValue(value, field, {
76
- isObjectRes,
62
+ const propsVal = getPropsValue(value, {
77
63
  lonKey,
78
64
  latKey,
79
65
  addrKey,
@@ -83,12 +69,17 @@ export function LocationPicker(props) {
83
69
  // 如果没有传入的经纬度,获取当前实际的经纬度数据
84
70
  // 获取当前经纬度
85
71
  getCurrentPosition()
86
- .then((res) => {
72
+ .then(async (res) => {
87
73
  const { coords = {} } = res;
74
+ const lon = coords.longitude;
75
+ const lat = coords.latitude;
76
+ const addr: string = await getAddress(lon, lat).then((addr) => {
77
+ return addr;
78
+ });
88
79
  pickInfoRef.current = {
89
- lon: coords.longitude,
90
- lat: coords.latitude,
91
- addr: "",
80
+ lon,
81
+ lat,
82
+ addr,
92
83
  };
93
84
  setDefaultLocation(pickInfoRef.current);
94
85
  setLoading(false);
@@ -120,18 +111,6 @@ export function LocationPicker(props) {
120
111
  [addrKey]: info.addr,
121
112
  };
122
113
  props.onChange && props.onChange(_res);
123
- if (isObjectRes === false) {
124
- // 只有一层的情况
125
- if (!field.parent) {
126
- field.form.setValues(_res);
127
- } else if (field.parent && fieldSchema.parent) {
128
- // 嵌套在 ArrayBase: ArrayTable ArrayCard 等 里面的情况
129
- const parentVal = getParentValue(field);
130
- Object.keys(_res).forEach((key) => {
131
- parentVal[key] = _res[key];
132
- });
133
- }
134
- }
135
114
  }
136
115
 
137
116
  function onOk() {
@@ -149,8 +128,7 @@ export function LocationPicker(props) {
149
128
  }
150
129
 
151
130
  const _props = {
152
- disabled: props.disabled,
153
- readOnly: props.readOnly,
131
+ ...props,
154
132
  /**
155
133
  * 地图显示类型:
156
134
  * 弹窗 dialog
@@ -165,23 +143,10 @@ export function LocationPicker(props) {
165
143
  layout: layout ?? "ver",
166
144
  // 是否允许搜索
167
145
  hasSearch: hasSearch ?? true,
168
- /**
169
- *
170
- isObjectRes
171
- true: 把所有数据存放在一个对象中(该对象和其他表单项平级),对象 key 为当前项的 name
172
- false: 所有数据打平放到当前的 data 中,和其他表单项平级
173
- */
174
- isObjectRes: isObjectRes ?? true,
175
146
  /**
176
147
  * 打开地图时是否根据经纬度自动修正已填的地址
177
148
  */
178
149
  isAutoFixAddr: isAutoFixAddr ?? false,
179
- /**
180
- * 改变经纬度等数据的触发模式
181
- * 移动地图:move
182
- * 点击地图:click
183
- */
184
- changeMode: changeMode ?? "move",
185
150
  lonKey: lonKey ?? "longitude",
186
151
  latKey: latKey ?? "latitude",
187
152
  addrKey: addrKey ?? "address",
@@ -189,27 +154,21 @@ export function LocationPicker(props) {
189
154
  // 搜索框是否自动搜索
190
155
  isAutoSearch: isAutoSearch ?? true,
191
156
  defaultLocation,
192
- // 地图选点按钮的 icon 元素
193
- pickerIcon: props.pickerIcon,
194
157
  showGetPositionBtn,
158
+ visible,
159
+ loading,
160
+ setLoading,
195
161
  };
196
162
 
197
163
  return (
198
164
  <div className="location-picker">
199
165
  {mode === "show" ? (
200
- <ModalContent
201
- {..._props}
202
- visible={visible}
203
- setPickInfo={setResInfo}
204
- layout={layout}
205
- setLoading={setLoading}
206
- loading={loading}
207
- />
166
+ <ModalContent {..._props} setPickInfo={setResInfo} />
208
167
  ) : (
209
168
  <>
210
169
  {/* 弹窗 */}
211
170
  {/* 有弹窗时,显示表单选中的结果 */}
212
- <ResInfo {..._props} onShow={onShow} />
171
+ <ResInfo {..._props} onShow={onShow} pickerIcon={icons.pickerIcon} />
213
172
  <Popup
214
173
  maskClassName="location-picker-popup-mask"
215
174
  className="location-picker-popup"
@@ -229,19 +188,12 @@ export function LocationPicker(props) {
229
188
  确认
230
189
  </Button>
231
190
  </div>
232
- <ModalContent
233
- {..._props}
234
- visible={visible}
235
- setPickInfo={setPickInfo}
236
- layout={layout}
237
- setLoading={setLoading}
238
- loading={loading}
239
- />
191
+ <ModalContent {..._props} setPickInfo={setPickInfo} />
240
192
  </Popup>
241
193
  </>
242
194
  )}
243
195
  </div>
244
196
  );
245
- }
197
+ });
246
198
 
247
199
  export default LocationPicker;
@@ -1,13 +1,33 @@
1
+ export interface addressErrorI extends Error {
2
+ result?: string;
3
+ }
4
+
1
5
  /**
2
6
  * 根据经纬度获取定义的地址
3
7
  * @param lon
4
8
  * @param lat
5
9
  * @returns
6
10
  */
7
- export function getAddress(lon, lat) {
11
+ export function getAddress(lon, lat): Promise<string> {
12
+ return new Promise((resolve, reject) => {
13
+ getAddressByAMap(lon, lat)
14
+ .then(resolve)
15
+ .catch((err) => {
16
+ if (err.result === "USER_DAILY_QUERY_OVER_LIMIT" || err.result === "A_MAP_IS_NOT_DEFINED") {
17
+ getAddressByFetch(lon, lat).then(resolve).catch(reject);
18
+ } else {
19
+ reject(err);
20
+ }
21
+ });
22
+ });
23
+ }
24
+
25
+ export const getAddressByAMap = function (lon, lat): Promise<string> {
8
26
  return new Promise((resolve, reject) => {
9
27
  if (!window.AMap) {
10
- reject(Error("Error getAddress window.AMap is not defined."));
28
+ const error: addressErrorI = Error("Error getAddress window.AMap is not defined.");
29
+ error.result = "A_MAP_IS_NOT_DEFINED";
30
+ reject(error);
11
31
  return;
12
32
  }
13
33
  const geocoder = new window.AMap.Geocoder({});
@@ -17,35 +37,43 @@ export function getAddress(lon, lat) {
17
37
  resolve(formattedAddress);
18
38
  return formattedAddress;
19
39
  } else if (result === "USER_DAILY_QUERY_OVER_LIMIT") {
20
- // 超出限制,使用 webServer 进行请求
21
- if (!window._AMapLoaderTemp.serverKey) {
22
- reject(new Error("超出使用限制,请联系管理员"));
23
- return;
24
- }
25
- fetch(
26
- `https://restapi.amap.com/v3/geocode/regeo?location=${lon?.toFixed(6)},${lat?.toFixed(6)}&key=${
27
- window._AMapLoaderTemp.serverKey
28
- }`,
29
- {
30
- mode: "cors",
31
- },
32
- )
33
- .then((res) => res.json())
34
- .then((res) => {
35
- if (res.status === "1") {
36
- resolve(res.regeocode?.formatted_address);
37
- } else {
38
- console.warn("Warn getAddress fetch: ", res);
39
- reject(new Error(res.info));
40
- }
41
- })
42
- .catch(reject);
40
+ const error: addressErrorI = new Error("超出使用限制,请联系管理员");
41
+ error.result = result;
42
+ reject(error);
43
43
  } else {
44
44
  reject(result);
45
45
  }
46
46
  });
47
47
  });
48
- }
48
+ };
49
+
50
+ export const getAddressByFetch = function (lon, lat): Promise<string> {
51
+ return new Promise((resolve, reject) => {
52
+ // 超出限制,使用 webServer 进行请求
53
+ if (!window._AMapLoaderTemp.serverKey) {
54
+ reject(new Error("请配置 serverKey"));
55
+ return;
56
+ }
57
+ fetch(
58
+ `https://restapi.amap.com/v3/geocode/regeo?location=${lon?.toFixed(6)},${lat?.toFixed(6)}&key=${
59
+ window._AMapLoaderTemp.serverKey
60
+ }`,
61
+ {
62
+ mode: "cors",
63
+ },
64
+ )
65
+ .then((res) => res.json())
66
+ .then((res) => {
67
+ if (res.status === "1") {
68
+ resolve(res.regeocode?.formatted_address);
69
+ } else {
70
+ console.warn("Warn getAddressByFetch: ", res);
71
+ reject(new Error(res.info));
72
+ }
73
+ })
74
+ .catch(reject);
75
+ });
76
+ };
49
77
 
50
78
  /**
51
79
  * 获取搜索提示
@@ -1,29 +1,59 @@
1
- import { useEffect, useRef, useState } from "react";
1
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
2
2
  import { Checkbox } from "antd-mobile";
3
3
  import { DownOutline, UpOutline } from "antd-mobile-icons";
4
4
  import { List as VirtualizedList, AutoSizer } from "react-virtualized";
5
5
  import _ from "lodash";
6
6
 
7
- import { getTreeAllExpandKeys, flatActiveTreeData } from "../common/data-handler";
7
+ import { getTreeAllExpandKeys, flatActiveTreeData, handleChecked, initChecked } from "../common/data-handler";
8
8
 
9
9
  import "./index.less";
10
10
 
11
11
  export const SelectList = (props) => {
12
- const { multiple, selected, treeData, fieldNames, setSelected, treeDefaultExpandAll } = props;
12
+ const {
13
+ multiple,
14
+ selected,
15
+ // 处理过的数据(搜索等)
16
+ treeData,
17
+ // 源数据
18
+ dataSource,
19
+ fieldNames,
20
+ setSelected = () => {},
21
+ treeDefaultExpandAll,
22
+ treeCheckStrictly,
23
+ } = props;
13
24
  const { label: labelKey = "label", value: valueKey = "value", children: childrenKey = "children" } = fieldNames || {};
14
25
 
15
26
  const [activeKeys, setActiveKeys] = useState(
16
27
  treeDefaultExpandAll ? getTreeAllExpandKeys(treeData, { fieldNames }) : [],
17
28
  );
18
29
 
30
+ const checkedOpt = {
31
+ fieldNames,
32
+ treeCheckStrictly,
33
+ };
34
+
19
35
  const boxRef = useRef();
20
36
  const [boxH, setBoxH] = useState(0);
37
+ const [treeDataChecked, setTreeDataChecked] = useState(
38
+ initChecked(treeData, multiple ? selected : [selected], checkedOpt),
39
+ );
21
40
  const [list, setList] = useState(flatActiveTreeData(treeData, activeKeys, { fieldNames }));
41
+ const selectedRef = useRef(selected);
42
+
43
+ useEffect(() => {
44
+ selectedRef.current = selected;
45
+ }, [selected]);
22
46
 
23
47
  useEffect(() => {
24
- const _activeKeys = treeDefaultExpandAll ? getTreeAllExpandKeys(treeData, { fieldNames }) : [];
48
+ const _treeDataChecked = initChecked(
49
+ treeData,
50
+ Array.isArray(selectedRef.current) ? selectedRef.current : [selectedRef.current],
51
+ checkedOpt,
52
+ );
53
+ const _activeKeys = treeDefaultExpandAll ? getTreeAllExpandKeys(_treeDataChecked, { fieldNames }) : [];
25
54
  setActiveKeys(_activeKeys);
26
- setList(flatActiveTreeData(treeData, _activeKeys, { fieldNames }));
55
+ setList(flatActiveTreeData(_treeDataChecked, _activeKeys, { fieldNames }));
56
+ setTreeDataChecked(_treeDataChecked);
27
57
  }, [treeData]);
28
58
 
29
59
  useEffect(() => {
@@ -50,42 +80,44 @@ export const SelectList = (props) => {
50
80
  } else {
51
81
  keys.push(val);
52
82
  }
53
- setList(flatActiveTreeData(treeData, keys, { fieldNames }));
83
+ setList(flatActiveTreeData(treeDataChecked, keys, { fieldNames }));
54
84
  return [...keys];
55
85
  });
56
86
  }
57
87
 
58
88
  function onCheckboxChange(key, val) {
89
+ // 处理选中状态
59
90
  if (multiple) {
60
91
  // 多选
61
- setSelected &&
62
- setSelected((v = []) => {
63
- if (val) {
64
- // 选中则往选中数组中添加
65
- return _.uniq([...v, key]);
66
- }
67
- // 非选中,从选中数组中剔除
68
- const idx = v.findIndex((it) => it === key);
69
- if (idx >= 0) {
70
- v.splice(idx, 1);
71
- return [...v];
72
- }
73
- return v;
74
- });
92
+ const checkedRes = handleChecked(treeDataChecked, key, val, checkedOpt);
93
+ const treeDataRes = _.cloneDeep(checkedRes.treeData);
94
+ setTreeDataChecked(treeDataRes);
95
+ setList(flatActiveTreeData(checkedRes.treeData, activeKeys, { fieldNames }));
96
+ setSelected(checkedRes.selected);
75
97
  } else {
76
98
  setSelected(key);
77
99
  }
78
100
  }
79
101
 
80
- function rowRender({ index, key: listKey, style }: { index: number; key: string; style: ElementCSSInlineStyle }) {
102
+ // TODO: useCallback 优化
103
+ const rowRender = function ({
104
+ index,
105
+ key: listKey,
106
+ style,
107
+ }: {
108
+ index: number;
109
+ key: string;
110
+ style: ElementCSSInlineStyle;
111
+ }) {
81
112
  const it = list[index];
82
113
  if (!it) {
83
114
  return null;
84
115
  }
85
116
 
86
117
  const itKey = it[valueKey];
87
- const checked = multiple ? selected?.includes(itKey) : selected === itKey;
118
+
88
119
  const active = activeKeys.includes(itKey);
120
+
89
121
  return (
90
122
  <div
91
123
  className="virtualized-list-item"
@@ -102,16 +134,18 @@ export const SelectList = (props) => {
102
134
  <Checkbox
103
135
  key={itKey}
104
136
  value={itKey}
105
- checked={checked}
137
+ indeterminate={it._indeterminate}
138
+ checked={it._checked}
139
+ disabled={it.disabled}
106
140
  onClick={onStopPropagation}
107
141
  onChange={(v) => onCheckboxChange(itKey, v)}
108
142
  >
109
- {it[labelKey]}
143
+ {it[labelKey]}-{itKey}
110
144
  </Checkbox>
111
145
  {it.hasChildren && (active ? <UpOutline className="arrow-icon" /> : <DownOutline className="arrow-icon" />)}
112
146
  </div>
113
147
  );
114
- }
148
+ };
115
149
 
116
150
  return (
117
151
  <div className="tree-select-list" ref={boxRef}>
@@ -1,3 +1,5 @@
1
+ import _ from "lodash";
2
+
1
3
  /**
2
4
  * 获取列表枚举数据
3
5
  * @param list
@@ -14,14 +16,24 @@ export const getDataEnum = function (list, opt?: any) {
14
16
  level,
15
17
  fullPathLabels: [...(parent.fullPathLabels || []), it[label]],
16
18
  fullPathValues: [...(parent.fullPathValues || []), it[value]],
19
+ parentEnum: { ...parent.parentEnum },
17
20
  };
21
+ if (parent[value]) {
22
+ item.parentEnum[parent[value]] = 1;
23
+ }
18
24
  item.fullPathItems = [...(parent.fullPathItems || []), item];
19
25
  delete item[children];
20
26
 
21
27
  dataEnum[it[value]] = item;
22
28
 
23
- if (it[children]) {
24
- getDataEnum(it[children], { ...opt, dataEnum, parent: item });
29
+ const childrenList = it[children];
30
+ if (childrenList) {
31
+ const childrenEnum = {};
32
+ childrenList.forEach((it) => {
33
+ childrenEnum[it[value]] = 1;
34
+ });
35
+ item.childrenEnum = childrenEnum;
36
+ getDataEnum(childrenList, { ...opt, dataEnum, parent: item });
25
37
  }
26
38
  });
27
39
  return dataEnum;
@@ -89,21 +101,32 @@ export const flatActiveTreeData = function (treeData, activeKeys = [], opt?: any
89
101
  const { list = [], fieldNames, parent = {}, level = 1 } = opt || {};
90
102
  const { value = "value", children = "children", label = "label" } = fieldNames || {};
91
103
  treeData?.forEach((it) => {
104
+ const childrenList = it?.[children];
92
105
  const item = {
93
106
  ...it,
94
107
  parent,
95
108
  level,
96
109
  fullPathLabel: [...(parent.fullPathLabel || []), it[label]],
110
+ fullPathValues: [...(parent.fullPathValues || []), it[value]],
111
+ parentEnum: { ...parent.parentEnum },
112
+ childrenLen: childrenList?.length || 0,
97
113
  };
114
+ if (parent[value]) {
115
+ item.parentEnum[parent[value]] = 1;
116
+ }
98
117
  item.fullPathItems = [...(parent.fullPathItems || []), item];
99
118
 
100
119
  if (item.parentId === null || item.parentId === undefined || item.parentId === "") {
101
120
  item.parentId = parent[value];
102
121
  }
103
- const childrenList = it?.[children];
104
122
  delete item[children];
105
123
  list.push(item);
106
124
  if (Array.isArray(childrenList) && childrenList.length > 0) {
125
+ const childrenEnum = {};
126
+ childrenList.forEach((it) => {
127
+ childrenEnum[it[value]] = 1;
128
+ });
129
+ item.childrenEnum = childrenEnum;
107
130
  item.hasChildren = true;
108
131
  activeKeys.includes(it[value]) &&
109
132
  flatActiveTreeData(childrenList, activeKeys, {
@@ -133,3 +156,135 @@ export const getTreeAllExpandKeys = function (treeData, opt?: any) {
133
156
  });
134
157
  return expandKeys;
135
158
  };
159
+
160
+ export const removeAllSelected = function (treeData, selected = [], opt?: any) {
161
+ const { fieldNames } = opt || {};
162
+ const { value = "value", children = "children" } = fieldNames || {};
163
+ treeData?.forEach((it) => {
164
+ const key = it[value];
165
+ const idx = selected.findIndex((k) => k === key);
166
+ idx >= 0 && selected.splice(idx, 1);
167
+ const childList = it[children];
168
+ if (Array.isArray(childList) && childList.length > 0) {
169
+ removeAllSelected(childList, selected, opt);
170
+ }
171
+ });
172
+ return selected;
173
+ };
174
+
175
+ /**
176
+ * 处理选中状态
177
+ * @param treeData
178
+ * @param key
179
+ * @param val
180
+ * @param opt
181
+ * @returns
182
+ * _checked 选中状态
183
+ * _indeterminate 半选状态(只在父子联动中使用)
184
+ */
185
+ export const handleChecked = function (treeData, targetKey, targetVal, opt) {
186
+ const {
187
+ fieldNames,
188
+ /**
189
+ * 是否是父子联动
190
+ */
191
+ treeCheckStrictly,
192
+ selected = [],
193
+ } = opt || {};
194
+ const { value = "value", children = "children" } = fieldNames || {};
195
+ const dataLen = treeData?.length;
196
+ let checkedCount = 0;
197
+ let indeterminate = false;
198
+ for (let i = 0; i < dataLen; i++) {
199
+ const it = treeData[i];
200
+ const key = it[value];
201
+ // 处理禁用、只读状态?
202
+ if (key === targetKey) {
203
+ it._checked = targetVal;
204
+ it._indeterminate = false;
205
+ if (treeCheckStrictly) {
206
+ // 父子联动,处理当前项子项的选中状态,所有子项跟随当前项
207
+ setAllChecked(it[children], targetVal, opt);
208
+ // 结束当前项的处理,当前项及父级的状态由上层遍历处理
209
+ }
210
+ } else {
211
+ const childList = it[children];
212
+ if (Array.isArray(childList) && childList.length > 0) {
213
+ const childRes = handleChecked(childList, targetKey, targetVal, { ...opt, selected });
214
+ if (treeCheckStrictly) {
215
+ // 父子联动,处理父级的选中、半选状态
216
+ it._checked = childRes._checked;
217
+ it._indeterminate = childRes._indeterminate;
218
+ // 子项有半选,则父级也是半选
219
+ if (it._indeterminate && !it._checked) {
220
+ indeterminate = true;
221
+ }
222
+ if (it._checked) {
223
+ it._indeterminate = false;
224
+ removeAllSelected(childList, selected, opt);
225
+ }
226
+ }
227
+ }
228
+ }
229
+
230
+ if (it._checked) {
231
+ // 当前项处理完处理选中状态,checkedCount + 1, key 添加到 selected 数组中
232
+ checkedCount += 1;
233
+ selected.push(key);
234
+ }
235
+ }
236
+
237
+ return {
238
+ treeData,
239
+ checkedCount,
240
+ _checked: dataLen > 0 && checkedCount === dataLen,
241
+ _indeterminate: indeterminate || (checkedCount > 0 && checkedCount < dataLen),
242
+ selected,
243
+ };
244
+ };
245
+
246
+ /**
247
+ * 初始化选中状态
248
+ * @param _treeData
249
+ * @param opt
250
+ * _checked 选中状态
251
+ * _indeterminate 半选状态(只在父子联动中使用)
252
+ */
253
+ export const initChecked = function (_treeData, selected, opt) {
254
+ const treeData = _.cloneDeep(_treeData);
255
+ _.uniq(selected || [])?.forEach((it) => {
256
+ handleChecked(treeData, it, true, opt);
257
+ });
258
+ return treeData;
259
+ };
260
+
261
+ /**
262
+ * 设置所有项的选中状态
263
+ * @param treeData
264
+ * @param targetVal
265
+ * @param opt
266
+ */
267
+ export const setAllChecked = function (treeData, targetVal, opt) {
268
+ const { fieldNames } = opt || {};
269
+ const { children = "children" } = fieldNames || {};
270
+ treeData?.forEach((it) => {
271
+ it._checked = targetVal;
272
+ it._indeterminate = undefined;
273
+ const childList = it[children];
274
+ if (Array.isArray(childList) && childList.length > 0) {
275
+ setAllChecked(childList, targetVal, opt);
276
+ }
277
+ });
278
+ return treeData;
279
+ };
280
+ /**
281
+ * 清除所有的选中状态
282
+ * @param treeData
283
+ * @param opt
284
+ * @returns
285
+ * _checked 选中状态
286
+ * _indeterminate 半选状态
287
+ */
288
+ export const cleanChecked = function (treeData, opt) {
289
+ return setAllChecked(treeData, undefined, opt);
290
+ };
@@ -1,6 +1,7 @@
1
1
  .formily-tree-select {
2
2
  height: 100%;
3
3
  .tree-selected {
4
+ flex: 1;
4
5
  height: 100%;
5
6
  }
6
7
  }
@@ -122,7 +122,14 @@ export const TreeSelect = observer((props: any) => {
122
122
  {showSearch && (
123
123
  <TreeSearch visible={visible} dataSource={dataSource} setTreeData={setTreeData} fieldNames={fieldNames} />
124
124
  )}
125
- <SelectList {...props} visible={visible} treeData={treeData} selected={selected} setSelected={setSelected} />
125
+ <SelectList
126
+ {...props}
127
+ visible={visible}
128
+ dataSource={dataSource}
129
+ treeData={treeData}
130
+ selected={selected}
131
+ setSelected={setSelected}
132
+ />
126
133
  </div>
127
134
  </Popup>
128
135
  </PickerRightOutline>
package/src/index.less CHANGED
@@ -3,10 +3,13 @@
3
3
  .adm-formily-item {
4
4
  font-size: 4vw;
5
5
  .adm-formily-item-label {
6
- line-height: 1.2;
6
+ line-height: 1.5;
7
7
  }
8
8
  .adm-formily-item-error-help {
9
- line-height: 1.2;
9
+ line-height: 1.5;
10
+ }
11
+ .adm-formily-item-control .adm-formily-item-control-content .adm-formily-item-control-content-component {
12
+ line-height: 1.5;
10
13
  }
11
14
  }
12
15
  .adm-list-body {