update 增加难度系数占比图表
This commit is contained in:
@@ -42,7 +42,7 @@ interface ChartConfig {
|
||||
id: string;
|
||||
title: string;
|
||||
component: any;
|
||||
props: Record<string, any>;
|
||||
props?: Record<string, any>;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
@@ -104,12 +104,17 @@ const updateConfigFun = async (info: any) => {
|
||||
const setConfig = (dataStatisticsSetting: any) => {
|
||||
if (dataStatisticsSetting) {
|
||||
const configInfo = JSON.parse(dataStatisticsSetting);
|
||||
// 找到baseList中存在但configInfo中不存在的项(新增项)
|
||||
const newItems = props.baseList.filter(
|
||||
(baseItem) => !configInfo.some((config: any) => config.key === baseItem.id)
|
||||
);
|
||||
// 根据配置的结果对展示的图表进行排序
|
||||
const list = configInfo
|
||||
.filter((config: any) => config.inBoard)
|
||||
.map((config: any) => props.baseList.find((item) => item.id === config.key))
|
||||
.filter(Boolean);
|
||||
currentList.value = list as ChartConfig[];
|
||||
// 将新增项添加到列表最后
|
||||
currentList.value = [...list, ...newItems] as ChartConfig[];
|
||||
} else {
|
||||
currentList.value = props.baseList;
|
||||
}
|
||||
|
||||
@@ -100,11 +100,27 @@ watch(
|
||||
);
|
||||
const updateTable = () => {
|
||||
if (props.configJson) {
|
||||
tableData.value = JSON.parse(props.configJson);
|
||||
// 解析配置JSON
|
||||
const configData = JSON.parse(props.configJson);
|
||||
// 找到baseList中存在但configJson中不存在的项(新增项)
|
||||
const newItems = props.baseList
|
||||
.filter((baseItem) => !configData.some((config: any) => config.key === baseItem.id))
|
||||
.map((item) => ({
|
||||
key: item.id,
|
||||
title: item.title,
|
||||
inBoard: true,
|
||||
}));
|
||||
// 过滤掉baseList中不存在但configJson中存在的项(已删除的表)
|
||||
const validConfigData = configData.filter((config: any) =>
|
||||
props.baseList.some((baseItem) => baseItem.id === config.key)
|
||||
);
|
||||
// 将新增项添加到配置列表的最后面
|
||||
tableData.value = [...validConfigData, ...newItems];
|
||||
} else {
|
||||
tableData.value = getBaseTable();
|
||||
}
|
||||
};
|
||||
|
||||
const updateFun = () => {
|
||||
emit('update:modelValue', false);
|
||||
emit('updateConfig', JSON.stringify(tableData.value));
|
||||
|
||||
@@ -351,6 +351,7 @@ const lang = {
|
||||
工位评审通过统计: 'Workspace Review Statistics',
|
||||
项目任务完成情况统计: 'Project Task Completion Statistics',
|
||||
文件操作统计: 'File Operate Statistics',
|
||||
难度系数占比: 'Difficulty Coefficient Ratio',
|
||||
},
|
||||
工位时间维护: {
|
||||
阶段: 'Phase',
|
||||
|
||||
@@ -346,6 +346,7 @@ const lang = {
|
||||
工位评审通过统计: '工位评审通过统计',
|
||||
项目任务完成情况统计: '项目任务完成情况统计',
|
||||
文件操作统计: '文件操作统计',
|
||||
难度系数占比: '难度系数占比',
|
||||
},
|
||||
工位时间维护: {
|
||||
阶段: '阶段',
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getThemeColor } from '@/utils/theme';
|
||||
import { useDict } from '@/utils/useDict';
|
||||
import { useProjectList } from '@/utils/useProjectList';
|
||||
import { getTaskStatusColorList, getAchieveColorList } from '@/utils/enum/task';
|
||||
// 引入子组件
|
||||
import fileOperateChart from './dataStatistics/fileOperateChart.vue';
|
||||
import userGroupProjectChart from './dataStatistics/userGroupProjectChart.vue';
|
||||
@@ -16,9 +19,7 @@ import performanceCompletion from './dataStatistics/performanceCompletion.vue';
|
||||
import projectTaskComplete from './dataStatistics/projectTaskComplete.vue';
|
||||
import reviewPassed from './dataStatistics/reviewPassed.vue';
|
||||
import dashboardSetting from '@/components/common/dashboardSetting/index.vue';
|
||||
import { useDict } from '@/utils/useDict';
|
||||
import { useProjectList } from '@/utils/useProjectList';
|
||||
import { getTaskStatusColorList, getAchieveColorList } from '@/utils/enum/task';
|
||||
import userDifficultyRateChart from './dataStatistics/userDifficultyRateChart.vue';
|
||||
|
||||
// 统一请求项目列表
|
||||
useProjectList();
|
||||
@@ -30,15 +31,6 @@ const { TASK_ACHIEVE_STATUS, RESULT_ACHIEVE_STATUS } = useDict(
|
||||
const statusColorList = getTaskStatusColorList(Object.keys(TASK_ACHIEVE_STATUS.value.O));
|
||||
const performanceColorList = getAchieveColorList(Object.keys(RESULT_ACHIEVE_STATUS.value.O));
|
||||
|
||||
// 难度系数颜色列表
|
||||
const difficultyCountColorList = [
|
||||
'#67c23a',
|
||||
'rgb(179, 225, 157)',
|
||||
'rgb(248, 227, 197)',
|
||||
'rgb(243, 209, 158)',
|
||||
'rgb(248, 152, 152)',
|
||||
'#f56c6c',
|
||||
];
|
||||
// 流程状态颜色列表
|
||||
const processNodeColorList = [
|
||||
'rgb(200, 201, 204)', // 未评审
|
||||
@@ -59,9 +51,11 @@ const baseList = [
|
||||
id: 'userDifficultyCoefficient',
|
||||
title: '用户组难度系数统计',
|
||||
component: userDifficultyCoefficientChart, // 用户组难度系数统计
|
||||
props: {
|
||||
difficultyCountColorList,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'userDifficultyRate',
|
||||
title: '难度系数占比',
|
||||
component: userDifficultyRateChart, // 难度系数占比
|
||||
},
|
||||
{
|
||||
id: 'userTaskComplete',
|
||||
|
||||
@@ -25,18 +25,22 @@ import commonFilterChart from '@/components/common/echartCard/commonFilterChart.
|
||||
import { getUserGroupDifficultyStatisticsApi } from '@/api/project/node';
|
||||
import { useDict } from '@/utils/useDict';
|
||||
|
||||
const props = defineProps({
|
||||
difficultyCountColorList: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
// 数组对象排序
|
||||
const sortObjectArray = (arr: any, key: any) => {
|
||||
return arr.sort((a: any, b: any) => {
|
||||
return a[key] - b[key];
|
||||
});
|
||||
};
|
||||
const getDifficultyLevelColor = (difficulty: number) => {
|
||||
// 1 低难度 2 中难度 3 高难度
|
||||
if (Number(difficulty) <= 1) {
|
||||
return '#67c23a'; // 绿色
|
||||
} else if (Number(difficulty) == 2) {
|
||||
return 'rgb(248, 227, 197)';
|
||||
} else {
|
||||
return '#f56c6c'; // 红色
|
||||
}
|
||||
};
|
||||
// 难度系数字典
|
||||
const { DIFFICULTY_COEFFICIENT } = useDict('DIFFICULTY_COEFFICIENT');
|
||||
const getDifficultyLevel = (difficulty: number) => {
|
||||
@@ -49,6 +53,7 @@ const chartOption = ref();
|
||||
const initUserDifficultyCoefficientChart = async (formData: any) => {
|
||||
let xData: any = [];
|
||||
let titles: any = [];
|
||||
let colors: any = [];
|
||||
const seriesList: any = [];
|
||||
const params = {
|
||||
...formData,
|
||||
@@ -62,6 +67,9 @@ const initUserDifficultyCoefficientChart = async (formData: any) => {
|
||||
return item.userName;
|
||||
}) || [];
|
||||
titles = res.data?.alldifficultyValue || [];
|
||||
colors = titles
|
||||
.sort((a: any, b: any) => Number(a) - Number(b))
|
||||
.map((key: any) => getDifficultyLevelColor(Number(key)));
|
||||
for (let i = 0; i < titles.length; i++) {
|
||||
const str = titles[i].toFixed(1);
|
||||
const obj: any = {
|
||||
@@ -79,7 +87,7 @@ const initUserDifficultyCoefficientChart = async (formData: any) => {
|
||||
seriesList.push(obj);
|
||||
}
|
||||
const option = {
|
||||
color: props.difficultyCountColorList,
|
||||
color: colors,
|
||||
legend: {
|
||||
data: titles,
|
||||
},
|
||||
|
||||
@@ -0,0 +1,166 @@
|
||||
<template>
|
||||
<commonFilterChart
|
||||
:title="$t('数据统计.难度系数占比')"
|
||||
:charts-id="'chart-difficulty-rate'"
|
||||
:bar-type="'pieChart'"
|
||||
:option="chartOption"
|
||||
:filterItems="[
|
||||
'userGroup',
|
||||
'user',
|
||||
'projectName',
|
||||
'projectCode',
|
||||
'discipline',
|
||||
'createTime',
|
||||
'finishTime',
|
||||
]"
|
||||
:multipleItems="['user']"
|
||||
:nodata="nodata"
|
||||
@update="updateStatistics"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
import commonFilterChart from '@/components/common/echartCard/commonFilterChart.vue';
|
||||
import { getUserGroupDifficultyStatisticsApi } from '@/api/project/node';
|
||||
import { useDict } from '@/utils/useDict';
|
||||
|
||||
// 难度系数字典
|
||||
const { DIFFICULTY_COEFFICIENT } = useDict('DIFFICULTY_COEFFICIENT');
|
||||
const getDifficultyLevel = (difficulty: number) => {
|
||||
const str = DIFFICULTY_COEFFICIENT.value.O[Number(difficulty)];
|
||||
return str ? str : '难度系数';
|
||||
};
|
||||
const getDifficultyLevelColor = (difficulty: number) => {
|
||||
// 1 低难度 2 中难度 3 高难度
|
||||
if (Number(difficulty) <= 1) {
|
||||
return '#67c23a'; // 绿色
|
||||
} else if (Number(difficulty) == 2) {
|
||||
return 'rgb(248, 227, 197)';
|
||||
} else {
|
||||
return '#f56c6c'; // 红色
|
||||
}
|
||||
};
|
||||
|
||||
// 初始化用户组项目统计
|
||||
const chartOption = ref();
|
||||
const nodata = ref(false);
|
||||
const updateStatistics = async (formData: any) => {
|
||||
const params = {
|
||||
...formData,
|
||||
userIds: formData.userId ? formData.userId.split(',') : [],
|
||||
};
|
||||
delete params.userId;
|
||||
const res: any = await getUserGroupDifficultyStatisticsApi(params);
|
||||
if (res && res.code === 200) {
|
||||
const difficultyCount: Record<any, number> = {};
|
||||
res.data.result.forEach((item: any) => {
|
||||
// 遍历item.difficultyCount这个对象,将key和value分别存入difficultyCount对象中,如果key已经存在,则将value累加
|
||||
Object.keys(item.difficultyCount).forEach((key: any) => {
|
||||
if (difficultyCount[key]) {
|
||||
difficultyCount[key] += item.difficultyCount[key];
|
||||
} else {
|
||||
difficultyCount[key] = item.difficultyCount[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const seriesData = Object.keys(difficultyCount).map((key: any) => {
|
||||
return {
|
||||
key: Number(key),
|
||||
name: getDifficultyLevel(key) + key,
|
||||
value: difficultyCount[key],
|
||||
};
|
||||
});
|
||||
const colorList = Object.keys(difficultyCount)
|
||||
.sort((a, b) => Number(a) - Number(b))
|
||||
.map((key: any) => getDifficultyLevelColor(Number(key)));
|
||||
chartOption.value = getPieOptions(colorList, sortObjectArray(seriesData, 'key'));
|
||||
}
|
||||
};
|
||||
// 数组对象排序
|
||||
const sortObjectArray = (arr: any, key: any) => {
|
||||
return arr.sort((a: any, b: any) => {
|
||||
return a[key] - b[key];
|
||||
});
|
||||
};
|
||||
|
||||
// 饼图配置 statusColorList 颜色列表 seriesData 数据 [{ name: '分类1', value: 10 },{ name: '分类2', value: 20 }]
|
||||
const getPieOptions = (statusColorList: any, seriesData: any) => {
|
||||
const option = {
|
||||
color: statusColorList,
|
||||
legend: {
|
||||
show: true,
|
||||
icon: 'circle',
|
||||
itemWidth: 12,
|
||||
itemHeight: 12,
|
||||
borderWidth: 0,
|
||||
top: '0',
|
||||
formatter: (name: any) => {
|
||||
const str = seriesData.filter((item: any) => item.name === name)[0];
|
||||
return `{name|${name}} {value|${str.value}}`;
|
||||
},
|
||||
textStyle: {
|
||||
// color: 'inherit',
|
||||
rich: {
|
||||
name: {
|
||||
fontSize: 14,
|
||||
align: 'left',
|
||||
},
|
||||
value: {
|
||||
fontSize: 14,
|
||||
fontWeight: '700',
|
||||
align: 'right',
|
||||
},
|
||||
},
|
||||
},
|
||||
// orient: 'vertical', // 方向
|
||||
itemGap: 14,
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '',
|
||||
type: 'pie',
|
||||
radius: ['30%', '55%'],
|
||||
center: ['50%', '55%'],
|
||||
emphasis: {
|
||||
disabled: true, // 禁用emphasis效果
|
||||
},
|
||||
itemStyle: {
|
||||
borderRadius: 0,
|
||||
borderWidth: 0,
|
||||
},
|
||||
label: {
|
||||
formatter: (params: { name: any; percent: any }) => {
|
||||
return '{icon|●}{name|' + params.name + '} {value|' + params.percent + '%' + '}';
|
||||
},
|
||||
alignTo: 'labelLine',
|
||||
rich: {
|
||||
icon: {
|
||||
fontSize: 20,
|
||||
color: 'inherit',
|
||||
},
|
||||
name: {
|
||||
fontSize: 14,
|
||||
padding: [0, 6, 0, 4],
|
||||
color: 'inherit',
|
||||
},
|
||||
value: {
|
||||
fontSize: 12,
|
||||
fontWeight: 'bolder',
|
||||
color: 'inherit',
|
||||
},
|
||||
},
|
||||
},
|
||||
labelLine: {
|
||||
lineStyle: {
|
||||
cap: 'round',
|
||||
},
|
||||
},
|
||||
data: seriesData,
|
||||
},
|
||||
],
|
||||
};
|
||||
return option;
|
||||
};
|
||||
</script>
|
||||
@@ -211,11 +211,22 @@ const getDifficultyLevel = (difficulty: number) => {
|
||||
const str = DIFFICULTY_COEFFICIENT.value.O[difficulty];
|
||||
return str ? str : '难度系数';
|
||||
};
|
||||
const getDifficultyLevelColor = (difficulty: number) => {
|
||||
// 1 低难度 2 中难度 3 高难度
|
||||
if (Number(difficulty) <= 1) {
|
||||
return '#67c23a'; // 绿色
|
||||
} else if (Number(difficulty) == 2) {
|
||||
return 'rgb(248, 227, 197)';
|
||||
} else {
|
||||
return '#f56c6c'; // 红色
|
||||
}
|
||||
};
|
||||
const userDifficultyCoefficientOption = ref();
|
||||
const queryUserDifficultStatistics = async () => {
|
||||
let xData: any = [];
|
||||
let titles: any = [];
|
||||
let seriesData: any = [];
|
||||
let colors: any = [];
|
||||
const res: any = await getUserDifficultyStatisticsApi({
|
||||
tag1: currentProjectUuid.value,
|
||||
});
|
||||
@@ -224,6 +235,9 @@ const queryUserDifficultStatistics = async () => {
|
||||
return item.userName;
|
||||
});
|
||||
titles = res.data.alldifficultyValue;
|
||||
colors = titles
|
||||
.sort((a: any, b: any) => Number(a) - Number(b))
|
||||
.map((key: any) => getDifficultyLevelColor(Number(key)));
|
||||
seriesData = titles.map((title: any) => {
|
||||
const str = title.toFixed(1);
|
||||
return {
|
||||
@@ -238,7 +252,7 @@ const queryUserDifficultStatistics = async () => {
|
||||
});
|
||||
}
|
||||
const option = {
|
||||
color: difficultyCountColorList,
|
||||
color: colors,
|
||||
legend: { data: titles },
|
||||
grid: { bottom: xData.length > 5 ? '50' : '10' },
|
||||
xAxis: { data: xData },
|
||||
|
||||
Reference in New Issue
Block a user