类名 common/view/BaseView.js
import { LayerEvent, Event, Evented, Collection, Projection } from '../base'
import { Log, defaultValue } from '../util'
import { LayerEventType, LayerType, MapEventType } from '../base/enum'
import { Layer, TileInfoUtil } from '../document/layer'
import LayerView from './LayerView'
import { Extent, Point, SpatialReference } from '../base/geometry'
import Map from '../document/mapCollection/Map'

/**
 * 视图类
 * @class BaseView
 * @extends Event
 * @moduleEX ViewModule
 * @param {Object} options 构造参数
 * @param {Map}  [options.map = '']  图层管理器
 * @param {String} [options.viewId = ''] 图层容器ID
 */

/**
 * @event BaseView#地图视图加载完毕事件
 * @property {Object} event 事件对象
 * @example <caption><h7>地图视图加载完毕事件</h7></caption>
 * view.on('loaded', (event) => {
 *   console.log("点击事件:", event)
 * })
 */

/**
 * @event BaseView#鼠标点击事件
 * @property {Object} event 事件对象
 * @property {LayerEventType} [event.type = 'click'] 事件类型
 * @property {Object} [event.mapPoint] 鼠标在地图上的经纬度位置
 * @property {Object} [event.x] 鼠标的像素x坐标,单位px
 * @property {Object} [event.y] 鼠标的像素y坐标,单位px
 * @property {Number} [event.button]
 * @property {Number} [event.buttons]
 * @property {Function} [event.stopPropagation] 阻止事件捕获或冒泡
 * @property {Object} [event.timeStamp] 时间戳,单位ms
 * @property {Object} [event.native] 事件对象
 * @property {BaseView} [event.sourceTarget] 事件发起对象
 * @property {Map} [event.target] 事件接收对象
 * @example <caption><h7>鼠标点击事件</h7></caption>
 * view.on('click', (event) => {
 *   console.log("点击事件:", event)
 * })
 */

/**
 * @event BaseView#鼠标点击事件
 * @property {Object} event 事件对象
 * @property {LayerEventType} [event.type = 'immediate-click'] 事件类型
 * @property {Object} [event.mapPoint] 鼠标在地图上的经纬度位置
 * @property {Object} [event.x] 鼠标的像素x坐标,单位px
 * @property {Object} [event.y] 鼠标的像素y坐标,单位px
 * @property {Number} [event.button]
 * @property {Number} [event.buttons]
 * @property {Function} [event.stopPropagation] 阻止事件捕获或冒泡
 * @property {Object} [event.timeStamp] 时间戳,单位ms
 * @property {Object} [event.native] 事件对象
 * @property {BaseView} [event.sourceTarget] 事件发起对象
 * @property {Map} [event.target] 事件接收对象
 * @example <caption><h7>鼠标立即点击事件</h7></caption>
 * view.on('immediate-click', (event) => {
 *   console.log("点击事件:", event)
 * })
 */

/**
 * @event BaseView#鼠标双击事件
 * @property {Object} event 事件对象
 * @property {LayerEventType} [event.type = 'double-click'] 事件类型
 * @property {Object} [event.mapPoint] 鼠标在地图上的经纬度位置
 * @property {Object} [event.longitude] 鼠标的经度坐标,单位度
 * @property {Object} [event.latitude] 鼠标的纬度坐标,单位度
 * @property {Object} [event.x] 鼠标的像素x坐标,单位px
 * @property {Object} [event.y] 鼠标的像素y坐标,单位px
 * @property {Object} [event.timeStamp] 时间戳,单位ms
 * @property {BaseView} [event.sourceTarget] 事件发起对象
 * @property {Map} [event.target] 事件接收对象
 * @property {Object} [event.event] 事件对象
 * @example <caption><h7>鼠标双击事件</h7></caption>
 * view.on('double-click', (event) => {
 *   console.log("双击事件:", event)
 * })
 */

