core: Add data source radar map within 7 days (#118)

This commit is contained in:
qianmoQ 2022-11-07 01:00:11 +08:00 committed by GitHub
commit 0c6bba0c34
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 198 additions and 43 deletions

View File

@ -2,6 +2,7 @@ package io.edurt.datacap.server.controller.user;
import io.edurt.datacap.server.common.Response;
import io.edurt.datacap.server.itransient.ContributionHistory;
import io.edurt.datacap.server.itransient.ContributionRadar;
import io.edurt.datacap.server.service.PluginAuditService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@ -31,4 +32,10 @@ public class PluginAuditAdminController
{
return this.pluginAuditService.getAllContribution();
}
@GetMapping(value = "radar")
public Response<List<ContributionRadar>> radar()
{
return this.pluginAuditService.getContributionRadar();
}
}

View File

@ -0,0 +1,17 @@
package io.edurt.datacap.server.itransient;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class ContributionRadar
{
private Long count;
private String label;
private Double percentage;
}

View File

@ -49,4 +49,11 @@ public interface PluginAuditRepository
" ) AS tbr ON tbl._date = tbr.create_time\n" +
"GROUP BY tbl._date", nativeQuery = true)
List<Map<String, Object>> selectContributionByUserId(Long id);
@Query(value = "SELECT count(1) AS dataOfCount, s.name AS dataOfLabel\n" +
"FROM audit_plugin AS ap\n" +
"LEFT JOIN source AS s ON ap.plugin_id = s.id\n" +
"WHERE date_sub(curdate(), interval 7 day) <= date(ap.create_time)\n" +
"GROUP BY s._type", nativeQuery = true)
List<Map<String, Object>> selectRadarByUserId(Long id);
}

View File

@ -4,6 +4,7 @@ import io.edurt.datacap.server.common.Response;
import io.edurt.datacap.server.entity.PageEntity;
import io.edurt.datacap.server.entity.PluginAuditEntity;
import io.edurt.datacap.server.itransient.ContributionHistory;
import io.edurt.datacap.server.itransient.ContributionRadar;
import java.util.List;
@ -14,4 +15,6 @@ public interface PluginAuditService
Response<Long> count();
Response<List<ContributionHistory>> getAllContribution();
Response<List<ContributionRadar>> getContributionRadar();
}

View File

@ -6,14 +6,17 @@ import io.edurt.datacap.server.entity.PageEntity;
import io.edurt.datacap.server.entity.PluginAuditEntity;
import io.edurt.datacap.server.entity.UserEntity;
import io.edurt.datacap.server.itransient.ContributionHistory;
import io.edurt.datacap.server.itransient.ContributionRadar;
import io.edurt.datacap.server.repository.PluginAuditRepository;
import io.edurt.datacap.server.security.UserDetailsService;
import io.edurt.datacap.server.service.PluginAuditService;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Service
public class PluginAuditServiceImpl
@ -57,4 +60,22 @@ public class PluginAuditServiceImpl
});
return Response.success(contributions);
}
@Override
public Response<List<ContributionRadar>> getContributionRadar()
{
UserEntity user = UserDetailsService.getUser();
List<ContributionRadar> contributionRadars = new ArrayList<>();
List<Map<String, Object>> list = this.pluginAuditRepository.selectRadarByUserId(user.getId());
Long count = list.stream().mapToLong(v -> Long.valueOf(String.valueOf(v.get("dataOfCount")))).sum();
list.forEach(v -> {
ContributionRadar radar = new ContributionRadar();
radar.setLabel(String.valueOf(v.get("dataOfLabel")));
radar.setCount(Long.valueOf(String.valueOf(v.get("dataOfCount"))));
BigDecimal bigDecimal = new BigDecimal(Double.valueOf(radar.getCount()) / Double.valueOf(count));
radar.setPercentage(bigDecimal.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue() * 100.0);
contributionRadars.add(radar);
});
return Response.success(contributionRadars);
}
}

View File

