From 0d2203b4027ae3bf524d63da67202e778648e4cf Mon Sep 17 00:00:00 2001
From: jinlin <jinlin>
Date: 星期五, 02 八月 2024 09:59:20 +0800
Subject: [PATCH] 修改
---
web/src/views/modules/taskReliability/TimeDiagram.vue | 789 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 781 insertions(+), 8 deletions(-)
diff --git a/web/src/views/modules/taskReliability/TimeDiagram.vue b/web/src/views/modules/taskReliability/TimeDiagram.vue
index a5fc186..5d7577f 100644
--- a/web/src/views/modules/taskReliability/TimeDiagram.vue
+++ b/web/src/views/modules/taskReliability/TimeDiagram.vue
@@ -12,36 +12,54 @@
<zt-form-item label="浠跨湡璁板綍" prop="simulatHis">
<zt-select v-model="dataForm.id" :datas="simulatList" @change="onSimulatSelected"/>
</zt-form-item>
+ <zt-form-item label="閲囨牱鍛ㄦ湡" prop="samplPeriod">
+ <el-input v-model="dataForm.samplPeriod" readonly="false">
+ </el-input>
+ </zt-form-item>
+ <zt-form-item label="浠跨湡娆℃暟" prop="simulatFrequency">
+ <el-input v-model="dataForm.simulatFrequency" readonly="false">
+ </el-input>
+ </zt-form-item>
+ <zt-form-item >
+ <zt-button @click="getDiagram()">鏌ョ湅鏃跺簭鍥�</zt-button>
+ </zt-form-item>
</el-form>
<div>
<el-col :span="4">
<div style="margin-right: 5px;height: calc(88vh - 100px)" v-if="isSelect">
- <product-model-tree @on-selected="onTreeSelected" showXdy="false"
- ref="ProductModelTree" :isShow="false" basic="5"/>
+ <product-model-tree @on-selected="onTreeSelected"
+ ref="ProductModelTree" :isShow="false" :productId="dataForm.productId"/>
</div>
</el-col>
<el-col :span="20">
<div style="margin-top: 20px">
- <div>
- <SimulatCurve ref="SimulatCurve"></SimulatCurve>
+ <div id="container" style="border: 1px solid #EAEBEE;border-radius: 6px;
+ box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);">
</div>
</div>
</el-col>
</div>
</div>
</el-row>
+ <el-dialog v-dialogDrag title="妯″瀷璁捐" top="1vh" width='95%' :visible.sync="dialogVisible2" v-if="dialogVisible2">
+ <RBDEditImg ref="rbdEditImg"></RBDEditImg>
+ </el-dialog>
</div>
</template>
<script>
import SimulatCurve from "./SimulatCurve";
import ProductModelTree from "../basicInfo/ProductModelTree";
+ import {Graph, Shape, Addon, Cell} from '@antv/x6'
+ import RBDEditImg from './RBD-edit-img'
export default {
data() {
return {
+ dialogVisible2: false,
timers: '',
+ shape: '',
isSelect: false,
isShow: false,
productList: [],
@@ -49,6 +67,42 @@
taskList: [],
MTBF: '',
MTTR: '',
+ diagramJson: '',
+ graph: null,
+ globalGridAttr: {
+ type: 'mesh',
+ size: 10,
+ color: '#e5e5e5',
+ thickness: 1,
+ colorSecond: '#d0d0d0',
+ thicknessSecond: 1,
+ factor: 4,
+ bgColor: '#e5e5e5',
+ showImage: true,
+ repeat: 'watermark',
+ position: 'center',
+ bgSize: JSON.stringify({width: 150, height: 150}),
+ opacity: 0.1,
+
+ stroke: '#5F95FF',
+ strokeWidth: 1,
+ connector: 'normal',
+ label: '',
+ nodeStroke: '#5F95FF',
+ nodeStrokeWidth: 1,
+ nodeFill: '#ffffff',
+ nodeFontSize: 12,
+ nodeColor: '#080808',
+ nodeText: '',
+ nodeDate: '',
+ nodeUsers: '',
+ nodeDataDate: '',
+ nodeDataText: '',
+ dataId: '',
+ inspectName: '',
+ distance: 0.5,
+ angle: 0,
+ },
dataForm: {
id: '',
pid: '',
@@ -64,13 +118,692 @@
},
mounted() {
this.getProductList()
+ this.init()
},
components: {
ProductModelTree,
SimulatCurve,
},
-
methods: {
+ init() {
+ console.log(document.documentElement.clientWidth, 'document.documentElement.clientWidth')
+ console.log(document.documentElement.clientHeight, 'document.documentElement.clientHeight')
+ this.graph = new Graph({
+ container: document.getElementById('container'),
+ width: document.documentElement.clientWidth,
+ height: document.documentElement.clientHeight - 220,
+ // async: true,
+ grid: {
+ visible: true,
+ },
+ embedding: {
+ enabled: true,
+ findParent({node}) {
+ const bbox = node.getBBox()
+ return this.getNodes().filter((node) => {
+ // 鍙湁 data.parent 涓� true 鐨勮妭鐐规墠鏄埗鑺傜偣
+ const data = node.getData()
+ if (data && data.parent) {
+ const targetBBox = node.getBBox()
+ return bbox.isIntersectWithRect(targetBBox)
+ }
+ return false
+ })
+ }
+ },
+ // translating: {
+ // restrict(view) {
+ // const cell = view.cell
+ // if (cell.isNode()) {
+ // const parent = cell.getParent()
+ // if (parent) {
+ // return parent.getBBox()
+ // }
+ // }
+ //
+ // return null
+ // },
+ // },
+ onToolItemCreated({tool}) {
+ const handle = tool
+ const options = handle.options
+ if (options && options.index % 2 === 1) {
+ tool.setAttrs({fill: 'red'})
+ }
+ },
+ autoResize: true,
+ history: true,
+ // panning: {
+ // enabled: true,
+ // },
+ scroller: {
+ enabled: true,
+ pageVisible: true,
+ pageBreak: true,
+ pannable: true,
+ },
+ mousewheel: {
+ enabled: true,
+ zoomAtMousePosition: true,
+ modifiers: 'ctrl',
+ minScale: 0.1,
+ maxScale: 10,
+ },
+ connecting: {
+ router: {
+ name: 'normal',
+ // args: {
+ // padding: 1,
+ // },
+ },
+ connector: {
+ name: 'rounded',
+ args: {
+ radius: 8,
+ },
+ },
+ // anchor: 'center',
+ connectionPoint: 'anchor',
+ allowBlank: false,
+ snap: {
+ radius: 20,
+ },
+ createEdge() {
+ return new Shape.Edge({
+ attrs: {
+ line: {
+ stroke: '#A2B1C3',
+ strokeWidth: 2,
+ targetMarker: 'classic'
+ }
+ },
+ tools: {
+ name: 'vertices',
+ },
+ labels: [{
+ attrs: {
+ body: {
+ stroke: '#5F95FF',
+ },
+ text: {
+ // fontFamily: '浠垮畫',
+ text: ''
+ }
+ },
+ // position: {
+ // distance: 0.5,
+ // angle: 180,
+ // options: {
+ // keepGradient: true,
+ // ensureLegibility: true
+ // }
+ // }
+ }],
+ zIndex: 0,
+ })
+ },
+ // validateConnection({targetMagnet}) {
+ // return !!targetMagnet
+ // },
+ },
+ highlighting: {
+ magnetAdsorbed: {
+ name: 'stroke',
+ args: {
+ attrs: {
+ fill: '#5F95FF',
+ stroke: '#5F95FF',
+ },
+ },
+ },
+ },
+ resizing: {
+ enabled: true,
+ restricted: true
+ },
+ rotating: true,
+ selecting: {
+ enabled: true,
+ rubberband: true,
+ rubberEdge: true,
+ showNodeSelectionBox: true,
+ },
+ snapline: true,
+ keyboard: true,
+ clipboard: true,
+ })
+ this.graph.centerContent()
+ const stencil = new Addon.Stencil({
+ title: '',
+ target: this.graph,
+ stencilGraphWidth: 260,
+ stencilGraphHeight: 700,
+ collapsable: false,
+ groups: [
+ {
+ title: '鍥惧厓',
+ name: 'group1',
+ collapsable: false
+ }
+ ],
+ layoutOptions: {
+ columns: 2,
+ columnWidth: 130,
+ rowHeight: 100,
+ },
+ })
+ Graph.registerNode(
+ 'custom-rect',
+ {
+ inherit: 'rect',
+ width: 86,
+ height: 26,
+ zIndex: 10,
+ data: {
+ dataId: '',
+ finishDate: '',
+ inspectName: ''
+ },
+ attrs: {
+ body: {
+ strokeWidth: 1,
+ stroke: 'none',
+ fill: 'none',
+ },
+ text: {
+ // fontFamily: '浠垮畫',
+ fontSize: 20,
+ fill: '#000',
+ },
+ label: {
+ refX: 0,
+ refY: 0.5,
+ textAnchor: 'start',
+ textVerticalAnchor: 'middle',
+ textWrap: {
+ text: '鏂囧瓧妯℃澘',
+ width: -10, // 瀹藉害鍑忓皯 10px
+ ellipsis: false, // 鏂囨湰瓒呭嚭鏄剧ず鑼冨洿鏃讹紝鑷姩娣诲姞鐪佺暐鍙�
+ breakWord: true, // 鏄惁鎴柇鍗曡瘝
+ }
+ },
+ },
+ ports: {...this.ports},
+ },
+ true,
+ )
+
+ Graph.registerNode(
+ 'custom-polygon',
+ {
+ inherit: 'polygon',
+ width: 86,
+ height: 56,
+ attrs: {
+ body: {
+ strokeWidth: 1,
+ stroke: '#5F95FF',
+ fill: '#EFF4FF',
+ },
+ // title:{
+ // text:'',
+ // refX: 40,
+ // refY: 38,
+ // fontSize: 20,
+ // fill: '#262626',
+ // 'text-anchor': 'start',
+ // },
+ text: {
+ // refX: 40,
+ // refY: 20,
+ fontSize: 20,
+ fill: '#262626',
+ // 'text-anchor': 'start',
+ },
+ },
+ // markup: [
+ // {
+ // tagName: 'polygon',
+ // selector: 'body',
+ // },
+ // {
+ // tagName: 'text',
+ // selector: 'title',
+ // },
+ // {
+ // tagName: 'text',
+ // selector: 'text',
+ // },
+ // ],
+ ports: {
+ ...this.ports
+ // items: [
+ // {
+ // group: 'top',
+ // },
+ // {
+ // group: 'bottom',
+ // },
+ // ],
+ },
+ },
+ true,
+ )
+ //
+ Graph.registerNode(
+ 'custom-circle',
+ {
+ inherit: 'ellipse',
+ width: 120,
+ height: 120,
+ data: {
+ dataId: '',
+ finishDate: ''
+ },
+ attrs: {
+ body: {
+ strokeWidth: 1,
+ stroke: '#5F95FF',
+ fill: '#EFF4FF',
+ },
+ //鏃ユ湡
+ title: {
+ text: '',
+ fontSize: 12,
+ fill: '#262626',
+ refX: 0.5,
+ refY: '100%',
+ refY2: -10,
+ textAnchor: 'middle',
+ textVerticalAnchor: 'bottom',
+ },
+ // 鍚嶇О
+ text: {
+ // fontFamily: '浠垮畫',
+ fontSize: 20,
+ fill: '#262626',
+ textWrap: {
+ width: 80, // 瀹藉害涓� 80px鎹㈣
+ ellipsis: false, // 鏂囨湰瓒呭嚭鏄剧ず鑼冨洿鏃讹紝鑷姩娣诲姞鐪佺暐鍙�
+ breakWord: true, // 鏄惁鎴柇鍗曡瘝
+ }
+ },
+ },
+ markup: [
+ {
+ tagName: 'ellipse',
+ selector: 'body',
+ },
+ {
+ tagName: 'text',
+ selector: 'title',
+ },
+ {
+ tagName: 'text',
+ selector: 'text',
+ },
+ ],
+ ports: {...this.ports},
+ },
+ true,
+ )
+ Graph.registerNode(
+ 'custom-circle1',
+ {
+ inherit: 'ellipse',
+ width: 65,
+ height: 65,
+ data: {
+ dataId: '',
+ finishDate: ''
+ },
+ attrs: {
+ body: {
+ strokeWidth: 1,
+ stroke: '#5F95FF',
+ fill: '#EFF4FF',
+ },
+ //鏃ユ湡
+ text: {
+ // fontFamily: '浠垮畫',
+ fontSize: 12,
+ text: '鏃ユ湡鑺傜偣',
+ fill: '#262626',
+ },
+ },
+ ports: {...this.ports},
+ },
+ true,
+ )
+ Graph.registerNode(
+ 'custom-text',
+ {
+ inherit: 'text-block',
+ width: 86,
+ height: 56,
+ attrs: {
+ body: {
+ strokeWidth: 1,
+ stroke: '#5F95FF',
+ fill: '#EFF4FF',
+ },
+ text: {
+ text: '涓撲笟',
+ fontSize: 20,
+ style: {
+ color: this.globalGridAttr.nodeColor
+ },
+ refX: '0',
+ refY: -0.5,
+ refY2: 1,
+ textAnchor: 'middle',
+ textVerticalAnchor: 'middle',
+ },
+ },
+ markup: [
+ {
+ tagName: 'rect',
+ selector: 'body',
+ },
+ {
+ tagName: 'text',
+ selector: 'text',
+ },
+ ],
+ ports: {...this.ports},
+ },
+ true,
+ )
+ // 涓�绾х綉缁滃浘鐨勬棩鏈熸枃瀛楄妭鐐�
+ const r5 = this.graph.createNode({
+ shape: 'custom-circle',
+ data: {
+ dataId: '',
+ finishDate: '',
+ inspectName: ''
+ },
+ label: '闃舵',
+ })
+ // 浜岀骇缃戠粶鍥炬棩鏈熻妭鐐�
+ const r6 = this.graph.createNode({
+ shape: 'custom-circle1',
+ data: {
+ dataId: '',
+ finishDate: '',
+ inspectName: ''
+ },
+ })
+ // 浜岀骇缃戠粶鍥炬枃瀛楄妭鐐�
+ const r9 = this.graph.createNode({
+ shape: 'custom-rect'
+ })
+
+ const scaleImgCenter = this.graph.createNode({
+ shape: 'image',
+ imageUrl: require('@/assets/img/scale/center.jpg'),
+ width: 36,
+ height: 20,
+ data: {
+ imagePost: 'center'
+ }
+ })
+
+ const scaleImgTop = this.graph.createNode({
+ shape: 'image',
+ imageUrl: require('@/assets/img/scale/top.jpg'),
+ width: 36,
+ height: 20,
+ data: {
+ imagePost: 'top'
+ }
+ })
+
+ const scaleImgRight = this.graph.createNode({
+ shape: 'image',
+ imageUrl: require('@/assets/img/scale/right.jpg'),
+ width: 36,
+ height: 20,
+ data: {
+ imagePost: 'right'
+ }
+ })
+ const scaleImgBottom = this.graph.createNode({
+ shape: 'image',
+ imageUrl: require('@/assets/img/scale/bottom.jpg'),
+ width: 36,
+ height: 20,
+ data: {
+ imagePost: 'bottom'
+ }
+ })
+ const scaleImgLeft = this.graph.createNode({
+ shape: 'image',
+ imageUrl: require('@/assets/img/scale/left.jpg'),
+ width: 36,
+ height: 20,
+ data: {
+ imagePost: 'left'
+ }
+ })
+
+ // scaleImgTop.setAttribute('crossOrigin', 'Anonymous')
+ stencil.load([r5, r6, r9, scaleImgTop, scaleImgCenter, scaleImgRight, scaleImgBottom, scaleImgLeft], 'group1')
+ this.graph.bindKey(['meta+c', 'ctrl+c'], () => {
+ const cells = this.graph.getSelectedCells()
+ if (cells.length) {
+ this.graph.copy(cells)
+ }
+ return false
+ })
+
+ this.graph.bindKey(['meta+x', 'ctrl+x'], () => {
+ const cells = this.graph.getSelectedCells()
+ if (cells.length) {
+ this.graph.cut(cells)
+ }
+ return false
+ })
+ // 鐩戝惉 stencil 鐨勬嫋鎷藉紑濮嬩簨浠�
+ this.graph.on('node:embed', ({node, e}) => {
+ // 闃绘浜嬩欢鍐掓场
+ e.stopPropagation()
+ console.log(node.shape, 'node node')
+ let parent
+ let child
+ if (node.shape === 'custom-rect') {
+ child = node
+ } else {
+ parent = node
+ }
+ console.log('parent:' + parent, 'child:' + child)
+ // parent.addChild(child);
+ })
+ this.graph.bindKey(['meta+v', 'ctrl+v'], () => {
+ if (!this.graph.isClipboardEmpty()) {
+ const cells = this.graph.paste({offset: 32})
+ this.graph.cleanSelection()
+ this.graph.select(cells)
+ }
+ return false
+ })
+//undo redo
+ this.graph.bindKey(['meta+z', 'ctrl+z'], () => {
+ if (this.graph.history.canUndo()) {
+ this.graph.history.undo()
+ }
+ return false
+ })
+
+ this.graph.bindKey(['meta+shift+z', 'ctrl+shift+z'], () => {
+ if (this.graph.history.canRedo()) {
+ this.graph.history.redo()
+ }
+ return false
+ })
+
+// select all
+ this.graph.bindKey(['meta+a', 'ctrl+a'], () => {
+ const nodes = this.graph.getNodes()
+ if (nodes) {
+ this.graph.select(nodes)
+ }
+ })
+//delete
+ this.graph.bindKey('delete', () => {
+ const cells = this.graph.getSelectedCells()
+ if (cells.length) {
+ this.$confirm('鏄惁鍒犻櫎璇ヨ妭鐐�?', '鎻愮ず', {
+ confirmButtonText: '纭畾',
+ cancelButtonText: '鍙栨秷',
+ type: 'warning'
+ }).then(() => {
+ this.$message({
+ type: 'success',
+ message: '鍒犻櫎鎴愬姛!'
+ })
+ this.graph.removeCells(cells)
+ }).catch(() => {
+ this.$message({
+ type: 'info',
+ message: '宸插彇娑堝垹闄�'
+ })
+ })
+ }
+ })
+// zoom
+ this.graph.bindKey(['ctrl+1', 'meta+1'], () => {
+ const zoom = this.graph.zoom()
+ if (zoom < 1.5) {
+ this.graph.zoom(0.1)
+ }
+ })
+
+ this.graph.bindKey(['ctrl+2', 'meta+2'], () => {
+ const zoom = this.graph.zoom()
+ if (zoom > 0.5) {
+ this.graph.zoom(-0.1)
+ }
+ })
+
+ this.graph.on('blank:click', ({cell}) => {
+ this.type = 'grid'
+ })
+
+ this.graph.on('cell:click', ({cell}) => {
+ // this.type.value = cell.isNode() ? "node" : "edge"
+ this.type = cell.isNode() ? 'node' : 'edge'
+ this.shape = cell.shape
+ this.id = cell.id
+ console.log(this.shape, 'this.shape')
+ // this.nodeOpt(this.id, this.globalGridAttr)
+ })
+ //鍗曞嚮杈硅妭鐐�
+ this.graph.on('edge:click', ({edge}) => {
+ // this.reset()
+ edge.attr('line/stroke', '#5F95FF')
+ edge.prop('labels/0', {
+ attrs: {
+ body: {
+ stroke: '#5F95FF',
+ },
+ },
+
+ })
+ })
+ // 鍗曞嚮node鑺傜偣
+ this.graph.on('node:click', ({node}) => {
+ // this.reset()
+ if (node.getData().dataId) {
+ this.dialogVisible2 = true
+ let param = {
+ id: node.getData().dataId,
+ modelName: node.attr('label/textWrap/text'),
+ }
+ this.$nextTick(() => {
+ this.$refs.rbdEditImg.init(param)
+ })
+ }
+ })
+ // 鎺у埗杩炴帴妗╂樉绀�/闅愯棌
+ this.graph.on('node:delete', ({view, e}) => {
+ e.stopPropagation()
+ view.cell.remove()
+ })
+
+ this.graph.on('node:customevent', ({name, view, e}) => {
+ if (name === 'node:delete') {
+ e.stopPropagation()
+ view.cell.remove()
+ }
+ })
+ // 鍙屽嚮缂栬緫
+ this.graph.on('cell:dblclick', ({cell, e}) => {
+ const isNode = cell.isNode()
+ const name = cell.isNode() ? 'node-editor' : 'edge-editor'
+ cell.removeTool(name)
+ cell.addTools({
+ name,
+ args: {
+ event: e,
+ attrs: {
+ backgroundColor: isNode ? '#EFF4FF' : '#FFF',
+ text: {
+ fontSize: 16,
+ fill: '#262626',
+ },
+ },
+ },
+ })
+ })
+
+ this.graph.on('node:mouseenter', ({node}) => {
+ const container = document.getElementById('container')
+ const ports = container.querySelectorAll(
+ '.x6-port-body',
+ )
+ this.showPorts(ports, true)
+ })
+
+ this.graph.on('node:mouseleave', ({node}) => {
+ // if (node.hasTool('button-remove')) {
+ // node.removeTool('button-remove')
+ // }
+ const container = document.getElementById('container')
+ const ports = container.querySelectorAll(
+ '.x6-port-body',
+ )
+ this.showPorts(ports, false)
+ })
+
+ this.graph.on('edge:mouseenter', ({cell, view}) => {
+ // alert(123)
+ cell.addTools([
+ {
+ name: 'source-arrowhead',
+ },
+ {
+ name: 'target-arrowhead',
+ args: {
+ attrs: {
+ fill: 'red',
+ },
+ },
+ },
+ ])
+ cell.addTools(
+ [
+ {
+ name: 'segments',
+ args: {snapRadius: 20, attrs: {fill: '#444'}}
+ }
+ ]
+ )
+ })
+
+ this.graph.on('edge:mouseleave', ({cell}) => {
+ cell.removeTools()
+ })
+ },
async getProductList() {
let res = await this.$http.get('/basicInfo/XhProductModel/getTaskProductList')
this.productList = res.data
@@ -95,10 +828,18 @@
async onTreeSelected(data) {
this.dataForm.productId = data.id
console.log(this.dataForm.productId)
+ if (!this.dataForm.taskModelId) {
+ this.$alert("璇峰厛閫夋嫨鍏蜂綋浠诲姟")
+ return
+ }
+ if (!this.dataForm.id) {
+ this.$alert("璇峰厛閫夋嫨鍏蜂綋浠跨湡璁板綍")
+ return
+ }
let params = {
productId: this.dataForm.productId,
taskId: this.dataForm.taskModelId,
- fzId: '1722218139013042135'
+ fzId: this.dataForm.id
}
let res = await this.$http.get('/taskReliability/SimulatAssess/getStatus', {params: params})
console.log(res.data)
@@ -110,6 +851,9 @@
this.dataForm.productId = data.id
this.getTaskList()
this.dataForm.taskModelId = ''
+ this.$nextTick(() => {
+ this.$refs.ProductModelTree.getProductList()
+ })
},
onTaskSelected(data) {
console.log(data, ' onProductSelected(data)')
@@ -117,10 +861,39 @@
this.getSimulatList()
this.dataForm.id = ''
},
- onSimulatSelected(data) {
+ async onSimulatSelected(data) {
this.dataForm.id = data.id
this.dataForm.samplPeriod = data.samplPeriod
- this.$refs.SimulatCurve.initEcharts(this.dataForm);
+ let param = {
+ id: this.dataForm.id,
+ taskModelId: this.dataForm.taskModelId
+ }
+ let result = await this.$http.get('/taskReliability/SimulatAssess/getSimulatParams', {params: param})
+ this.dataForm.samplPeriod = result.data.samplPeriod
+ this.dataForm.simulatFrequency = result.data.simulatFrequency
+ },
+ async getDiagram() {
+ let params = {
+ productId: this.dataForm.productId,
+ taskId: this.dataForm.taskModelId,
+ fzId: this.dataForm.id
+ }
+ let res = await this.$http.get('/taskReliability/SimulatAssess/getStatus', {params: params})
+ if (res.data !== null) {
+ this.diagramJson = JSON.parse(res.data)
+ // console.log(this.dataForm.content,'this.Diagram content')
+ console.log(this.diagramJson, 'this.Diagram json')
+ this.graph.fromJSON(this.diagramJson)
+ this.graph.centerContent()
+ this.graph.zoomToFit()
+ this.graph.freeze()
+ } else {
+ this.graph.fromJSON(this.emptyJson)
+ this.graph.centerContent()
+ this.graph.zoomToFit()
+ this.graph.freeze()
+ }
+ console.log(res.data)
},
}
}
--
Gitblit v1.9.1