@hzab/form-render-mobile 0.2.3 → 0.2.4
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/lib/index.js +1 -1
- package/package.json +1 -1
- package/src/components/LocationPicker/common/utils.ts +0 -4
- package/src/components/LocationPicker/components/ModalContent/index.less +48 -0
- package/src/components/LocationPicker/components/ModalContent/index.tsx +202 -0
- package/src/components/LocationPicker/components/PickerInfo/index.tsx +31 -26
- package/src/components/LocationPicker/index.less +1 -47
- package/src/components/LocationPicker/index.tsx +123 -189
- package/src/index.less +6 -4
|
@@ -1,35 +1,28 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Popup, Button
|
|
1
|
+
import { useRef, useState } from "react";
|
|
2
|
+
import { Popup, Button } from "antd-mobile";
|
|
3
3
|
import { useField, useFieldSchema } from "@formily/react";
|
|
4
|
-
import { LocationFill } from "antd-mobile-icons";
|
|
5
|
-
import { debounce } from "lodash";
|
|
6
4
|
|
|
7
5
|
import ResInfo from "./components/ResInfo";
|
|
8
|
-
|
|
9
|
-
import PickerInfo from "./components/PickerInfo";
|
|
10
|
-
import AMapCom from "./Map/AMap";
|
|
11
|
-
import Notice from "./components/Notice";
|
|
6
|
+
import ModalContent from "./components/ModalContent";
|
|
12
7
|
|
|
13
8
|
import { MapUtils } from "./Map/AMap/common/utils";
|
|
14
9
|
import { getCurrentPosition } from "../../common/location-utils";
|
|
15
|
-
import
|
|
16
|
-
|
|
17
|
-
import { getAddress } from "./servers/index";
|
|
18
|
-
import { getPropsValue, getParentValue } from "./common/utils";
|
|
10
|
+
import { getParentValue } from "./common/utils";
|
|
19
11
|
|
|
20
12
|
import "./index.less";
|
|
21
13
|
|
|
22
|
-
const
|
|
23
|
-
lon: 120.
|
|
24
|
-
lat: 30.
|
|
14
|
+
const defaultLocation = {
|
|
15
|
+
lon: 120.168893,
|
|
16
|
+
lat: 30.225404,
|
|
17
|
+
addr: "浙江省杭州市上城区南星街道杭州西湖风景名胜区",
|
|
25
18
|
};
|
|
26
19
|
|
|
27
20
|
// 获取当前经纬度
|
|
28
21
|
getCurrentPosition()
|
|
29
22
|
.then((res) => {
|
|
30
23
|
const { coords = {} } = res;
|
|
31
|
-
|
|
32
|
-
|
|
24
|
+
defaultLocation.lon = coords.longitude;
|
|
25
|
+
defaultLocation.lat = coords.latitude;
|
|
33
26
|
})
|
|
34
27
|
.catch((e) => {
|
|
35
28
|
console.warn("Error getCurrentPosition e: ", e);
|
|
@@ -37,6 +30,18 @@ getCurrentPosition()
|
|
|
37
30
|
|
|
38
31
|
export function LocationPicker(props) {
|
|
39
32
|
const {
|
|
33
|
+
/**
|
|
34
|
+
* 地图显示类型:
|
|
35
|
+
* 弹窗 dialog
|
|
36
|
+
* 直接显示 show
|
|
37
|
+
*/
|
|
38
|
+
mode = "dialog",
|
|
39
|
+
/**
|
|
40
|
+
* 选择器和地图的布局
|
|
41
|
+
* 水平 hor
|
|
42
|
+
* 垂直 ver
|
|
43
|
+
*/
|
|
44
|
+
layout = "ver",
|
|
40
45
|
// 是否允许搜索
|
|
41
46
|
hasSearch = true,
|
|
42
47
|
/**
|
|
@@ -52,8 +57,8 @@ export function LocationPicker(props) {
|
|
|
52
57
|
isAutoFixAddr = false,
|
|
53
58
|
/**
|
|
54
59
|
* 改变经纬度等数据的触发模式
|
|
55
|
-
*
|
|
56
|
-
*
|
|
60
|
+
* 移动地图 move
|
|
61
|
+
* 点击地图 click
|
|
57
62
|
*/
|
|
58
63
|
changeMode = "move",
|
|
59
64
|
lonKey = "longitude",
|
|
@@ -62,128 +67,15 @@ export function LocationPicker(props) {
|
|
|
62
67
|
value,
|
|
63
68
|
// 搜索框是否自动搜索
|
|
64
69
|
isAutoSearch = true,
|
|
65
|
-
// 是否是移动端,changeMode == 'move' 时改变监听事件
|
|
66
|
-
isMobile = true,
|
|
67
70
|
} = props;
|
|
68
71
|
const field: any = useField();
|
|
69
72
|
const fieldSchema = useFieldSchema();
|
|
70
73
|
|
|
71
74
|
const mapUtilsRef = useRef<MapUtils>();
|
|
75
|
+
const pickInfoRef = useRef(defaultLocation);
|
|
72
76
|
|
|
73
77
|
const [loading, setLoading] = useState(false);
|
|
74
|
-
const [addrLoading, setAddrLoading] = useState(false);
|
|
75
78
|
const [visible, setVisible] = useState(false);
|
|
76
|
-
// 数据格式转为内部格式,方便存取
|
|
77
|
-
const opt = {
|
|
78
|
-
isObjectRes,
|
|
79
|
-
lonKey,
|
|
80
|
-
latKey,
|
|
81
|
-
addrKey,
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
const formatVal = useMemo(
|
|
85
|
-
() => getPropsValue(value, field, opt),
|
|
86
|
-
[isObjectRes, lonKey, latKey, addrKey, value, field.data],
|
|
87
|
-
);
|
|
88
|
-
|
|
89
|
-
// 地图选点组件选中的值
|
|
90
|
-
const [pickInfo, setPickInfo] = useState(formatVal);
|
|
91
|
-
|
|
92
|
-
useEffect(() => {
|
|
93
|
-
if (visible) {
|
|
94
|
-
let _lon = defaultLngLat.lon;
|
|
95
|
-
let _lat = defaultLngLat.lat;
|
|
96
|
-
if (formatVal.lon && formatVal.lat) {
|
|
97
|
-
_lon = formatVal.lon;
|
|
98
|
-
_lat = formatVal.lat;
|
|
99
|
-
}
|
|
100
|
-
// 解决关闭弹窗之后点位不居中的问题
|
|
101
|
-
if (window.AMap && window.AMap.LngLat) {
|
|
102
|
-
setMapCenter(_lon, _lat);
|
|
103
|
-
}
|
|
104
|
-
setPoint(_lon, _lat, { isAutoFixAddr: false });
|
|
105
|
-
}
|
|
106
|
-
}, [visible, formatVal, changeMode]);
|
|
107
|
-
|
|
108
|
-
useEffect(() => {
|
|
109
|
-
setPickInfo(formatVal);
|
|
110
|
-
}, [formatVal, isAutoFixAddr]);
|
|
111
|
-
|
|
112
|
-
function mapInit({ map, mapUtils }) {
|
|
113
|
-
mapUtilsRef.current = mapUtils;
|
|
114
|
-
setLoading(false);
|
|
115
|
-
let _lon = defaultLngLat.lon;
|
|
116
|
-
let _lat = defaultLngLat.lat;
|
|
117
|
-
if (pickInfo.lon && pickInfo.lat) {
|
|
118
|
-
_lon = pickInfo.lon;
|
|
119
|
-
_lat = pickInfo.lat;
|
|
120
|
-
}
|
|
121
|
-
setPoint(_lon, _lat, { isAutoFixAddr });
|
|
122
|
-
|
|
123
|
-
setMapCenter(_lon, _lat);
|
|
124
|
-
if (changeMode === "click") {
|
|
125
|
-
mapUtilsRef.current?.setPickerMarker(_lon, _lat);
|
|
126
|
-
// 点击选中点位的情况
|
|
127
|
-
mapUtilsRef.current.on("click", function (ev) {
|
|
128
|
-
const { lng: evLon, lat: evLat } = ev.lnglat || {};
|
|
129
|
-
setPoint(evLon, evLat, { changeCenter: true });
|
|
130
|
-
});
|
|
131
|
-
} else {
|
|
132
|
-
// 移动地图
|
|
133
|
-
mapUtilsRef.current.on(
|
|
134
|
-
isMobile ? "touchend" : "mouseup",
|
|
135
|
-
debounce(function (ev) {
|
|
136
|
-
let currentCenter = mapUtilsRef.current?.getCenter();
|
|
137
|
-
const { lng: centerLon, lat: centerLat } = currentCenter || {};
|
|
138
|
-
// 移动选中点位的情况
|
|
139
|
-
let _lon = centerLon;
|
|
140
|
-
let _lat = centerLat;
|
|
141
|
-
setPoint(_lon, _lat);
|
|
142
|
-
}, 1000),
|
|
143
|
-
);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* 设置地图中心点
|
|
149
|
-
* @param lon
|
|
150
|
-
* @param lat
|
|
151
|
-
*/
|
|
152
|
-
function setMapCenter(lon, lat) {
|
|
153
|
-
mapUtilsRef.current?.setCenter(lon, lat);
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
function setPoint(_lon, _lat, opt?: any) {
|
|
157
|
-
const { isAutoFixAddr: _isAutoFixAddr = isAutoFixAddr || true, changeCenter } = opt || {};
|
|
158
|
-
const lon = _lon || pickInfo.lon;
|
|
159
|
-
const lat = _lat || pickInfo.lat;
|
|
160
|
-
(_isAutoFixAddr || !pickInfo.addr) && getAddr(lon, lat);
|
|
161
|
-
const res = { ...pickInfo, lon, lat, center: [lon, lat] };
|
|
162
|
-
setPickInfo(res);
|
|
163
|
-
if (changeMode === "click") {
|
|
164
|
-
mapUtilsRef.current?.setPickerMarker(_lon, _lat);
|
|
165
|
-
}
|
|
166
|
-
if (changeCenter) {
|
|
167
|
-
setMapCenter(_lon, _lat);
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
function getAddr(_lng, _lat) {
|
|
172
|
-
if (!window.AMap) {
|
|
173
|
-
return "";
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
setAddrLoading(true);
|
|
177
|
-
getAddress(_lng, _lat)
|
|
178
|
-
.then((addr) => {
|
|
179
|
-
setAddrLoading(false);
|
|
180
|
-
setPickInfo((_p) => ({ ..._p, addr }));
|
|
181
|
-
})
|
|
182
|
-
.catch((err) => {
|
|
183
|
-
Toast.show({ icon: "fail", content: err });
|
|
184
|
-
setAddrLoading(false);
|
|
185
|
-
});
|
|
186
|
-
}
|
|
187
79
|
|
|
188
80
|
function onShow() {
|
|
189
81
|
// 等待地图加载完毕
|
|
@@ -193,81 +85,123 @@ export function LocationPicker(props) {
|
|
|
193
85
|
|
|
194
86
|
function onClose() {
|
|
195
87
|
setVisible(false);
|
|
196
|
-
setLoading(false);
|
|
197
88
|
}
|
|
198
89
|
|
|
199
|
-
function
|
|
200
|
-
const
|
|
201
|
-
|
|
202
|
-
[
|
|
203
|
-
[
|
|
90
|
+
function onChange(res = pickInfoRef.current) {
|
|
91
|
+
const info = res || pickInfoRef.current;
|
|
92
|
+
const _res = {
|
|
93
|
+
[lonKey]: info.lon,
|
|
94
|
+
[latKey]: info.lat,
|
|
95
|
+
[addrKey]: info.addr,
|
|
204
96
|
};
|
|
205
|
-
props.onChange && props.onChange(
|
|
97
|
+
props.onChange && props.onChange(_res);
|
|
206
98
|
if (isObjectRes === false) {
|
|
207
99
|
// 只有一层的情况
|
|
208
100
|
if (!field.parent) {
|
|
209
|
-
field.form.setValues(
|
|
101
|
+
field.form.setValues(_res);
|
|
210
102
|
} else if (field.parent && fieldSchema.parent) {
|
|
211
103
|
// 嵌套在 ArrayBase: ArrayTable ArrayCard 等 里面的情况
|
|
212
104
|
const parentVal = getParentValue(field);
|
|
213
|
-
Object.keys(
|
|
214
|
-
parentVal[key] =
|
|
105
|
+
Object.keys(_res).forEach((key) => {
|
|
106
|
+
parentVal[key] = _res[key];
|
|
215
107
|
});
|
|
216
108
|
}
|
|
217
109
|
}
|
|
110
|
+
}
|
|
218
111
|
|
|
112
|
+
function onOk() {
|
|
113
|
+
onChange();
|
|
219
114
|
onClose();
|
|
220
115
|
}
|
|
221
116
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
onMaskClick={onClose}
|
|
231
|
-
onClose={onClose}
|
|
232
|
-
bodyStyle={{
|
|
233
|
-
minHeight: "80vh",
|
|
234
|
-
maxHeight: "100vh",
|
|
235
|
-
}}
|
|
236
|
-
visible={visible}
|
|
237
|
-
>
|
|
238
|
-
<div className="location-popup-header">
|
|
239
|
-
<Button fill="none" onClick={onClose}>
|
|
240
|
-
取消
|
|
241
|
-
</Button>
|
|
242
|
-
<Button color="primary" fill="none" onClick={onOk} loading={addrLoading || loading}>
|
|
243
|
-
确认
|
|
244
|
-
</Button>
|
|
245
|
-
</div>
|
|
117
|
+
function setResInfo(res) {
|
|
118
|
+
setPickInfo(res);
|
|
119
|
+
onChange(res);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function setPickInfo(res) {
|
|
123
|
+
pickInfoRef.current = res;
|
|
124
|
+
}
|
|
246
125
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
126
|
+
const _props = {
|
|
127
|
+
/**
|
|
128
|
+
* 地图显示类型:
|
|
129
|
+
* 弹窗 dialog
|
|
130
|
+
* 直接显示 show
|
|
131
|
+
*/
|
|
132
|
+
mode: mode ?? "dialog",
|
|
133
|
+
/**
|
|
134
|
+
* 选择器和地图的布局
|
|
135
|
+
* 水平 hor
|
|
136
|
+
* 垂直 ver
|
|
137
|
+
*/
|
|
138
|
+
layout: layout ?? "ver",
|
|
139
|
+
// 是否允许搜索
|
|
140
|
+
hasSearch: hasSearch ?? true,
|
|
141
|
+
/**
|
|
142
|
+
*
|
|
143
|
+
isObjectRes
|
|
144
|
+
true: 把所有数据存放在一个对象中(该对象和其他表单项平级),对象 key 为当前项的 name
|
|
145
|
+
false: 所有数据打平放到当前的 data 中,和其他表单项平级
|
|
146
|
+
*/
|
|
147
|
+
isObjectRes: isObjectRes ?? true,
|
|
148
|
+
/**
|
|
149
|
+
* 打开地图时是否根据经纬度自动修正已填的地址
|
|
150
|
+
*/
|
|
151
|
+
isAutoFixAddr: isAutoFixAddr ?? false,
|
|
152
|
+
/**
|
|
153
|
+
* 改变经纬度等数据的触发模式
|
|
154
|
+
* 移动地图:move
|
|
155
|
+
* 点击地图:click
|
|
156
|
+
*/
|
|
157
|
+
changeMode: changeMode ?? "move",
|
|
158
|
+
lonKey: lonKey ?? "longitude",
|
|
159
|
+
latKey: latKey ?? "latitude",
|
|
160
|
+
addrKey: addrKey ?? "address",
|
|
161
|
+
value,
|
|
162
|
+
// 搜索框是否自动搜索
|
|
163
|
+
isAutoSearch: isAutoSearch ?? true,
|
|
164
|
+
defaultLocation,
|
|
165
|
+
};
|
|
256
166
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
{
|
|
265
|
-
|
|
266
|
-
|
|
167
|
+
return (
|
|
168
|
+
<div className="location-picker">
|
|
169
|
+
{mode === "show" ? (
|
|
170
|
+
<ModalContent {..._props} visible={visible} setPickInfo={setResInfo} layout={layout} />
|
|
171
|
+
) : (
|
|
172
|
+
<>
|
|
173
|
+
{/* 弹窗 */}
|
|
174
|
+
{/* 有弹窗时,显示表单选中的结果 */}
|
|
175
|
+
<ResInfo {..._props} onShow={onShow} />
|
|
176
|
+
<Popup
|
|
177
|
+
maskClassName="location-picker-popup-mask"
|
|
178
|
+
className="location-picker-popup"
|
|
179
|
+
onMaskClick={onClose}
|
|
180
|
+
onClose={onClose}
|
|
181
|
+
bodyStyle={{
|
|
182
|
+
minHeight: "78vh",
|
|
183
|
+
maxHeight: "100vh",
|
|
184
|
+
}}
|
|
185
|
+
visible={visible}
|
|
186
|
+
>
|
|
187
|
+
<div className="location-popup-header">
|
|
188
|
+
<Button fill="none" onClick={onClose}>
|
|
189
|
+
取消
|
|
190
|
+
</Button>
|
|
191
|
+
<Button color="primary" fill="none" onClick={onOk} loading={loading}>
|
|
192
|
+
确认
|
|
193
|
+
</Button>
|
|
267
194
|
</div>
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
195
|
+
<ModalContent
|
|
196
|
+
{..._props}
|
|
197
|
+
visible={visible}
|
|
198
|
+
setPickInfo={setPickInfo}
|
|
199
|
+
layout={layout}
|
|
200
|
+
setLoading={setLoading}
|
|
201
|
+
/>
|
|
202
|
+
</Popup>
|
|
203
|
+
</>
|
|
204
|
+
)}
|
|
271
205
|
</div>
|
|
272
206
|
);
|
|
273
207
|
}
|
package/src/index.less
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
.form-render {
|
|
2
|
+
font-size: 4vw;
|
|
3
|
+
.adm-formily-item {
|
|
4
|
+
font-size: 4vw;
|
|
5
|
+
}
|
|
2
6
|
.adm-list-body {
|
|
3
7
|
background-color: unset;
|
|
4
8
|
.adm-card-body {
|
|
5
9
|
.adm-list-item-content {
|
|
6
10
|
border-top: unset;
|
|
7
11
|
}
|
|
8
|
-
.adm-formily-item{
|
|
9
|
-
font-size: 30px ;
|
|
10
|
-
}
|
|
11
12
|
}
|
|
12
13
|
}
|
|
13
14
|
.picker-box {
|
|
@@ -37,7 +38,8 @@
|
|
|
37
38
|
}
|
|
38
39
|
}
|
|
39
40
|
|
|
40
|
-
& .adm-radio,
|
|
41
|
+
& .adm-radio,
|
|
42
|
+
& .adm-checkbox {
|
|
41
43
|
padding-right: 10px;
|
|
42
44
|
}
|
|
43
45
|
}
|