/**
 * @event BaseView#鼠标按下事件
 * @property {Object} event 事件对象
 * @property {LayerEventType} [event.type = 'pointer-down'] 事件类型
 * @property {Object} [event.mapPoint] 鼠标在地图上的经纬度位置
 * @property {Object} [event.longitude] 鼠标的经度坐标,单位度
 * @property {Object} [event.latitude] 鼠标的纬度坐标,单位度
 * @property {Object} [event.x] 鼠标的像素x坐标,单位px
 * @property {Object} [event.y] 鼠标的像素y坐标,单位px
 * @property {Object} [event.timeStamp] 时间戳,单位ms
 * @property {BaseView} [event.sourceTarget] 事件发起对象
 * @property {Map} [event.target] 事件接收对象
 * @property {Object} [event.event] 事件对象
 * @example <caption><h7>鼠标按下事件</h7></caption>
 * view.on('pointer-down', (event) => {
 *   console.log("鼠标按下事件:", event)
 * })
 */

/**
 * @event BaseView#鼠标抬起事件
 * @property {Object} event 事件对象
 * @property {LayerEventType} [event.type = 'pointer-up'] 事件类型
 * @property {Object} [event.mapPoint] 鼠标在地图上的经纬度位置
 * @property {Object} [event.longitude] 鼠标的经度坐标,单位度
 * @property {Object} [event.latitude] 鼠标的纬度坐标,单位度
 * @property {Object} [event.x] 鼠标的像素x坐标,单位px
 * @property {Object} [event.y] 鼠标的像素y坐标,单位px
 * @property {Object} [event.timeStamp] 时间戳,单位ms
 * @property {BaseView} [event.sourceTarget] 事件发起对象
 * @property {Map} [event.target] 事件接收对象
 * @property {Object} [event.event] 事件对象
 * @example <caption><h7>鼠标抬起事件</h7></caption>
 * view.on('pointer-up', (event) => {
 *   console.log("鼠标抬起事件:", event)
 * })
 */

/**
 * @event BaseView#鼠标移动事件
 * @property {Object} event 事件对象
 * @property {LayerEventType} [event.type = 'pointer-move'] 事件类型
 * @property {Object} [event.mapPoint] 鼠标在地图上的经纬度位置
 * @property {Object} [event.longitude] 鼠标的经度坐标,单位度
 * @property {Object} [event.latitude] 鼠标的纬度坐标,单位度
 * @property {Object} [event.x] 鼠标的像素x坐标,单位px
 * @property {Object} [event.y] 鼠标的像素y坐标,单位px
 * @property {Object} [event.timeStamp] 时间戳,单位ms
 * @property {BaseView} [event.sourceTarget] 事件发起对象
 * @property {Map} [event.target] 事件接收对象
 * @property {Object} [event.event] 事件对象
 * @example <caption><h7>鼠标移动事件</h7></caption>
 * view.on('pointer-move', (event) => {
 *   console.log("鼠标移动事件:", event)
 * })
 */

/**
 * @event BaseView#鼠标拖拽事件
 * @property {Object} event 事件对象
 * @property {LayerEventType} [event.type = 'drag'] 事件类型
 * @property {Object} [event.x] 鼠标的像素x坐标,单位px
 * @property {Object} [event.y] 鼠标的像素y坐标,单位px
 * @property {Number} [event.button]
 * @property {Number} [event.buttons]
 * @property {Boolean} [event.cancelable]
 * @property {Object} [event.origin] 拖拽起点
 * @property {Function} [event.stopPropagation] 阻止事件捕获或冒泡
 * @property {Object} [event.timeStamp] 时间戳,单位ms
 * @property {Object} [event.native] 事件对象
 * @property {String} [event.action] 拖拽状态
 * @property {String} [event.type] 事件类型
 * @example <caption><h7>鼠标拖拽事件</h7></caption>
 * view.on('drag', (event) => {
 *   console.log("鼠标拖拽事件:", event)
 * })
 */

