From 1ba44459ed390fbcb4b05dea06923e4df99d3acc Mon Sep 17 00:00:00 2001
From: wangrui <zephyrs0894@163.com>
Date: 星期三, 23 十二月 2020 15:06:11 +0800
Subject: [PATCH] basemap图层控制ui

---
 src/store/index.js                                   |   15 ++
 src/components/LayerController/modules/LcBaseMap.vue |   40 ++++++++
 src/components/helpers/VectorLayerHelper.js          |   40 ++-----
 src/conf/MapConfig.js                                |   10 ++
 package.json                                         |    2 
 src/views/MapTemplate.vue                            |   32 ++++-
 src/base/BaseVectorLayer.js                          |   10 +-
 src/components/LayerController/LayerController.vue   |    3 
 src/components/helpers/BasemapHelper.js              |   10 +
 src/components/helpers/ServiceLayerHelper.js         |  109 +++++++++++----------
 src/Sgis.js                                          |    1 
 11 files changed, 168 insertions(+), 104 deletions(-)

diff --git a/package.json b/package.json
index 26a7e11..4f30062 100644
--- a/package.json
+++ b/package.json
@@ -16,7 +16,7 @@
     "element-ui": "^2.14.1",
     "jquery": "^3.5.1",
     "js-cookie": "^2.2.0",
-    "leaflet": "^1.7.1",
+    "leaflet": "^1.6.0",
     "leaflet-canvas-marker": "^0.2.0",
     "leaflet.markercluster": "^1.4.1",
     "lodash": "^4.17.10",
diff --git a/src/Sgis.js b/src/Sgis.js
index d8b2ffd..8751989 100644
--- a/src/Sgis.js
+++ b/src/Sgis.js
@@ -49,6 +49,7 @@
 const initBasemapsHelper = (map, L) => {
     // todo 杩欓噷杩涜搴曞浘鍦板浘鐨勫垵濮嬪寲
     var basemapHelper = new BasemapHelper({map, L})
+    console.log(basemapHelper)
     return basemapHelper
 }
 /**
diff --git a/src/base/BaseLayer.js b/src/base/BaseVectorLayer.js
similarity index 93%
rename from src/base/BaseLayer.js
rename to src/base/BaseVectorLayer.js
index aae9cad..7bc8396 100644
--- a/src/base/BaseLayer.js
+++ b/src/base/BaseVectorLayer.js
@@ -3,7 +3,7 @@
 /**
  * 鍩虹鍥惧眰绫伙紝 鍖呭惈鍥惧眰鐨勫垱寤猴紝鍔犺浇鍜屾竻闄ょ瓑鍩虹鍔熻兘銆�
  */
