@hzab/form-render 1.1.0 → 1.1.2
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/lib/index.js +1 -1
- package/package.json +1 -1
- package/src/common/schema-merge.ts +68 -0
- package/src/components/LocationListPicker/assets/icon.js +1 -0
- package/src/components/LocationListPicker/components/AddrList/index.less +13 -2
- package/src/components/LocationListPicker/components/AddrList/index.tsx +13 -6
- package/src/components/LocationListPicker/components/Popup/address.schema.json +21 -0
- package/src/components/LocationListPicker/components/Popup/index.tsx +13 -8
- package/src/components/LocationListPicker/index.less +1 -3
- package/src/components/LocationListPicker/index.tsx +109 -16
- package/src/components/LocationPicker/Map/AMap/common/utils.ts +71 -6
- package/src/components/LocationPicker/Map/AMap/index.jsx +7 -2
- package/src/components/Upload/uploader.jsx +25 -7
package/package.json
CHANGED
@@ -0,0 +1,68 @@
|
|
1
|
+
import _ from "lodash";
|
2
|
+
|
3
|
+
export function mergeSchema(BaseSchema, InsideSchema, title = "") {
|
4
|
+
const _schema = {
|
5
|
+
form: BaseSchema.form,
|
6
|
+
schema: _.cloneDeep(BaseSchema.schema),
|
7
|
+
};
|
8
|
+
let idx = Object.keys(_schema.schema.properties).length;
|
9
|
+
|
10
|
+
if (title) {
|
11
|
+
_schema.schema.properties.insideTitle = {
|
12
|
+
type: "string",
|
13
|
+
"x-component": "Text",
|
14
|
+
"x-component-props": {
|
15
|
+
content: title || "内部情况",
|
16
|
+
},
|
17
|
+
"x-designable-id": "insideTitle" + idx,
|
18
|
+
"x-index": idx,
|
19
|
+
};
|
20
|
+
}
|
21
|
+
|
22
|
+
Object.keys(InsideSchema.schema.properties).forEach((key) => {
|
23
|
+
const obj = InsideSchema.schema.properties[key];
|
24
|
+
idx += 1;
|
25
|
+
obj["x-index"] = idx;
|
26
|
+
_schema.schema.properties[key] = obj;
|
27
|
+
});
|
28
|
+
return _schema;
|
29
|
+
}
|
30
|
+
|
31
|
+
export function mergeSchemas(schemas) {
|
32
|
+
if (!(Array.isArray(schemas) && schemas.length > 0)) {
|
33
|
+
console.error("请传入 schema");
|
34
|
+
return;
|
35
|
+
}
|
36
|
+
const _schemaList = _.cloneDeep(schemas);
|
37
|
+
const _schema = {
|
38
|
+
form: _schemaList[0].json.form,
|
39
|
+
schema: {
|
40
|
+
type: "object",
|
41
|
+
properties: {},
|
42
|
+
"x-designable-id": _.uniqueId("schema-merge-"),
|
43
|
+
},
|
44
|
+
};
|
45
|
+
|
46
|
+
let idx = 0;
|
47
|
+
_schemaList.forEach((schema, i) => {
|
48
|
+
const titleName = `insideTitle-${i}`;
|
49
|
+
_schema.schema.properties[titleName] = {
|
50
|
+
type: "string",
|
51
|
+
"x-component": "Text",
|
52
|
+
"x-component-props": {
|
53
|
+
content: schema.title,
|
54
|
+
},
|
55
|
+
"x-designable-id": titleName,
|
56
|
+
"x-index": idx,
|
57
|
+
};
|
58
|
+
idx += 1;
|
59
|
+
Object.keys(schema.json.schema.properties).forEach((key) => {
|
60
|
+
const obj = schema.json.schema.properties[key];
|
61
|
+
obj["x-index"] = idx;
|
62
|
+
_schema.schema.properties[key] = obj;
|
63
|
+
idx += 1;
|
64
|
+
});
|
65
|
+
});
|
66
|
+
|
67
|
+
return _schema;
|
68
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
export const iconCircle0080ff = `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAJQSURBVGhD3ZrrdcIwDIVldw26R+kesEdZALJA2QMGgT3KGq2razk4cV4OSYPd7w92yznRtSUrslA0B3uzohd6pW/a8OyNFI+JVvZ/nhsZutiRpjPt1dmOJzJNQGE2bNQnj0Jj4zAsZKKY8QKw2sRGK7va82HoSIXauVk04wQU5sOt+N+haMc7cnSzQeIEYNWV9d/HXGUsEitb3pGb/KEb7T67gZ8r+uLRMsYDRWv7TDx7gH4B4jInN1sePBs29NDtQkv4eyw9cdEuQI7H5618G4pjouW4bQqQgIXPp4fhBBkEdlsMpLXyVeQkrFEXAL/HCZAuqzCo6y50MMaN0qbiSn4H9iaNEyeOu61egKLe8zYpKu9hIiAi4yWHs1kE/Mz8ZrkELslKEOcSvCEczDpL9ynhKlBn6T4lXMLWE1l+vOnEM28/Ci60ZKEyP6vcXSh4mcuQfyFgsPJPmJvmbJZm9RWDoQt24CqzPNGcjme5ZH0Kms6a03G+LrRXLEBKs/wCGTfbjByjuDjKDVzLM76oz60mOChru09kbkuyAL0Eh9+BlG/kQtzqA78DCOYcYiGw0e9AycEs2wsYAxofhXp3M4vfgRKTdIGzdZ93mgLElRpffDqwKbiZBk0BAPfwKcWDNDhaT8lmDFRJoUsjxnd2LfsFgGd2azq6MlWGBQBpbp/420sFOH6WsG7z+ZA4ASVLuNSAy4SME1CCXsLc1/HyKrOLWfUqjwkoQXzgavLx301I9h/w8z6mCahSigESK2E2h18jy19tFYhCauRqNyH6BUPQrVUSJvRPAAAAAElFTkSuQmCC`;
|
@@ -7,11 +7,22 @@
|
|
7
7
|
display: flex;
|
8
8
|
justify-content: space-between;
|
9
9
|
align-items: center;
|
10
|
+
padding: 12px 24px;
|
11
|
+
line-height: 1;
|
12
|
+
|
13
|
+
&.active {
|
14
|
+
background: #f2f9ff;
|
15
|
+
border: 1px solid #0080ff;
|
16
|
+
}
|
17
|
+
|
18
|
+
.addr-item-content {
|
19
|
+
flex: 1;
|
20
|
+
width: 100%;
|
21
|
+
}
|
10
22
|
|
11
23
|
.item-content {
|
12
24
|
display: flex;
|
13
|
-
.item-addr{
|
14
|
-
flex: 1;
|
25
|
+
.item-addr {
|
15
26
|
}
|
16
27
|
.item-range {
|
17
28
|
flex-shrink: 0;
|
@@ -2,9 +2,10 @@ import { Popconfirm } from "antd";
|
|
2
2
|
import { EditOutlined, DeleteOutlined } from "@ant-design/icons";
|
3
3
|
|
4
4
|
import "./index.less";
|
5
|
+
import { useState } from "react";
|
5
6
|
|
6
7
|
export const AddrList = (props) => {
|
7
|
-
const { list, ItemRender, onItemClick, onEdit, onDel, hasAction = true } = props;
|
8
|
+
const { list, ItemRender, onItemClick, onEdit, onDel, hasAction = true, activeId, onDelClick, onDelCancel } = props;
|
8
9
|
|
9
10
|
const CItemRender = ItemRender ?? LItemRender;
|
10
11
|
|
@@ -12,13 +13,19 @@ export const AddrList = (props) => {
|
|
12
13
|
<div className="addr-list">
|
13
14
|
{list?.map((it, i) => {
|
14
15
|
return (
|
15
|
-
<div className=
|
16
|
-
<
|
16
|
+
<div className={`addr-item ${activeId === it.id ? "active" : ""}`} key={it.id ?? i}>
|
17
|
+
<div className="addr-item-content" onClick={(e) => onItemClick(it, i, e)}>
|
18
|
+
<CItemRender item={it} index={i} />
|
19
|
+
</div>
|
17
20
|
{hasAction && (
|
18
21
|
<div className="action-box">
|
19
|
-
<EditOutlined className="action-btn edit-btn" onClick={(e) => onEdit(it, i, e)} />
|
20
|
-
<Popconfirm
|
21
|
-
|
22
|
+
<EditOutlined className="action-btn edit-btn" onClick={(e) => onEdit && onEdit(it, i, e)} />
|
23
|
+
<Popconfirm
|
24
|
+
title={"确认删除当前项?"}
|
25
|
+
onConfirm={(e) => onDel && onDel(it, i, e)}
|
26
|
+
onOpenChange={(open) => open === false && onDelCancel && onDelCancel(it, i)}
|
27
|
+
>
|
28
|
+
<DeleteOutlined className="action-btn del-btn" onClick={(e) => onDelClick && onDelClick(it, i, e)} />
|
22
29
|
</Popconfirm>
|
23
30
|
</div>
|
24
31
|
)}
|
@@ -0,0 +1,21 @@
|
|
1
|
+
{
|
2
|
+
"form": {},
|
3
|
+
"schema": {
|
4
|
+
"type": "object",
|
5
|
+
"properties": {
|
6
|
+
"address": {
|
7
|
+
"type": "string",
|
8
|
+
"title": "位置",
|
9
|
+
"x-decorator": "FormItem",
|
10
|
+
"x-component": "text",
|
11
|
+
"x-validator": [],
|
12
|
+
"x-component-props": {},
|
13
|
+
"x-decorator-props": {},
|
14
|
+
"x-designable-id": "address",
|
15
|
+
"name": "address",
|
16
|
+
"x-index": 0
|
17
|
+
}
|
18
|
+
},
|
19
|
+
"x-designable-id": "o6m980wykh1"
|
20
|
+
}
|
21
|
+
}
|
@@ -3,6 +3,8 @@ import { Button } from "antd";
|
|
3
3
|
|
4
4
|
import FormRender from "@hzab/form-render";
|
5
5
|
|
6
|
+
import { mergeSchema } from "../../../../common/schema-merge";
|
7
|
+
import AddressSchema from "./range.schema.json";
|
6
8
|
import RangeSchema from "./range.schema.json";
|
7
9
|
|
8
10
|
import "./index.less";
|
@@ -44,18 +46,21 @@ export const Popup = forwardRef((props: IPopupProps, parentRef) => {
|
|
44
46
|
|
45
47
|
function onCancel() {
|
46
48
|
setData(null);
|
47
|
-
rejectRef.current();
|
49
|
+
rejectRef.current && rejectRef.current();
|
48
50
|
}
|
49
51
|
|
50
52
|
function onConfirm() {
|
51
|
-
formRef.current?.formRender
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
53
|
+
formRef.current?.formRender
|
54
|
+
?.validate()
|
55
|
+
.then(() => {
|
56
|
+
resolveRef.current(formRef.current.formRender.values);
|
57
|
+
setData(null);
|
58
|
+
})
|
59
|
+
.catch(() => {});
|
57
60
|
}
|
58
61
|
|
62
|
+
const schema = mergeSchema(AddressSchema, formProps?.schema ?? RangeSchema);
|
63
|
+
|
59
64
|
return data ? (
|
60
65
|
<div className="popup-box" style={{ top: data?.top, left: data?.left }}>
|
61
66
|
<div className="popup-body">
|
@@ -64,7 +69,7 @@ export const Popup = forwardRef((props: IPopupProps, parentRef) => {
|
|
64
69
|
<FormRender
|
65
70
|
ref={formRef}
|
66
71
|
{...formProps}
|
67
|
-
schema={
|
72
|
+
schema={schema}
|
68
73
|
initialValues={{ ...formProps?.initialValues, ...data }}
|
69
74
|
/>
|
70
75
|
</div>
|
@@ -12,6 +12,9 @@ import AMapCom from "../LocationPicker/Map/AMap";
|
|
12
12
|
import MapSearch from "../LocationPicker/components/MapSearch";
|
13
13
|
import { MapUtils } from "../LocationPicker/Map/AMap/common/utils";
|
14
14
|
import { getAddress } from "../LocationPicker/servers";
|
15
|
+
import { markerIconBase64 } from "../LocationPicker/assets/svg-icon";
|
16
|
+
|
17
|
+
import { iconCircle0080ff } from "./assets/icon";
|
15
18
|
|
16
19
|
import "./index.less";
|
17
20
|
|
@@ -19,7 +22,11 @@ export const LocationListPicker = observer((props) => {
|
|
19
22
|
const { value, listProps, popupProps, ItemRender, markerIconConf, isAutoSearch, onChange } = props;
|
20
23
|
|
21
24
|
const [loading, setLoading] = useState(props.loading || false);
|
25
|
+
const [showTip, setShowTip] = useState(false);
|
26
|
+
const [tipPosition, setTipPosition] = useState({});
|
27
|
+
const [activeId, setActiveId] = useState();
|
22
28
|
|
29
|
+
const mapDomRef = useRef();
|
23
30
|
const mapUtilsRef = useRef<MapUtils>();
|
24
31
|
const listRef = useRef(value);
|
25
32
|
const statusRef = useRef();
|
@@ -31,6 +38,7 @@ export const LocationListPicker = observer((props) => {
|
|
31
38
|
return () => {
|
32
39
|
// 取消监听
|
33
40
|
mapUtilsRef.current?.off("click", onMapClick);
|
41
|
+
mapDomRef.current.current.removeEventListener("mousemove", onMouseMove);
|
34
42
|
};
|
35
43
|
}, []);
|
36
44
|
|
@@ -49,17 +57,25 @@ export const LocationListPicker = observer((props) => {
|
|
49
57
|
}, [value]);
|
50
58
|
|
51
59
|
function renderMarker() {
|
52
|
-
listRef.current?.forEach((
|
53
|
-
mapUtilsRef.current.setMarker(
|
54
|
-
|
60
|
+
listRef.current?.forEach((item) => {
|
61
|
+
mapUtilsRef.current.setMarker(item.longitude, item.latitude, {
|
62
|
+
...item,
|
63
|
+
data: item,
|
64
|
+
onClick: onMarkerClick,
|
65
|
+
});
|
66
|
+
mapUtilsRef.current.setCircle(item.longitude, item.latitude, item.range, { ...item });
|
67
|
+
setInactiveMarkerIcon(item.id);
|
55
68
|
});
|
56
69
|
}
|
57
70
|
|
58
|
-
function mapInit({ map, mapUtils }) {
|
71
|
+
function mapInit({ map, mapUtils, mapDomRef: _mapDomRef }) {
|
72
|
+
mapDomRef.current = _mapDomRef;
|
73
|
+
_mapDomRef.current.addEventListener("mousemove", onMouseMove);
|
59
74
|
mapUtilsRef.current = mapUtils;
|
60
75
|
// 启动监听事件
|
61
76
|
mapUtilsRef.current.on("click", onMapClick);
|
62
77
|
renderMarker();
|
78
|
+
mapUtilsRef.current.setFitView();
|
63
79
|
}
|
64
80
|
|
65
81
|
function onAddClick() {
|
@@ -67,6 +83,8 @@ export const LocationListPicker = observer((props) => {
|
|
67
83
|
message.warn("请先完成上次操作");
|
68
84
|
return;
|
69
85
|
}
|
86
|
+
setInactiveMarkerIcon(activeId);
|
87
|
+
setShowTip(true);
|
70
88
|
statusRef.current = "add";
|
71
89
|
}
|
72
90
|
|
@@ -75,6 +93,7 @@ export const LocationListPicker = observer((props) => {
|
|
75
93
|
const status = statusRef.current;
|
76
94
|
const isAdd = status === "add";
|
77
95
|
const isEdit = status === "edit";
|
96
|
+
setShowTip(false);
|
78
97
|
|
79
98
|
if (!isAdd && !isEdit) {
|
80
99
|
return;
|
@@ -106,7 +125,11 @@ export const LocationListPicker = observer((props) => {
|
|
106
125
|
item.address = await getAddress(lng, lat);
|
107
126
|
|
108
127
|
// 更新地图状态
|
109
|
-
mapUtilsRef.current.setMarker(lng, lat, {
|
128
|
+
mapUtilsRef.current.setMarker(lng, lat, {
|
129
|
+
...item,
|
130
|
+
onClick: onMarkerClick,
|
131
|
+
data: item,
|
132
|
+
});
|
110
133
|
// 回显范围
|
111
134
|
mapUtilsRef.current.setCircle(lng, lat, item.range, { ...item });
|
112
135
|
|
@@ -126,10 +149,13 @@ export const LocationListPicker = observer((props) => {
|
|
126
149
|
isAdd && mapUtilsRef.current.rmMarker(item.id);
|
127
150
|
// 编辑状态恢复数据
|
128
151
|
if (isEdit) {
|
129
|
-
mapUtilsRef.current.setMarker(preItem.longitude, preItem.latitude, {
|
152
|
+
mapUtilsRef.current.setMarker(preItem.longitude, preItem.latitude, {
|
153
|
+
...preItem,
|
154
|
+
data: item,
|
155
|
+
});
|
130
156
|
mapUtilsRef.current.setCircle(preItem.longitude, preItem.latitude, preItem.range, { ...preItem });
|
131
157
|
}
|
132
|
-
clearStatus();
|
158
|
+
clearStatus(item.id);
|
133
159
|
return;
|
134
160
|
}
|
135
161
|
|
@@ -151,12 +177,51 @@ export const LocationListPicker = observer((props) => {
|
|
151
177
|
clearStatus();
|
152
178
|
}
|
153
179
|
|
154
|
-
function
|
180
|
+
function onMarkerClick(e, ...args) {
|
181
|
+
const { id } = e.target.getExtData() || {};
|
182
|
+
setActiveId((_id) => {
|
183
|
+
setInactiveMarkerIcon(_id);
|
184
|
+
return id;
|
185
|
+
});
|
186
|
+
setActiveMarkerIcon(id);
|
187
|
+
}
|
188
|
+
|
189
|
+
function clearStatus(id) {
|
155
190
|
isEditingRef.current = false;
|
156
191
|
// 清除状态,解决重复创建的问题
|
157
192
|
statusRef.current = null;
|
158
193
|
// 编辑状态清除数据
|
159
194
|
currentItemRef.current = null;
|
195
|
+
setShowTip(false);
|
196
|
+
id && setInactiveMarkerIcon(id);
|
197
|
+
popupRef.current.onCancel();
|
198
|
+
}
|
199
|
+
|
200
|
+
function onItemClick(item, i) {
|
201
|
+
clearStatus(item.id);
|
202
|
+
setInactiveMarkerIcon(activeId);
|
203
|
+
setActiveId(item.id);
|
204
|
+
const mapUtils = mapUtilsRef.current;
|
205
|
+
const marker = mapUtils.markers[item.id];
|
206
|
+
const position = marker?.getPosition();
|
207
|
+
position && mapUtils.setCenter(position.lng, position.lat);
|
208
|
+
setActiveMarkerIcon(item.id);
|
209
|
+
}
|
210
|
+
|
211
|
+
function setActiveMarkerIcon(id) {
|
212
|
+
mapUtilsRef.current.setMarkerIcon(id, {
|
213
|
+
image: markerIconBase64,
|
214
|
+
size: [34, 34],
|
215
|
+
offset: [-17, -34],
|
216
|
+
});
|
217
|
+
}
|
218
|
+
|
219
|
+
function setInactiveMarkerIcon(id) {
|
220
|
+
mapUtilsRef.current.setMarkerIcon(id, {
|
221
|
+
image: iconCircle0080ff,
|
222
|
+
size: [12, 12],
|
223
|
+
offset: [-6, -6],
|
224
|
+
});
|
160
225
|
}
|
161
226
|
|
162
227
|
function onEdit(item, i) {
|
@@ -164,9 +229,13 @@ export const LocationListPicker = observer((props) => {
|
|
164
229
|
message.warn("请先完成上次操作");
|
165
230
|
return;
|
166
231
|
}
|
232
|
+
setInactiveMarkerIcon(activeId);
|
233
|
+
setActiveId(item.id);
|
234
|
+
setShowTip(true);
|
167
235
|
statusRef.current = "edit";
|
168
236
|
currentItemRef.current = item;
|
169
237
|
mapUtilsRef.current.setCenter(item.longitude, item.latitude, { immediately: true });
|
238
|
+
setActiveMarkerIcon(item.id);
|
170
239
|
onMapClick({
|
171
240
|
lnglat: {
|
172
241
|
lng: item.longitude,
|
@@ -175,6 +244,13 @@ export const LocationListPicker = observer((props) => {
|
|
175
244
|
});
|
176
245
|
}
|
177
246
|
|
247
|
+
function onDelClick(item, i) {
|
248
|
+
setInactiveMarkerIcon(activeId);
|
249
|
+
setActiveId(item.id);
|
250
|
+
mapUtilsRef.current.setCenter(item.longitude, item.latitude, { immediately: true });
|
251
|
+
setActiveMarkerIcon(item.id);
|
252
|
+
}
|
253
|
+
|
178
254
|
function onDel(item, i) {
|
179
255
|
const list = [...listRef.current];
|
180
256
|
list?.splice(i, 1);
|
@@ -185,9 +261,13 @@ export const LocationListPicker = observer((props) => {
|
|
185
261
|
mapUtilsRef.current.rmCircle(item.id);
|
186
262
|
}
|
187
263
|
|
264
|
+
function onDelCancel(item, i) {
|
265
|
+
setInactiveMarkerIcon(item.id);
|
266
|
+
setActiveId(null);
|
267
|
+
}
|
268
|
+
|
188
269
|
function setPoint(lng, lat) {
|
189
270
|
mapUtilsRef.current.setCenter(lng, lat, { immediately: true });
|
190
|
-
mapUtilsRef.current.map.setZoom(15, true);
|
191
271
|
statusRef.current = "add";
|
192
272
|
onMapClick({
|
193
273
|
lnglat: {
|
@@ -197,23 +277,36 @@ export const LocationListPicker = observer((props) => {
|
|
197
277
|
});
|
198
278
|
}
|
199
279
|
|
280
|
+
function onMouseMove(e) {
|
281
|
+
const { offsetX, offsetY } = e;
|
282
|
+
setTipPosition({ left: offsetX + 10, top: offsetY + 10 });
|
283
|
+
}
|
284
|
+
|
200
285
|
return (
|
201
286
|
<div className="location-list-picker">
|
202
287
|
<div className="map-box">
|
203
288
|
<AMapCom init={mapInit} loading={loading} markerIconConf={markerIconConf} />
|
204
289
|
<MapSearch setPoint={setPoint} isAutoSearch={isAutoSearch} />
|
205
|
-
|
206
|
-
className="location-list-picker-notice-bar"
|
207
|
-
|
208
|
-
type="info"
|
209
|
-
showIcon
|
210
|
-
/>
|
290
|
+
{showTip && (
|
291
|
+
<Alert className="location-list-picker-notice-bar" message={"点击选择地址"} type="info" style={tipPosition} />
|
292
|
+
)}
|
211
293
|
<Button className="add-btn" onClick={onAddClick}>
|
212
294
|
新增地址
|
213
295
|
</Button>
|
214
296
|
<Popup ref={popupRef} {...popupProps} />
|
215
297
|
</div>
|
216
|
-
<AddrList
|
298
|
+
<AddrList
|
299
|
+
{...listProps}
|
300
|
+
mapUtilsRef={mapUtilsRef}
|
301
|
+
activeId={activeId}
|
302
|
+
list={value}
|
303
|
+
ItemRender={ItemRender}
|
304
|
+
onItemClick={onItemClick}
|
305
|
+
onEdit={onEdit}
|
306
|
+
onDel={onDel}
|
307
|
+
onDelClick={onDelClick}
|
308
|
+
onDelCancel={onDelCancel}
|
309
|
+
/>
|
217
310
|
</div>
|
218
311
|
);
|
219
312
|
});
|
@@ -23,16 +23,26 @@ export function setSecurityJsCode(securityJsCode) {
|
|
23
23
|
};
|
24
24
|
}
|
25
25
|
|
26
|
+
export interface IMarker {
|
27
|
+
setIcon: Function;
|
28
|
+
setSize: Function;
|
29
|
+
setOffset: Function;
|
30
|
+
getPosition: Function;
|
31
|
+
}
|
32
|
+
|
26
33
|
export type setMarkerOptT = {
|
27
34
|
id?: number | string;
|
28
|
-
marker?:
|
35
|
+
marker?: IMarker;
|
29
36
|
map?: Object;
|
30
37
|
AMap?: Object;
|
31
38
|
markerIconConf?: Object;
|
39
|
+
markerConf?: Object;
|
40
|
+
onClick?: Function;
|
41
|
+
data?: Object;
|
32
42
|
};
|
33
43
|
|
34
44
|
export type markersT = {
|
35
|
-
[k: number | string]:
|
45
|
+
[k: number | string]: IMarker;
|
36
46
|
};
|
37
47
|
|
38
48
|
export class MapUtils {
|
@@ -42,14 +52,16 @@ export class MapUtils {
|
|
42
52
|
public circles = {};
|
43
53
|
public pickerMarker;
|
44
54
|
public markerIconConf;
|
55
|
+
public markerConf;
|
45
56
|
|
46
|
-
constructor({ map, AMap, markerIconConf }) {
|
57
|
+
constructor({ map, AMap, markerIconConf, markerConf }) {
|
47
58
|
if (!map) {
|
48
59
|
throw new Error("请传入地图实例");
|
49
60
|
}
|
50
61
|
this.map = map;
|
51
62
|
this.AMap = AMap;
|
52
63
|
this.markerIconConf = markerIconConf || {};
|
64
|
+
this.markerConf = markerConf || {};
|
53
65
|
}
|
54
66
|
|
55
67
|
/**
|
@@ -84,6 +96,11 @@ export class MapUtils {
|
|
84
96
|
map.setCenter(position, immediately, duration);
|
85
97
|
}
|
86
98
|
|
99
|
+
setFitView() {
|
100
|
+
// 调整地图以适应所有标记点
|
101
|
+
this.map.setFitView();
|
102
|
+
}
|
103
|
+
|
87
104
|
/**
|
88
105
|
* 创建或修改 Marker
|
89
106
|
* @param lon
|
@@ -92,7 +109,16 @@ export class MapUtils {
|
|
92
109
|
* @returns
|
93
110
|
*/
|
94
111
|
setMarker(lon, lat, opt?: setMarkerOptT) {
|
95
|
-
const {
|
112
|
+
const {
|
113
|
+
data,
|
114
|
+
id = nanoid(),
|
115
|
+
marker,
|
116
|
+
map = this.map,
|
117
|
+
AMap = this.AMap,
|
118
|
+
markerIconConf = {},
|
119
|
+
markerConf = {},
|
120
|
+
onClick,
|
121
|
+
} = opt || {};
|
96
122
|
|
97
123
|
if (!(AMap && map)) {
|
98
124
|
throw new Error("请传入地图实例和 AMap");
|
@@ -111,10 +137,11 @@ export class MapUtils {
|
|
111
137
|
return _marker;
|
112
138
|
}
|
113
139
|
|
140
|
+
const size = new AMap.Size(34, 34);
|
114
141
|
const icon = new AMap.Icon({
|
115
|
-
size
|
142
|
+
size, //图标尺寸
|
116
143
|
image: markerIconBase64, // Icon 的图像
|
117
|
-
imageSize:
|
144
|
+
imageSize: size, // 根据所设置的大小拉伸或压缩图片
|
118
145
|
...this.markerIconConf,
|
119
146
|
...markerIconConf,
|
120
147
|
});
|
@@ -122,13 +149,51 @@ export class MapUtils {
|
|
122
149
|
offset: new AMap.Pixel(-17, -34),
|
123
150
|
icon,
|
124
151
|
position,
|
152
|
+
extData: {
|
153
|
+
id,
|
154
|
+
data,
|
155
|
+
},
|
156
|
+
...this.markerConf,
|
157
|
+
...markerConf,
|
125
158
|
});
|
159
|
+
|
126
160
|
this.markers[id] = _m;
|
127
161
|
|
162
|
+
if (onClick) {
|
163
|
+
_m.on("click", onClick);
|
164
|
+
}
|
165
|
+
|
128
166
|
map?.add(_m);
|
129
167
|
return _m;
|
130
168
|
}
|
131
169
|
|
170
|
+
setMarkerIcon(
|
171
|
+
id,
|
172
|
+
opt = {
|
173
|
+
size: null,
|
174
|
+
image: null,
|
175
|
+
offset: null,
|
176
|
+
},
|
177
|
+
) {
|
178
|
+
const marker = this.markers[id];
|
179
|
+
if (!marker) {
|
180
|
+
return;
|
181
|
+
}
|
182
|
+
const { image, offset } = opt || {};
|
183
|
+
const AMap = this.AMap;
|
184
|
+
|
185
|
+
const size = new AMap.Size(...opt?.size);
|
186
|
+
const icon = new AMap.Icon({
|
187
|
+
size, //图标尺寸
|
188
|
+
image: image, // Icon 的图像
|
189
|
+
imageSize: size, // 根据所设置的大小拉伸或压缩图片
|
190
|
+
});
|
191
|
+
|
192
|
+
marker.setIcon(icon);
|
193
|
+
marker.setSize(size);
|
194
|
+
marker.setOffset(new AMap.Pixel(...offset));
|
195
|
+
}
|
196
|
+
|
132
197
|
/**
|
133
198
|
* 删除指定 marker
|
134
199
|
* @param id
|
@@ -25,11 +25,16 @@ function AMapCom(props) {
|
|
25
25
|
}).then((AMap) => {
|
26
26
|
const { zoom, center, init } = props;
|
27
27
|
mapRef.current = new AMap.Map(mapDomRef.current, {
|
28
|
-
zoom: zoom ||
|
28
|
+
zoom: zoom || 14,
|
29
29
|
center: center || [120.160217, 30.243861],
|
30
30
|
});
|
31
31
|
init &&
|
32
|
-
init({
|
32
|
+
init({
|
33
|
+
mapDomRef,
|
34
|
+
map: mapRef.current,
|
35
|
+
mapUtils: new MapUtils({ map: mapRef.current, AMap, markerIconConf }),
|
36
|
+
AMap,
|
37
|
+
});
|
33
38
|
});
|
34
39
|
}, []);
|
35
40
|
|