From add294f3c89ab2c6adbe11bc5c718c855a7fc545 Mon Sep 17 00:00:00 2001
From: maven <2163098428@qq.com>
Date: 星期五, 10 十月 2025 15:56:25 +0800
Subject: [PATCH] yys 联调关键煤种锁仓页面
---
src/views/index.vue | 725 +++++++++++++++++++++++++++++++++++--------------------
1 files changed, 459 insertions(+), 266 deletions(-)
diff --git a/src/views/index.vue b/src/views/index.vue
index 60dba1c..941b982 100644
--- a/src/views/index.vue
+++ b/src/views/index.vue
@@ -8,24 +8,50 @@
</div>
<div class="card-content">
<div class="card-title">钀ユ敹閲戦</div>
- <div class="card-value">楼1,234,567</div>
- <div class="card-trend">
+ <div class="card-value">
+ 楼{{
+ homePageData.revenueAmount
+ ? formatThousand(homePageData.revenueAmount)
+ : "--"
+ }}
+ </div>
+ <div class="card-trend" v-if="homePageData.trend == '+'">
<span class="trend-label">杈冩槰鏃�</span>
- <span class="trend-value up">+12.5%</span>
+ <span class="trend-value up">+ {{ homePageData.changeRate }}</span>
+ </div>
+ <div class="card-trend" v-if="homePageData.trend == '-'">
+ <span class="trend-label">杈冩槰鏃�</span>
+ <span class="trend-value down"
+ >- {{ homePageData.changeRate }}</span
+ >
</div>
</div>
</div>
-
+
<div class="stat-card supply">
<div class="card-icon">
<i class="el-icon-truck"></i>
</div>
<div class="card-content">
<div class="card-title">渚涘簲閲�</div>
- <div class="card-value">8,965 鍚�</div>
- <div class="card-trend">
+ <div class="card-value">
+ {{
+ homePageData.saleQuantity
+ ? formatThousand(homePageData.saleQuantity)
+ : "--"
+ }}鍚�
+ </div>
+ <div class="card-trend" v-if="homePageData.trendQuantity == '+'">
<span class="trend-label">杈冩槰鏃�</span>
- <span class="trend-value up">+8.2%</span>
+ <span class="trend-value up"
+ >+ {{ homePageData.saleQuantityRate }}</span
+ >
+ </div>
+ <div class="card-trend" v-if="homePageData.trendQuantity == '-'">
+ <span class="trend-label">杈冩槰鏃�</span>
+ <span class="trend-value down"
+ >- {{ homePageData.saleQuantityRate }}</span
+ >
</div>
</div>
</div>
@@ -37,9 +63,25 @@
<div class="chart-title">钀ユ敹鍒嗗竷</div>
<div ref="pieChart" class="chart-content pie-chart"></div>
</div>
-
+
<div class="chart-container">
- <div class="chart-title">渚涘簲閲忚秼鍔�</div>
+ <div class="chart-title">
+ <span>渚涘簲閲忚秼鍔�</span>
+ <div>
+ <el-date-picker
+ :locale="zhCN"
+ v-model="selectMonth"
+ type="monthrange"
+ placeholder="閫夋嫨鏃ユ湡"
+ format="YYYY/MM"
+ value-format="YYYY-MM"
+ range-separator="鑷�"
+ start-placeholder="寮�濮嬫棩鏈�"
+ end-placeholder="缁撴潫鏃ユ湡"
+ @change="searchMonth"
+ />
+ </div>
+ </div>
<div ref="areaChart" class="chart-content area-chart"></div>
</div>
</div>
@@ -52,25 +94,10 @@
<h3>搴撳瓨缁熻</h3>
</div>
<div class="inventory-items">
- <div class="inventory-item">
- <div class="item-name">鍘熺叅</div>
- <div class="item-value">15,432 鍚�</div>
- <div class="item-status normal">姝e父</div>
- </div>
- <div class="inventory-item">
- <div class="item-name">绮剧叅</div>
- <div class="item-value">8,765 鍚�</div>
- <div class="item-status normal">姝e父</div>
- </div>
- <div class="inventory-item">
- <div class="item-name">鐒︾叅</div>
- <div class="item-value">3,241 鍚�</div>
- <div class="item-status low">鍋忎綆</div>
- </div>
- <div class="inventory-item">
- <div class="item-name">鍧楃叅</div>
- <div class="item-value">6,789 鍚�</div>
- <div class="item-status normal">姝e父</div>
+ <div class="inventory-item" v-for="(item, index) in inventoryList.Yvalues" :key="index">
+ <div class="item-name">{{ inventoryList.Xkeys[index]? inventoryList.Xkeys[index] : "--"}}</div>
+ <div class="item-value">{{ item ? formatThousand(item) : "0" }}</div>
+ <div class="item-status">鍚�</div>
</div>
</div>
</div>
@@ -88,248 +115,401 @@
<div class="card-header">
<h3>閿�鍞暟鎹�</h3>
</div>
- <el-table
- :data="salesData"
+ <el-table
+ :data="salesData"
style="width: 100%"
:header-cell-style="tableHeaderStyle"
>
- <el-table-column prop="product" label="浜у搧" width="80"></el-table-column>
- <el-table-column prop="quantity" label="鏁伴噺" width="80"></el-table-column>
- <el-table-column prop="amount" label="閲戦" width="90"></el-table-column>
- <el-table-column prop="status" label="鐘舵��" width="70">
- <template #default="scope">
- <el-tag
- :type="scope.row.status === '宸插畬鎴�' ? 'success' : 'warning'"
- size="small"
- >
- {{ scope.row.status }}
- </el-tag>
- </template>
- </el-table-column>
+ <el-table-column
+ prop="coalName"
+ label="浜у搧"
+ align="center"
+ mini-width="50"
+ ></el-table-column>
+ <el-table-column
+ prop="inventoryQuantity"
+ label="鏁伴噺"
+ align="center"
+ mini-width="50"
+ ></el-table-column>
+ <el-table-column
+ prop="totalAmount"
+ label="閲戦"
+ align="center"
+ mini-width="50"
+ ></el-table-column>
</el-table>
</div>
</div>
</div>
</template>
-<script>
-import * as echarts from 'echarts'
+<!-- 鍒犻櫎澶氫綑鐨� script 缁撴潫鏍囩 -->
+<script setup>
+import { getCoalInfo, getYearlySales } from "@/api/home/index";
+import { ref, onMounted, nextTick } from "vue";
+import zhCn from "element-plus/dist/locale/zh-cn.mjs";
-export default {
- name: 'Dashboard',
- data() {
- return {
- salesData: [
- { product: '鍘熺叅', quantity: '1,234鍚�', amount: '楼456,789', status: '宸插畬鎴�' },
- { product: '绮剧叅', quantity: '567鍚�', amount: '楼234,567', status: '宸插畬鎴�' },
- { product: '鐒︾叅', quantity: '890鍚�', amount: '楼345,678', status: '杩涜涓�' },
- { product: '鍧楃叅', quantity: '432鍚�', amount: '楼123,456', status: '宸插畬鎴�' },
- { product: '鐓ゆ偿', quantity: '678鍚�', amount: '楼234,567', status: '杩涜涓�' }
- ],
- tableHeaderStyle: {
- backgroundColor: '#f5f7fa',
- color: '#606266',
- fontSize: '12px'
- }
- }
- },
- mounted() {
- this.$nextTick(() => {
- this.initCharts()
- })
- },
- methods: {
- initCharts() {
- this.initPieChart()
- this.initAreaChart()
- this.initBarChart()
- },
-
- initPieChart() {
- const chart = echarts.init(this.$refs.pieChart)
- const option = {
- tooltip: {
- trigger: 'item',
- formatter: '{a} <br/>{b}: {c} ({d}%)'
- },
- legend: {
- orient: 'vertical',
- left: 'right',
- top: 'center',
- textStyle: {
- fontSize: 12
- }
- },
- series: [
- {
- name: '钀ユ敹鍒嗗竷',
- type: 'pie',
- radius: ['30%', '70%'],
- center: ['40%', '50%'],
- avoidLabelOverlap: false,
- label: {
- show: false,
- position: 'center'
- },
- emphasis: {
- label: {
- show: true,
- fontSize: '16',
- fontWeight: 'bold'
- }
- },
- labelLine: {
- show: false
- },
- data: [
- { value: 335, name: '鍘熺叅', itemStyle: { color: '#409EFF' } },
- { value: 310, name: '绮剧叅', itemStyle: { color: '#67C23A' } },
- { value: 234, name: '鐒︾叅', itemStyle: { color: '#E6A23C' } },
- { value: 135, name: '鍧楃叅', itemStyle: { color: '#F56C6C' } },
- { value: 155, name: '鍏朵粬', itemStyle: { color: '#909399' } }
- ]
- }
- ]
- }
- chart.setOption(option)
-
- // 鍝嶅簲寮�
- window.addEventListener('resize', () => {
- chart.resize()
- })
- },
-
- initAreaChart() {
- const chart = echarts.init(this.$refs.areaChart)
- const option = {
- tooltip: {
- trigger: 'axis',
- axisPointer: {
- type: 'cross',
- label: {
- backgroundColor: '#6a7985'
- }
- }
- },
- legend: {
- data: ['渚涘簲閲�'],
- top: 10
- },
- grid: {
- left: '3%',
- right: '4%',
- bottom: '3%',
- containLabel: true
- },
- xAxis: [
- {
- type: 'category',
- boundaryGap: false,
- data: ['1鏈�', '2鏈�', '3鏈�', '4鏈�', '5鏈�', '6鏈�', '7鏈�'],
- axisLabel: {
- fontSize: 12
- }
- }
- ],
- yAxis: [
- {
- type: 'value',
- axisLabel: {
- fontSize: 12
- }
- }
- ],
- series: [
- {
- name: '渚涘簲閲�',
- type: 'line',
- stack: 'Total',
- areaStyle: {
- color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
- { offset: 0, color: 'rgba(64, 158, 255, 0.3)' },
- { offset: 1, color: 'rgba(64, 158, 255, 0.1)' }
- ])
- },
- emphasis: {
- focus: 'series'
- },
- data: [1200, 1320, 1010, 1340, 900, 1230, 1100],
- lineStyle: {
- color: '#409EFF'
- },
- itemStyle: {
- color: '#409EFF'
- }
- }
- ]
- }
- chart.setOption(option)
-
- // 鍝嶅簲寮�
- window.addEventListener('resize', () => {
- chart.resize()
- })
- },
-
- initBarChart() {
- const chart = echarts.init(this.$refs.barChart)
- const option = {
- tooltip: {
- trigger: 'axis',
- axisPointer: {
- type: 'shadow'
- }
- },
- grid: {
- left: '3%',
- right: '4%',
- bottom: '3%',
- containLabel: true
- },
- xAxis: {
- type: 'category',
- data: ['鍘熺叅', '绮剧叅', '鐒︾叅', '鍧楃叅', '鐓ゆ偿'],
- axisLabel: {
- fontSize: 11
- }
- },
- yAxis: {
- type: 'value',
- axisLabel: {
- fontSize: 11
- }
- },
- series: [
- {
- name: '閿�閲�',
- type: 'bar',
- data: [320, 302, 301, 334, 290],
- itemStyle: {
- color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
- { offset: 0, color: '#409EFF' },
- { offset: 1, color: '#79bbff' }
- ])
- },
- barWidth: '60%'
- }
- ]
- }
- chart.setOption(option)
-
- // 鍝嶅簲寮�
- window.addEventListener('resize', () => {
- chart.resize()
- })
- }
+// 鍏煎妯℃澘鍙橀噺鍚嶏紝鏆撮湶缁欐ā鏉夸娇鐢�
+const zhCN = zhCn;
+import * as echarts from "echarts";
+
+const homePageData = ref({});
+const selectMonth = ref([]);
+
+// 鐢熸垚鏃犻檺闅忔満棰滆壊锛圚SL绠楁硶淇濊瘉楂樿鲸璇嗗害銆佹煍鍜屼笉鍒虹溂锛�
+function generateRandomColors(count = 10) {
+ const colors = [];
+ const goldenAngle = 137.508; // 榛勯噾瑙掑害锛屼繚璇侀鑹插垎甯冨潎鍖�
+
+ for (let i = 0; i < count; i++) {
+ // 浣跨敤榛勯噾瑙掑害鍒嗗壊纭繚棰滆壊宸紓澶�
+ const hue = (i * goldenAngle) % 360;
+
+ // 楗卞拰搴︼細40-70% 閬垮厤杩囦簬椴滆壋
+ const saturation = 40 + Math.random() * 30;
+
+ // 鏄庡害锛�45-75% 閬垮厤杩囨殫鎴栬繃浜�
+ const lightness = 45 + Math.random() * 30;
+
+ colors.push(
+ `hsl(${Math.round(hue)}, ${Math.round(saturation)}%, ${Math.round(
+ lightness
+ )}%)`
+ );
}
+
+ return colors;
}
+
+// HSL杞�16杩涘埗锛堝彲閫夛紝濡傛灉闇�瑕乭ex鏍煎紡锛�
+function hslToHex(hsl) {
+ const match = hsl.match(/hsl\((\d+),\s*(\d+)%,\s*(\d+)%\)/);
+ if (!match) return hsl;
+
+ const h = parseInt(match[1]) / 360;
+ const s = parseInt(match[2]) / 100;
+ const l = parseInt(match[3]) / 100;
+
+ const hue2rgb = (p, q, t) => {
+ if (t < 0) t += 1;
+ if (t > 1) t -= 1;
+ if (t < 1 / 6) return p + (q - p) * 6 * t;
+ if (t < 1 / 2) return q;
+ if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
+ return p;
+ };
+
+ let r, g, b;
+ if (s === 0) {
+ r = g = b = l;
+ } else {
+ const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
+ const p = 2 * l - q;
+ r = hue2rgb(p, q, h + 1 / 3);
+ g = hue2rgb(p, q, h);
+ b = hue2rgb(p, q, h - 1 / 3);
+ }
+
+ const toHex = (c) => {
+ const hex = Math.round(c * 255).toString(16);
+ return hex.length === 1 ? "0" + hex : hex;
+ };
+
+ return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
+}
+
+// 渚挎嵎鏂规硶锛氱洿鎺ヨ幏鍙�16杩涘埗棰滆壊鏁扮粍
+function getRandomHexColors(count = 1) {
+ return generateRandomColors(count).map(hslToHex);
+}
+
+// 鍗冨垎浣嶆牸寮忓寲鍑芥暟
+function formatThousand(num) {
+ if (typeof num === "number") return num.toLocaleString();
+ if (typeof num === "string") {
+ const n = Number(num.replace(/,/g, ""));
+ if (isNaN(n)) return num;
+ return n.toLocaleString();
+ }
+ return num;
+}
+
+// 閿�鍞暟鎹師濮�
+const salesData = ref([]);
+
+const tableHeaderStyle = {
+ backgroundColor: "#f5f7fa",
+ color: "#606266",
+ fontSize: "12px",
+};
+
+// 鍥捐〃ref
+const pieChart = ref(null);
+const areaChart = ref(null);
+const barChart = ref(null);
+
+// 楗煎浘鍒濆鍖�
+const initPieChart = () => {
+ const chart = echarts.init(pieChart.value);
+ const option = {
+ tooltip: {
+ trigger: "item",
+ formatter: "{a} <br/>{b}: {c} ({d}%)",
+ },
+ legend: {
+ orient: "vertical",
+ left: "right",
+ top: "center",
+ textStyle: {
+ fontSize: 12,
+ },
+ },
+ series: [
+ {
+ name: "钀ユ敹鍒嗗竷",
+ type: "pie",
+ radius: ["30%", "70%"],
+ center: ["40%", "50%"],
+ avoidLabelOverlap: false,
+ label: {
+ show: false,
+ position: "center",
+ },
+ emphasis: {
+ label: {
+ show: true,
+ fontSize: "16",
+ fontWeight: "bold",
+ },
+ },
+ labelLine: {
+ show: false,
+ },
+ data: revenueDistribution.value,
+ },
+ ],
+ };
+ chart.setOption(option);
+ window.addEventListener("resize", () => {
+ chart.resize();
+ });
+};
+
+// 闈㈢Н鍥惧垵濮嬪寲
+const initAreaChart = () => {
+ const chart = echarts.init(areaChart.value);
+ const option = {
+ title: {
+ show: supplyTrend.value.length == 0, // 娌℃暟鎹墠鏄剧ず
+ extStyle: {
+ color: "grey",
+ fontSize: 20,
+ },
+ text: "鏆傛棤鏁版嵁",
+ left: "center",
+ top: "center",
+ },
+ tooltip: {
+ trigger: "axis",
+ axisPointer: {
+ type: "cross",
+ label: {
+ backgroundColor: "#6a7985",
+ },
+ },
+ },
+ legend: {
+ data: ["渚涘簲閲�"],
+ top: 10,
+ },
+ grid: {
+ left: "3%",
+ right: "4%",
+ bottom: "3%",
+ containLabel: true,
+ },
+ xAxis: [
+ {
+ type: "category",
+ boundaryGap: false,
+ data: supplyTrend.value.Xkeys || [],
+ axisLabel: {
+ fontSize: 12,
+ },
+ },
+ ],
+ yAxis: [
+ {
+ type: "value",
+ axisLabel: {
+ fontSize: 12,
+ },
+ },
+ ],
+ series: [
+ {
+ name: "渚涘簲閲�",
+ type: "line",
+ stack: "Total",
+ areaStyle: {
+ color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+ { offset: 0, color: "rgba(64, 158, 255, 0.3)" },
+ { offset: 1, color: "rgba(64, 158, 255, 0.1)" },
+ ]),
+ },
+ emphasis: {
+ focus: "series",
+ },
+ data: supplyTrend.value.Yvalues || [],
+ lineStyle: {
+ color: "#409EFF",
+ },
+ itemStyle: {
+ color: "#409EFF",
+ },
+ },
+ ],
+ };
+ chart.setOption(option);
+ window.addEventListener("resize", () => {
+ chart.resize();
+ });
+};
+
+// 鏌辩姸鍥惧垵濮嬪寲
+const initBarChart = () => {
+ const chart = echarts.init(barChart.value);
+ const option = {
+ tooltip: {
+ trigger: "axis",
+ axisPointer: {
+ type: "shadow",
+ },
+ },
+ grid: {
+ left: "3%",
+ right: "4%",
+ bottom: "3%",
+ containLabel: true,
+ },
+ xAxis: {
+ type: "category",
+ data: resultMonthList.value.Xkeys || [],
+ axisLabel: {
+ fontSize: 11,
+ },
+ },
+ yAxis: {
+ type: "value",
+ axisLabel: {
+ fontSize: 11,
+ },
+ },
+ series: [
+ {
+ name: "閿�閲�",
+ type: "bar",
+ data: resultMonthList.value.Yvalues || [],
+ itemStyle: {
+ color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+ { offset: 0, color: "#409EFF" },
+ { offset: 1, color: "#79bbff" },
+ ]),
+ },
+ barWidth: "60%",
+ },
+ ],
+ };
+ chart.setOption(option);
+ window.addEventListener("resize", () => {
+ chart.resize();
+ });
+};
+// 鏀跺叆鍒嗗竷鏁版嵁
+const revenueDistribution = ref([]);
+
+// 鍒濆鍖栨墍鏈夊浘琛�
+const initCharts = () => {
+ initPieChart();
+ initAreaChart();
+ initBarChart();
+};
+
+const getList = async () => {
+ try {
+ searchMonth();
+ const res = await getCoalInfo();
+ homePageData.value = res.data || {};
+ revenueDistribution.value = [];
+ if (homePageData.value.revenueDistribution) {
+ Object.keys(homePageData.value.revenueDistribution).forEach((key) => {
+ let obj = {};
+ obj.name = key;
+ obj.value = homePageData.value.revenueDistribution[key];
+ obj.itemStyle = {
+ color: getRandomHexColors(1)[0], // 浣跨敤闅忔満棰滆壊
+ };
+ revenueDistribution.value.push(obj);
+ });
+ }
+ if (homePageData.value.inventory) {
+ let inventoryListXkeys = Object.keys(homePageData.value.inventory);
+ let inventoryListYvalues = Object.values(homePageData.value.inventory);
+ inventoryList.value = {
+ Xkeys: inventoryListXkeys,
+ Yvalues: inventoryListYvalues,
+ };
+ }
+ if(homePageData.value.resultMouth){
+ let resultMonthXkeys = Object.keys(homePageData.value.resultMouth);
+ let resultMonthYvalues = Object.values(homePageData.value.resultMouth);
+ resultMonthList.value = {
+ Xkeys: resultMonthXkeys,
+ Yvalues: resultMonthYvalues,
+ };
+ console.log(resultMonthList.value);
+ }
+ if(homePageData.value.salesResults){
+ salesData.value = homePageData.value.salesResults;
+ }
+ // 鏁版嵁鍔犺浇瀹屾垚鍚庨噸鏂板垵濮嬪寲鍥捐〃
+ nextTick(() => {
+ initCharts();
+ });
+ } catch (error) {
+ console.error("鑾峰彇鐓ょ淇℃伅澶辫触:", error);
+ }
+};
+const inventoryList = ref([]);
+const resultMonthList = ref([]);
+
+const supplyTrend = ref({});
+const searchMonth = async () => {
+ let res = await getYearlySales({
+ timeRange: selectMonth.value ? selectMonth.value : null,
+ });
+ let Xkeys = Object.keys(res.data.data);
+ let Yvalues = Object.values(res.data.data);
+ supplyTrend.value = {
+ Xkeys,
+ Yvalues,
+ };
+ nextTick(() => {
+ initAreaChart();
+ });
+};
+onMounted(() => {
+ getList();
+});
</script>
-<style scoped>
+<style scoped lang="scss">
.dashboard {
padding: 20px;
background-color: #f5f7fa;
- min-height: 100vh;
+ min-height: 91vh;
+ box-sizing: border-box;
}
/* 椤堕儴缁熻鍗$墖 */
@@ -362,11 +542,11 @@
}
.revenue .card-icon {
- background: linear-gradient(135deg, #409EFF, #79bbff);
+ background: linear-gradient(135deg, #409eff, #79bbff);
}
.supply .card-icon {
- background: linear-gradient(135deg, #67C23A, #95d475);
+ background: linear-gradient(135deg, #67c23a, #95d475);
}
.card-content {
@@ -396,7 +576,10 @@
}
.trend-value.up {
- color: #67C23A;
+ color: #67c23a;
+}
+.trend-value.down {
+ color: #f56c6c;
}
/* 涓棿鍥捐〃鍖哄煙 */
@@ -405,7 +588,7 @@
gap: 20px;
margin-bottom: 20px;
}
-.el-scrollbar__view{
+.el-scrollbar__view {
width: 100%;
}
.chart-container {
@@ -423,6 +606,8 @@
margin-bottom: 15px;
padding-bottom: 10px;
border-bottom: 2px solid #f0f0f0;
+ display: flex;
+ justify-content: space-between;
}
.chart-content {
@@ -470,7 +655,7 @@
padding: 12px;
background: #f8f9fa;
border-radius: 6px;
- border-left: 3px solid #409EFF;
+ border-left: 3px solid #409eff;
}
.item-name {
@@ -492,12 +677,12 @@
.item-status.normal {
background: #f0f9ff;
- color: #67C23A;
+ color: #67c23a;
}
.item-status.low {
background: #fef0e6;
- color: #E6A23C;
+ color: #e6a23c;
}
/* 鏌辩姸鍥惧鍣� */
@@ -507,7 +692,7 @@
/* 琛ㄦ牸鏍峰紡璋冩暣 */
.bottom-card.table {
- min-width: 320px;
+ width: 100%;
}
.bottom-card.table .el-table {
@@ -518,13 +703,21 @@
.bottom-card.table .el-table th {
padding: 8px 0;
}
-
+:deep(.el-scrollbar__view) {
+ width: 100% !important;
+}
+:deep(.el-table__header, ) {
+ width: 100% !important;
+}
+:deep(.el-table__body, ) {
+ width: 100% !important;
+}
/* 鍝嶅簲寮忚璁� */
@media (max-width: 1200px) {
.bottom-section {
flex-direction: column;
}
-
+
.chart-section {
flex-direction: column;
}
@@ -534,15 +727,15 @@
.top-cards {
flex-direction: column;
}
-
+
.dashboard {
padding: 10px;
}
-
+
.stat-card {
padding: 15px;
}
-
+
.card-value {
font-size: 20px;
}
--
Gitblit v1.9.3