上饶市警务平台后台管理前端
shuishen
2023-02-07 2fe7ce75ab7b9c07c64ae3e7af65c3414059b2b5
登录方式更改
9 files modified
4642 ■■■■ changed files
package-lock.json 19 ●●●●● patch | view | raw | blame | history
src/App.vue 37 ●●●● patch | view | raw | blame | history
src/components/map/mapBox.vue 791 ●●●● patch | view | raw | blame | history
src/main.js 134 ●●●● patch | view | raw | blame | history
src/permission.js 272 ●●●● patch | view | raw | blame | history
src/store/modules/user.js 567 ●●●● patch | view | raw | blame | history
src/views/security/security.vue 782 ●●●● patch | view | raw | blame | history
src/views/system/user.vue 1958 ●●●● patch | view | raw | blame | history
vue.config.js 82 ●●●●● patch | view | raw | blame | history
package-lock.json
@@ -2495,6 +2495,16 @@
      "dev": true,
      "optional": true
    },
    "bindings": {
      "version": "1.5.0",
      "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
      "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
      "dev": true,
      "optional": true,
      "requires": {
        "file-uri-to-path": "1.0.0"
      }
    },
    "bluebird": {
      "version": "3.7.2",
      "resolved": "https://registry.npmmirror.com/bluebird/-/bluebird-3.7.2.tgz",
@@ -5572,6 +5582,13 @@
          }
        }
      }
    },
    "file-uri-to-path": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
      "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
      "dev": true,
      "optional": true
    },
    "filesize": {
      "version": "3.6.1",
@@ -13367,6 +13384,7 @@
          "dev": true,
          "optional": true,
          "requires": {
            "bindings": "^1.5.0",
            "nan": "^2.12.1"
          }
        },
@@ -13693,6 +13711,7 @@
          "dev": true,
          "optional": true,
          "requires": {
            "bindings": "^1.5.0",
            "nan": "^2.12.1"
          }
        },
src/App.vue
@@ -1,30 +1,29 @@
<template>
  <div id="app">
    <router-view />
  </div>
    <div id="app">
        <router-view />
    </div>
</template>
<script>
export default {
  name: "app",
  data() {
    return {};
  },
  watch: {},
  created() {
  },
  methods: {},
  computed: {}
};
    name: "app",
    data () {
        return {}
    },
    watch: {},
    created () { },
    methods: {},
    computed: {}
}
</script>
<style lang="scss">
#app {
  width: 100%;
  height: 100%;
  overflow: hidden;
    width: 100%;
    height: 100%;
    overflow: hidden;
}
.avue--detail .el-col{
  margin-bottom: 0;
.avue--detail .el-col {
    margin-bottom: 0;
}
</style>
src/components/map/mapBox.vue
@@ -1,424 +1,429 @@
<template>
  <div>
    <div id='map' :style="{height:isDetail?'90vh':'40vh',width:'100%'}">
      <div style="position: absolute;right:40%;top:-1%;z-index: 999999">
        <p style="margin-top: 10px" v-if="!isDetail">
          <el-button type="primary" size="small" @click="point()">绘制路线</el-button>
          <el-button  size="small" @click="clearDraw()">重置</el-button>
        </p>
      </div>
      <!--画线后的提示-->
      <div class="mapTip" v-if="showTip" :style="{ top: tipPosition.h + 'px', left: tipPosition.w + 'px' }">
        {{ tipTitle }}
      </div>
    <div>
        <div id='map' :style="{ height: isDetail ? '90vh' : '40vh', width: '100%' }" ref="MapContent">
            <div style="position: absolute;right:40%;top:-1%;z-index: 999999">
                <p style="margin-top: 10px" v-if="!isDetail">
                    <el-button type="primary" size="small" @click="point()">绘制路线</el-button>
                    <el-button size="small" @click="clearDraw()">重置</el-button>
                </p>
            </div>
            <!--画线后的提示-->
            <div class="mapTip" v-if="showTip" :style="{ top: tipPosition.h + 'px', left: tipPosition.w + 'px' }">
                {{ tipTitle }}
            </div>
        </div>
    </div>
  </div>
</template>
<script>
import 'ol/ol.css'
import {Map, View, Feature} from 'ol'
import { Map, View, Feature } from 'ol'
import VectorSource from 'ol/source/Vector'
import Cluster from 'ol/source/Cluster'
import {Vector as VectorLayer, Tile as TileLayer} from 'ol/layer'
import LineString from "ol/geom/LineString";
import Point from 'ol/geom/Point';
import Icon from 'ol/style/Icon';
import {Style, Fill as StyleFill, Stroke as StyleStroke, Text as StyleText, Circle as StyleCircle} from 'ol/style'
import {Circle as GeomCircle, Point as GeomPoint, LineString as GeomLineString, Polygon as GeomPolygon} from 'ol/geom'
import { Vector as VectorLayer, Tile as TileLayer } from 'ol/layer'
import LineString from "ol/geom/LineString"
import Point from 'ol/geom/Point'
import Icon from 'ol/style/Icon'
import { Style, Fill as StyleFill, Stroke as StyleStroke, Text as StyleText, Circle as StyleCircle } from 'ol/style'
import { Circle as GeomCircle, Point as GeomPoint, LineString as GeomLineString, Polygon as GeomPolygon } from 'ol/geom'
import Draw from 'ol/interaction/Draw'
import XYZ from "ol/source/XYZ";
import XYZ from "ol/source/XYZ"
import 'ol/ol.css'
export default {
  name: 'mapBox',
  props:['routeRange','isDetail'],
  data() {
    return {
      map: null,
      points: [],
      // 线条点数组
      linePoints: [],
      // 多边形数组
      polygonPoints: [],
      draw: null,
      drawLayer: null,
      lineVector: null,
      pointVector:null,
      coordinates: [],// 保存绘画坐标地址   [[115.90490549080435, 28.746101718722358],[115.93151300423209, 28.741123538790717]]
      toData: null,// 保存数据库格式坐标地址
      showTip:false,
      tipPosition: {//提示的位置
        w: 200,
        h: 10,
      },
      tipTitle:null
    }
  },
  methods: {
    name: 'mapBox',
    props: ['routeRange', 'isDetail'],
    data () {
        return {
            map: null,
            points: [],
            // 线条点数组
            linePoints: [],
            // 多边形数组
            polygonPoints: [],
            draw: null,
            drawLayer: null,
            lineVector: null,
            pointVector: null,
            coordinates: [],// 保存绘画坐标地址   [[115.90490549080435, 28.746101718722358],[115.93151300423209, 28.741123538790717]]
            toData: null,// 保存数据库格式坐标地址
            showTip: false,
            tipPosition: {//提示的位置
                w: 200,
                h: 10,
            },
            tipTitle: null
        }
    },
    methods: {
    createMap() {
      let _this = this
        createMap () {
            let _this = this
      _this.map = new Map({
        target: 'map',
        layers: [
          new TileLayer({
            source: new XYZ({
              url: "https://webmap-tile.sf-express.com/MapTileService/rt?fetchtype=static&x={x}&y={y}&z={z}&project=sfmap&pic_size=256&pic_type=png8&data_name=361100&data_format=merged-dat&data_type=normal", // 行政区划
            _this.map = new Map({
                target: 'map',
                layers: [
                    new TileLayer({
                        source: new XYZ({
                            url: "https://webmap-tile.sf-express.com/MapTileService/rt?fetchtype=static&x={x}&y={y}&z={z}&project=sfmap&pic_size=256&pic_type=png8&data_name=361100&data_format=merged-dat&data_type=normal", // 行政区划
                        })
                    }),
                ],
                view: new View({
                    // 设置中心点,默认南昌,用于规划南昌市的路线
                    center: [115.9032747077233, 28.67433116990186],
                    projection: 'EPSG:4326',
                    // 设置缩放倍数
                    zoom: 13,
                    minZoom: 8,
                    maxZoom: 19
                })
            })
          }),
            _this.lineVector = new VectorLayer({
                //layer所对应的source
                source: new VectorSource({
                    wrapX: false // 禁止横向无限重复(底图渲染的时候会横向无限重复),设置了这个属性,可以让绘制的图形不跟随底图横向无限重复
                }),
            })
            _this.pointVector = new VectorLayer({
                //layer所对应的source
                source: new VectorSource({
                    wrapX: false // 禁止横向无限重复(底图渲染的时候会横向无限重复),设置了这个属性,可以让绘制的图形不跟随底图横向无限重复
                }),
            })
            _this.map.addLayer(_this.lineVector)
            _this.map.addLayer(_this.pointVector)
            //在地图上回显线或点
            _this.startAdd(_this.routeRange)
        },
        // 绘画之后的样式
        styleFunction () {
            // 绘画之后的样式
            let styles = [
                new Style({
                    fill: new StyleFill({ color: "rgba(255, 255, 255, 0.2)" }),
                    stroke: new StyleStroke({
                        color: 'rgb(252, 94, 32)',
                        width: 5
                    })
                })
            ]
            return styles
        },
        // 添加线路
        addLineDraw (toData) {
            // toData = 'LINESTRING(115.90505364627936 28.740342332731327,115.9119724729309 28.74040302419318,115.90766337913915 28.73566909016844)'
            if (toData) {
                // 将数据库点坐标数据转换
                let entityData = ""
                let entityArr = []
                entityData = toData.match(/\(([^)]*)\)/)
                if (entityData && entityData != "") {
                    entityData = entityData[1].split(",")
                    for (let j = 0; j < entityData.length; j++) {
                        entityArr.push([
                            Number(entityData[j].split(" ")[0]),
                            Number(entityData[j].split(" ")[1]),
                        ])
                    }
                }
                // let lineCoords = [[115.90490549080435, 28.746101718722358],[115.93151300423209, 28.741123538790717],[115.90696542732779, 28.73408542233564],[115.90696542732779, 28.73408542233564]]
                let lineCoords = entityArr
                let view = this.map.getView()
                view.setCenter([
                    lineCoords[Math.ceil(lineCoords.length / 2)][0],
                    lineCoords[Math.ceil(lineCoords.length / 2)][1],
                ])
                view.setZoom(14.5)
        ],
        view: new View({
          // 设置中心点,默认南昌,用于规划南昌市的路线
          center: [115.9032747077233, 28.67433116990186],
          projection: 'EPSG:4326',
          // 设置缩放倍数
          zoom: 13,
          minZoom: 8,
          maxZoom: 19
        })
      })
      _this.lineVector = new VectorLayer({
        //layer所对应的source
        source: new VectorSource({
          wrapX: false // 禁止横向无限重复(底图渲染的时候会横向无限重复),设置了这个属性,可以让绘制的图形不跟随底图横向无限重复
        }),
      })
      _this.pointVector = new VectorLayer({
        //layer所对应的source
        source: new VectorSource({
          wrapX: false // 禁止横向无限重复(底图渲染的时候会横向无限重复),设置了这个属性,可以让绘制的图形不跟随底图横向无限重复
        }),
      })
      _this.map.addLayer(_this.lineVector)
      _this.map.addLayer(_this.pointVector)
      //在地图上回显线或点
      _this.startAdd(_this.routeRange)
    },
    // 绘画之后的样式
    styleFunction() {
      // 绘画之后的样式
      let styles = [
        new Style({
          fill: new StyleFill({color: "rgba(255, 255, 255, 0.2)"}),
          stroke: new StyleStroke({
            color: 'rgb(252, 94, 32)',
            width: 5
          })
        })
      ]
      return styles
    },
    // 添加线路
    addLineDraw(toData) {
      // toData = 'LINESTRING(115.90505364627936 28.740342332731327,115.9119724729309 28.74040302419318,115.90766337913915 28.73566909016844)'
      if (toData) {
        // 将数据库点坐标数据转换
        let entityData = "";
        let entityArr = [];
        entityData = toData.match(/\(([^)]*)\)/);
        if (entityData && entityData != "") {
          entityData = entityData[1].split(",");
          for (let j = 0; j < entityData.length; j++) {
            entityArr.push([
              Number(entityData[j].split(" ")[0]),
              Number(entityData[j].split(" ")[1]),
            ]);
          }
        }
        // let lineCoords = [[115.90490549080435, 28.746101718722358],[115.93151300423209, 28.741123538790717],[115.90696542732779, 28.73408542233564],[115.90696542732779, 28.73408542233564]]
        let lineCoords = entityArr
        let view = this.map.getView();
        view.setCenter([
          lineCoords[Math.ceil(lineCoords.length / 2)][0],
          lineCoords[Math.ceil(lineCoords.length / 2)][1],
        ]);
        view.setZoom(14.5);
        let feature_LineString = new Feature({
          geometry: new LineString(lineCoords),
        });
        feature_LineString.setStyle(this.styleFunction());// 设置样式
        this.lineVector.getSource().addFeature(feature_LineString);
      }
    },
    // 添加点
    addPoint(pointLonLat){
      // pointLonLat = POINT(115.87531914674 28.8603307485585)
      if (pointLonLat){
        let pointData = ""
        let pointArray = []
        pointData = pointLonLat.match(/\(([^)]*)\)/);
        pointArray = pointData[1].split(" ")
        //设置点
        let feature_Point = new Feature({
          geometry: new Point([Number(pointArray[0]), Number(pointArray[1])])
        })
        //点样式
        let style = new Style({
          image: new Icon({
            src: "/img/dwicon.jpeg",
            anchor: [0.48, 0.52],
            // imgSize: [250,320],
            scale: 0.2
          }),
        });
        feature_Point.setStyle(style);
        this.pointVector.getSource().addFeature(feature_Point);
        let center = [Number(pointArray[0]), Number(pointArray[1])];
        let view = this.map.getView();
        view.setZoom(16);
        view.animate({
          center: center,
          duration: 5,
        });
      }
    },
    // 将点坐标集合转换为数据库数据
    doData(val) {
      let str = "LINESTRING(";
      for (let k = 0; k < val.length; k++) {
        str += `${val[k][0]} ${val[k][1]}`;
        if (k != val.length - 1) {
          str += ",";
        }
      }
      str += ")";
      // console.log(str)
      return '\''+str+'\'';
    },
    // 开始绘制
    point() {
      let _this = this
      _this.coordinates = []
      _this.map.removeInteraction(_this.draw)
      _this.lineVector.getSource().clear()
      //提示
      if(!_this.showTip){
        _this.showTip = true
      }
      _this.tipTitle = "单击左键或者右键开始绘画"
      //提示器
      $("#map").off("mousemove").mousemove(function (e) {
        _this.setTipPosition(e.offsetX, e.offsetY, 5, 5);
      })
      $("#map").off("mousedown").mousedown(function () {
        _this.tipTitle = "可继续,或选择最终位置双击结束绘画"
      })
      _this.draw = new Draw({
        source: _this.lineVector.getSource(),
        type: 'LineString',
        style: new Style({
          stroke: new StyleStroke({
            color: "red",
            width: 3,
          })
        }),
      })
      _this.map.addInteraction(_this.draw)
      // 点击事件
      _this.map.on('click', function (e) {
        // 将点坐标保存集合
        _this.coordinates.push(e.coordinate)
      })
      // 结束事件
      _this.draw.on('drawend', function () {
        _this.map.removeInteraction(_this.draw);
        _this.lineVector.setStyle(_this.styleFunction())// 路线画好之后的样式
                let feature_LineString = new Feature({
                    geometry: new LineString(lineCoords),
                })
                feature_LineString.setStyle(this.styleFunction())// 设置样式
                this.lineVector.getSource().addFeature(feature_LineString)
            }
        },
        // 添加点
        addPoint (pointLonLat) {
            // pointLonLat = POINT(115.87531914674 28.8603307485585)
            if (pointLonLat) {
                let pointData = ""
                let pointArray = []
                pointData = pointLonLat.match(/\(([^)]*)\)/)
                pointArray = pointData[1].split(" ")
                //设置点
                let feature_Point = new Feature({
                    geometry: new Point([Number(pointArray[0]), Number(pointArray[1])])
                })
                //点样式
                let style = new Style({
                    image: new Icon({
                        src: "/img/dwicon.jpeg",
                        anchor: [0.48, 0.52],
                        // imgSize: [250,320],
                        scale: 0.2
                    }),
                })
                feature_Point.setStyle(style)
                this.pointVector.getSource().addFeature(feature_Point)
                let center = [Number(pointArray[0]), Number(pointArray[1])]
                let view = this.map.getView()
                view.setZoom(16)
                view.animate({
                    center: center,
                    duration: 5,
                })
            }
        },
        // 将点坐标集合转换为数据库数据
        let toData = _this.doData(_this.coordinates)
        // 传值给父组件
        _this.$emit('toData',toData)
        //隐藏提示
        _this.tipTitle = null;
        _this.showTip = false
      })
    },
    // 设置统一控制点击事件,需要画图方式在此处切换
    handleClick(point) {
      // 绘制连线
      this.drawLineString(point)
      // 绘制点
      // this.drawPoint(point)
      // 绘制圆形
      // this.drawCircle(point)
      // 绘制多边形
      // this.drawPolygon(point)
    },
    // 绘制点位
    drawPoint(center) {
      let vectorLayer = this.getLayer()
        doData (val) {
            let str = "LINESTRING("
            for (let k = 0; k < val.length; k++) {
                str += `${val[k][0]} ${val[k][1]}`
                if (k != val.length - 1) {
                    str += ","
                }
            }
            str += ")"
            // console.log(str)
            return '\'' + str + '\''
        },
        // 开始绘制
        point () {
            let _this = this
            _this.coordinates = []
            _this.map.removeInteraction(_this.draw)
            _this.lineVector.getSource().clear()
            //提示
            if (!_this.showTip) {
                _this.showTip = true
            }
            _this.tipTitle = "单击左键或者右键开始绘画"
            //提示器
            function mapMousemove (e) {
                _this.setTipPosition(e.offsetX, e.offsetY, 5, 5)
            }
            this.$refs.MapContent.addEventListener('mousemove', mapMousemove)
            this.$refs.MapContent.removeEventListener('mousemove', mapMousemove)
      let point = new GeomPoint(center)
      let feature = new Feature(point)
      vectorLayer.getSource().addFeature(feature)
      this.map.addLayer(vectorLayer)
    },
    // 绘制连线
    drawLineString(point) {
      this.linePoints.push(point)
      let featureLine = new Feature({
        geometry: new GeomLineString(this.linePoints),
      });
            function mapMousedown () {
                _this.tipTitle = "可继续,或选择最终位置双击结束绘画"
            }
            this.$refs.MapContent.addEventListener('mousedown', mapMousedown)
            this.$refs.MapContent.removeEventListener('mousedown', mapMousedown)
      // 添加线的样式
      let lineStyle = new Style({
        fill: new StyleFill({
          color: 'rgba(1, 210, 241, 0.1)'
        }),
        stroke: new StyleStroke({
          color: 'rgba(255, 0, 0)',
          width: 4,
        }),
      });
      featureLine.setStyle(lineStyle);
      let source = new VectorSource()
      source.addFeature(featureLine)
      let layer = new VectorLayer()
      layer.setSource(source)
      this.map.addLayer(layer)
    },
    // 绘制区域圆形
    drawCircle(center) {
      let vectorLayer = this.getLayer()
      // 设置半径
      let circle = new GeomCircle(center, 0.003)// 新建圆对象
      let feature = new Feature(circle)// 新建Feature对象 并将circle传入
      vectorLayer.getSource().addFeature(feature)// 将Feature对象填入图层源
      this.map.addLayer(vectorLayer) // 将图层添至地图对象
    },
    // 画多边形
    drawPolygon(point) {
      this.polygonPoints.push(point)
      let feature = new Feature({
        geometry: new GeomPolygon([this.polygonPoints]),
        attributes: null
      });
      // 添加线的样式
      let lineStyle = new Style({
        fill: new StyleFill({
          color: 'rgba(1, 210, 241, 0.1)'
        }),
        stroke: new StyleStroke({
          color: 'rgba(255, 0, 0)',
          width: 4,
        }),
      });
      feature.setStyle(lineStyle);
      let source = new VectorSource();
      source.addFeature(feature)
      let vectorLayer = new VectorLayer({
        source: source
      })
      this.map.addLayer(vectorLayer)
    },
    // 设置聚合点
    addMarker() {
      let source = new VectorSource();
      // 随机创建200个要素,后台点位取出后按此格式处理
      for (let i = 1; i <= 200; i++) {
        let coordinates = [115.90 + Math.random() * 0.05, 28.64 + Math.random() * 0.05];
        let feature = new Feature(new GeomPoint(coordinates));
        source.addFeature(feature);
      }
      // 聚合
      let clusterSource = new Cluster({
        source: source,
        distance: 50
      })
      let clusters = new VectorLayer({
        source: clusterSource,
        style: function (feature) {
          let size = feature.get('features').length;
          let style = new Style({
            image: new StyleCircle({
              radius: 20,
              stroke: new StyleStroke({
                color: 'white'
              }),
              fill: new StyleFill({
                color: '#AAD3DF'
              })
            }),
            text: new StyleText({
              text: size.toString(),
              fill: new StyleFill({
                color: 'black'
              })
            _this.draw = new Draw({
                source: _this.lineVector.getSource(),
                type: 'LineString',
                style: new Style({
                    stroke: new StyleStroke({
                        color: "red",
                        width: 3,
                    })
                }),
            })
          })
          return style;
        }
      });
            _this.map.addInteraction(_this.draw)
            // 点击事件
            _this.map.on('click', function (e) {
                // 将点坐标保存集合
                _this.coordinates.push(e.coordinate)
            })
            // 结束事件
            _this.draw.on('drawend', function () {
      this.map.addLayer(clusters)
                _this.map.removeInteraction(_this.draw)
                _this.lineVector.setStyle(_this.styleFunction())// 路线画好之后的样式
                // 将点坐标集合转换为数据库数据
                let toData = _this.doData(_this.coordinates)
                // 传值给父组件
                _this.$emit('toData', toData)
                //隐藏提示
                _this.tipTitle = null
                _this.showTip = false
            })
        },
        // 设置统一控制点击事件,需要画图方式在此处切换
        handleClick (point) {
            // 绘制连线
            this.drawLineString(point)
            // 绘制点
            // this.drawPoint(point)
            // 绘制圆形
            // this.drawCircle(point)
            // 绘制多边形
            // this.drawPolygon(point)
        },
        // 绘制点位
        drawPoint (center) {
            let vectorLayer = this.getLayer()
            let point = new GeomPoint(center)
            let feature = new Feature(point)
            vectorLayer.getSource().addFeature(feature)
            this.map.addLayer(vectorLayer)
        },
        // 绘制连线
        drawLineString (point) {
            this.linePoints.push(point)
            let featureLine = new Feature({
                geometry: new GeomLineString(this.linePoints),
            })
            // 添加线的样式
            let lineStyle = new Style({
                fill: new StyleFill({
                    color: 'rgba(1, 210, 241, 0.1)'
                }),
                stroke: new StyleStroke({
                    color: 'rgba(255, 0, 0)',
                    width: 4,
                }),
            })
            featureLine.setStyle(lineStyle)
            let source = new VectorSource()
            source.addFeature(featureLine)
            let layer = new VectorLayer()
            layer.setSource(source)
            this.map.addLayer(layer)
        },
        // 绘制区域圆形
        drawCircle (center) {
            let vectorLayer = this.getLayer()
            // 设置半径
            let circle = new GeomCircle(center, 0.003)// 新建圆对象
            let feature = new Feature(circle)// 新建Feature对象 并将circle传入
            vectorLayer.getSource().addFeature(feature)// 将Feature对象填入图层源
            this.map.addLayer(vectorLayer) // 将图层添至地图对象
        },
        // 画多边形
        drawPolygon (point) {
            this.polygonPoints.push(point)
            let feature = new Feature({
                geometry: new GeomPolygon([this.polygonPoints]),
                attributes: null
            })
            // 添加线的样式
            let lineStyle = new Style({
                fill: new StyleFill({
                    color: 'rgba(1, 210, 241, 0.1)'
                }),
                stroke: new StyleStroke({
                    color: 'rgba(255, 0, 0)',
                    width: 4,
                }),
            })
            feature.setStyle(lineStyle)
            let source = new VectorSource()
            source.addFeature(feature)
            let vectorLayer = new VectorLayer({
                source: source
            })
            this.map.addLayer(vectorLayer)
        },
        // 设置聚合点
        addMarker () {
            let source = new VectorSource()
            // 随机创建200个要素,后台点位取出后按此格式处理
            for (let i = 1; i <= 200; i++) {
                let coordinates = [115.90 + Math.random() * 0.05, 28.64 + Math.random() * 0.05]
                let feature = new Feature(new GeomPoint(coordinates))
                source.addFeature(feature)
            }
            // 聚合
            let clusterSource = new Cluster({
                source: source,
                distance: 50
            })
            let clusters = new VectorLayer({
                source: clusterSource,
                style: function (feature) {
                    let size = feature.get('features').length
                    let style = new Style({
                        image: new StyleCircle({
                            radius: 20,
                            stroke: new StyleStroke({
                                color: 'white'
                            }),
                            fill: new StyleFill({
                                color: '#AAD3DF'
                            })
                        }),
                        text: new StyleText({
                            text: size.toString(),
                            fill: new StyleFill({
                                color: 'black'
                            })
                        })
                    })
                    return style
                }
            })
            this.map.addLayer(clusters)
        },
        // 重置图层
        clearDraw () {
            let _this = this
            _this.coordinates = []
            _this.map.removeInteraction(_this.draw)
            _this.lineVector.getSource().clear()
            _this.showTip = false
            _this.tipTitle = null
        },
        // 获取新的 layer 图层对象
        getLayer () {
            return new VectorLayer({
                source: new VectorSource({
                    features: ''
                }),
                // 设置样式,但不完全兼容
                // style: function (feature) {
                //   let style = new Style({
                //     stroke: new StyleStroke({
                //       color: '#E80000',
                //       width: 2
                //     }),
                //     fill: new StyleFill({
                //       color: 'rgba(0,0,0,0)'
                //     })
                //   })
                //   return style
                // }
            })
        },
        // 设置提示位置
        setTipPosition (x, y, n, m) {
            let _this = this
            _this.tipPosition.w = x + n
            _this.tipPosition.h = y + m
        },
        startAdd (routeRange) {
            if (routeRange.startsWith("LINESTRING")) {
                this.addLineDraw(routeRange)
            } else {
                this.addPoint(routeRange)
            }
        }
    },
    // 重置图层
    clearDraw(){
      let _this = this
      _this.coordinates = []
      _this.map.removeInteraction(_this.draw)
      _this.lineVector.getSource().clear()
      _this.showTip = false
      _this.tipTitle = null
    },
    // 获取新的 layer 图层对象
    getLayer() {
      return new VectorLayer({
        source: new VectorSource({
          features: ''
        }),
        // 设置样式,但不完全兼容
        // style: function (feature) {
        //   let style = new Style({
        //     stroke: new StyleStroke({
        //       color: '#E80000',
        //       width: 2
        //     }),
        //     fill: new StyleFill({
        //       color: 'rgba(0,0,0,0)'
        //     })
        //   })
        //   return style
        // }
      })
    },
    // 设置提示位置
    setTipPosition(x, y, n, m) {
      let _this = this
      _this.tipPosition.w = x + n;
      _this.tipPosition.h = y + m;
    },
    startAdd(routeRange){
      if (routeRange.startsWith("LINESTRING")){
        this.addLineDraw(routeRange)
      }else {
        this.addPoint(routeRange)
      }
    mounted () {
        this.createMap()
    }
  },
  mounted() {
    this.createMap()
  }
}
</script>
<style>
.mapTip {
  background-color: rgb(168, 168, 168);
  padding: 5px;
  border: 1px solid #000;
  position: absolute;
  z-index: 10 !important;
  border-radius: 5px;
    background-color: rgb(168, 168, 168);
    padding: 5px;
    border: 1px solid #000;
    position: absolute;
    z-index: 10 !important;
    border-radius: 5px;
}
</style>
src/main.js
@@ -1,90 +1,80 @@
import Vue from 'vue';
import axios from './router/axios';
import VueAxios from 'vue-axios';
import App from './App';
import router from './router/router';
import './permission'; // 权限
import './error'; // 日志
import './cache';//页面缓存
import store from './store';
/*
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2023-02-06 10:34:02
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2023-02-07 10:39:07
 * @FilePath: \srs-police-web\src\main.js
 * @Description:
 *
 * Copyright (c) 2023 by ${git_name_email}, All Rights Reserved.
 */
import Vue from 'vue'
import axios from './router/axios'
import VueAxios from 'vue-axios'
import App from './App'
import router from './router/router'
import './permission' // 权限
import './error' // 日志
import './cache'//页面缓存
import store from './store'
import { loadStyle } from './util/util'
import * as urls from '@/config/env';
import Element from 'element-ui';
import * as urls from '@/config/env'
import Element from 'element-ui'
import {
  iconfontUrl,
  iconfontVersion
} from '@/config/env';
import i18n from './lang'; // Internationalization
import './styles/common.scss';
import basicBlock from './components/basic-block/main';
import basicContainer from './components/basic-container/main';
import thirdRegister from './components/third-register/main';
import flowDesign from './components/flow-design/main';
import avueUeditor from 'avue-plugin-ueditor';
import website from '@/config/website';
import crudCommon from '@/mixins/crud';
    iconfontUrl,
    iconfontVersion
} from '@/config/env'
import i18n from './lang' // Internationalization
import './styles/common.scss'
import basicBlock from './components/basic-block/main'
import basicContainer from './components/basic-container/main'
import thirdRegister from './components/third-register/main'
import flowDesign from './components/flow-design/main'
import avueUeditor from 'avue-plugin-ueditor'
import website from '@/config/website'
import crudCommon from '@/mixins/crud'
// 业务组件
import tenantPackage from './views/system/tenantpackage';
import tenantPackage from './views/system/tenantpackage'
// 注册全局crud驱动
window.$crudCommon = crudCommon;
window.$crudCommon = crudCommon
// 加载Vue拓展
Vue.use(router);
Vue.use(VueAxios, axios);
Vue.use(router)
Vue.use(VueAxios, axios)
Vue.use(Element, {
  i18n: (key, value) => i18n.t(key, value)
});
    i18n: (key, value) => i18n.t(key, value)
})
Vue.use(window.AVUE, {
  size: 'small',
  tableSize: 'small',
  calcHeight: 65,
  i18n: (key, value) => i18n.t(key, value)
});
    size: 'small',
    tableSize: 'small',
    calcHeight: 65,
    i18n: (key, value) => i18n.t(key, value)
})
// 注册全局容器
Vue.component('basicContainer', basicContainer);
Vue.component('basicBlock', basicBlock);
Vue.component('thirdRegister', thirdRegister);
Vue.component('avueUeditor', avueUeditor);
Vue.component('flowDesign', flowDesign);
Vue.component('tenantPackage', tenantPackage);
Vue.component('basicContainer', basicContainer)
Vue.component('basicBlock', basicBlock)
Vue.component('thirdRegister', thirdRegister)
Vue.component('avueUeditor', avueUeditor)
Vue.component('flowDesign', flowDesign)
Vue.component('tenantPackage', tenantPackage)
// 加载相关url地址
Object.keys(urls).forEach(key => {
  Vue.prototype[key] = urls[key];
});
    Vue.prototype[key] = urls[key]
})
// 加载NutFlow
Vue.use(window.WfDesignBase);
Vue.use(window.WfDesignBase)
// 加载website
Vue.prototype.website = website;
Vue.prototype.website = website
// 动态加载阿里云字体库
iconfontVersion.forEach(ele => {
  loadStyle(iconfontUrl.replace('$key', ele));
});
    loadStyle(iconfontUrl.replace('$key', ele))
})
Vue.config.productionTip = false;
//import Cookies from 'js-cookie'
// 携带token跳转页面设置
//const tokenLength = window.location.href.indexOf('=');
//if(tokenLength>0){
//  //取“=”之后的token
 // let z = window.location.href.substring(tokenLength + 1)
 // // 把token存进B系统
 // let obj = {
 //   dataType: typeof (z),
 //   content: z,
 //   datetime: new Date().getTime()
 // }
 // window.localStorage.setItem('saber-token', JSON.stringify(obj));
 // Cookies.set('saber-access-token', z)
//}
Vue.config.productionTip = false
new Vue({
  router,
  store,
  i18n,
  render: h => h(App)
}).$mount('#app');
    router,
    store,
    i18n,
    render: h => h(App)
}).$mount('#app')
src/permission.js
@@ -2,9 +2,9 @@
 * 全站权限配置
 *
 */
