merge
This commit is contained in:
@@ -5,9 +5,9 @@
|
||||
v-bind="$attrs"
|
||||
:title="title"
|
||||
ref="chartRef"
|
||||
:option="option"
|
||||
:charts-id="chartsId"
|
||||
:bar-type="barType"
|
||||
@refresh="refreshChart"
|
||||
>
|
||||
<template #formSlot v-if="filterItems.length > 0 || Object.keys(extraFilters).length > 0">
|
||||
<el-form :model="formData" label-width="auto">
|
||||
@@ -156,20 +156,6 @@ const filterChange = () => {
|
||||
emit('update', formatEmitData());
|
||||
};
|
||||
|
||||
// 初始化图表
|
||||
const refreshChart = async () => {
|
||||
if (!chartRef.value?.commonChartRef) return;
|
||||
chartRef.value.commonChartRef.disposeEchartsByKey(props.chartsId);
|
||||
chartRef.value.commonChartRef.option = props.option;
|
||||
chartRef.value.commonChartRef.initChart();
|
||||
};
|
||||
// 监听配置项
|
||||
watch(
|
||||
() => props.option,
|
||||
async () => {
|
||||
await refreshChart();
|
||||
}
|
||||
);
|
||||
// 监听插槽中的额外筛选条件
|
||||
watch(
|
||||
() => props.extraFilters,
|
||||
|
||||
@@ -13,7 +13,7 @@ const commonEchartColor = {
|
||||
// y轴文字颜色
|
||||
yAxisColor: '#333',
|
||||
// 分割线颜色
|
||||
splitLineColor: '#00000015',
|
||||
splitLineColor: 'rgba(0,0,0,0.05)',
|
||||
// 提示框背景色
|
||||
tooltipBgColor: '#fff',
|
||||
// 提示框文字颜色
|
||||
@@ -268,6 +268,8 @@ const barChart = (
|
||||
},
|
||||
]),
|
||||
};
|
||||
} else {
|
||||
item.showBackground = false;
|
||||
}
|
||||
return item;
|
||||
}) ?? [];
|
||||
|
||||
@@ -5,6 +5,13 @@
|
||||
<div class="operation-container">
|
||||
<slot v-if="showFilterContent" name="formSlot"></slot>
|
||||
<el-space>
|
||||
<el-icon
|
||||
v-if="showChangeModel && barType === 'barChart' && option?.series?.length > 1"
|
||||
class="common-icon-style"
|
||||
:title="isStack ? '切换为平铺模式' : '切换为堆叠模式'"
|
||||
@click="changeModel"
|
||||
><Switch
|
||||
/></el-icon>
|
||||
<el-popover
|
||||
v-if="$slots.formSlot && !showFilterContent"
|
||||
:visible="popoverVisible"
|
||||
@@ -61,6 +68,7 @@ const props = withDefaults(
|
||||
loading?: boolean; // 加载状态
|
||||
nodata?: boolean; // 无数据状态
|
||||
option?: any;
|
||||
showChangeModel?: boolean; // 是否展示切换堆叠/平铺的按钮
|
||||
}>(),
|
||||
{
|
||||
title: '',
|
||||
@@ -71,6 +79,7 @@ const props = withDefaults(
|
||||
loading: false,
|
||||
nodata: false,
|
||||
option: () => {},
|
||||
showChangeModel: false,
|
||||
}
|
||||
);
|
||||
// const emits = defineEmits(['refresh']);
|
||||
@@ -91,16 +100,43 @@ defineExpose({
|
||||
const refreshChart = async () => {
|
||||
if (!commonChartRef.value) return;
|
||||
commonChartRef.value.disposeEchartsByKey(props.chartsId);
|
||||
commonChartRef.value.option = props.option;
|
||||
commonChartRef.value.option = chartOption.value;
|
||||
commonChartRef.value.initChart();
|
||||
};
|
||||
// 监听配置项
|
||||
const chartOption = ref<any>();
|
||||
const isStack = ref(false);
|
||||
watch(
|
||||
() => props.option,
|
||||
async () => {
|
||||
chartOption.value = props.option;
|
||||
isStack.value = chartOption.value.series?.[0]?.stack === 'total';
|
||||
await refreshChart();
|
||||
}
|
||||
);
|
||||
|
||||
// 切换柱状图状态
|
||||
const changeModel = async () => {
|
||||
if (isStack.value) {
|
||||
chartOption.value.series.forEach((item: any) => {
|
||||
delete item.stack;
|
||||
item.label.show = false;
|
||||
});
|
||||
isStack.value = false;
|
||||
} else {
|
||||
chartOption.value.series.forEach((item: any) => {
|
||||
item.stack = 'total';
|
||||
item.label = {
|
||||
show: true,
|
||||
formatter: (params: any) => {
|
||||
return params.value || '';
|
||||
},
|
||||
};
|
||||
});
|
||||
isStack.value = true;
|
||||
}
|
||||
await refreshChart();
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.container {
|
||||
|
||||
@@ -27,7 +27,7 @@ export const FILE_TYPE = {
|
||||
MODEL_3D_FILE: 13,
|
||||
/** 试验数据闭环报告 */
|
||||
TEST_CLOSURE_REPORT: 14,
|
||||
/** 复盘报告 */
|
||||
/** 复盘报告(仅Lyric租户) */
|
||||
REVIEW_FILE: 15,
|
||||
/** 结果视频 */
|
||||
VIDEO_FILE: 16,
|
||||
|
||||
@@ -135,9 +135,11 @@ export const disposeDisabledExeStatus = (
|
||||
// 审批未通过的 不能改成 已完成 、已关闭 、已闭环
|
||||
if (
|
||||
Number(taskInfo.approvalStatus) !== TASK_APPROVE_STATUS_ENUM.APPROVED &&
|
||||
(option.value === TASK_PROCESS_STATUS.COMPLETED ||
|
||||
option.value === TASK_PROCESS_STATUS.CLOSED_LOOP ||
|
||||
option.value === TASK_PROCESS_STATUS.CLOSED)
|
||||
[
|
||||
TASK_PROCESS_STATUS.COMPLETED,
|
||||
TASK_PROCESS_STATUS.CLOSED_LOOP,
|
||||
TASK_PROCESS_STATUS.CLOSED,
|
||||
].includes(option.value)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -5,12 +5,7 @@
|
||||
ref="inputModelTableRef"
|
||||
tableName="RESULT_MODEL"
|
||||
:api="getFileListApiFun"
|
||||
:params="{
|
||||
uuid: runId,
|
||||
fileTypeDictValue: String(FILE_TYPE.MODEL_FILE),
|
||||
fileTypeDictClass: FILE_DICT_CLASS,
|
||||
dictTags: DICT_TAGS,
|
||||
}"
|
||||
:params="getParamsByTypeFun(FILE_TYPE.MODEL_FILE)"
|
||||
showIndex
|
||||
:fullHeight="true"
|
||||
hideSearch
|
||||
@@ -44,12 +39,7 @@
|
||||
ref="calcModelTableRef"
|
||||
tableName="RESULT_FILE"
|
||||
:api="getFileListApiFun"
|
||||
:params="{
|
||||
uuid: runId,
|
||||
fileTypeDictValue: String(FILE_TYPE.CALCULATION_FILE),
|
||||
fileTypeDictClass: FILE_DICT_CLASS,
|
||||
dictTags: DICT_TAGS,
|
||||
}"
|
||||
:params="getParamsByTypeFun(FILE_TYPE.CALCULATION_FILE)"
|
||||
showIndex
|
||||
:fullHeight="true"
|
||||
hideSearch
|
||||
@@ -58,21 +48,21 @@
|
||||
</div>
|
||||
|
||||
<div v-else-if="currentNode === 'calcResult'" class="detail-content">
|
||||
<BaseTable
|
||||
ref="calcResultTableRef"
|
||||
tableName="RESULT_FILE"
|
||||
:api="getFileListApiFun"
|
||||
:params="{
|
||||
uuid: runId,
|
||||
fileTypeDictValue: String(FILE_TYPE.CALCULATION_FILE),
|
||||
fileTypeDictClass: FILE_DICT_CLASS,
|
||||
dictTags: DICT_TAGS,
|
||||
}"
|
||||
showIndex
|
||||
:fullHeight="true"
|
||||
hideSearch
|
||||
:actionList="calcFileActionList"
|
||||
/>
|
||||
<div class="sim-params-tabs">
|
||||
<el-radio-group v-model="currentCalcResultNodeId" @change="flowNodeRadioChangeFun">
|
||||
<el-radio-button v-for="item in flowNodeList" :key="item.uuid" :value="item.uuid">
|
||||
{{ item.nodeName }}
|
||||
</el-radio-button>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<div class="sim-params-content">
|
||||
<RunDataPage
|
||||
v-if="currentCalcResultNode"
|
||||
:nodeInfo="currentCalcResultNode"
|
||||
:fileId="currentCalcResultNode.outputDirId"
|
||||
:readonly="true"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else-if="currentNode === 'keyResult'" class="detail-content">
|
||||
@@ -81,6 +71,7 @@
|
||||
<el-radio-button value="1">{{ $t('数据谱系.云图结果') }}</el-radio-button>
|
||||
<el-radio-button value="2">{{ $t('数据谱系.曲线结果') }}</el-radio-button>
|
||||
<el-radio-button value="3">{{ $t('数据谱系.数值指标') }}</el-radio-button>
|
||||
<el-radio-button value="4">{{ $t('数据谱系.视频文件') }}</el-radio-button>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<div class="key-result-content">
|
||||
@@ -89,12 +80,7 @@
|
||||
ref="cloudImageTableRef"
|
||||
tableName="RESULT_PNG"
|
||||
:api="getFileListApiFun"
|
||||
:params="{
|
||||
uuid: runId,
|
||||
fileTypeDictValue: String(FILE_TYPE.PNG_FILE),
|
||||
fileTypeDictClass: FILE_DICT_CLASS,
|
||||
dictTags: DICT_TAGS,
|
||||
}"
|
||||
:params="getKeyResultParamsFun(FILE_TYPE.PNG_FILE)"
|
||||
showIndex
|
||||
:fullHeight="true"
|
||||
hideSearch
|
||||
@@ -105,12 +91,7 @@
|
||||
ref="curveTableRef"
|
||||
tableName="RESULT_CURVE"
|
||||
:api="getFileListApiFun"
|
||||
:params="{
|
||||
uuid: runId,
|
||||
fileTypeDictValue: String(FILE_TYPE.CANVAS_FILE),
|
||||
fileTypeDictClass: FILE_DICT_CLASS,
|
||||
dictTags: DICT_TAGS,
|
||||
}"
|
||||
:params="getKeyResultParamsFun(FILE_TYPE.CANVAS_FILE)"
|
||||
showIndex
|
||||
:fullHeight="true"
|
||||
hideSearch
|
||||
@@ -131,6 +112,17 @@
|
||||
{{ PERFORMANCE_UNIT.O[row.unit] }}
|
||||
</template>
|
||||
</BaseTable>
|
||||
<BaseTable
|
||||
v-else-if="keyResultType === '4'"
|
||||
ref="videoTableRef"
|
||||
tableName="RESULT_REPORT"
|
||||
:api="getFileListApiFun"
|
||||
:params="getKeyResultParamsFun(FILE_TYPE.VIDEO_FILE)"
|
||||
showIndex
|
||||
:fullHeight="true"
|
||||
hideSearch
|
||||
:actionList="videoActionList"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -139,12 +131,7 @@
|
||||
ref="reportTableRef"
|
||||
tableName="RESULT_REPORT"
|
||||
:api="getFileListApiFun"
|
||||
:params="{
|
||||
uuid: runId,
|
||||
fileTypeDictValue: String(FILE_TYPE.REPORT_FILE),
|
||||
fileTypeDictClass: FILE_DICT_CLASS,
|
||||
dictTags: DICT_TAGS,
|
||||
}"
|
||||
:params="getParamsByTypeFun(FILE_TYPE.REPORT_FILE)"
|
||||
showIndex
|
||||
:fullHeight="true"
|
||||
hideSearch
|
||||
@@ -157,12 +144,7 @@
|
||||
ref="testDataTableRef"
|
||||
tableName="RESULT_REPORT"
|
||||
:api="getFileListApiFun"
|
||||
:params="{
|
||||
uuid: runId,
|
||||
fileTypeDictValue: String(FILE_TYPE.TEST_CLOSURE_REPORT),
|
||||
fileTypeDictClass: FILE_DICT_CLASS,
|
||||
dictTags: DICT_TAGS,
|
||||
}"
|
||||
:params="getParamsByTypeFun(FILE_TYPE.TEST_CLOSURE_REPORT)"
|
||||
showIndex
|
||||
:fullHeight="true"
|
||||
hideSearch
|
||||
@@ -170,17 +152,15 @@
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div v-else-if="currentNode === 'reviewReport'" class="detail-content">
|
||||
<div
|
||||
v-else-if="currentNode === 'reviewReport' && enableConfigByTenant([TENANT_ENUM.LYRIC])"
|
||||
class="detail-content"
|
||||
>
|
||||
<BaseTable
|
||||
ref="reviewReportTableRef"
|
||||
tableName="RESULT_REPORT"
|
||||
:api="getFileListApiFun"
|
||||
:params="{
|
||||
uuid: runId,
|
||||
fileTypeDictValue: String(FILE_TYPE.REVIEW_FILE),
|
||||
fileTypeDictClass: FILE_DICT_CLASS,
|
||||
dictTags: DICT_TAGS,
|
||||
}"
|
||||
:params="getParamsByTypeFun(FILE_TYPE.REVIEW_FILE)"
|
||||
showIndex
|
||||
:fullHeight="true"
|
||||
hideSearch
|
||||
@@ -199,6 +179,7 @@ import { getSimulationTaskFileApi } from '@/api/data/dataAnalysis';
|
||||
import { getRunPerformanceApi } from '@/api/task/taskpool';
|
||||
import { FILE_TYPE } from '@/utils/enum/file';
|
||||
import FlowNodeParamTable from '@/components/flow/flowNodeParamTable.vue';
|
||||
import RunDataPage from '@/views/task/execution/components/runDetailPage/runPagecomponent/runDataPage.vue';
|
||||
import { listSimulationFlowNodeApi } from '@/api/project/run';
|
||||
import { getRunListByRunIdListApi } from '@/api/project/node';
|
||||
import { queryFlowTemplateDetailApi } from '@/api/capability/flow';
|
||||
@@ -206,6 +187,7 @@ import { useDict } from '@/utils/useDict';
|
||||
import FilePreview from '@/components/common/filePreview/index.vue';
|
||||
import { downloadFileById } from '@/utils/file';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
import { enableConfigByTenant, TENANT_ENUM } from '@/tenants/tenant';
|
||||
|
||||
const FILE_DICT_CLASS = 'ALL_FILE_TYPE';
|
||||
const DICT_TAGS = ['fileTypeDictClass', 'fileTypeDictValue'];
|
||||
@@ -213,14 +195,18 @@ const DICT_TAGS = ['fileTypeDictClass', 'fileTypeDictValue'];
|
||||
interface Props {
|
||||
currentNode?: string;
|
||||
runId?: string;
|
||||
taskId?: string;
|
||||
rowData?: Record<string, any>;
|
||||
pedigreeType?: 'task' | 'run';
|
||||
defaultKeyResultType?: '1' | '2' | '3' | string;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
currentNode: 'inputModel',
|
||||
runId: '',
|
||||
taskId: '',
|
||||
rowData: () => ({}),
|
||||
pedigreeType: 'run',
|
||||
defaultKeyResultType: '1',
|
||||
});
|
||||
const { PERFORMANCE_UNIT } = useDict('PERFORMANCE_UNIT');
|
||||
@@ -262,17 +248,23 @@ const reviewReportActionList = [
|
||||
{ title: '预览', type: 'primary', click: previewFileFun },
|
||||
{ title: '下载', type: 'primary', click: downloadFileFun },
|
||||
];
|
||||
const videoActionList = [
|
||||
{ title: '预览', type: 'primary', click: previewFileFun },
|
||||
{ title: '下载', type: 'primary', click: downloadFileFun },
|
||||
];
|
||||
|
||||
const keyResultType = ref('1');
|
||||
|
||||
const flowNodeList = ref<any[]>([]);
|
||||
const currentFlowNodeId = ref<string>('');
|
||||
const runInfo = ref<any>({});
|
||||
const paramTableRef = ref();
|
||||
const currentFlowNode = ref<any>(null);
|
||||
const currentPageInfo = ref<any>({});
|
||||
const nodeConfigList = ref<any>({});
|
||||
|
||||
const currentCalcResultNodeId = ref<string>('');
|
||||
const currentCalcResultNode = ref<any>(null);
|
||||
|
||||
const fetchFlowNodesFun = async () => {
|
||||
if (!props.runId) {
|
||||
flowNodeList.value = [];
|
||||
@@ -318,6 +310,10 @@ const fetchFlowNodesFun = async () => {
|
||||
currentFlowNodeId.value = flowNodeList.value[0].uuid;
|
||||
flowNodeRadioChangeFun(flowNodeList.value[0].uuid);
|
||||
}
|
||||
if (flowNodeList.value.length > 0 && !currentCalcResultNodeId.value) {
|
||||
currentCalcResultNodeId.value = flowNodeList.value[0].uuid;
|
||||
flowNodeRadioChangeFun(flowNodeList.value[0].uuid);
|
||||
}
|
||||
} else {
|
||||
flowNodeList.value = [];
|
||||
}
|
||||
@@ -357,22 +353,53 @@ const mergeUserParamsFun = (list: any[], userParams: any): any[] => {
|
||||
};
|
||||
|
||||
const getFileListApiFun = async (params: any) => {
|
||||
const res: any = await getSimulationTaskFileApi({
|
||||
...params,
|
||||
runId: props.runId,
|
||||
});
|
||||
return res;
|
||||
if (props.pedigreeType === 'task') {
|
||||
const res: any = await getSimulationTaskFileApi({
|
||||
...params,
|
||||
runId: props.runId,
|
||||
});
|
||||
return res;
|
||||
} else {
|
||||
const res: any = await getSimulationTaskFileApi({
|
||||
...params,
|
||||
runId: props.runId,
|
||||
});
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
const getParamsByTypeFun = (fileType: number) => {
|
||||
if (props.pedigreeType === 'task') {
|
||||
return {
|
||||
uuid: props.taskId,
|
||||
fileBizType: String(fileType),
|
||||
level: 'task',
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
uuid: props.runId,
|
||||
fileTypeDictValue: String(fileType),
|
||||
fileTypeDictClass: FILE_DICT_CLASS,
|
||||
dictTags: DICT_TAGS,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const getKeyResultParamsFun = (fileType: number) => {
|
||||
return getParamsByTypeFun(fileType);
|
||||
};
|
||||
|
||||
const cloudImageTableRef = ref();
|
||||
const curveTableRef = ref();
|
||||
const performanceTableRef = ref();
|
||||
const videoTableRef = ref();
|
||||
|
||||
const refreshKeyResultTableFun = () => {
|
||||
const tableRefMap: Record<string, any> = {
|
||||
'1': cloudImageTableRef,
|
||||
'2': curveTableRef,
|
||||
'3': performanceTableRef,
|
||||
'4': videoTableRef,
|
||||
};
|
||||
if (keyResultType.value === '3') {
|
||||
fetchPerformanceListFun();
|
||||
@@ -392,6 +419,8 @@ const flowNodeRadioChangeFun = (uuid: string) => {
|
||||
const nodeName = selectedNode.nodeName || '';
|
||||
const templateConfig = nodeConfigList.value[nodeName] || [];
|
||||
currentNodeParams.value = mergeUserParamsFun(templateConfig, userParams);
|
||||
|
||||
currentCalcResultNode.value = selectedNode;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -401,6 +430,9 @@ watch(
|
||||
if (newVal === 'simParams') {
|
||||
currentFlowNodeId.value = '';
|
||||
fetchFlowNodesFun();
|
||||
} else if (newVal === 'calcResult') {
|
||||
currentCalcResultNodeId.value = '';
|
||||
fetchFlowNodesFun();
|
||||
} else if (newVal === 'keyResult' && props.defaultKeyResultType) {
|
||||
keyResultType.value = props.defaultKeyResultType;
|
||||
refreshKeyResultTableFun();
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
<template>
|
||||
<Dialog v-model="visible" :diaTitle="$t('数据谱系.算例数据谱系')" width="90%" height="90%">
|
||||
<Dialog
|
||||
v-model="visible"
|
||||
:diaTitle="pedigreeType === 'task' ? $t('数据谱系.任务数据谱系') : $t('数据谱系.算例数据谱系')"
|
||||
width="90%"
|
||||
height="90%"
|
||||
>
|
||||
<div class="pedigree-dialog-content">
|
||||
<div class="flow-section">
|
||||
<div class="section-title">
|
||||
@@ -7,7 +12,12 @@
|
||||
<span class="title-text">{{ $t('数据谱系.谱系图') }}</span>
|
||||
</div>
|
||||
<div class="flow-wrapper">
|
||||
<PedigreeFlow ref="flowRef" :currentNodeId="currentNodeId" @nodeClick="nodeClickFun" />
|
||||
<PedigreeFlow
|
||||
ref="flowRef"
|
||||
:currentNodeId="currentNodeId"
|
||||
:pedigreeType="pedigreeType"
|
||||
@nodeClick="nodeClickFun"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -20,7 +30,9 @@
|
||||
<PedigreeDetail
|
||||
:currentNode="currentNodeId"
|
||||
:runId="runId"
|
||||
:taskId="taskId"
|
||||
:rowData="rowData"
|
||||
:pedigreeType="pedigreeType"
|
||||
:defaultKeyResultType="defaultKeyResultType"
|
||||
/>
|
||||
</div>
|
||||
@@ -42,12 +54,14 @@ interface Props {
|
||||
modelValue?: boolean;
|
||||
rowData?: Record<string, any>;
|
||||
dataType?: '模型文件' | '仿真报告' | '计算文件' | '结果曲线' | '结果云图' | string;
|
||||
pedigreeType?: 'task' | 'run';
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
modelValue: false,
|
||||
rowData: () => ({}),
|
||||
dataType: '',
|
||||
pedigreeType: 'run',
|
||||
});
|
||||
|
||||
const emits = defineEmits(['update:modelValue', 'close']);
|
||||
@@ -103,6 +117,10 @@ const runId = computed(() => {
|
||||
return props.rowData?.ownRunId || props.rowData?.runId || '';
|
||||
});
|
||||
|
||||
const taskId = computed(() => {
|
||||
return props.rowData?.owntaskId || props.rowData?.taskId || '';
|
||||
});
|
||||
|
||||
const nodeClickFun = (nodeId: string) => {
|
||||
currentNodeId.value = nodeId;
|
||||
};
|
||||
|
||||
@@ -8,15 +8,18 @@
|
||||
import { ref, onMounted, onBeforeUnmount, nextTick, computed, watch } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { Graph } from '@antv/x6';
|
||||
import { enableConfigByTenant, TENANT_ENUM } from '@/tenants/tenant';
|
||||
|
||||
const { t, locale } = useI18n();
|
||||
|
||||
interface Props {
|
||||
currentNodeId?: string;
|
||||
pedigreeType?: 'task' | 'run';
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
currentNodeId: 'inputModel',
|
||||
pedigreeType: 'run',
|
||||
});
|
||||
|
||||
const emits = defineEmits(['nodeClick']);
|
||||
@@ -27,21 +30,41 @@ const resizeObserver = ref<ResizeObserver>();
|
||||
|
||||
const nodeWidth = computed(() => (locale.value === 'EN' ? 160 : 100));
|
||||
const nodeGap = computed(() => (locale.value === 'EN' ? 40 : 60));
|
||||
const totalWidth = computed(() => 8 * nodeWidth.value + 7 * nodeGap.value);
|
||||
|
||||
const flowNodesConfig = [
|
||||
const taskFlowNodesConfig = computed(() => {
|
||||
const baseNodes = [
|
||||
{ id: 'inputModel', labelKey: '数据谱系.输入模型' },
|
||||
{ id: 'calcModel', labelKey: '数据谱系.计算模型' },
|
||||
{ id: 'keyResult', labelKey: '数据谱系.关键结果' },
|
||||
{ id: 'simReport', labelKey: '数据谱系.仿真报告' },
|
||||
{ id: 'testData', labelKey: '数据谱系.试验数据' },
|
||||
];
|
||||
if (enableConfigByTenant([TENANT_ENUM.LYRIC])) {
|
||||
baseNodes.push({ id: 'reviewReport', labelKey: '数据谱系.复盘报告' });
|
||||
}
|
||||
return baseNodes;
|
||||
});
|
||||
|
||||
const runFlowNodesConfig = [
|
||||
{ id: 'inputModel', labelKey: '数据谱系.输入模型' },
|
||||
{ id: 'simParams', labelKey: '数据谱系.仿真参数' },
|
||||
{ id: 'calcModel', labelKey: '数据谱系.计算模型' },
|
||||
{ id: 'calcResult', labelKey: '数据谱系.计算结果' },
|
||||
{ id: 'keyResult', labelKey: '数据谱系.关键结果' },
|
||||
{ id: 'simReport', labelKey: '数据谱系.仿真报告' },
|
||||
{ id: 'testData', labelKey: '数据谱系.试验数据' },
|
||||
{ id: 'reviewReport', labelKey: '数据谱系.复盘报告' },
|
||||
];
|
||||
|
||||
const flowNodesConfig = computed(() => {
|
||||
return props.pedigreeType === 'task' ? taskFlowNodesConfig.value : runFlowNodesConfig;
|
||||
});
|
||||
|
||||
const totalWidth = computed(() => {
|
||||
const nodeCount = flowNodesConfig.value.length;
|
||||
return nodeCount * nodeWidth.value + (nodeCount - 1) * nodeGap.value;
|
||||
});
|
||||
|
||||
const flowNodesData = computed(() =>
|
||||
flowNodesConfig.map((node) => ({
|
||||
flowNodesConfig.value.map((node) => ({
|
||||
id: node.id,
|
||||
label: t(node.labelKey),
|
||||
}))
|
||||
@@ -51,15 +74,17 @@ const getStartXFun = (containerWidth: number) => {
|
||||
return containerWidth >= totalWidth.value ? (containerWidth - totalWidth.value) / 2 : 20;
|
||||
};
|
||||
|
||||
const flowEdges = [
|
||||
{ source: 'inputModel', target: 'simParams' },
|
||||
{ source: 'simParams', target: 'calcModel' },
|
||||
{ source: 'calcModel', target: 'calcResult' },
|
||||
{ source: 'calcResult', target: 'keyResult' },
|
||||
{ source: 'keyResult', target: 'simReport' },
|
||||
{ source: 'simReport', target: 'testData' },
|
||||
{ source: 'testData', target: 'reviewReport' },
|
||||
];
|
||||
const flowEdges = computed(() => {
|
||||
const nodes = flowNodesConfig.value;
|
||||
const edges = [];
|
||||
for (let i = 0; i < nodes.length - 1; i++) {
|
||||
edges.push({
|
||||
source: nodes[i].id,
|
||||
target: nodes[i + 1].id,
|
||||
});
|
||||
}
|
||||
return edges;
|
||||
});
|
||||
|
||||
const defaultBodyAttrs = {
|
||||
fill: '#fff',
|
||||
@@ -137,7 +162,7 @@ const initGraphFun = () => {
|
||||
});
|
||||
});
|
||||
|
||||
flowEdges.forEach((edge) => {
|
||||
flowEdges.value.forEach((edge) => {
|
||||
graph.value?.addEdge({
|
||||
source: edge.source,
|
||||
target: edge.target,
|
||||
@@ -208,7 +233,7 @@ const updateNodesLabelFun = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
flowNodesConfig.forEach((nodeConfig) => {
|
||||
flowNodesConfig.value.forEach((nodeConfig) => {
|
||||
const node = graph.value?.getCellById(nodeConfig.id);
|
||||
if (node && node.isNode()) {
|
||||
node.attr('label/text', t(nodeConfig.labelKey));
|
||||
@@ -224,7 +249,7 @@ const updateNodesSizeAndPositionFun = () => {
|
||||
const containerWidth = containerRef.value.clientWidth || 1200;
|
||||
const startX = getStartXFun(containerWidth);
|
||||
|
||||
flowNodesConfig.forEach((nodeConfig, index) => {
|
||||
flowNodesConfig.value.forEach((nodeConfig, index) => {
|
||||
const node = graph.value?.getCellById(nodeConfig.id);
|
||||
if (node && node.isNode()) {
|
||||
const x = startX + (nodeWidth.value + nodeGap.value) * index;
|
||||
@@ -239,6 +264,19 @@ watch(locale, () => {
|
||||
updateNodesSizeAndPositionFun();
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.pedigreeType,
|
||||
() => {
|
||||
if (graph.value) {
|
||||
graph.value.dispose();
|
||||
graph.value = undefined;
|
||||
}
|
||||
nextTick(() => {
|
||||
initGraphFun();
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
defineExpose({
|
||||
setSelectedNodeFun,
|
||||
});
|
||||
|
||||
@@ -284,12 +284,8 @@
|
||||
v-model="pedigreeVisible"
|
||||
:rowData="currentPedigreeRow"
|
||||
:dataType="currentModel"
|
||||
:pedigreeType="pedigreeType"
|
||||
/>
|
||||
<TaskPedigreeDialog
|
||||
v-model="taskPedigreeVisible"
|
||||
:rowData="currentPedigreeRow"
|
||||
:dataType="currentModel"
|
||||
></TaskPedigreeDialog>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
@@ -333,7 +329,6 @@ import { downloadFileById } from '@/utils/file';
|
||||
import { exportToPdf } from '@/utils/exportPdf';
|
||||
import dayjs from 'dayjs';
|
||||
import { CommonStore } from '@/stores/common';
|
||||
import TaskPedigreeDialog from './components/Taskpedigree/pedigreeDialog.vue';
|
||||
|
||||
const commonStore = CommonStore();
|
||||
|
||||
@@ -349,7 +344,7 @@ const showRunDetailDialog = ref(false);
|
||||
const showPerformanceInfoDialog = ref(false);
|
||||
const showAnalysisDialog = ref(false);
|
||||
const pedigreeVisible = ref(false);
|
||||
const taskPedigreeVisible = ref(false);
|
||||
const pedigreeType = ref<'task' | 'run'>('run');
|
||||
const currentPedigreeRow = ref<any>({});
|
||||
const dictModeOptions = commonStore.getDictData('ALL_FILE_TYPE').A || [];
|
||||
const tableRef = ref();
|
||||
@@ -525,6 +520,7 @@ const actionList = ref<any>([
|
||||
return;
|
||||
}
|
||||
currentPedigreeRow.value = row;
|
||||
pedigreeType.value = 'run';
|
||||
pedigreeVisible.value = true;
|
||||
},
|
||||
hide: (row: any) => {
|
||||
@@ -541,7 +537,8 @@ const actionList = ref<any>([
|
||||
return;
|
||||
}
|
||||
currentPedigreeRow.value = row;
|
||||
taskPedigreeVisible.value = true;
|
||||
pedigreeType.value = 'task';
|
||||
pedigreeVisible.value = true;
|
||||
},
|
||||
hide: (row: any) => {
|
||||
return !row.owntaskId || row.ownRunId;
|
||||
|
||||
@@ -56,9 +56,9 @@ const statusColorList = [
|
||||
'rgb(179, 225, 157)', // 已闭环
|
||||
];
|
||||
const performanceColorList = [
|
||||
'rgb(200, 201, 204)',
|
||||
getThemeColor('--el-color-danger'),
|
||||
getThemeColor('--el-color-success'),
|
||||
'rgb(200, 201, 204)', // 未分析
|
||||
getThemeColor('--el-color-danger'), // 不合格
|
||||
getThemeColor('--el-color-success'), // 合格
|
||||
];
|
||||
// 难度系数颜色列表
|
||||
const difficultyCountColorList = [
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
:charts-id="'performanceCompletion-' + resultTagType"
|
||||
:bar-type="'barChart'"
|
||||
:option="chartOption"
|
||||
:showChangeModel="true"
|
||||
:filterItems="['projectName', 'projectCode']"
|
||||
@update="initCompleteChart"
|
||||
/>
|
||||
@@ -16,12 +17,13 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
import commonFilterChart from '@/components/common/echartCard/commonFilterChart.vue';
|
||||
import { TASK_CALCULATE_STATUS_OBJ } from '@/utils/enum/task';
|
||||
import {
|
||||
getCommonCompleteStatisticsApi,
|
||||
getPerformanceCompleteStatisticsByDisciplineApi,
|
||||
} from '@/api/project/node';
|
||||
import { useDict } from '@/utils/useDict';
|
||||
|
||||
const { RESULT_ACHIEVE_STATUS } = useDict('RESULT_ACHIEVE_STATUS');
|
||||
const props = defineProps({
|
||||
// x轴 机台、学科discipline
|
||||
resultTagType: {
|
||||
@@ -61,17 +63,12 @@ const initCompleteChart = async (formData: any) => {
|
||||
res.data?.result?.map((item: any) => {
|
||||
return item.name;
|
||||
}) || [];
|
||||
const allExeStatus = Object.keys(TASK_CALCULATE_STATUS_OBJ);
|
||||
titles =
|
||||
allExeStatus?.map((item: any) => {
|
||||
return TASK_CALCULATE_STATUS_OBJ[item] || item;
|
||||
}) || [];
|
||||
const names = allExeStatus || [];
|
||||
|
||||
for (let i = 0; i < names.length; i++) {
|
||||
const str = names[i];
|
||||
const allExeStatus = Object.keys(RESULT_ACHIEVE_STATUS.value.O);
|
||||
titles = Object.values(RESULT_ACHIEVE_STATUS.value.O);
|
||||
for (let i = 0; i < allExeStatus.length; i++) {
|
||||
const str = allExeStatus[i];
|
||||
const obj: any = {
|
||||
name: TASK_CALCULATE_STATUS_OBJ[str] || str,
|
||||
name: titles[i],
|
||||
type: 'bar',
|
||||
|
||||
emphasis: {
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
:option="chartOption"
|
||||
:filterItems="['projectName', 'projectCode']"
|
||||
:projectMultiple="true"
|
||||
:showChangeModel="true"
|
||||
@update="initProjectTaskCompleteChart"
|
||||
/>
|
||||
</template>
|
||||
@@ -50,7 +51,7 @@ const getProjectGroupTaskCompleteStatistics = async (formData: any) => {
|
||||
label: {
|
||||
show: true,
|
||||
formatter: (params: any) => {
|
||||
return params.value;
|
||||
return params.value || '';
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
:option="chartOption"
|
||||
:filterItems="['projectName', 'projectCode', 'discipline']"
|
||||
:extraFilters="extraFilters"
|
||||
:showChangeModel="true"
|
||||
@update="initReviewPassedChart"
|
||||
>
|
||||
<!-- <template #extraFilters="{ extraFilters }">
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
:bar-type="'barChart'"
|
||||
:option="chartOption"
|
||||
:filterItems="['projectName', 'projectCode']"
|
||||
:showChangeModel="true"
|
||||
@update="initTaskCompleteChart"
|
||||
/>
|
||||
</template>
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
:charts-id="'chart-3-userDifficulty'"
|
||||
:bar-type="'barChart'"
|
||||
:option="chartOption"
|
||||
:showChangeModel="true"
|
||||
:filterItems="['userGroup', 'user', 'projectName', 'projectCode', 'discipline']"
|
||||
@update="initUserDifficultyCoefficientChart"
|
||||
/>
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
:charts-id="'chart-2-UserTaskComplete'"
|
||||
:bar-type="'barChart'"
|
||||
:option="chartOption"
|
||||
:showChangeModel="true"
|
||||
:filterItems="['userGroup', 'user', 'projectName', 'projectCode', 'discipline']"
|
||||
@update="initUserTaskCompleteChart"
|
||||
/>
|
||||
@@ -47,7 +48,7 @@ const getUserGroupTaskCompleteStatistics = async (formData: any) => {
|
||||
label: {
|
||||
show: true,
|
||||
formatter: (params: any) => {
|
||||
return params.value;
|
||||
return params.value || '';
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
:full-height="true"
|
||||
:show-setting="false"
|
||||
>
|
||||
<template #leftOptions>
|
||||
<template #leftOptions v-if="!readonly">
|
||||
<el-button type="" @click="asyncFileFun">归档</el-button>
|
||||
<el-upload :show-file-list="false" :before-upload="beforeUploadFun">
|
||||
<el-button class="ml10" type="primary">上传</el-button>
|
||||
@@ -29,6 +29,9 @@
|
||||
<el-button type="primary" class="ml10" @click="downLoadFileFun">下载</el-button>
|
||||
<el-button type="danger" @click="deleteFileFun">删除</el-button>
|
||||
</template>
|
||||
<template #leftOptions v-else>
|
||||
<el-button type="primary" @click="downLoadFileFun">下载</el-button>
|
||||
</template>
|
||||
<template #fileSize="{ row }">
|
||||
<span>{{ formatFileSize(row.fileSize) }}</span>
|
||||
</template>
|
||||
@@ -94,6 +97,10 @@ const props = defineProps({
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
readonly: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
const baseTableRef = ref();
|
||||
const showSyncFileTypeSelectFlag = ref(false);
|
||||
@@ -210,6 +217,9 @@ const actionList = ref([
|
||||
{
|
||||
title: '删除',
|
||||
type: 'danger',
|
||||
hide: () => {
|
||||
return props.readonly;
|
||||
},
|
||||
click: async (row: any) => {
|
||||
const res: any = await dataDelFileApi({ delFileId: row.id });
|
||||
if (res && res.code === 200) {
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
:bar-type="'barChart'"
|
||||
:nodata="taskCompletionAtWorkstations?.xAxis.data.length === 0"
|
||||
:option="taskCompletionAtWorkstations"
|
||||
:showChangeModel="true"
|
||||
>
|
||||
</EchartCard>
|
||||
</div>
|
||||
@@ -18,6 +19,7 @@
|
||||
:bar-type="'barChart'"
|
||||
:nodata="taskCompletionAtDisciplineOption?.xAxis.data.length === 0"
|
||||
:option="taskCompletionAtDisciplineOption"
|
||||
:showChangeModel="true"
|
||||
>
|
||||
</EchartCard>
|
||||
</div>
|
||||
@@ -29,6 +31,7 @@
|
||||
:bar-type="'barChart'"
|
||||
:nodata="taskAchieveAtWorkstations?.xAxis.data.length === 0"
|
||||
:option="taskAchieveAtWorkstations"
|
||||
:showChangeModel="true"
|
||||
>
|
||||
</EchartCard>
|
||||
</div>
|
||||
@@ -39,6 +42,7 @@
|
||||
:bar-type="'barChart'"
|
||||
:nodata="taskAchieveAtDisciplineOption?.xAxis.data.length === 0"
|
||||
:option="taskAchieveAtDisciplineOption"
|
||||
:showChangeModel="true"
|
||||
>
|
||||
</EchartCard>
|
||||
</div>
|
||||
@@ -49,6 +53,7 @@
|
||||
:bar-type="'barChart'"
|
||||
:nodata="performanceCompletionAtWorkstationsOption?.xAxis.data.length === 0"
|
||||
:option="performanceCompletionAtWorkstationsOption"
|
||||
:showChangeModel="true"
|
||||
>
|
||||
</EchartCard>
|
||||
</div>
|
||||
@@ -59,6 +64,7 @@
|
||||
:bar-type="'barChart'"
|
||||
:nodata="performanceCompletionAtDisciplineOption?.xAxis.data.length === 0"
|
||||
:option="performanceCompletionAtDisciplineOption"
|
||||
:showChangeModel="true"
|
||||
>
|
||||
</EchartCard>
|
||||
</div>
|
||||
@@ -69,6 +75,7 @@
|
||||
:bar-type="'barChart'"
|
||||
:nodata="userTaskCompleteOption?.xAxis.data.length === 0"
|
||||
:option="userTaskCompleteOption"
|
||||
:showChangeModel="true"
|
||||
>
|
||||
</EchartCard>
|
||||
</div>
|
||||
@@ -79,6 +86,7 @@
|
||||
:bar-type="'barChart'"
|
||||
:nodata="userDifficultyCoefficientOption?.xAxis.data.length === 0"
|
||||
:option="userDifficultyCoefficientOption"
|
||||
:showChangeModel="true"
|
||||
>
|
||||
</EchartCard>
|
||||
</div>
|
||||
@@ -100,9 +108,10 @@ import { useDict } from '@/utils/useDict';
|
||||
import { TASK_CALCULATE_STATUS_OPTIONS } from '@/utils/enum/task';
|
||||
import { getThemeColor } from '@/utils/theme';
|
||||
|
||||
const { TASK_ACHIEVE_STATUS, DIFFICULTY_COEFFICIENT } = useDict(
|
||||
const { TASK_ACHIEVE_STATUS, DIFFICULTY_COEFFICIENT, RESULT_ACHIEVE_STATUS } = useDict(
|
||||
'TASK_ACHIEVE_STATUS',
|
||||
'DIFFICULTY_COEFFICIENT'
|
||||
'DIFFICULTY_COEFFICIENT',
|
||||
'RESULT_ACHIEVE_STATUS'
|
||||
);
|
||||
const taskCalculateStatusLegendData = TASK_CALCULATE_STATUS_OPTIONS.map((item) => ({
|
||||
name: item.label,
|
||||
@@ -146,6 +155,11 @@ const completionStatusColorList = [
|
||||
getThemeColor('--el-color-danger'),
|
||||
getThemeColor('--el-color-success'),
|
||||
];
|
||||
const performanceColorList = [
|
||||
'rgb(200, 201, 204)', // 未分析
|
||||
getThemeColor('--el-color-danger'), // 不合格
|
||||
getThemeColor('--el-color-success'), // 合格
|
||||
];
|
||||
const difficultyCountColorList = [
|
||||
'#67c23a',
|
||||
'rgb(179, 225, 157)',
|
||||
@@ -437,8 +451,9 @@ const queryPerfCompletionByWorkspace = async () => {
|
||||
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 allExeStatus = RESULT_ACHIEVE_STATUS.value.A;
|
||||
for (let i = 0; i < allExeStatus.length; i++) {
|
||||
const item = allExeStatus[i];
|
||||
const obj: any = {
|
||||
name: item.label,
|
||||
type: 'bar',
|
||||
@@ -454,9 +469,9 @@ const queryPerfCompletionByWorkspace = async () => {
|
||||
}
|
||||
}
|
||||
const option = {
|
||||
color: completionStatusColorList,
|
||||
color: performanceColorList,
|
||||
legend: {
|
||||
data: taskCalculateStatusLegendData,
|
||||
data: Object.values(RESULT_ACHIEVE_STATUS.value.O),
|
||||
},
|
||||
xAxis: {
|
||||
data: xData,
|
||||
@@ -531,8 +546,9 @@ const queryPerfCompletionByDiscipline = async () => {
|
||||
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 allExeStatus = RESULT_ACHIEVE_STATUS.value.A;
|
||||
for (let i = 0; i < allExeStatus.length; i++) {
|
||||
const item = allExeStatus[i];
|
||||
const obj: any = {
|
||||
name: item.label,
|
||||
type: 'bar',
|
||||
@@ -548,9 +564,9 @@ const queryPerfCompletionByDiscipline = async () => {
|
||||
}
|
||||
}
|
||||
const option = {
|
||||
color: completionStatusColorList,
|
||||
color: performanceColorList,
|
||||
legend: {
|
||||
data: taskCalculateStatusLegendData,
|
||||
data: Object.values(RESULT_ACHIEVE_STATUS.value.O),
|
||||
},
|
||||
xAxis: {
|
||||
data: xData,
|
||||
|
||||
Reference in New Issue
Block a user