/**
 * @event BaseView#地图大小变化事件
 * @property {Object} event 事件对象
 * @property {LayerEventType} [event.type = 'resize'] 事件类型
 * @property {Number} [event.oldWidth] 变化前的视图宽度,单位px
 * @property {Number} [event.oldHeight] 变化前的视图高度,单位px
 * @property {Number} [event.width] 变化后的视图高度,单位px
 * @property {Number} [event.height] 变化后的视图高度,单位px
 * @property {BaseView} [event.sourceTarget] 事件发起对象
 * @property {Map} [event.target] 事件接收对象
 * @property {Object} [event.event] 事件对象
 * @example <caption><h7>地图大小变化事件</h7></caption>
 * view.on('resize', (event) => {
 *   console.log("地图大小变化事件:", event)
 * })
 */

/**
 * @event BaseView#键盘按下事件
 * @property {Object} event 事件对象
 * @property {LayerEventType} [event.type = 'key-down'] 事件类型
 * @property {String} [event.key] 变化后的视图高度,单位px
 * @property {Number} [event.timeStamp] 时间戳,单位ms
 * @property {BaseView} [event.sourceTarget] 事件发起对象
 * @property {Map} [event.target] 事件接收对象
 * @property {Object} [event.event] 事件对象
 * @example <caption><h7>键盘按下事件</h7></caption>
 * view.on('key-down', (event) => {
 *   console.log("键盘按下事件:", event)
 * })
 */

/**
 * @event BaseView#键盘抬起事件
 * @property {Object} event 事件对象
 * @property {LayerEventType} [event.type = 'key-up'] 事件类型
 * @property {String} [event.key] 变化后的视图高度,单位px
 * @property {Number} [event.timeStamp] 时间戳,单位ms
 * @property {BaseView} [event.sourceTarget] 事件发起对象
 * @property {Map} [event.target] 事件接收对象
 * @property {Object} [event.event] 事件对象
 * @example <caption><h7>键盘抬起事件</h7></caption>
 * view.on('key-up', (event) => {
 *   console.log("键盘抬起事件:", event)
 * })
 */

/**
 * @event BaseView#地图视图改变事件
 * @property {Object} event 事件对象
 * @property {LayerEventType} [event.type = 'view-change'] 事件类型
 * @property {BaseView} [event.target] 事件接收对象
 * @property {BaseView} [event.mapView] 事件地图视图对象
 * @property {Number} [event.scale] 事件地图比例尺
 * @property {Number} [event.zoom] 事件地图层级
 * @property {Point} [event.center] 事件地图视图中心
 * @example <caption><h7>地图视野改变事件</h7></caption>
 * view.on('view-change', (event) => {
 *   console.log("地图视图改变事件:", event)
 * })
 */

/**
 * @event BaseView#视图图层创建事件
 * @property {Object} event 事件对象
 * @property {LayerEventType} [event.type = 'layerview-created'] 事件类型
 * @property {Layer} [event.layer] 事件接收对象
 * @property {LayerView} [event.layerView] 事件地图视图中心
 * @property {BaseView} [event.view] 事件地图视图对象
 * @example <caption><h7>视图图层创建事件</h7></caption>
 * view.on('layerview-created', (event) => {
 *   console.log("添加地图图层事件:", event)
 * })
 */

/**
 * @event BaseView#视图图层移除事件
 * @property {Object} event 事件对象
 * @property {LayerEventType} [event.type = 'layerview-remove'] 事件类型
 * @property {Layer} [event.layer] 事件接收对象
 * @property {LayerView} [event.layerView] 事件地图视图中心
 * @property {BaseView} [event.view] 事件地图视图对象
 * @example <caption><h7>视图图层移除事件</h7></caption>
 * view.on('layerview-remove', (event) => {
 *   console.log("销毁地图图层事件:", event)
 * })
 */

/**
 * @event BaseView#视图图层创建错误事件
 * @property {Object} event 事件对象
 * @property {LayerEventType} [event.type = 'layerview-created-error'] 事件类型
 * @property {Layer} [event.layer] 事件接收对象
 * @property {BaseView} [event.view] 事件地图视图对象
 * @property {String} [event.error] 错误消息
 * @example <caption><h7>视图图层创建错误事件</h7></caption>
 * view.on('layerview-created-error', (event) => {
 *   console.log("添加地图图层事件:", event)
 * })
 */
