1108 lines
34 KiB
Vue
1108 lines
34 KiB
Vue
<template>
|
||
<div class="loadcase">
|
||
<div class="contain" v-if="loadcaseOrPerformanceSwitch || pageType === 'loadcase'">
|
||
<div
|
||
class="flex-end"
|
||
:style="{
|
||
right: loadcaseOrPerformanceSwitch ? '375px' : '165px',
|
||
top: loadcaseOrPerformanceSwitch ? '12px' : '1px',
|
||
}"
|
||
>
|
||
<el-space>
|
||
<template v-if="pageType === 'loadcase' || loadcaseOrPerformanceSwitch">
|
||
<el-button @click="addPoolFun">
|
||
<el-icon class="mr5">
|
||
<Plus />
|
||
</el-icon>
|
||
{{ $t("工况库.创建清单库") }}
|
||
</el-button>
|
||
|
||
<el-button @click="openImportPoolFun">
|
||
<el-icon class="mr5">
|
||
<Upload />
|
||
</el-icon>
|
||
{{ $t("工况库.导入Excel") }}
|
||
</el-button>
|
||
|
||
<el-button @click="onExportPoolFun" :loading="exportLoading">
|
||
<el-icon class="mr5">
|
||
<Download />
|
||
</el-icon>
|
||
{{ $t("工况库.导出Excel") }}
|
||
</el-button>
|
||
</template>
|
||
<el-button type="primary" @click="openAddApproveUserFun">
|
||
<el-icon class="mr5">
|
||
<Finished />
|
||
</el-icon>
|
||
{{ $t("工况库.提交评审") }}
|
||
</el-button>
|
||
<el-button type="danger" @click="openDelPoolFun">
|
||
<el-icon class="mr5">
|
||
<Finished />
|
||
</el-icon>
|
||
{{ $t("工况库.删除库") }}
|
||
</el-button>
|
||
<div class="pool-select select-form">
|
||
<el-form :inline="true">
|
||
<el-form-item :label="$t('工况库.工况清单库')" :label-width="100">
|
||
<el-select
|
||
:teleported="false"
|
||
v-model="currentPoolBrief"
|
||
:props="{ label: 'poolName', value: 'value' }"
|
||
value-key="poolName"
|
||
:fit-input-width="true"
|
||
@change="onPoolChangeFun"
|
||
>
|
||
<el-option
|
||
v-for="item in poolList"
|
||
:key="item.value"
|
||
:label="item.poolName"
|
||
:value="item"
|
||
/>
|
||
</el-select>
|
||
</el-form-item>
|
||
<el-form-item :label="$t('工况库.版本')" :label-width="40">
|
||
<el-select
|
||
:teleported="false"
|
||
v-model="currentPoolBriefVersion"
|
||
:props="{ label: 'poolVersion', value: 'value' }"
|
||
value-key="poolVersion"
|
||
:fit-input-width="true"
|
||
@change="onVersionChangeFun"
|
||
>
|
||
<el-option
|
||
v-for="item in versionList"
|
||
:key="item.value"
|
||
:label="item.poolVersion"
|
||
:value="item"
|
||
/>
|
||
</el-select>
|
||
</el-form-item>
|
||
<el-form-item :label="$t('工况库.显示配置')" :label-width="80">
|
||
<el-select
|
||
v-model="currentTableType"
|
||
:fit-input-width="true"
|
||
:options="tableTypeOptions"
|
||
>
|
||
</el-select>
|
||
</el-form-item>
|
||
</el-form>
|
||
</div>
|
||
</el-space>
|
||
</div>
|
||
<loadCaseTable
|
||
v-show="currentTableType==='tree'"
|
||
ref="treeTableRef"
|
||
tableName="TASK_POOL"
|
||
:modalTableNameList="['TASK_POOL_CATEGORY','TASK_POOL_TASK','TASK_POOL_PERFORMANCE']"
|
||
:data="tableData"
|
||
:loading="loading"
|
||
:editMode="true"
|
||
> </loadCaseTable>
|
||
<loadCaseTable
|
||
v-show="currentTableType==='list'"
|
||
ref="listTableRef"
|
||
border="full"
|
||
:hasOperationColumn="false"
|
||
readonly
|
||
tableName="TASK_POOL_LIST"
|
||
:data="extractTableData"
|
||
:loading="loading"
|
||
:editMode="false"
|
||
>
|
||
</loadCaseTable>
|
||
<loadcase-pro-table
|
||
v-if="false"
|
||
ref="treeTableRef2"
|
||
:columns="tableColumns"
|
||
:data-source="tableData"
|
||
:checkStrictly="true"
|
||
:loading="loading"
|
||
:leftVisible="true"
|
||
:toolbarConfig="{
|
||
enabled: true,
|
||
custom: true,
|
||
}"
|
||
:key="tableKey"
|
||
:showHeader="false"
|
||
:isAdaptTableHeight="true"
|
||
@refresh="refreshData"
|
||
:readonly="true"
|
||
>
|
||
<template #toolbar_tools_extra>
|
||
<span v-if="pageType === 'performance'">
|
||
显示配置:
|
||
<el-radio-group
|
||
v-model="loadcaseOrPerformanceSwitch"
|
||
@change="changeLoadcaseOrPerformanceType"
|
||
>
|
||
<el-radio :value="true" size="large">树结构</el-radio>
|
||
<el-radio :value="false" size="large">表结构</el-radio>
|
||
</el-radio-group>
|
||
</span>
|
||
</template>
|
||
</loadcase-pro-table>
|
||
</div>
|
||
<div class="contain" v-if="!loadcaseOrPerformanceSwitch && pageType !== 'loadcase'">
|
||
<div class="pool-select">
|
||
<el-form :inline="true">
|
||
<el-form-item :label="$t('工况库.工况清单库')" :label-width="100">
|
||
<el-select
|
||
:teleported="false"
|
||
v-model="currentPoolBrief"
|
||
:props="{ label: 'poolName', value: 'value' }"
|
||
value-key="poolName"
|
||
:fit-input-width="true"
|
||
@change="onPoolChangeFun"
|
||
>
|
||
<el-option
|
||
v-for="item in poolList"
|
||
:key="item.value"
|
||
:label="item.poolName"
|
||
:value="item"
|
||
/>
|
||
</el-select>
|
||
</el-form-item>
|
||
<el-form-item :label="$t('工况库.版本')" :label-width="40">
|
||
<el-select
|
||
:teleported="false"
|
||
v-model="currentPoolBriefVersion"
|
||
:props="{ label: 'poolVersion', value: 'value' }"
|
||
value-key="poolVersion"
|
||
:fit-input-width="true"
|
||
@change="onVersionChangeFun"
|
||
>
|
||
<el-option
|
||
v-for="item in versionList"
|
||
:key="item.value"
|
||
:label="item.poolVersion"
|
||
:value="item"
|
||
/>
|
||
</el-select>
|
||
</el-form-item>
|
||
</el-form>
|
||
</div>
|
||
<loadCaseTable
|
||
:editMode="false"
|
||
ref="treeTableRef"
|
||
:loading="performanceLoading"
|
||
readonly
|
||
:loadCaseTable="false"
|
||
tableName="PERFORMANCE_POOL"
|
||
:data="performanceData"
|
||
:hasOperationColumn="false"
|
||
> </loadCaseTable>
|
||
<loadcase-pro-table
|
||
v-if="false"
|
||
ref="treeTableRef"
|
||
:toolbarConfig="{
|
||
enabled: false,
|
||
custom: true,
|
||
}"
|
||
:loading="performanceLoading"
|
||
:columns="tableColumns"
|
||
:data-source="performanceData"
|
||
:isTreeTable="false"
|
||
:excludeOperation="[]"
|
||
:expandVisible="loadcaseOrPerformanceSwitch"
|
||
:key="tableKey"
|
||
:showHeader="false"
|
||
:isAdaptTableHeight="true"
|
||
readonly
|
||
>
|
||
<template #toolbar_tools_extra>
|
||
<span v-if="pageType === 'performance'">
|
||
显示配置:
|
||
<el-radio-group v-model="loadcaseOrPerformanceSwitch">
|
||
<el-radio :value="true" size="large">树结构</el-radio>
|
||
<el-radio :value="false" size="large">表结构</el-radio>
|
||
</el-radio-group>
|
||
</span>
|
||
</template>
|
||
<template #loadcase_name="{ row, column }">
|
||
<!-- <img
|
||
width="15"
|
||
class="mr5"
|
||
style="vertical-align: text-bottom"
|
||
src="@/components/loadCaseTable/img/systemConfig/loadcase.png"
|
||
alt=""
|
||
/> -->
|
||
{{ row[column.field] }}
|
||
</template>
|
||
</loadcase-pro-table>
|
||
</div>
|
||
</div>
|
||
|
||
<addApproveUser
|
||
v-model="dialogApproveUserVisible"
|
||
:isInitial="isEmptyPool"
|
||
@ok="onConfirmFun"
|
||
></addApproveUser>
|
||
<add-pool-modal
|
||
v-model="addPoolModalVisible"
|
||
mode="add"
|
||
:poolList="poolList"
|
||
detail="{}"
|
||
@ok="onAddPoolOkFun"
|
||
/>
|
||
<del-pool-modal v-model="delPoolModalVisible" @ok="onDelPoolOkFun" />
|
||
<import-pool-modal
|
||
v-model="importPoolModalVisible"
|
||
:poolList="poolList"
|
||
@ok="onImportPoolOkFun"
|
||
/>
|
||
</template>
|
||
|
||
<script lang="ts" setup>
|
||
import { computed, nextTick, onMounted, ref, type Ref } from 'vue';
|
||
import { ElMessageBox, ElMessage } from 'element-plus';
|
||
import { clone, cloneDeep, groupBy, isEqual, uniqBy } from 'lodash-es';
|
||
import { onBeforeRouteLeave, useRouter } from 'vue-router';
|
||
import loadcaseProTable from '@/components/loadCaseTable/commonTable/loadcaseProTable.vue';
|
||
import loadCaseTable from '@/components/common/treeCaseTable/loadCaseTable.vue';
|
||
import {
|
||
getLoadcaseLibColumn,
|
||
getPerformanceLibColumn,
|
||
taskPoolDictOptions,
|
||
} from '@/components/loadCaseTable/utils/project.ts';
|
||
import addApproveUser from './addApproveUsers.vue';
|
||
import {
|
||
transformPoolNodesToTree,
|
||
transformTreeToPoolNodes,
|
||
getNodeExtras,
|
||
canAddChild,
|
||
extractLeafNodesWithParentTypes,
|
||
} from '@/utils/node';
|
||
import { poolNodeExtraPropPickMap } from '@/utils/enum/node';
|
||
import {
|
||
createTaskPoolApi,
|
||
updateTaskPoolApi,
|
||
getTaskPoolApi,
|
||
getTaskPoolPerformanceApi,
|
||
getTaskPoolVersionsApi,
|
||
getAllTaskPoolApi,
|
||
importTaskPoolApi,
|
||
exportTaskPoolApi,
|
||
} from '@/api/task/taskpool';
|
||
import { NODE_TYPE } from '@/utils/enum/node';
|
||
import addPoolModal from './addPoolModal.vue';
|
||
import delPoolModal from './delPoolModal.vue';
|
||
import importPoolModal from './importPoolModal.vue';
|
||
import type { Pool, Extra } from './types';
|
||
import type { TreeNode } from '@/utils/enum/node';
|
||
import { getUserTenantId } from '@/utils/user';
|
||
|
||
const props = defineProps(['pageType']);
|
||
|
||
const tenantId = getUserTenantId();
|
||
const loading = ref(false);
|
||
const loadcaseLibColumn = ref<any>([]);
|
||
const getColumnsFun = async () => {
|
||
if (props.pageType === 'loadcase') {
|
||
loadcaseLibColumn.value = await getLoadcaseLibColumn();
|
||
} else if (props.pageType === 'performance') {
|
||
loadcaseLibColumn.value = await getPerformanceLibColumn([], false);
|
||
}
|
||
};
|
||
const tableColumns = computed(() => {
|
||
let data: any = cloneDeep(loadcaseLibColumn.value);
|
||
if (props.pageType === 'performance' && !loadcaseOrPerformanceSwitch.value) {
|
||
data = data.filter((item: any) => {
|
||
return ![
|
||
'operation',
|
||
'nodeType',
|
||
'days',
|
||
'flowTemplateName',
|
||
'analysisSoftware',
|
||
'confidence',
|
||
'difficult',
|
||
'analyseTarget',
|
||
].includes(item.field);
|
||
});
|
||
data.forEach((item: any) => {
|
||
if (item.field === 'nodeName') {
|
||
item.title = '指标名';
|
||
item.treeNode = false;
|
||
}
|
||
});
|
||
data.splice(1, 0, {
|
||
title: '分析项名',
|
||
dataIndex: 'taskName',
|
||
field: 'taskName',
|
||
key: 'taskName',
|
||
ellipsis: true,
|
||
resizable: true,
|
||
minWidth: 150,
|
||
custom: true,
|
||
align: 'left',
|
||
slots: { default: 'loadcase_name', header: 'content_filter' },
|
||
});
|
||
}
|
||
return data;
|
||
});
|
||
|
||
const tableData = ref<any>([]);
|
||
|
||
const isHaveNotSave = () => {
|
||
|
||
try {
|
||
const { insertRecords, removeRecords, updateRecords } = getRecordSetFun();
|
||
return (
|
||
insertRecords.length > 0 || removeRecords.length > 0 || updateRecords.length > 0
|
||
);
|
||
} catch (e) {
|
||
console.error('e', e);
|
||
return false;
|
||
}
|
||
};
|
||
|
||
const saveType = ref<string>('');
|
||
|
||
const refreshData = async (callback?: any) => {
|
||
if (callback) {
|
||
callback();
|
||
}
|
||
// 指标库
|
||
if (props.pageType === 'performance') {
|
||
}
|
||
saveType.value = '';
|
||
};
|
||
|
||
const treeTableRef = ref();
|
||
const listTableRef = ref();
|
||
const getVxeRef = () => {
|
||
return treeTableRef?.value?.loadcaseTableRef?.TreeTableRef?.treeTableRef;
|
||
};
|
||
const getRecordSetFun = () => {
|
||
return treeTableRef?.value?.loadcaseTableRef?.TreeTableRef?.getRecordSetFun();
|
||
};
|
||
// 任务模板库、仿真指标库切换
|
||
const loadcaseOrPerformanceSwitch = ref<boolean>(false); // 指标数据
|
||
|
||
// 获取指标库
|
||
const performanceLoading = ref<boolean>(false);
|
||
const performanceData = ref<any>([]);
|
||
|
||
const dialogApproveUserVisible = ref(false);
|
||
// 打开选中评审人弹窗
|
||
const openAddApproveUserFun = () => {
|
||
const { visibleData } = getVxeRef()?.getTableData();
|
||
if (!visibleData.length) {
|
||
ElMessage.warning('不能提交空数据');
|
||
return;
|
||
}
|
||
if (!isEmptyPool.value ) {
|
||
if (!isHaveNotSave()) {
|
||
ElMessage.warning('没有修改的数据需要提交审批');
|
||
return;
|
||
}
|
||
}
|
||
|
||
dialogApproveUserVisible.value = true;
|
||
};
|
||
|
||
const isEmptyPool = ref(true);
|
||
const currentPoolBrief = ref();
|
||
const currentPoolBriefVersion = ref();
|
||
const currentTableType = ref('tree');
|
||
const tableTypeOptions = ref([
|
||
{ label: '树结构', value: 'tree' },
|
||
{ label: '一维表格', value: 'list' },
|
||
]);
|
||
const onConfirmFun = async (formData: any) => {
|
||
dialogApproveUserVisible.value = false;
|
||
if (isEmptyPool.value) {
|
||
await createTaskPoolFun(formData);
|
||
} else {
|
||
await updateTaskPoolFun(formData);
|
||
}
|
||
if (pendingRoute.value) {
|
||
const to = pendingRoute.value;
|
||
pendingRoute.value = null;
|
||
suppressConfirm.value = true;
|
||
router.push(to.fullPath || to.path).catch(() => {
|
||
suppressConfirm.value = false;
|
||
});
|
||
}
|
||
};
|
||
|
||
const createTaskPoolFun = async (formData: any) => {
|
||
const { fullData } = getVxeRef()?.getTableData();
|
||
const columns = getVxeRef()?.getColumns();
|
||
const nodes = cloneDeep(fullData);
|
||
const pickedNodes = transformTreeToPoolNodes(nodes);
|
||
const req = {
|
||
poolBrief: {
|
||
poolName: currentPoolBrief.value.poolName,
|
||
tenantId: currentPoolBrief.value.tenantId,
|
||
},
|
||
nodes: pickedNodes,
|
||
bApprove: formData.bApprove,
|
||
approveTemplateId: formData.approveTemplateId,
|
||
approveTemplateName: formData.approveTemplateName,
|
||
fullTableColumns: cloneDeep(columns),
|
||
fullTableData: cloneDeep(fullData),
|
||
};
|
||
const res: any = await createTaskPoolApi(req);
|
||
if (res.code === 200) {
|
||
refreshPoolFun();
|
||
}
|
||
};
|
||
const updateTaskPoolFun = async (formData: any) => {
|
||
const { insertRecords, removeRecords, updateRecords } =
|
||
getRecordSetFun();
|
||
const { fullData } = getVxeRef()?.getTableData();
|
||
const columns = getVxeRef()?.getColumns();
|
||
const req = {
|
||
bApprove: formData.bApprove,
|
||
approveTemplateId: formData.approveTemplateId,
|
||
approveTemplateName: formData.approveTemplateName,
|
||
bNewVersion: formData.bNewVersion,
|
||
versionType: formData.versionType,
|
||
poolBrief: {
|
||
...currentPoolBriefVersion.value,
|
||
},
|
||
addNodes: [],
|
||
addNodeArray: [],
|
||
addNodeExtras: [],
|
||
addTasks: [],
|
||
addTaskArray: [],
|
||
addTaskExtras: [],
|
||
addPerformances: [],
|
||
addPerformanceExtras: [],
|
||
updateNodes: [],
|
||
updateNodeExtras: [],
|
||
updateTasks: [],
|
||
updateTaskExtras: [],
|
||
updatePerformances: [],
|
||
updatePerformanceExtras: [],
|
||
deleteNodes: [],
|
||
deleteNodeExtras: [],
|
||
deleteTasks: [],
|
||
deleteTaskExtras: [],
|
||
deletePerformances: [],
|
||
deletePerformanceExtras: [],
|
||
fullTableColumns: cloneDeep(columns),
|
||
fullTableData: cloneDeep(fullData),
|
||
};
|
||
if (insertRecords.length > 0) {
|
||
const addObj = formatAddFun(cloneDeep(insertRecords), cloneDeep(updateRecords));
|
||
Object.assign(req, addObj);
|
||
}
|
||
if (updateRecords.length > 0) {
|
||
const updateObj = formatUpdateFun(cloneDeep(updateRecords));
|
||
Object.assign(req, updateObj);
|
||
}
|
||
if (removeRecords.length > 0) {
|
||
const delObj = formatDelFun(cloneDeep(removeRecords));
|
||
Object.assign(req, delObj);
|
||
}
|
||
const res: any = await updateTaskPoolApi(req);
|
||
if (res.code === 200) {
|
||
ElMessage.success(res.message);
|
||
refreshVersionFun();
|
||
}
|
||
};
|
||
const dedupeTreeFun = (nodes: any[]) => {
|
||
const flattenAll = (arr: any[]) => {
|
||
const out: any[] = [];
|
||
const walk = (list: any[]) => {
|
||
(list || []).forEach((it: any) => {
|
||
if (!it) return;
|
||
out.push(it);
|
||
if (it.children && it.children.length) {
|
||
walk(it.children);
|
||
}
|
||
});
|
||
};
|
||
walk(arr);
|
||
return out;
|
||
};
|
||
|
||
const flatInsert = flattenAll(nodes);
|
||
const uniqueFlatInsert = uniqBy(flatInsert, 'fakeId');
|
||
|
||
const map: Record<string, any> = {};
|
||
uniqueFlatInsert.forEach((node: any) => {
|
||
map[node.fakeId] = { ...cloneDeep(node), children: [] };
|
||
});
|
||
const roots: any[] = [];
|
||
uniqueFlatInsert.forEach((node: any) => {
|
||
const cur = map[node.fakeId];
|
||
if (cur.parentId && map[cur.parentId]) {
|
||
map[cur.parentId].children.push(cur);
|
||
} else {
|
||
roots.push(cur);
|
||
}
|
||
});
|
||
return roots;
|
||
};
|
||
const formatAddFun = (insertRecords: TreeNode[], updateRecords: TreeNode[]) => {
|
||
const { visibleData } = getVxeRef()?.getTableData();
|
||
let nodes: any[] = [];
|
||
const nodeExtras: any[] = [];
|
||
let tasks: any[] = [];
|
||
const taskExtras: any[] = [];
|
||
let performances: any[] = [];
|
||
const performanceExtras: any[] = [];
|
||
const formatAdd = (arr: any) => {
|
||
arr.forEach((item: any) => {
|
||
const parentRow = visibleData.find((row: any) => {
|
||
return row.fakeId === item.parentId;
|
||
});
|
||
if (item.nodeType === NODE_TYPE.TASK) {
|
||
if (parentRow && parentRow.uuid) {
|
||
item.parentId = parentRow.uuid;
|
||
tasks.push(item);
|
||
} else {
|
||
item.isTemp = true;
|
||
}
|
||
} else if (item.nodeType === NODE_TYPE.PERFORMANCE) {
|
||
if (parentRow && parentRow.uuid) {
|
||
item.parentId = parentRow.uuid;
|
||
performances.push(item);
|
||
} else {
|
||
item.isTemp = true;
|
||
}
|
||
} else {
|
||
if (parentRow && parentRow.uuid) {
|
||
item.parentId = parentRow.uuid;
|
||
} else {
|
||
if (canAddChild({ nodeType: NODE_TYPE.ROOT }, item.nodeType)) {
|
||
item.parentId = '';
|
||
} else {
|
||
item.isTemp = true;
|
||
}
|
||
}
|
||
nodes.push(item);
|
||
}
|
||
});
|
||
};
|
||
formatAdd(dedupeTreeFun(insertRecords));
|
||
|
||
nodes = nodes.filter((item) => !item.isTemp);
|
||
tasks = tasks.filter((item) => !item.isTemp);
|
||
performances = performances.filter((item) => !item.isTemp);
|
||
const nodesGroup = groupBy(nodes, 'parentId');
|
||
const addNodes = Object.keys(nodesGroup).map((key) => {
|
||
return {
|
||
parentId: key === 'undefined' ? '' : key,
|
||
nodes: transformTreeToPoolNodes(nodesGroup[key]),
|
||
};
|
||
});
|
||
const tasksGroup = groupBy(tasks, 'parentId');
|
||
const addTasks = Object.keys(tasksGroup).map((key) => {
|
||
return {
|
||
nodeId: key === 'undefined' ? '' : key,
|
||
tasks: transformTreeToPoolNodes(tasksGroup[key]),
|
||
};
|
||
});
|
||
const performancesGroup = groupBy(performances, 'parentId');
|
||
const addPerformances = Object.keys(performancesGroup).map((key) => {
|
||
return {
|
||
nodeId: key === 'undefined' ? '' : key,
|
||
taskId: key === 'undefined' ? '' : key,
|
||
performances: transformTreeToPoolNodes(performancesGroup[key]),
|
||
};
|
||
});
|
||
|
||
const formatUpdate = (arr: any) => {
|
||
arr.forEach((item: any) => {
|
||
item.extras = getNodeExtras(item, poolNodeExtraPropPickMap);
|
||
if (Array.isArray(item.extras) && item.extras.length > 0) {
|
||
item.extras.forEach((extra: any) => {
|
||
if (!extra.uuid) {
|
||
if (item.nodeType === NODE_TYPE.TASK) {
|
||
taskExtras.push(extra);
|
||
} else if (item.nodeType === NODE_TYPE.PERFORMANCE) {
|
||
performanceExtras.push(extra);
|
||
} else {
|
||
nodeExtras.push(extra);
|
||
}
|
||
}
|
||
});
|
||
}
|
||
});
|
||
};
|
||
formatUpdate(updateRecords);
|
||
return {
|
||
addNodeArray: addNodes,
|
||
addNodeExtras: nodeExtras,
|
||
addTaskArray: addTasks,
|
||
addTaskExtras: taskExtras,
|
||
addPerformances,
|
||
addPerformanceExtras: performanceExtras,
|
||
};
|
||
};
|
||
const formatUpdateFun = (updateRecords: TreeNode[]) => {
|
||
const updateNodes: any[] = [];
|
||
const updateNodeExtras: any[] = [];
|
||
const updateTasks: any[] = [];
|
||
const updateTaskExtras: any[] = [];
|
||
const updatePerformances: any[] = [];
|
||
const updatePerformanceExtras: any[] = [];
|
||
const formatUpdate = (arr: TreeNode[]) => {
|
||
arr.forEach((item) => {
|
||
if (item.nodeType === NODE_TYPE.TASK) {
|
||
updateTasks.push(item);
|
||
} else if (item.nodeType === NODE_TYPE.PERFORMANCE) {
|
||
updatePerformances.push(item);
|
||
} else {
|
||
updateNodes.push(item);
|
||
}
|
||
item.extras = getNodeExtras(item, poolNodeExtraPropPickMap);
|
||
if (Array.isArray(item.extras) && item.extras.length > 0) {
|
||
item.extras.forEach((extra) => {
|
||
if (extra.uuid) {
|
||
if (item.nodeType === NODE_TYPE.TASK) {
|
||
updateTaskExtras.push(extra);
|
||
} else if (item.nodeType === NODE_TYPE.PERFORMANCE) {
|
||
updatePerformanceExtras.push(extra);
|
||
} else {
|
||
updateNodeExtras.push(extra);
|
||
}
|
||
}
|
||
});
|
||
}
|
||
});
|
||
};
|
||
formatUpdate(updateRecords);
|
||
return {
|
||
updateNodes: transformTreeToPoolNodes(updateNodes),
|
||
updateNodeExtras,
|
||
updateTasks: transformTreeToPoolNodes(updateTasks),
|
||
updateTaskExtras,
|
||
updatePerformances: transformTreeToPoolNodes(updatePerformances),
|
||
updatePerformanceExtras,
|
||
};
|
||
};
|
||
const formatDelFun = (removeRecords: TreeNode[]) => {
|
||
const deleteNodes: any[] = [];
|
||
const deleteNodeExtras: any[] = [];
|
||
const deleteTasks: any[] = [];
|
||
const deleteTaskExtras: any[] = [];
|
||
const deletePerformances: any[] = [];
|
||
const deletePerformanceExtras: any[] = [];
|
||
removeRecords.forEach((item: TreeNode) => {
|
||
if (item.nodeType === NODE_TYPE.TASK) {
|
||
deleteTasks.push(item.uuid);
|
||
if (Array.isArray(item.extras) && item.extras.length > 0) {
|
||
item.extras.forEach((extra: Extra) => {
|
||
deleteTaskExtras.push(extra.uuid);
|
||
});
|
||
}
|
||
} else if (item.nodeType === NODE_TYPE.PERFORMANCE) {
|
||
deletePerformances.push(item.uuid);
|
||
if (Array.isArray(item.extras) && item.extras.length > 0) {
|
||
item.extras.forEach((extra: Extra) => {
|
||
deletePerformanceExtras.push(extra.uuid);
|
||
});
|
||
}
|
||
} else {
|
||
deleteNodes.push(item.uuid);
|
||
if (Array.isArray(item.extras) && item.extras.length > 0) {
|
||
item.extras.forEach((extra: Extra) => {
|
||
deleteNodeExtras.push(extra.uuid);
|
||
});
|
||
}
|
||
}
|
||
});
|
||
return {
|
||
deleteNodes,
|
||
deleteNodeExtras,
|
||
deleteTasks,
|
||
deleteTaskExtras,
|
||
deletePerformances,
|
||
deletePerformanceExtras,
|
||
};
|
||
};
|
||
|
||
const tableKey = ref<any>(new Date().getTime());
|
||
const changeLoadcaseOrPerformanceType = () => {
|
||
tableKey.value = new Date().getTime();
|
||
};
|
||
const router = useRouter();
|
||
const pendingRoute: any = ref(null);
|
||
const suppressConfirm = ref(false);
|
||
onBeforeRouteLeave((to, from, next) => {
|
||
if (suppressConfirm.value) {
|
||
suppressConfirm.value = false;
|
||
next();
|
||
return;
|
||
}
|
||
if (!isHaveNotSave()) {
|
||
next();
|
||
return;
|
||
}
|
||
ElMessageBox.confirm('当前有修改未保存!是否将修改提交评审后离开!', '提示', {
|
||
confirmButtonText: '是',
|
||
cancelButtonText: '否',
|
||
type: 'warning',
|
||
})
|
||
.then(() => {
|
||
pendingRoute.value = to;
|
||
dialogApproveUserVisible.value = true;
|
||
next(false);
|
||
})
|
||
.catch(() => {
|
||
next();
|
||
});
|
||
});
|
||
const poolList: Ref<Pool[]> = ref([]);
|
||
const queryPoolListFun = async () => {
|
||
const res: any = await getAllTaskPoolApi();
|
||
if (res.code === 200 && Array.isArray(res.data)) {
|
||
poolList.value = res.data.reverse();
|
||
} else {
|
||
poolList.value = [];
|
||
}
|
||
if (poolList.value.length > 0) {
|
||
currentPoolBrief.value = poolList.value[0];
|
||
queryVersionsFun();
|
||
}
|
||
};
|
||
const versionList = ref();
|
||
const onPoolChangeFun = (pool: any) => {
|
||
if (isHaveNotSave()) {
|
||
ElMessageBox.confirm('当前有修改未保存!是否先提交评审?', '提示', {
|
||
confirmButtonText: '是',
|
||
cancelButtonText: '否',
|
||
type: 'warning',
|
||
})
|
||
.then(() => {
|
||
dialogApproveUserVisible.value = true;
|
||
})
|
||
.catch(() => {
|
||
currentPoolBrief.value = pool;
|
||
queryVersionsFun();
|
||
});
|
||
|
||
return;
|
||
} else {
|
||
currentPoolBrief.value = pool;
|
||
queryVersionsFun();
|
||
}
|
||
};
|
||
const onVersionChangeFun = () => {
|
||
if (!isHaveNotSave()) {
|
||
refreshTreeFun();
|
||
return;
|
||
}
|
||
ElMessageBox.confirm('当前有修改未保存!是否先提交评审?', '提示', {
|
||
confirmButtonText: '是',
|
||
cancelButtonText: '否',
|
||
type: 'warning',
|
||
})
|
||
.then(() => {
|
||
dialogApproveUserVisible.value = true;
|
||
})
|
||
.catch(() => {
|
||
refreshTreeFun();
|
||
});
|
||
};
|
||
const extractTableData:any = ref([]);
|
||
const queryTaskPoolFun = async () => {
|
||
if (!currentPoolBriefVersion.value) {
|
||
return;
|
||
}
|
||
const req = {
|
||
poolName: currentPoolBriefVersion.value.poolName,
|
||
version: currentPoolBriefVersion.value.poolVersion,
|
||
};
|
||
loading.value = true;
|
||
const res: any = await getTaskPoolApi(req);
|
||
loading.value = false;
|
||
let tree = [];
|
||
if (res.code === 200 && res.data.poolBrief && res.data && res.data.nodes) {
|
||
tree = transformPoolNodesToTree(res.data.nodes);
|
||
tableData.value = tree;
|
||
isEmptyPool.value = false;
|
||
extractTableData.value = extractLeafNodesWithParentTypes(res.data.nodes);
|
||
const vxeInstance = listTableRef?.value?.loadcaseTableRef?.TreeTableRef?.treeTableRef;
|
||
const mergeCells = calcMergeCellsFun(cloneDeep(extractTableData.value));
|
||
console.log('extractTableData.value', extractTableData.value);
|
||
console.log('mergeCells', mergeCells);
|
||
nextTick(() => {
|
||
vxeInstance.setMergeCells(mergeCells);
|
||
// treeTableRef.value?.changeLevel('全部展开');
|
||
});
|
||
} else {
|
||
tableData.value = [];
|
||
isEmptyPool.value = true;
|
||
}
|
||
};
|
||
const calcMergeCellsFun = (tableData: any) => {
|
||
const mergeCells: any[] = [];
|
||
if (!Array.isArray(tableData) || tableData.length === 0) return mergeCells;
|
||
|
||
const excludeFields = ['performanceName', 'operation', '_X_ROW_KEY', '_X_ROW_CHILD'];
|
||
const isEmpty = (v: any) => v === null || v === undefined || v === '';
|
||
|
||
const vxeInstance = listTableRef?.value?.loadcaseTableRef?.TreeTableRef?.treeTableRef;
|
||
let columnOrder: string[] = [];
|
||
try {
|
||
if (vxeInstance && typeof vxeInstance.getColumns === 'function') {
|
||
const cols = vxeInstance.getColumns() || [];
|
||
columnOrder = cols
|
||
.filter((c: any) => {
|
||
const t = c.type || c.colType || '';
|
||
return !['checkbox', 'seq', 'expand', 'radio'].includes(t);
|
||
})
|
||
.map((c: any) => c.property || c.field || c.dataIndex || c.key || '')
|
||
.filter(Boolean);
|
||
}
|
||
} catch (e) {
|
||
throw new Error('获取表格列顺序失败');
|
||
}
|
||
|
||
const compCols =
|
||
Array.isArray(tableColumns?.value) && tableColumns.value.length > 0
|
||
? tableColumns.value.map((c: any) => c.field || c.dataIndex || c.key).filter(Boolean)
|
||
: [];
|
||
const rowKeys = Object.keys(tableData[0] || {});
|
||
const fullOrder = columnOrder.length > 0 ? columnOrder : compCols.length > 0 ? compCols : rowKeys;
|
||
|
||
const fields = fullOrder.filter((f) => !!f && !excludeFields.includes(f));
|
||
|
||
const norm = (v: any) => {
|
||
if (isEmpty(v)) return null;
|
||
if (typeof v === 'object') return v;
|
||
return String(v).trim();
|
||
};
|
||
const valuesEqual = (a: any, b: any) => {
|
||
if (a === null || b === null) return false;
|
||
if (typeof a === 'object' || typeof b === 'object') return isEqual(a, b);
|
||
return a === b;
|
||
};
|
||
|
||
fields.forEach((field) => {
|
||
const colIdx = fullOrder.findIndex((f) => f === field);
|
||
if (colIdx === -1) return;
|
||
const n = tableData.length;
|
||
|
||
let start = 0;
|
||
while (start < n && norm(tableData[start]?.[field]) === null) start++;
|
||
if (start >= n) return;
|
||
let startVal = norm(tableData[start][field]);
|
||
|
||
for (let i = start + 1; i <= n; i++) {
|
||
const currVal = i < n ? norm(tableData[i]?.[field]) : null;
|
||
const equal = i < n && valuesEqual(startVal, currVal);
|
||
|
||
if (!equal) {
|
||
const rowspan = i - start;
|
||
if (rowspan > 1 && startVal !== null) {
|
||
mergeCells.push({
|
||
row: start,
|
||
col: colIdx + 1,
|
||
rowspan,
|
||
colspan: 1,
|
||
});
|
||
}
|
||
start = i;
|
||
while (start < n && norm(tableData[start]?.[field]) === null) start++;
|
||
startVal = start < n ? norm(tableData[start][field]) : null;
|
||
}
|
||
}
|
||
});
|
||
|
||
return mergeCells;
|
||
};
|
||
|
||
const queryTaskPoolPerformanceFun = async () => {
|
||
performanceLoading.value = true;
|
||
const req = {
|
||
poolName: currentPoolBriefVersion.value.poolName,
|
||
};
|
||
const res: any = await getTaskPoolPerformanceApi(req);
|
||
performanceLoading.value = false;
|
||
if (res.code === 200 && Array.isArray(res.data)) {
|
||
performanceData.value = transformPoolNodesToTree(res.data);
|
||
}
|
||
};
|
||
const refreshTreeFun = async () => {
|
||
if (props.pageType === 'loadcase') {
|
||
await queryTaskPoolFun();
|
||
}
|
||
if (props.pageType === 'performance') {
|
||
await queryTaskPoolPerformanceFun();
|
||
}
|
||
};
|
||
const refreshPoolFun = async () => {
|
||
await queryPoolListFun();
|
||
};
|
||
const refreshVersionFun = async () => {
|
||
await queryVersionsFun();
|
||
};
|
||
const queryVersionsFun = async () => {
|
||
const req = {
|
||
poolName: currentPoolBrief.value.poolName,
|
||
};
|
||
const res: any = await getTaskPoolVersionsApi(req);
|
||
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];
|
||
}
|
||
} else {
|
||
versionList.value = [];
|
||
currentPoolBriefVersion.value = null;
|
||
tableData.value = [];
|
||
}
|
||
await refreshTreeFun();
|
||
};
|
||
const addPoolModalVisible = ref(false);
|
||
const addPoolFun = () => {
|
||
addPoolModalVisible.value = true;
|
||
};
|
||
const onAddPoolOkFun = (formData: any) => {
|
||
const newPool = {
|
||
tenantId,
|
||
poolName: formData.name,
|
||
};
|
||
currentPoolBrief.value = newPool;
|
||
currentPoolBriefVersion.value = null;
|
||
poolList.value.unshift(newPool);
|
||
versionList.value = [];
|
||
addPoolModalVisible.value = false;
|
||
tableData.value = [];
|
||
isEmptyPool.value = true;
|
||
};
|
||
const delPoolModalVisible = ref(false);
|
||
const openDelPoolFun = () => {
|
||
delPoolModalVisible.value = true;
|
||
};
|
||
const onDelPoolOkFun = () => {
|
||
refreshPoolFun();
|
||
};
|
||
const importPoolModalVisible = ref(false);
|
||
const openImportPoolFun = () => {
|
||
importPoolModalVisible.value = true;
|
||
};
|
||
// const compareTree = (originArr:TreeNode[], insertArr:TreeNode[]) => {
|
||
// const insertData: any = [];
|
||
// const findInsert = (originArr: any, insertArr: any, originNode: any = null) => {
|
||
// insertArr.forEach((insertNode: any) => {
|
||
// let found = false;
|
||
// // 在第一个树中查找是否存在相同的节点
|
||
// originArr.some((originNode: any) => {
|
||
// if (insertNode.nodeName === originNode.nodeName && insertNode.nodeType === originNode.nodeType) {
|
||
// found = true;
|
||
// for (const key in insertNode) {
|
||
// if (!['children', 'fakeId', 'parentId', 'highValue', 'oldValue'].includes(key)) {
|
||
// originNode[key] = insertNode[key];
|
||
// }
|
||
// }
|
||
|
||
// // 如果存在相同节点且有子节点,则递归比较子节点
|
||
// if (insertNode.children && originNode.children) {
|
||
// findInsert(originNode.children, insertNode.children, originNode);
|
||
// }
|
||
// return true; // 停止遍历
|
||
// }
|
||
// return false;
|
||
// });
|
||
// // 如果在第一个树中未找到相同的节点,则插入
|
||
// if (!found) {
|
||
// if (originNode?.fakeId) {
|
||
// insertNode.parentId = originNode?.fakeId;
|
||
// insertNode.fakeId = insertNode.fakeId + random(0, 1, true);
|
||
// }
|
||
// insertNode._X_ROW_CHILD = [];
|
||
// insertNode._X_ROW_KEY = null;
|
||
// insertData.push(insertNode);
|
||
// }
|
||
// });
|
||
// };
|
||
// findInsert(originArr, insertArr);
|
||
// return insertData;
|
||
// };
|
||
const dict = computed(() => ({
|
||
bCapacity: taskPoolDictOptions.value.capacityOptions,
|
||
unit: taskPoolDictOptions.value.performanceUnitOptions,
|
||
department: taskPoolDictOptions.value.departmentListOptions,
|
||
section: taskPoolDictOptions.value.sectionListOptions,
|
||
group: taskPoolDictOptions.value.groupListOptions,
|
||
}));
|
||
const onImportPoolOkFun = async (formData: any) => {
|
||
importPoolModalVisible.value = false;
|
||
const req = {
|
||
poolName: formData.poolName,
|
||
file: formData.file.raw,
|
||
dicts: JSON.stringify(dict.value),
|
||
};
|
||
const res: any = await importTaskPoolApi(req);
|
||
if (res.code === 200) {
|
||
const newPool = {
|
||
tenantId,
|
||
poolName: formData.poolName,
|
||
};
|
||
currentPoolBrief.value = newPool;
|
||
currentPoolBriefVersion.value = null;
|
||
poolList.value.unshift(newPool);
|
||
versionList.value = [];
|
||
isEmptyPool.value = true;
|
||
const tree = transformPoolNodesToTree(res.data.nodes);
|
||
tableData.value = tree;
|
||
extractTableData.value = extractLeafNodesWithParentTypes(res.data.nodes);
|
||
const vxeInstance = listTableRef?.value?.loadcaseTableRef?.TreeTableRef?.treeTableRef;
|
||
const mergeCells = calcMergeCellsFun(cloneDeep(extractTableData.value));
|
||
nextTick(() => {
|
||
vxeInstance.setMergeCells(mergeCells);
|
||
// treeTableRef.value?.changeLevel('全部展开');
|
||
});
|
||
}
|
||
// let excelJson = [];
|
||
// if (res.code === 200) {
|
||
// excelJson = res.data;
|
||
// } else {
|
||
// ElMessage.error(res.message || '导入失败');
|
||
// }
|
||
// if (excelJson.length > 0) {
|
||
// if (formData.importExcelType === 'add') {
|
||
// const newPool = {
|
||
// tenantId,
|
||
// poolName: formData.poolName,
|
||
// };
|
||
// currentPoolBrief.value = newPool;
|
||
// currentPoolBriefVersion.value = null;
|
||
// poolList.value.unshift(newPool);
|
||
// versionList.value = [];
|
||
// tableData.value = transformPoolNodesToTree(excelJson);
|
||
// isEmptyPool.value = true;
|
||
// } else if (formData.importExcelType === 'cover') {
|
||
// const insertData = compareTree(tableData.value, transformPoolNodesToTree(excelJson));
|
||
// const insertDataFlat = flatNode(insertData);
|
||
// console.log('insertDataFlat', insertDataFlat);
|
||
// treeTableRef.value?.loadcaseTableRef.proTreeRef.vxeGridRef?.insertAt(insertDataFlat);
|
||
// }
|
||
// nextTick(() => {
|
||
// treeTableRef.value?.changeLevel('全部展开');
|
||
// });
|
||
// };
|
||
};
|
||
const exportLoading = ref(false);
|
||
const onExportPoolFun = async () => {
|
||
exportLoading.value = true;
|
||
if (!currentPoolBriefVersion.value) {
|
||
exportLoading.value = false;
|
||
return ElMessage.warning('请选择工况库及版本');
|
||
}
|
||
const req = {
|
||
poolName: currentPoolBriefVersion.value.poolName,
|
||
poolVersion: currentPoolBriefVersion.value.poolVersion,
|
||
dicts: JSON.stringify(dict.value),
|
||
};
|
||
await exportTaskPoolApi(req);
|
||
exportLoading.value = false;
|
||
};
|
||
|
||
onMounted(async () => {
|
||
await getColumnsFun();
|
||
await queryPoolListFun();
|
||
});
|
||
</script>
|
||
|
||
<style src="./taskPool.scss" lang="scss" scoped />
|