feat: commit、issue图表修改

This commit is contained in:
lu tailin 2024-09-11 22:47:25 +08:00
parent f9345c3e35
commit a17d9d07a2
5 changed files with 127 additions and 84 deletions

View File

@ -0,0 +1,72 @@
<template>
<v-chart ref="customChart" :option="option" autoresize />
</template>
<script>
import { use } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
import { LineChart, BarChart } from 'echarts/charts'
import { GridComponent, LegendComponent, TooltipComponent, DataZoomComponent } from 'echarts/components'
import VChart from 'vue-echarts'
use([CanvasRenderer, LineChart, LegendComponent, GridComponent, TooltipComponent, BarChart, DataZoomComponent])
export default {
name: 'CustomChart',
props: {
customOption: { type: Object, default: () => {} }
},
components: {
VChart,
},
computed: {
option() {
if (this.customOption) {
const option = {
tooltip: {
trigger: 'axis',
textStyle: {
align: 'left'
},
...this.customOption?.tooltip
},
legend: {
data: this.customOption.series.map(ser => ser.name) || [],
...this.customOption?.legend
},
xAxis: {
type: 'category',
axisLabel: {
showMaxLabel: true,
showMinLabel: true
},
boundaryGap: false,
...this.customOption?.xAxis
},
yAxis: {
type: 'value',
...this.customOption?.yAxis
},
dataZoom: [{
type: 'slider',
startValue: 0,
endValue: 3,
show: this.customOption?.xAxis?.data?.length > 4
}],
series: this.customOption.series || [],
}
return option
}
return {}
}
},
beforeUnmount() {
//
if (this.$refs.customChart && this.$refs.customChart.dispose) {
this.$refs.customChart.dispose();
}
}
}
</script>
<style lang="scss" scoped>
</style>

View File

@ -1,58 +0,0 @@
<template>
<v-chart ref="lineChart" :option="option" autoresize />
</template>
<script>
import { use } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
import { LineChart } from 'echarts/charts'
import { GridComponent, LegendComponent, TooltipComponent } from 'echarts/components'
import VChart from 'vue-echarts'
use([CanvasRenderer, LineChart, LegendComponent, GridComponent, TooltipComponent])
export default {
name: 'LineChart',
props: {
data: { type: Object, default: () => {} }
},
components: {
VChart,
},
computed: {
option() {
const option = {
tooltip: {
trigger: 'axis'
},
legend: {
data: this.data.series.map(ser => ser.name) || []
},
xAxis: {
type: 'category',
boundaryGap: false,
data: this.data.xData || [],
axisLabel: {
showMaxLabel: true,
showMinLabel: true
}
},
yAxis: {
type: 'value',
minInterval: 1
},
series: this.data.series || []
}
return option
}
},
beforeUnmount() {
//
if (this.$refs.lineChart && this.$refs.lineChart.dispose) {
this.$refs.lineChart.dispose();
}
}
}
</script>
<style lang="scss" scoped>
</style>

View File

@ -217,5 +217,8 @@ export default {
'Upload attachment': 'Upload attachment', 'Upload attachment': 'Upload attachment',
"Didn't get the email? Check junk folder or": "Didn't get the email? Check junk folder or ", "Didn't get the email? Check junk folder or": "Didn't get the email? Check junk folder or ",
'send again': 'send again', 'send again': 'send again',
'No content yet': 'No content yet' 'No content yet': 'No content yet',
'open': 'open',
'resolved': 'resolved',
'unresolved': 'unresolved'
} }

View File

@ -225,5 +225,8 @@ export default {
CLOSED: '已关闭', CLOSED: '已关闭',
REJECTED: '已拒绝', REJECTED: '已拒绝',
APPLYING: '申请中', APPLYING: '申请中',
ACCEPTING: '接受中' ACCEPTING: '接受中',
'open': '未解决',
'resolved': '已解决',
'unresolved': '未解决总计'
} }

View File