class BaseView extends Evented {
  constructor(options) {
    super()
    options = defaultValue(options, {})
    // 地图对象
    this._map = null
    /**
     * 鼠标样式,参考css的cursor样式
     * @member {String} BaseView.prototype.cursor
     */
    this.cursor = defaultValue(options.cursor, undefined)
    /**
     * 地图视图的比例尺,改变该值后会立刻改变视图范围
     * @member {Number} BaseView.prototype.scale
     */
    this.scale = defaultValue(options.scale, undefined)
    /**
     * 最小缩放比例尺
     * @member {Number} BaseView.prototype.minScale
     */
    this.minScale = undefined
    /**
     * 最大缩放比例尺
     * @member {Number} BaseView.prototype.maxScale
     */
    this.maxScale = undefined
    /**
     * 视图旋转角度
     * @member {Number} BaseView.prototype.rotation
     */
    this.rotation = 0
    /**
     * 视图中心点
     * @member {Array} BaseView.prototype.center
     */
    this.center = defaultValue(options.center, [0, 0])
    /**
     * 最小缩放级数
     * @member {Number} BaseView.prototype.minZoom
     */
    this.minZoom = defaultValue(options.minZoom, 0)
    /**
     * 最大缩放级数
     * @member {Number} BaseView.prototype.maxZoom
     */
    this.maxZoom = defaultValue(options.maxZoom, 19)
    /**
     * 初始化级数
     * @member {Number} BaseView.prototype.zoom
     */
    this.zoom = defaultValue(options.zoom, 1)
    /**
     * 弹窗设置
     * @member {Object} BaseView.prototype.popup
     */
    this.popup = undefined
    /**
     * 视图是否静止
     * @readonly
     * @member {Boolean} BaseView.prototype.stationary
     */
    this.stationary = true
    /**
     * 视图空间参考系
     * @readonly
     * @member {SpatialReference} BaseView.prototype._spatialReference
     */
    this._spatialReference = new SpatialReference('EPSG:4326')
    // 图层管理器传递事件处理
    this._initMapEventHandlers()
    // 添加图层管理模块
    this.setMap(options.map)
    // 图层容器ID
    this._viewId = defaultValue(options.viewId, '')
    // 视图容器
    this._mapCollection = []
    // 引擎视图
    this._innerView = null
    this.graphics = new Collection()
    // 设置鼠标样式
    this._initCursor()
  }

  /**
   * 添加图层管理容器
   * @param {Map} map 图层管理容器
   * */
  setMap(map) {
    if (!this._map) {
      // 设置图层管理器
      this._map = map instanceof Map ? map : Map.fromJSON(map)
      // 初始化 图层管理器-> 视图 事件
      this._linkMapEvent()
      // 初始化 图层 -> 图层管理器 -> 视图 事件
      this._linkLayerEvent()
      if (this._innerView) {
        this._map._haveInnerView = true
      } else {
        this._map._haveInnerView = false
      }
      // 加载图层
      this._map._loadLayers()
      // 加载basemap图层
      this._map._loadBasemap()
    }
  }

  /**
   * @description 链接图层Layer事件
   */
  _linkLayerEvent() {
    if (this._map) {
      for (const eventStr in LayerEventType) {
        const self = this
        this._map.on(
          LayerEventType[eventStr],
          function (event) {
            const data = event
            // 扩展事件属性
            if (data instanceof Event) {
              data.addProperty('view', self)
            } else if (data) {
              data.view = self
            }
            self.fire(LayerEventType[eventStr], data)
          },
          this._map
        )
      }
    }
  }

  /**
   * @description 链接图层管理器Map事件
   */
  _linkMapEvent() {
    if (this._map) {
      for (const eventStr in MapEventType) {
        const self = this
        this._map.on(MapEventType[eventStr], function (event) {
          const data = event
          // 扩展事件属性
          if (data instanceof Event) {
            data.addProperty('view', self)
          } else if (data) {
            data.view = self
          }
          self.fire(MapEventType[eventStr], data)
        })
      }
    }
  }