@ -10,6 +10,7 @@
"lint": "vue-cli-service lint"
},
"dependencies": {
"@antv/data-set": "^0.11.8",
"@antv/g2": "^4.2.8",
"@antv/s2": "^1.30.0",
"@antv/s2-vue": "^1.3.0",

View File

@ -6,7 +6,6 @@ import {defineComponent, PropType} from "vue";
import {Chart, IGroup, registerShape} from "@antv/g2";
import {RangePoint, ShapeInfo} from "@antv/g2/lib/interface";
import {ShapeCfg} from "@antv/g-base/src/types";
import {Data} from "@antv/s2";
import {Calendar} from "@/charts/calendar/Calendar";
export default defineComponent({
@ -46,33 +45,6 @@ export default defineComponent({
group.addShape('path', {
attrs
});
const dat = cfg.data as Data;
if (dat.lastWeek) {
const linePath = [
['M', points[2].x, points[2].y],
['L', points[3].x, points[3].y]
];
// Add the right border for the last week's polygon
group.addShape('path', {
attrs: {
path: this.parsePath(linePath),
lineWidth: 4,
stroke: '#404040'
}
});
if (dat.lastDay) {
group.addShape('path', {
attrs: {
path: this.parsePath([
['M', points[1].x, points[1].y],
['L', points[2].x, points[2].y]
]),
lineWidth: 2,
stroke: '#404040'
}
});
}
}
return group;
}
});
@ -109,7 +81,7 @@ export default defineComponent({
});
chart.coordinate().reflect('y');
chart.polygon().position('week*day*date')
.color('count', '#BAE7FF-#1890FF-#0050B3')
.color('count', '#F0F0F2-#6bd08d-#023915')
.shape('boundary-polygon');
chart.interaction('element-active');
chart.render();

View File

@ -0,0 +1,6 @@
export interface Radar
{
label: string;
percentage: number;
value: number;
}

View File

@ -0,0 +1,80 @@
<template>
<div id="containerForRadar"/>
</template>
<script lang="ts">
import {defineComponent, PropType} from "vue";
import {Chart} from "@antv/g2";
import DataSet from '@antv/data-set';
import {Radar} from "@/charts/radar/Radar";
const {DataView} = DataSet;
export default defineComponent({
name: "RadarChart",
props: {
data: {
type: Array as PropType<Array<Radar>>,
default: () => []
}
},
created()
{
this.handlerInitialize();
},
methods: {
handlerInitialize()
{
setTimeout(() => {
const dv = new DataView().source(this.data);
dv.transform({
type: 'fold',
fields: ['percentage'],
value: 'percentage',
});
const chart = new Chart({
container: 'containerForRadar',
autoFit: true,
height: 200,
});
chart.data(dv.rows);
chart.scale('percentage', {
min: 0,
max: 100,
});
chart.coordinate('polar', {
radius: 0.9,
});
chart.axis('label', {
line: null,
tickLine: null,
});
chart.axis('score', {
line: null,
tickLine: null,
grid: {
line: {
type: 'circle',
},
},
});
chart.tooltip({
shared: true,
showCrosshairs: true,
crosshairs: {
type: 'xy',
line: {
style: {
stroke: '#565656',
lineDash: [4],
},
},
follow: true
}
});
chart.line().position('label*percentage').color('#5BD9A6');
chart.point().position('label*percentage').color('#5BD9A6').shape('circle');
chart.render();
}, 0)
}
}
});
</script>

View File

@ -3,11 +3,13 @@ import common from "@/i18n/langs/en/common";
import required from "@/i18n/langs/en/required";
import tooltip from "@/i18n/langs/en/tooltip";
import settings from "@/i18n/langs/en/settings";
import profile from "@/i18n/langs/en/profile";
export default {
...enGB,
common: common,
required: required,
tooltip: tooltip,
setting: settings
setting: settings,
profile: profile
}

View File

@ -0,0 +1,3 @@
export default {
radar7Days: 'Data source radar map within 7 days'
}

View File

@ -3,11 +3,13 @@ import common from "@/i18n/langs/zhCn/common";
import required from "@/i18n/langs/zhCn/required";
import tooltip from "@/i18n/langs/zhCn/tooltip";
import settings from "@/i18n/langs/zhCn/settings";
import profile from "@/i18n/langs/zhCn/profile";
export default {
...zhCN,
common: common,
required: required,
tooltip: tooltip,
setting: settings
setting: settings,
profile: profile
}

View File

@ -0,0 +1,3 @@
export default {
radar7Days: '7天内数据源雷达图'
}

View File

@ -20,4 +20,9 @@ export class AdminService
{
return new HttpCommon().get(pluginHistoryAdmin + '/contribution');
}
getUserContributionRadar()
{
return new HttpCommon().get(pluginHistoryAdmin + '/radar');
}
}

View File

@ -1,26 +1,44 @@
<template>
<a-layout-content>
<a-card size="small">
<a-card size="small" :loading="loading">
<template #title>
{{$t('common.contribution')}}
{{ $t('common.contribution') }}
</template>
<div :style="{ background: '#fff', minHeight: '280px' }">
<CalendarChart v-if="data.length > 0" :data="data"></CalendarChart>
<div :style="{ background: '#fff', minHeight: '150px' }">
<CalendarChart v-if="summary.contribution.length > 0" :data="summary.contribution"></CalendarChart>
</div>
</a-card>
<a-row :gutter="16" style="margin-top: 10px;">
<a-col :span="8">
<a-card size="small" :loading="loading">
<template #title>
{{ $t('profile.radar7Days') }}
</template>
<div>
<RadarChart v-if="summary.contributionRadar.length > 0" :data="summary.contributionRadar"></RadarChart>
</div>
</a-card>
</a-col>
</a-row>
</a-layout-content>
</template>
<script lang="ts">
import {defineComponent} from 'vue';
import CalendarChart from "@/charts/calendar/CalendarChart.vue";
import {AdminService} from "@/services/AdminService";
import RadarChart from "@/charts/radar/RadarChart.vue";
import {HttpCommon} from "@/common/HttpCommon";
export default defineComponent({
components: {CalendarChart},
components: {RadarChart, CalendarChart},
data()
{
return {
data: []
loading: false,
summary: {
contribution: [],
contributionRadar: []
}
}
},
created()
@ -30,12 +48,20 @@ export default defineComponent({
methods: {
handlerInitialize()
{
new AdminService()
.getUserContribution()
.then((response) => {
if (response.status) {
this.data = response.data;
this.loading = true;
const adminService = new AdminService();
const axios = new HttpCommon().getAxios();
axios.all([adminService.getUserContribution(), adminService.getUserContributionRadar()])
.then(axios.spread((contribution, contributionRadar) => {
if (contribution.status) {
this.summary.contribution = contribution.data;
}
if (contributionRadar.status) {
this.summary.contributionRadar = contributionRadar.data;
}
}))
.finally(() => {
this.loading = false;
});
}
}

View File

@ -5,7 +5,7 @@
<ProfileLayoutSidebar></ProfileLayoutSidebar>
</a-layout-sider>
<a-layout style="margin-left: 10px;">
<a-layout-content>
<a-layout-content style="background: #ffffff;">
<ProfileLayoutContent></ProfileLayoutContent>
</a-layout-content>
</a-layout>