import md5 from 'js-md5'
import request from '@/router/axios';
import { Message } from 'element-ui'
// import md5 from 'js-md5'
// import request from '@/router/axios'
// import { Message } from 'element-ui'
import router from './router/router'
import store from './store'
@@ -12,144 +12,144 @@
import { getToken } from '@/util/auth'
import NProgress from 'nprogress' // progress bar
import 'nprogress/nprogress.css' // progress bar style
NProgress.configure({ showSpinner: false });
const lockPage = store.getters.website.lockPage; //锁屏页
NProgress.configure({ showSpinner: false })
const lockPage = store.getters.website.lockPage //锁屏页
router.beforeEach((to, from, next) => {
  var tag = false;
  // if (to.fullPath.indexOf("token") > 0) {
  //   tag = true;
  // }
  const meta = to.meta || {};
  const isMenu = meta.menu === undefined ? to.query.menu : meta.menu;
  store.commit('SET_IS_MENU', isMenu === undefined);
  if (getToken()) {
    if (store.getters.isLock && to.path !== lockPage) { //如果系统激活锁屏,全部跳转到锁屏页
      next({ path: lockPage })
    } else if (to.path === '/login') { //如果登录成功访问登录页跳转到主页
      next({ path: '/' })
    } else {
      //如果用户信息为空则获取用户信息,获取用户信息失败,跳转到登录页
      // if (store.getters.token.length === 0 && tag==false) {
        if (store.getters.token.length === 0) {
        store.dispatch('FedLogOut').then(() => {
          next({ path: '/login' })
        })
      } else {
        const value = to.query.src || to.fullPath;
        const label = to.query.name || to.name;
        const meta = to.meta || router.$avueRouter.meta || {};
        const i18n = to.query.i18n;
        if (to.query.target) {
          window.open(value)
        } else if (meta.isTab !== false && !validatenull(value) && !validatenull(label)) {
       // } else if (meta.isTab !== false && !validatenull(value) && !validatenull(label) && tag==false) {
          store.commit('ADD_TAG', {
            label: label,
            value: value,
            params: to.params,
            query: to.query,
            meta: (() => {
              if (!i18n) {
                return meta
              }
              return {
                i18n: i18n
              }
            })(),
            group: router.$avueRouter.group || []
          });
        }
        next()
      }
    let hrefIdx = window.location.href.indexOf('token=') // url中是否携带token
    var tag = false
    if (to.fullPath.indexOf("token") > 0) {
        tag = true
    }
  } else {
    //判断是否需要认证,没有登录访问去登录页
    if (meta.isAuth === false) {
      next()
    } else {
      console.log(to.path,66666)
      if (to.path == '/security/security') {
        // console.log('进入首页-----')
        var a = to.query.securitySupervisionSystem;
        if (a == undefined || typeof a != "string") {
          // console.log("无securitySupervisionSystem参数  跳回登入");
          next('/login');
          next('/login');
          return;
        }
        // console.log("有securitySupervisionSystem参数");
        try {
          // console.log("判断securitySupervisionSystem是否能被JSOn解码");
          var obj = JSON.parse(a);
          if (typeof obj == "object" && obj && obj.tokenMY == '987654321S') {
            debugger
            var data = {
              tenantId: obj.data.dip,
              username: obj.data.rese,
              password: md5(obj.data.sap),
              grant_type: 'password',
              scope: 'all',
              type: 'account'
            };
            request({
              url: '/api/blade-auth/oauth/token',
              method: 'post',
              headers: {
                'Authorization': 'Basic c2FiZXI6c2FiZXJfc2VjcmV0',
                "Tenant-Id": "000000"
              },
              params: data
            }).then(res => {
              const data = res.data;
              if (data.error_description) {
                // console.log("登入失败");
                Message({
                  message: data.error_description,
                  type: 'error'
    const meta = to.meta || {}
    const isMenu = meta.menu === undefined ? to.query.menu : meta.menu
    store.commit('SET_IS_MENU', isMenu === undefined)
    if (hrefIdx > -1 || getToken()) {
        if (store.getters.isLock && to.path !== lockPage) { //如果系统激活锁屏,全部跳转到锁屏页
            next({ path: lockPage })
        } else if (to.path === '/login') { //如果登录成功访问登录页跳转到主页
            next({ path: '/' })
        } else {
            //如果用户信息为空则获取用户信息,获取用户信息失败,跳转到登录页
            if (store.getters.token.length === 0 && tag == false) {
                // if (store.getters.token.length === 0) {
                store.dispatch('FedLogOut').then(() => {
                    next({ path: '/login' })
                })
                next('/login');
                next('/login');
                return;
              } else {
                // console.log("登入成功");
                store.commit('SET_TOKEN', data.access_token);
                store.commit('SET_REFRESH_TOKEN', data.refresh_token);
                store.commit('SET_TENANT_ID', data.tenant_id);
                store.commit('SET_USER_INFO', data);
                store.commit('DEL_ALL_TAG');
                store.commit('CLEAR_LOCK');
                next(to.path);
                return;
              }
            })
            return;
          } else {
            // console.log("成功解码 不是对象");
            next('/login');
            next('/login');
            return;
          }
        } catch {
          // console.log('不是Json对象 跳回登入');
          next('/login');
          next('/login');
          return;
            } else {
                const value = to.query.src || to.fullPath
                const label = to.query.name || to.name
                const meta = to.meta || router.$avueRouter.meta || {}
                const i18n = to.query.i18n
                if (to.query.target) {
                    window.open(value)
                    // } else if (meta.isTab !== false && !validatenull(value) && !validatenull(label)) {
                } else if (meta.isTab !== false && !validatenull(value) && !validatenull(label) && tag == false) {
                    store.commit('ADD_TAG', {
                        label: label,
                        value: value,
                        params: to.params,
                        query: to.query,
                        meta: (() => {
                            if (!i18n) {
                                return meta
                            }
                            return {
                                i18n: i18n
                            }
                        })(),
                        group: router.$avueRouter.group || []
                    })
                }
                next()
            }
        }
      }
      next('/login')
    } else {
        //判断是否需要认证,没有登录访问去登录页
        if (meta.isAuth === false) {
            next()
        } else {
            // console.log(to.path, 66666)
            // if (to.path == '/security/security') {
            //     // console.log('进入首页-----')
            //     var a = to.query.securitySupervisionSystem
            //     if (a == undefined || typeof a != "string") {
            //         // console.log("无securitySupervisionSystem参数  跳回登入");
            //         next('/login')
            //         next('/login')
            //         return
            //     }
            //     // console.log("有securitySupervisionSystem参数");
            //     try {
            //         // console.log("判断securitySupervisionSystem是否能被JSOn解码");
            //         var obj = JSON.parse(a)
            //         if (typeof obj == "object" && obj && obj.tokenMY == '987654321S') {
            //             debugger
            //             var data = {
            //                 tenantId: obj.data.dip,
            //                 username: obj.data.rese,
            //                 password: md5(obj.data.sap),
            //                 grant_type: 'password',
            //                 scope: 'all',
            //                 type: 'account'
            //             }
            //             request({
            //                 url: '/api/blade-auth/oauth/token',
            //                 method: 'post',
            //                 headers: {
            //                     'Authorization': 'Basic c2FiZXI6c2FiZXJfc2VjcmV0',
            //                     "Tenant-Id": "000000"
            //                 },
            //                 params: data
            //             }).then(res => {
            //                 const data = res.data
            //                 if (data.error_description) {
            //                     // console.log("登入失败");
            //                     Message({
            //                         message: data.error_description,
            //                         type: 'error'
            //                     })
            //                     next('/login')
            //                     next('/login')
            //                     return
            //                 } else {
            //                     // console.log("登入成功");
            //                     store.commit('SET_TOKEN', data.access_token)
            //                     store.commit('SET_REFRESH_TOKEN', data.refresh_token)
            //                     store.commit('SET_TENANT_ID', data.tenant_id)
            //                     store.commit('SET_USER_INFO', data)
            //                     store.commit('DEL_ALL_TAG')
            //                     store.commit('CLEAR_LOCK')
            //                     next(to.path)
            //                     return
            //                 }
            //             })
            //             return
            //         } else {
            //             // console.log("成功解码 不是对象");
            //             next('/login')
            //             return
            //         }
            //     } catch {
            //         // console.log('不是Json对象 跳回登入');
            //         next('/login')
            //         return
            //     }
            // }
            next('/login')
        }
    }
  }
})
router.afterEach(() => {
  NProgress.done();
  let title = store.getters.tag.label;
  let i18n = store.getters.tag.meta.i18n;
  title = router.$avueRouter.generateTitle(title, i18n);
  //判断登录页的情况
  if (router.history.current.fullPath === "/login") {
    title = "登录";
  }
  //根据当前的标签也获取label的值动态设置浏览器标题
  router.$avueRouter.setTitle(title);
});
    NProgress.done()
    let title = store.getters.tag.label
    let i18n = store.getters.tag.meta.i18n
    title = router.$avueRouter.generateTitle(title, i18n)
    //判断登录页的情况
    if (router.history.current.fullPath === "/login") {
        title = "登录"
    }
    //根据当前的标签也获取label的值动态设置浏览器标题
    router.$avueRouter.setTitle(title)
})
src/store/modules/user.js
@@ -1,301 +1,302 @@
import {setToken, setRefreshToken, removeToken, removeRefreshToken} from '@/util/auth'
import {Message} from 'element-ui'
import {setStore, getStore} from '@/util/store'
import {isURL, validatenull} from '@/util/validate'
import {deepClone} from '@/util/util'
import { setToken, setRefreshToken, removeToken, removeRefreshToken } from '@/util/auth'
import { Message } from 'element-ui'
import { setStore, getStore } from '@/util/store'
import { isURL, validatenull } from '@/util/validate'
import { deepClone } from '@/util/util'
import website from '@/config/website'
import {loginByUsername, loginBySocial, loginBySso, getUserInfo, logout, refreshToken, getButtons} from '@/api/user'
import {getTopMenu, getRoutes} from '@/api/system/menu'
import { loginByUsername, loginBySocial, loginBySso, getUserInfo, logout, refreshToken, getButtons } from '@/api/user'
import { getTopMenu, getRoutes } from '@/api/system/menu'
import md5 from 'js-md5'
function addPath(ele, first) {
  const menu = website.menu;
  const propsConfig = menu.props;
  const propsDefault = {
    label: propsConfig.label || 'name',
    path: propsConfig.path || 'path',
    icon: propsConfig.icon || 'icon',
    children: propsConfig.children || 'children'
  }
  const icon = ele[propsDefault.icon];
  ele[propsDefault.icon] = validatenull(icon) ? menu.iconDefault : icon;
  const isChild = ele[propsDefault.children] && ele[propsDefault.children].length !== 0;
  if (!isChild) ele[propsDefault.children] = [];
  if (!isChild && first && !isURL(ele[propsDefault.path])) {
    ele[propsDefault.path] = ele[propsDefault.path] + '/index'
  } else {
    ele[propsDefault.children].forEach(child => {
      addPath(child);
    })
  }
function addPath (ele, first) {
    const menu = website.menu
    const propsConfig = menu.props
    const propsDefault = {
        label: propsConfig.label || 'name',
        path: propsConfig.path || 'path',
        icon: propsConfig.icon || 'icon',
        children: propsConfig.children || 'children'
    }
    const icon = ele[propsDefault.icon]
    ele[propsDefault.icon] = validatenull(icon) ? menu.iconDefault : icon
    const isChild = ele[propsDefault.children] && ele[propsDefault.children].length !== 0
    if (!isChild) ele[propsDefault.children] = []
    if (!isChild && first && !isURL(ele[propsDefault.path])) {
        ele[propsDefault.path] = ele[propsDefault.path] + '/index'
    } else {
        ele[propsDefault.children].forEach(child => {
            addPath(child)
        })
    }
}
const user = {
  state: {
    tenantId: getStore({name: 'tenantId'}) || '',
    userInfo: getStore({name: 'userInfo'}) || [],
    permission: getStore({name: 'permission'}) || {},
    roles: [],
    menuId: {},
    menu: getStore({name: 'menu'}) || [],
    menuAll: getStore({name: 'menuAll'}) || [],
    token: getStore({name: 'token'}) || '',
    refreshToken: getStore({name: 'refreshToken'}) || '',
  },
  actions: {
    //根据用户名登录
    LoginByUsername({commit}, userInfo) {
      return new Promise((resolve, reject) => {
        loginByUsername(userInfo.tenantId, userInfo.deptId, userInfo.roleId, userInfo.username, md5(userInfo.password), userInfo.type, userInfo.key, userInfo.code).then(res => {
          const data = res.data;
          if (data.error_description) {
            Message({
              message: data.error_description,
              type: 'error'
    state: {
        tenantId: getStore({ name: 'tenantId' }) || '',
        userInfo: getStore({ name: 'userInfo' }) || [],
        permission: getStore({ name: 'permission' }) || {},
        roles: [],
        menuId: {},
        menu: getStore({ name: 'menu' }) || [],
        menuAll: getStore({ name: 'menuAll' }) || [],
        token: getStore({ name: 'token' }) || '',
        refreshToken: getStore({ name: 'refreshToken' }) || '',
    },
    actions: {
        //根据用户名登录
        LoginByUsername ({ commit }, userInfo) {
            return new Promise((resolve, reject) => {
                loginByUsername(userInfo.tenantId, userInfo.deptId, userInfo.roleId, userInfo.username, md5(userInfo.password), userInfo.type, userInfo.key, userInfo.code).then(res => {
                    const data = res.data
                    console.log(data, userInfo, 489)
                    if (data.error_description) {
                        Message({
                            message: data.error_description,
                            type: 'error'
                        })
                    } else {
                        commit('SET_TOKEN', data.access_token)
                        commit('SET_REFRESH_TOKEN', data.refresh_token)
                        commit('SET_TENANT_ID', data.tenant_id)
                        commit('SET_USER_INFO', data)
                        commit('DEL_ALL_TAG')
                        commit('CLEAR_LOCK')
                    }
                    resolve()
                }).catch(error => {
                    reject(error)
                })
            })
          } else {
            commit('SET_TOKEN', data.access_token);
            commit('SET_REFRESH_TOKEN', data.refresh_token);
            commit('SET_TENANT_ID', data.tenant_id);
            commit('SET_USER_INFO', data);
            commit('DEL_ALL_TAG');
            commit('CLEAR_LOCK');
          }
          resolve();
        }).catch(error => {
          reject(error);
        })
      })
    },
    //根据手机号登录
    LoginByPhone({commit}, userInfo) {
      return new Promise((resolve) => {
        loginByUsername(userInfo.phone, userInfo.code).then(res => {
          const data = res.data.data;
          commit('SET_TOKEN', data);
          commit('DEL_ALL_TAG');
          commit('CLEAR_LOCK');
          resolve();
        })
      })
    },
    //根据第三方信息登录
    LoginBySocial({commit}, userInfo) {
      return new Promise((resolve) => {
        loginBySocial(userInfo.tenantId, userInfo.source, userInfo.code, userInfo.state).then(res => {
          const data = res.data;
          if (data.error_description) {
            Message({
              message: data.error_description,
              type: 'error'
        },
        //根据手机号登录
        LoginByPhone ({ commit }, userInfo) {
            return new Promise((resolve) => {
                loginByUsername(userInfo.phone, userInfo.code).then(res => {
                    const data = res.data.data
                    commit('SET_TOKEN', data)
                    commit('DEL_ALL_TAG')
                    commit('CLEAR_LOCK')
                    resolve()
                })
            })
          } else {
            commit('SET_TOKEN', data.access_token);
            commit('SET_REFRESH_TOKEN', data.refresh_token);
            commit('SET_USER_INFO', data);
            commit('SET_TENANT_ID', data.tenant_id);
            commit('DEL_ALL_TAG');
            commit('CLEAR_LOCK');
          }
          resolve();
        })
      })
    },
    //根据单点信息登录
    LoginBySso({commit}, userInfo) {
      return new Promise((resolve) => {
        loginBySso(userInfo.state, userInfo.code).then(res => {
          const data = res.data;
          if (data.error_description) {
            Message({
              message: data.error_description,
              type: 'error'
        },
        //根据第三方信息登录
        LoginBySocial ({ commit }, userInfo) {
            return new Promise((resolve) => {
                loginBySocial(userInfo.tenantId, userInfo.source, userInfo.code, userInfo.state).then(res => {
                    const data = res.data
                    if (data.error_description) {
                        Message({
                            message: data.error_description,
                            type: 'error'
                        })
                    } else {
                        commit('SET_TOKEN', data.access_token)
                        commit('SET_REFRESH_TOKEN', data.refresh_token)
                        commit('SET_USER_INFO', data)
                        commit('SET_TENANT_ID', data.tenant_id)
                        commit('DEL_ALL_TAG')
                        commit('CLEAR_LOCK')
                    }
                    resolve()
                })
            })
          } else {
            commit('SET_TOKEN', data.access_token);
            commit('SET_REFRESH_TOKEN', data.refresh_token);
            commit('SET_USER_INFO', data);
            commit('SET_TENANT_ID', data.tenant_id);
            commit('DEL_ALL_TAG');
            commit('CLEAR_LOCK');
          }
          resolve();
        })
      })
        },
        //根据单点信息登录
        LoginBySso ({ commit }, userInfo) {
            return new Promise((resolve) => {
                loginBySso(userInfo.state, userInfo.code).then(res => {
                    const data = res.data
                    if (data.error_description) {
                        Message({
                            message: data.error_description,
                            type: 'error'
                        })
                    } else {
                        commit('SET_TOKEN', data.access_token)
                        commit('SET_REFRESH_TOKEN', data.refresh_token)
                        commit('SET_USER_INFO', data)
                        commit('SET_TENANT_ID', data.tenant_id)
                        commit('DEL_ALL_TAG')
                        commit('CLEAR_LOCK')
                    }
                    resolve()
                })
            })
        },
        //获取用户信息
        GetUserInfo ({ commit }) {
            return new Promise((resolve, reject) => {
                getUserInfo().then((res) => {
                    const data = res.data.data
                    commit('SET_ROLES', data.roles)
                    resolve(data)
                }).catch(err => {
                    reject(err)
                })
            })
        },
        //刷新token
        refreshToken ({ state, commit }, userInfo) {
            window.console.log('handle refresh token')
            return new Promise((resolve, reject) => {
                refreshToken(state.refreshToken, state.tenantId,
                    !validatenull(userInfo) ? userInfo.deptId : state.userInfo.dept_id,
                    !validatenull(userInfo) ? userInfo.roleId : state.userInfo.role_id
                ).then(res => {
                    const data = res.data
                    commit('SET_TOKEN', data.access_token)
                    commit('SET_REFRESH_TOKEN', data.refresh_token)
                    commit('SET_USER_INFO', data)
                    resolve()
                }).catch(error => {
                    reject(error)
                })
            })
        },
        // 登出
        LogOut ({ commit }) {
            return new Promise((resolve, reject) => {
                logout().then(() => {
                    commit('SET_TOKEN', '')
                    commit('SET_MENU', [])
                    commit('SET_MENU_ALL_NULL', [])
                    commit('SET_ROLES', [])
                    commit('SET_TAG_LIST', [])
                    commit('DEL_ALL_TAG')
                    commit('CLEAR_LOCK')
                    removeToken()
                    removeRefreshToken()
                    resolve()
                }).catch(error => {
                    reject(error)
                })
            })
        },
        //注销session
        FedLogOut ({ commit }) {
            return new Promise(resolve => {
                commit('SET_TOKEN', '')
                commit('SET_MENU_ALL_NULL', [])
                commit('SET_MENU', [])
                commit('SET_ROLES', [])
                commit('SET_TAG_LIST', [])
                commit('DEL_ALL_TAG')
                commit('CLEAR_LOCK')
                removeToken()
                removeRefreshToken()
                resolve()
            })
        },
        //获取顶部菜单
        GetTopMenu () {
            return new Promise(resolve => {
                getTopMenu().then((res) => {
                    const data = res.data.data || []
                    resolve(data)
                })
            })
        },
        //获取系统菜单
        GetMenu ({ commit, dispatch }, topMenuId) {
            return new Promise(resolve => {
                getRoutes(topMenuId).then((res) => {
                    const data = res.data.data
                    let menu = deepClone(data)
                    menu.forEach(ele => {
                        addPath(ele, true)
                    })
                    commit('SET_MENU_ALL', menu)
                    commit('SET_MENU', menu)
                    dispatch('GetButtons')
                    resolve(menu)
                })
            })
        },
        //获取系统按钮
        GetButtons ({ commit }) {
            return new Promise((resolve) => {
                getButtons().then(res => {
                    const data = res.data.data
                    commit('SET_PERMISSION', data)
                    resolve()
                })
            })
        },
    },
    //获取用户信息
    GetUserInfo({commit}) {
      return new Promise((resolve, reject) => {
        getUserInfo().then((res) => {
          const data = res.data.data;
          commit('SET_ROLES', data.roles);
          resolve(data);
        }).catch(err => {
          reject(err);
        })
      })
    },
    //刷新token
    refreshToken({state, commit}, userInfo) {
      window.console.log('handle refresh token');
      return new Promise((resolve, reject) => {
        refreshToken(state.refreshToken, state.tenantId,
          !validatenull(userInfo) ? userInfo.deptId : state.userInfo.dept_id,
          !validatenull(userInfo) ? userInfo.roleId : state.userInfo.role_id
        ).then(res => {
          const data = res.data;
          commit('SET_TOKEN', data.access_token);
          commit('SET_REFRESH_TOKEN', data.refresh_token);
          commit('SET_USER_INFO', data);
          resolve();
        }).catch(error => {
          reject(error)
        })
      })
    },
    // 登出
    LogOut({commit}) {
      return new Promise((resolve, reject) => {
        logout().then(() => {
          commit('SET_TOKEN', '');
          commit('SET_MENU', []);
          commit('SET_MENU_ALL_NULL', []);
          commit('SET_ROLES', []);
          commit('SET_TAG_LIST', []);
          commit('DEL_ALL_TAG');
          commit('CLEAR_LOCK');
          removeToken();
          removeRefreshToken();
          resolve();
        }).catch(error => {
          reject(error)
        })
      })
    },
    //注销session
    FedLogOut({commit}) {
      return new Promise(resolve => {
        commit('SET_TOKEN', '');
        commit('SET_MENU_ALL_NULL', []);
        commit('SET_MENU', []);
        commit('SET_ROLES', []);
        commit('SET_TAG_LIST', []);
        commit('DEL_ALL_TAG');
        commit('CLEAR_LOCK');
        removeToken();
        removeRefreshToken();
        resolve();
      })
    },
    //获取顶部菜单
    GetTopMenu() {
      return new Promise(resolve => {
        getTopMenu().then((res) => {
          const data = res.data.data || [];
          resolve(data)
        })
      })
    },
    //获取系统菜单
    GetMenu({commit, dispatch}, topMenuId) {
      return new Promise(resolve => {
        getRoutes(topMenuId).then((res) => {
          const data = res.data.data
          let menu = deepClone(data);
          menu.forEach(ele => {
            addPath(ele, true);
          });
          commit('SET_MENU_ALL', menu)
          commit('SET_MENU', menu)
          dispatch('GetButtons');
          resolve(menu)
        })
      })
    },
    //获取系统按钮
    GetButtons({commit}) {
      return new Promise((resolve) => {
        getButtons().then(res => {
          const data = res.data.data;
          commit('SET_PERMISSION', data);
          resolve();
        })
      })
    },
  },
  mutations: {
    SET_TOKEN: (state, token) => {
      setToken(token);
      state.token = token;
      setStore({name: 'token', content: state.token})
    },
    SET_MENU_ID(state, menuId) {
      state.menuId = menuId;
    },
    SET_MENU_ALL: (state, menuAll) => {
      let menu = state.menuAll;
      menuAll.forEach(ele => {
        if (!menu.find(item => item.label === ele.label && item.path === ele.path)) {
          menu.push(ele);
        }
      })
      state.menuAll = menu
      setStore({ name: 'menuAll', content: state.menuAll })
    },
    SET_MENU_ALL_NULL: (state) => {
      state.menuAll = []
      setStore({ name: 'menuAll', content: state.menuAll })
    },
    SET_MENU: (state, menu) => {
      state.menu = menu
      setStore({ name: 'menu', content: state.menu })
    },
    SET_REFRESH_TOKEN: (state, refreshToken) => {
      setRefreshToken(refreshToken)
      state.refreshToken = refreshToken;
      setStore({name: 'refreshToken', content: state.refreshToken})
    },
    SET_TENANT_ID: (state, tenantId) => {
      state.tenantId = tenantId;
      setStore({name: 'tenantId', content: state.tenantId})
    },
    SET_USER_INFO: (state, userInfo) => {
      if (validatenull(userInfo.avatar)) {
        userInfo.avatar = "/img/bg/img-logo.png";
      }
      state.userInfo = userInfo;
      setStore({name: 'userInfo', content: state.userInfo})
    },
    SET_ROLES: (state, roles) => {
      state.roles = roles;
    },
    SET_PERMISSION: (state, permission) => {
      let result = [];
      function getCode(list) {
        list.forEach(ele => {
          if (typeof (ele) === 'object') {
            const chiildren = ele.children;
            const code = ele.code;
            if (chiildren) {
              getCode(chiildren)
            } else {
              result.push(code);
    mutations: {
        SET_TOKEN: (state, token) => {
            setToken(token)
            state.token = token
            setStore({ name: 'token', content: state.token })
        },
        SET_MENU_ID (state, menuId) {
            state.menuId = menuId
        },
        SET_MENU_ALL: (state, menuAll) => {
            let menu = state.menuAll
            menuAll.forEach(ele => {
                if (!menu.find(item => item.label === ele.label && item.path === ele.path)) {
                    menu.push(ele)
                }
            })
            state.menuAll = menu
            setStore({ name: 'menuAll', content: state.menuAll })
        },
        SET_MENU_ALL_NULL: (state) => {
            state.menuAll = []
            setStore({ name: 'menuAll', content: state.menuAll })
        },
        SET_MENU: (state, menu) => {
            state.menu = menu
            setStore({ name: 'menu', content: state.menu })
        },
        SET_REFRESH_TOKEN: (state, refreshToken) => {
            setRefreshToken(refreshToken)
            state.refreshToken = refreshToken
            setStore({ name: 'refreshToken', content: state.refreshToken })
        },
        SET_TENANT_ID: (state, tenantId) => {
            state.tenantId = tenantId
            setStore({ name: 'tenantId', content: state.tenantId })
        },
        SET_USER_INFO: (state, userInfo) => {
            if (validatenull(userInfo.avatar)) {
                userInfo.avatar = "/img/bg/img-logo.png"
            }
          }
        })
      }
            state.userInfo = userInfo
            setStore({ name: 'userInfo', content: state.userInfo })
        },
        SET_ROLES: (state, roles) => {
            state.roles = roles
        },
        SET_PERMISSION: (state, permission) => {
            let result = []
      getCode(permission);
      state.permission = {};
      result.forEach(ele => {
        state.permission[ele] = true;
      });
      setStore({name: 'permission', content: state.permission})
            function getCode (list) {
                list.forEach(ele => {
                    if (typeof (ele) === 'object') {
                        const chiildren = ele.children
                        const code = ele.code
                        if (chiildren) {
                            getCode(chiildren)
                        } else {
                            result.push(code)
                        }
                    }
                })
            }
            getCode(permission)
            state.permission = {}
            result.forEach(ele => {
                state.permission[ele] = true
            })
            setStore({ name: 'permission', content: state.permission })
        }
    }
  }
}
export default user
src/views/security/security.vue
@@ -1,410 +1,416 @@
<template>
  <basic-container>
    <avue-crud :option="option" :table-loading="loading" :data="data" :page.sync="page" :permission="permissionList"
      :before-open="beforeOpen" v-model="form" ref="crud" @row-update="rowUpdate" @row-save="rowSave" @row-del="rowDel"
      @search-change="searchChange" @search-reset="searchReset" @selection-change="selectionChange"
      @current-change="currentChange" @size-change="sizeChange" @refresh-change="refreshChange" @on-load="onLoad">
      <template slot="menuLeft">
        <el-button size="small" icon="el-icon-delete" plain v-if="permission.security_delete" @click="handleDelete">删 除
        </el-button>
      </template>
      <template slot-scope="{type,size,row,index}" slot="menu">
        <el-button icon="el-icon-coordinate" :size="size" :type="type" @click="handlePersonList(row)">活动人员</el-button>
        <el-button icon="el-icon-data-line" :size="size" :type="type" @click="handleCarList(row)">活动车辆</el-button>
      </template>
    </avue-crud>
    <basic-container>
        <avue-crud :option="option" :table-loading="loading" :data="data" :page.sync="page" :permission="permissionList"
            :before-open="beforeOpen" v-model="form" ref="crud" @row-update="rowUpdate" @row-save="rowSave"
            @row-del="rowDel" @search-change="searchChange" @search-reset="searchReset"
            @selection-change="selectionChange" @current-change="currentChange" @size-change="sizeChange"
            @refresh-change="refreshChange" @on-load="onLoad">
            <template slot="menuLeft">
                <el-button size="small" icon="el-icon-delete" plain v-if="permission.security_delete"
                    @click="handleDelete">删 除
                </el-button>
            </template>
            <template slot-scope="{type,size,row,index}" slot="menu">
                <el-button icon="el-icon-coordinate" :size="size" :type="type"
                    @click="handlePersonList(row)">活动人员</el-button>
                <el-button icon="el-icon-data-line" :size="size" :type="type"
                    @click="handleCarList(row)">活动车辆</el-button>
            </template>
        </avue-crud>
    <el-drawer title="活动人员区域" :visible.sync="personBox" :append-to-body="true" size="50%" :destroy-on-close="true">
      <securityManage ref="securityManage" :securityId="securityId"/>
    </el-drawer>
        <el-drawer title="活动人员区域" :visible.sync="personBox" :append-to-body="true" size="50%" :destroy-on-close="true">
            <securityManage ref="securityManage" :securityId="securityId" />
        </el-drawer>
    <el-drawer title="活动车辆区域" :visible.sync="carBox" :append-to-body="true" size="50%" :destroy-on-close="true">
      <securityManageCar ref="car" :securityId="securityId"/>
    </el-drawer>
  </basic-container>
        <el-drawer title="活动车辆区域" :visible.sync="carBox" :append-to-body="true" size="50%" :destroy-on-close="true">
            <securityManageCar ref="car" :securityId="securityId" />
        </el-drawer>
    </basic-container>
</template>
<script>
import { getPage, getDetail, add, update, remove } from "@/api/security/security";
import { getUserInfos } from "@/api/system/user";
import { getPage, getDetail, add, update, remove } from "@/api/security/security"
import { getUserInfos } from "@/api/system/user"
// import AvueMap from 'avue-plugin-map';
import { mapGetters } from "vuex";
import { mapGetters } from "vuex"
import securityManage from "@/views/securityManage/securityManage"
import securityManageCar from "@/views/securityManageCar/securityManageCar"
export default {
  components: {
    securityManage,
    securityManageCar
  },
  data() {
    return {
      securityId:"",
      carBox: false,
      personBox: false,
      form: {},
      query: {},
      loading: true,
      page: {
        pageSize: 10,
        currentPage: 1,
        total: 0
      },
      selectionList: [],
      option: {
        height: 'auto',
        calcHeight: 30,
        labelWidth: "100",
        dialogWidth: 950,
        tip: false,
        searchShow: true,
        searchMenuSpan: 6,
        border: true,
        index: true,
        viewBtn: true,
        selection: true,
        excelBtn: true,
        dialogClickModal: false,
        menuWidth: 370,
        column: [
          {
            label: "活动名称",
            prop: "name",
            search: true,
            searchSpan: 4,
            rules: [{
              required: true,
              message: "请输入活动名称",
              trigger: "blur"
            }],
          },
          {
            label: "负责单位",
            prop: "company",
          },
          {
            label: "负责人",
            prop: "person",
            width: 80,
            rules: [{
              required: true,
              message: "请输入负责人",
              trigger: "blur"
            }],
          },
          {
            label: "联系方式",
            prop: "contact",
            width: 100,
            rules: [{
              required: true,
              message: "请输入联系方式",
              trigger: "blur"
            }],
          },
          {
            label: "活动地点",
            prop: "place",
            // addDisplay: false,
            // editDisplay: false,
            // viewDisplay: false,
          },
          {
            label: "所属辖区",
            prop: "deptId",
            type: "tree",
            dicUrl: "api/blade-system/dept/lazy-list",
            props: {
              label: 'deptName',
              value: 'id',
              children: 'children'
    components: {
        securityManage,
        securityManageCar
    },
    data () {
        return {
            securityId: "",
            carBox: false,
            personBox: false,
            form: {},
            query: {},
            loading: true,
            page: {
                pageSize: 10,
                currentPage: 1,
                total: 0
            },
            search: true,
            searchSpan: 4,
            width: 110,
            rules: [{
              required: true,
              message: "请选择所属辖区",
              trigger: "blur"
            }]
          },
          // {
          //   label: "地址",
          //   prop: "avueMap",
          //   type: "map",
          // },
          {
            label: "开始时间",
            prop: "startTime",
            type: "datetime",
            defaultTime: '00:00:00',
            format: "yyyy-MM-dd HH:mm",
            valueFormat: "yyyy-MM-dd HH:mm:ss",
            rules: [{
              required: true,
              message: "请输入开始时间",
              trigger: "blur"
            }],
            width: 120,
          },
          {
            label: "结束时间",
            prop: "endTime",
            type: "datetime",
            defaultTime: '23:59:59',
            format: "yyyy-MM-dd HH:mm",
            valueFormat: "yyyy-MM-dd HH:mm",
            rules: [{
              required: true,
              message: "请输入结束时间",
              trigger: "blur"
            }],
            width: 120,
          },
          {
            label: "经度",
            prop: "longitude",
            span: 12,
            hide: true,
            rules: [{
              required: true,
              message: "请输入纬度",
              trigger: "blur"
            }],
          },
          {
            label: "纬度",
            prop: "latitude",
            span: 12,
            hide: true,
            rules: [{
              required: true,
              message: "请输入纬度",
              trigger: "blur"
            }],
          },
          // {
          //   label: "",
          //   prop: "map",
          //   labelWidth: 10,
          //   searchSpan: 0,
          //   // maxlength: 5,
          //   hide: true,
          //   span: 3,
          //   // display:false,
          //   component: "AvueMap",
          // },
          {
            label: "活动类型",
            prop: "type",
            type: "select",
            dicUrl: "/api/blade-system/dict-biz/dictionary?code=securityType",
            props: {
              label: "dictValue",
              value: "dictKey"
            selectionList: [],
            option: {
                height: 'auto',
                calcHeight: 30,
                labelWidth: "100",
                dialogWidth: 950,
                tip: false,
                searchShow: true,
                searchMenuSpan: 6,
                border: true,
                index: true,
                viewBtn: true,
                selection: true,
                excelBtn: true,
                dialogClickModal: false,
                menuWidth: 370,
                column: [
                    {
                        label: "活动名称",
                        prop: "name",
                        search: true,
                        searchSpan: 4,
                        rules: [{
                            required: true,
                            message: "请输入活动名称",
                            trigger: "blur"
                        }],
                    },
                    {
                        label: "负责单位",
                        prop: "company",
                    },
                    {
                        label: "负责人",
                        prop: "person",
                        width: 80,
                        rules: [{
                            required: true,
                            message: "请输入负责人",
                            trigger: "blur"
                        }],
                    },
                    {
                        label: "联系方式",
                        prop: "contact",
                        width: 100,
                        rules: [{
                            required: true,
                            message: "请输入联系方式",
                            trigger: "blur"
                        }],
                    },
                    {
                        label: "活动地点",
                        prop: "place",
                        // addDisplay: false,
                        // editDisplay: false,
                        // viewDisplay: false,
                    },
                    {
                        label: "所属辖区",
                        prop: "deptId",
                        type: "tree",
                        dicUrl: "api/blade-system/dept/lazy-list",
                        props: {
                            label: 'deptName',
                            value: 'id',
                            children: 'children'
                        },
                        search: true,
                        searchSpan: 4,
                        width: 110,
                        rules: [{
                            required: true,
                            message: "请选择所属辖区",
                            trigger: "blur"
                        }]
                    },
                    // {
                    //   label: "地址",
                    //   prop: "avueMap",
                    //   type: "map",
                    // },
                    {
                        label: "开始时间",
                        prop: "startTime",
                        type: "datetime",
                        defaultTime: '00:00:00',
                        format: "yyyy-MM-dd HH:mm",
                        valueFormat: "yyyy-MM-dd HH:mm:ss",
                        rules: [{
                            required: true,
                            message: "请输入开始时间",
                            trigger: "blur"
                        }],
                        width: 120,
                    },
                    {
                        label: "结束时间",
                        prop: "endTime",
                        type: "datetime",
                        defaultTime: '23:59:59',
                        format: "yyyy-MM-dd HH:mm",
                        valueFormat: "yyyy-MM-dd HH:mm",
                        rules: [{
                            required: true,
                            message: "请输入结束时间",
                            trigger: "blur"
                        }],
                        width: 120,
                    },
                    {
                        label: "经度",
                        prop: "longitude",
                        span: 12,
                        hide: true,
                        rules: [{
                            required: true,
                            message: "请输入纬度",
                            trigger: "blur"
                        }],
                    },
                    {
                        label: "纬度",
                        prop: "latitude",
                        span: 12,
                        hide: true,
                        rules: [{
                            required: true,
                            message: "请输入纬度",
                            trigger: "blur"
                        }],
                    },
                    // {
                    //   label: "",
                    //   prop: "map",
                    //   labelWidth: 10,
                    //   searchSpan: 0,
                    //   // maxlength: 5,
                    //   hide: true,
                    //   span: 3,
                    //   // display:false,
                    //   component: "AvueMap",
                    // },
                    {
                        label: "活动类型",
                        prop: "type",
                        type: "select",
                        dicUrl: "/api/blade-system/dict-biz/dictionary?code=securityType",
                        props: {
                            label: "dictValue",
                            value: "dictKey"
                        },
                        rules: [{
                            required: true,
                            message: "请选择活动类型",
                            trigger: "blur"
                        }],
                        width: 90,
                    },
                    {
                        label: "人数",
                        prop: "number",
                        width: 60,
                    },
                    {
                        label: "活动内容",
                        prop: "content",
                        type: "textarea",
                        span: 24
                    },
                ]
            },
            rules: [{
              required: true,
              message: "请选择活动类型",
              trigger: "blur"
            }],
            width: 90,
          },
          {
            label: "人数",
            prop: "number",
            width: 60,
          },
          {
            label: "活动内容",
            prop: "content",
            type:"textarea",
            span:24
          },
        ]
      },
      data: []
    };
  },
  // watch: {
  //   //latitude   longitude   formattedAddress
  //   "form.avueMap":{
  //     handler (newObj) {
  //       if (newObj.length>0) {
  //         this.form.place = newObj[2]
  //         this.form.position = newObj[0]+","+newObj[1]
  //       }
  //     }
  //   }
  // },
  computed: {
    ...mapGetters(["userInfo", "permission"]),
    permissionList() {
      return {
        addBtn: this.vaildData(this.permission.security_add, false),
        viewBtn: this.vaildData(this.permission.security_view, false),
        delBtn: this.vaildData(this.permission.security_delete, false),
        editBtn: this.vaildData(this.permission.security_edit, false)
      };
            data: []
        }
    },
    ids() {
      let ids = [];
      this.selectionList.forEach(ele => {
        ids.push(ele.id);
      });
      return ids.join(",");
    }
  },
  created(){
    const tokenLength = window.location.href.indexOf('=');
    if(tokenLength>0){
      //取“=”之后的token
      let z = window.location.href.substring(tokenLength + 1)
      this.$store.commit('SET_TOKEN', z);
      this.$store.commit('DEL_ALL_TAG');
      this.$store.commit('CLEAR_LOCK');
      this.getUserInfo()
    }
  },
  methods: {
    getUserInfo(){
      getUserInfos().then(res=>{
         this.$store.commit('SET_USER_INFO', res.data.data);
      })
    // watch: {
    //   //latitude   longitude   formattedAddress
    //   "form.avueMap":{
    //     handler (newObj) {
    //       if (newObj.length>0) {
    //         this.form.place = newObj[2]
    //         this.form.position = newObj[0]+","+newObj[1]
    //       }
    //     }
    //   }
    // },
    computed: {
        ...mapGetters(["userInfo", "permission"]),
        permissionList () {
            return {
                addBtn: this.vaildData(this.permission.security_add, false),
                viewBtn: this.vaildData(this.permission.security_view, false),
                delBtn: this.vaildData(this.permission.security_delete, false),
                editBtn: this.vaildData(this.permission.security_edit, false)
            }
        },
        ids () {
            let ids = []
            this.selectionList.forEach(ele => {
                ids.push(ele.id)
            })
            return ids.join(",")
        }
    },
    rowSave(row, done, loading) {
      row.position = row.longitude + " " + row.latitude;
      add(row).then(() => {
        this.onLoad(this.page);
        this.$message({
          type: "success",
          message: "操作成功!"
        });
        done();
      }, error => {
        loading();
        window.console.log(error);
      });
    created () {
        const tokenLength = window.location.href.indexOf('=')
        if (tokenLength > 0) {
            //取“=”之后的token
            this.getUserInfo()
        }
    },
    rowUpdate(row, index, done, loading) {
      row.position = row.longitude + " " + row.latitude;
      update(row).then(() => {
        this.onLoad(this.page);
        this.$message({
          type: "success",
          message: "操作成功!"
        });
        done();
      }, error => {
        loading();
        console.log(error);
      });
    },
    rowDel(row) {
      this.$confirm("确定将选择数据删除?", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      })
        .then(() => {
          return remove(row.id);
        })
        .then(() => {
          this.onLoad(this.page);
          this.$message({
            type: "success",
            message: "操作成功!"
          });
        });
    },
    handleDelete() {
      if (this.selectionList.length === 0) {
        this.$message.warning("请选择至少一条数据");
        return;
      }
      this.$confirm("确定将选择数据删除?", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      })
        .then(() => {
          return remove(this.ids);
        })
        .then(() => {
          this.onLoad(this.page);
          this.$message({
            type: "success",
            message: "操作成功!"
          });
          this.$refs.crud.toggleSelection();
        });
    },
    beforeOpen(done, type) {
      if (["edit", "view"].includes(type)) {
        getDetail(this.form.id).then(res => {
            var data = res.data.data;
            this.form = data;
            this.form['longitude'] = data.position.split(" ")[0]
            this.form['latitude'] = data.position.split(" ")[1]
        });
      }
      done();
    },
    searchReset() {
      this.query = {};
      this.onLoad(this.page);
    },
    searchChange(params, done) {
      this.query = params;
      this.page.currentPage = 1;
      this.onLoad(this.page, params);
      done();
    },
    selectionChange(list) {
      this.selectionList = list;
    },
    selectionClear() {
      this.selectionList = [];
      this.$refs.crud.toggleSelection();
    },
    currentChange(currentPage) {
      this.page.currentPage = currentPage;
    },
    sizeChange(pageSize) {
      this.page.pageSize = pageSize;
    },
    refreshChange() {
      this.onLoad(this.page, this.query);
    },
    onLoad(page, params = {}) {
      this.loading = true;
    methods: {
        getUserInfo () {
            getUserInfos().then(res => {
                const data = res.data
                this.$store.commit('SET_TOKEN', data.access_token)
                this.$store.commit('SET_REFRESH_TOKEN', data.refresh_token)
                this.$store.commit('SET_TENANT_ID', data.tenant_id)
                this.$store.commit('SET_USER_INFO', data)
                this.$store.commit('DEL_ALL_TAG')
                this.$store.commit('CLEAR_LOCK')
            })
        },
        rowSave (row, done, loading) {
            row.position = row.longitude + " " + row.latitude
            add(row).then(() => {
                this.onLoad(this.page)
                this.$message({
                    type: "success",
                    message: "操作成功!"
                })
                done()
            }, error => {
                loading()
                window.console.log(error)
            })
        },
        rowUpdate (row, index, done, loading) {
            row.position = row.longitude + " " + row.latitude
            update(row).then(() => {
                this.onLoad(this.page)
                this.$message({
                    type: "success",
                    message: "操作成功!"
                })
                done()
            }, error => {
                loading()
                console.log(error)
            })
        },
        rowDel (row) {
            this.$confirm("确定将选择数据删除?", {
                confirmButtonText: "确定",
                cancelButtonText: "取消",
                type: "warning"
            })
                .then(() => {
                    return remove(row.id)
                })
                .then(() => {
                    this.onLoad(this.page)
                    this.$message({
                        type: "success",
                        message: "操作成功!"
                    })
                })
        },
        handleDelete () {
            if (this.selectionList.length === 0) {
                this.$message.warning("请选择至少一条数据")
                return
            }
            this.$confirm("确定将选择数据删除?", {
                confirmButtonText: "确定",
                cancelButtonText: "取消",
                type: "warning"
            })
                .then(() => {
                    return remove(this.ids)
                })
                .then(() => {
                    this.onLoad(this.page)
                    this.$message({
                        type: "success",
                        message: "操作成功!"
                    })
                    this.$refs.crud.toggleSelection()
                })
        },
        beforeOpen (done, type) {
            if (["edit", "view"].includes(type)) {
                getDetail(this.form.id).then(res => {
                    var data = res.data.data
                    this.form = data
                    this.form['longitude'] = data.position.split(" ")[0]
                    this.form['latitude'] = data.position.split(" ")[1]
                })
            }
            done()
        },
        searchReset () {
            this.query = {}
            this.onLoad(this.page)
        },
        searchChange (params, done) {
            this.query = params
            this.page.currentPage = 1
            this.onLoad(this.page, params)
            done()
        },
        selectionChange (list) {
            this.selectionList = list
        },
        selectionClear () {
            this.selectionList = []
            this.$refs.crud.toggleSelection()
        },
        currentChange (currentPage) {
            this.page.currentPage = currentPage
        },
        sizeChange (pageSize) {
            this.page.pageSize = pageSize
        },
        refreshChange () {
            this.onLoad(this.page, this.query)
        },
        onLoad (page, params = {}) {
            this.loading = true
      if (this.userInfo.role_name != "admin" && this.userInfo.role_name != "administrator") {
        params["jurisdiction"] = this.userInfo.dept_id;
      }
            if (this.userInfo.role_name != "admin" && this.userInfo.role_name != "administrator") {
                params["jurisdiction"] = this.userInfo.dept_id
            }
      getPage(page.currentPage, page.pageSize, Object.assign(params, this.query)).then(res => {
        const data = res.data.data;
        this.page.total = data.total;
        this.data = data.records;
        this.loading = false;
        this.selectionClear();
      });
    },
    //活动人员区域点击按钮事件
    handlePersonList(row) {
      this.personBox = true;
      this.securityId = row.id
    },
    //活动车辆区域点击按钮事件
    handleCarList(row) {
      this.carBox = true;
      this.securityId = row.id
            getPage(page.currentPage, page.pageSize, Object.assign(params, this.query)).then(res => {
                const data = res.data.data
                this.page.total = data.total
                this.data = data.records
                this.loading = false
                this.selectionClear()
            })
        },
        //活动人员区域点击按钮事件
        handlePersonList (row) {
            this.personBox = true
            this.securityId = row.id
        },
        //活动车辆区域点击按钮事件
        handleCarList (row) {
            this.carBox = true
            this.securityId = row.id
        }
    }
  }
};
}
</script>
<style>
src/views/system/user.vue
@@ -1,173 +1,101 @@
<template>
  <el-row>
    <el-col :span="5">
      <div class="box">
        <el-scrollbar>
          <basic-container>
            <avue-tree :option="treeOption" :data="treeData" @node-click="nodeClick"/>
          </basic-container>
        </el-scrollbar>
      </div>
    </el-col>
    <el-col :span="19">
      <basic-container>
        <avue-crud :option="option"
                   :search.sync="search"
                   :table-loading="loading"
                   :data="data"
                   ref="crud"
                   v-model="form"
                   :defaults.sync="defaults"
                   :permission="permissionList"
                   @row-del="rowDel"
                   @row-update="rowUpdate"
                   @row-save="rowSave"
                   :before-open="beforeOpen"
                   :page.sync="page"
                   @search-change="searchChange"
                   @search-reset="searchReset"
                   @selection-change="selectionChange"
                   @current-change="currentChange"
                   @size-change="sizeChange"
                   @refresh-change="refreshChange"
                   @on-load="onLoad">
          <template slot="menuLeft">
            <el-button
                       size="small"
                       plain
                       icon="el-icon-delete"
                       v-if="permission.user_delete"
                       @click="handleDelete">删 除
            </el-button>
            <el-button
                       size="small"
                       plain
                       v-if="permission.user_role"
                       icon="el-icon-user"
                       @click="handleGrant">角色配置
            </el-button>
            <el-button
                       size="small"
                       plain
                       v-if="permission.user_reset"
                       icon="el-icon-refresh"
                       @click="handleReset">密码重置
            </el-button>
            <el-button
                       size="small"
                       plain
                       v-if="userInfo.role_name.indexOf('admin')"
                       icon="el-icon-setting"
                       @click="handlePlatform">平台配置
            </el-button>
            <el-button
                       size="small"
                       plain
                       v-if="userInfo.role_name.indexOf('admin')"
                       icon="el-icon-coordinate"
                       @click="handleLock">账号解封
            </el-button>
            <el-button
                       size="small"
                       plain
                       v-if="userInfo.role_name.indexOf('admin')"
                       icon="el-icon-upload2"
                       @click="handleImport">导入
            </el-button>
            <el-button
                       size="small"
                       plain
                       v-if="userInfo.role_name.indexOf('admin')"
                       icon="el-icon-download"
                       @click="handleExport">导出
            </el-button>
          </template>
          <template slot-scope="{row}"
                    slot="tenantName">
            <el-tag>{{row.tenantName}}</el-tag>
          </template>
          <template slot-scope="{row}"
                    slot="roleName">
            <el-tag>{{row.roleName}}</el-tag>
          </template>
          <template slot-scope="{row}"
                    slot="deptName">
            <el-tag>{{row.deptName}}</el-tag>
          </template>
          <template slot-scope="{row}"
                    slot="userTypeName">
            <el-tag>{{row.userTypeName}}</el-tag>
          </template>
        </avue-crud>
        <el-dialog title="用户角色配置"
                   append-to-body
                   :visible.sync="roleBox"
                   width="345px">
    <el-row>
        <el-col :span="5">
            <div class="box">
                <el-scrollbar>
                    <basic-container>
                        <avue-tree :option="treeOption" :data="treeData" @node-click="nodeClick" />
                    </basic-container>
                </el-scrollbar>
            </div>
        </el-col>
        <el-col :span="19">
            <basic-container>
                <avue-crud :option="option" :search.sync="search" :table-loading="loading" :data="data" ref="crud"
                    v-model="form" :defaults.sync="defaults" :permission="permissionList" @row-del="rowDel"
                    @row-update="rowUpdate" @row-save="rowSave" :before-open="beforeOpen" :page.sync="page"
                    @search-change="searchChange" @search-reset="searchReset" @selection-change="selectionChange"
                    @current-change="currentChange" @size-change="sizeChange" @refresh-change="refreshChange"
                    @on-load="onLoad">
                    <template slot="menuLeft">
                        <el-button size="small" plain icon="el-icon-delete" v-if="permission.user_delete"
                            @click="handleDelete">删 除
                        </el-button>
                        <el-button size="small" plain v-if="permission.user_role" icon="el-icon-user"
                            @click="handleGrant">角色配置
                        </el-button>
                        <el-button size="small" plain v-if="permission.user_reset" icon="el-icon-refresh"
                            @click="handleReset">密码重置
                        </el-button>
                        <el-button size="small" plain v-if="userInfo.role_name.indexOf('admin')" icon="el-icon-setting"
                            @click="handlePlatform">平台配置
                        </el-button>
                        <el-button size="small" plain v-if="userInfo.role_name.indexOf('admin')"
                            icon="el-icon-coordinate" @click="handleLock">账号解封
                        </el-button>
                        <el-button size="small" plain v-if="userInfo.role_name.indexOf('admin')" icon="el-icon-upload2"
                            @click="handleImport">导入
                        </el-button>
                        <el-button size="small" plain v-if="userInfo.role_name.indexOf('admin')" icon="el-icon-download"
                            @click="handleExport">导出
                        </el-button>
                    </template>
                    <template slot-scope="{row}" slot="tenantName">
                        <el-tag>{{ row.tenantName }}</el-tag>
                    </template>
                    <template slot-scope="{row}" slot="roleName">
                        <el-tag>{{ row.roleName }}</el-tag>
                    </template>
                    <template slot-scope="{row}" slot="deptName">
                        <el-tag>{{ row.deptName }}</el-tag>
                    </template>
                    <template slot-scope="{row}" slot="userTypeName">
                        <el-tag>{{ row.userTypeName }}</el-tag>
                    </template>
                </avue-crud>
                <el-dialog title="用户角色配置" append-to-body :visible.sync="roleBox" width="345px">
          <el-tree :data="roleGrantList"
                   show-checkbox
                   check-strictly
                   default-expand-all
                   node-key="id"
                   ref="treeRole"
                   :default-checked-keys="roleTreeObj"
                   :props="props">
          </el-tree>
                    <el-tree :data="roleGrantList" show-checkbox check-strictly default-expand-all node-key="id"
                        ref="treeRole" :default-checked-keys="roleTreeObj" :props="props">
                    </el-tree>
          <span slot="footer" class="dialog-footer">
            <el-button @click="roleBox = false">取 消</el-button>
            <el-button type="primary"
                       @click="submitRole">确 定</el-button>
          </span>
        </el-dialog>
        <el-dialog title="用户数据导入"
                   append-to-body
                   :visible.sync="excelBox"
                   width="555px">
          <avue-form :option="excelOption" v-model="excelForm" :upload-after="uploadAfter">
            <template slot="excelTemplate">
              <el-button type="primary" @click="handleTemplate">
                点击下载<i class="el-icon-download el-icon--right"></i>
              </el-button>
            </template>
          </avue-form>
        </el-dialog>
        <el-dialog title="用户平台配置"
                   append-to-body
                   :visible.sync="platformBox">
          <avue-crud :option="platformOption"
                     :table-loading="platformLoading"
                     :data="platformData"
                     ref="platformCrud"
                     v-model="platformForm"
                     :before-open="platformBeforeOpen"
                     :page.sync="platformPage"
                     :permission="platformPermissionList"
                     @row-update="platformRowUpdate"
                     @search-change="platformSearchChange"
                     @search-reset="platformSearchReset"
                     @selection-change="platformSelectionChange"
                     @current-change="platformCurrentChange"
                     @size-change="platformSizeChange"
                     @refresh-change="platformRefreshChange"
                     @on-load="platformOnLoad">
            <template slot-scope="{row}"
                      slot="tenantName">
              <el-tag>{{row.tenantName}}</el-tag>
            </template>
            <template slot-scope="{row}"
                      slot="userTypeName">
              <el-tag>{{row.userTypeName}}</el-tag>
            </template>
          </avue-crud>
        </el-dialog>
      </basic-container>
    </el-col>
  </el-row>
                    <span slot="footer" class="dialog-footer">
                        <el-button @click="roleBox = false">取 消</el-button>
                        <el-button type="primary" @click="submitRole">确 定</el-button>
                    </span>
                </el-dialog>
                <el-dialog title="用户数据导入" append-to-body :visible.sync="excelBox" width="555px">
                    <avue-form :option="excelOption" v-model="excelForm" :upload-after="uploadAfter">
                        <template slot="excelTemplate">
                            <el-button type="primary" @click="handleTemplate">
                                点击下载<i class="el-icon-download el-icon--right"></i>
                            </el-button>
                        </template>
                    </avue-form>
                </el-dialog>
                <el-dialog title="用户平台配置" append-to-body :visible.sync="platformBox">
                    <avue-crud :option="platformOption" :table-loading="platformLoading" :data="platformData"
                        ref="platformCrud" v-model="platformForm" :before-open="platformBeforeOpen"
                        :page.sync="platformPage" :permission="platformPermissionList" @row-update="platformRowUpdate"
                        @search-change="platformSearchChange" @search-reset="platformSearchReset"
                        @selection-change="platformSelectionChange" @current-change="platformCurrentChange"
                        @size-change="platformSizeChange" @refresh-change="platformRefreshChange"
                        @on-load="platformOnLoad">
                        <template slot-scope="{row}" slot="tenantName">
                            <el-tag>{{ row.tenantName }}</el-tag>
                        </template>
                        <template slot-scope="{row}" slot="userTypeName">
                            <el-tag>{{ row.userTypeName }}</el-tag>
                        </template>
                    </avue-crud>
                </el-dialog>
            </basic-container>
        </el-col>
    </el-row>
</template>
<script>
  import {
import {
    getList,
    getUser,
    getUserPlatform,
@@ -177,881 +105,881 @@
    add,
    grant,
    resetPassword, unlock
  } from "@/api/system/user";
  import {exportBlob} from "@/api/common";
  import {getDeptTree, getDeptLazyTree} from "@/api/system/dept";
  import {getRoleTree} from "@/api/system/role";
  import {getPostList} from "@/api/system/post";
  import {mapGetters} from "vuex";
  import website from '@/config/website';
  import {getToken} from '@/util/auth';
  import {downloadXls} from "@/util/util";
  import {dateNow} from "@/util/date";
  import NProgress from 'nprogress';
  import 'nprogress/nprogress.css';
  import func from "@/util/func";
} from "@/api/system/user"
import { exportBlob } from "@/api/common"
import { getDeptTree, getDeptLazyTree } from "@/api/system/dept"
import { getRoleTree } from "@/api/system/role"
//   import {getPostList} from "@/api/system/post";
import { mapGetters } from "vuex"
import website from '@/config/website'
import { getToken } from '@/util/auth'
import { downloadXls } from "@/util/util"
import { dateNow } from "@/util/date"
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
import func from "@/util/func"
  export default {
    data() {
      const validatePass = (rule, value, callback) => {
        if (value === '') {
          callback(new Error('请输入密码'));
        } else {
          callback();
        }
      };
      const validatePass2 = (rule, value, callback) => {
        if (value === '') {
          callback(new Error('请再次输入密码'));
        } else if (value !== this.form.password) {
          callback(new Error('两次输入密码不一致!'));
        } else {
          callback();
        }
      };
      return {
        form: {},
        search:{},
        roleBox: false,
        excelBox: false,
        platformBox: false,
        initFlag: true,
        selectionList: [],
        query: {},
        loading: true,
        platformLoading: false,
        page: {
          pageSize: 10,
          currentPage: 1,
          total: 0
        },
        platformPage: {
          pageSize: 10,
          currentPage: 1,
          total: 0
        },
        init: {
          roleTree: [],
          deptTree: [],
        },
        props: {
          label: "title",
          value: "key"
        },
        roleGrantList: [],
        roleTreeObj: [],
        treeDeptId: '',
        treeData: [],
        treeOption: {
          nodeKey: 'id',
          lazy: true,
          treeLoad: function (node, resolve) {
            const parentId = (node.level === 0) ? 0 : node.data.id;
            getDeptLazyTree(parentId).then(res => {
              resolve(res.data.data.map(item => {
                return {
                  ...item,
                  leaf: !item.hasChildren
                }
              }))
            });
          },
          addBtn: false,
          menu: false,
          size: 'small',
          props: {
            labelText: '标题',
            label: 'title',
            value: 'value',
            children: 'children'
          }
        },
        option: {
          height: 'auto',
          calcHeight: 80,
          tip: false,
          searchShow: true,
          searchMenuSpan: 6,
          border: true,
          index: true,
          selection: true,
          menuWidth:250,
          viewBtn: true,
          dialogType: 'drawer',
          dialogClickModal: false,
          column: [
            {
              label: "登录账号",
              prop: "account",
              search: true,
              display: false
            },
            {
              label: "所属租户",
              prop: "tenantName",
              slot: true,
              display: false,
              hide: true
            },
            {
              label: "用户姓名",
              prop: "realName",
              search: true,
              display: false
            },
            {
              label: "所属角色",
              prop: "roleName",
              slot: true,
              display: false
            },
            {
              label: "所属单位",
              prop: "deptName",
              slot: true,
              display: false
            },
            {
              label: "用户平台",
              prop: "userTypeName",
              slot: true,
              display: false
            },
            {
              label: "用户平台",
              type: "select",
              dicUrl: "/api/blade-system/dict/dictionary?code=user_type",
              props: {
                label: "dictValue",
                value: "dictKey"
              },
              dataType: "number",
              search: true,
              hide: true,
              display: false,
              prop: "userType",
              rules: [{
                required: true,
                message: "请选择用户平台",
                trigger: "blur"
              }]
            },
          ],
          group: [
            {
              label: '基础信息',
              prop: 'baseInfo',
              icon: 'el-icon-user-solid',
              column: [
                {
                  label: "所属租户",
                  prop: "tenantId",
                  type: "tree",
                  dicUrl: "/api/blade-system/tenant/select",
                  props: {
                    label: "tenantName",
                    value: "tenantId"
                  },
                  hide: !website.tenantMode,
                  addDisplay: website.tenantMode,
                  editDisplay: website.tenantMode,
                  viewDisplay: website.tenantMode,
                  rules: [{
                    required: true,
                    message: "请输入所属租户",
                    trigger: "click"
                  }],
                  span: 24,
                },
                {
                  label: "登录账号",
                  prop: "account",
                  rules: [{
                    required: true,
                    message: "请输入登录账号",
                    trigger: "blur"
                  }],
                },
                {
                  label: "用户平台",
                  type: "select",
                  dicUrl: "/api/blade-system/dict/dictionary?code=user_type",
                  props: {
                    label: "dictValue",
                    value: "dictKey"
                  },
                  dataType: "number",
                  slot: true,
                  prop: "userType",
                  rules: [{
                    required: true,
                    message: "请选择用户平台",
                    trigger: "blur"
                  }]
                },
                {
                  label: '密码',
                  prop: 'password',
                  hide: true,
                  editDisplay: false,
                  viewDisplay: false,
                  rules: [{required: true, validator: validatePass, trigger: 'blur'}]
                },
                {
                  label: '确认密码',
                  prop: 'password2',
                  hide: true,
                  editDisplay: false,
                  viewDisplay: false,
                  rules: [{required: true, validator: validatePass2, trigger: 'blur'}]
                },
              ]
            },
            {
              label: '详细信息',
              prop: 'detailInfo',
              icon: 'el-icon-s-order',
              column: [
                {
                  label: "用户昵称",
                  prop: "name",
                  hide: true,
                  rules: [{
                    required: true,
                    message: "请输入用户昵称",
                    trigger: "blur"
                  }]
                },
                {
                  label: "用户姓名",
                  prop: "realName",
                  rules: [{
                    required: true,
                    message: "请输入用户姓名",
                    trigger: "blur"
                  }, {
                    min: 2,
                    max: 10,
                    message: '姓名长度在2到5个字符'
                  }]
                },
                {
                  label: "手机号码",
                  prop: "phone",
                  overHidden: true
                },
                {
                  label: "电子邮箱",
                  prop: "email",
                  hide: true,
                  overHidden: true
                },
                {
                  label: "用户性别",
                  prop: "sex",
                  type: "select",
                  dicData: [
                    {
                      label: "男",
                      value: 1
                    },
                    {
                      label: "女",
                      value: 2
                    },
                    {
                      label: "未知",
                      value: 3
                    }
                  ],
                  hide: true
                },
                {
                  label: "用户生日",
                  type: "date",
                  prop: "birthday",
                  format: "yyyy-MM-dd hh:mm:ss",
                  valueFormat: "yyyy-MM-dd hh:mm:ss",
                  hide: true
                },
                {
                  label: "账号状态",
                  prop: "statusName",
                  hide: true,
                  display: false
                }
              ]
            },
            {
              label: '职责信息',
              prop: 'dutyInfo',
              icon: 'el-icon-s-custom',
              column: [
                {
                  label: "用户编号",
                  prop: "code",
                },
                {
                  label: "所属角色",
                  prop: "roleId",
                  multiple: true,
                  type: "tree",
                  dicData: [],
                  props: {
                    label: "title"
                  },
                  /*control:() =>{
                    if (this.userInfo.role_name.indexOf("administrator")){
                      debugger
                      return{
                        roleId:{
                          disabled:true
                        }
                      }
                    }
                  },*/
                  checkStrictly: true,
                  slot: true,
                  rules: [{
                    required: true,
                    message: "请选择所属角色",
                    trigger: "click"
                  }]
                },
                {
                  label: "所属单位",
                  prop: "deptId",
                  type: "tree",
                  multiple: true,
                  dicData: [],
                  props: {
                    label: "title"
                  },
                  checkStrictly: true,
                  slot: true,
                  rules: [{
                    required: true,
                    message: "请选择所属单位",
                    trigger: "click"
                  }]
                },
/*                {
                  label: "所属岗位",
                  prop: "postId",
                  type: "tree",
                  multiple: true,
                  dicData: [],
                  props: {
                    label: "postName",
                    value: "id"
                  },
                  rules: [{
                    required: true,
                    message: "请选择所属岗位",
                    trigger: "click"
                  }],
                },*/
              ]
            },
          ]
        },
        data: [],
        platformQuery: {},
        platformSelectionList: [],
        platformData: [],
        platformForm: {},
        platformOption: {
          tip: false,
          searchShow: true,
          searchMenuSpan: 6,
          border: true,
          index: true,
          selection: true,
          viewBtn: true,
          dialogClickModal: false,
          menuWidth: 120,
          editBtnText: '配置',
          column: [
            {
              label: "登录账号",
              prop: "account",
              search: true,
              display: false
            },
            {
              label: "所属租户",
              prop: "tenantName",
              slot: true,
              display: false
            },
            {
              label: "用户姓名",
              prop: "realName",
              search: true,
              display: false
            },
            {
              label: "用户平台",
              prop: "userTypeName",
              slot: true,
              display: false
            },
            {
              label: "用户平台",
              type: "select",
              dicUrl: "/api/blade-system/dict/dictionary?code=user_type",
              props: {
                label: "dictValue",
                value: "dictKey"
              },
              dataType: "number",
              search: true,
              hide: true,
              display: false,
              prop: "userType",
              rules: [{
                required: true,
                message: "请选择用户平台",
                trigger: "blur"
              }]
            },
            {
              label: "用户拓展",
              prop: "userExt",
              type: "textarea",
              minRows: 8,
              span: 24,
              overHidden: true,
              row: true,
              hide: true,
            },
          ],
        },
        excelForm: {},
        excelOption: {
          submitBtn: false,
          emptyBtn: false,
          column: [
            {
              label: '模板上传',
              prop: 'excelFile',
              type: 'upload',
              drag: true,
              loadText: '模板上传中,请稍等',
              span: 24,
              propsHttp: {
                res: 'data'
              },
              tip: '请上传 .xls,.xlsx 标准格式文件',
              action: "/api/blade-user/import-user"
            },
            {
              label: "数据覆盖",
              prop: "isCovered",
              type: "switch",
              align: "center",
              width: 80,
              dicData: [
                {
                  label: "否",
                  value: 0
                },
                {
                  label: "是",
                  value: 1
                }
              ],
              value: 0,
              slot: true,
              rules: [
                {
                  required: true,
                  message: "请选择是否覆盖",
                  trigger: "blur"
                }
              ]
            },
            {
              label: '模板下载',
              prop: 'excelTemplate',
              formslot: true,
              span: 24,
export default {
    data () {
        const validatePass = (rule, value, callback) => {
            if (value === '') {
                callback(new Error('请输入密码'))
            } else {
                callback()
            }
          ]
        }
      };
        const validatePass2 = (rule, value, callback) => {
            if (value === '') {
                callback(new Error('请再次输入密码'))
            } else if (value !== this.form.password) {
                callback(new Error('两次输入密码不一致!'))
            } else {
                callback()
            }
        }
        return {
            form: {},
            search: {},
            roleBox: false,
            excelBox: false,
            platformBox: false,
            initFlag: true,
            selectionList: [],
            query: {},
            loading: true,
            platformLoading: false,
            page: {
                pageSize: 10,
                currentPage: 1,
                total: 0
            },
            platformPage: {
                pageSize: 10,
                currentPage: 1,
                total: 0
            },
            init: {
                roleTree: [],
                deptTree: [],
            },
            props: {
                label: "title",
                value: "key"
            },
            roleGrantList: [],
            roleTreeObj: [],
            treeDeptId: '',
            treeData: [],
            treeOption: {
                nodeKey: 'id',
                lazy: true,
                treeLoad: function (node, resolve) {
                    const parentId = (node.level === 0) ? 0 : node.data.id
                    getDeptLazyTree(parentId).then(res => {
                        resolve(res.data.data.map(item => {
                            return {
                                ...item,
                                leaf: !item.hasChildren
                            }
                        }))
                    })
                },
                addBtn: false,
                menu: false,
                size: 'small',
                props: {
                    labelText: '标题',
                    label: 'title',
                    value: 'value',
                    children: 'children'
                }
            },
            option: {
                height: 'auto',
                calcHeight: 80,
                tip: false,
                searchShow: true,
                searchMenuSpan: 6,
                border: true,
                index: true,
                selection: true,
                menuWidth: 250,
                viewBtn: true,
                dialogType: 'drawer',
                dialogClickModal: false,
                column: [
                    {
                        label: "登录账号",
                        prop: "account",
                        search: true,
                        display: false
                    },
                    {
                        label: "所属租户",
                        prop: "tenantName",
                        slot: true,
                        display: false,
                        hide: true
                    },
                    {
                        label: "用户姓名",
                        prop: "realName",
                        search: true,
                        display: false
                    },
                    {
                        label: "所属角色",
                        prop: "roleName",
                        slot: true,
                        display: false
                    },
                    {
                        label: "所属单位",
                        prop: "deptName",
                        slot: true,
                        display: false
                    },
                    {
                        label: "用户平台",
                        prop: "userTypeName",
                        slot: true,
                        display: false
                    },
                    {
                        label: "用户平台",
                        type: "select",
                        dicUrl: "/api/blade-system/dict/dictionary?code=user_type",
                        props: {
                            label: "dictValue",
                            value: "dictKey"
                        },
                        dataType: "number",
                        search: true,
                        hide: true,
                        display: false,
                        prop: "userType",
                        rules: [{
                            required: true,
                            message: "请选择用户平台",
                            trigger: "blur"
                        }]
                    },
                ],
                group: [
                    {
                        label: '基础信息',
                        prop: 'baseInfo',
                        icon: 'el-icon-user-solid',
                        column: [
                            {
                                label: "所属租户",
                                prop: "tenantId",
                                type: "tree",
                                dicUrl: "/api/blade-system/tenant/select",
                                props: {
                                    label: "tenantName",
                                    value: "tenantId"
                                },
                                hide: !website.tenantMode,
                                addDisplay: website.tenantMode,
                                editDisplay: website.tenantMode,
                                viewDisplay: website.tenantMode,
                                rules: [{
                                    required: true,
                                    message: "请输入所属租户",
                                    trigger: "click"
                                }],
                                span: 24,
                            },
                            {
                                label: "登录账号",
                                prop: "account",
                                rules: [{
                                    required: true,
                                    message: "请输入登录账号",
                                    trigger: "blur"
                                }],
                            },
                            {
                                label: "用户平台",
                                type: "select",
                                dicUrl: "/api/blade-system/dict/dictionary?code=user_type",
                                props: {
                                    label: "dictValue",
                                    value: "dictKey"
                                },
                                dataType: "number",
                                slot: true,
                                prop: "userType",
                                rules: [{
                                    required: true,
                                    message: "请选择用户平台",
                                    trigger: "blur"
                                }]
                            },
                            {
                                label: '密码',
                                prop: 'password',
                                hide: true,
                                editDisplay: false,
                                viewDisplay: false,
                                rules: [{ required: true, validator: validatePass, trigger: 'blur' }]
                            },
                            {
                                label: '确认密码',
                                prop: 'password2',
                                hide: true,
                                editDisplay: false,
                                viewDisplay: false,
                                rules: [{ required: true, validator: validatePass2, trigger: 'blur' }]
                            },
                        ]
                    },
                    {
                        label: '详细信息',
                        prop: 'detailInfo',
                        icon: 'el-icon-s-order',
                        column: [
                            {
                                label: "用户昵称",
                                prop: "name",
                                hide: true,
                                rules: [{
                                    required: true,
                                    message: "请输入用户昵称",
                                    trigger: "blur"
                                }]
                            },
                            {
                                label: "用户姓名",
                                prop: "realName",
                                rules: [{
                                    required: true,
                                    message: "请输入用户姓名",
                                    trigger: "blur"
                                }, {
                                    min: 2,
                                    max: 10,
                                    message: '姓名长度在2到5个字符'
                                }]
                            },
                            {
                                label: "手机号码",
                                prop: "phone",
                                overHidden: true
                            },
                            {
                                label: "电子邮箱",
                                prop: "email",
                                hide: true,
                                overHidden: true
                            },
                            {
                                label: "用户性别",
                                prop: "sex",
                                type: "select",
                                dicData: [
                                    {
                                        label: "男",
                                        value: 1
                                    },
                                    {
                                        label: "女",
                                        value: 2
                                    },
                                    {
                                        label: "未知",
                                        value: 3
                                    }
                                ],
                                hide: true
                            },
                            {
                                label: "用户生日",
                                type: "date",
                                prop: "birthday",
                                format: "yyyy-MM-dd hh:mm:ss",
                                valueFormat: "yyyy-MM-dd hh:mm:ss",
                                hide: true
                            },
                            {
                                label: "账号状态",
                                prop: "statusName",
                                hide: true,
                                display: false
                            }
                        ]
                    },
                    {
                        label: '职责信息',
                        prop: 'dutyInfo',
                        icon: 'el-icon-s-custom',
                        column: [
                            {
                                label: "用户编号",
                                prop: "code",
                            },
                            {
                                label: "所属角色",
                                prop: "roleId",
                                multiple: true,
                                type: "tree",
                                dicData: [],
                                props: {
                                    label: "title"
                                },
                                /*control:() =>{
                                  if (this.userInfo.role_name.indexOf("administrator")){
                                    debugger
                                    return{
                                      roleId:{
                                        disabled:true
                                      }
                                    }
                                  }
                                },*/
                                checkStrictly: true,
                                slot: true,
                                rules: [{
                                    required: true,
                                    message: "请选择所属角色",
                                    trigger: "click"
                                }]
                            },
                            {
                                label: "所属单位",
                                prop: "deptId",
                                type: "tree",
                                multiple: true,
                                dicData: [],
                                props: {
                                    label: "title"
                                },
                                checkStrictly: true,
                                slot: true,
                                rules: [{
                                    required: true,
                                    message: "请选择所属单位",
                                    trigger: "click"
                                }]
                            },
                            /*                {
                                              label: "所属岗位",
                                              prop: "postId",
                                              type: "tree",
                                              multiple: true,
                                              dicData: [],
                                              props: {
                                                label: "postName",
                                                value: "id"
                                              },
                                              rules: [{
                                                required: true,
                                                message: "请选择所属岗位",
                                                trigger: "click"
                                              }],
                                            },*/
                        ]
                    },
                ]
            },
            data: [],
            platformQuery: {},
            platformSelectionList: [],
            platformData: [],
            platformForm: {},
            platformOption: {
                tip: false,
                searchShow: true,
                searchMenuSpan: 6,
                border: true,
                index: true,
                selection: true,
                viewBtn: true,
                dialogClickModal: false,
                menuWidth: 120,
                editBtnText: '配置',
                column: [
                    {
                        label: "登录账号",
                        prop: "account",
                        search: true,
                        display: false
                    },
                    {
                        label: "所属租户",
                        prop: "tenantName",
                        slot: true,
                        display: false
                    },
                    {
                        label: "用户姓名",
                        prop: "realName",
                        search: true,
                        display: false
                    },
                    {
                        label: "用户平台",
                        prop: "userTypeName",
                        slot: true,
                        display: false
                    },
                    {
                        label: "用户平台",
                        type: "select",
                        dicUrl: "/api/blade-system/dict/dictionary?code=user_type",
                        props: {
                            label: "dictValue",
                            value: "dictKey"
                        },
                        dataType: "number",
                        search: true,
                        hide: true,
                        display: false,
                        prop: "userType",
                        rules: [{
                            required: true,
                            message: "请选择用户平台",
                            trigger: "blur"
                        }]
                    },
                    {
                        label: "用户拓展",
                        prop: "userExt",
                        type: "textarea",
                        minRows: 8,
                        span: 24,
                        overHidden: true,
                        row: true,
                        hide: true,
                    },
                ],
            },
            excelForm: {},
            excelOption: {
                submitBtn: false,
                emptyBtn: false,
                column: [
                    {
                        label: '模板上传',
                        prop: 'excelFile',
                        type: 'upload',
                        drag: true,
                        loadText: '模板上传中,请稍等',
                        span: 24,
                        propsHttp: {
                            res: 'data'
                        },
                        tip: '请上传 .xls,.xlsx 标准格式文件',
                        action: "/api/blade-user/import-user"
                    },
                    {
                        label: "数据覆盖",
                        prop: "isCovered",
                        type: "switch",
                        align: "center",
                        width: 80,
                        dicData: [
                            {
                                label: "否",
                                value: 0
                            },
                            {
                                label: "是",
                                value: 1
                            }
                        ],
                        value: 0,
                        slot: true,
                        rules: [
                            {
                                required: true,
                                message: "请选择是否覆盖",
                                trigger: "blur"
                            }
                        ]
                    },
                    {
                        label: '模板下载',
                        prop: 'excelTemplate',
                        formslot: true,
                        span: 24,
                    }
                ]
            }
        }
    },
    watch: {
      'form.tenantId'() {
        if (this.form.tenantId !== '' && this.initFlag) {
          this.initData(this.form.tenantId);
        'form.tenantId' () {
            if (this.form.tenantId !== '' && this.initFlag) {
                this.initData(this.form.tenantId)
            }
        },
        'excelForm.isCovered' () {
            if (this.excelForm.isCovered !== '') {
                const column = this.findObject(this.excelOption.column, "excelFile")
                column.action = `/api/blade-user/import-user?isCovered=${this.excelForm.isCovered}`
            }
        }
      },
      'excelForm.isCovered'() {
        if (this.excelForm.isCovered !== '') {
          const column = this.findObject(this.excelOption.column, "excelFile");
          column.action = `/api/blade-user/import-user?isCovered=${this.excelForm.isCovered}`;
        }
      }
    },
    computed: {
      ...mapGetters(["userInfo", "permission"]),
      permissionList() {
        return {
          addBtn: this.vaildData(this.permission.user_add, false),
          viewBtn: this.vaildData(this.permission.user_view, false),
          delBtn: this.vaildData(this.permission.user_delete, false),
          editBtn: this.vaildData(this.permission.user_edit, false)
        };
      },
      platformPermissionList() {
        return {
          addBtn: false,
          viewBtn: false,
          delBtn: false,
          editBtn: this.vaildData(this.permission.user_edit, false)
        };
      },
      ids() {
        let ids = [];
        this.selectionList.forEach(ele => {
          ids.push(ele.id);
        });
        return ids.join(",");
      },
        ...mapGetters(["userInfo", "permission"]),
        permissionList () {
            return {
                addBtn: this.vaildData(this.permission.user_add, false),
                viewBtn: this.vaildData(this.permission.user_view, false),
                delBtn: this.vaildData(this.permission.user_delete, false),
                editBtn: this.vaildData(this.permission.user_edit, false)
            }
        },
        platformPermissionList () {
            return {
                addBtn: false,
                viewBtn: false,
                delBtn: false,
                editBtn: this.vaildData(this.permission.user_edit, false)
            }
        },
        ids () {
            let ids = []
            this.selectionList.forEach(ele => {
                ids.push(ele.id)
            })
            return ids.join(",")
        },
    },
    mounted() {
      // 非租户模式默认加载管理组数据
      if (!website.tenantMode) {
        this.initData(website.tenantId);
      }
    mounted () {
        // 非租户模式默认加载管理组数据
        if (!website.tenantMode) {
            this.initData(website.tenantId)
        }
    },
    methods: {
      nodeClick(data) {
        this.treeDeptId = data.id;
        this.page.currentPage = 1;
        this.onLoad(this.page);
      },
      initData(tenantId) {
        getRoleTree(tenantId).then(res => {
          const column = this.findObject(this.option.group, "roleId");
          res.data.data[0].disabled = true;
          // res.data.data[1].disabled = true;
          column.dicData = res.data.data;
        });
        getDeptTree(tenantId).then(res => {
          const column = this.findObject(this.option.group, "deptId");
          column.dicData = res.data.data;
        });
        //getPostList(tenantId).then(res => {
        //  const column = this.findObject(this.option.group, "postId");
        //  column.dicData = res.data.data;
        //});
      },
      submitRole() {
        const roleList = this.$refs.treeRole.getCheckedKeys().join(",");
        grant(this.ids, roleList).then(() => {
          this.roleBox = false;
          this.$message({
            type: "success",
            message: "操作成功!"
          });
          this.onLoad(this.page);
        });
      },
      rowSave(row, done, loading) {
        row.deptId = row.deptId.join(",");
        row.roleId = row.roleId.join(",");
        // row.postId = row.postId.join(",");
        row.postId = '';
        add(row).then(() => {
          this.initFlag = false;
          this.onLoad(this.page);
          this.$message({
            type: "success",
            message: "操作成功!"
          });
          done();
        }, error => {
          window.console.log(error);
          loading();
        });
      },
      rowUpdate(row, index, done, loading) {
        row.deptId = row.deptId.join(",");
        row.roleId = row.roleId.join(",");
        // row.postId = row.postId.join(",");
        row.postId = '';
        update(row).then(() => {
          this.initFlag = false;
          this.onLoad(this.page);
          this.$message({
            type: "success",
            message: "操作成功!"
          });
          done();
        }, error => {
          window.console.log(error);
          loading();
        });
      },
      rowDel(row) {
        this.$confirm("确定将选择数据删除?", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning"
        })
          .then(() => {
            return remove(row.id);
          })
          .then(() => {
            this.onLoad(this.page);
            this.$message({
              type: "success",
              message: "操作成功!"
            });
          });
      },
      searchReset() {
        this.query = {};
        this.treeDeptId = '';
        this.onLoad(this.page);
      },
      searchChange(params, done) {
        this.query = params;
        this.page.currentPage = 1;
        this.onLoad(this.page, params);
        done();
      },
      selectionChange(list) {
        this.selectionList = list;
      },
      selectionClear() {
        this.selectionList = [];
        this.$refs.crud.toggleSelection();
      },
      handleDelete() {
        if (this.selectionList.length === 0) {
          this.$message.warning("请选择至少一条数据");
          return;
        }
        this.$confirm("确定将选择数据删除?", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning"
        })
          .then(() => {
            return remove(this.ids);
          })
          .then(() => {
            this.onLoad(this.page);
            this.$message({
              type: "success",
              message: "操作成功!"
            });
            this.$refs.crud.toggleSelection();
          });
      },
      handleReset() {
        if (this.selectionList.length === 0) {
          this.$message.warning("请选择至少一条数据");
          return;
        }
        this.$confirm("确定将选择账号密码重置为123456?", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning"
        })
          .then(() => {
            return resetPassword(this.ids);
          })
          .then(() => {
            this.$message({
              type: "success",
              message: "操作成功!"
            });
            this.$refs.crud.toggleSelection();
          });
      },
      handleGrant() {
        if (this.selectionList.length === 0) {
          this.$message.warning("请选择至少一条数据");
          return;
        }
        this.roleTreeObj = [];
        if (this.selectionList.length === 1) {
          this.roleTreeObj = this.selectionList[0].roleId.split(",");
        }
        getRoleTree().then(res => {
          this.roleGrantList = res.data.data;
          this.roleBox = true;
        });
      },
      handlePlatform() {
        this.platformBox = true;
      },
      handleLock() {
        if (this.selectionList.length === 0) {
          this.$message.warning("请选择至少一条数据");
          return;
        }
        this.$confirm("确定将选择账号解封?", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning"
        })
          .then(() => {
            return unlock(this.ids);
          })
          .then(() => {
            this.$message({
              type: "success",
              message: "操作成功!"
            });
          });
      },
      handleImport() {
        this.excelBox = true;
      },
      uploadAfter(res, done, loading, column) {
        window.console.log(column);
        this.excelBox = false;
        this.refreshChange();
        done();
      },
      handleExport() {
        const account = func.toStr(this.search.account);
        const realName = func.toStr(this.search.realName);
        this.$confirm("是否导出用户数据?", "提示", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning"
        }).then(() => {
          NProgress.start();
          exportBlob(`/api/blade-user/export-user?${this.website.tokenHeader}=${getToken()}&account=${account}&realName=${realName}`).then(res => {
            downloadXls(res.data, `用户数据表${dateNow()}.xlsx`);
            NProgress.done();
          })
        });
      },
      handleTemplate() {
        exportBlob(`/api/blade-user/export-template?${this.website.tokenHeader}=${getToken()}`).then(res => {
          downloadXls(res.data, "用户数据模板.xlsx");
        })
      },
      beforeOpen(done, type) {
        if (["edit", "view"].indexOf(type)) {
          getUser(this.form.id).then(res => {
            this.form = res.data.data;
            if(this.form.hasOwnProperty("deptId")){
              this.form.deptId = this.form.deptId.split(",");
        nodeClick (data) {
            this.treeDeptId = data.id
            this.page.currentPage = 1
            this.onLoad(this.page)
        },
        initData (tenantId) {
            getRoleTree(tenantId).then(res => {
                const column = this.findObject(this.option.group, "roleId")
                res.data.data[0].disabled = true
                // res.data.data[1].disabled = true;
                column.dicData = res.data.data
            })
            getDeptTree(tenantId).then(res => {
                const column = this.findObject(this.option.group, "deptId")
                column.dicData = res.data.data
            })
            //getPostList(tenantId).then(res => {
            //  const column = this.findObject(this.option.group, "postId");
            //  column.dicData = res.data.data;
            //});
        },
        submitRole () {
            const roleList = this.$refs.treeRole.getCheckedKeys().join(",")
            grant(this.ids, roleList).then(() => {
                this.roleBox = false
                this.$message({
                    type: "success",
                    message: "操作成功!"
                })
                this.onLoad(this.page)
            })
        },
        rowSave (row, done, loading) {
            row.deptId = row.deptId.join(",")
            row.roleId = row.roleId.join(",")
            // row.postId = row.postId.join(",");
            row.postId = ''
            add(row).then(() => {
                this.initFlag = false
                this.onLoad(this.page)
                this.$message({
                    type: "success",
                    message: "操作成功!"
                })
                done()
            }, error => {
                window.console.log(error)
                loading()
            })
        },
        rowUpdate (row, index, done, loading) {
            row.deptId = row.deptId.join(",")
            row.roleId = row.roleId.join(",")
            // row.postId = row.postId.join(",");
            row.postId = ''
            update(row).then(() => {
                this.initFlag = false
                this.onLoad(this.page)
                this.$message({
                    type: "success",
                    message: "操作成功!"
                })
                done()
            }, error => {
                window.console.log(error)
                loading()
            })
        },
        rowDel (row) {
            this.$confirm("确定将选择数据删除?", {
                confirmButtonText: "确定",
                cancelButtonText: "取消",
                type: "warning"
            })
                .then(() => {
                    return remove(row.id)
                })
                .then(() => {
                    this.onLoad(this.page)
                    this.$message({
                        type: "success",
                        message: "操作成功!"
                    })
                })
        },
        searchReset () {
            this.query = {}
            this.treeDeptId = ''
            this.onLoad(this.page)
        },
        searchChange (params, done) {
            this.query = params
            this.page.currentPage = 1
            this.onLoad(this.page, params)
            done()
        },
        selectionChange (list) {
            this.selectionList = list
        },
        selectionClear () {
            this.selectionList = []
            this.$refs.crud.toggleSelection()
        },
        handleDelete () {
            if (this.selectionList.length === 0) {
                this.$message.warning("请选择至少一条数据")
                return
            }
            if(this.form.hasOwnProperty("roleId")){
              this.form.roleId = this.form.roleId.split(",");
            this.$confirm("确定将选择数据删除?", {
                confirmButtonText: "确定",
                cancelButtonText: "取消",
                type: "warning"
            })
                .then(() => {
                    return remove(this.ids)
                })
                .then(() => {
                    this.onLoad(this.page)
                    this.$message({
                        type: "success",
                        message: "操作成功!"
                    })
                    this.$refs.crud.toggleSelection()
                })
        },
        handleReset () {
            if (this.selectionList.length === 0) {
                this.$message.warning("请选择至少一条数据")
                return
            }
            if(this.form.hasOwnProperty("postId")){
              this.form.postId = this.form.postId.split(",");
            this.$confirm("确定将选择账号密码重置为123456?", {
                confirmButtonText: "确定",
                cancelButtonText: "取消",
                type: "warning"
            })
                .then(() => {
                    return resetPassword(this.ids)
                })
                .then(() => {
                    this.$message({
                        type: "success",
                        message: "操作成功!"
                    })
                    this.$refs.crud.toggleSelection()
                })
        },
        handleGrant () {
            if (this.selectionList.length === 0) {
                this.$message.warning("请选择至少一条数据")
                return
            }
          });
        }
        this.initFlag = true;
        done();
      },
      currentChange(currentPage) {
        this.page.currentPage = currentPage;
      },
      sizeChange(pageSize) {
        this.page.pageSize = pageSize;
      },
      refreshChange() {
        this.onLoad(this.page, this.query);
      },
      onLoad(page, params = {}) {
        this.loading = true;
            this.roleTreeObj = []
            if (this.selectionList.length === 1) {
                this.roleTreeObj = this.selectionList[0].roleId.split(",")
            }
            getRoleTree().then(res => {
                this.roleGrantList = res.data.data
                this.roleBox = true
            })
        },
        handlePlatform () {
            this.platformBox = true
        },
        handleLock () {
            if (this.selectionList.length === 0) {
                this.$message.warning("请选择至少一条数据")
                return
            }
            this.$confirm("确定将选择账号解封?", {
                confirmButtonText: "确定",
                cancelButtonText: "取消",
                type: "warning"
            })
                .then(() => {
                    return unlock(this.ids)
                })
                .then(() => {
                    this.$message({
                        type: "success",
                        message: "操作成功!"
                    })
                })
        },
        handleImport () {
            this.excelBox = true
        },
        uploadAfter (res, done, loading, column) {
            window.console.log(column)
            this.excelBox = false
            this.refreshChange()
            done()
        },
        handleExport () {
            const account = func.toStr(this.search.account)
            const realName = func.toStr(this.search.realName)
            this.$confirm("是否导出用户数据?", "提示", {
                confirmButtonText: "确定",
                cancelButtonText: "取消",
                type: "warning"
            }).then(() => {
                NProgress.start()
                exportBlob(`/api/blade-user/export-user?${this.website.tokenHeader}=${getToken()}&account=${account}&realName=${realName}`).then(res => {
                    downloadXls(res.data, `用户数据表${dateNow()}.xlsx`)
                    NProgress.done()
                })
            })
        },
        handleTemplate () {
            exportBlob(`/api/blade-user/export-template?${this.website.tokenHeader}=${getToken()}`).then(res => {
                downloadXls(res.data, "用户数据模板.xlsx")
            })
        },
        beforeOpen (done, type) {
            if (["edit", "view"].indexOf(type)) {
                getUser(this.form.id).then(res => {
                    this.form = res.data.data
                    if (this.form.hasOwnProperty("deptId")) {
                        this.form.deptId = this.form.deptId.split(",")
                    }
                    if (this.form.hasOwnProperty("roleId")) {
                        this.form.roleId = this.form.roleId.split(",")
                    }
                    if (this.form.hasOwnProperty("postId")) {
                        this.form.postId = this.form.postId.split(",")
                    }
                })
            }
            this.initFlag = true
            done()
        },
        currentChange (currentPage) {
            this.page.currentPage = currentPage
        },
        sizeChange (pageSize) {
            this.page.pageSize = pageSize
        },
        refreshChange () {
            this.onLoad(this.page, this.query)
        },
        onLoad (page, params = {}) {
            this.loading = true
        if (this.userInfo.role_name != "admin" && this.userInfo.role_name != "administrator"){
          params["jurisdiction"] = this.userInfo.dept_id;
        }
            if (this.userInfo.role_name != "admin" && this.userInfo.role_name != "administrator") {
                params["jurisdiction"] = this.userInfo.dept_id
            }
        getList(page.currentPage, page.pageSize, Object.assign(params, this.query), this.treeDeptId).then(res => {
          const data = res.data.data;
          this.page.total = data.total;
          this.data = data.records;
          this.loading = false;
          this.selectionClear();
        });
      },
      platformRowUpdate(row, index, done, loading) {
        updatePlatform(row.id, row.userType, row.userExt).then(() => {
          this.platformOnLoad(this.platformPage);
          this.$message({
            type: "success",
            message: "操作成功!"
          });
          done();
        }, error => {
          window.console.log(error);
          loading();
        });
      },
      platformBeforeOpen(done, type) {
        if (["edit", "view"].indexOf(type)) {
          getUserPlatform(this.platformForm.id).then(res => {
            this.platformForm = res.data.data;
          });
            getList(page.currentPage, page.pageSize, Object.assign(params, this.query), this.treeDeptId).then(res => {
                const data = res.data.data
                this.page.total = data.total
                this.data = data.records
                this.loading = false
                this.selectionClear()
            })
        },
        platformRowUpdate (row, index, done, loading) {
            updatePlatform(row.id, row.userType, row.userExt).then(() => {
                this.platformOnLoad(this.platformPage)
                this.$message({
                    type: "success",
                    message: "操作成功!"
                })
                done()
            }, error => {
                window.console.log(error)
                loading()
            })
        },
        platformBeforeOpen (done, type) {
            if (["edit", "view"].indexOf(type)) {
                getUserPlatform(this.platformForm.id).then(res => {
                    this.platformForm = res.data.data
                })
            }
            done()
        },
        platformSearchReset () {
            this.platformQuery = {}
            this.platformOnLoad(this.platformPage)
        },
        platformSearchChange (params, done) {
            this.platformQuery = params
            this.platformPage.currentPage = 1
            this.platformOnLoad(this.platformPage, params)
            done()
        },
        platformSelectionChange (list) {
            this.platformSelectionList = list
        },
        platformSelectionClear () {
            this.platformSelectionList = []
            this.$refs.platformCrud.toggleSelection()
        },
        platformCurrentChange (currentPage) {
            this.platformPage.currentPage = currentPage
        },
        platformSizeChange (pageSize) {
            this.platformPage.pageSize = pageSize
        },
        platformRefreshChange () {
            this.platformOnLoad(this.platformPage, this.platformQuery)
        },
        platformOnLoad (page, params = {}) {
            this.platformLoading = true
            getList(page.currentPage, page.pageSize, Object.assign(params, this.query), this.treeDeptId).then(res => {
                const data = res.data.data
                this.platformPage.total = data.total
                this.platformData = data.records
                this.platformLoading = false
                this.selectionClear()
            })
        }
        done();
      },
      platformSearchReset() {
        this.platformQuery = {};
        this.platformOnLoad(this.platformPage);
      },
      platformSearchChange(params, done) {
        this.platformQuery = params;
        this.platformPage.currentPage = 1;
        this.platformOnLoad(this.platformPage, params);
        done();
      },
      platformSelectionChange(list) {
        this.platformSelectionList = list;
      },
      platformSelectionClear() {
        this.platformSelectionList = [];
        this.$refs.platformCrud.toggleSelection();
      },
      platformCurrentChange(currentPage) {
        this.platformPage.currentPage = currentPage;
      },
      platformSizeChange(pageSize) {
        this.platformPage.pageSize = pageSize;
      },
      platformRefreshChange() {
        this.platformOnLoad(this.platformPage, this.platformQuery);
      },
      platformOnLoad(page, params = {}) {
        this.platformLoading = true;
        getList(page.currentPage, page.pageSize, Object.assign(params, this.query), this.treeDeptId).then(res => {
          const data = res.data.data;
          this.platformPage.total = data.total;
          this.platformData = data.records;
          this.platformLoading = false;
          this.selectionClear();
        });
      }
    }
  };
}
</script>
<style>
  .box {
.box {
    height: 800px;
  }
}
  .el-scrollbar {
.el-scrollbar {
    height: 100%;
  }
}
  .box .el-scrollbar__wrap {
.box .el-scrollbar__wrap {
    overflow: scroll;
  }
}
</style>
vue.config.js
@@ -1,39 +1,49 @@
/*
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2023-02-06 10:34:02
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2023-02-07 10:00:48
 * @FilePath: \srs-police-web\vue.config.js
 * @Description:
 *
 * Copyright (c) 2023 by ${git_name_email}, All Rights Reserved.
 */
module.exports = {
  //路径前缀
  publicPath: "/",
  lintOnSave: true,
  productionSourceMap: false,
  chainWebpack: (config) => {
    //忽略的打包文件
    config.externals({
      'vue': 'Vue',
      'vue-router': 'VueRouter',
      'vuex': 'Vuex',
      'axios': 'axios',
      'element-ui': 'ELEMENT',
    });
    const entry = config.entry('app');
    entry.add('babel-polyfill').end();
    entry.add('classlist-polyfill').end();
    entry.add('@/mock').end();
  },
  css: {
    extract: { ignoreOrder: true }
  },
  //开发模式反向代理配置,生产模式请使用Nginx部署并配置反向代理
  devServer: {
    port: 1888,
    proxy: {
      '/api': {
        //本地服务接口地址
        target: 'http://localhost:82/',
        //远程演示服务地址,可用于直接启动项目
        //target: 'https://saber.bladex.vip/api',
        ws: true,
        pathRewrite: {
          '^/api': '/'
    //路径前缀
    publicPath: "/",
    lintOnSave: true,
    productionSourceMap: false,
    chainWebpack: (config) => {
        //忽略的打包文件
        config.externals({
            'vue': 'Vue',
            'vue-router': 'VueRouter',
            'vuex': 'Vuex',
            'axios': 'axios',
            'element-ui': 'ELEMENT',
        })
        const entry = config.entry('app')
        entry.add('babel-polyfill').end()
        entry.add('classlist-polyfill').end()
        entry.add('@/mock').end()
    },
    css: {
        extract: { ignoreOrder: true }
    },
    //开发模式反向代理配置,生产模式请使用Nginx部署并配置反向代理
    devServer: {
        port: 1888,
        proxy: {
            '/api': {
                //本地服务接口地址
                target: 'http://192.168.43.199:82',
                //远程演示服务地址,可用于直接启动项目
                //target: 'https://saber.bladex.vip/api',
                ws: true,
                pathRewrite: {
                    '^/api': '/'
                }
            }
        }
      }
    }
  }
};
}