  /**
   * @description 获取引擎视图对象,在leaflet引擎上返回leafelt map,在cesium引擎上返回cesium viewer
   * @return {Object}
   */
  getInnerView() {
    return this._innerView
  }

  /**
   * @description 初始化图层管理器事件handler
   */
  _initMapEventHandlers() {
    this._processEvent = this._processEvent.bind(this)
    this.on(MapEventType.layerAdd, this._processEvent)
    this.on(MapEventType.layerRemove, this._processEvent)
    // this.on(LayerEventType.featureAdd, this._processEvent)
    this.on(LayerEventType.layerUpdate, this._processEvent)
    this.on(MapEventType.layerRemoveMany, this._processEvent)
    this.on(MapEventType.layerRemoveAll, this._processEvent)
    // this.on(MapEventType.baseLayerAdd, this._processEvent)
  }

  /**
   * @description 事件处理器
   */
  _processEvent(event) {
    // 地图文档Map事件处理
    // 1.图层的增删操作等/地图状态变化操作等
    if (event.type === MapEventType.layerAdd) {
      if (event.layer instanceof Layer) {
        this._addLayerView(event.layer, event)
      }
    }

    if (event.type === MapEventType.layerRemove) {
      if (event.layer instanceof Layer) {
        this._removeLayerView(event.layer, event)
      }
    }
    // 图层事件处理
    // 2.图层的更新
    if (event.type === LayerEventType.layerUpdate) {
      if (event.layer instanceof Layer) {
        this._updateLayerView(event.layer, event)
      }
    }
    // if (event.type === MapEventType.baseLayerAdd) {
    //   if (event.layer instanceof Layer) {
    //     this._addLayerView(event.layer, event)
    //   }
    // }
  }

  /**
   * @description 添加图层视图
   * @private
   */
  _addLayerView(layer, event) {
    const self = this
    layer.load().then(
      (result) => {
        // 图层信息获取完毕,根据图层的参考系,设置view空间参考系
        // 如果view空间参考系和该图层参考系不同,则初始化引擎view。相同则不做改变
        // 如果加载图层是basemap的图层,则在basemap上获取坐标系
        if (layer._isBasemapLayer) {
          self._map.basemap.setSpatialReference()
        }
        this._loadedLayer = layer
        if (self._setSpatialReference) {
          self._setSpatialReference(layer)
        }
        this._loadedLayer = undefined
        // 没有参考系或者 || result._isSRLayer
        if (!self._spatialReference) return
        const loadedEvent = new LayerEvent({
          type: LayerEventType.layerLoaded,
          target: result,
          message: '图层资源加载完毕',
          layer: result
        })

        // 发送图层创建失败事件
        function fireCreatedError(err) {
          const data = new LayerEvent({
            type: LayerEventType.layerViewCreatedError,
            target: result,
            error: err || '图层在视图中创建失败',
            layer: result
          })
          data.addProperty('view', self)
          data.addProperty('layerView', null)
          self.dispatchEvent(LayerEventType.layerViewCreatedError, data)
          Log.error(err)
        }

        // 发送load事件
        self.dispatchEvent(LayerEventType.layerLoaded, loadedEvent)
        // 添加图层
        if (!result) {
          Log.error('图层加载失败,请检查数据服务是否正常')
        }
        // 添加图层到所有图层中
        self._map.allLayers.add(layer)
        // 有子图层获取子图层
        if (
          layer.type === LayerType.igsMapImage ||
          layer.type === LayerType.wms ||
          layer.type === LayerType.arcgisMapImage ||
          layer.type === LayerType.igsVectorTile
        ) {
          layer.allSublayers.forEach(function (sublayer) {
            self._map.allLayers.add(sublayer)
          })
        } else if (layer.type === LayerType.scene) {
          for (let i = 0; i < layer.scenes.length; i++) {
            for (let j = 0; j < layer.scenes[i].sublayers.length; j++) {
              self._map.allLayers.add(layer.scenes[i].sublayers[j])
            }
          }
        }
        self._waitLayerLoaded(layer, result, fireCreatedError)
      },
      (message) => {
        // 请求失败信息
        this.dispatchEvent(
          LayerEventType.layerLoadError,
          new LayerEvent({
            type: LayerEventType.layerLoadError,
            target: layer,
            message: message || '图层资源加载失败,请检查网络状态或服务器状态'
          })
        )
      }
    )
  }

