Commit 2ed9c863 authored by shaoan123's avatar shaoan123

对接表字段分组排序接口

parent c38ec5dd
Pipeline #30245 skipped with stages
...@@ -2,6 +2,7 @@ const path = require('path'); ...@@ -2,6 +2,7 @@ const path = require('path');
const webpack = require('webpack'); const webpack = require('webpack');
const slash = require('slash2'); const slash = require('slash2');
const CopyPlugin = require('copy-webpack-plugin'); const CopyPlugin = require('copy-webpack-plugin');
const cesiumSource = './node_modules/cesium/Source';
console.log(); console.log();
module.exports = options => ({ module.exports = options => ({
mode: options.mode, mode: options.mode,
...@@ -12,10 +13,19 @@ module.exports = options => ({ ...@@ -12,10 +13,19 @@ module.exports = options => ({
? path.resolve(process.env.npm_config_releasepath, 'civmanage') ? path.resolve(process.env.npm_config_releasepath, 'civmanage')
: path.resolve(process.cwd(), 'civmanage'), : path.resolve(process.cwd(), 'civmanage'),
publicPath: process.env.PUBLIC_PATH || '/civmanage/', publicPath: process.env.PUBLIC_PATH || '/civmanage/',
sourcePrefix : ''//需要编译Cesium中的多行字符串
}, },
options.output, options.output,
), // Merge with env dependent settings ), // Merge with env dependent settings
optimization: options.optimization, optimization: options.optimization,
amd: {
//允许Cesium兼容 webpack的require方式
toUrlUndefined: true
},
node: {
// 解决fs模块的问题(Resolve node module use of fs)
fs: 'empty'
},
module: { module: {
rules: [ rules: [
{ {
...@@ -172,7 +182,24 @@ module.exports = options => ({ ...@@ -172,7 +182,24 @@ module.exports = options => ({
{ {
from: path.resolve(process.cwd(), './public'), from: path.resolve(process.cwd(), './public'),
}, },
{
from : path.join(process.cwd(), cesiumSource, '../Build/Cesium/Workers'),
to : 'Workers',
},{
from : path.join(process.cwd(), cesiumSource, 'Assets'),
to : 'Assets',
},{
from : path.join(process.cwd(), cesiumSource, 'Widgets'),
to : 'Widgets',
},{
from : path.join(process.cwd(), cesiumSource, 'ThirdParty'),
to : 'ThirdParty'
}
]), ]),
new webpack.DefinePlugin ({
CESIUM_BASE_URL : JSON.stringify('/civmanage') //定义packName
})
]), ]),
resolve: { resolve: {
modules: ['node_modules', 'src'], modules: ['node_modules', 'src'],
...@@ -181,6 +208,7 @@ module.exports = options => ({ ...@@ -181,6 +208,7 @@ module.exports = options => ({
alias: { alias: {
'@': path.resolve(process.cwd(), './src'), '@': path.resolve(process.cwd(), './src'),
components: path.resolve(process.cwd(), './src/components'), components: path.resolve(process.cwd(), './src/components'),
cesium : path.resolve(process.cwd(), cesiumSource)
}, },
}, },
devtool: options.devtool, devtool: options.devtool,
......
...@@ -87,9 +87,11 @@ ...@@ -87,9 +87,11 @@
"@babel/polyfill": "7.4.3", "@babel/polyfill": "7.4.3",
"@babel/preset-typescript": "^7.12.1", "@babel/preset-typescript": "^7.12.1",
"@babel/runtime": "^7.10.5", "@babel/runtime": "^7.10.5",
"@wisdom-cesium/cesium": "^1.0.9",
"ace-builds": "^1.4.12", "ace-builds": "^1.4.12",
"antd-img-crop": "^3.13.2", "antd-img-crop": "^3.13.2",
"bizcharts": "^4.0.15", "bizcharts": "^4.0.15",
"cesium": "^1.82.1",
"chalk": "2.4.2", "chalk": "2.4.2",
"compression": "1.7.4", "compression": "1.7.4",
"connected-react-router": "6.4.0", "connected-react-router": "6.4.0",
......
...@@ -22,11 +22,34 @@ const AddModal = props => { ...@@ -22,11 +22,34 @@ const AddModal = props => {
// 提交 // 提交
const onSubmit = () => { const onSubmit = () => {
setLoading(true); setLoading(true);
let arr = []
data.map((item) => {
if (item.children && item.children.length) {
item.children.map(childrenItem => {
arr.push({ groupName: item.title, ID: childrenItem.key })
})
}
})
ChangeOrder(arr).then(res => {
setLoading(false);
if (res.msg === 'Ok' || res.msg === '') {
notification.success({
message: '提示',
duration: 3,
description: '编辑成功',
});
callBackSubmit();
}
else {
notification.error({
message: '提示',
duration: 3,
description: res.msg,
});
}
})
}; };
const Submit = prop => {
setIsVisible(false);
setFlag(flag + 1)
};
useEffect(() => { useEffect(() => {
if (type != '') { if (type != '') {
setTreeLoading(true) setTreeLoading(true)
...@@ -83,7 +106,7 @@ const AddModal = props => { ...@@ -83,7 +106,7 @@ const AddModal = props => {
} }
//完成拖拽 //完成拖拽
const onDrop = info => { const onDrop = (info,node) => {
const dropKey = info.node.props.eventKey; const dropKey = info.node.props.eventKey;
const dragKey = info.dragNode.props.eventKey; const dragKey = info.dragNode.props.eventKey;
const dropPos = info.node.props.pos.split('-'); const dropPos = info.node.props.pos.split('-');
......
import { Space, Table, Button, Popconfirm, notification, Spin } from 'antd';
import React, { useState, useEffect } from 'react';
import styles from '../dimensionsConfig.less'
import {
GettMaplayer,
deleteConfig
} from '@/services/webConfig/api';
import AddModal from './AddModal'
const TileData = props => {
const [treeLoading, setTreeLoading] = useState(false);// 弹窗显示
const [tileData, setTileData] = useState([]); // table表格数据
const [visible, setVisible] = useState(false); // 弹窗
const [type, setType] = useState(''); // 弹窗类型
const [formObj, setFormObj] = useState({});
const [flag, setFlag] = useState(0); // 弹窗类型
const [baseMap, setBaseMap] = useState([]); //底图数据
const columns = [
{
title: '服务名',
dataIndex: 'servicename',
key: 'servicename',
align: 'center'
},
{
title: '标签',
dataIndex: 'label',
key: 'label',
align: 'center'
},
{
title: '类型',
dataIndex: 'type',
key: 'type',
align: 'center'
},
{
title: '透明度',
dataIndex: 'alpha',
key: 'alpha',
align: 'center'
},
{
title: '编辑',
align: 'center',
render: (text, record) => (
<Space>
<Button
type="primary"
size="small"
onClick={() => {
changebaseMap(record);
}}
>
编辑
</Button>
<div onClick={e => e.stopPropagation()}>
<Popconfirm
title="是否删除该底图?"
okText="确认"
cancelText="取消"
onConfirm={() => {
delConfirm(record);
}}
>
<Button size="small" danger>
删除
</Button>
</Popconfirm>
</div>
</Space>
),
},
];
const changebaseMap = (record) => {
setType('edit');
setFormObj(record);
setVisible(true);
}
const onSubmit = prop => {
setVisible(false);
setFlag(flag + 1)
};
const delConfirm = (record) => {
const { servicename = '' } = record;
setTreeLoading(true);
deleteConfig({
servicename: servicename,
terminalType: 'base',
isBaseMap: true
}).then(res => {
setFlag(flag + 1)
setTreeLoading(false);
if (res.msg === 'Ok') {
// form.resetFields();
// callBackSubmit();
notification.success({
message: '提示',
duration: 3,
description: res.message || '删除成功',
});
} else {
notification.error({
message: '提示',
duration: 3,
description: res.message || '删除失败',
});
}
}).catch(err => {
setFlag(flag + 1)
setTreeLoading(false);
})
}
const handleAdd = () => {
if (baseMap.length) {
setType('add');
setVisible(true);
}
else {
notification.warning({
message: '提示',
duration: 3,
description: '地图类型已都存在,可编辑修改',
});
}
}
useEffect(() => {
renderTile();
}, [flag]);
// 获取瓦片数据配置数据
const renderTile = () => {
setTreeLoading(true);
const baseMapData = ['高德地形', '高德影像', '天地图地形', '天地图影像']
GettMaplayer({
terminalType: 'base',
isBaseMap: true
}).then(
res => {
if (res.msg === "Ok") {
setTreeLoading(false);
setTileData(res.data.general.baseMap.layers);
res.data.general.baseMap.layers.map((item) => {
let index = baseMapData.indexOf(item.servicename);
if (index != -1) {
baseMapData.splice(index, 1);
}
})
setBaseMap(baseMapData)
} else {
setTreeLoading(false);
notification.error({
message: '获取失败',
description: res.message,
});
}
}
)
};
return (
<>
<Spin tip="loading..." spinning={treeLoading}>
<div className={styles.tileBtn}>
<Button type="primary" onClick={() => {
handleAdd();
}} >
新增
</Button>
</div>
<Table
columns={columns}
dataSource={tileData}
bordered
rowKey="type"
scroll={{ y: 400 }}
pagination={{
showTotal: (total, range) =>
`第${range[0]}-${range[1]} 条/共 ${total} 条`
}}
>
</Table>
<AddModal
visible={visible}
onCancel={() => setVisible(false)}
callBackSubmit={onSubmit}
type={type}
formObj={formObj}
baseMap={baseMap}
/>
</Spin>
</>
)
}
export default TileData
\ No newline at end of file
import React, { useState, useEffect } from 'react';
import { Form, Modal, Input, Select, AutoComplete, Button, notification } from 'antd';
import styles from '../dimensionsConfig.less'
import {
GetGISServerMapList,
publisService
} from '@/services/webConfig/api';
const { Option } = Select;
const AddModal = props => {
const { callBackSubmit = () => { }, type, formObj, visible, solutionNames } = props;
const [loading, setLoading] = useState(false);
const [workList, setWorkList] = useState([]);
const [gsIp, setGsIp] = useState([]);
const [form] = Form.useForm();
const { Item } = Form;
// 提交
const onSubmit = () => {
form.validateFields().then(validate => {
if (validate) {
setLoading(true);
let obj = form.getFieldsValue();
if (type === 'add') {
let query = {
_version: 9999,
gsIP: obj.serviceadress,
gsPort: obj.port,
gsAppName: obj.servicename,
gsUser: obj.user,
gsWorkspaceName: obj.workname,
gsPwd: obj.password,
serviceName: obj.name,
solution: solutionNames,
}
publisService(query, { timeout: 120000 })
.then(res => {
setLoading(false);
if (res.success) {
form.resetFields();
callBackSubmit();
notification.success({
message: '提示',
duration: 3,
description: '新增成功',
});
setWorkList([])
handlelocalStorage('add', obj.serviceadress, obj.servicename)
} else {
notification.error({
message: '提示',
duration: 3,
description: '新增失败',
});
}
})
.catch(err => {
notification.error({
message: '提示',
duration: 3,
description: '新增失败',
});
setLoading(false);
});
}
}
});
};
const onFinish = value => { };
useEffect(() => {
switch (type) {
case 'add':
let gsIp = [];
let localStorageData = handlelocalStorage('get');
if (localStorageData) {
gsIp = localStorageData.map(item => ({
value: item.gsIp,
item: item.gsIp
}));
}
setGsIp(gsIp)
let localIps = ['192.168.12.7', '192.168.19.100']
let port = localIps.includes(gsIp) ? 8080 : 8088
form.setFieldsValue({ ...formObj });
break;
case 'edit':
form.setFieldsValue({ ...formObj });
break;
default:
break;
}
}, [visible]);
//存储到localstorage
const handlelocalStorage = (type, gsIp, gisAppName) => {
if (!localStorage) return null;
let result = JSON.parse(localStorage.getItem('metaData'))
if (type == 'get') {
return result;
}
if (!result || !result.find(item => item.gsIp == gsIp)) {
if (!result) result = [];
result.push({
gsIp,
gisAppName: [{
value: gisAppName,
item: gisAppName
}]
})
localStorage.setItem('metaData', JSON.stringify(result))
return
}
let data = result.find(item => item.gsIp == gsIp)
let isHasGisAppName = data.gisAppName.find(item => item.value == gisAppName);
if (isHasGisAppName) return;
data.gisAppName.push({
value: gisAppName,
item: gisAppName
})
localStorage.setItem('metaData', JSON.stringify(result))
};
const layout = {
layout: 'horizontal',
labelCol: {
span: 4,
},
wrapperCol: {
span: 16,
},
};
const selectIp = (value) => {
let localIps = ['192.168.12.7', '192.168.19.100']
let port = localIps.includes(value) ? 8080 : 8088
form.setFieldsValue({ port, serviceadress: value });
}
return (
<Modal
title={`${type === 'add' ? '元数据发布' : '编辑'}`}
bodyStyle={{ width: '100%', minHeight: '100px' }}
style={{ top: '150px' }}
width="700px"
destroyOnClose
maskClosable={false}
cancelText="取消"
okText="确认"
{...props}
onOk={() => onSubmit()}
confirmLoading={loading}
forceRender={true}
getContainer={false}
>
{visible && (
<Form form={form} {...layout} onFinish={onFinish}>
<Item
label="IP"
name="serviceadress"
rules={[{ required: true, message: '请选择服务名' }]}
>
<AutoComplete
placeholder="请输入IP"
options={gsIp}
onSelect={selectIp}
/>
</Item>
<Item
label="端口"
name="port"
rules={[{ required: true, message: '请输入端口' }]}
>
<Input placeholder="请输入GIS服务器端口" allowClear />
</Item>
<Item
label="项目名"
name="projectName"
rules={[{ required: true, message: '请选择项目名' }]}
>
<Select>
{workList.length ? workList.map((item, index) => { return <Option key={index} value={item}>{item}</Option> }) : ''}
</Select>
</Item>
<Item
label="数据源名"
name="origin"
rules={[{ required: true, message: '请选择数据源名' }]}
>
<Select>
{workList.length ? workList.map((item, index) => { return <Option key={index} value={item}>{item}</Option> }) : ''}
</Select>
</Item>
<Item
label="数据类型"
name="name"
rules={[{ required: true, message: '请输入数据类型' }]}
>
<Input placeholder="请输入数据类型" allowClear />
</Item>
<Item
label="额外属性"
name="name"
rules={[{ required: true, message: '请输入额外属性' }]}
>
<Input placeholder="请输入额外属性" allowClear />
</Item>
</Form>
)}
</Modal>
);
};
export default AddModal;
import { Space, Table, Button, Popconfirm, notification, Spin } from 'antd';
import React, { useState, useEffect } from 'react';
import styles from '../dimensionsConfig.less'
import {
GetVectorService, deleteVectorService, getSolutionList, updatePublishedMetaData
} from '@/services/webConfig/api';
import AddModal from './AddModal'
import PreviewModal from './VectorPreviewModal'
const VectorData = props => {
const [treeLoading, setTreeLoading] = useState(false);// 弹窗显示
const [tileData, setTileData] = useState([]); // table表格数据
const [visible, setVisible] = useState(false); // 弹窗
const [previewVisible, setPreviewVisible] = useState(false); // 预览弹窗
const [flag, setFlag] = useState(0); // 更新list
const [loading, setLoading] = useState([]); // 更新状态
const [type, setType] = useState(''); // 弹窗类型
const [solutionNames, setSolutionNames] = useState('');
const [formObj, setFormObj] = useState({ user: 'admin', password: 'geoserver' });
const [currentMetaData, setCurrentMetaData] = useState(null)
const columns = [
{
title: '数据源',
dataIndex: 'ServiceName',
key: 'ServiceName',
align: 'center'
},
{
title: 'IP',
dataIndex: 'GISServerIP',
key: 'GISServerIP',
align: 'center'
},
{
title: '端口',
dataIndex: 'GISServerPort',
key: 'GISServerPort',
align: 'center'
},
{
title: '工程名',
dataIndex: 'GISServerProjectName',
key: 'GISServerProjectName',
align: 'center'
},
{
title: '发布时间',
dataIndex: 'publishTime',
key: 'publishTime',
align: 'center'
},
{
title: '编辑',
align: 'center',
render: (text, record, index) => (
<Space>
<Button type="primary" size="small" onClick={() => previewMetaData(record, index)}>
预览
</Button>
<Button type="primary" size="small" loading={loading[index]} onClick={() => enterLoading(record, index)}>
更新
</Button>
<div onClick={e => e.stopPropagation()}>
<Popconfirm
title="是否删除该矢量数据?"
okText="确认"
cancelText="取消"
onConfirm={() => {
delConfirm(record);
}}
>
<Button size="small" danger>
删除
</Button>
</Popconfirm>
</div>
</Space>
),
},
];
//更新
const enterLoading = (record, index) => {
const newLoadings = [...loading];
newLoadings[index] = true
setLoading(newLoadings)
let query = {
serviceName: record.ServiceName,
_version: 9999,
solution: solutionNames
}
updatePublishedMetaData(query).then(res => {
const newLoadings = [...loading];
newLoadings[index] = false
setLoading(newLoadings)
if (res.success) {
setFlag(flag + 1)
notification.success({
message: '提示',
duration: 3,
description: '更新元数据成功',
});
} else {
notification.error({
message: '提示',
duration: 3,
description: '更新元数据失败',
});
};
}).catch(err => {
const newLoadings = [...loading];
newLoadings[index] = false
setLoading(newLoadings)
notification.error({
message: '提示',
duration: 3,
description: '服务无法访问',
});
})
}
const previewMetaData = (record) => {
setCurrentMetaData(record)
setPreviewVisible(true)
}
const solutionName = () => {
getSolutionList({
_version: 9999
}).then(res => {
setSolutionNames(res.currentSolution)
})
}
const onSubmit = prop => {
setVisible(false);
setFlag(flag + 1)
};
const delConfirm = (record) => {
console.log(' record.ServiceName', record.ServiceName.split("."));
let query = {
serviceName: record.ServiceName.split(".")[0],
_version: 9999,
solution: solutionNames
}
deleteVectorService(query).then(res => {
if (res.success) {
setFlag(flag + 1)
notification.success({
message: '提示',
duration: 3,
description: '删除元数据成功',
});
} else {
notification.error({
message: '提示',
duration: 3,
description: '删除元数据失败',
});
};
})
}
const handleAdd = () => {
setType('add');
setVisible(true);
}
useEffect(() => {
renderTile();
}, [flag]);
// 获取瓦片数据配置数据
const renderTile = () => {
setTreeLoading(true);
solutionName();
GetVectorService().then(
res => {
if (res.msg==='Ok') {
let arr = []
res.data.VectorList.map(item => {
arr.push(false)
})
setLoading(arr)
setTreeLoading(false);
setTileData(res.data.VectorList);
} else {
setTreeLoading(false);
notification.error({
message: '获取失败',
description: res.message,
});
}
}
)
};
return (
<>
<Spin tip="loading..." spinning={treeLoading}>
<div className={styles.tileBtn}>
<Button type="primary" onClick={() => {
handleAdd();
}} >
新增
</Button>
</div>
<Table
columns={columns}
dataSource={tileData}
bordered
rowKey="CreateTime"
scroll={{ y: 400 }}
pagination={{
showTotal: (total, range) =>
`第${range[0]}-${range[1]} 条/共 ${total} 条`
}}
>
</Table>
<AddModal
visible={visible}
onCancel={() => setVisible(false)}
callBackSubmit={onSubmit}
type={type}
formObj={formObj}
solutionNames={solutionNames}
/>
<PreviewModal
visible={previewVisible}
onCancel={() => setPreviewVisible(false)}
metaData={currentMetaData}
/>
</Spin>
</>
)
}
export default VectorData
\ No newline at end of file
import React, { useEffect, useState, useRef } from 'react'
import SiteModal from '@/components/Modal/SiteModa';
import { Input, Cascader, Button, message, Spin } from 'antd'
import { gcj_decrypt, exetent2AmapPoint, lngLat2WebMercator, plan2AMapbound, webMercator2LngLat } from '@/utils/transformUtil'
import { GetAllConfig, GetMetaData } from '@/services/platform/gis'
import ReactJson from 'react-json-view'
import { tr } from 'voca';
const { Search } = Input;
const VectorPreviewModal = props => {
const { metaData } = props
const mapID = useRef();
const [currentMeta, setCurrentMeta] = useState()
const [isLoading, setIsLoading] = useState(false)
useEffect(() => {
if (document.getElementById("map-container")) {
if (!mapID.current) {
//1.加载底图
let m = new window.AMap.Map('map-container');
mapID.current = m
}
}
}, [props])
useEffect(() => {
let map = mapID.current
map && map.clearMap()
map && map.remove(map.getLayers())
setIsLoading(true)
map && GetMetaData(metaData.GISServerProjectName).then(
res2 => {
if (res2 && res2.units) {
setIsLoading(false)
setCurrentMeta(res2)
const layers = res2.layers || [];
const workspace = res2.mapName.split('_')[0];
const subLayers = layers.filter(layer => layer.subLayerIds && layer.subLayerIds.length === 0).map(layer => layer.name);
const paramLayers = `${workspace}:${subLayers.join(',')}`;
const params = {
'LAYERS': paramLayers,
'VERSION': '1.1.1',
'_site': ''
};
const wmsOption = {
tileSize: 512,
url: `${location.origin}/Cityinterface/rest/services/MapServer.svc/${metaData.GISServerProjectName}/GeoServerProxy/wms`,
blend: false,
params: params,
zooms: [2, 20],
}
let wms = new window.AMap.TileLayer.WMS(wmsOption)
map.add(wms);
setIsLoading(true)
// wms.complete(() => {
// setIsLoading(false)
// })
wms.on("complete",()=>{
setIsLoading(false)
})
const extent = res2.fullExtent;
if (extent.xmax < 100000000 && extent.xmax > 0) {
const a = webMercator2LngLat(extent.xmin, extent.ymin)
const b = webMercator2LngLat(extent.xmax, extent.ymax)
const southWest = new AMap.LngLat(a[0], a[1])
const northEast = new AMap.LngLat(b[0], b[1])
mapID.current.setBounds(new AMap.Bounds(southWest, northEast))
}
}
}
)
}, [metaData])
const resetmap = () => {
}
const getInitConfig = () => {
}
const onSubmit = () => {
}
return (
<SiteModal
{...props}
title={"元数据预览"}
bodyStyle={{ width: '100%', minHeight: '100px' }}
style={{ top: 200, borderRadius: '20px' }}
width="1050px"
cancelText="取消"
okText="确认"
onOk={() => onSubmit()}
>
<Spin spinning={isLoading}>
<div style={{ width: "1000px", height: "500px" }}>
<div style={{ width: "1000px", height: "500px", position: "absolute" }}>
<div id="map-container" style={{ width: "1000px", height: "500px" }}></div>
<div style={{ top: "10px", right: "10px", position: "absolute", overflowY: "scroll", maxHeight: "480px", backgroundColor: "white" }}>
<ReactJson src={currentMeta} collapsed={true} />
</div>
</div>
</div>
</Spin>
</SiteModal>
)
}
export default VectorPreviewModal
\ No newline at end of file
import { Tabs, Button } from 'antd';
import React from 'react';
import PageContainer from '@/components/BasePageContainer';
import styles from './dimensionsConfig.less'
import TileConfig from './TileConfig/TileConfig';
import VectorData from './VectorData/VectorData';
import ProjectMessage from './projectMessage/projectMessage';
import SolutionConfig from './solutionConfig/solutionConfig';
const { TabPane } = Tabs;
const SchemeConfig = () => {
const callback = () => {
}
return (
<PageContainer>
<div className={styles.container}>
<Tabs onChange={callback} type="card">
<TabPane tab="瓦片数据配置" key="1">
<TileConfig />
</TabPane>
<TabPane tab="矢量数据配置" key="2">
<VectorData />
</TabPane>
<TabPane tab="方案管理" key="3">
<ProjectMessage />
</TabPane>
<TabPane tab="方案配置" key="4">
<SolutionConfig/>
</TabPane>
</Tabs>
</div>
</PageContainer>
)
}
export default SchemeConfig;
\ No newline at end of file
.container{
width: 100%;
background-color: #ffffff;
display: flex;
padding: 0.8rem;
.ant-table-thead tr th {
font-weight: 600;
color: rgba(0, 0, 0, 0.85);
}
overflow-y: scroll;
.ant-input-number-input{
background-color: #ffffff;
color: #000000;
}
}
.imgList{
display: flex;
}
.imgItem{
display: flex;
flex-direction: column;
align-items: center;
margin:0 1rem 1rem 0;
}
.tileBtn{
display: flex;
justify-content: flex-end;
width: 100%;
padding: 0 0 2rem
}
.schemeName{
margin-right: 0.8rem;
font-weight: bold;
}
.schemeItem,.schemeBtn{
display: flex;
align-items: center;
}
.schemeBtn{
width: 12rem;
justify-content: center;
}
.mapItem{
display: flex;
border: 1px solid #ccc;
border-radius: 4px;
height: 2.2rem;
align-items: center;
margin: 0.5rem 0;
width: 14.5rem;
}
.defaultTile{
background: #ccc;
color: white;
cursor: pointer;
height: 100%;
display: flex;
align-items: center;
width: 3rem;
justify-content: center;
}
.mapText{
width: 10rem;
text-align: center;
}
.mapIcon{
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
}
.activeTile{
background-color: #4699f4
}
.dropList {
position: absolute;
right: 2%;
top: 25%;
color: rgba(0, 0, 0, 0.25);
z-index: 99;
}
.divider{
display: flex;
align-items: center;
line-height: 100%;
padding: 0.5rem;
.dividerIcon{
margin-left: 0.8rem;
color: #4699f4;
cursor: pointer;
}
}
.ant-table {
min-height: 15rem !important;
}
.cardsList{
display: flex;
flex-wrap: wrap;
}
.cardItem{
width: 18rem;
height: 26rem;
margin: 0 2rem;
}
.solutionConfig{
}
\ No newline at end of file
import React, { useState, useEffect } from 'react';
import { Form, Modal, Input, Select, notification } from 'antd';
import {
GettMaplayer,
GetVectorService,
SetServiceConfig,
bindSchemeBaseMap
} from '@/services/webConfig/api';
const { Item } = Form;
const { Option } = Select;
const AddModal = props => {
const { callBackSubmit = () => { }, type, formObj, visible, serviceList } = props;
const [loading, setLoading] = useState(false);
const [baseMap, setBaseMap] = useState([]);
const [pipeArr, setPipeArr] = useState([]);
const [form] = Form.useForm();
// 提交
const onSubmit = () => {
form.validateFields().then(validate => {
if (validate) {
setLoading(true);
let obj = form.getFieldsValue();
if (type === 'add') {
bindSchemeBaseMap({
schemename: formObj.schemename,
basemapName: obj.serverName
}).then(res => {
setLoading(false);
if (res.code === 0) {
form.resetFields();
callBackSubmit();
prompt('success', '瓦片新增成功')
}
else {
prompt('fail', '瓦片新增失败')
}
})
} else {
handleEdit();
}
}
});
};
const prompt = (type, content) => {
if (type == 'success') {
notification.success({
message: '提示',
duration: 3,
description: content,
});
}
else {
notification.error({
message: '提示',
duration: 3,
description: content,
});
}
}
const handleEdit = () => {
let obj = form.getFieldsValue();
let query = {
schemename: obj.schemename,
terminalType: 'scheme',
isBaseMap: 'false',
jsonCfg: JSON.stringify({
baseMap: [obj.baseMap],
servicename: obj.servicename,
label: obj.label,
url: obj.url,
alpha: 1,
})
}
SetServiceConfig(query)
.then(res => {
setLoading(false);
if (res.msg === "Ok") {
form.resetFields();
callBackSubmit();
prompt('success', '方案新增成功')
} else {
prompt('fail', '方案新增失败')
}
})
.catch(err => {
setLoading(false);
});
};
const onFinish = value => {
};
useEffect(() => {
switch (type) {
case 'add':
addTile()
break;
case 'schemeAdd':
pipeNetwork()
break;
default:
break;
}
}, [visible]);
//添加瓦片
const addTile = () => {
form.setFieldsValue({
serverName: serviceList[0]
})
}
//获取管网及默认底图
const pipeNetwork = () => {
form.resetFields();
let req1 = GettMaplayer({ terminalType: 'base', isBaseMap: true })
let req2 = GetVectorService()
let pipeArr = [], baseMap = [];
Promise.all([req1, req2]).then(res => {
if (res[0].msg === 'Ok') {
(res[0].data.general.baseMap.layers || []).map(item => {
baseMap.push(item.servicename)
})
}
if (res[1].msg === 'Ok') {
(res[1].data.VectorList || []).map(item => {
pipeArr.push(item.ServiceName.split(".")[0])
})
}
console.log('pipeArr', pipeArr);
console.log('baseMap', baseMap);
setPipeArr(pipeArr)
setBaseMap(baseMap)
form.setFieldsValue({
baseMap: baseMap[0]
})
})
}
const layout = {
layout: 'horizontal',
labelCol: {
span: 4,
},
wrapperCol: {
span: 16,
},
};
//选择服务名
const handleChange = () => { }
//选择管网
const handleService = (value) => {
form.setFieldsValue({
label: value,
url: `http://{IP}/CityInterface/rest/services/MapServer.svc/${value}`
})
}
//选择底图
const handleBaseMap = () => { }
return (
<Modal
title={`${type === 'add' ? '添加底图' : '添加方案'}`}
bodyStyle={{ width: '100%', minHeight: '100px' }}
style={{ top: '150px' }}
width="700px"
destroyOnClose
maskClosable={false}
cancelText="取消"
okText="确认"
{...props}
onOk={() => onSubmit()}
confirmLoading={loading}
forceRender={true}
getContainer={false}
>
{visible && (
<Form form={form} {...layout} onFinish={onFinish}>
{type === 'add' ? <Item
label="服务名"
name="serverName"
>
<Select onChange={handleChange}>
{serviceList.length ? serviceList.map((item, index) => { return <Option key={index} value={item}>{item}</Option> }) : ''}
</Select>
</Item> :
<>
<Item
label="方案名"
name="schemename"
rules={[{ required: true, message: '请输入方案名' }]}
>
<Input placeholder="请输入方案名" allowClear />
</Item>
<Item
label="管网"
name="servicename"
>
<Select onChange={handleService}>
{pipeArr.length ? pipeArr.map((item, index) => { return <Option key={index} value={item}>{item}</Option> }) : ''}
</Select>
</Item>
<Item
label="标签"
name="label"
>
<Input placeholder="请输入标签" allowClear />
</Item>
<Item
label="url"
name="url"
>
<Input placeholder="请输入url" allowClear />
</Item>
<Item
label="默认底图"
name="baseMap"
rules={[{ required: true, message: '请选择底图' }]}
>
<Select onChange={handleBaseMap}>
{baseMap.length ? baseMap.map((item, index) => { return <Option key={index} value={item}>{item}</Option> }) : ''}
</Select>
</Item>
</>
}
</Form>
)}
</Modal>
);
};
export default AddModal;
import React, { useState, useEffect } from 'react';
import classnames from 'classnames'
import styles from '../../dimensionsConfig.less'
import { Popconfirm, notification, Card, Button, message } from 'antd';
import {
unbindSchemeBaseMap, GettMaplayer, SetServiceConfig,deleteConfig
} from '@/services/webConfig/api';
import {
CloseOutlined, PlusOutlined
} from '@ant-design/icons';
import AddModal from '../AddModal'
import MapScope from '@/components/MapScope'
import { createGuid } from '@/utils/transformUtil'
import DemoTest from './demoTest'
const CardData = props => {
const { deletebaseMaps = () => { }, item } = props;
const [visible, setVisible] = useState(false); // 弹窗
const [flag, setFlag] = useState(0); // 状态更新
const [type, setType] = useState(''); // 弹窗类型
const [formObj, setFormObj] = useState({});
const [serviceList, setServiceList] = useState([]);
const [mapScopeVisible, setMapScopeVisible] = useState(false)
//删除瓦片
const deletebaseMap = (item, baseMapItem) => {
unbindSchemeBaseMap({ schemename: item.schemename, basemapName: baseMapItem }).then(res => {
if (res.code === 0) {
notification.success({
message: '提示',
duration: 3,
description: '底图删除成功',
});
deletebaseMaps()
}
else {
notification.error({
message: '提示',
duration: 3,
description: '底图删除失败',
});
}
})
}
//删除方案
const deleteTile = (item) => {
deleteConfig({
schemename: item.schemename,
terminalType: 'scheme',
isBaseMap: false
}).then(res => {
if (res.msg === "Ok") {
notification.success({
message: '提示',
duration: 3,
description: '方案删除成功',
});
deletebaseMaps()
}
else {
notification.error({
message: '提示',
duration: 3,
description: '方案删除失败',
});
}
})
}
const onSubmit = prop => {
setVisible(false);
deletebaseMaps()
};
//增加瓦片
const addTile = (value) => {
let serverList = []
setFormObj(value);
if (JSON.stringify(value) != "{}") {
GettMaplayer({ terminalType: 'base', isBaseMap: true }).then(res => {
if (res.msg==='Ok') {
res.data.general.baseMap.layers.map(item => {
if (value.baseMap.indexOf(item.servicename) == -1) {
serverList.push(item.servicename)
}
})
}
if (serverList.length) {
setServiceList(serverList)
setType('add');
setVisible(true);
}
else {
notification.warning({
message: '提示',
duration: 3,
description: '请先在基础配置-配置底图',
});
}
})
}
}
const submitExtent = (extent, areaName) => {
const jsConfig = {
extent: extent,
areaName: areaName,
boundColor: "#86c8f8",
boundWidth: "10px",
backgroundColor: "#000000",
backgroundOpacity: "0.6"
}
SetServiceConfig(
{
schemename: item.schemename,
terminalType: "web",
isBaseMap: false,
jsconCfg: JSON.stringify(jsConfig)
}
).then(
res => {
if (res.msg === "Ok") {
setMapScopeVisible(true)
message.info("范围设置成功")
}
}
)
}
return (
<>
<Card title={<div><span className={styles.schemeName}>方案名</span>{props.item.schemename}</div>} extra={<a href="#">
<Popconfirm
title="是否删除该方案?"
okText="确认"
cancelText="取消"
onConfirm={() => {
deleteTile(props.item);
}}
>
<CloseOutlined />
</Popconfirm> </a>} style={{ width: 300 }}>
<p><span className={styles.schemeName}>矢量</span> {props.item.servicename}</p>
<div>
<span className={styles.schemeName}>范围</span>
<Button style={{ width: '12rem', marginBottom: '0.5rem' }} onClick={() => setMapScopeVisible(true)}>选择范围</Button>
</div>
<div className={styles.schemeItem}><span className={styles.schemeName}>瓦片</span>
<Button className={styles.schemeBtn} onClick={() => addTile(props.item)}> <PlusOutlined />添加瓦片</Button>
</div>
<div style={{ overflowY: 'scroll', maxHeight: '11.4rem' }}>
{props.item.baseMap && props.item.baseMap.length ? props.item.baseMap.map((baseMapItem, baseindex) => {
return <div className={styles.mapItem} key={baseindex} >
<div className={classnames({
[styles.defaultTile]: true,
[styles.activeTile]: baseindex == props.item.defaultBaseMap,
})}>默认</div>
<div className={styles.mapText}>{baseMapItem}</div>
<div className={styles.mapIcon}>
<Popconfirm
title="是否删除该底图?"
okText="确认"
cancelText="取消"
onConfirm={() => {
deletebaseMap(props.item, baseMapItem);
}}
>
<CloseOutlined />
</Popconfirm> </div>
</div>
}) : ''}
</div>
</Card>
<AddModal
visible={visible}
onCancel={() => setVisible(false)}
callBackSubmit={onSubmit}
type={type}
serviceList={serviceList}
formObj={formObj}
/>
<MapScope
mapId={createGuid()}
visible={mapScopeVisible}
onCancel={() => setMapScopeVisible(false)}
confirmModal={submitExtent}
/>
</>
)
}
export default CardData
import React, { useState, useEffect , useRef} from 'react';
const pdCesium = require('@wisdom-cesium/cesium')
const Cesium = require('cesium/Cesium')
export default () => {
let el = useRef(null);
let buttonEl = useRef(null);
let pdViewer, viewer, extent, orientation, position;
useEffect(() => {
pdViewer = new pdCesium.PdRender({
el: el.current,
});
viewer = pdViewer.viewer;
pdViewer.viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(114.31, 30.52, 15000.0), //武汉
});
}, []);
function buttonClick(e) {
position = getCenterPosition();
extent = getCurrentExtent();
orientation = getOrientation();
console.log('当前视图范围', extent);
console.log('相机俯仰角', orientation);
console.log('相机位置', position);
}
function getOrientation() {
const { heading, pitch, roll } = viewer.camera;
const headingDegrees = Cesium.Math.toDegrees(heading);
const pitchDegrees = Cesium.Math.toDegrees(pitch);
const rollDegrees = Cesium.Math.toDegrees(roll);
return {
heading: headingDegrees,
pitch: pitchDegrees,
roll: rollDegrees,
};
}
/* 获取camera高度 */
function getHeight() {
if (viewer) {
var scene = viewer.scene;
var ellipsoid = scene.globe.ellipsoid;
var height = ellipsoid.cartesianToCartographic(viewer.camera.position)
.height;
return height;
}
}
/* 获取camera中心点坐标 */
function getCenterPosition() {
var result = viewer.camera.pickEllipsoid(
new Cesium.Cartesian2(
viewer.canvas.clientWidth / 2,
viewer.canvas.clientHeight / 2,
),
);
var curPosition = Cesium.Ellipsoid.WGS84.cartesianToCartographic(result);
var lon = (curPosition.longitude * 180) / Math.PI;
var lat = (curPosition.latitude * 180) / Math.PI;
var height = getHeight();
return {
lon: lon,
lat: lat,
height: height,
};
}
function getCurrentExtent() {
// 范围对象
var extent = {};
// 得到当前三维场景
var scene = viewer.scene;
// 得到当前三维场景的椭球体
var ellipsoid = scene.globe.ellipsoid;
var canvas = scene.canvas;
// canvas左上角
var car3_lt = viewer.camera.pickEllipsoid(
new Cesium.Cartesian2(0, 0),
ellipsoid,
);
// canvas右下角
var car3_rb = viewer.camera.pickEllipsoid(
new Cesium.Cartesian2(canvas.width, canvas.height),
ellipsoid,
);
// 当canvas左上角和右下角全部在椭球体上
if (car3_lt && car3_rb) {
var carto_lt = ellipsoid.cartesianToCartographic(car3_lt);
var carto_rb = ellipsoid.cartesianToCartographic(car3_rb);
extent.xmin = Cesium.Math.toDegrees(carto_lt.longitude);
extent.ymax = Cesium.Math.toDegrees(carto_lt.latitude);
extent.xmax = Cesium.Math.toDegrees(carto_rb.longitude);
extent.ymin = Cesium.Math.toDegrees(carto_rb.latitude);
}
// 当canvas左上角不在但右下角在椭球体上
else if (!car3_lt && car3_rb) {
var car3_lt2 = null;
var yIndex = 0;
do {
// 这里每次10像素递加,一是10像素相差不大,二是为了提高程序运行效率
yIndex <= canvas.height ? (yIndex += 10) : canvas.height;
car3_lt2 = viewer.camera.pickEllipsoid(
new Cesium.Cartesian2(0, yIndex),
ellipsoid,
);
} while (!car3_lt2);
var carto_lt2 = ellipsoid.cartesianToCartographic(car3_lt2);
var carto_rb2 = ellipsoid.cartesianToCartographic(car3_rb);
extent.xmin = Cesium.Math.toDegrees(carto_lt2.longitude);
extent.ymax = Cesium.Math.toDegrees(carto_lt2.latitude);
extent.xmax = Cesium.Math.toDegrees(carto_rb2.longitude);
extent.ymin = Cesium.Math.toDegrees(carto_rb2.latitude);
}
// 获取高度
extent.height = Math.ceil(viewer.camera.positionCartographic.height);
return [extent.xmin, extent.ymin, extent.xmax, extent.ymax];
}
return (
<div>
<div ref={el} style={{ width: '100%', height: '150px' }} />
<button ref={buttonEl} onClick={buttonClick}>
获取视角
</button>
</div>
);
};
import { Button,Spin } from 'antd';
import React, { useState, useEffect } from 'react';
import styles from '../dimensionsConfig.less'
import {
GetMaplayerByTerminalType
} from '@/services/webConfig/api';
import AddModal from './AddModal'
import Cards from './components/card'
const VectorData = props => {
const [treeLoading, setTreeLoading] = useState(false);// 弹窗显示
const [tileData, setTileData] = useState([]); // 页面初始化数据
const [visible, setVisible] = useState(false); // 弹窗
const [flag, setFlag] = useState(0); // 状态更新
const [type, setType] = useState(''); // 弹窗类型
const [formObj, setFormObj] = useState({});
const onSubmit = prop => {
setVisible(false);
};
const onDeletebaseMap = (value) => {
setFlag(flag + 1)
}
const handleAdd = () => {
setType('schemeAdd');
setVisible(true);
}
useEffect(() => {
renderTile();
}, [visible, flag]);
// 获取瓦片数据配置数据
const renderTile = () => {
setTreeLoading(true);
GetMaplayerByTerminalType({
terminalType: 'scheme',
isBaseMap: false
}).then(
res => {
console.log('res',res);
if (res.msg ==='Ok') {
setTreeLoading(false);
setTileData(res.data.scheme.optionalLayer.layers);
} else {
setTreeLoading(false);
}
}
)
};
return (
<>
<Spin tip="loading..." spinning={treeLoading}>
<div style={{ width: 'calc(100vw - 265px)' }}>
<div className={styles.tileBtn}>
<Button type="primary" onClick={() => {
handleAdd();
}} >
新增
</Button>
</div>
<div className={styles.cardsList}>
{tileData && tileData.length ?
tileData.map((item, index) => {
return <div className={styles.cardItem} key={index} span={5} offset={2} style={{ marginBottom: '1rem' }}>
<Cards item={item} deletebaseMaps={onDeletebaseMap} ></Cards>
</div>
}) : ''}
</div >
<AddModal
visible={visible}
onCancel={() => setVisible(false)}
callBackSubmit={onSubmit}
type={type}
formObj={formObj}
/>
</div>
</Spin>
</>
)
}
export default VectorData
\ No newline at end of file
import React, { useState, useEffect } from 'react';
import { Form, Modal, Input, Select, AutoComplete, Button, notification } from 'antd';
import {
SetServiceConfig
} from '@/services/webConfig/api';
const { Option } = Select;
const AddModal = props => {
const { callBackSubmit = () => { }, type, formObj, visible, listData } = props;
const [loading, setLoading] = useState(false);
const [form] = Form.useForm();
const { Item } = Form;
// 提交
const onSubmit = () => {
form.validateFields().then(validate => {
if (validate) {
setLoading(true);
let obj = form.getFieldsValue();
SetServiceConfig({
schemename: obj.schemename,
terminalType: type === 'add' ? 'web' : 'phone',
isBaseMap: 'false',
jsonCfg: type === 'add' ? JSON.stringify({ type: 'dynamic' }) : JSON.stringify({ isDefault: false })
})
.then(res => {
setLoading(false);
if (res.msg === "Ok") {
form.resetFields();
callBackSubmit();
notification.success({
message: '提示',
duration: 3,
description: '新增成功',
});
} else {
notification.error({
message: '提示',
duration: 3,
description: '新增失败',
});
}
})
.catch(err => {
notification.error({
message: '提示',
duration: 3,
description: '新增失败',
});
setLoading(false);
});
}
});
};
const onFinish = value => { };
useEffect(() => {
if(type!=''){
form.setFieldsValue({ schemename: listData[0] });
}
}, [visible]);
const layout = {
layout: 'horizontal',
labelCol: {
span: 4,
},
wrapperCol: {
span: 16,
},
};
const handleChange = (value) => {
form.setFieldsValue({ schemename: value});
}
return (
<Modal
title={`${type === 'add' ? '元数据发布' : '编辑'}`}
bodyStyle={{ width: '100%', minHeight: '100px' }}
style={{ top: '150px' }}
width="700px"
destroyOnClose
maskClosable={false}
cancelText="取消"
okText="确认"
{...props}
onOk={() => onSubmit()}
confirmLoading={loading}
forceRender={true}
getContainer={false}
>
{visible && (
<Form form={form} {...layout} onFinish={onFinish}>
<Item
label="方案名"
name="schemename"
rules={[{ required: true, message: '请选择服务名' }]}
>
<Select onChange={handleChange}>
{listData.map((item, index) => { return <Option value={item} key={index}>{item}</Option> }) }
</Select>
</Item>
</Form>
)}
</Modal>
);
};
export default AddModal;
...@@ -39,6 +39,8 @@ import JumpContainer from '@/components/JumpContainer'; ...@@ -39,6 +39,8 @@ import JumpContainer from '@/components/JumpContainer';
import HostManager from '@/pages/platformCenter/hostmanager' import HostManager from '@/pages/platformCenter/hostmanager'
import MessageManager from '@/pages/platformCenter/messageManage' import MessageManager from '@/pages/platformCenter/messageManage'
import SchemeConfig from '@/pages/platformCenter/schemeConfig/schemeConfig'; import SchemeConfig from '@/pages/platformCenter/schemeConfig/schemeConfig';
import DimensionsConfig from '@/pages/platformCenter/dimensionsConfig/dimensionsConfig';
import TaskScheduling from '@/pages/artificial/taskScheduling/taskScheduling'; import TaskScheduling from '@/pages/artificial/taskScheduling/taskScheduling';
import PoliciesIssued from '@/pages/artificial/policiesIssued/policiesIssued'; import PoliciesIssued from '@/pages/artificial/policiesIssued/policiesIssued';
import TableManager from '@/pages/platformCenter/bsmanager/tablemanager' import TableManager from '@/pages/platformCenter/bsmanager/tablemanager'
...@@ -163,7 +165,7 @@ export default { ...@@ -163,7 +165,7 @@ export default {
{ {
path: '/platformCenter/gis/threeDimensionConfig', path: '/platformCenter/gis/threeDimensionConfig',
name: '三维配置', name: '三维配置',
component: SchemeConfig, component: DimensionsConfig,
} }
], ],
// routes: [{ // routes: [{
......
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