Commit aba3f653 authored by mayongxin's avatar mayongxin

perf:范围配置组件

parent 3bd8c65c
Pipeline #26046 passed with stages
in 18 minutes 38 seconds
import React, { useEffect, useState, useRef } from 'react'
import SiteModal from '@/components/Modal/SiteModa';
import { Input, Cascader, Button } from 'antd'
import {gcj_decrypt,exetent2AmapPoint,lngLat2WebMercator} from '@/utils/transformUtil'
const { Search } = Input;
const MapScope = props => {
const [options, setOptions] = useState([])
//const [mouseTool,setMouseTool] = useState(null)
const { confirmModal, stationId,distinct,extent } = props
const [currentExtent, setCurrentExtent] = useState()
const [isDistrict, setIsDistrict] = useState(false)
const [currentAreaName,setCurrentAreaName] = useState(null)
const mapID = useRef();
const mouseToolID = useRef();
useEffect(() => {
if (document.getElementById("map-container")) {
if (!mapID.current) {
let m = new window.AMap.Map('map-container');
mapID.current = m
}
if (!mouseToolID.current) {
let tool = new AMap.MouseTool(mapID.current)
mouseToolID.current = tool
}
extent&&mapID.current.setCenter(exetent2AmapPoint(extent))
distinct&&onCascderChange([distinct])
window.AMap.plugin('AMap.DistrictSearch', function () {
let districtSearch = new AMap.DistrictSearch({
// 关键字对应的行政区级别,country表示国家
level: 'country',
// 显示下级行政区级数,1表示返回下一级行政区
subdistrict: 3
})
// 搜索所有省/直辖市信息
districtSearch.search('中国', function (status, result) {
// 查询成功时,result即为对应的行政区信息
console.log(result, "行政区划信息")
setOptions(result.districtList[0].districtList)
})
})
}
}, [props])
const resetmap = ()=>{
}
const getInitConfig = () => {
}
const onSubmit = () => {
confirmModal && confirmModal(currentExtent,currentAreaName)
let mouseTool = mouseToolID.current;
mouseTool.close(true)
let map = mapID.current
map.clearMap()
}
const handleSearch = () => {
}
const onTangleClick = () => {
// if(!mouseTool){
// let tool = new AMap.MouseTool(map)
// setMouseTool(tool)
// }
let mouseTool = mouseToolID.current
mouseTool.close(true)
mouseTool.rectangle({
fillColor: '#00b0ff',
strokeColor: '#80d8ff'
//同Polygon的Option设置
});
mouseTool.on('draw', function (event) {
mouseTool.close(false)
//console.log(event.obj.getBounds(),"矩形对象")
let bounds = event.obj.getBounds()
let ne = bounds.northEast.pos
let sw = bounds.southWest.pos
let str = (sw.concat(ne)).toString()
setCurrentExtent(str)
})
}
const onCascderChange = (value) => {
let map = mapID.current
map.clearMap()
console.log(value, "选中的行政区")
let dic = {
"1": "province",
"2": "city",
"3": "district"
}
let level = dic[value.length.toString]
AMap.plugin('AMap.DistrictSearch', function () {
// 创建行政区查询对象
let district = new AMap.DistrictSearch({
// 返回行政区边界坐标等具体信息
extensions: 'all',
// 设置查询行政区级别为 区
level: level
})
district.search(`${value[value.length - 1]}`, function (status, result) {
// 获取朝阳区的边界信息
let bounds = result.districtList[0].boundaries
let polygons = []
if (bounds) {
for (let i = 0, l = bounds.length; i < l; i++) {
//生成行政区划polygon
let polygon = new AMap.Polygon({
map: map,
strokeWeight: 1,
path: bounds[i],
fillOpacity: 0.7,
fillColor: '#CCF3FF',
strokeColor: '#CC66CC'
})
polygons.push(polygon)
}
// 地图自适应
map.setFitView()
setCurrentAreaName(value[value.length-1])
setIsDistrict(true)
}
})
})
}
const filter = (inputValue, path) => {
return path.some(option => option.name.toLowerCase().indexOf(inputValue.toLowerCase()) > -1)
}
return (
<SiteModal
{...props}
title={"范围选择"}
bodyStyle={{ width: '100%', minHeight: '100px' }}
style={{ top: 200, borderRadius: '20px' }}
width="800px"
cancelText="取消"
okText="确认"
onOk={() => onSubmit()}
>
<div style={{ width: "750px", height: "500px" }}>
<div style={{ width: "750px", height: "500px", position: "absolute" }} >
<div id="map-container" style={{ width: "750px", height: "500px" }}></div>
<div style={{ top: "10px", left: "10px", position: "absolute" }}>
<Cascader
fieldNames={{ label: 'name', value: 'name', children: 'districtList' }}
options={options}
onChange={onCascderChange}
placeholder="请选择行政区"
showSearch={{ filter }}
changeOnSelect
style={{ width: "200px" }}
/>
</div>
<div style={{ top: "10px", right: "10px", position: "absolute" }}>
<Button type="primary" onClick={onTangleClick}>框选范围</Button>
</div>
<div style={{ display: `${isDistrict ? "inline" : "none"}`, top: "10px", left: "220px", position: "absolute" }}>
<Button type="primary" onClick={onTangleClick}>样式调整</Button>
</div>
</div>
</div>
</SiteModal>
)
}
export default MapScope
\ No newline at end of file
......@@ -28,5 +28,5 @@
<!-- A lot of magic happens in this file. HtmlWebpackPlugin automatically injects all assets (e.g. bundle.js, main.css) with the correct HTML tags, which is why they are missing in this file. Don't add any assets here! (Check out webpack.dev.babel.js and webpack.prod.babel.js if you want to know more) -->
</body>
<script src="https://webapi.amap.com/maps?v=2.0&key=c7c2931895f0627fe659d2e82d914f29&plugin=AMap.DistrictSearch,AMap.MouseTool"></script>
</html>
......@@ -28,6 +28,7 @@ import {
DoubleLeftOutlined,
DoubleRightOutlined,
DownOutlined,
BorderlessTableOutlined
} from '@ant-design/icons';
import PageContainer from '@/components/BasePageContainer';
import voca from 'voca';
......@@ -42,6 +43,8 @@ import {
deleteUser as postDeleteUser,
setUserState as postSetUserState,
multiDeleteUsers,
setOrgArea,
getOrgArea
} from '@/services/userCenter/userManage/api';
import Tree from '@/components/ExpendableTree';
import classnames from 'classnames';
......@@ -52,7 +55,9 @@ import DeleteOrgModal from './DeleteOrgModal';
import RelateRoleModal from './RelateRoleModal';
import EditUserModal from './EditUserModal';
import ChangePasswordModal from './ChangePasswordModal';
import MapScopeEditModal from '@/components/MapScope'
import styles from './UserManage.less';
import { useTheme } from 'bizcharts';
const UserManage = () => {
const [treeLoading, setTreeLoading] = useState(false);
......@@ -78,6 +83,7 @@ const UserManage = () => {
const [addOrgVisible, setAddOrgVisible] = useState(false); // 添加机构
const [editOrgVisible, setEditOrgVisible] = useState(false); // 编辑机构
const [deleteOrgVisible, setDeleteOrgVisible] = useState(false); // 删除机构
const [editOrgExtentVisible, setEditOrgExtentVisible] = useState(false); // 删除机构
const [roleVisible, setRoleVisible] = useState(false); // 关联角色
const [changeOrgVisible, setChangeOrgVisible] = useState(false); // 更改机构
const [passwordVisible, setPasswordVisible] = useState(false); // 修改密码
......@@ -101,6 +107,11 @@ const UserManage = () => {
const [rolelist, setRolelist] = useState([]); // 角色列表
const [stationlist, setStationlist] = useState([]); // 站点列表
const [orgAreas,setOrgAreas] = useState([])
const [currentOrgArea,setCurrentOrgArea] = useState("")
const [currentOrgDistinct,setCurrentOrgDistinct] = useState("")
const [saveExtentFlag,setSaveExtentFlag] = useState(0)
const { Search } = Input;
const setRowClassName = record =>
record.userID === selectColor.userID ? styles.clickRowStyle : '';
......@@ -329,7 +340,16 @@ const UserManage = () => {
// 获取用户机构树
useEffect(() => {
updateTrees();
}, []);
//更新获取初始范围
useEffect(()=>{
getOrgArea().then(res => {
if (res.IsSuccess) {
setOrgAreas(res.Results)
}
})
},[saveExtentFlag])
// 点击树节点,获取当前机构下所有用户
const onSelect = (props, e) => {
......@@ -342,6 +362,13 @@ const UserManage = () => {
} else {
setCurrentSelectOrg(props[0]);
}
orgAreas.map((item)=>{
if(item.OUID == props[0]){
setCurrentOrgArea(item.Extent)
setCurrentOrgDistinct(item.AreaName)
}
})
setOrgID(props[0] || currentSelectOrg);
// 树节点变化(即props不为空)时才请求,避免重复请求
if (props[0]) {
......@@ -426,6 +453,10 @@ const UserManage = () => {
// 删除后默认选择第一个组织
setTreeState(true);
};
//编辑机构范围
const EditOrgScope = () => {
setEditOrgExtentVisible(true)
}
// 在currentUser变化后获取角色列表
useEffect(() => {
......@@ -696,7 +727,27 @@ const UserManage = () => {
setTableLoading(false);
message.error(err);
});
};
//更改机构范围
const submitExtent = (extent, areaName) => {
console.log(extent)
if (extent) {
setOrgArea({
OUID: currentSelectOrg,
areaName: areaName,
extent: extent
}).then(res => {
if (res.IsSuccess) {
setSaveExtentFlag(saveExtentFlag + 1)
message.success("机构范围设置成功!")
} else {
message.warn(res.Message)
}
})
}
setEditOrgExtentVisible(false)
}
/** ***操作按钮**** */
// 机构操作
......@@ -715,6 +766,9 @@ const UserManage = () => {
<Menu.Item key="4" onClick={deleteOrg} icon={<DeleteOutlined />}>
删除当前机构
</Menu.Item>
<Menu.Item key="5" onClick={EditOrgScope} icon={<BorderlessTableOutlined />}>
编辑机构范围
</Menu.Item>
</Menu>
);
// 用户批量操作
......@@ -794,9 +848,8 @@ const UserManage = () => {
<div style={{ height: '50px' }}>
<p
className={styles.title}
title={`${orgTitle}(已选${
selectedRowKeys.length
}/共${tableLength}人)`}
title={`${orgTitle}(已选${selectedRowKeys.length
}/共${tableLength}人)`}
>
{orgTitle}(已选{selectedRowKeys.length}/共{tableLength}人
</p>
......@@ -989,6 +1042,14 @@ const UserManage = () => {
, 是否确认删除?
</p>
</Modal>
<MapScopeEditModal
visible={editOrgExtentVisible}
stationId={currentSelectOrg}
onCancel={() => setEditOrgExtentVisible(false)}
confirmModal={submitExtent}
distinct={currentOrgDistinct}
extent={currentOrgArea}
/>
</div>
</PageContainer>
);
......
......@@ -169,3 +169,8 @@ export const setUserRelations = (userIDs, roleList, stationList) =>
roleIds: roleList || '',
stationList: stationList || '',
});
export const setOrgArea = params =>
get(`${CITY_SERVICE}/OMS.svc/SetOrgUserArea`, params)
export const getOrgArea = params =>
get(`${CITY_SERVICE}/OMS.svc/GetOrgUserArea`, params)
// 平面坐标转换经纬度
const webMercator2LngLat = (x, y) => {
var lng = (x / 20037508.34) * 180;
var lat = (y / 20037508.34) * 180;
lat =
(180 / Math.PI) *
(2 * Math.atan(Math.exp((lat * Math.PI) / 180)) - Math.PI / 2);
return [lng, lat]; //[114.32894001591471, 30.58574800385281]
};
// 平面复位范围转高德坐标
const exetent2AmapPoint = extent => {
let extents = extent.split(",");
let midX = (parseFloat(extents[0]) + parseFloat(extents[2])) / 2;
let midY = (parseFloat(extents[1]) + parseFloat(extents[3])) / 2;
return webMercator2LngLat(midX, midY);
};
//平面复位范围转高德范围
const plan2AMapbound = extent => {
let extents = extent.split(",")
let minPoint = webMercator2LngLat(parseFloat(extents[0]), parseFloat(extents[1]))
let maxPoint = webMercator2LngLat(parseFloat(extents[2]), parseFloat(extents[3]))
return [minPoint, maxPoint]
}
// 将数字处理成每三个数字加一个逗号的形式,并保留n位有效小数
const dealWithNumber = (num, n = 0) => {
return Number(num)
.toFixed(n)
.replace(/\d(?=(?:\d{3})+\b)/g, "$&,");
};
// 解析内容
// 以&分隔的直接解析成数组输出
// 以 | & 分隔的 通常为(图片)|标题|描述,先按这种情况进行解析
export function getDecodeDatas(data, key) {
if (key) {
if (data[key] && data[key].length) {
let list = data[key].split('&')
if (data[key].includes('|')) {
let res = []
list.forEach(item => {
res.push(item.split('|'))
})
return res
} else {
return list
}
} else {
return []
}
} else {
if (data.length) {
let list = data.split('&')
if (data.includes('|')) {
let res = []
list.forEach(item => {
res.push(item.split('|'))
})
return res
} else {
return list
}
} else {
return []
}
}
}
// 将location中的search字符串转化成query对象
const searchToQuery = (search) => {
if (search.length <= 1) {
return {};
}
const query = {};
// console.log(search)
search
.slice(1)
.split("&")
.forEach(item => {
const [key, value] = item.split("=");
query[key] = decodeURIComponent(value);
});
return query;
};
// 节流
const throttle = function (func, delay) {
var timer = null;
return function () {
var context = this;
var args = arguments;
if (!timer) {
timer = setTimeout(function () {
func.apply(context, args);
timer = null;
}, delay);
}
};
};
// 经纬度转墨卡托平面坐标
const lngLat2WebMercator = (lng, lat) => {
const earthRad = 6378137.0;
const x = ((lng * Math.PI) / 180) * earthRad;
const a = (lat * Math.PI) / 180;
const y =
(earthRad / 2) * Math.log((1.0 + Math.sin(a)) / (1.0 - Math.sin(a)));
return [x, y];
};
const PI = 3.14159265358979324
const delta = (lat, lon) => {
var a = 6378245.0; // a: 卫星椭球坐标投影到平面地图坐标系的投影因子。
var ee = 0.00669342162296594323; // ee: 椭球的偏心率。
var dLat = transformLat(lon - 105.0, lat - 35.0);
var dLon = transformLon(lon - 105.0, lat - 35.0);
var radLat = lat / 180.0 * PI;
var magic = Math.sin(radLat);
magic = 1 - ee * magic * magic;
var sqrtMagic = Math.sqrt(magic);
dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * PI);
dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * PI);
return { 'lat': dLat, 'lon': dLon };
}
const outOfChina = (lat, lon) => {
if (lon < 72.004 || lon > 137.8347)
return true;
if (lat < 0.8293 || lat > 55.8271)
return true;
return false;
}
const transformLat = (x, y) => {
var ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
ret += (20.0 * Math.sin(6.0 * x * PI) + 20.0 * Math.sin(2.0 * x * PI)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(y * PI) + 40.0 * Math.sin(y / 3.0 * PI)) * 2.0 / 3.0;
ret += (160.0 * Math.sin(y / 12.0 * PI) + 320 * Math.sin(y * PI / 30.0)) * 2.0 / 3.0;
return ret;
}
const transformLon = (x, y) => {
var ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
ret += (20.0 * Math.sin(6.0 * x * PI) + 20.0 * Math.sin(2.0 * x * PI)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(x * PI) + 40.0 * Math.sin(x / 3.0 * PI)) * 2.0 / 3.0;
ret += (150.0 * Math.sin(x / 12.0 * PI) + 300.0 * Math.sin(x / 30.0 * PI)) * 2.0 / 3.0;
return ret;
}
const gcj_decrypt = (gcjLat, gcjLon) => {
if (outOfChina(gcjLat, gcjLon))
return { 'lat': gcjLat, 'lon': gcjLon };
var d = delta(gcjLat, gcjLon);
return { 'lat': gcjLat - d.lat, 'lon': gcjLon - d.lon };
}
/**
* 根据坐标获取位置名称,调用高德API
*/
const getAddressByPosition = (lng, lat, callback) => {
const geocoder = new window.AMap.Geocoder();
geocoder.getAddress(
new window.AMap.LngLat(lng, lat), (status, result) => {
if(String(status) === 'complete') {
const address = result.regeocode.formattedAddress;
callback && typeof callback === 'function' && callback(address);
}
});
}
/**
* 高德定位
*/
const positionByGaode = (callback) => {
window.AMap.plugin('AMap.Geolocation', () => {
const geolocation = new window.AMap.Geolocation({
// 是否使用高精度定位,默认:true
enableHighAccuracy: true,
// 设置定位超时时间,默认:无穷大
timeout: 10000,
// 定位按钮的停靠位置的偏移量,默认:Pixel(10, 20)
buttonOffset: new window.AMap.Pixel(10, 20),
// 定位成功后调整地图视野范围使定位位置及精度范围视野内可见,默认:false
zoomToAccuracy: true,
// 定位按钮的排放位置, RB表示右下
buttonPosition: 'RB'
});
geolocation.getCurrentPosition((status, data) => {
if(status == 'complete'){
const { position: { lng, lat } } = data;
typeof callback === 'function' && callback(lng, lat);
}else{
console.log(data)
typeof callback === 'function' && callback('', '');
}
});
});
}
export {
webMercator2LngLat,
dealWithNumber,
searchToQuery,
throttle,
exetent2AmapPoint,
lngLat2WebMercator,
plan2AMapbound,
gcj_decrypt,
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment