suerprisePlus
2024-07-30 e5e65bb50cbfb973f98191993ab559767eff7a53
页面添加(知识图谱,数据统计,数据分析,站点管理)
已添加23个文件
已修改16个文件
2823 ■■■■■ 文件已修改
package.json 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/config/config.js 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/glb/BDZ.glb 补丁 | 查看 | 原始文档 | blame | 历史
public/glb/BYQ.glb 补丁 | 查看 | 原始文档 | blame | 历史
public/glb/DLQ.glb 补丁 | 查看 | 原始文档 | blame | 历史
public/glb/GGG.glb 补丁 | 查看 | 原始文档 | blame | 历史
public/glb/GLKG.glb 补丁 | 查看 | 原始文档 | blame | 历史
public/glb/LJX.glb 补丁 | 查看 | 原始文档 | blame | 历史
public/glb/PDS.glb 补丁 | 查看 | 原始文档 | blame | 历史
public/glb/QT.glb 补丁 | 查看 | 原始文档 | blame | 历史
public/glb/RDQ.glb 补丁 | 查看 | 原始文档 | blame | 历史
public/glb/SNG.glb 补丁 | 查看 | 原始文档 | blame | 历史
public/glb/XB.glb 补丁 | 查看 | 原始文档 | blame | 历史
public/glb/ZB.glb 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mapView/map.js 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/js/configTools.js 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/js/mapSdk/index.js 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/js/mapSdk/mapConfig.js 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/js/mapSdk/mapData.js 133 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/js/mapSdk/mapServe.js 169 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/js/mapSdk/menuManager.js 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Tool/Popup.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/mapOl/index.vue 193 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/getters.js 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/index.js 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/modules/mapLayers.js 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/mapServer/kgServer.js 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dataManager/siteInfo/index.vue 285 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/visual/analysis/index.vue 197 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/visual/atlas/index.vue 363 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/visual/mapLayer/index.vue 460 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/visual/mapView/attributeInfo.vue 171 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/visual/mapView/dataAnalysis.vue 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/visual/mapView/dataStatistics.vue 157 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/visual/mapView/index.vue 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/visual/mapView/layerManager.vue 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/visual/mapView/lineRoaming.vue 118 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/visual/mapView/location.vue 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/visual/mapView/undergroundMode.vue 116 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package.json
@@ -36,14 +36,16 @@
    "url": "https://gitee.com/y_project/RuoYi-Vue.git"
  },
  "dependencies": {
    "@antv/g6": "^4.8.19",
    "@easydarwin/easywasmplayer": "^4.0.7",
    "@jiaminghi/data-view": "^2.10.0",
    "@riophae/vue-treeselect": "0.4.0",
    "@turf/turf": "^7.0.0",
    "axios": "0.24.0",
    "clipboard": "2.0.8",
    "codemirror": "^5.65.2",
    "core-js": "3.25.3",
    "echarts": "5.4.0",
    "core-js": "^3.25.3",
    "echarts": "^5.4.0",
    "element-china-area-data": "^4.1.1",
    "element-ui": "2.15.10",
    "file-saver": "2.0.5",
@@ -58,11 +60,14 @@
    "moment": "^2.29.4",
    "mqtt": "^4.3.3",
    "nprogress": "0.2.0",
    "ol": "^6.15.1",
    "quill": "1.3.7",
    "relation-graph": "^2.2.3",
    "screenfull": "5.0.2",
    "script-loader": "^0.7.2",
    "sortablejs": "1.10.2",
    "sql-formatter": "^4.0.2",
    "terraformer-wkt-parser": "^1.2.1",
    "three": "^0.157.0",
    "vue": "2.6.12",
    "vue-clipboard2": "^0.3.3",
@@ -76,7 +81,8 @@
    "vue-router": "3.4.9",
    "vue-seamless-scroll": "^1.1.23",
    "vuedraggable": "2.24.3",
    "vuex": "3.6.0"
    "vuex": "3.6.0",
    "xlsx": "^0.16.0"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "4.4.6",
public/config/config.js
@@ -1,8 +1,39 @@
console.log(location);
const host = location.origin;
const isWeb = false;
var isUrl = isWeb ? "103.135.160.14" : "192.168.11.24";
// api端口
const apiHost = isWeb ? isUrl + "" : isUrl + ":12316";
// é…ç½‘端口
const peiWangHost = isWeb ? isUrl + "" : isUrl + ":8101";
// GeoServer端口
const geoHost = isWeb ? isUrl + "" : isUrl + ":9055";
// {host}替换
const iisHost = isWeb ? isUrl + ":9036" : "localhost:80";
// çŸ¥è¯†å›¾è°±ç«¯å£
const kgHost = isWeb ? isUrl + ":9036" : isUrl + ":8080";
// æ•°æ®åˆ†æžç«¯å£
const pyHost = isWeb ? isUrl + ":9036" : isUrl + ":8000";
//配置
const config = {
  apiServices: "http://192.168.11.24:12316/server/",
  // server服务
  apiServices: "http://" + apiHost + "/server/",
  // çŸ¥è¯†å›¾è°±æœåŠ¡
  kgServices: "http://" + kgHost,
  // é…ç½‘服务
  peiWangServices: "http://" + peiWangHost + "/peiwang/",
  //数据分析接口
  pyServices: "http://" + pyHost + "/py",
  imageUrl: "",
  sdkImg: host+"/visual/CimSDK/"
  // sdk显示
  sdkImg: host + "/visual/CimSDK/",
  // å¤©åœ°å›¾
  tdToken: "94a34772eb88317fcbf8428e10448561",
  // geoServer服务
  geoServer: {
    url: "http://" + geoHost + "/geoserver/sxpw",
    wms: "/wms",
    wfs: ""
  }
};
public/glb/BDZ.glb
Binary files differ
public/glb/BYQ.glb
Binary files differ
public/glb/DLQ.glb
Binary files differ
public/glb/GGG.glb
Binary files differ
public/glb/GLKG.glb
Binary files differ
public/glb/LJX.glb
Binary files differ
public/glb/PDS.glb
Binary files differ
public/glb/QT.glb
Binary files differ
public/glb/RDQ.glb
Binary files differ
public/glb/SNG.glb
Binary files differ
public/glb/XB.glb
Binary files differ
public/glb/ZB.glb
Binary files differ
src/api/mapView/map.js
@@ -1,6 +1,63 @@
import mapServer from '../../utils/mapServer/mapServer';
import mapServer from '@/utils/mapServer/mapServer';
import kgServer from '@/utils/mapServer/kgServer';
//配网接口 => æŸ¥è¯¢æ‰€æœ‰
export function zhangzitou_selectAllLine(params) {
    return mapServer.get('/zhangzitou/selectAllLine', { params: params });
}
//图层管理 => æŸ¥è¯¢æ‰€æœ‰
export function layer_selectAll(params) {
    return mapServer.get('/layer/selectAll', { params: params });
}
//图层管理 => æ–°å¢žå›¾å±‚
export function layer_insert(params) {
    return mapServer.post('/layer/insert', params);
}
//图层管理=> åˆ é™¤å›¾å±‚
export function layer_delete(params) {
    return mapServer.get('/layer/delete', { params: params });
}
//图层管理=> åˆ é™¤å›¾å±‚
export function layer_updates(params) {
    return mapServer.post('/layer/updates', params);
}
//图层管理=> æ›´æ–°ä¸€æ¡
export function layer_update(params) {
    return mapServer.post('/layer/update', params);
}
//配网接口 => æŸ¥è¯¢æ‰€æœ‰
export function zhangzitou_selectAll(params) {
    return mapServer.get('/zhangzitou/selectAll', { params: params });
}
//图谱查询接口
export function kg_getGraph(params) {
    return kgServer.post('/kg/getGraph', params);
}
//图谱查询接口
export function kg_queryGraphResult(params) {
    return kgServer.post('/kg/queryGraphResult', params);
}
//配网接口 => æ•°æ®ç»Ÿè®¡
export function zhangzitou_selectInfos(params) {
    return mapServer.get('/zhangzitou/selectInfos', { params: params });
}
//配网接口 => æ•°æ®ç»Ÿè®¡=>线路
export function zhangzitou_deleteZhangzitouEntitys(params) {
    return mapServer.get('/zhangzitou/deleteZhangzitouEntitys', { params: params });
}
//配网接口 => ç«™ç‚¹æ–°å¢ž
export function zhangzitou_insertZhangzitouEntity(params) {
    return mapServer.post('/zhangzitou/insertZhangzitouEntity', params);
}
//配网接口 => ä¿®æ”¹ç«™ç‚¹
export function zhangzitou_updateZhangzitouEntity(params) {
    return mapServer.post('/zhangzitou/updateZhangzitouEntity', params);
}
// //配网接口 => åˆ é™¤ç«™ç‚¹
// export function zhangzitou_deleteZhangzitouEntitys(params) {
//     return mapServer.get('/zhangzitou/deleteZhangzitouEntitys', { params: params } );
//   }
src/assets/js/configTools.js
@@ -20,6 +20,25 @@
    },
    add0(m) {
        return m < 10 ? '0' + m : m;
      },
    },
    //JSON生成目录树
    getTreeData(res) {
        let cloneData = JSON.parse(JSON.stringify(res)); // å¯¹æºæ•°æ®æ·±åº¦å…‹éš†
        return cloneData.filter((father) => {
            // å¾ªçŽ¯æ‰€æœ‰é¡¹
            let branchArr = cloneData.filter((child) => father.id == child.pid);
            if (branchArr.length > 0) {
                branchArr.sort(function (a, b) {
                    return a.orderNum - b.orderNum;
                });
            }
            branchArr.length > 0 ? (father.children = branchArr) : ''; // ç»™çˆ¶çº§æ·»åŠ ä¸€ä¸ªchildren属性,并赋值
            // å±žäºŽåŒä¸€å¯¹è±¡é—®é¢˜ï¼Œä¾‹å¦‚:令 a=b、c=1 ï¼Œç„¶åŽå†ä»¤ b.c=c ï¼Œ é‚£ä¹ˆ a.c=b.c=c=1 ï¼›åŒç†ï¼ŒåŽç»­ä»¤ c.d=2 ,那么 a.c.d ä¹Ÿæ˜¯=2;
            // ç”±æ­¤å¾ªçŽ¯å¤šæ¬¡åŽï¼Œå°±èƒ½å½¢æˆç›¸åº”çš„æ ‘å½¢æ•°æ®ç»“æž„
            return father.pid == 0; // è¿”回一级菜单
        });
    },
};
export default configTools;
src/assets/js/mapSdk/index.js
@@ -1,3 +1,7 @@
import mapConfig from './mapConfig';
import mapData from './mapData';
import mapServer from './mapServe';
const mapInit = {
    Init() {
        window.earthCtrl = new SmartEarth.EarthCtrl('sdkContainer', {
@@ -7,9 +11,32 @@
            printLog: false,
            // sceneMode: SmartEarth.Cesium.SceneMode.SCENE2D
        });
        // åˆå§‹åŒ–Cesium
        window.Cesium = SmartEarth.Cesium;
        // åˆå§‹åŒ–Viewer
        window.Viewer = earthCtrl.viewer;
        Viewer.scene.globe.baseColor = Cesium.Color.fromCssColorString('#A9A9A9'); //设置地球颜色
        //设置地球颜色
        Viewer.scene.globe.baseColor = Cesium.Color.fromCssColorString('#A9A9A9');
        // é»˜è®¤è®¾ç½®åº•图
        this.addImageLayer();
    },
    addImageLayer() {
        const baseLayer = mapData.baseLayer;
        // æ·»åŠ å¤©åœ°å›¾åº•å›¾
        mapServer.addLayer({
            serveType: 'tdMap',
            url: baseLayer.sUrl + baseLayer.vecLayer + baseLayer.lUrl,
        });
        // æ·»åŠ å¤©åœ°å›¾æ ‡æ³¨
        mapServer.addLayer({
            serveType: 'tdMap',
            url: baseLayer.sUrl + baseLayer.cvaLayer + baseLayer.lUrl,
        });
        // åˆå§‹åŒ–视角
        this.setdefaultPerspective();
    },
    setdefaultPerspective() {
        mapConfig.sertCameraTo(mapData.defaultPerspective);
    },
};
export default mapInit;
src/assets/js/mapSdk/mapConfig.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,35 @@
import WKT from 'terraformer-wkt-parser';
const mapConfig = {
    sertCameraTo(res) {
        earthCtrl.camera.jumpTo({
            destination: {
                x: res.x,
                y: res.y,
                z: res.z,
            },
        });
    },
    userSceneFlyTo(res){
        const options = {
            duration: 2,
            offset: new SmartEarth.Cesium.HeadingPitchRange(1.0, -0.3, 1000)
        };
        earthCtrl.userScene.flyTo(res,options);
    },
    getModelMatrix(res) {
        var headingPitchRoll = new Cesium.HeadingPitchRoll(res.heading, res.pitch, res.roll);
        var position = Cesium.Cartesian3.fromDegrees(res.longitude, res.latitude, res.altitude);
        var modelMatrix = Cesium.Transforms.headingPitchRollToFixedFrame(
            position, headingPitchRoll, Cesium.Ellipsoid.WGS84,
            Cesium.Transforms.eastNorthUpToFixedFrame,
            new Cesium.Matrix4());
        return modelMatrix;
    },
    getWKTParse(res){
        return WKT.parse(res)
    },
    getWKTConvert(res){
        return WKT.convert(res)
    }
};
export default mapConfig;
src/assets/js/mapSdk/mapData.js
@@ -1,3 +1,5 @@
// import { label } from 'three/examples/jsm/nodes/Nodes.js';
const mapData = {
    menuData: [
        {
@@ -73,13 +75,13 @@
        {
            id: 's6',
            name: '定位',
            children:[
            children: [
                {
                    id:'a1',
                    name:'坐标定位',
                    id: 'a1',
                    name: '坐标定位',
                    pid: 's6',
                }
            ]
                },
            ],
        },
        {
            id: 's7',
@@ -147,7 +149,7 @@
                    pid: 's8',
                },
                {
                    id: 'a6',
                    id: 'a5',
                    name: '清除',
                    pid: 's8',
                },
@@ -159,7 +161,7 @@
            children: [
                {
                    id: 'a1',
                    name: '地下模型',
                    name: '地下模式',
                    pid: 's9',
                },
                {
@@ -170,5 +172,122 @@
            ],
        },
    ],
    // é»˜è®¤åº•图
    baseLayer: {
        sUrl: 'http://t0.tianditu.gov.cn/DataServer?T=',
        lUrl: '&x={x}&y={y}&l={z}&tk=',
        vecLayer: 'vec_w',
        cvaLayer: 'cva_w',
    },
    // é»˜è®¤è§†è§’
    defaultPerspective: {
        x: -1935239.1689147458,
        y: 4653957.816261454,
        z: 3900586.9686804516,
    },
    // å›¾å±‚管理
    layerData: {
        layerOption: [
            {
                value: '1',
                label: '目录',
            },
            {
                value: '2',
                label: '图层',
            },
        ],
        sourceOption: [
            {
                value: 'Tileset',
                label: 'Tileset',
            },
            {
                value: 'WMS',
                label: 'WMS',
            },
            {
                value: 'TMS',
                label: 'TMS',
            },
            {
                value: 'GEOJSON',
                label: 'GEOJSON',
            },
            {
                value: 'WFS',
                label: 'WFS',
            },
        ],
        dataOption: [
            { value: '杆塔', label: '杆塔' },
            {
                value: '配网箱',
                label: '配网箱',
            },
            {
                value: '环网柜',
                label: '环网柜',
            },
            {
                value: 'HW',
                label: 'HW',
            },
            {
                value: 'KG',
                label: 'KG',
            },
            {
                value: 'PD',
                label: 'PD',
            },
            {
                value: 'XB',
                label: 'XB',
            },
            {
                value: 'ZB',
                label: 'ZB',
            },
            {
                value: '变压器',
                label: '变压器',
            },
            {
                value: '变电站',
                label: '变电站',
            },
            {
                value: '指示器',
                label: '指示器',
            },
            {
                value: '其他',
                label: '其他',
            },
        ],
    },
    // æ•°æ®ç»Ÿè®¡
    dataStatistics: {
        BDZ: '变电站',
        BYQ: '变压器',
        DLQ: '断路器',
        GT: '杆塔',
        GGG: '钢管杆',
        GLKG: '隔离开关',
        LJX: '连接线',
        PD: '配电室',
        RDQ: '熔断器',
        SNG: '水泥杆',
        XB: '箱变',
        HW: '环网柜',
        DLZJJT: '电缆中间接头',
        ZB: 'ZB',
        KG: '开关',
        ZSQ: '故障指示器',
        PDS: 'PDS',
    },
};
export default mapData;
src/assets/js/mapSdk/mapServe.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,169 @@
import mapConfig from './mapConfig';
import { zhangzitou_selectAll } from '@/api/mapView/map.js';
import WKT from 'terraformer-wkt-parser';
// æœåŠ¡åŠ è½½
const mapServer = {
    serveType: null,
    layerList: [],
    addLayer(res) {
        const obj = this.getLayerChecked(res);
        if (obj) return;
        this.serveType = res.serveType;
        switch (this.serveType) {
            case 'tdMap':
                this.addTdLayer(res);
                break;
            case 'WMS':
                this.addWMSLayer(res);
                break;
            case 'Tileset':
                this.addTilesetLayer(res);
                break;
            case 'WFS':
                this.addWFSLayer(res);
                break;
        }
    },
    addWFSLayer(res) {
        zhangzitou_selectAll({
            limit: 1000000,
            page: 1,
        }).then((response) => {
            if (response.data.code != 200) return;
            const pois = response.data.result.pois;
            const cnName = res.cnName + '_' + res.id;
            const modelLayer = new Cesium.PrimitiveCollection();
           modelLayer.name = cnName;
            Viewer.scene.primitives.add(modelLayer);
            pois.map((item) => {
                var geom = WKT.parse(item.geom);
                var style = {
                    longitude: geom.coordinates[0],
                    latitude: geom.coordinates[1],
                    altitude: 0,
                    heading: 0,
                    pitch: 0,
                    roll: 0,
                };
                const modelMatrix = mapConfig.getModelMatrix(style);
                const url =  '/glb/' + item.type + '.glb';
                modelLayer.add(
                    Cesium.Model.fromGltf({
                        id: item.id,
                        url: url,
                        scale: 1,
                        minimumPixelSize: 20,
                        maximumScale: 20,
                        modelMatrix: modelMatrix,
                        primitive: item,
                    })
                );
            });
            this.layerList.push({
                id: res.id,
                name: cnName,
                layer: modelLayer,
                serveType: this.serveType,
            });
        });
    },
    addTdLayer(res) {
        const url = res.url + config.tdToken;
        Viewer.imageryLayers.addImageryProvider(
            new Cesium.UrlTemplateImageryProvider({
                url: url,
            })
        );
    },
    getLayerChecked(res) {
        const obj = this.layerList.filter((item) => {
            if (item.id == res.id) {
                return item;
            }
        });
        const boolen = obj.length > 0 ? true : false;
        return boolen;
    },
    addWMSLayer(res) {
        const serverUrl = config.geoServer;
        const that = this;
        var getFeatureInfoFormat = new Cesium.GetFeatureInfoFormat('html', null, function (html) {
            that.getFeatureInfo(html);
        });
        const layer = new Cesium.WebMapServiceImageryProvider({
            url: serverUrl.url + serverUrl.wms,
            layers: res.url,
            getFeatureInfoParameters: { info_format: 'text/html' },
            enablePickFeatures: true,
            getFeatureInfoFormats: [getFeatureInfoFormat],
            parameters: {
                transparent: true,
                format: 'image/png',
                srs: 'EPSG:4490',
                styles: '',
                cql_filter: '',
            },
            tileWidth: 512,
            tileHeight: 512,
        });
        const imageLayer = Viewer.imageryLayers.addImageryProvider(layer);
        const cnName = res.cnName + '_' + res.id;
        imageLayer.name = cnName;
        imageLayer.id = res.id;
        this.layerList.push({
            id: res.id,
            name: cnName,
            layer: imageLayer,
            serveType: this.serveType,
        });
    },
    addTilesetLayer(res) {
        let url = res.url.indexOf('{host}') > -1 ? res.url.replace('{host}', iisHost) : res.url;
        var height = 0;
        if (res.bak) {
            height = JSON.parse(res.bak).height;
        }
        var model = earthCtrl.factory.create3DTilesets({
            url: url,
            option: {
                height: height,
                id: res.id,
            },
        });
        const cnName = res.cnName + '_' + res.id;
        model.item.readyPromise.then((item) => {
            mapConfig.userSceneFlyTo(item);
            this.layerList.push({
                id: res.id,
                name: cnName,
                layer: model,
                serveType: this.serveType,
            });
        });
    },
    setTilesetArgs() {},
    removeLayer(res) {
        const cnName = res.cnName + '_' + res.id;
        this.layerList.map((item, index) => {
            if (cnName == item.name && res.id == item.id) {
                if (item.serveType == 'WMS') {
                    Viewer.imageryLayers.remove(item.layer);
                    this.layerList.splice(index, 1);
                } else if (item.serveType == 'Tileset') {
                    item.layer.deleteObject();
                    this.layerList.splice(index, 1);
                }else if (item.serveType == 'WFS') {
                    Viewer.scene.primitives.remove(item.layer)
                    this.layerList.splice(index, 1);
                }
            }
        });
    },
    async getFeatureInfo(res) {
        console.log(res);
    },
};
export default mapServer;
src/assets/js/mapSdk/menuManager.js
@@ -1,3 +1,4 @@
const menuManager = {
    pid: null,
    pointFly: null,
@@ -190,7 +191,7 @@
                return res.name;
                break;
            case 'a2':
                return res.name;
                earthCtrl.factory.createScreenshot();
                break;
            default:
                return null;
src/components/Tool/Popup.vue
@@ -43,7 +43,7 @@
            showBox: false,
            // æ˜¯å¦æ˜¾ç¤ºå†…容
            showContainer: true,
            defaultMaxHeight: '400px',
            defaultMaxHeight: '700px',
        };
    },
    directives: {
src/components/mapOl/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,193 @@
<template>
    <div id="mapView" class="olBox">
        <div class="menuTool">
            <el-form :inline="true" :model="formInline" class="demo-form-inline">
                <el-form-item label="经度:">
                    {{ formInline.lon }}
                </el-form-item>
                <el-form-item label="纬度:">
                    {{ formInline.lat }}
                </el-form-item>
                <el-form-item>
                    <el-button type="success" icon="el-icon-plus" @click="drowPoint"></el-button>
                    <el-button type="danger" icon="el-icon-delete" @click="clearDrawPoint"></el-button>
                </el-form-item>
            </el-form>
        </div>
    </div>
</template>
<script>
import TileLayer from 'ol/layer/Tile';
import XYZ from 'ol/source/XYZ';
import Map from 'ol/Map';
import View from 'ol/View';
import { transform } from 'ol/proj';
import VectorSource from 'ol/source/Vector';
import { Vector as VectorLayer, Tile } from 'ol/layer';
import { Draw } from 'ol/interaction';
import Feature from 'ol/Feature';
import { Circle as CircleStyle, Style, Fill, Stroke, Icon, Text } from 'ol/style';
import { Point } from 'ol/geom';
import ImageWMS from "ol/source/ImageWMS";
import Image from "ol/layer/Image";
import mapData from '@/assets/js/mapSdk/mapData.js';
import mapConfig from '../../assets/js/mapSdk/mapConfig';
import * as turf from '@turf/turf'
export default {
    props: {
        parentData: {
            type: String,
            default: '',
        }
    },
    data() {
        return {
            mapol: null,
            drawLayer: null,
            formInline: {
                lon: '',
                lat: ''
            }
        }
    },
    mounted() {
        this.initOlMap();
    },
    methods: {
        initOlMap() {
            const baseLayer = mapData.baseLayer;
            const vecUrl = baseLayer.sUrl + baseLayer.vecLayer + baseLayer.lUrl
            var vectorLayer = new TileLayer({
                source: new XYZ({
                    url: vecUrl + config.tdToken,
                }),
            });
            const cvaUrl = baseLayer.sUrl + baseLayer.cvaLayer + baseLayer.lUrl
            var vectorLayer1 = new TileLayer({
                source: new XYZ({
                    url: cvaUrl + config.tdToken,
                }),
            });
            this.mapol = new Map({
                target: 'mapView',
                layers: [vectorLayer, vectorLayer1],
                view: new View({
                    center: transform([112.5545931210261, 37.86275646283009], 'EPSG:4326', 'EPSG:3857'),
                    zoom: 12,
                    projection: 'EPSG:3857',
                }),
            });
            var layer2 = new Image({
                name: "Wms_Layer",
                source: new ImageWMS({
                    crossOrigin: "anonymous",
                    url: config.geoServer.url + config.geoServer.wms,
                    params: {
                        FORMAT: "image/png",
                        VERSION: "1.1.1",
                        LAYERS: 'sxpw:sxdwx',
                    },
                }),
            });
            this.mapol.addLayer(layer2);
            if (this.parentData) {
                const obj = mapConfig.getWKTParse(this.parentData)
                this.formInline = {
                    lon: obj.coordinates[0],
                    lat: obj.coordinates[1],
                }
                this.addPointData(obj);
            }
        },
        addPointData(res) {
            const coord = res.coordinates;
            const urlImg = config.sdkImg + 'Workers/image/mark.png';
            var geom = transform(
                [parseFloat(coord[0]), parseFloat(coord[1])],
                'EPSG:4326',
                'EPSG:3857'
            );
            var feature = new Feature({
                geometry: new Point(geom),
            });
            feature.setStyle(
                new Style({
                    image: new Icon({
                        scale: [0.8, 0.8],
                        src: urlImg
                    }),
                })
            );
            const source = new VectorSource();
            source.addFeature(feature);
            this.drawLayer = new VectorLayer();
            this.drawLayer.setSource(source);
            this.mapol.addLayer(this.drawLayer);
            this.setOlLocal(coord)
        },
        setOlLocal(geom) {
            this.mapol.getView().animate({
                center: transform(geom, 'EPSG:4326', 'EPSG:3857'), // ä¸­å¿ƒç‚¹
                zoom: 18, // ç¼©æ”¾çº§åˆ«
            });
        },
        drowPoint() {
            const source = new VectorSource({ wrapX: false });
            this.clearDrawPoint();
            this.drawLayer = new VectorLayer({
                source: source,
            });
            this.mapol.addLayer(this.drawLayer);
            this.draw = new Draw({
                source: source, // å’Œå›¾å±‚使用同一个source,画的图形在图层上,图层在地图上即可展示
                type: 'Point', // å¯é€‰æ‹©ä¸‰è§’形,多边形,圆形等具体见官网demo
                freehand: false, // ç”»é€‰è¿˜æ˜¯ç‚¹é€‰
            });
            // æ·»åŠ äº¤äº’
            this.mapol.addInteraction(this.draw);
            this.draw.on('drawend', (e) => {
                let feature = e.feature;
                let geom = feature.getGeometry();
                var extent = geom.flatCoordinates;
                var a1 = transform([extent[0], extent[1]], 'EPSG:3857', 'EPSG:4326');
                this.formInline.lon = parseFloat(a1[0]).toFixed(6);
                this.formInline.lat = parseFloat(a1[1]).toFixed(6);
                var point = turf.point([this.formInline.lon, this.formInline.lat]);
                const gPoint= mapConfig.getWKTConvert(point.geometry)
                this.$emit('childData', gPoint);
                this.mapol.removeInteraction(this.draw);
            });
        },
        clearDrawPoint() {
            if (this.drawLayer) {
                this.mapol.removeLayer(this.drawLayer);
            }
        },
    }
}
</script>
<style lang="scss" scoped>
.olBox {
    width: 100%;
    height: 100%;
    overflow: hidden;
    margin: 0;
    padding: 0;
    ::v-deep.ol-control {
        display: none;
    }
    .menuTool {}
}
</style>
src/store/getters.js
@@ -15,5 +15,7 @@
  topbarRouters:state => state.permission.topbarRouters,
  defaultRoutes:state => state.permission.defaultRoutes,
  sidebarRouters:state => state.permission.sidebarRouters,
  layerTree:state => state.mapLayers.layerTree,
  defaultLayer:state => state.mapLayers.defaultLayer,
}
export default getters
src/store/index.js
@@ -7,7 +7,7 @@
import permission from './modules/permission'
import settings from './modules/settings'
import getters from './getters'
import mapLayers from './modules/mapLayers'
Vue.use(Vuex)
const store = new Vuex.Store({
@@ -17,7 +17,8 @@
    user,
    tagsView,
    permission,
    settings
    settings,
    mapLayers
  },
  getters
})
src/store/modules/mapLayers.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,31 @@
import Cookies from 'js-cookie';
const state = {
    layerTree: [],
    defaultLayer: [],
};
const mutations = {
    CHANGE_LAYERTREE: (state, res) => {
        state.layerTree = res;
    },
    CHANGE_DEFAULTLAYER: (state,res) => {
        state.defaultLayer = res;
    },
};
const actions = {
    changeLayerTree({ commit }, obj) {
        commit('CHANGE_LAYERTREE', obj);
    },
    changeDefaultLayer({ commit }, obj) {
        commit('CHANGE_DEFAULTLAYER', obj);
    },
};
export default {
    namespaced: true,
    state,
    mutations,
    actions,
};
src/utils/mapServer/kgServer.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,9 @@
import axios from "axios";
const kgServer = axios.create({
    // axios中请求配置有baseURL选项,表示请求URL公共部分
    baseURL: config.kgServices,
    // è¶…æ—¶
    timeout: -1
  });
  export default kgServer;
src/views/dataManager/siteInfo/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,285 @@
<template>
    <div class="siteInfo">
        <el-card>
            <div class="infoSearch">
                <el-form :inline="true" :model="queryParams" class="demo-form-inline">
                    <el-form-item label="名称">
                        <el-input size="small" v-model="queryParams.name" placeholder="请输点位名称..."></el-input>
                    </el-form-item>
                </el-form>
                <div>
                    <el-button size="small" plain type="primary" @click="setInfoQyery" icon="el-icon-search">查询</el-button>
                    <el-button size="small" plain type="info" @click="setInfoRefresh" icon="el-icon-refresh">重置</el-button>
                    <el-button size="small" plain type="success" @click="setInfoAdd" icon="el-icon-plus">添加</el-button>
                    <el-button size="small" plain type="danger" @click="setInfoDel" icon="el-icon-delete">删除</el-button>
                </div>
            </div>
        </el-card>
        <el-card class="infoConTent">
            <div class="infoTable">
                <el-table :data="tableData" style="width: 100%" border height="calc(100% - 65px)" @selection-change="handleSelectionChange">
                    <el-table-column type="selection" width="55" />
                    <el-table-column align="center" type="index" label="序号" width="70px" />
                    <el-table-column align="center" prop="id" v-if="false" />
                    <el-table-column align="center" prop="name" label="名称" />
                    <el-table-column align="center" prop="line" label="环线" />
                    <el-table-column align="center" prop="type" label="类型" :formatter="setInFoType" />
                    <el-table-column align="center" prop="geom" label="位置" />
                    <el-table-column min-width="100" label="操作">
                        <template slot-scope="scope">
                            <el-button @click="setInfoEdit(scope.$index, scope.row)" type="warning" plain size="small">编辑</el-button>
                        </template>
                    </el-table-column>
                </el-table>
                <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageIndex" :limit.sync="queryParams.pageSize" @pagination="setInfoSearch" />
            </div>
        </el-card>
        <el-dialog width="30%" :title="dialogTitle" :before-close="outerClose" :visible.sync="dialogFlag">
            <el-form :model="editData">
                <el-form-item label="名称" :label-width="formLabelWidth">
                    <el-input v-model="editData.name" style="width: 100%" placeholder=""></el-input>
                </el-form-item>
                <el-form-item label="环线" :label-width="formLabelWidth">
                    <el-input v-model="editData.line" style="width: 100%" placeholder=""></el-input>
                </el-form-item>
                <el-form-item label="类型" :label-width="formLabelWidth">
                    <el-select v-model="editData.type" style="width: 100%" placeholder="">
                        <el-option v-for="item in siteOption" :key="item.value" :label="item.name" :value="item.val"></el-option>
                    </el-select>
                </el-form-item>
                <el-form-item label="位置" :label-width="formLabelWidth">
                    <div style="width: 100%">
                        <el-input v-model="editData.geom" style="width: 92%" placeholder="" disabled=""></el-input>
                        <el-link style="float: right" @click="setInnerDialog"><i class="el-icon-plus"></i></el-link>
                    </div>
                </el-form-item>
            </el-form>
            <el-dialog width="50%" title="点位" :visible.sync="innerVisible" :before-close="innerClose" append-to-body>
                <div style="height: 540px">
                    <olMap v-if="innerVisible" @childData="childData" :parentData="parentData"></olMap>
                </div>
            </el-dialog>
            <div slot="footer" class="dialog-footer">
                <el-button @click="outerClose">取 æ¶ˆ</el-button>
                <el-button @click="submitOuter" type="primary">ç¡® è®¤</el-button>
            </div>
        </el-dialog>
    </div>