@ -445,7 +445,7 @@
{{ $t('TO BE IMPLEMENTED.') }} {{ $t('TO BE IMPLEMENTED.') }}
</div> --> </div> -->
<div class="chart-container"> <div class="chart-container">
<line-chart :data="getCodeChartData(project.project.code)" /> <custom-chart :customOption="getCodeChartOption(project.project.code)" />
</div> </div>
</div> </div>
</div> </div>
@ -493,7 +493,7 @@
</button> </button>
</div> </div>
<div class="chart-container"> <div class="chart-container">
<line-chart :data="getIssueChartData(project.project.issue)" /> <custom-chart :customOption="getIssueChartOption(project.project.issue)" />
</div> </div>
<!-- <div class="project-invite-collaborator-containter"> <!-- <div class="project-invite-collaborator-containter">
<button <button
@ -615,11 +615,11 @@ import {
convertIntoToMilestoneStatus, convertIntoToMilestoneStatus,
convertIntoToProjectIssueStatus convertIntoToProjectIssueStatus
} from '@/types/index' } from '@/types/index'
import LineChart from '@/components/LineChart.vue' import CustomChart from '@/components/CustomChart.vue'
import EmptyContent from '@/components/EmptyContent.vue' import EmptyContent from '@/components/EmptyContent.vue'
export default { export default {
name: 'Workspace', name: 'Workspace',
components: { LineChart, EmptyContent }, components: { CustomChart, EmptyContent },
props: {}, props: {},
mounted() { mounted() {
this.loading = true this.loading = true
@ -989,20 +989,27 @@ export default {
this.websocketOnClose this.websocketOnClose
) )
}, },
getCodeChartData(code) { getCodeChartOption(code) {
const { weekly_commits } = code const { weekly_commits } = code
if (weekly_commits) { if (weekly_commits) {
// //
const sortData = Object.entries(weekly_commits).sort((a, b) => new Date(a[0]) - new Date(b[0])); const sortData = Object.entries(weekly_commits).sort((a, b) => new Date(a[0]) - new Date(b[0]))
const xData = sortData.map(data => data[0])
return { return {
xData: sortData.map(data => data[0]), xAxis: {
data: xData
},
yAxis: {
minInterval: 1
},
series: [ series: [
{ {
data: sortData.map(data => data[1]), data: sortData.map(data => data[1]),
type: 'line', type: 'line',
name: 'commits', name: this.$t('Commits'),
areaStyle: { color: 'rgba(63,73,255,0.1)' }, lineStyle: {
smooth: true, color: 'rgb(23,72,248)'
},
symbol: 'none', symbol: 'none',
connectNulls: true connectNulls: true
} }
@ -1011,32 +1018,48 @@ export default {
} }
return {} return {}
}, },
getIssueChartData(issue) { getIssueChartOption(issue) {
const { weekly_open_issues, weekly_resolved_issues } = issue const { weekly_open_issues, weekly_resolved_issues } = issue
if (weekly_open_issues && weekly_resolved_issues) { if (weekly_open_issues && weekly_resolved_issues) {
// //
const sortOpenData = Object.entries(weekly_open_issues).sort((a, b) => new Date(a[0]) - new Date(b[0])); const sortOpenData = Object.entries(weekly_open_issues).sort((a, b) => new Date(a[0]) - new Date(b[0]))
const sortResolvedData = Object.entries(weekly_resolved_issues).sort((a, b) => new Date(a[0]) - new Date(b[0])); const sortResolvedData = Object.entries(weekly_resolved_issues).sort((a, b) => new Date(a[0]) - new Date(b[0]))
const openSerData = sortOpenData.map(data => data[1])
const resolvedSerData = sortResolvedData.map(data => data[1])
const unresolvedSerData = openSerData.map((data, index) => data - resolvedSerData[index]).reduce((acc, cur, index) => {
acc.push(index === 0 ? cur : cur + acc[index - 1]);
return acc
}, [])
const xData = sortOpenData.map(data => data[0])
return { return {
xData: sortOpenData.map(data => data[0]), xAxis: {
data: xData
},
yAxis: {
minInterval: 1
},
series: [ series: [
{ {
data: sortOpenData.map(data => data[1]), data: openSerData,
name: 'open', name: this.$t('open'),
type: 'line', type: 'line',
stack: 'issue',
areaStyle: { color: 'rgba(63,73,255,0.1)' },
smooth: true,
symbol: 'none', symbol: 'none',
connectNulls: true connectNulls: true
}, },
{ {
data: sortResolvedData.map(data => data[1]), data: resolvedSerData,
name: 'resolved', name: this.$t('resolved'),
type: 'line', type: 'line',
stack: 'issue', symbol: 'none',
areaStyle: { color: 'rgba(63,73,255,0.2)' }, connectNulls: true
smooth: true, },
{
data: unresolvedSerData,
name: this.$t('unresolved'),
type: 'line',
lineStyle: {
type: 'dashed'
},
symbol: 'none', symbol: 'none',
connectNulls: true connectNulls: true
} }