  _getFlyToCenter(options) {
    // 获取center
    let center = undefined
    if (options.center) {
      if (Array.isArray(options.center) && options.center.length > 1) {
        const coordinates =
          options.center.length > 2
            ? [options.center[0], options.center[1], options.center[2]]
            : [options.center[0], options.center[1]]
        const code =
          this._innerView.options && this._innerView.options.crs
            ? this._innerView.options.crs.code
            : 'EPSG:4326'
        center = new Point({
          coordinates,
          spatialReference: new SpatialReference(code)
        })
      } else if (options.center instanceof Point) {
        center = Point.fromJSON(options.center)
      } else if (!(options.center instanceof Point)) {
        Log.error('center类型为不支持的类型!')
      }
      if (!center.spatialReference.isGeographic) {
        center = Projection.project(
          center,
          new SpatialReference({
            wkid: 4326
          })
        )
      }
    }

    return center
  }

  _getFlyToExtent(options) {
    // 获取extent
    let extent = undefined
    if (options.extent) {
      if (options.extent instanceof Extent) {
        extent = Extent.fromJSON(options.extent)
        if (!extent.spatialReference.isGeographic) {
          extent = Projection.project(
            extent,
            new SpatialReference({
              wkid: 4326
            })
          )
        }
      } else {
        Log.error('extent类型为不支持的类型!')
      }
    }
    return extent
  }

  /**
   * 等待图层加载完毕,可有BaseView的子类重写
   * @param {Layer} layer 基础图层对象
   * @param {Object} result 图层加载完毕后的对象
   * @param {Function} fireCreatedError 创建失败回调
   * */
  _waitLayerLoaded(layer, result, fireCreatedError) {
    const self = this
    const promise = self._addLayer(result, event)
    self._layerLoaded(promise, layer, result, fireCreatedError)
  }

  /**
   * 图层加载完毕后做的事情
   * @private
   * @param {Promise} promise Promise对象
   * @param {Layer} layer 基础图层对象
   * @param {Object} result 图层加载完毕后的对象
   * @param {Function} fireCreatedError 创建失败回调
   * */
  _layerLoaded(promise, layer, result, fireCreatedError) {
    const self = this
    // 视频调绘的视频图层在_addLayer后不会返回一个Promise
    if (!promise) {
      return
    }
    promise
      .then((layerView) => {
        Log.info('创建图层', layer)
        // // 如果加载图层是basemap的图层,则在basemap上获取坐标系
        // if (layer._isBasemapLayer) {
        //   self._map.basemap.setSpatialReference()
        //   self._setSpatialReference()
        // }
        const data = new LayerEvent({
          type: LayerEventType.layerViewCreated,
          message: '图层在视图中创建完毕',
          layer: result
        })
        data.addProperty('view', self)
        data.addProperty('layerView', layerView)
        self.dispatchEvent(LayerEventType.layerViewCreated, data)
        // if (self._map.basemap && layer._isBasemapLayer) {
        //   self._map.basemap.fire(LayerEventType.layerViewCreated, data)
        //   // self._map.basemap.dispatchEvent(LayerEventType.layerViewCreated, data)
        // }
      })
      .catch((err) => {
        fireCreatedError(err)
      })
  }

  /**
   * @description 添加图层(在视图中创建成功后返回promise,创建失败返回null)
   * @private
   * @param {Layer} layer
   * @return {Promise<LayerView>|null}
   */
  _addLayer(layer, event) {
    const layerView = this._createLayerView(layer, event)
    if (layerView instanceof LayerView) {
      // layerView添加
      return layerView.onAdd(event).then(() => {
        // 在图层视图加载到引擎内后,加入视图队列
        this._mapCollection.push(layerView)
        // 保证返回的是图层视图
        return layerView
      })
    }
    Log.info('图层视图创建失败,未定义该类型的图层视图!')
    // 添加失败
    return null
  }