</template>
<script>
import { zhangzitou_selectAll, zhangzitou_insertZhangzitouEntity, zhangzitou_updateZhangzitouEntity, zhangzitou_deleteZhangzitouEntitys } from '@/api/mapView/map.js';
import mapData from '@/assets/js/mapSdk/mapData';
import olMap from '@/components/mapOl/index.vue';
export default {
    components: {
        olMap,
    },
    data() {
        return {
            total: 0,
            queryParams: {
                pageIndex: 1,
                pageSize: 10,
                name: '',
                srid: 4326,
            },
            formLabelWidth: '80px',
            multipleSelection: [],
            tableData: [],
            editData: {
                type: '',
            },
            dialogTitle: null,
            dialogFlag: false,
            siteOption: [],
            infoOption: null,
            innerVisible: false,
            parentData: null,
        };
    },
    mounted() {
        this.setInfoSearch();
        this.getInfoOption();
    },
    methods: {
        setInFoType(row, column) {
            var obj = row.type;
            if (this.infoOption[obj]) {
                return this.infoOption[obj];
            }
            return obj;
        },
        getInfoOption() {
            this.infoOption = mapData.dataStatistics;
            const option = [];
            for (var key in this.infoOption) {
                option.push({
                    name: this.infoOption[key],
                    val: key,
                });
            }
            this.siteOption = option;
        },
        setInfoQyery() {
            this.queryParams.pageIndex = 1;
            this.queryParams.pageSize = 10;
            this.setInfoSearch();
        },
        setInfoSearch() {
            zhangzitou_selectAll({
                limit: this.queryParams.pageSize,
                page: this.queryParams.pageIndex,
                name: this.queryParams.name,
            }).then((response) => {
                if (response.data.code != 200) return;
                const valData = response.data.result;
                this.tableData = valData.pois;
                this.total = valData.total;
            });
        },
        setInfoRefresh() {
            this.queryParams = {
                pageIndex: 1,
                pageSize: 10,
                name: '',
                srid: 4326,
            };
            this.setInfoSearch();
        },
        setInfoAdd() {
            this.dialogTitle = '新增';
            this.editData.type = this.siteOption[0].val;
            this.dialogFlag = true;
        },
        setInfoDel() {
            if (this.multipleSelection.length < 0) return;
            const std = [];
            for (var i in this.multipleSelection) {
                std.push(this.multipleSelection[i].id);
            }
            zhangzitou_deleteZhangzitouEntitys({ ids: std.toString() }).then((response) => {
                if (response.data.code != 200) {
                    return this.$message('删除失败');
                }
                this.$message({
                    message: '删除成功',
                    type: 'success',
                });
                this.setInfoQyery();
            });
        },
        setInfoEdit(index, row) {
            this.dialogTitle = '修改';
            this.editData = { ...row };
            this.parentData = this.editData.geom;
            this.dialogFlag = true;
        },
        handleSelectionChange(res) {
            this.multipleSelection = res;
        },
        setInnerDialog() {
            this.innerVisible = true;
        },
        outerClose() {
            this.dialogFlag = false;
            this.parentData = null;
            this.editData = {
                type: '',
            };
        },
        innerClose() {
            this.innerVisible = false;
            this.parentData = null;
        },
        submitOuter() {
            if (this.dialogTitle == '新增') {
                this.outerInsert();
            } else {
                this.outerEdit();
            }
            this.dialogFlag = false;
        },
        childData(res) {
            this.editData.geom = res;
        },
        outerInsert() {
            const obj = { ...this.editData };
            zhangzitou_insertZhangzitouEntity(obj).then((response) => {
                if (response.data.code != 200) {
                    return this.$message('新增失败');
                }
                this.$message({
                    message: '新增成功',
                    type: 'success',
                });
                this.outerClose();
                this.setInfoRefresh();
            });
        },
        outerEdit() {
            const obj = { ...this.editData };
            console.log(obj);
            zhangzitou_updateZhangzitouEntity(obj).then((response) => {
                if (response.data.code != 200) {
                    return this.$message('修改失败');
                }
                this.$message({
                    message: '修改成功',
                    type: 'success',
                });
                this.outerClose();
                this.setInfoSearch();
            });
        },
    },
};
</script>
<style lang="scss" scoped>
.siteInfo {
    width: calc(100% - 20px);
    height: calc(100% - 20px);
    position: absolute;
    margin: 10px;
    border-radius: 5px;
    display: flex;
    flex-direction: column;
    .infoSearch {
        display: flex;
        justify-content: space-between;
        align-items: center;
        ::v-deep.el-form-item {
            margin: 0px;
        }
    }
    .infoConTent {
        margin-top: 10px;
        flex: 1;
        position: relative;
        .infoTable {
            width: calc(100% - 30px);
            height: calc(100% - 36px);
            position: absolute;
            display: flex;
            flex-direction: column;
        }
    }
    ::v-deep.el-divider--horizontal {
        margin: 0px;
        margin-bottom: 10px;
    }
    ::v-deep.el-card__body {
        padding: 15px;
    }
}
</style>
src/views/visual/analysis/index.vue
@@ -1,9 +1,160 @@
<template>
    <div class="atlasBox"></div>
    <div class="atlasBox" v-loading="gLoading">
        <el-form :inline="true" :model="formInline" class="demo-form-inline">
            <el-form-item label="上传数据">
                <el-input :placeholder="placeholder" v-model="formInline.file">
                    <i slot="suffix" @click="onClickInputFile" class="el-input__icon el-icon-upload2"></i>
                </el-input>
            </el-form-item>
            <el-form-item>
                <el-button type="primary" size="small" plain icon="el-icon-setting" @click="onSubmit">分 æž</el-button>
                <el-button type="info" size="small" plain icon="el-icon-refresh" @click="onRefresh">重 ç½®</el-button>
            </el-form-item>
        </el-form>
        <input size="small" id="fromFile" type="file" style="display: none;" accept=".xlsx,.xls"
            @change="onFileInputChange"></input>
        <el-divider />
        <div class="atlasContnt">
            <el-table v-show="showTable" height=" calc(100% - 1px)" style="  width:100%" :data="tableData">
                <el-table-column v-for="(item, index) in tableDataHeader" :key="index" align="center" :prop="item.name
                    " :label="item.name"></el-table-column>
            </el-table>
            <el-carousel v-show="!showTable" style="height: 100%;" :interval="5000" arrow="always">
                <el-carousel-item v-for="(item, key) in carouseList" :key="key">
                    <el-image class="image" :src="item.src" :preview-src-list="[item.src]">
                    </el-image>
                </el-carousel-item>
            </el-carousel>
        </div>
    </div>
</template>
<script>
export default {};
import XLSX from 'xlsx'
import $ from "jquery";
export default {
    data() {
        return {
            formInline: {
                file: ''
            },
            placeholder: "请选择要上传的数据",
            selectFileType: ".xlsx,.xls",
            tableData: [],
            tableDataHeader: [],
            gLoading: false,
            showTable: true,
            carouseList: [],
        }
    },
    methods: {
        onSubmit() {
            var fs = document.getElementById("fromFile");
            if (fs.files.length == 0) {
                this.$store.state.setLoading = false;
                return this.$message("请选择需要上传的数据文件");
            }
            this.gLoading = true;
            var formFile = new FormData();
            var fileObj = fs.files[0]
            formFile.append("file", fileObj); //加入文件对象
            document.getElementById('fromFile').vlaue = "";
            this.formInline.file = ''
            const that = this;
            $.ajax(
                config.pyServices + "/scatterplot",
                {
                    type: 'POST',
                    data: formFile,
                    async: true,
                    cache: false,
                    contentType: false,
                    processData: false,
                    success: (rs) => {
                        that.showTable = false;
                        that.setShowImage(rs);
                        that.gLoading = false
                    },
                    error: (rs) => {
                        that.gLoading = false
                    },
                })
        },
        onRefresh() {
            this.gLoading = false;
            this.showTable = true;
            this.carouseList = [];
            this.tableData = [];
            this.tableDataHeader = [];
            document.getElementById('fromFile').vlaue = "";
            this.formInline.file = ''
        },
        setShowImage(response) {
            const std = [];
            for (var key in response) {
                std.push({
                    src: config.pyServices + '/image?file_name=' + response[key]
                })
            }
            this.carouseList = std
        },
        onClickInputFile() {
            document.getElementById('fromFile').click();
        },
        onFileInputChange(event) {
            var that = this
            // æ‹¿å–文件对象
            let f = event.currentTarget.files[0]
            this.formInline.file = f.name
            // ç”¨FileReader来读取
            let reader = new FileReader()
            // é‡å†™FileReader上的readAsBinaryString方法
            FileReader.prototype.readAsBinaryString = (f) => {
                let binary = ''
                let wb // è¯»å–完成的数据
                let outdata // ä½ éœ€è¦çš„æ•°æ®
                let reader = new FileReader()
                reader.onload = (e) => {
                    // è¯»å–成Uint8Array,再转换为Unicode编码(Unicode占两个字节)
                    let bytes = new Uint8Array(reader.result)
                    let length = bytes.byteLength
                    for (let i = 0; i < length; i++) {
                        binary += String.fromCharCode(bytes[i])
                    }
                    // æŽ¥ä¸‹æ¥å°±æ˜¯xlsx了,具体可看api
                    wb = XLSX.read(binary, {
                        type: 'binary'
                    })
                    outdata = XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]])
                    var str = outdata[0];
                    var std = [];
                    for (var key in str) {
                        std.push({ name: key })
                    }
                    that.tableDataHeader = std
                    that.tableData = outdata
                }
                reader.readAsArrayBuffer(f)
            }
            reader.readAsBinaryString(f)
        }
    }
};
</script>
<style lang="scss" scoped>
@@ -13,6 +164,46 @@
    position: absolute;
    margin: 10px;
    border-radius: 5px;
    background: yellowgreen;
    display: flex;
    flex-direction: column;
    // background: yellowgreen;
    ::v-deep.el-divider--horizontal {
        margin: 0px;
        margin-bottom: 10px;
    }
    ::v-deep.el-form-item {
        margin-bottom: 15px;
        margin-top: 10px;
    }
    .atlasContnt {
        flex: 1;
        .image {
            width: 100%;
            height: 95%;
        }
        ::v-deep.el-carousel__container {
            height: 100%;
        }
        ::v-deep.el-carousel__button {
            background: #409EFF !important
        }
        // background: skyblue;
        // ::v-deep.el-carousel__container {
        //     height: 100%;
        // }
        // ::v-deep.el-carousel__button {
        //     background: #409EFF !important
        // }
    }
}
</style>
src/views/visual/atlas/index.vue
@@ -1,10 +1,335 @@
<template>
    <div class="atlasBox"></div>
    <div class="atlasBox">
        <div id="container" class="container" v-show="!showEcharts">
            <svg class="keywords" @mousemove="listener($event)">
                <a href="javascript:void(0)" v-for="(tag, index) in tags" :key="index"
                    @contextmenu="removeClick($event, tag)" @click="nodeClick(tag)">
                    <text class="text" :x="tag.x" :y="tag.y" :font-size="20 * (600 / (600 - tag.z))"
                        :fill-opacity="(400 + tag.z) / 600" :fill="tag.color">{{ tag.text }}</text>
                </a>
            </svg>
        </div>
        <div class="graphicBox" v-show="showEcharts">
            <div class="konwReturn fl">
                <el-link @click="showEcharts = false">
                    <i class="el-icon-d-arrow-left"></i>
                </el-link>
                å½“前领域:{{ targetName }}
            </div>
            <div id="graphicContent" v-loading="g_loading" class="graphicContent">
                <RelationGraph ref="graphRef" :options="graphOptions" :on-node-expand="onNodeExpand"
                    :on-node-collapse="onNodeCollapse">
                </RelationGraph>
            </div>
        </div>
    </div>
</template>
<script>
import G6 from '@antv/g6';
import { kg_getGraph, kg_queryGraphResult } from '@/api/mapView/map.js';
import RelationGraph from 'relation-graph'
export default {
    components: { RelationGraph },
    data() {
        return {
            width: null,
            height: null,
            tags: [],
            showEcharts: false,
            speedX: Math.PI / 360,
            speedY: Math.PI / 360,
            CX: 600,
            CY: 300,
            RADIUS: 200,
            ZRADIUS: 200,
            targetName: null,
            // å›¾è°±
            g_loading: true,
            demoname: '---',
            graphOptions: {
                layout:
                {
                    label: '中心',
                    layoutName: 'tree',
                    layoutClassName: 'seeks-layout-center',
                    defaultJunctionPoint: 'border',
                    defaultNodeShape: 0,
                    defaultLineShape: 1,
                    from: 'left',
                    max_per_width: 300,
                    min_per_height: 40
                },
                defaultLineMarker: {
                    markerWidth: 12,
                    markerHeight: 12,
                    refX: 6,
                    refY: 6,
                    data: 'M2,2 L10,6 L2,10 L6,6 L2,2'
                },
                moveToCenterWhenRefresh: false,
                defaultExpandHolderPosition: 'right',
                defaultNodeShape: 1,
                defaultNodeWidth: 100,
                defaultLineShape: 4,
                defaultJunctionPoint: 'lr',
                defaultNodeBorderWidth: 0,
                defaultLineColor: 'rgba(0, 186, 189, 1)',
                defaultNodeColor: 'rgba(0, 206, 209, 1)'
            }
        }
    },
    mounted() {
        // ;
        this.setResizeStart();
    },
    methods: {
        nodeClick(tag) {
            this.showEcharts = true;
            this.targetName = tag.text
            this.g_loading = true
            this.getGraphData(tag.text)
        },
        getGraphData(name) {
            this.graphOptions.layout.max_per_width = this.width
            kg_queryGraphResult(
                { domain: name }
            ).then(response => {
                if (response.data.code != 200) return
                this.g_loading = false;
                const data = response.data.data
                if (!this.width) {
                    this.width = document.getElementById('container').innerWidth;
                }
                const obj = data.node.filter(item => {
                    if (item.name == name) {
                        return item
                    }
                })
                this.getGraphicNodes(data.node, data.relationship, obj)
            })
        },
        onNodeCollapse(node, e) {
            // const graphInstance = this.$refs.graphRef.getInstance();
            // graphInstance.doLayout();
        },
        // é€šè¿‡onNodeExpand事件监听节点的展开事件,在被展开的时候有选择的去从后台获取数据,如果已经从后台加载过数据,则让当前图谱根据当前的节点重新布局
        onNodeExpand(node, e) {
            const graphInstance = this.$refs.graphRef.getInstance();
            // æ ¹æ®å…·ä½“的业务需要决定是否需要从后台加载数据
            if (!node.data.isNeedLoadDataFromRemoteServer) {
                console.log('这个节点的子节点已经加载过了');
                graphInstance.doLayout();
                return;
            }
            // åˆ¤æ–­æ˜¯å¦å·²ç»åŠ¨æ€åŠ è½½æ•°æ®äº†
            if (node.data.childrenLoaded) {
                console.log('这个节点的子节点已经加载过了');
                graphInstance.doLayout();
                return;
            }
            // this.g_loading = true;
            node.data.childrenLoaded = true;
            this.loadChildNodesFromRemoteServer(node);
        },
        loadChildNodesFromRemoteServer(node) {
            var graphInstance = this.$refs.graphRef.getInstance();
            graphInstance.doLayout();
        },
        getGraphicNodes(res, lines, obj) {
            const std = [];
            const ids = [];
            lines.filter(item => {
                if (ids.indexOf(item.sourceId) < 0) {
                    ids.push(item.sourceId)
                }
                if (obj && obj.length > 0) {
                    if (item.targetId == obj[0].uuid) {
                        ids.push(item.targetId)
                    }
                }
            })
            res.filter(item => {
                var poi = false;
                if (item.poi && item.poi == 1) {
                    poi = true;
                }
                const expand = ids.indexOf(item.uuid) > -1 ? false : true
                if (!expand) {
                    std.push({
                        // 'uuid': item.id ? item.id : new Date().getTime(),
                        'id': item.uuid,
                        'text': item.name,
                        // expandHolderPosition: 'right',
                        // expanded: true,
                        // data: { isNeedLoadDataFromRemoteServer: true, childrenLoaded: false },
                    })
                } else {
                    std.push({
                        // 'uuid': item.id ? item.id : new Date().getTime(),
                        'id': item.uuid,
                        'text': item.name,
                        // expandHolderPosition: 'right',
                        // expanded: false,
                        // data: { isNeedLoadDataFromRemoteServer: true, childrenLoaded: false },
                    })
                }
            })
            this.getGraphicLines(std, lines)
        },
        getGraphicLines(nodes, res) {
            const std = [];
            res.filter(item => {
                std.push({
                    "from": "" + item.sourceId + "",
                    "to": "" + item.targetId + "",
                    "text": "包含",
                })
            })
            const json_data = {
                'rootId': 'a',
                'nodes': nodes,
                'lines': std
            };
            this.setGraphic(json_data)
        },
        setGraphic(res) {
            setTimeout(() => {
                this.$refs.graphRef.setJsonData(res, (graphInstance) => {
                    // è¿™äº›å†™ä¸Šå½“图谱初始化完成后需要执行的代码
                    graphInstance.doLayout();
                });
            }, 1000);
            setTimeout(() => {
                var graphInstance = this.$refs.graphRef.getInstance();
            }, 2000);
        },
        removeClick() { },
        rotateX(speedX) {
            var cos = Math.cos(speedX);
            var sin = Math.sin(speedX);
            for (let tag of this.tags) {
                var y1 = (tag.y - this.CY) * cos - tag.z * sin + this.CY;
                var z1 = tag.z * cos + (tag.y - this.CY) * sin;
                tag.y = y1;
                tag.z = z1;
            }
        },
        rotateY(speedY) {
            var cos = Math.cos(speedY);
            var sin = Math.sin(speedY);
            for (let tag of this.tags) {
                var x1 = (tag.x - this.CX) * cos - tag.z * sin + this.CX;
                var z1 = tag.z * cos + (tag.x - this.CX) * sin;
                tag.x = x1;
                tag.z = z1;
            }
        },
        resizeWindow() {
            if (this.showEcharts) return;
            let height = document.getElementById('container').clientHeight;
            let width = document.getElementById('container').clientWidth;
            width = width * 0.85;
            if (width > 1200) {
                this.CX = width / 2;
            }
            height = height - 150;
            this.CY = height / 2;
            let radius = Math.min(this.CY, this.CX) / 2;
            if (radius > 200) {
                this.RADIUS = radius;
            }
            this.setCreateGraph();
        },
        setResizeStart() {
            this.resizeWindow();
            window.addEventListener('resize', this.resizeWindow);
            this.setCreateGraph();
            //使球开始旋转
            const interval = setInterval(() => {
                this.rotateX(this.speedX);
                this.rotateY(this.speedY);
            }, 17);
            this.$once('hook:beforedestroy', () => {
                interval && clearInterval(interval);
                window.removeEventListener('resize', this.resizeWindow);
            });
        },
        //图谱初始化
        setCreateGraph() {
            kg_getGraph({
                command: 0,
                pageIndex: 1,
                pageSize: 5000,
            }).then((response) => {
                if (response.data.code != 200) return;
                this.setGraphStart(response.data.data.nodeList);
            });
        },
        listener(event) {
            var x = event.clientX - this.CX;
            var y = event.clientY - this.CY;
            if (event.target.tagName == 'text') {
                this.speedX = 0;
                this.speedY = 0;
            } else {
                this.speedX = x * 0.00001 > 0 ? Math.min(this.RADIUS * 0.00002, x * 0.0001) : Math.max(-this.RADIUS * 0.00002, x * 0.0001);
                this.speedY = y * 0.00001 > 0 ? Math.min(this.RADIUS * 0.00002, y * 0.0001) : Math.max(-this.RADIUS * 0.00002, y * 0.0001);
            }
            // var val = document.getElementById("removeLabel").style.display;
            // if (val == "none") {
            //     document.getElementById("removeLabel").style.top = event.clientY - 20 + 'px';
            //     document.getElementById("removeLabel").style.left = event.clientX + 10 + 'px';
            // }
        },
        setGraphStart(arr) {
            const field = 'label';
            const obj = arr.filter((item, index) => {
                return arr.findIndex((i) => i[field] === item[field]) === index;
            });
            let tags = [];
            const length = obj.length;
            for (let i = 0; i < length; i++) {
                let tag = {};
                let k = -1 + (2 * (i + 1) - 1) / length;
                let a = Math.acos(k);
                let b = a * Math.sqrt(length * Math.PI);
                tag.text = obj[i].label;
                (tag.id = obj[i].id), (tag.label = obj[i].label), (tag.x = this.CX + this.RADIUS * Math.sin(a) * Math.cos(b));
                tag.y = this.CY + this.RADIUS * Math.sin(a) * Math.sin(b);
                tag.z = this.ZRADIUS * Math.cos(a);
                tag.color = 'rgb(' + parseInt(Math.random() * 255) + ',' + parseInt(Math.random() * 255) + ',' + parseInt(Math.random() * 255) + ')';
                tags.push(tag);
            }
            this.tags = [].concat(tags);
        },
    },
};
</script>
@@ -15,6 +340,38 @@
    position: absolute;
    margin: 10px;
    border-radius: 5px;
    background: skyblue;
    // background: skyblue;
    .container {
        width: 100%;
        height: 100%;
    }
    .keywords {
        width: 100%;
        height: 100%;
    }
    .keywords .text:hover {
        font-size: 200%;
    }
    .SVGBox {
        width: 100%;
        height: 100%;
    }
    .graphicBox {
        width: 100%;
        height: 100%;
        display: flex;
        flex-direction: column;
        .graphicContent {
            padding: 10px;
            flex: 1;
        }
    }
}
</style>
src/views/visual/mapLayer/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,460 @@
<template>
    <div class="layerBox">
        <div class="leftTree">
            <el-card class="treeCard">
                <div>
                    <el-input :placeholder="placeholderData" suffix-icon="el-icon-search" v-model="searchData">
                    </el-input>
                </div>
                <div class="treeBox">
                    <el-tree :data="treeData" node-key="id" :default-checked-keys="activeNodeId"
                        :default-expanded-keys="activeNodeId" :filter-node-method="filterNode" highlight-current
                        ref="tree" :props="defaultProps" @node-click="handleNodeClick"></el-tree>
                </div>
            </el-card>
        </div>
        <div class="rightContent">
            <el-card style="height: 100%;">
                <div class="contentMenu">
                    <el-button icon="el-icon-plus" @click="setAddNode(true)">新增同级</el-button>
                    <el-button icon="el-icon-plusde" :disabled="activeNode && activeNode.type != '1'"
                        @click="setAddNode(false)">新增子级</el-button>
                    <el-button icon="el-icon-delete" @click="setDelNode">删除</el-button>
                    <el-button icon="el-icon-top" @click="setMoveUp">向上移动</el-button>
                    <el-button icon="el-icon-bottom" @click="setMoveDown">向下移动</el-button>
                </div>
                <el-divider />
                <el-form ref="formInline" :model="formInline" label-width="80px">
                    <el-form-item label="图层名称 : ">
                        <el-input v-model="formInline.cnName"></el-input>
                    </el-form-item>
                    <el-form-item label="图层类型 : ">
                        <el-select v-model="formInline.type" style="width: 100%;">
                            <el-option v-for="item in layerOption" :key="item.value" :label="item.label"
                                :value="item.value">
                            </el-option>
                        </el-select>
                    </el-form-item>
                    <el-form-item label="服务类型 : " v-show="formInline.type == '2'">
                        <el-select v-model="formInline.serveType" style="width: 100%;">
                            <el-option v-for="item in sourceOption" :key="item.value" :label="item.label"
                                :value="item.value">
                            </el-option>
                        </el-select>
                    </el-form-item>
                    <el-form-item label="服务地址 : " v-show="formInline.type == '2'">
                        <el-input v-model="formInline.url"></el-input>
                    </el-form-item>
                    <el-form-item label="数据类型 : " v-show="formInline.type == '2'">
                        <el-select v-model="formInline.dataType" style="width: 100%;">
                            <el-option v-for="item in dataOption" :key="item.value" :label="item.label"
                                :value="item.value">
                            </el-option>
                        </el-select>
                    </el-form-item>
                    <el-form-item label="是否显示 : " v-show="formInline.type == '2'">
                        <el-radio v-model="formInline.isShow" label="0">否</el-radio>
                        <el-radio v-model="formInline.isShow" label="1">是</el-radio>
                    </el-form-item>
                    <el-form-item label="备注 : ">
                        <el-input v-model="formInline.bak"></el-input>
                    </el-form-item>
                    <el-form-item>
                        <el-button type="primary" @click="onSubEdit">修改</el-button>
                        <el-button @click="onCanelEdit">重置</el-button>
                    </el-form-item>
                </el-form>
            </el-card>
        </div>
        <el-dialog :title="appendTitle" :visible.sync="appendActive" width="30%">
            <el-form ref="appendFrom" :model="appendFrom" label-width="80px">
                <el-form-item label="图层名称 : ">
                    <el-input v-model="appendFrom.cnName"></el-input>
                </el-form-item>
                <el-form-item label="图层类型 : ">
                    <el-select v-model="appendFrom.type" style="width: 100%;">
                        <el-option v-for="item in layerOption" :key="item.value" :label="item.label"
                            :value="item.value">
                        </el-option>
                    </el-select>
                </el-form-item>
                <el-form-item label="服务类型 : " v-show="appendFrom.type == '2'">
                    <el-select v-model="appendFrom.serveType" style="width: 100%;">
                        <el-option v-for="item in sourceOption" :key="item.value" :label="item.label"
                            :value="item.value">
                        </el-option>
                    </el-select>
                </el-form-item>
                <el-form-item label="服务地址 : " v-show="appendFrom.type == '2'">
                    <el-input v-model="appendFrom.url"></el-input>
                </el-form-item>
                <el-form-item label="数据类型 : " v-show="appendFrom.type == '2'">
                    <el-select v-model="appendFrom.dataType" style="width: 100%;">
                        <el-option v-for="item in dataOption" :key="item.value" :label="item.label" :value="item.value">
                        </el-option>
                    </el-select>
                </el-form-item>
                <el-form-item label="是否显示 : " v-show="appendFrom.type == '2'">
                    <el-radio v-model="appendFrom.isShow" label="0">否</el-radio>
                    <el-radio v-model="appendFrom.isShow" label="1">是</el-radio>
                </el-form-item>
                <el-form-item label="备注 : ">
                    <el-input v-model="appendFrom.bak"></el-input>
                </el-form-item>
            </el-form>
            <span slot="footer" class="dialog-footer">
                <el-button @click="handleSubmitClose">取 æ¶ˆ</el-button>
                <el-button type="primary" @click="handleSubmit">ç¡® å®š</el-button>
            </span>
        </el-dialog>
    </div>
</template>
<script>
import mapData from '@/assets/js/mapSdk/mapData.js';
import { layer_selectAll, layer_insert, layer_delete, layer_updates, layer_update } from "@/api/mapView/map.js"
import configTools from '@/assets/js/configTools.js';
export default {
    name: 'mapLayer',
    components: {},
    data() {
        return {
            searchData: '',
            placeholderData: '请输入要查询的图层名称',
            formInline: {},
            layerOption: [],
            sourceOption: [],
            dataOption: [],
            treeData: [],
            defaultProps: {
                children: 'children',
                label: 'cnName'
            },
            activeNode: null,
            activeNodeId: [],
            formData: {},
            appendData: {},
            appendActive: false,
            appendTitle: "",
            appendFlag: null,
            appendFrom: {},
            insertData: {},
            treeList: [],
        };
    },
    created() {
        this.setFormInlineStart();
    },
    watch: {
        searchData(val) {
            this.$refs.tree.filter(val);
        },
    },
    mounted() {
        this.setlayerStart();
    },
    methods: {
        //图层模糊查询
        filterNode(value, data) {
            if (!value) return true;
            return data.cnName.indexOf(value) !== -1;
        },
        // æ•°æ®åˆå§‹åŒ–
        setFormInlineStart() {
            const layerData = mapData.layerData;
            this.layerOption = layerData.layerOption;
            this.sourceOption = layerData.sourceOption;
            this.dataOption = layerData.dataOption;
            this.formData = {
                cnName: '',
                type: this.layerOption[0].value,
                serveType: this.sourceOption[0].value,
                url: '',
                dataType: this.dataOption[0].value,
                isShow: '0',
                bak: ''
            }
            this.formInline = { ... this.formData }
        },
        // å›¾å±‚树获取数据
        setlayerStart() {
            layer_selectAll().then(response => {
                if (response.data && response.data.result && response.data.result.length > 0) {
                    const val = response.data.result;
                    this.treeList = val;
                    this.treeData = configTools.getTreeData(val)
                    this.$nextTick(() => {
                        if (this.insertData && this.insertData.name) {
                            const obj = val.filter(item => {
                                if (item.pid == this.insertData.id && item.cnName == this.insertData.name) {
                                    return item;
                                }
                            })
                            if (obj && obj.length > 0) {
                                this.handleNodeClick(obj[0])
                                this.insertData = {}
                            }
                        } else if (!this.activeNode) {
                            if (this.treeData.length > 0) {
                                this.handleNodeClick(this.treeData[0])
                            }
                        } else if (this.activeNode) {
                            this.handleNodeClick(this.activeNode)
                        }
                    })
                }
            })
        },
        setLayerFormInline(res) {
            res.type = res.type.toString();
            res.isShow = res.isShow.toString();
            res.isProject = res.isProject.toString();
            this.formInline = res
        },
        //修改提交
        onSubEdit() {
            layer_update(this.formInline).then(response => {
                if (response.data.code != 200) {
                    return this.$message({
                        showClose: true,
                        message: '修改失败',
                        type: 'error'
                    });
                }
                this.$message({
                    showClose: true,
                    message: '修改成功',
                    type: 'success'
                });
                this.setlayerStart();
            })
        },
        // å›¾å±‚树点击
        handleNodeClick(res) {
            const lid = res.id;
            this.activeNodeId = [lid];
            this.$refs.tree.setCurrentKey(lid);
            this.activeNode = this.$refs.tree.getNode(lid).data;
            this.onCanelEdit();
        },
        // é‡ç½®
        onCanelEdit() {
            const val = { ... this.activeNode }
            this.setLayerFormInline(val)
        },
        //添加节点
        setAddNode(res) {
            this.appendTitle = res ? '新增同级' : '新增子级'
            this.appendActive = true;
            this.appendFrom = { ... this.formData }
        },
        // å–消添加
        handleSubmitClose() {
            this.appendActive = false;
            this.appendTitle = "";
            this.appendFrom = {};
        },
        setDelNode() {
            layer_delete({ id: this.formInline.id }).then(response => {
                if (response.data.code == 200) {
                    this.activeNode = null;
                    this.activeNodeId = null;
                    this.setlayerStart();
                    this.$message({
                        showClose: true,
                        message: '删除成功',
                        type: 'success'
                    });
                } else {
                    this.$message({
                        showClose: true,
                        message: '删除失败',
                        type: 'error'
                    });
                }
            })
        },
        getMaxOrderNum(res) {
            var val = null;
            for (var i in res) {
                if (val) {
                    val = res[i].data.orderNum
                } else {
                    if (res[i].data.orderNum > val) {
                        val = res[i].data.orderNum;
                    }
                }
            }
            return val + 1;
        },
        //添加提交
        async handleSubmit() {
            const isAddParent = this.appendTitle == "新增同级" ? true : false;
            const val = { ... this.appendFrom };
            val.isShow = parseInt(val.isShow);
            val.isProject = parseInt(val.isProject);
            val.level = isAddParent ? this.activeNode.level : this.activeNode.level + 1;
            val.pid = isAddParent ? this.activeNode.pid : this.activeNode.id;
            const pchildNodes = isAddParent ? this.$refs.tree.getNode(this.activeNode.id).parent.childNodes : this.$refs.tree.getNode(this.activeNode.id).childNodes
            val.orderNum = this.getMaxOrderNum(pchildNodes);
            if (this.treeData.length <= 0) {
                val.pid = 0;
                val.orderNum = 1;
                val.lever = 1;
            }
            this.insertData = {
                name: val.cnName,
                id: val.pid
            }
            const response = await layer_insert(val);
            if (response.data.code == 200) {
                this.$message({
                    showClose: true,
                    message: '添加成功',
                    type: 'success'
                });
                this.handleSubmitClose();
                this.setlayerStart();
            } else {
                this.$message({
                    showClose: true,
                    message: '添加失败',
                    type: 'error'
                });
            }
        },
        // å‘上移动
        setMoveUp() {
            let node = this.$refs.tree.getCurrentNode();
            let pchildNodes = this.$refs.tree.getNode(node.id).parent.childNodes;
            let currentId = null;
            for (let i = 0; i < pchildNodes.length; i++) {
                if (pchildNodes[i].data.id == node.id) {
                    currentId = i;
                }
            }
            if (currentId == 0) {
                return this.$message({
                    message: "处于顶端,不能继续上移",
                    type: "warning",
                });
            }
            const tempChildrenNodex1 = pchildNodes[currentId - 1];
            const tempChildrenNodex2 = pchildNodes[currentId];
            var arr = [];
            this.treeList.filter((res) => {
                if (res.id == tempChildrenNodex2.data.id) {
                    arr.push(res);
                } else if (res.id == tempChildrenNodex1.data.id) {
                    arr.push(res);
                }
            });
            const orderNum = arr[1].orderNum
            arr[1].orderNum = arr[0].orderNum
            arr[0].orderNum = orderNum
            this.sendChange(arr)
        },
        // å‘下移动
        setMoveDown() {
            let node = this.$refs.tree.getCurrentNode();
            let pchildNodes = this.$refs.tree.getNode(node.id).parent.childNodes;
            let currentId = null;
            for (let i = 0; i < pchildNodes.length; i++) {
                if (pchildNodes[i].data.id == node.id) {
                    currentId = i;
                }
            }
            if (currentId > pchildNodes.length - 1) {
                return this.$message({
                    message: "处于底端,不能继续上移",
                    type: "warning",
                });
            }
            const tempChildrenNodex1 = pchildNodes[currentId + 1];
            const tempChildrenNodex2 = pchildNodes[currentId];
            var arr = [];
            this.treeList.filter((res) => {
                if (res.id == tempChildrenNodex2.data.id) {
                    arr.push(res);
                } else if (res.id == tempChildrenNodex1.data.id) {
                    arr.push(res);
                }
            });
            const orderNum = arr[1].orderNum
            arr[1].orderNum = arr[0].orderNum
            arr[0].orderNum = orderNum;
            this.sendChange(arr)
        },
        sendChange(res) {
            layer_updates(res).then(response => {
                if (response.data.code != 200) {
                    return this.$message({
                        showClose: true,
                        message: '移动失败',
                        type: 'error'
                    });
                }
                this.setlayerStart();
            })
        }
    },
};
</script>
<style lang="scss" scoped>
.layerBox {
    width: calc(100% - 20px);
    height: calc(100% - 20px);
    position: absolute;
    margin: 10px;
    border-radius: 5px;
    display: flex;
    .leftTree {
        width: 20%;
        height: 100%;
        margin-right: 10px;
        .treeCard {
            height: 100%;
            ::v-deep.el-card__body {
                height: 100%;
                display: flex;
                flex-direction: column;
            }
            .treeBox {
                margin-top: 10px;
                flex: 1;
                overflow: auto;
            }
        }
        ::v-deep .el-tree--highlight-current .el-tree-node.is-current>.el-tree-node__content {
            color: #409EFF;
        }
    }
    .rightContent {
        flex: 1;
        .contentMenu {
            display: flex;
            justify-content: flex-end;
        }
        ::v-deep .el-divider--horizontal {
            margin: 15px 0px;
        }
    }
}
</style>
</style>
src/views/visual/mapView/attributeInfo.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,171 @@
<template>
    <Popup ref="pop" top="20px" :title="title" @close="close(true)" width="1000px" :maxHeight="'700px'"
        @cancel="close(false)">
        <div class="menuBox">
            <div class="serachContent">
                <el-form :inline="true" :model="formInline" class="demo-form-inline">
                    <el-form-item label="名称">
                        <el-input size="small" v-model="formInline.name" placeholder="请输入定位名称..."></el-input>
                    </el-form-item>
                    <el-form-item>
                        <el-button size="small" plain type="primary" @click="setInfoSearch"
                            icon="el-icon-search">查询</el-button>
                    </el-form-item>
                    <el-form-item>
                        <el-button size="small" plain type="info" @click="setInfoRefresh"
                            icon="el-icon-refresh">重置</el-button>
                    </el-form-item>
                </el-form>
            </div>
            <div class="tableContent">
                <div class="tableBox">
                    <el-table :data="tableData" border height="calc(100% - 2px)" ref="filterTable" style="width: 100%">
                        <el-table-column label="定位" width="100" align="center">
                            <template slot-scope="scope">
                                <el-button icon="el-icon-map-location" size="small"
                                    @click="spaceLocation(scope.$index, scope.row)"></el-button>
                            </template>
                        </el-table-column>
                        <el-table-column label="名称" prop="name" align="center"></el-table-column>
                        <el-table-column label="环线" prop="line" align="center"></el-table-column>
                        <el-table-column label="类型" prop="type" align="center"></el-table-column>
                        <el-table-column label="位置" prop="geom" align="center"></el-table-column>
                    </el-table>
                </div>
                <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageIndex"
                    :limit.sync="queryParams.pageSize" @pagination="getAttributeInfo" />
            </div>
        </div>
    </Popup>
</template>
<script>
import Popup from '@/components/Tool/Popup.vue';
import { zhangzitou_selectAll } from "@/api/mapView/map.js"
import mapConfig from '../../../assets/js/mapSdk/mapConfig';
export default {
    name: 'attributeInfo',
    components: { Popup },
    data() {
        return {
            title: '属性信息',
            total: 0,
            queryParams: {
                pageIndex: 1,
                pageSize: 10,
                name: "",
                srid: 4326,
            },
            billboardEntity: null,
            formInline: {
                name: ''
            }
        };
    },
    methods: {
        // å…³é—­å¼¹çª—
        close(isCloseBtn, removeLayer = true) {
            //   removeLayer && this.removeImageLayer();
            this.delBillboard();
            // é‡ç½®data值
            Object.assign(this.$data, this.$options.data());
            !isCloseBtn && this.$refs.pop.close();
        },
        // æ‰“开弹窗
        open() {
            this.close(true);
            this.$refs.pop.open();
            this.getAttributeInfo();
        },
        setInfoSearch() {
            this.queryParams.name = this.formInline.name;
            this.getAttributeInfo();
        },
        setInfoRefresh() {
            this.formInline.name = "";
            this.queryParams.pageIndex = 1;
            this.queryParams.pageSize = 10;
            this.setInfoSearch();
        },
        getAttributeInfo() {
            zhangzitou_selectAll({
                name: this.queryParams.name,
                page: this.queryParams.pageIndex,
                limit: this.queryParams.pageSize,
                srid: this.queryParams.srid
            }).then(response => {
                if (response.data.code != 200) return;
                const valDta = response.data.result;
                this.total = valDta.total;
                this.tableData = valDta.pois
            })
        },
        delBillboard() {
            if (this.billboardEntity) {
                this.billboardEntity.removeFromMap();
                this.billboardEntity = null;
                return
            }
        },
        spaceLocation(index, row) {
            var wkt = mapConfig.getWKTParse(row.geom);
            this.delBillboard();
            const url = config.sdkImg + 'Workers/image/mark.png';
            this.billboardEntity = earthCtrl.factory.createBillboard({
                name: "标签点",
                image: url,
                width: 16,
                height: 22,
                lon: wkt.coordinates[0],
                lat: wkt.coordinates[1],
                alt: 10,
                scale: 1.5,
            });
            earthCtrl.userScene.flyTo(this.billboardEntity)
        },
    },
};
</script>
<style lang="scss" scoped>
.menuBox {
    position: relative;
    height: 660px;
    width: calc(100% - 0px);
    padding: 10px;
    display: flex;
    flex-direction: column;
    .serachContent {
        display: flex;
    }
    .tableContent {
        flex: 1;
        display: flex;
        flex-direction: column;
        background: #ffffff;
        .tableBox {
            flex: 1;
        }
        .pagination-container {
            padding: 0px 10px !important;
        }
    }
}
</style>
src/views/visual/mapView/dataAnalysis.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,44 @@
<template>
    <Popup ref="pop" top="20px" :title="title" @close="close(true)" width="1400px" :maxHeight="'700px'"
        @cancel="close(false)">
        <div class="menuBox">
          <analysis></analysis>
        </div>
    </Popup>
</template>
<script>
import Popup from '@/components/Tool/Popup.vue';
import analysis from '../analysis/index.vue'
export default {
    name: 'dataAnalysis',
    components: { Popup, analysis },
    data() {
        return {
            title: '数据分析',
        };
    },
    methods: {
        // å…³é—­å¼¹çª—
        close(isCloseBtn, removeLayer = true) {
            //   removeLayer && this.removeImageLayer();
            // é‡ç½®data值
            Object.assign(this.$data, this.$options.data());
            !isCloseBtn && this.$refs.pop.close();
        },
        // æ‰“开弹窗
        open() {
            this.close(true);
            this.$refs.pop.open();
        },
    },
};
</script>
<style lang="scss" scoped>
.menuBox {
    position: relative;
    height: 680px;
    width: 100%;
}
</style>
src/views/visual/mapView/dataStatistics.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,157 @@
<template>
    <Popup ref="pop" top="20px" :title="title" @close="close(true)" width="1000px" :maxHeight="'700px'"
        @cancel="close(false)">
        <div class="menuBox">
            <div class="serachContent">
                <el-select v-model="linesName" @change="setEchartChange" placeholder="请选择">
                    <el-option v-for="(item, key) in linesOption" :key="key" :label="item.line" :value="item.line">
                    </el-option>
                </el-select>
            </div>
            <div class="echartContent">
                <div id="myEchart" class="myChart"> </div>
            </div>
        </div>
    </Popup>
</template>
<script>
import Popup from '@/components/Tool/Popup.vue';
import { zhangzitou_selectInfos } from "@/api/mapView/map.js"
import mapData from '@/assets/js/mapSdk/mapData';
import * as echarts from 'echarts';
export default {
    name: 'dataAnalysis',
    components: { Popup },
    data() {
        return {
            title: '数据统计',
            allLines: [],
            linesOption: [],
            linesName: '',
            myChart: null,
        };
    },
    methods: {
        // å…³é—­å¼¹çª—
        close(isCloseBtn, removeLayer = true) {
            //   removeLayer && this.removeImageLayer();
            // é‡ç½®data值
            Object.assign(this.$data, this.$options.data());
            !isCloseBtn && this.$refs.pop.close();
        },
        // æ‰“开弹窗
        open() {
            this.close(true);
            this.$refs.pop.open();
            this.getAllLines();
        },
        getAllLines() {
            zhangzitou_selectInfos().then(response => {
                if (response.data.code != 200) {
                    return this.close();
                }
                this.setAllLinses(response.data.result)
            })
        },
        setAllLinses(res) {
            this.allLines = res;
            this.linesOption = this.allLines.filter((item, index, self) =>
                index === self.findIndex((t) => t.line === item.line)
            );
            this.linesName = this.linesOption[0].line;
            this.setEchartChange();
        },
        setEchartChange() {
            zhangzitou_selectInfos({
                line: this.linesName
            }).then(response => {
                if (response.data.code != 200) return
                const result = response.data.result;
                const objData = []
                result.filter(item => {
                    const type = mapData.dataStatistics[item.type];
                    if (type) {
                        item.type = type
                    }
                    objData.push({
                        value: item.count, name: item.type
                    })
                })
                this.setEchartShow(objData)
            })
        },
        setEchartShow(res) {
            let option = {
                title: {
                    left: 'center'
                },
                tooltip: {
                    trigger: 'item'
                },
                legend: {
                    orient: 'vertical',
                    left: 'left'
                },
                series: [
                    {
                        name: this.linesName,
                        type: 'pie',
                        radius: '50%',
                        data: res,
                        emphasis: {
                            itemStyle: {
                                shadowBlur: 10,
                                shadowOffsetX: 0,
                                shadowColor: 'rgba(0, 0, 0, 0.5)'
                            }
                        }
                    }
                ]
            };
            if (!this.myChart) {
                this.myChart = echarts.init(document.getElementById("myEchart"));
            }
            this.myChart.setOption(option);
            window.addEventListener("resize", () => {
                this.myChart.resize();
            });
        },
    },
};
</script>
<style lang="scss" scoped>
.menuBox {
    position: relative;
    height: 660px;
    width: calc(100% - 0px);
    padding: 10px;
    display: flex;
    flex-direction: column;
    .serachContent {
        display: flex;
    }
    .echartContent {
        flex: 1;
        .myChart {
            margin-top: 10px;
            width: 100%;
            height: calc(100% - 10px);
        }
    }
}
</style>
src/views/visual/mapView/index.vue
@@ -13,7 +13,8 @@
                            </span>
                            <div v-if="item.children">
                                <el-dropdown-menu v-show="item.children" slot="dropdown">
                                    <el-dropdown-item style="text-align: center" :command="res" v-for="(res, key) in item.children" :key="key">{{ res.name }}</el-dropdown-item>
                                    <el-dropdown-item style="text-align: center" :command="res"
                                        v-for="(res, key) in item.children" :key="key">{{ res.name }}</el-dropdown-item>
                                </el-dropdown-menu>
                            </div>
                        </el-dropdown>
@@ -28,10 +29,22 @@
                    <i :size="20" class="el-icon-d-arrow-left"></i>
                </div>
            </div>
            <!-- å›¾å±‚管理 -->
            <layer-manager ref="layerManager"></layer-manager>
            <!-- åæ ‡å®šä½ -->
            <location ref="location"></location>
            <!-- çŸ¥è¯†å›¾è°± -->
            <knowledge ref="knowledge"></knowledge>
            <!-- çº¿è·¯æ¼«æ¸¸ -->
            <lineRoaming ref="lineRoaming"></lineRoaming>
            <!-- åœ°ä¸‹æ¨¡å¼ -->
            <undergroundMode ref="undergroundMode"></undergroundMode>
            <!-- æ•°æ®åˆ†æž -->
            <dataAnalysis ref="dataAnalysis"></dataAnalysis>
            <!-- æ•°æ®ç»Ÿè®¡ -->
            <dataStatistics ref="dataStatistics"></dataStatistics>
            <!-- å±žæ€§ä¿¡æ¯ -->
            <attributeInfo ref="attributeInfo"></attributeInfo>
        </div>
    </div>
