This commit is contained in:
2025-12-17 14:59:36 +08:00
6 changed files with 355 additions and 42 deletions

View File

@@ -224,6 +224,8 @@ const lang = {
: {
: 'Task Completion Statistics (Workspace)',
: 'Task Completion Statistics (Discipline)',
: 'Task Quality Statistics (Workspace)',
: 'Task Quality Statistics (Discipline)',
: 'Performance Completion Statistics (Workspace)',
: 'Performance Completion Statistics (Discipline)',
: 'Member Task Progress Statistics',

View File

@@ -221,6 +221,8 @@ const lang = {
: {
: '任务完成统计(工位)',
: '任务完成统计(学科)',
: '任务达成统计(工位)',
: '任务达成统计(学科)',
: '指标完成统计(工位)',
: '指标完成统计(学科)',
: '成员任务进度统计',

View File

@@ -746,26 +746,38 @@ const onVersionChangeFun = () => {
});
};
const extractTableData: any = ref([]);
const queryTaskPoolFun = async () => {
if (!currentPoolBriefVersion.value) {
const queryTaskPoolFun = async (poolBriefVersion?: any) => {
const version = poolBriefVersion || currentPoolBriefVersion.value;
if (!version) {
return;
}
const req = {
poolName: currentPoolBriefVersion.value.poolName,
version: currentPoolBriefVersion.value.poolVersion,
poolName: version.poolName,
version: version.poolVersion,
};
console.log('[工况库] 开始加载数据...');
loading.value = true;
const startTime = performance.now();
const res: any = await getTaskPoolApi(req);
const apiTime = performance.now();
console.log(`[工况库] getTaskPool 请求耗时: ${(apiTime - startTime).toFixed(2)}ms`);
loading.value = false;
let tree = [];
let tree: any = [];
if (res.code === 200 && res.data.poolBrief && res.data && res.data.nodes) {
const transformStart = performance.now();
tree = transformPoolNodesToTree(res.data.nodes);
console.log(`[工况库] 数据转换耗时: ${(performance.now() - transformStart).toFixed(2)}ms`);
tableData.value = tree;
originalSnapshot = cloneDeep(tree);
isEmptyPool.value = false;
if (currentTableType.value === TableViewType.LIST) {
mergeListTableColumnsFun(res.data.nodes);
}
nextTick(() => {
console.log(`[工况库] 总渲染耗时: ${(performance.now() - startTime).toFixed(2)}ms`);
setTimeout(() => {
originalSnapshot = cloneDeep(tree);
}, 0);
});
expandAllFun();
} else {
tableData.value = [];
@@ -858,9 +870,9 @@ const queryTaskPoolPerformanceFun = async () => {
performanceData.value = transformPoolNodesToTree(res.data);
}
};
const refreshTreeFun = async () => {
const refreshTreeFun = async (poolBriefVersion?: any) => {
if (props.pageType === 'loadcase') {
await queryTaskPoolFun();
await queryTaskPoolFun(poolBriefVersion);
}
if (props.pageType === 'performance') {
await queryTaskPoolPerformanceFun();
@@ -877,17 +889,17 @@ const queryVersionsFun = async () => {
poolName: currentPoolBrief.value.poolName,
};
const res: any = await getTaskPoolVersionsApi(req);
let targetVersion = null;
if (res.code === 200 && res.data && Array.isArray(res.data) && res.data.length > 0) {
versionList.value = res.data;
if (versionList.value.length > 0) {
currentPoolBriefVersion.value = versionList.value[0];
}
targetVersion = res.data[0];
currentPoolBriefVersion.value = targetVersion;
} else {
versionList.value = [];
currentPoolBriefVersion.value = null;
tableData.value = [];
}
await refreshTreeFun();
await refreshTreeFun(targetVersion);
};
const addPoolModalVisible = ref(false);
const addPoolFun = () => {

View File

@@ -314,11 +314,37 @@ import {
} from '@/api/project/node';
import ProjectSelect from '@/components/common/projectSelect/index.vue';
import { TASK_CALCULATE_STATUS_OBJ, TASK_PROCESS_STATUS_OBJ } from '@/utils/enum/task';
import { getThemeColor } from '@/utils/theme';
const userGroupOptions = ref<any>([]);
const disciplineOptions = ref<any>([]);
const statusColorList = [
getThemeColor('--el-color-info-light-5'),
getThemeColor('--el-color-primary'),
getThemeColor('--el-color-danger'),
getThemeColor('--el-color-success'),
getThemeColor('--el-color-warning'),
];
const performanceColorList = [
getThemeColor('--el-color-info-light-5'),
getThemeColor('--el-color-success'),
];
const difficultyCountColorList = [
getThemeColor('--el-color-success'),
getThemeColor('--el-color-success-light-5'),
getThemeColor('--el-color-warning-light-5'),
getThemeColor('--el-color-warning'),
getThemeColor('--el-color-danger-light-5'),
getThemeColor('--el-color-danger'),
];
// 封装方法,根据对象的某个属性对对象数组进行排序
const sortObjectArray = (arr: any, key: any) => {
return arr.sort((a: any, b: any) => {
return a[key] - b[key];
});
};
// const projectStorageSpaceStatisticsFormData = ref<any>({
// userId: '',
@@ -400,8 +426,12 @@ const initUserProjectStatistics = async () => {
series: [
{
type: 'bar',
name: '项目数量',
barWidth: '30%',
data: yData,
itemStyle: {
color: getThemeColor('--el-color-primary'),
},
},
],
};
@@ -463,10 +493,10 @@ const getUserGroupTaskCompleteStatistics = async () => {
};
const initUserTaskComplete = async () => {
const { xData, seriesData, legendData } = await getUserGroupTaskCompleteStatistics();
// 模拟接口延时
userTaskCompleteChartRef.value.commonChartRef.disposeEchartsByKey('chart-2');
userTaskCompleteChartRef.value.commonChartRef.option = {
color: statusColorList,
title: {
show: false,
},
@@ -575,6 +605,7 @@ const initUserDifficultyCoefficientStatistics = async () => {
// 模拟接口延时
userDifficultyCoefficientChartRef.value.commonChartRef.disposeEchartsByKey('chart-3');
userDifficultyCoefficientChartRef.value.commonChartRef.option = {
color: difficultyCountColorList,
title: {
textStyle: {
fontSize: 20,
@@ -630,7 +661,7 @@ const initUserDifficultyCoefficientStatistics = async () => {
},
]
: null,
series: seriesData,
series: sortObjectArray(seriesData, 'name'),
};
userDifficultyCoefficientChartRef.value.commonChartRef.initChart();
};
@@ -696,6 +727,7 @@ const initTaskCompletionAtWorkstations = async () => {
taskCompletionAtWorkstationsChartRef.value.commonChartRef.disposeEchartsByKey('chart-4');
taskCompletionAtWorkstationsChartRef.value.commonChartRef.option = {
color: statusColorList,
title: {
show: false,
},
@@ -807,6 +839,7 @@ const initTaskCompletionAtDiscipline = async () => {
taskCompletionAtDisciplineChartRef.value.commonChartRef.disposeEchartsByKey('chart-5');
taskCompletionAtDisciplineChartRef.value.commonChartRef.option = {
color: statusColorList,
title: {
show: false,
},
@@ -915,7 +948,8 @@ const initPerformanceCompletionAtWorkstations = async () => {
}
performanceCompletionAtWorkstationsChartRef.value.commonChartRef.disposeEchartsByKey('chart-6');
performanceCompletionAtWorkstationsChartRef.value.commonChartRef.option = {
color: ['#37a93d', '#de4231', '#808080'],
// color: ['#37a93d', '#de4231', '#808080'],
color: performanceColorList,
title: {
show: false,
},
@@ -1029,7 +1063,8 @@ const initPerformanceCompletionAtDiscipline = async () => {
performanceCompletionAtDisciplineChartRef.value.commonChartRef.disposeEchartsByKey('chart-7');
performanceCompletionAtDisciplineChartRef.value.commonChartRef.option = {
color: ['#37a93d', '#de4231', '#808080'],
// color: ['#37a93d', '#de4231', '#808080'],
color: performanceColorList,
title: {
show: false,
},
@@ -1135,8 +1170,6 @@ const initReviewPassed = async () => {
}
}
console.log(seriesData, 'seriesData');
reviewPassedChartRef.value.commonChartRef.disposeEchartsByKey('chart-8');
reviewPassedChartRef.value.commonChartRef.option = {
color: ['#808080', '#b6d634', '#37a93d', '#de4231'],

View File

@@ -2,7 +2,7 @@
<div class="gl-page-content-grey log-page">
<div class="tabs">
<el-tabs v-model="showType" type="card">
<el-tab-pane label="日志" name="1" />
<el-tab-pane label="日志列表" name="1" />
<el-tab-pane label="日志统计" name="2" />
</el-tabs>
</div>

View File

@@ -43,6 +43,27 @@
</template> -->
</EchartCard>
</div>
<!-- 新增 任务达成统计 工位/学科 -->
<div class="chart-box">
<EchartCard
:title="$t('统计分析.任务达成统计工位')"
ref="taskQualityAtWorkstationsChartRef"
:charts-id="'chart-Quality-1'"
:bar-type="'barChart'"
@refresh="queryTaskQualityByWorkspace"
>
</EchartCard>
</div>
<div class="chart-box">
<EchartCard
:title="$t('统计分析.任务达成统计学科')"
ref="taskQualityAtDisciplineChartRef"
:charts-id="'chart-Quality-2'"
:bar-type="'barChart'"
@refresh="queryTaskQualityByDiscipline"
>
</EchartCard>
</div>
<div class="chart-box">
<EchartCard
:title="$t('统计分析.指标完成统计工位')"
@@ -207,15 +228,15 @@
<script setup lang="ts">
import { ref, onMounted, reactive, watchEffect } from 'vue';
import EchartCard from '@/components/common/echartCard/index.vue';
import UserSelect from '@/components/common/userSelect/index.vue';
// import UserSelect from '@/components/common/userSelect/index.vue';
import { userQueryGroupApi } from '@/api/system/user';
import {
getUserGroupProjectStatisticsApi,
getUserGroupTaskCompleteStatisticsApi,
// getUserGroupTaskCompleteStatisticsApi,
queryNodeListApi,
getWorkstationReviewStatisticsApi,
getUserGroupDifficultyStatisticsApi,
getCommonCompleteStatisticsApi,
// getWorkstationReviewStatisticsApi,
// getUserGroupDifficultyStatisticsApi,
// getCommonCompleteStatisticsApi,
} from '@/api/project/node';
import {
getTaskCompleteStatisticsApi,
@@ -226,6 +247,7 @@ import {
// import ProjectSelect from '@/components/common/projectSelect/index.vue';
import { useDict } from '@/utils/useDict';
import { TASK_CALCULATE_STATUS_OPTIONS } from '@/utils/enum/task';
import { getThemeColor } from '@/utils/theme';
const { TASK_EXE_STATUS } = useDict('TASK_EXE_STATUS');
const taskCalculateStatusLegendData = TASK_CALCULATE_STATUS_OPTIONS.map((item) => ({
@@ -262,6 +284,37 @@ const disciplineOptions = ref<any>([]);
// });
const userProjectChartRef = ref();
// 进度状态颜色列表:已驳回、未开始、进行中、已完成、已暂停、已关闭、已延期
const statusColorList = [
getThemeColor('--el-color-danger'),
getThemeColor('--el-color-info-light-5'),
getThemeColor('--el-color-primary'),
getThemeColor('--el-color-success'),
getThemeColor('--el-color-warning'),
getThemeColor('--el-color-info-light-7'),
getThemeColor('--el-color-danger-light-5'),
];
// 完成情况颜色列表:未分析、不合格、合格
const completionStatusColorList = [
getThemeColor('--el-color-info'),
getThemeColor('--el-color-danger'),
getThemeColor('--el-color-success'),
];
const difficultyCountColorList = [
getThemeColor('--el-color-success'),
getThemeColor('--el-color-success-light-5'),
getThemeColor('--el-color-warning-light-5'),
getThemeColor('--el-color-warning'),
getThemeColor('--el-color-danger-light-5'),
getThemeColor('--el-color-danger'),
];
// 封装方法,根据对象的某个属性对对象数组进行排序
const sortObjectArray = (arr: any, key: any) => {
return arr.sort((a: any, b: any) => {
return a[key] - b[key];
});
};
const getUserGroupProjectStatistics = async () => {
const xData: any = [];
const yData: any = [];
@@ -349,9 +402,9 @@ const userTaskCompleteFormData = ref<any>({
tag1: '',
tag2: '',
});
const userTaskCompleteProjectChangeFun = async () => {
await queryUserTaskCompletion();
};
// const userTaskCompleteProjectChangeFun = async () => {
// await queryUserTaskCompletion();
// };
const getUserTaskCompleteStatistics = async () => {
const xData: any = [];
const seriesData: any = [];
@@ -395,6 +448,7 @@ const queryUserTaskCompletion = async () => {
const { xData, seriesData } = await getUserTaskCompleteStatistics();
userTaskCompleteChartRef.value.commonChartRef.disposeEchartsByKey('chart-2');
userTaskCompleteChartRef.value.commonChartRef.option = {
color: statusColorList,
title: {
show: false,
},
@@ -499,6 +553,7 @@ const queryUserDifficultStatistics = async () => {
userDifficultyCoefficientChartRef.value.commonChartRef.disposeEchartsByKey('chart-3');
userDifficultyCoefficientChartRef.value.commonChartRef.option = {
color: difficultyCountColorList,
title: {
textStyle: {
fontSize: 20,
@@ -554,15 +609,16 @@ const queryUserDifficultStatistics = async () => {
},
]
: null,
series: seriesData,
// series: seriesData,
series: sortObjectArray(seriesData, 'name'),
};
userDifficultyCoefficientChartRef.value.commonChartRef.initChart();
};
const taskCompletionAtWorkstationsChartRef = ref();
const taskCompletionAtWorkstationsFormData = reactive<any>({
tag1: '',
});
// const taskCompletionAtWorkstationsFormData = reactive<any>({
// tag1: '',
// });
const queryTaskCompletionByWorkspace = async () => {
let xData: any = [];
const seriesData: any = [];
@@ -604,6 +660,7 @@ const queryTaskCompletionByWorkspace = async () => {
}
taskCompletionAtWorkstationsChartRef.value.commonChartRef.disposeEchartsByKey('chart-4');
taskCompletionAtWorkstationsChartRef.value.commonChartRef.option = {
color: statusColorList,
title: {
show: false,
},
@@ -654,9 +711,9 @@ const queryTaskCompletionByWorkspace = async () => {
taskCompletionAtWorkstationsChartRef.value.commonChartRef.initChart();
};
const initTaskCompletionAtDisciplineFormData = reactive<any>({
tag1: '',
});
// const initTaskCompletionAtDisciplineFormData = reactive<any>({
// tag1: '',
// });
const taskCompletionAtDisciplineChartRef = ref();
const queryTaskCompletionByDiscipline = async () => {
@@ -702,6 +759,7 @@ const queryTaskCompletionByDiscipline = async () => {
taskCompletionAtDisciplineChartRef.value.commonChartRef.disposeEchartsByKey('chart-5');
taskCompletionAtDisciplineChartRef.value.commonChartRef.option = {
color: statusColorList,
title: {
show: false,
},
@@ -752,11 +810,109 @@ const queryTaskCompletionByDiscipline = async () => {
taskCompletionAtDisciplineChartRef.value.commonChartRef.initChart();
};
// 新增 任务达成统计 —— 工位
const taskQualityAtWorkstationsChartRef = ref();
const queryTaskQualityByWorkspace = async () => {
let xData: any = [];
const seriesData: any = [];
// todo 接口待确认
const res: any = await getPerformanceCompleteStatisticsApi({
resultTagType: 'tag5',
tag1: currentProjectUuid.value,
tag2: '',
tag3: '',
tag4: '',
tag5: '',
tag6: '',
tag7: '',
tag8: '',
tag9: '',
tag10: '',
});
if (res && res.code === 200) {
xData = res.data.result.map((item: any) => {
return item.name;
});
for (let i = 0; i < TASK_CALCULATE_STATUS_OPTIONS.length; i++) {
const item = TASK_CALCULATE_STATUS_OPTIONS[i];
const obj: any = {
name: item.label,
type: 'bar',
emphasis: {
focus: 'series',
},
data: [],
};
for (let j = 0; j < res.data.result.length; j++) {
obj.data.push(res.data.result[j]?.statusCount[item.value] || 0);
}
seriesData.push(obj);
}
}
taskQualityAtWorkstationsChartRef.value.commonChartRef.disposeEchartsByKey('chart-Quality-1');
taskQualityAtWorkstationsChartRef.value.commonChartRef.option = {
// color: ['#808080', '#de4231', '#37a93d'],
color: completionStatusColorList,
title: {
show: false,
},
tooltip: {
trigger: 'axis',
},
legend: {
show: true,
top: '0%',
left: 'center',
data: taskCalculateStatusLegendData,
},
grid: {
top: '10%',
bottom: '10%',
left: '5%',
right: '5%',
},
xAxis: {
type: 'category',
data: xData,
},
yAxis: {
type: 'value',
},
dataZoom:
xData.length > 4
? [
{
type: 'slider',
show: true,
xAxisIndex: [0],
start: 0,
end: 100,
textStyle: {
color: 'transparent',
},
maxValueSpan: 4,
minValueSpan: 4,
moveHandleSize: 10,
height: 0,
filterMode: 'empty',
bottom: 15,
},
]
: null,
series: seriesData,
};
taskQualityAtWorkstationsChartRef.value.commonChartRef.initChart();
};
const performanceCompletionAtWorkstationsChartRef = ref();
const queryPerfCompletionByWorkspaceFormData = reactive<any>({
tag1: '',
});
// const queryPerfCompletionByWorkspaceFormData = reactive<any>({
// tag1: '',
// });
const queryPerfCompletionByWorkspace = async () => {
let xData: any = [];
@@ -800,7 +956,8 @@ const queryPerfCompletionByWorkspace = async () => {
}
performanceCompletionAtWorkstationsChartRef.value.commonChartRef.disposeEchartsByKey('chart-6');
performanceCompletionAtWorkstationsChartRef.value.commonChartRef.option = {
color: ['#808080', '#de4231', '#37a93d'],
// color: ['#808080', '#de4231', '#37a93d'],
color: completionStatusColorList,
title: {
show: false,
},
@@ -852,10 +1009,110 @@ const queryPerfCompletionByWorkspace = async () => {
performanceCompletionAtWorkstationsChartRef.value.commonChartRef.initChart();
};
// 新增 任务达成统计 —— 学科
const taskQualityAtDisciplineChartRef = ref();
const queryTaskQualityByDiscipline = async () => {
let xData: any = [];
const seriesData: any = [];
// todo 接口待确认
const res: any = await getPerformanceCompleteStatisticsApi({
resultTagType: 'tag6',
tag1: currentProjectUuid.value,
tag2: '',
tag3: '',
tag4: '',
tag5: '',
tag6: '',
tag7: '',
tag8: '',
tag9: '',
tag10: '',
});
if (res && res.code === 200) {
xData = res.data.result.map((item: any) => {
return item.name;
});
for (let i = 0; i < TASK_CALCULATE_STATUS_OPTIONS.length; i++) {
const item = TASK_CALCULATE_STATUS_OPTIONS[i];
const obj: any = {
name: item.label,
type: 'bar',
emphasis: {
focus: 'series',
},
data: [],
};
for (let j = 0; j < res.data.result.length; j++) {
obj.data.push(res.data.result[j]?.statusCount[item.value] || 0);
}
seriesData.push(obj);
}
}
taskQualityAtDisciplineChartRef.value.commonChartRef.disposeEchartsByKey('chart-Quality-2');
taskQualityAtDisciplineChartRef.value.commonChartRef.option = {
// color: ['#808080', '#de4231', '#37a93d'],
color: completionStatusColorList,
title: {
show: false,
},
tooltip: {
trigger: 'axis',
},
legend: {
show: true,
top: '0%',
left: 'center',
data: taskCalculateStatusLegendData,
},
grid: {
top: '10%',
bottom: '10%',
left: '5%',
right: '5%',
},
xAxis: {
type: 'category',
data: xData,
},
yAxis: {
type: 'value',
},
dataZoom:
xData.length > 4
? [
{
type: 'slider',
show: true,
xAxisIndex: [0],
start: 0,
end: 100,
textStyle: {
color: 'transparent',
},
maxValueSpan: 4,
minValueSpan: 4,
moveHandleSize: 10,
height: 0,
filterMode: 'empty',
bottom: 15,
},
]
: null,
series: seriesData,
};
taskQualityAtDisciplineChartRef.value.commonChartRef.initChart();
};
const performanceCompletionAtDisciplineChartRef = ref();
const queryPerfCompletionByDisciplineFormData = reactive<any>({
tag1: '',
});
// const queryPerfCompletionByDisciplineFormData = reactive<any>({
// tag1: '',
// });
const queryPerfCompletionByDiscipline = async () => {
let xData: any = [];
@@ -900,7 +1157,8 @@ const queryPerfCompletionByDiscipline = async () => {
performanceCompletionAtDisciplineChartRef.value.commonChartRef.disposeEchartsByKey('chart-7');
performanceCompletionAtDisciplineChartRef.value.commonChartRef.option = {
color: ['#808080', '#de4231', '#37a93d'],
// color: ['#808080', '#de4231', '#37a93d'],
color: completionStatusColorList,
title: {
show: false,
},
@@ -1007,6 +1265,12 @@ const initData = async () => {
await queryUserTaskCompletion();
// 难度系数统计难度系数有1、2、3、4、5统计1有几个2有几个。。。
await queryUserDifficultStatistics();
// 新增 todo 暂时没接口
// 按照工位统计任务质量达成情况
// await queryTaskQualityByWorkspace();
// // 按照学科统计任务质量达成情况
// await queryTaskQualityByDiscipline();
};
watchEffect(() => {
if (props.projectUuid) {