  /**
   * @description 移除图层视图
   * @private
   */
  _removeLayerView(layer, event) {
    const self = this
    const promise = this._removeLayer(layer, event)
    if (promise) {
      promise.then((layerView) => {
        Log.info('删除图层', layer)
        const data = new LayerEvent({
          type: LayerEventType.layerViewRemove,
          message: '删除图层',
          layer
        })
        data.addProperty('view', self)
        data.addProperty('layerView', layerView)
        self.dispatchEvent(LayerEventType.layerViewRemove, data)
      })
    }
  }

  /**
   * @description 删除图层(在视图中删除成功后返回promise,删除失败返回null)
   * @private
   * @param {Layer} layer 待删除图层
   * @return {Promise|null}
   */
  _removeLayer(layer, event) {
    const layerView = this._findLayerById(layer.id)
    if (layerView instanceof LayerView) {
      // layerView添加
      return layerView.onRemove(event).then(() => {
        // 引擎内在移除图层视图后,删除队列中图层视图
        this._removeLayerById(layer.id)
        // 保证返回的是图层视图
        return layerView
      })
    }
    Log.info('图层删除失败,未找到该类型的视图!')
    return null
  }

  /**
   * @description 更新图层视图
   */
  _updateLayerView(layer, event) {
    const promise = this._updateLayer(layer, event)
    if (promise) {
      promise.then((layerView) => {
        Log.info('更新图层', layer)
        if (event) {
          event.addProperty('view', self)
          event.addProperty('layerView', layerView)
        }
        this.dispatchEvent(LayerEventType.layerViewUpdate, event)
      })
    }
  }

  /**
   * @description 更新图层(在视图中更新成功后返回promise,更新失败返回null)
   * @private
   * @param {Layer} layer 带更新图层
   * @param {LayerViewUpdateEvent} event 图层视图更新事件
   * @return {Promise|null}
   */
  _updateLayer(layer, event) {
    const layerView = this._findLayerById(layer.id)
    if (layerView instanceof LayerView) {
      // layerView添加
      return layerView.onUpdate(event)
    }
    Log.info('图层更新失败,未找到该类型的视图!')
    return null
  }

  /**
   * @description 事件触发器
   */
  dispatchEvent(type, data, propagate) {
    // 传递给图层
    if (data instanceof LayerEvent && data.layer) {
      data.layer.fire(type, data, propagate)
    }

    // 传递给图层管理器和图层容器
    if (this._map) {
      this._map.dispatchEvent(type, data, propagate)
    }

    if (
      this._map &&
      this._map.basemap &&
      data.layer &&
      data.layer._isBasemapLayer
    ) {
      this._map.basemap.fire(LayerEventType.layerViewCreated, data)
    }

    return this
  }

  _findLayerById(id) {
    let _layer
    for (let i = 0; i < this._mapCollection.length; i++) {
      // 如果是组图层,则遍历子图层的layerview
      if (this._mapCollection[i].layer.type === LayerType.group) {
        const layerViews = this._mapCollection[i].layerViews
        for (let j = 0; j < layerViews.length; j++) {
          if (layerViews[j].id === id) {
            _layer = layerViews[j]
            break
          }
        }
      }
      // 非组图层逻辑
      else if (this._mapCollection[i].id === id) {
        _layer = this._mapCollection[i]
        break
      }
    }

    return _layer
  }

  _removeLayerById(id) {
    for (let i = 0; i < this._mapCollection.length; i++) {
      if (this._mapCollection[i].id === id) {
        this._mapCollection.splice(i, 1)
        break
      }
    }
  }

  _findLayerIndex(id) {
    let _index
    for (let i = 0; i < this._mapCollection.length; i++) {
      if (this._mapCollection[i].id === id) {
        _index = i
        break
      }
    }
    return _index
  }

  /* *********************************     基类需要实现的方法      ************************************* */
  /**
   * @description 创建图层视图
   * @private
   * @param {Layer} layer 图层
   * @param {LayerEvent} event 添加事件
   * @return {LayerView| null}
   */
  _createLayerView(layer) {
    return null
  }

  /**
   * @description 初始化鼠标样式
   * @private
   */
  _initCursor() {
    this._setCursor(this.cursor)
    Object.defineProperty(this, 'cursor', {
      set(newVal) {
        this._setCursor(newVal)
      }
    })
  }

  /**
   * @description 设置鼠标样式
   * @param {String}  type 鼠标样式名
   * @private
   */
  _setCursor(type) {
    if (type) {
      this._innerView._container.style.cursor = type
    }
  }

  /**
   * 根据基础图层对象或者图层id查询并返回实际图层,如果是场景图层,则会返回一个数组对象
   * @param {Object | String} layer 基础图层对象或者图层id
   * @return {Object} 实际图层对象
   * @example <caption><h7>根据基础图层对象或者图层id查询并返回实际图层</h7></caption>
   * // ES5引入方式
   * const { Map, SceneView } = Zondy
   * const { IGSSceneLayer } = Zondy.Layer
   * // ES6引入方式
   * import { Map, SceneView, IGSSceneLayer } from "@@mapgis/webclient-cesium-plugin"
   * // 初始化图层管理容器
   * const map = new Map();
   * // 初始化地图视图对象
   * const sceneView = new SceneView({
   *   // 视图id
   *   viewId: "mapgis-3d-viewer",
   *   // 图层管理容器
   *   map: map
   * });
   * // 添加一个场景图层
   * const igsSceneLayer = new IGSSceneLayer({
   *   url: 'http://192.168.82.89:8089/igs/rest/g3d/Scene:DaYanTa-M3D'
   * });
   * map.add(igsSceneLayer);
   * // 添加完毕后,过去实际图层对象
   * igsSceneLayer.on("layerview-created", function (result) {
   *   console.log("加载完毕:", result.layer)
   *   const innerLayer = sceneView.getInnerLayer(igsSceneLayer)
   *   console.log("innerLayer:", innerLayer)
   * })
   * */
  getInnerLayer(layer) {
    let innerLayer = undefined
    for (let i = 0; i < this._mapCollection.length; i++) {
      if (typeof layer === 'string') {
        if (this._mapCollection[i].layer.id === layer) {
          innerLayer = this._mapCollection[i].innerLayer
          break
        }
      } else if (layer instanceof Object) {
        if (this._mapCollection[i].layer.id === layer.id) {
          innerLayer = this._mapCollection[i].innerLayer
          break
        }
      }
    }
    return innerLayer
  }

  _getLayerView(layer) {
    let layerView = undefined
    for (let i = 0; i < this._mapCollection.length; i++) {
      if (typeof layer === 'string') {
        if (this._mapCollection[i].layer.id === layer) {
          layerView = this._mapCollection[i]
          break
        }
      } else if (layer instanceof Object) {
        if (this._mapCollection[i].layer.id === layer.id) {
          layerView = this._mapCollection[i]
          break
        }
      }
    }
    return layerView
  }

  /**
   * 根据基础图层id查询并返回基础图层对象
   * @param {String} layerId 基础图层ID
   * @return {Layer} 基础图层对象
   * */
  getLayer(layerId) {
    let layer = undefined
    for (let i = 0; i < this._mapCollection.length; i++) {
      if (this._mapCollection[i].layer.id === layerId) {
        layer = this._mapCollection[i].layer
        break
      }
    }
    return layer
  }
}

Object.defineProperties(BaseView.prototype, {
  /**
   * 地图管理容器对象
   * @member {Map} BaseView.prototype.map
   * */
  map: {
    get() {
      return this._map
    },
    set(value) {
      this._map = value
    }
  }
})

export default BaseView
构造函数
成员变量
方法
事件