@hzab/form-render 1.0.3 → 1.1.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 +9 -1
- package/lib/index.js +1 -1
- package/package.json +1 -1
- package/src/components/LocationListPicker/components/AddrList/index.less +39 -0
- package/src/components/LocationListPicker/components/AddrList/index.tsx +43 -0
- package/src/components/LocationListPicker/components/Popup/index.less +19 -0
- package/src/components/LocationListPicker/components/Popup/index.tsx +81 -0
- package/src/components/LocationListPicker/components/Popup/range.schema.json +21 -0
- package/src/components/LocationListPicker/index.less +26 -0
- package/src/components/LocationListPicker/index.tsx +221 -0
- package/src/components/LocationPicker/Map/AMap/common/utils.ts +67 -4
- package/src/components/LocationPicker/Map/AMap/index.less +4 -0
- package/src/components/Upload/uploader.jsx +25 -7
- package/src/components/index.tsx +1 -0
package/package.json
CHANGED
@@ -0,0 +1,39 @@
|
|
1
|
+
.addr-list {
|
2
|
+
flex: 1;
|
3
|
+
height: 100%;
|
4
|
+
min-height: 600px;
|
5
|
+
overflow-y: auto;
|
6
|
+
.addr-item {
|
7
|
+
display: flex;
|
8
|
+
justify-content: space-between;
|
9
|
+
align-items: center;
|
10
|
+
|
11
|
+
.item-content {
|
12
|
+
display: flex;
|
13
|
+
.item-addr{
|
14
|
+
flex: 1;
|
15
|
+
}
|
16
|
+
.item-range {
|
17
|
+
flex-shrink: 0;
|
18
|
+
color: #999;
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
22
|
+
.action-box {
|
23
|
+
min-width: 56px;
|
24
|
+
}
|
25
|
+
.action-btn {
|
26
|
+
margin-right: 12px;
|
27
|
+
font-size: 16px;
|
28
|
+
&:last-child {
|
29
|
+
margin-right: none;
|
30
|
+
}
|
31
|
+
}
|
32
|
+
.edit-btn {
|
33
|
+
color: #0080ff;
|
34
|
+
}
|
35
|
+
.del-btn {
|
36
|
+
color: #ff3333;
|
37
|
+
}
|
38
|
+
}
|
39
|
+
}
|
@@ -0,0 +1,43 @@
|
|
1
|
+
import { Popconfirm } from "antd";
|
2
|
+
import { EditOutlined, DeleteOutlined } from "@ant-design/icons";
|
3
|
+
|
4
|
+
import "./index.less";
|
5
|
+
|
6
|
+
export const AddrList = (props) => {
|
7
|
+
const { list, ItemRender, onItemClick, onEdit, onDel, hasAction = true } = props;
|
8
|
+
|
9
|
+
const CItemRender = ItemRender ?? LItemRender;
|
10
|
+
|
11
|
+
return (
|
12
|
+
<div className="addr-list">
|
13
|
+
{list?.map((it, i) => {
|
14
|
+
return (
|
15
|
+
<div className="addr-item" key={it.id ?? i} onClick={onItemClick}>
|
16
|
+
<CItemRender item={it} index={i} />
|
17
|
+
{hasAction && (
|
18
|
+
<div className="action-box">
|
19
|
+
<EditOutlined className="action-btn edit-btn" onClick={(e) => onEdit(it, i, e)} />
|
20
|
+
<Popconfirm title={"确认删除当前项?"} onConfirm={(e) => onDel(it, i, e)}>
|
21
|
+
<DeleteOutlined className="action-btn del-btn" />
|
22
|
+
</Popconfirm>
|
23
|
+
</div>
|
24
|
+
)}
|
25
|
+
</div>
|
26
|
+
);
|
27
|
+
})}
|
28
|
+
</div>
|
29
|
+
);
|
30
|
+
};
|
31
|
+
|
32
|
+
function LItemRender(props) {
|
33
|
+
const { item } = props;
|
34
|
+
const { address, range } = item || {};
|
35
|
+
return (
|
36
|
+
<div className="item-content">
|
37
|
+
<div className="item-addr">{address}</div>
|
38
|
+
{range && <span className="item-range">(范围:{range})</span>}
|
39
|
+
</div>
|
40
|
+
);
|
41
|
+
}
|
42
|
+
|
43
|
+
export default AddrList;
|
@@ -0,0 +1,19 @@
|
|
1
|
+
.popup-box {
|
2
|
+
position: absolute;
|
3
|
+
z-index: 9;
|
4
|
+
min-width: 200px;
|
5
|
+
padding: 20px;
|
6
|
+
border-radius: 4px;
|
7
|
+
background-color: #fff;
|
8
|
+
box-shadow: 0px 0px 4px 0px rgba(0, 0, 0, 0.25);
|
9
|
+
|
10
|
+
.popup-footer {
|
11
|
+
.ant-btn {
|
12
|
+
margin-right: 12px;
|
13
|
+
|
14
|
+
&:last-child {
|
15
|
+
margin-right: none;
|
16
|
+
}
|
17
|
+
}
|
18
|
+
}
|
19
|
+
}
|
@@ -0,0 +1,81 @@
|
|
1
|
+
import { useRef, forwardRef, useImperativeHandle, useState } from "react";
|
2
|
+
import { Button } from "antd";
|
3
|
+
|
4
|
+
import FormRender from "@hzab/form-render";
|
5
|
+
|
6
|
+
import RangeSchema from "./range.schema.json";
|
7
|
+
|
8
|
+
import "./index.less";
|
9
|
+
|
10
|
+
export interface IPopupProps {
|
11
|
+
formProps?: {
|
12
|
+
schema;
|
13
|
+
initialValues?: Object;
|
14
|
+
};
|
15
|
+
}
|
16
|
+
|
17
|
+
export interface IData {
|
18
|
+
top: number;
|
19
|
+
left: number;
|
20
|
+
address: string;
|
21
|
+
}
|
22
|
+
|
23
|
+
export const Popup = forwardRef((props: IPopupProps, parentRef) => {
|
24
|
+
const { formProps = { schema: RangeSchema } } = props;
|
25
|
+
|
26
|
+
const [data, setData] = useState<IData>();
|
27
|
+
|
28
|
+
const formRef: any = useRef();
|
29
|
+
const resolveRef = useRef<Function>();
|
30
|
+
const rejectRef = useRef<Function>();
|
31
|
+
|
32
|
+
useImperativeHandle(parentRef, () => ({
|
33
|
+
onShow,
|
34
|
+
onCancel,
|
35
|
+
}));
|
36
|
+
|
37
|
+
function onShow(data) {
|
38
|
+
setData(data ?? {});
|
39
|
+
return new Promise((resolve, reject) => {
|
40
|
+
resolveRef.current = resolve;
|
41
|
+
rejectRef.current = reject;
|
42
|
+
});
|
43
|
+
}
|
44
|
+
|
45
|
+
function onCancel() {
|
46
|
+
setData(null);
|
47
|
+
rejectRef.current();
|
48
|
+
}
|
49
|
+
|
50
|
+
function onConfirm() {
|
51
|
+
formRef.current?.formRender?.validate().then(() => {
|
52
|
+
resolveRef.current(formRef.current.formRender.values);
|
53
|
+
setData(null);
|
54
|
+
}).catch(() => {
|
55
|
+
|
56
|
+
});
|
57
|
+
}
|
58
|
+
|
59
|
+
return data ? (
|
60
|
+
<div className="popup-box" style={{ top: data?.top, left: data?.left }}>
|
61
|
+
<div className="popup-body">
|
62
|
+
{/* TODO: schema 中插入地址字段 text 格式 */}
|
63
|
+
<div>地址:{data?.address}</div>
|
64
|
+
<FormRender
|
65
|
+
ref={formRef}
|
66
|
+
{...formProps}
|
67
|
+
schema={formProps?.schema ?? RangeSchema}
|
68
|
+
initialValues={{ ...formProps?.initialValues, ...data }}
|
69
|
+
/>
|
70
|
+
</div>
|
71
|
+
<div className="popup-footer">
|
72
|
+
<Button type="primary" onClick={onConfirm}>
|
73
|
+
确定
|
74
|
+
</Button>
|
75
|
+
<Button onClick={onCancel}>取消</Button>
|
76
|
+
</div>
|
77
|
+
</div>
|
78
|
+
) : null;
|
79
|
+
});
|
80
|
+
|
81
|
+
export default Popup;
|
@@ -0,0 +1,21 @@
|
|
1
|
+
{
|
2
|
+
"form": {},
|
3
|
+
"schema": {
|
4
|
+
"type": "object",
|
5
|
+
"properties": {
|
6
|
+
"range": {
|
7
|
+
"type": "string",
|
8
|
+
"title": "范围",
|
9
|
+
"x-decorator": "FormItem",
|
10
|
+
"x-component": "Input",
|
11
|
+
"x-validator": [],
|
12
|
+
"x-component-props": {},
|
13
|
+
"x-decorator-props": {},
|
14
|
+
"x-designable-id": "range",
|
15
|
+
"name": "range",
|
16
|
+
"x-index": 0
|
17
|
+
}
|
18
|
+
},
|
19
|
+
"x-designable-id": "o6m980wykh1"
|
20
|
+
}
|
21
|
+
}
|
@@ -0,0 +1,26 @@
|
|
1
|
+
.location-list-picker {
|
2
|
+
width: 100%;
|
3
|
+
display: flex;
|
4
|
+
.location-map-search {
|
5
|
+
top: 12px;
|
6
|
+
left: 12px;
|
7
|
+
}
|
8
|
+
.map-box {
|
9
|
+
position: relative;
|
10
|
+
width: 50%;
|
11
|
+
min-height: 600px;
|
12
|
+
margin-right: 12px;
|
13
|
+
.location-list-picker-notice-bar {
|
14
|
+
position: absolute;
|
15
|
+
left: 0;
|
16
|
+
right: 0;
|
17
|
+
bottom: 0;
|
18
|
+
z-index: 9;
|
19
|
+
}
|
20
|
+
.add-btn {
|
21
|
+
position: absolute;
|
22
|
+
top: 12px;
|
23
|
+
right: 12px;
|
24
|
+
}
|
25
|
+
}
|
26
|
+
}
|
@@ -0,0 +1,221 @@
|
|
1
|
+
// @ts-nocheck
|
2
|
+
import { useEffect, useRef, useState } from "react";
|
3
|
+
import { Button, message, Alert } from "antd";
|
4
|
+
import { observer } from "@formily/react";
|
5
|
+
|
6
|
+
import { nanoid } from "nanoid";
|
7
|
+
|
8
|
+
import AddrList from "./components/AddrList";
|
9
|
+
import Popup from "./components/Popup";
|
10
|
+
|
11
|
+
import AMapCom from "../LocationPicker/Map/AMap";
|
12
|
+
import MapSearch from "../LocationPicker/components/MapSearch";
|
13
|
+
import { MapUtils } from "../LocationPicker/Map/AMap/common/utils";
|
14
|
+
import { getAddress } from "../LocationPicker/servers";
|
15
|
+
|
16
|
+
import "./index.less";
|
17
|
+
|
18
|
+
export const LocationListPicker = observer((props) => {
|
19
|
+
const { value, listProps, popupProps, ItemRender, markerIconConf, isAutoSearch, onChange } = props;
|
20
|
+
|
21
|
+
const [loading, setLoading] = useState(props.loading || false);
|
22
|
+
|
23
|
+
const mapUtilsRef = useRef<MapUtils>();
|
24
|
+
const listRef = useRef(value);
|
25
|
+
const statusRef = useRef();
|
26
|
+
const currentItemRef = useRef();
|
27
|
+
const popupRef = useRef();
|
28
|
+
const isEditingRef = useRef();
|
29
|
+
|
30
|
+
useEffect(() => {
|
31
|
+
return () => {
|
32
|
+
// 取消监听
|
33
|
+
mapUtilsRef.current?.off("click", onMapClick);
|
34
|
+
};
|
35
|
+
}, []);
|
36
|
+
|
37
|
+
useEffect(() => {
|
38
|
+
if (!Array.isArray(value) || value?.length == 0 || !mapUtilsRef.current) {
|
39
|
+
return;
|
40
|
+
}
|
41
|
+
// 处理 id
|
42
|
+
value?.forEach((it) => {
|
43
|
+
if (!it.id) {
|
44
|
+
it.id = nanoid();
|
45
|
+
}
|
46
|
+
});
|
47
|
+
listRef.current = value;
|
48
|
+
renderMarker();
|
49
|
+
}, [value]);
|
50
|
+
|
51
|
+
function renderMarker() {
|
52
|
+
listRef.current?.forEach((it) => {
|
53
|
+
mapUtilsRef.current.setMarker(it.longitude, it.latitude, { ...it });
|
54
|
+
mapUtilsRef.current.setCircle(it.longitude, it.latitude, it.range, { ...it });
|
55
|
+
});
|
56
|
+
}
|
57
|
+
|
58
|
+
function mapInit({ map, mapUtils }) {
|
59
|
+
mapUtilsRef.current = mapUtils;
|
60
|
+
// 启动监听事件
|
61
|
+
mapUtilsRef.current.on("click", onMapClick);
|
62
|
+
renderMarker();
|
63
|
+
}
|
64
|
+
|
65
|
+
function onAddClick() {
|
66
|
+
if (isEditingRef.current) {
|
67
|
+
message.warn("请先完成上次操作");
|
68
|
+
return;
|
69
|
+
}
|
70
|
+
statusRef.current = "add";
|
71
|
+
}
|
72
|
+
|
73
|
+
// 处理 marker、范围 绘制填写逻辑
|
74
|
+
async function onMapClick(e) {
|
75
|
+
const status = statusRef.current;
|
76
|
+
const isAdd = status === "add";
|
77
|
+
const isEdit = status === "edit";
|
78
|
+
|
79
|
+
if (!isAdd && !isEdit) {
|
80
|
+
return;
|
81
|
+
}
|
82
|
+
isEditingRef.current = true;
|
83
|
+
|
84
|
+
const { lng, lat } = e.lnglat || {};
|
85
|
+
|
86
|
+
const preItem = currentItemRef.current;
|
87
|
+
const id = isAdd ? nanoid() : preItem?.id;
|
88
|
+
|
89
|
+
let item = {
|
90
|
+
id,
|
91
|
+
longitude: lng,
|
92
|
+
latitude: lat,
|
93
|
+
address: "",
|
94
|
+
range: null,
|
95
|
+
...preItem,
|
96
|
+
};
|
97
|
+
|
98
|
+
// 解决新增时点击修改重复创建的问题
|
99
|
+
if (isAdd) {
|
100
|
+
item.longitude = lng;
|
101
|
+
item.latitude = lat;
|
102
|
+
currentItemRef.current = item;
|
103
|
+
}
|
104
|
+
|
105
|
+
// 接口获取地址
|
106
|
+
item.address = await getAddress(lng, lat);
|
107
|
+
|
108
|
+
// 更新地图状态
|
109
|
+
mapUtilsRef.current.setMarker(lng, lat, { ...item });
|
110
|
+
// 回显范围
|
111
|
+
mapUtilsRef.current.setCircle(lng, lat, item.range, { ...item });
|
112
|
+
|
113
|
+
// 根据经纬度获取弹窗位置
|
114
|
+
const { x, y } = mapUtilsRef.current.map.lngLatToContainer([lng, lat]);
|
115
|
+
let res = {};
|
116
|
+
try {
|
117
|
+
res = await popupRef.current?.onShow({
|
118
|
+
top: y,
|
119
|
+
left: x,
|
120
|
+
address: item.address,
|
121
|
+
range: item.range,
|
122
|
+
item,
|
123
|
+
});
|
124
|
+
} catch (error) {
|
125
|
+
// 新增状态,取消时清除已添加的 marker circle
|
126
|
+
isAdd && mapUtilsRef.current.rmMarker(item.id);
|
127
|
+
// 编辑状态恢复数据
|
128
|
+
if (isEdit) {
|
129
|
+
mapUtilsRef.current.setMarker(preItem.longitude, preItem.latitude, { ...preItem });
|
130
|
+
mapUtilsRef.current.setCircle(preItem.longitude, preItem.latitude, preItem.range, { ...preItem });
|
131
|
+
}
|
132
|
+
clearStatus();
|
133
|
+
return;
|
134
|
+
}
|
135
|
+
|
136
|
+
// 设置范围
|
137
|
+
mapUtilsRef.current.setCircle(lng, lat, res.range, { ...item });
|
138
|
+
|
139
|
+
item = Object.assign(item, res);
|
140
|
+
|
141
|
+
const list = [...listRef.current];
|
142
|
+
|
143
|
+
if (isAdd) {
|
144
|
+
list.push(item);
|
145
|
+
} else if (isEdit) {
|
146
|
+
const idx = list.findIndex((it) => it.id === id);
|
147
|
+
list.splice(idx, 1, item);
|
148
|
+
}
|
149
|
+
|
150
|
+
onChange && onChange(list);
|
151
|
+
clearStatus();
|
152
|
+
}
|
153
|
+
|
154
|
+
function clearStatus() {
|
155
|
+
isEditingRef.current = false;
|
156
|
+
// 清除状态,解决重复创建的问题
|
157
|
+
statusRef.current = null;
|
158
|
+
// 编辑状态清除数据
|
159
|
+
currentItemRef.current = null;
|
160
|
+
}
|
161
|
+
|
162
|
+
function onEdit(item, i) {
|
163
|
+
if (isEditingRef.current) {
|
164
|
+
message.warn("请先完成上次操作");
|
165
|
+
return;
|
166
|
+
}
|
167
|
+
statusRef.current = "edit";
|
168
|
+
currentItemRef.current = item;
|
169
|
+
mapUtilsRef.current.setCenter(item.longitude, item.latitude, { immediately: true });
|
170
|
+
onMapClick({
|
171
|
+
lnglat: {
|
172
|
+
lng: item.longitude,
|
173
|
+
lat: item.latitude,
|
174
|
+
},
|
175
|
+
});
|
176
|
+
}
|
177
|
+
|
178
|
+
function onDel(item, i) {
|
179
|
+
const list = [...listRef.current];
|
180
|
+
list?.splice(i, 1);
|
181
|
+
onChange && onChange(list);
|
182
|
+
// 清除对应的 marker
|
183
|
+
mapUtilsRef.current.rmMarker(item.id);
|
184
|
+
// 清除对应的 circle
|
185
|
+
mapUtilsRef.current.rmCircle(item.id);
|
186
|
+
}
|
187
|
+
|
188
|
+
function setPoint(lng, lat) {
|
189
|
+
mapUtilsRef.current.setCenter(lng, lat, { immediately: true });
|
190
|
+
mapUtilsRef.current.map.setZoom(15, true);
|
191
|
+
statusRef.current = "add";
|
192
|
+
onMapClick({
|
193
|
+
lnglat: {
|
194
|
+
lng,
|
195
|
+
lat,
|
196
|
+
},
|
197
|
+
});
|
198
|
+
}
|
199
|
+
|
200
|
+
return (
|
201
|
+
<div className="location-list-picker">
|
202
|
+
<div className="map-box">
|
203
|
+
<AMapCom init={mapInit} loading={loading} markerIconConf={markerIconConf} />
|
204
|
+
<MapSearch setPoint={setPoint} isAutoSearch={isAutoSearch} />
|
205
|
+
<Alert
|
206
|
+
className="location-list-picker-notice-bar"
|
207
|
+
message={"点击地图上的位置,选择目标地址"}
|
208
|
+
type="info"
|
209
|
+
showIcon
|
210
|
+
/>
|
211
|
+
<Button className="add-btn" onClick={onAddClick}>
|
212
|
+
新增地址
|
213
|
+
</Button>
|
214
|
+
<Popup ref={popupRef} {...popupProps} />
|
215
|
+
</div>
|
216
|
+
<AddrList {...listProps} list={value} ItemRender={ItemRender} onEdit={onEdit} onDel={onDel} />
|
217
|
+
</div>
|
218
|
+
);
|
219
|
+
});
|
220
|
+
|
221
|
+
export default LocationListPicker;
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import AMapLoader from "./loader";
|
2
2
|
import { markerIconBase64 } from "../../../assets/svg-icon";
|
3
|
+
import { nanoid } from "nanoid";
|
3
4
|
|
4
5
|
if (!window._AMapLoaderTemp) {
|
5
6
|
window._AMapLoaderTemp = {};
|
@@ -38,6 +39,7 @@ export class MapUtils {
|
|
38
39
|
public map;
|
39
40
|
public AMap;
|
40
41
|
public markers: markersT = {};
|
42
|
+
public circles = {};
|
41
43
|
public pickerMarker;
|
42
44
|
public markerIconConf;
|
43
45
|
|
@@ -68,14 +70,18 @@ export class MapUtils {
|
|
68
70
|
* @param lat
|
69
71
|
* @param opt
|
70
72
|
*/
|
71
|
-
setCenter(
|
72
|
-
|
73
|
+
setCenter(
|
74
|
+
lon,
|
75
|
+
lat,
|
76
|
+
opt = { immediately: undefined, duration: undefined, map: this.map, AMap: this.AMap || window.AMap },
|
77
|
+
) {
|
78
|
+
const { map = this.map, AMap = this.AMap || window.AMap, immediately, duration } = opt || {};
|
73
79
|
if (!(AMap && map)) {
|
74
80
|
throw new Error("请传入地图实例和 AMap");
|
75
81
|
}
|
76
82
|
const position = new window.AMap.LngLat(lon, lat);
|
77
83
|
// 设置中心点
|
78
|
-
map.setCenter(position);
|
84
|
+
map.setCenter(position, immediately, duration);
|
79
85
|
}
|
80
86
|
|
81
87
|
/**
|
@@ -86,7 +92,8 @@ export class MapUtils {
|
|
86
92
|
* @returns
|
87
93
|
*/
|
88
94
|
setMarker(lon, lat, opt?: setMarkerOptT) {
|
89
|
-
const { id =
|
95
|
+
const { id = nanoid(), marker, map = this.map, AMap = this.AMap, markerIconConf = {} } = opt || {};
|
96
|
+
|
90
97
|
if (!(AMap && map)) {
|
91
98
|
throw new Error("请传入地图实例和 AMap");
|
92
99
|
}
|
@@ -96,6 +103,7 @@ export class MapUtils {
|
|
96
103
|
}
|
97
104
|
const position = new AMap.LngLat(lon, lat);
|
98
105
|
let _marker = marker || this.markers[id];
|
106
|
+
|
99
107
|
// 创建 Marker 或修改位置
|
100
108
|
if (_marker) {
|
101
109
|
// @ts-ignore
|
@@ -116,12 +124,67 @@ export class MapUtils {
|
|
116
124
|
position,
|
117
125
|
});
|
118
126
|
this.markers[id] = _m;
|
127
|
+
|
119
128
|
map?.add(_m);
|
120
129
|
return _m;
|
121
130
|
}
|
122
131
|
|
132
|
+
/**
|
133
|
+
* 删除指定 marker
|
134
|
+
* @param id
|
135
|
+
*/
|
136
|
+
rmMarker(id) {
|
137
|
+
this.map.remove(this.markers[id]);
|
138
|
+
delete this.markers[id];
|
139
|
+
}
|
140
|
+
|
141
|
+
setCircle(lon, lat, radius, opt?) {
|
142
|
+
const { id = nanoid(), circle, map = this.map, AMap = this.AMap, circleConf = {} } = opt || {};
|
143
|
+
if (!(AMap && map)) {
|
144
|
+
throw new Error("请传入地图实例和 AMap");
|
145
|
+
}
|
146
|
+
if (lon === null || lon === undefined || lat === null || lat === undefined) {
|
147
|
+
console.warn("setMarker 请传入正确的经纬度");
|
148
|
+
return;
|
149
|
+
}
|
150
|
+
// circles
|
151
|
+
|
152
|
+
const center = new AMap.LngLat(lon, lat);
|
153
|
+
let _circle = circle || this.circles[id];
|
154
|
+
|
155
|
+
// 创建 Marker 或修改位置
|
156
|
+
if (_circle) {
|
157
|
+
// @ts-ignore
|
158
|
+
_circle.setCenter(center);
|
159
|
+
_circle.setRadius(radius);
|
160
|
+
return _circle;
|
161
|
+
}
|
162
|
+
|
163
|
+
//创建圆形 Circle 实例
|
164
|
+
const _c = new AMap.Circle({
|
165
|
+
center: center, // 圆心
|
166
|
+
radius: radius, // 半径
|
167
|
+
borderWeight: 1, // 描边的宽度
|
168
|
+
strokeColor: "#0080FF", // 轮廓线颜色
|
169
|
+
strokeWeight: 1, // 轮廓线宽度
|
170
|
+
fillOpacity: 0.1, // 圆形填充透明度
|
171
|
+
fillColor: "#0080FF", // 圆形填充颜色
|
172
|
+
zIndex: 50, // 圆形的叠加顺序
|
173
|
+
...circleConf,
|
174
|
+
});
|
175
|
+
this.circles[id] = _c;
|
176
|
+
map?.add(_c);
|
177
|
+
return _c;
|
178
|
+
}
|
179
|
+
|
180
|
+
rmCircle(id) {
|
181
|
+
this.map.remove(this.circles[id]);
|
182
|
+
delete this.circles[id];
|
183
|
+
}
|
184
|
+
|
123
185
|
/**
|
124
186
|
* 创建或修改地图选点的 Marker
|
187
|
+
* 在当前 utils 中唯一
|
125
188
|
* @param lon
|
126
189
|
* @param lat
|
127
190
|
* @param opt
|
@@ -11,7 +11,7 @@ import React, { useEffect, useState } from "react";
|
|
11
11
|
import { nanoid } from "nanoid";
|
12
12
|
|
13
13
|
import { handleInputFileList, getFileName, getFileType } from "./common/utils";
|
14
|
-
import
|
14
|
+
import LUploadOss from "./common/ossUpload";
|
15
15
|
|
16
16
|
import PreviewModal, { hasPreviewRender, hasPreviewMedium } from "./components/PreviewModal";
|
17
17
|
|
@@ -43,6 +43,9 @@ export function Uploader({ onChange, ...props }) {
|
|
43
43
|
templateUrl,
|
44
44
|
beforeUploadCheck,
|
45
45
|
templateDownloadText = "模板下载",
|
46
|
+
isFileObj = false,
|
47
|
+
isFileJson = false,
|
48
|
+
UploadOss,
|
46
49
|
} = props;
|
47
50
|
|
48
51
|
const [fileList, setFileList] = useState([]);
|
@@ -60,8 +63,14 @@ export function Uploader({ onChange, ...props }) {
|
|
60
63
|
_file = _file?.originFileObj;
|
61
64
|
}
|
62
65
|
// 从文件对象中获取 url,ossPromise 为上传中的文件,兼容 file 为字符串的情况
|
63
|
-
|
64
|
-
|
66
|
+
|
67
|
+
if (isFileObj) {
|
68
|
+
let { ossUrl, url, uid, name, type } = (await _file.ossPromise) || _file;
|
69
|
+
_files[i] = { ossUrl, url, uid, name, type };
|
70
|
+
} else {
|
71
|
+
let str = (await _file.ossPromise) || _file.url || _file.ossUrl || _file;
|
72
|
+
_files[i] = str;
|
73
|
+
}
|
65
74
|
}
|
66
75
|
}
|
67
76
|
// 处理空数据情况
|
@@ -71,17 +80,25 @@ export function Uploader({ onChange, ...props }) {
|
|
71
80
|
// maxCount 为 1 的时候返回结果去除数组
|
72
81
|
_files = _files[0];
|
73
82
|
}
|
74
|
-
onChange && onChange?.(_files);
|
83
|
+
onChange && onChange?.(isFileJson ? JSON.stringify(_files) : _files);
|
75
84
|
};
|
76
85
|
|
77
86
|
useEffect(() => {
|
78
87
|
if (!value) {
|
79
88
|
return;
|
80
89
|
}
|
81
|
-
|
90
|
+
|
91
|
+
let _list = [];
|
92
|
+
try {
|
93
|
+
_list = JSON.parse(value);
|
94
|
+
} catch (e) {
|
95
|
+
_list = value;
|
96
|
+
}
|
97
|
+
|
82
98
|
if (typeof _list === "string") {
|
83
99
|
_list = value.split(",");
|
84
100
|
}
|
101
|
+
|
85
102
|
if (Array.isArray(_list)) {
|
86
103
|
_list = _list.map((res) => {
|
87
104
|
if (typeof res === "string") {
|
@@ -173,7 +190,8 @@ export function Uploader({ onChange, ...props }) {
|
|
173
190
|
},
|
174
191
|
customRequest: isOssUpload
|
175
192
|
? function customRequest({ action, data, file, filename, headers, method, onSuccess, onProgress, onError }) {
|
176
|
-
const
|
193
|
+
const _UploadOss = UploadOss || LUploadOss;
|
194
|
+
const ossUpload = new _UploadOss({
|
177
195
|
serverUrl: ossUrl,
|
178
196
|
...ossOpt,
|
179
197
|
});
|
@@ -188,7 +206,7 @@ export function Uploader({ onChange, ...props }) {
|
|
188
206
|
file.url = res?.data?.data?.fileUrl ?? res?.data?.fileUrl ?? res?.fileUrl;
|
189
207
|
file.ossUrl = file.url;
|
190
208
|
onSuccess(file);
|
191
|
-
return file.ossUrl;
|
209
|
+
return isFileObj ? file : file.ossUrl;
|
192
210
|
})
|
193
211
|
.catch(onError);
|
194
212
|
}
|