-class BaseLayer {
+class BaseVectorLayer {
     LOAD_TYPE_JSON = 'json' // GeoJson鍔犺浇鏂规硶
     LOAD_TYPE_URL = 'url' // ajax鍔犺浇鏂规硶
     /**
@@ -28,7 +28,7 @@
 
         this.layerCode = options.code || '' // 鍥惧眰缂栫爜
         this.layerName = options.name || '' // 鍥惧眰鍚嶇О
-        this.layerLoadType = options.loadType || BaseLayer.LOAD_TYPE_JSON // 鍥惧眰鍔犺浇绫诲瀷
+        this.layerLoadType = options.loadType || BaseVectorLayer.LOAD_TYPE_JSON // 鍥惧眰鍔犺浇绫诲瀷
         this.layerUrl = options.url || '' // 鏁版嵁璇锋眰鍦板潃
         this.layerData = options.data || '' // 鍘熷GeoJson鏁版嵁
 
@@ -61,10 +61,10 @@
         let features = [] 
 
         // 渚濇嵁鍔犺浇鏂瑰紡鍔犺浇鏁版嵁
-        if(this.layerLoadType === BaseLayer.LOAD_TYPE_JSON) {
+        if(this.layerLoadType === BaseVectorLayer.LOAD_TYPE_JSON) {
             this.features = this._loadFromJSON()
             
-        }else if(this.layerLoadType === BaseLayer.LOAD_TYPE_URL) {
+        }else if(this.layerLoadType === BaseVectorLayer.LOAD_TYPE_URL) {
             this.features = this._loadFromURL()
         }else {
             console.log('鍥惧眰銆�'+this.layerCode+'_'+this.layerName+'銆戠殑'+this.loadType+'鍔犺浇鏂瑰紡鏆備笉鏀寔锛�')
@@ -133,4 +133,4 @@
     }
 }
 
-export default BaseLayer
+export default BaseVectorLayer
diff --git a/src/components/LayerController/LayerController.vue b/src/components/LayerController/LayerController.vue
index 3234beb..b011d48 100644
--- a/src/components/LayerController/LayerController.vue
+++ b/src/components/LayerController/LayerController.vue
@@ -16,8 +16,7 @@
     </div>
     <div class="bodyBox" id="panelContent">
       <div id="panelInnerContent" style="height: auto; overflow: hidden;">
-        fdsafdsaf
-          
+        <slot>鍥惧眰鏁版嵁鏆傛湭鍔犺浇......</slot>
       </div>
     </div>
   </div>
diff --git a/src/components/LayerController/modules/LcBaseMap.vue b/src/components/LayerController/modules/LcBaseMap.vue
new file mode 100644
index 0000000..a9f615c
--- /dev/null
+++ b/src/components/LayerController/modules/LcBaseMap.vue
@@ -0,0 +1,40 @@
+<template>
+<div class="inner-panel">
+    <div v-for="item in basemapList" :key="item.code" class="basemap-layer-item">
+        <img src="" width="40" height="40" :title="item.name"/>
+        <input type="checkbox" title="鏄剧ず鏍囨敞" />
+    </div>
+</div>
+</template>
+
+<script>
+export default {
+  name: 'LcBaseMap',
+  components: {},
+  porps:['helper'],
+  data() {
+    return {
+        basemapList:[]
+    }
+  },
+  mounted(){
+    console.log('03姝ラ锛�', this.helper)
+  },
+  methods:{
+
+  }
+}
+</script>
+
+<style scoped lang="less">
+.inner-panel{
+    display: flex;
+    justify-content: center;
+    align-items: center;
+}
+.basemap-layer-item{
+    width: 40px;
+    height: 40px;
+    margin: 10px;
+}
+</style>
diff --git a/src/components/helpers/BasemapHelper.js b/src/components/helpers/BasemapHelper.js
index a1d315b..498e54b 100644
--- a/src/components/helpers/BasemapHelper.js
+++ b/src/components/helpers/BasemapHelper.js
@@ -78,12 +78,13 @@
         let internetBasemaps = mapConfig.mapConfig.InternetBaseMaps
         for(let i = 0, len = internetBasemaps.length; i < len; ++i) {
             let basemapConfig = internetBasemaps[i]
-            let basemapLayer = this.L.tileLayer(basemapConfig.map.url, basemapConfig.map.options)
-            let basemapAnnotationLayer = this.L.tileLayer(basemapConfig.annotation.url, basemapConfig.annotation.options)
+            let basemapLayer = this.L.tileLayer(basemapConfig.map.url, basemapConfig.map.option)
+            let basemapAnnotationLayer = this.L.tileLayer(basemapConfig.annotation.url, basemapConfig.annotation.option)
 
             let basemap = {
                 code: basemapConfig.code,
                 name: basemapConfig.name,
+                conf: basemapConfig,
                 layer: basemapLayer,
                 annotation: basemapAnnotationLayer
             }
@@ -111,12 +112,13 @@
         let intranetBasemaps = mapConfig.mapConfig.IntranetBaseMaps
         for(let i = 0, len = intranetBasemaps.length; i < len; ++i) {
             let basemapConfig = intranetBasemaps[i]
-            let basemapLayer = this.L.tileLayer(basemapConfig.map.url, basemapConfig.map.options)
-            let basemapAnnotationLayer = this.L.tileLayer(basemapConfig.annotation.url, basemapConfig.annotation.options)
+            let basemapLayer = this.L.tileLayer(basemapConfig.map.url, basemapConfig.map.option)
+            let basemapAnnotationLayer = this.L.tileLayer(basemapConfig.annotation.url, basemapConfig.annotation.option)
 
             let basemap = {
                 code: basemapConfig.code,
                 name: basemapConfig.name,
+                conf: basemapConfig,
                 layer: basemapLayer,
                 annotation: basemapAnnotationLayer
             }
diff --git a/src/components/helpers/ServiceLayerHelper.js b/src/components/helpers/ServiceLayerHelper.js
index c815807..3da6b7b 100644
--- a/src/components/helpers/ServiceLayerHelper.js
+++ b/src/components/helpers/ServiceLayerHelper.js
@@ -22,32 +22,38 @@
         this._loadLayers(mapConfig)
     }
 
+    /**
+     * 鎸夐厤缃枃浠跺姞杞戒笁绉嶄笉鍚岀被鍨嬬殑
+     * @param {*} mapConfig 
+     * @param {*} isAddToMap 
+     */
     _loadLayers(mapConfig, isAddToMap = true){
         console.debug('ServiceLayerHelper鍔犺浇鍙傛暟锛�',mapConfig)
-        this.loadTileLayer(mapConfig, isAddToMap)
-        this.loadWmtsLayer(mapConfig, isAddToMap)
-        this.loadWmtsLayer(mapConfig, isAddToMap)
+        for(let i = 0, len = mapConfig.mapConfig.ServiceLayers.length; i < len; ++i) {
+            let opt = mapConfig.mapConfig.ServiceLayers[i]
+            if(opt.type === 'wmts') {
+                this.loadWmtsLayer(opt, isAddToMap)
+            }else if(opt.type === 'wms') {
+                this.loadWmsLayer(opt, isAddToMap)
+            }else if(opt.type === 'tile') {
+                this.loadTileLayer(opt, isAddToMap)
+            }
+        }
     }
 
     /**
-     * 寰�鍦板浘涓姞鍏ヤ竴涓猼ile鏈嶅姟
+     * 寰�鍦板浘涓姞鍏ヤ竴涓猈MTS鏈嶅姟
      * @param {}} options 
      * @param {*} isAddToMap 
      */
     loadWmtsLayer(options, isAddToMap = true) {
-        for(let i = 0, len = options.mapConfig.ServiceLayers.length; i < len; ++i) {
-            let opt = options.mapConfig.ServiceLayers[i]
-            if(opt.type !== 'wmts') {
-                continue
-            }
-            const layer = this.L.tileLayer(opt.url, opt.option);
-       
-            if(isAddToMap) {
-                layer.addTo(this.map)
-            }
-            this.tileLayersMap.set(opt.code, layer)
-            this.tileLayersArray.push(layer)
+        const layer = this.L.tileLayer(options.url, options.option);
+    
+        if(isAddToMap) {
+            layer.addTo(this.map)
         }
+        this.tileLayersMap.set(options.code, layer)
+        this.tileLayersArray.push(layer)
     }
     /**
      * 寰�鍦板浘涓姞鍏ヤ竴涓猈MS鏈嶅姟
@@ -55,62 +61,57 @@
      * @param {*} isAddToMap 
      */
     loadWmsLayer(options, isAddToMap = true) {
-        for(let i = 0, len = options.mapConfig.ServiceLayers.length; i < len; ++i) {
-            let opt = options.mapConfig.ServiceLayers[i]
-            if(opt.type !== 'wms') {
-                continue
-            }
-
-            const layer =this.L.tileLayer.wms(opt.url, opt.option);
-       
-            if(isAddToMap) {
-                layer.addTo(this.map)
-            }
-            this.tileLayersMap.set(opt.code, layer)
-            this.tileLayersArray.push(layer)
+        const layer =this.L.tileLayer.wms(options.url, options.option);
+    
+        if(isAddToMap) {
+            layer.addTo(this.map)
         }
-        
+        this.tileLayersMap.set(options.code, layer)
+        this.tileLayersArray.push(layer)
     }
 
     /**
-     * 寰�鍦板浘涓姞鍏ヤ竴涓猈MS鏈嶅姟
+     * 寰�鍦板浘涓姞鍏ヤ竴涓猅ILE鏈嶅姟
      * @param {}} options 
      * @param {*} isAddToMap 
      */
     loadTileLayer(options, isAddToMap = true) {
-        for(let i = 0, len = options.mapConfig.ServiceLayers.length; i < len; ++i) {
-            let opt = options.mapConfig.ServiceLayers[i]
-            if(opt.type !== 'tile') {
-                continue
-            }
-
-            const layer =this.L.tileLayer(opt.url, {
-                layers: opt.layers || 'all',//country
-                format: opt.format || "image/png",
-                transparent: opt.true || true,
-                crs:opt.crs || L.CRS.EPSG4326,
-                maxZoom: opt.maxZoom || 21,
-                minZoom: opt.minZoom || 1,
-                zoomOffset: opt.zoomOffset || 0
-            });
-       
-            if(isAddToMap) {
-                layer.addTo(this.map)
-            }
-            this.tileLayersMap.set(opt.code , layer)
-            this.tileLayersArray.push(layer)
+        const layer =this.L.tileLayer(options.url, {
+            layers: options.layers || 'all',//country
+            format: options.format || "image/png",
+            transparent: options.true || true,
+            crs: options.crs || L.CRS.EPSG4326,
+            maxZoom: options.maxZoom || 21,
+            minZoom: options.minZoom || 1,
+            zoomOffset: options.zoomOffset || 0
+        });
+    
+        if(isAddToMap) {
+            layer.addTo(this.map)
         }
+        this.tileLayersMap.set(options.code , layer)
+        this.tileLayersArray.push(layer)
     }
     /**
      * 闅愯棌鏈嶅姟鍥惧眰
      * @param {*} name 
      */
-    hideTileLayer(name){
+    hideTileLayer(code){
         if(this.tileLayersMap){
-            let tileLayer = this.tileLayersMap.get(name)
+            let tileLayer = this.tileLayersMap.get(code)
             this.map.removeLayer(tileLayer)
         }
     }
+    /**
+     * 灞曠ず鏈嶅姟鍥惧眰
+     * @param {*} name 
+     */
+    showTileLayer(code){
+        if(this.tileLayersMap){
+            let tileLayer = this.tileLayersMap.get(code)
+            this.map.addLayer(tileLayer)
+        }
+    }
 
     /**
      * 鑾峰彇鎵�鏈夌殑鏈嶅姟鍥惧眰
diff --git a/src/components/helpers/VectorLayerHelper.js b/src/components/helpers/VectorLayerHelper.js
index 04abe59..2ebcbc9 100644
--- a/src/components/helpers/VectorLayerHelper.js
+++ b/src/components/helpers/VectorLayerHelper.js
@@ -4,32 +4,18 @@
 function VectorLayerHelper(options) {
     this.map = options.map
     this.L = options.L
-    this.vectorLayerMap = {}
+    this.vectorLayerMap = new Map()
     this.vectorLayerList = []
-    this.vueRefMap = {}
-    this.functionMap = {}
+    this.vectorLayerGroup = null
+    this.vueState = {} // 鐢ㄦ埛鍥惧眰鏉冮檺
     /**
      * 璇ユ柟娉曡礋璐e悇绉嶅簳鍥惧姞杞藉埌鍦板浘涓�
      * 涓嶅悓椤甸潰鍔犺浇鍥惧眰涓嶅悓鏍规嵁妯″潡绫诲瀷閫夋嫨鍔犺浇涓嶅悓鍥惧眰
      * @param map
-     * @param methodNames 闇�瑕佸姞杞界殑鏂规硶鍚嶇О
      */
-    this.initVectorLayers = (methodNames) => {
-        // todo 鍒涘缓瀹屼互鍚庯紝鎶婂浘灞傞兘鏀惧埌vectorLayerMap瀵硅薄淇濆瓨璧锋潵锛屾柟渚垮叾浠栨帴鍙h皟鐢�
-        // todo 鍦╩apmodules鏂囦欢澶瑰畾涔夌浉鍏冲浘灞傜殑瀹炵幇浠g爜銆�
-        this.loadFunction(methodNames)
-        // todo 浼佷笟鍥惧眰閮藉彲浠ュ悗闈㈠姞鍏ワ紝鐒跺悗缁熶竴鐢盚elper绋嬪簭鏉ョ鐞嗗浘灞傜殑寮�鍏炽��
-        return null
-    }
-    // 鎸夐渶鍔犺浇瀵瑰簲鏂规硶鍒涘缓鍥惧眰
-    this.loadFunction = (methodNames) => {
-        console.log(methodNames)
-    }
-
-    
-
-    this.setVueRef = (vueName, ref) => {
-       this.vueRefMap[vueName] = ref
+    this.initVectorLayers = (vueState) => {
+        this.vectorLayerGroup = options.L.layerGroup().addTo(options.map)
+        this.vueState = vueState
     }
 
     /**
@@ -44,24 +30,26 @@
      * 閫氳繃鍚嶇О鑾峰彇鍥惧眰瀵硅薄
      * @param name 鍚嶇О
      */
-    this.getVectorLayer = (name) => {
-        return this.vectorLayerMap[name]
+    this.getVectorLayer = (code) => {
+        return this.vectorLayerMap[code]
     }
 
     /**
      * 鏄剧ず鏌愪釜鍥惧眰
      * @param name  鍥惧眰鍚嶇О
      */
-    this.showVectorLayer = (name, vuexStat) => {
-        console.log(this.map, vuexStat)
+    this.showVectorLayer = (code) => {
+        let layer = this.vectorLayerMap.get(code)
+        this.map.addLayer(layer)
     }
 
     /**
      * 闅愯棌鏌愪釜鍥惧眰
      * @param name  鍥惧眰鍚嶇О
      */
-    this.hideVectorLayer = (name, vuexStat) => {
-        console.log(this.map, vuexStat)
+    this.hideVectorLayer = (code) => {
+        let layer = this.vectorLayerMap.get(code)
+        this.map.removeLayer(layer)
     }
 }
 
diff --git a/src/conf/MapConfig.js b/src/conf/MapConfig.js
index cf8d3d0..a12465e 100644
--- a/src/conf/MapConfig.js
+++ b/src/conf/MapConfig.js
@@ -36,6 +36,8 @@
         {
             code: 'sinopec_img',
             name: '涓煶鍖栧ぉ鍦板浘褰卞儚',
+            icon_actived: '',
+            icon_deactived: '',
             isAddToMap: true,
             map: {
                 layerName: '澶╁湴鍥惧奖鍍忓湴鍥�',
@@ -69,6 +71,8 @@
         {
             code: 'sinopec_vec',
             name: '涓煶鍖栧ぉ鍦板浘鐭㈤噺',
+            icon_actived: '',
+            icon_deactived: '',
             isAddToMap: false,
             map: {
                 layerName: '澶╁湴鍥剧煝閲忓湴鍥�',
@@ -104,6 +108,8 @@
         {
             code: 'tianditu_img',
             name: '澶╁湴鍥惧奖鍍�',
+            icon_actived: '',
+            icon_deactived: '',
             isAddToMap: true,
             map: {
                 layerName: '澶╁湴鍥惧奖鍍忓湴鍥�',
@@ -139,6 +145,8 @@
         {
             code: 'tianditu_vec',
             name: '澶╁湴鍥惧奖鍍�',
+            icon_actived: '',
+            icon_deactived: '',
             isAddToMap: false,
             map: {
                 layerName: '澶╁湴鍥剧煝閲忓湴鍥�',
@@ -187,6 +195,8 @@
         {
             code:'guojie',
             name:'鍥界晫',
+            icon_actived: '',
+            icon_deactived: '',
             type:'wmts',
             url: APP_GIS_HOST + '/server/ogcserver/whp_guojie/wmts?x={x}&y={y}&z={z}',
             option:{
diff --git a/src/store/index.js b/src/store/index.js
index 11ade1d..d5e9e1a 100644
--- a/src/store/index.js
+++ b/src/store/index.js
@@ -1,3 +1,4 @@
+/* eslint-disable no-debugger */
 import Vue from 'vue'
 import Vuex from 'vuex'
 import app from './app'
@@ -10,7 +11,9 @@
     currentCorpType: null,
     L: null,
     map: null, // 瀹炰緥鍖栫殑map
-    layerHelper: {}, // 鍥惧眰鎺у埗鍣ㄥ疄鐜板姪鎵嬬▼搴�
+    basemapHelper: {}, // 褰卞儚鍦板浘鍥惧眰鎺у埗鍣ㄥ疄鐜板姪鎵嬬▼搴�
+    serviceLayerHelper: {}, // 鏈嶅姟鍥惧眰鎺у埗鍣ㄥ疄鐜板姪鎵嬬▼搴�
+    vectoryLayerHelper: {}, // 鍔ㄦ�佸浘灞傛帶鍒跺櫒瀹炵幇鍔╂墜绋嬪簭
     layerControllerVisible: { // 鍥惧眰鎺у埗闈㈡澘鐨勬樉绀虹姸鎬佲�衡��
         layerController: true, // 鐖哥埜鏍忕洰锛氭槸鍚︽樉绀哄浘灞傛帶鍒堕潰鏉�
     }
@@ -20,8 +23,14 @@
         state.L = mObject.L
         state.map = mObject.map
     },
-    setLayerHelper(state, layerHelper) {
-        state.layerHelper = layerHelper
+    setBasemapHelper(state, layerHelper) {
+      state.basemapHelper = layerHelper
+    },
+    setServiceLayerHelper(state, layerHelper) {
+      state.serviceLayerHelper = layerHelper
+    },
+    setVectorLayerHelper(state, layerHelper) {
+        state.vectoryLayerHelper = layerHelper
     },
     updateLayerControllerVisible(state, preset) {
         state.layerControllerVisible = preset
diff --git a/src/views/MapTemplate.vue b/src/views/MapTemplate.vue
index 9dfea6c..cfb1870 100644
--- a/src/views/MapTemplate.vue
+++ b/src/views/MapTemplate.vue
@@ -1,7 +1,11 @@
 <template>
   <div class="full-screen">
         <div id="map" ref="rootmap"></div>
-        <sgis-layer-controller :preset="'warningPreset'"></sgis-layer-controller>
+        <sgis-layer-controller :preset="'warningPreset'">
+          <template v-slot:default>
+            <lc-basemap></lc-basemap>
+          </template>
+        </sgis-layer-controller>
         <monitor-panel></monitor-panel>
   </div>
 </template>
@@ -11,16 +15,21 @@
 import Sgis from '@src/Sgis'
 import mapConfig from '@/conf/MapConfig'
 import SgisLayerController from '@components/LayerController/LayerController'
+import LcBasemap from '@components/LayerController/modules/LcBaseMap'
 import MonitorPanel from '@components/panel/MonitorPanel'
-import { mapMutations, mapState } from 'vuex'
+import { mapMutations } from 'vuex'
 
 export default {
   name: 'MapTemplate',
-  components: {SgisLayerController, MonitorPanel},
-  datas:{
-      ...mapState("/",{})
+  components: {SgisLayerController, MonitorPanel, LcBasemap},
+  data(){
+    return {
+      basemapHelper: {},
+      serviceLayerHelper: {},
+      vectorLayerHelper: {}
+    }
   },
-  mounted(){
+  beforeMount(){
       this.$nextTick(() => {
           this.init()
       })
@@ -28,15 +37,17 @@
   methods:{
       ...mapMutations({
         setMapObj: 'setMapObj',
-        setLayerHelper: 'setLayerHelper'
+        setBasemapHelper: 'setBasemapHelper',
+        setServiceLayerHelper: 'setServiceLayerHelper',
+        setVectorLayerHelper: 'setVectorLayerHelper',
       }),
       init() {
         const mapcontainer = this.$refs.rootmap
         this.mapObj = Sgis.initMap(mapcontainer)
+        console.log('01姝ラ锛�', this.mapObj)
 
         this.basemapHelper = Sgis.initBasemapsHelper(this.mapObj.map, this.mapObj.L) // 鍒濆鍖栧熀纭�搴曞浘鍔╂墜
         this.basemapHelper.initBasemap(mapConfig, false) // 绗簩涓弬鏁帮紝琛ㄧず鏄惁鍐呯綉搴曞浘
-
 
         this.serviceLayerHelper = Sgis.initTileLayersHelper(this.mapObj.map, this.mapObj.L) // 鍒濆鍖栦笟鍔″簳鍥惧姪鎵�
         this.serviceLayerHelper.initServiceLayers(mapConfig)
@@ -44,7 +55,10 @@
         this.vectorLayerHelper = Sgis.initVectorLayersHelper(this.mapObj.map, this.mapObj.L) // 鍒濆鍖栧姩鎬佽绱犲浘灞傚姪鎵�
         this.vectorLayerHelper.initVectorLayers(mapConfig)
 
-        this.setLayerHelper(this.vectorLayerHelper)
+        console.log('02姝ラ锛�', this.basemapHelper)
+        this.setBasemapHelper(this.basemapHelper)
+        this.setServiceLayerHelper(this.serviceLayerHelper)
+        this.setVectorLayerHelper(this.vectorLayerHelper)
         return this.map
       }
   }

--
Gitblit v1.8.0