mirror of
https://gitee.com/devlive-community/datacap.git
synced 2024-12-03 04:27:56 +08:00
core: Add data source radar map within 7 days (#118)
This commit is contained in:
commit
0c6bba0c34
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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",
|
||||
|
@ -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();
|
||||
|
6
web/console-fe/src/charts/radar/Radar.ts
Normal file
6
web/console-fe/src/charts/radar/Radar.ts
Normal file
@ -0,0 +1,6 @@
|
||||
export interface Radar
|
||||
{
|
||||
label: string;
|
||||
percentage: number;
|
||||
value: number;
|
||||
}
|
80
web/console-fe/src/charts/radar/RadarChart.vue
Normal file
80
web/console-fe/src/charts/radar/RadarChart.vue
Normal 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>
|
@ -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
|
||||
}
|
||||
|
3
web/console-fe/src/i18n/langs/en/profile.ts
Normal file
3
web/console-fe/src/i18n/langs/en/profile.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export default {
|
||||
radar7Days: 'Data source radar map within 7 days'
|
||||
}
|
@ -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
|
||||
}
|
||||
|
3
web/console-fe/src/i18n/langs/zhCn/profile.ts
Normal file
3
web/console-fe/src/i18n/langs/zhCn/profile.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export default {
|
||||
radar7Days: '7天内数据源雷达图'
|
||||
}
|
@ -20,4 +20,9 @@ export class AdminService
|
||||
{
|
||||
return new HttpCommon().get(pluginHistoryAdmin + '/contribution');
|
||||
}
|
||||
|
||||
getUserContributionRadar()
|
||||
{
|
||||
return new HttpCommon().get(pluginHistoryAdmin + '/radar');
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user