</template>
@@ -44,10 +57,17 @@
import location from './location.vue';
import knowledge from './knowledge.vue';
import lineRoaming from './lineRoaming.vue';
import { layer_selectAll } from "@/api/mapView/map.js";
import configTools from '@/assets/js/configTools';
import store from "@/store";
import mapServer from '@/assets/js/mapSdk/mapServe';
import undergroundMode from './undergroundMode.vue';
import dataAnalysis from './dataAnalysis.vue';
import dataStatistics from './dataStatistics.vue'
import attributeInfo from './attributeInfo.vue';
export default {
    name: 'mapView',
    components: { layerManager, location, knowledge, lineRoaming },
    components: { layerManager, location, knowledge, lineRoaming, undergroundMode, dataAnalysis, dataStatistics, attributeInfo },
    data() {
        return {
            menuIsShow: false,
@@ -58,13 +78,37 @@
    },
    mounted() {
        this.mapViewStart();
    },
    beforeDestroy() {
        this.$store.dispatch('mapLayers/changeLayerTree', [])
        this.$store.dispatch('mapLayers/changeDefaultLayer', [])
    },
    methods: {
        mapViewStart() {
            this.menuOption = mapData.menuData;
            this.$nextTick(() => {
                mapInit.Init();
                this.getSelectLayers();
            });
        },
        getSelectLayers() {
            layer_selectAll().then(response => {
                if (response.data.code != 200) return
                const defaultLayer = [];
                const val = response.data.result.filter(item => {
                    item.checked = false;
                    if (item.type == 2 && item.isShow == 1) {
                        item.checked = true;
                        mapServer.addLayer(item)
                        defaultLayer.push(item.id)
                    }
                    return item;
                })
                this.$store.dispatch('mapLayers/changeDefaultLayer', defaultLayer)
                var obj = configTools.getTreeData(val)
                this.$store.dispatch('mapLayers/changeLayerTree', obj)
            })
        },
        setMenuClose() {
            this.menuIsShow = !this.menuIsShowx;
@@ -86,6 +130,7 @@
            this.$refs && this.$refs.knowledge && this.$refs.knowledge.close();
        },
        setPopShow(response) {
            console.log(response);
            switch (response) {
                case '图层管理':
                    this.$refs && this.$refs.layerManager && this.$refs.layerManager.open();
@@ -98,6 +143,18 @@
                    break;
                case '线路漫游':
                    this.$refs && this.$refs.lineRoaming && this.$refs.lineRoaming.open();
                    break;
                case '地下模式':
                    this.$refs && this.$refs.undergroundMode && this.$refs.undergroundMode.open();
                    break;
                case '数据分析':
                    this.$refs && this.$refs.dataAnalysis && this.$refs.dataAnalysis.open();
                    break;
                case '属性信息':
                    this.$refs && this.$refs.attributeInfo && this.$refs.attributeInfo.open();
                    break;
                case '数据统计':
                    this.$refs && this.$refs.dataStatistics && this.$refs.dataStatistics.open();
                    break;
                default:
                    break;
@@ -151,7 +208,7 @@
        .closeMenu {
            width: 30px;
            height: 100%;
            background: rgba(245, 245, 245, 1);
            background: rgb(255, 255, 255);
            color: #4ab1fc;
            display: flex;
            position: relative;
@@ -161,7 +218,7 @@
        .menuItemBox {
            color: #7a7a7a;
            background: rgba(245, 245, 245, 1);
            background: rgb(255, 255, 255);
            line-height: 40px;
            padding: 0px 10px;
            font-size: 14px;
src/views/visual/mapView/layerManager.vue
@@ -1,23 +1,42 @@
<template>
    <Popup ref="pop" top="20px" left="calc(100% - 600px)"  :title="title" @close="close(true)" width="300px"   @cancel="close(false)">
        <el-tree></el-tree>
    <Popup ref="pop" top="20px" left="calc(100% - 600px)" :title="title" @close="close(true)" width="300px"
        @cancel="close(false)">
        <div class="layerBox">
            <el-tree show-checkbox :data="treeData" ref="tree" node-key="id" :default-checked-keys="defaultLayer"
                @check-change="handleCheckChange" :props="defaultProps"></el-tree>
        </div>
    </Popup>
</template>
<script>
import Popup from '@/components/Tool/Popup.vue';
import store from "@/store";
import mapServer from '@/assets/js/mapSdk/mapServe';
export default {
    name: 'layerManager',
    components: { Popup },
    computed: {
        getlayerTree() {
            return store.getters.getlayerTree
        }
    },
    data() {
        return {
            title: '图层管理',
            defaultProps: {
                children: 'children',
                label: 'cnName'
            },
            treeData: [],
            defaultLayer: [],
            ids: [],
        };
    },
    methods: {
        // å…³é—­å¼¹çª—
        close(isCloseBtn, removeLayer = true) {
            //   removeLayer && this.removeImageLayer();
            // é‡ç½®data值
            Object.assign(this.$data, this.$options.data());
            !isCloseBtn && this.$refs.pop.close();
@@ -26,9 +45,87 @@
        open() {
            this.close(true);
            this.$refs.pop.open();
            this.$nextTick(() => {
                this.setLayerStart();
            })
        },
        setLayerStart() {
            if (store.getters && store.getters.layerTree) {
                this.defaultLayer = store.getters.defaultLayer;
                this.ids = this.defaultLayer;
                this.treeData = store.getters.layerTree
            }
        },
        handleCheckChange(data, checked, indeterminate) {
            const checkIds = this.$refs.tree.getCheckedKeys()
            if (this.ids === checkIds) return
            this.ids.map(o => {
                if (checkIds.indexOf(o) < 0) {
                    const obj = this.$refs.tree.getNode(o);
                    console.log(obj.checked);
                    if (obj.checked) {
                        mapServer.addLayer(obj.data)
                    } else {
                        mapServer.removeLayer(obj.data)
                    }
                }
            })
            checkIds.map(n => {
                if (this.ids.indexOf(n) < 0) {
                    const obj = this.$refs.tree.getNode(n);
                    if (obj.checked) {
                        mapServer.addLayer(obj.data)
                    } else {
                        mapServer.removeLayer(obj.data)
                    }
                }
            })
            this.$store.dispatch('mapLayers/changeLayerTree', this.treeData)
            const ids = this.$refs.tree.getCheckedKeys()
            this.ids = ids;
            this.$store.dispatch('mapLayers/changeDefaultLayer', ids)
        },
        setServerLayerChange(data, checked) {
            if (checked) {
                mapServer.addLayer(data)
            } else {
                mapServer.removeLayer(data)
            }
        },
        getNodeList(list, checked) {
            list.map(item => {
                if (item.type == 1) {
                    if (item.children && item.children.length > 0) {
                        this.getNodeList(item.children)
                    }
                } else {
                    this.setServerLayerChange(item, checked)
                }
            })
        },
    },
};
</script>
<style></style>
<style lang="scss" scoped>
.layerBox {
    height: 680px;
    ::v-deep.el-tree {
        background: transparent !important;
        .el-tree-node__content:hover {
            color: #409EFF;
        }
    }
}
</style>
src/views/visual/mapView/lineRoaming.vue
@@ -1,19 +1,26 @@
<template>
    <Popup ref="pop" top="20px" left="calc(100% - 600px)" :title="title" @close="close(true)" width="300px" :maxHeight="'700px'" @cancel="close(false)">
         <div class="menuBox">
            <el-form ref="form"   label-width="80px">
              <el-form-item label="线路:">
              </el-form-item>
              <el-form-item label="线路:">
              </el-form-item>
              <el-form-item>
                <el-button size="mini" >开始漫游</el-button>
                <el-button size="mini" >结束漫游</el-button>
              </el-form-item>
    <Popup ref="pop" top="20px" left="calc(100% - 600px)" :title="title" @close="close(true)" width="300px"
        :maxHeight="'700px'" @cancel="close(false)">
        <div class="menuBox">
            <el-form ref="form" label-width="80px">
                <el-form-item label="线路:">
                    <el-select v-model="value" @chagne="setLineOptionChagne" placeholder="请选择">
                        <el-option v-for="item in lineOption" :key="item.value" :label="item.name" :value="item.value">
                        </el-option>
                    </el-select>
                </el-form-item>
                <el-form-item label="线路:">
                    <el-select v-model="value1" placeholder="请选择">
                        <el-option v-for="item in lineOption1" :key="item.value" :label="item.name" :value="item.value">
                        </el-option>
                    </el-select>
                </el-form-item>
                <el-form-item>
                    <el-button size="mini" @click="setRoamStart">开始漫游</el-button>
                    <el-button size="mini" @click="setRoamStop">结束漫游</el-button>
                </el-form-item>
            </el-form>
         </div>
        </div>
    </Popup>
</template>
@@ -22,20 +29,26 @@
import {
    zhangzitou_selectAllLine
} from '@/api/mapView/map.js'
import WKT from 'terraformer-wkt-parser';
export default {
    name: 'location',
    components: { Popup },
    data() {
        return {
            title: '线路漫游',
            lineOption: [],
            lineOption1: [],
            lineObj: null,
            value: '',
            value1: '',
            roamLine: null,
        };
    },
    methods: {
        // å…³é—­å¼¹çª—
        close(isCloseBtn, removeLayer = true) {
            //   removeLayer && this.removeImageLayer();
            // é‡ç½®data值
            Object.assign(this.$data, this.$options.data());
            !isCloseBtn && this.$refs.pop.close();
@@ -46,14 +59,77 @@
            this.$refs.pop.open();
            this.romaLineStart();
        },
        romaLineStart(){
            zhangzitou_selectAllLine({
        romaLineStart() {
            zhangzitou_selectAllLine({
                limit: 100000,
                page: 1
            }).then((response)=>{
                console.log(response);
            }).then((response) => {
                if (response.data.code != 200) return
                this.lineOption = [];
                this.lineObj = response.data.result.pois;
                this.lineObj.map(item => {
                    if (this.lineOption.length == 0) {
                        this.lineOption.push({
                            name: item.line,
                            value: item.line
                        })
                    } else {
                        const n = this.lineOption.filter(r => {
                            if (r.name == item.line) {
                                return r
                            }
                        })
                        if (n.length == 0) {
                            this.lineOption.push({
                                name: item.line,
                                value: item.line
                            })
                        }
                    }
                })
                this.value = this.lineOption[0].value
                this.setLineOptionChagne();
            })
        },
        setLineOptionChagne() {
            const a = this.value
            this.lineOption1 = [];
            this.lineObj.map(item => {
                if (item.line == a) {
                    this.lineOption1.push({
                        name: item.name,
                        value: item.geom,
                    })
                }
            })
            this.value1 = this.lineOption1[0].value;
            this.setLineOption1Chagne();
        },
        setLineOption1Chagne() {
            this.roamLine = this.value1;
        },
        setRoamStart() {
            if (!this.roamLine) return;
            const obj = WKT.parse(this.roamLine).coordinates[0]
            var degreesArr = obj.reduce((combined, current) => combined.concat(current), []);
            earthCtrl.factory.getFlyData(degreesArr, data => {
                data.showPoint = false;
                data.showLine = true;
                data.mode = 1;
            })
        },
        setRoamStop(){
        },
    },
};
</script>
src/views/visual/mapView/location.vue
@@ -84,9 +84,7 @@
            this.$refs[formName].validate((valid) => {
                if (valid) {
                    this.setRemoveBillboard();
                    const url = config.sdkImg + 'Workers/image/mark.png';
                    console.log(url);
                    this.billboard = Viewer.entities.add({
                        position: Cesium.Cartesian3.fromDegrees(this.modelFrom.lon, this.modelFrom.lat), // è®¾ç½®å®žä½“在地球上的位置
                        billboard: {
src/views/visual/mapView/undergroundMode.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,116 @@
<template>
    <Popup ref="pop" top="20px" left="calc(100% - 600px)" :maxHeight="'700px'" :title="title" @close="close(true)"
        width="300px" @cancel="close(false)">
        <div style="padding: 10px;">
            <div class="underGroundBox">
                <el-switch class="elSwitch" @change="setUnderGroundCheck" v-model="value1" active-text="地下模式">
                </el-switch>
                <!-- <div class="contentRight">
                    <el-switch class="elSwitch" v-model="value2" active-text="地下网格">
                    </el-switch>
                </div> -->
            </div>
            <div class="underGroundBox">
                <span>
                    é€æ˜Žåº¦ :
                </span>
                <div class="contentRight">
                    <el-slider v-model="value3" @change="setAlphaChange" :format-tooltip="formatTooltip"></el-slider>
                </div>
            </div>
        </div>
    </Popup>
</template>
<script>
import Popup from '@/components/Tool/Popup.vue';
export default {
    name: 'location',
    components: { Popup },
    data() {
        return {
            title: '地下模式',
            value1: true,
            value2: false,
            value3: 50,
        };
    },
    methods: {
        // å…³é—­å¼¹çª—
        close(isCloseBtn, removeLayer = true) {
            //   removeLayer && this.removeImageLayer();
            // é‡ç½®data值
            this.value1 = false;
            this.value3 = 50;
            this.setUnderGroundCheck();
            this.setAlphaChange()
            Object.assign(this.$data, this.$options.data());
            !isCloseBtn && this.$refs.pop.close();
        },
        setUnderGroundCheck() {
            earthCtrl.camera.undergroundMode = this.value1
            earthCtrl.camera.imageryLayerAlpha = this.value3 / 100
        },
        // æ‰“开弹窗
        open() {
            this.close(true);
            this.$refs.pop.open();
            this.setUnderGroundCheck();
        },
        formatTooltip(val) {
            return val + '%'
        },
        setAlphaChange() {
            earthCtrl.camera.imageryLayerAlpha = this.value3 / 100
        }
    },
};
</script>
<style lang="scss" scoped>
.elSwitch {
    ::v-deep.el-switch__core {
        border-radius: 10px !important;
        width: 40px !important;
        height: 20px;
    }
    ::v-deep.el-switch__core:after {
        width: 16px;
        height: 16px;
        border-radius: 100%;
    }
}
.underGroundBox {
    display: flex;
    margin-bottom: 10px;
    align-items: center;
    span {
        font-size: 14px;
    }
    .contentRight {
        flex: 1;
        margin-left: 10px;
    }
}
::v-deep .el-switch.is-checked .el-switch__core:after {
    margin-left: -17px;
}
</style>