从历史项目选择数据导入,优化仿真策划选人,新增流程下一步按钮

This commit is contained in:
weibl
2025-11-24 15:03:50 +08:00
parent 8b23cb608f
commit 89c2bf253f
19 changed files with 397 additions and 209 deletions

View File

@@ -18,12 +18,12 @@
</div>
<slot name="otherLeftOptions"></slot>
</template>
<template #eMemberList="{row}">
<!-- <template #eMemberList="{row}">
{{ disposeMemberList(row,'eMemberList') }}
</template>
<template #pMemberList="{row}">
</template> -->
<!-- <template #pMemberList="{row}">
{{ disposeMemberList(row,'pMemberList') }}
</template>
</template> -->
<!-- <template #tableActions="{ row }" v-if="hasOperationColumn" >
<div class="gl-table-actions" v-if="!readonly">
<el-link type="primary" @click="editRowFun(row)">编辑</el-link>
@@ -163,6 +163,12 @@
:detail="modalDetail"
@confirm="onNodeDetailConfirmFun"
/>
<!-- <userSelectTable
v-if="showManageTable"
v-model:memberVisible="showManageTable"
:checkedUserList="selectManagerInfo.memberList"
@update:updateMemberList="updateTaskUser"
/> -->
</div>
</template>
@@ -264,7 +270,7 @@ const addRowFun = (nodeType?: any) => {
const editRowFun = (row: any) => {
operationType.value = OPERATION_TYPE.EDIT;
modalNodeType.value = row.nodeType;
modalDetail.value = { ...row, planTime: [row.beginTime, row.endTime] };
modalDetail.value = { ...row, planTime: [row.beginTime, row.endTime], eMemberListArr: row.eMemberList, pMemberListArr: row.pMemberList };
modalVisible.value = true;
};

View File

@@ -43,7 +43,7 @@ import { ref, computed, nextTick, watch } from 'vue';
import Dialog from '@/components/common/dialog/index.vue';
import TableForm from '@/components/common/table/tableForm.vue';
import { getTagKeyMap, NODE_TYPE } from '@/utils/enum/node';
import { getMemberListStr } from '@/utils/task';
import { getMemberListIds } from '@/utils/task';
import { disposeTagKey } from '@/views/task/projectDetail/components/project';
import { isCategoryType, isCategoryNodeType } from '@/utils/node';
import flowTemplateSelect from './flowTemplateSelect.vue';
@@ -89,7 +89,7 @@ const onShowFun = () => {
resetFun();
nextTick(() => {
if (localDetail.value) {
tableFormRef.value?.setFormDataFun({ ...localDetail.value, eMemberList: getMemberListStr(localDetail.value.eMemberList), pMemberList: getMemberListStr(localDetail.value.pMemberList) });
tableFormRef.value?.setFormDataFun({ ...localDetail.value, eMemberList: getMemberListIds(localDetail.value.eMemberList), pMemberList: getMemberListIds(localDetail.value.pMemberList) });
standard.value = localDetail.value.standard;
if (localDetail.value.flowTemplate) {
selectedFlowTemplate.value = localDetail.value.flowTemplate;
@@ -131,6 +131,14 @@ const onConfirmFun = async () => {
formData.beginTime = formData.planTime[0];
formData.endTime = formData.planTime[1];
}
formData.pMemberIds = '';
if (formData.pMemberList?.length > 0) {
formData.pMemberIds = formData.pMemberList.map((i:any) => i.id).join(',');
}
formData.eMemberIds = '';
if (formData.eMemberList?.length > 0) {
formData.eMemberIds = formData.eMemberList.map((i:any) => i.id).join(',');
}
emits('confirm', formData);
}
};

View File

@@ -44,6 +44,18 @@
<template #nodeCode-edit="{ row }">
<el-input v-model="row.nodeCode" size="small" placeholder="请输入" />
</template>
<template #pMemberIds="{ row }">
{{ disposeMemberList(row,'pMemberList') }}
</template>
<template #pMemberIds-edit="{ row,column }">
<userSelect @change="(data) => changeUserFun(row,data,'pMemberList','pMemberIds')" :multiple="true" v-model="row[column.field]"></userSelect>
</template>
<template #eMemberIds="{ row }">
{{ disposeMemberList(row,'eMemberList') }}
</template>
<template #eMemberIds-edit="{ row,column }">
<userSelect @change="(data) => changeUserFun(row,data,'eMemberList','eMemberIds')" :multiple="true" v-model="row[column.field]"></userSelect>
</template>
<!-- 计划开始时间 -->
<template #beginTime="{ row }">
<TreeEditItem
@@ -281,6 +293,9 @@ import flowTemplateSelect from './flowTemplateSelect.vue';
import knowledgeSelect from './knowledgeSelect.vue';
import uploadImg from '@/components/common/table/uploadImg.vue';
import { useTaskStore } from '@/stores/taskPool';
import userSelect from '../userSelect/index.vue';
import { disposeMemberList } from '@/views/task/projectDetail/components/project';
import { getMemberListIds } from '@/utils/task';
const TreeTableRef = ref<any>();
@@ -312,6 +327,12 @@ const treeDataFormatFun = (data: any, build: any, pId: any) => {
return build;
};
const changeUserFun = (row:any, data:any, listKey:string, idKey:string) => {
console.log('changeUserFun', row, data);
row[listKey] = data;
row[idKey] = getMemberListIds(data);
};
watch(() => props.data, (val: any) => {
treeData.value = treeDataFormatFun(val, [], '0');
}, { immediate: true });

View File

@@ -5,10 +5,14 @@
<script lang='ts' setup>
import { getChildrenNodeListApi } from '@/api/project/node';
import { NODE_TYPE } from '@/utils/enum/node';
import { onMounted, ref, watch } from 'vue';
import { computed, onMounted, ref, watch } from 'vue';
const props = defineProps({
nodeLevel1Uuid: {
projectUuid: {
type: String,
default: '',
},
phaseUuid: {
type: String,
default: '',
},
@@ -16,36 +20,47 @@ const props = defineProps({
const nodeLevel2ListOptions = ref();
const emits = defineEmits(['update:nodeLevel2Uuid', 'update:updateNodeLevel2Info']);
const nodeUuid = ref('');
const nodeInfo = ref();
const emits = defineEmits(['change']);
const nodeUuid = computed({
get() {
return props.phaseUuid;
},
set(val) {
// emits('update:phaseUuid', val);
emits('change', { phaseUuid: val, type: 'change' });
},
});
// const nodeInfo = ref();
const changeFun = () => {
emits('update:nodeLevel2Uuid', nodeUuid.value);
nodeInfo.value = nodeLevel2ListOptions.value.find((item: { value: string; }) => item.value === nodeUuid.value)?.info;
console.log('nodeLevel2ListOptions', nodeUuid.value, nodeInfo.value, nodeLevel2ListOptions.value);
emits('update:updateNodeLevel2Info',
{
// 反馈对应的项目信息
...(nodeLevel2ListOptions.value.find((item: { value: string; }) => {return item.value === nodeUuid.value;}).info),
});
// emits('update:phaseUuid', nodeUuid.value);
// nodeInfo.value = nodeLevel2ListOptions.value.find((item: { value: string; }) => item.value === nodeUuid.value)?.info;
// emits('change', nodeUuid.value);
// console.log('nodeLevel2ListOptions', nodeUuid.value, nodeInfo.value, nodeLevel2ListOptions.value);
// emits('update:updateNodeLevel2Info',
// {
// // 反馈对应的项目信息
// ...(nodeLevel2ListOptions.value.find((item: { value: string; }) => {return item.value === nodeUuid.value;}).info),
// });
};
// 将选中数据回滚到上一个版本
const rollBackValue = (value:string) => {
nodeUuid.value = value;
// emits('update:phaseUuid', value);
emits('change', { phaseUuid: value, type: 'rollBack' });
};
const nodeLevel2ListApi = async() => {
const res:any = await getChildrenNodeListApi({ current: 1, size: 999, nodeType: NODE_TYPE.PHASE, nodeId: props.nodeLevel1Uuid });
const res:any = await getChildrenNodeListApi({ current: 1, size: 999, nodeType: NODE_TYPE.PHASE, nodeId: props.projectUuid });
if (res && res.code === 200) {
nodeLevel2ListOptions.value = res.data.map((item: { nodeName: string; uuid: string; }) => {
return { label: item.nodeName, value: item.uuid, info: item };
});
// console.log('nodeLevel2ListOptions', nodeLevel2ListOptions.value);
if (nodeLevel2ListOptions.value.length) {
nodeUuid.value = nodeLevel2ListOptions.value[0].value;
changeFun();
// emits('update:phaseUuid', nodeLevel2ListOptions.value[0].value);
// changeFun();
emits('change', { phaseUuid: nodeLevel2ListOptions.value[0].value, type: 'change' });
}
} else {
nodeLevel2ListOptions.value = [];
@@ -54,10 +69,10 @@ const nodeLevel2ListApi = async() => {
onMounted(() => {
});
watch(
() => props.nodeLevel1Uuid,
() => props.projectUuid,
() => {
console.log('props.nodeLevel1Uuid', props.nodeLevel1Uuid);
if (props.nodeLevel1Uuid) {
console.log('props.nodeLevel1Uuid', props.projectUuid);
if (props.projectUuid) {
nodeLevel2ListApi();
}
},
@@ -65,6 +80,6 @@ watch(
immediate: true,
}
);
defineExpose({ rollBackValue, nodeInfo });
defineExpose({ rollBackValue });
</script>
<style lang='scss' scoped></style>

View File

@@ -77,7 +77,7 @@ import { computed, reactive, ref, watch } from 'vue';
import { getProjectExeStatus, getTagMapList } from '@/views/task/projectDetail/components/project';
import TableForm from '@/components/common/table/tableForm.vue';
import { PROJECT_EXE_STATUS_CODE } from '@/utils/enum/project';
import { getMemberListStr } from '@/utils/task';
import { getMemberListIds } from '@/utils/task';
const props = defineProps<{
modelValue: boolean;
@@ -191,7 +191,7 @@ const closeFun = () => {
// const setEditForm = (val: any) => {
// console.log('val', val, tableFormRef.value);
// nextTick(() => {
// const memberStr = getMemberListStr(val?.memberList);
// const memberStr = getMemberListIds(val?.memberList);
// tableFormRef.value.setFormDataFun({ ...val, memberList: memberStr });
// });
// };
@@ -236,8 +236,8 @@ const getNodeDetailFun = async() => {
for (const key in res.data) {
projectInfo[key] = res.data[key];
}
console.log('123', { ...projectInfo, planTime: [projectInfo.beginTime, projectInfo.endTime], memberList: getMemberListStr(projectInfo.memberList) });
tableFormRef.value.setFormDataFun({ ...projectInfo, planTime: [projectInfo.beginTime, projectInfo.endTime], memberList: getMemberListStr(projectInfo.memberList) });
console.log('123', { ...projectInfo, planTime: [projectInfo.beginTime, projectInfo.endTime], memberList: getMemberListIds(projectInfo.memberList) });
tableFormRef.value.setFormDataFun({ ...projectInfo, planTime: [projectInfo.beginTime, projectInfo.endTime], memberList: getMemberListIds(projectInfo.memberList) });
}
}
}

View File

@@ -1,5 +1,6 @@
import { nodeTypeList, NODE_TYPE, LEVEL_TYPE, nodeTypeRelations, poolNodePropPickMap, poolNodeExtraPropPickMap } from '@/utils/enum/node';
import type { TreeNode } from '@/utils/enum/node';
import { getMemberListIds } from './task';
export const toMap = <T extends string | number, U>(list: { value: T, label: U }[]): Record<T, U> => {
return (list.reduce((obj, { value, label }) => {
@@ -200,6 +201,14 @@ export const transformTreeToPoolNodes = (tree: TreeNode[]) => {
export const translateLoadcaseTree = (list: any[]) => {
const arr = list.map(item => {
item.fakeId = item.uuid;
item.pMemberIds = '';
if (item.pMemberList?.length > 0) {
item.pMemberIds = getMemberListIds(item.pMemberList);
}
item.eMemberIds = '';
if (item.eMemberList?.length > 0) {
item.eMemberIds = getMemberListIds(item.eMemberList);
}
if (Array.isArray(item.children)) {
item.children = translateLoadcaseTree(item.children);
}

View File

@@ -11,7 +11,12 @@ export const disposeSimType = (demandType: string, simType:string) => {
return simType;
};
export const getMemberListStr = (memberList: any[]) => {
/**
*
* @param memberList
* @returns 用户ids逗号隔开的id字符串
*/
export const getMemberListIds = (memberList: any[]) => {
const list = cloneDeep(memberList);
if (Array.isArray(list)) {
return list.map((item:any) => {

View File

@@ -40,7 +40,7 @@
<script lang='ts' setup>
import Dialog from '@/components/common/dialog/index.vue';
// import { ElMessage } from 'element-plus';
import { computed, inject, reactive, ref } from 'vue';
import { computed, reactive, ref } from 'vue';
import { ElMessage } from 'element-plus';
import ApproveList from '@/components/common/approveList/index.vue';
import { releaseFlowTemplateApi, upgradeFlowTemplateDraftApi } from '@/api/capability/flow';
@@ -51,10 +51,9 @@ const props = defineProps<{
versionType:string;
graph: any;
nodeRelation: any[];
flowDetail: any;
}>();
const flowDetail:any = inject('flowDetail');
const loadingInterface = ref(false);
const dialogVisible = computed({
@@ -92,11 +91,11 @@ const confirmFun = async () => {
});
} else {
const upgradeRes:any = await upgradeDraftFun({
'templateName': flowDetail.templateName,
'templateName': props.flowDetail.templateName,
'templateContent': JSON.stringify(props.nodeRelation),
'viewContent': JSON.stringify(props.graph.toJSON()),
'templateType': flowDetail.templateType,
'comment': flowDetail.comment,
'templateType': props.flowDetail.templateType,
'comment': props.flowDetail.comment,
versionType: approveForm.versionType,
});
await submitApproveFun(upgradeRes.data);

View File

@@ -87,7 +87,7 @@ export const registerCustomNode = () => {
// 自定义的画布中的显示节点
register({
shape: 'custom-app-vue-node',
type: 'HPC',
type: 'app',
width: 134,
height: 56,
component: AppNode,
@@ -97,7 +97,7 @@ export const registerCustomNode = () => {
// 自定义的画布中的显示节点
register({
shape: 'custom-local-vue-node',
type: 'HPC',
type: 'local',
width: 56,
height: 56,
component: LocalNode,

View File

@@ -44,13 +44,14 @@
:versionType="currentVersion?.templateVersion"
:graph="graph"
:nodeRelation="nodeRelation"
:flowDetail="flowDetail"
@saveDraft="saveDraftFun"
></ApproveDialog>
</div>
</template>
<script setup lang="ts">
import { onMounted, ref } from 'vue';
import { onMounted, reactive, ref } from 'vue';
import { getTeleport } from '@antv/x6-vue-shape';
import { useNodeAttribute, useNodeEvents } from './components/nodeEvents';
import ConfigPage from './components/configPage.vue';
@@ -111,9 +112,24 @@ const changeVersionFun = () => {
getFlowDetail();
};
const flowDetail = reactive({
uuid: '',
version: '',
comment: '',
templateName: '',
templateType: '',
});
const getFlowDetail = async() => {
const res:any = await queryFlowTemplateDetailApi({ uuid: currentVersion.value.uuid, status: 1 });
if (res.code === 200) {
flowDetail.uuid = res.data.uuid;
flowDetail.version = res.data.templateVersion;
flowDetail.templateName = res.data.templateName;
flowDetail.comment = res.data.comment;
flowDetail.templateType = res.data.templateType;
if (res.data.viewContent.length > 50) {
const dataJson = JSON.parse(res.data.viewContent);
graph.value.fromJSON(dataJson);

View File

@@ -13,7 +13,8 @@
<template #footer>
<div>
<el-button @click="closeFun">取消</el-button>
<el-button type="primary" @click="confirmFun" :loading="loadingInterface">确定</el-button>
<el-button type="primary" @click="confirmFun('ok')" :loading="loadingInterface">确定</el-button>
<el-button type="primary" @click="confirmFun('next')" :loading="loadingInterface">下一步</el-button>
</div>
</template>
</Dialog>
@@ -51,7 +52,7 @@ const emits = defineEmits(['update:showDialog', 'confirm' ]);
// description: '',
// });
const confirmFun = async () => {
const confirmFun = async (type:string) => {
console.log('tableFormRef.value', tableFormRef.value, await tableFormRef.value.validateFun());
if (await tableFormRef.value.validateFun()) {
loadingInterface.value = true;
@@ -61,15 +62,15 @@ const confirmFun = async () => {
flowForm.viewContent = props.flowContent.viewContent;
flowForm.templateContent = props.flowContent.templateContent;
}
await createFlow(flowForm);
const flowRes = await createFlow(flowForm);
emits('confirm', { type, uuid: flowRes.uuid });
} else {
// console.log('编辑项目', projectForm);
await editFlow(flowForm);
emits('confirm', { type, uuid: flowForm.uuid });
}
loadingInterface.value = false;
emits('confirm');
closeFun();
}
};
@@ -86,6 +87,7 @@ const createFlow = async(params: any) => {
const res:any = await addFlowTemplateDraftApi(params);
if (res && res.code === 200) {
ElMessage.success('创建流程成功!');
return res.data;
} else {
ElMessage.error(res.msg || '创建流程失败');
}
@@ -94,9 +96,9 @@ const createFlow = async(params: any) => {
const editFlow = async(params: any) => {
const res:any = await updateFlowTemplateDraftApi(params);
if (res && res.code === 200) {
ElMessage.success('编辑流程成功!');
ElMessage.success('编辑流程基本属性成功!');
} else {
ElMessage.error(res.msg || '编辑流程失败!');
ElMessage.error(res.msg || '编辑流程基本属性失败!');
}
};

View File

@@ -1,22 +1,22 @@
<template>
<div class="gl-page-content" v-if="!showFlowDetailVisible">
<div class="display-mode">
<!-- <div class="display-mode">
<el-radio-group v-model="viewType">
<!-- <el-radio-button label="甘特图" value="gantt" /> -->
<el-radio-button label="卡片" value="card" />
<el-radio-button label="列表" value="list" />
</el-radio-group>
</div>
</div> -->
<div class="flow-table-list">
<BaseTable
listTitle="仿真流程数据"
v-model:viewType="viewType"
showIndex
ref="tableRef"
tableName="SIMULATION_FLOW_LIB_LIST"
:params="{...apiParams}"
:api="queryFlowTemplateApi"
:searchLimitNum="3"
:listMode="viewType === 'list' ? 'default' : 'card'"
:actionsWidth="300"
:actionList="actionList"
>
<!-- :actionsWidth="tableActionsLength['2-2-2-2']" -->
<template #cardTemplate="{ tableData }">
@@ -34,12 +34,12 @@
>
{{ FLOW_APPROVE_STATUS.O[flow.approveType] }}
</span>
<el-dropdown class="flow-card-el-dropdown">
<el-dropdown class="flow-card-el-dropdown" :teleported="false">
<div class="btn-box">...</div>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="openDiaFun('edit', flow)">重命名</el-dropdown-item>
<el-dropdown-item @click="goFlowDetailFun(flow)">编辑</el-dropdown-item>
<el-dropdown-item @click="goFlowDetailFun(flow.uuid)">编辑</el-dropdown-item>
<el-dropdown-item v-if="flow.templateStatus === FLOW_USE_STATUS.USED" @click="changeFlowStatusMessageBox(flow.uuid,FLOW_USE_STATUS.STOP)">弃用</el-dropdown-item>
<el-dropdown-item v-if="flow.templateStatus === FLOW_USE_STATUS.STOP" @click="changeFlowStatusMessageBox(flow.uuid,FLOW_USE_STATUS.USED)">启用</el-dropdown-item>
<el-dropdown-item @click="deleteFlowMessageBox(flow.uuid)">删除</el-dropdown-item>
@@ -74,32 +74,26 @@
</el-button>
</template>
<template #templateStatus="{ row }">
<div
<span
:class="row.templateStatus === FLOW_USE_STATUS.USED?
'approve-box approve-success':'approve-refuse'"
>
<span class="dot">.</span>{{ FLOW_USE_TYPE.O[row.templateStatus] }}
</div>
'dot dot-success':'dot dot-refuse'"
>.</span>{{ FLOW_USE_TYPE.O[row.templateStatus] }}
</template>
<template #approveType="{ row }">
<div
<span
:class="row.approveType === FLOW_APPROVE_STATUS_ENUM.NOT_APPROVED?
'approve-status no-approve':
'dot dot-in-precess':
row.approveType === FLOW_APPROVE_STATUS_ENUM.APPROVING?
'approve-status approving':
'dot dot-approving':
row.approveType === FLOW_APPROVE_STATUS_ENUM.APPROVED?
'approve-status approve-success':'approve-refuse'"
>
<span class="dot">.</span>{{ FLOW_APPROVE_STATUS.O[row.approveType] }}
</div>
'dot dot-success':'dot-refuse'"
>.</span>{{ FLOW_APPROVE_STATUS.O[row.approveType] }}
</template>
<template #tableActions="{ row }">
<!-- <template #tableActions="{ row }">
<div class="gl-table-actions">
<el-link type="primary" @click="viewFlowFun(row)">预览</el-link>
<el-link type="primary" @click="openDiaFun('edit', row)">重命名</el-link>
<el-link type="primary" @click="copyFlowFun( row)">复制</el-link>
<!-- <el-link type="primary" @click="openDiaFun('edit', row)">升版</el-link> -->
<el-link type="primary" @click="goFlowDetailFun(row)">编辑</el-link>
<el-popconfirm v-if="row.templateStatus === FLOW_USE_STATUS.USED && row.approveType === FLOW_APPROVE_STATUS_ENUM.APPROVED" title="确认弃用?" @confirm="changeFlowStatus(row.uuid,FLOW_USE_STATUS.STOP)">
<template #reference>
@@ -117,7 +111,7 @@
</template>
</el-popconfirm>
</div>
</template>
</template> -->
</BaseTable>
</div>
</div>
@@ -130,18 +124,18 @@
></addDialog>
<flowCreate
v-if="showFlowDetailVisible"
:flowUuid="flowDetail.uuid"
:flowUuid="flowUuid"
@goBack="showFlowDetailVisible = false"
></flowCreate>
<flowViewDialog
v-if="showFlowViewVisible"
v-model:showDialog="showFlowViewVisible"
:flowUuid="flowDetail.uuid"
:flowUuid="flowUuid"
></flowViewDialog>
</template>
<script setup lang="ts">
import { nextTick, provide, reactive, ref } from 'vue';
import { nextTick, reactive, ref } from 'vue';
import BaseTable from '@/components/common/table/baseTable.vue';
import { useDict } from '@/utils/useDict';
import addDialog from './components/addDialog.vue';
@@ -174,6 +168,71 @@ const viewType = ref('list');
const addDiaRef = ref();
const actionList = ref<any>([
{
title: '预览',
type: 'primary',
click: (row: any) => {
viewFlowFun(row);
},
},
// {
// title: '重命名',
// type: 'primary',
// click: (row: any) => {
// openDiaFun('edit', row);
// },
// },
{
title: '编辑',
type: 'primary',
click: (row: any) => {
// goFlowDetailFun(row.uuid);
openDiaFun('edit', row);
},
},
{
title: '复制',
type: 'primary',
click: (row: any) => {
copyFlowFun( row);
},
},
{
title: '弃用',
type: 'danger',
needConfirm: true,
confirmTip: '确认弃用?',
click: (row: any) => {
changeFlowStatus(row.uuid, FLOW_USE_STATUS.STOP);
},
hide: (row: any) => {
return !(row.templateStatus === FLOW_USE_STATUS.USED && row.approveType === FLOW_APPROVE_STATUS_ENUM.APPROVED);
},
},
{
title: '启用',
type: 'primary',
needConfirm: true,
confirmTip: '确认启用?',
click: (row: any) => {
changeFlowStatus(row.uuid, FLOW_USE_STATUS.USED);
},
hide: (row: any) => {
return !(row.templateStatus === FLOW_USE_STATUS.STOP && row.approveType === FLOW_APPROVE_STATUS_ENUM.APPROVED);
},
},
{
title: '删除',
type: 'danger',
needConfirm: true,
confirmTip: '确认删除吗?',
click: (row: any) => {
deleteFlowFun(row.uuid);
},
},
]);
const openDiaFun = (tag: string, row?: any) => {
dialogType.value = tag;
showDialog.value = true;
@@ -195,8 +254,12 @@ const openDiaFun = (tag: string, row?: any) => {
};
const addOrEditFun = () => {
const addOrEditFun = ({ type, uuid }:any) => {
tableRef.value.resetFun();
flowUuid.value = uuid;
if (type === 'next') {
goFlowDetailFun(uuid);
}
};
const deleteFlowFun = async (uuid:string) => {
@@ -254,33 +317,16 @@ const changeFlowStatusMessageBox = (uuid:string, type:number) => {
});
};
const flowDetail = reactive({
uuid: '',
version: '',
comment: '',
templateName: '',
templateType: '',
});
provide('flowDetail', flowDetail);
const flowUuid = ref();
const viewFlowFun = (row: any) => {
showFlowViewVisible.value = true;
assignmentFlowFun(row);
flowUuid.value = row.uuid;
};
const goFlowDetailFun = (row: any) => {
console.log('row', row);
const goFlowDetailFun = (uuid: string) => {
showFlowDetailVisible.value = true;
assignmentFlowFun(row);
};
const assignmentFlowFun = (row: any) => {
flowDetail.uuid = row.uuid;
flowDetail.version = row.templateVersion;
flowDetail.templateName = row.templateName;
flowDetail.comment = row.comment;
flowDetail.templateType = row.templateType;
flowUuid.value = uuid;
};
// NODE_LIST_LEVEL1
@@ -319,7 +365,14 @@ const copyFlowFun = (flow:any) => {
position: absolute;
top: var(--margin-tiny);
right: var(--margin-tiny);
}
.el-dropdown-menu:hover ~ .btn-box {
visibility: visible;
transition: all 0.3s ease-in-out;
opacity: 1;
}
</style>
<style lang="scss" scoped>
@@ -406,7 +459,7 @@ const copyFlowFun = (flow:any) => {
border-radius: 12px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
// padding: 18px;
transition: all 0.3s ease;
transition: all 0.3s ease-in-out;
border: 1px solid #e2e8f0;
overflow: hidden;
.flow-background {
@@ -425,11 +478,19 @@ const copyFlowFun = (flow:any) => {
background-color: #F2F2F2;
background-image: none;
.approve-box {
display: none;
visibility: hidden;
opacity: 0;
transition: all 0.3s ease-in-out;
}
.use-btn {
display: block;
visibility: visible;
transition: all 0.3s ease-in-out;
opacity: 1;
}
.btn-box {
visibility: visible;
transition: all 0.3s ease-in-out;
opacity: 1;
}
}
@@ -453,12 +514,19 @@ const copyFlowFun = (flow:any) => {
top: var(--margin-tiny);
right: var(--margin-tiny);
font-weight: 600;
font-size: 18px;
text-align: center;
line-height: 25px;
line-height: 23px;
cursor: pointer;
visibility: hidden;
transition: all 0.3s ease;
opacity: 0;
border-radius: var(--border-radius-normal);
}
.use-btn {
display: none;
visibility: hidden;
opacity: 0;
transition: all 0.3s ease;
width: 100px;
.btn {
margin-bottom: var(--margin-small);
@@ -526,7 +594,7 @@ const copyFlowFun = (flow:any) => {
height: 100%;
background: linear-gradient(90deg, #3b82f6, #60a5fa);
border-radius: 3px;
transition: width 0.5s ease;
transition: width 0.5s ease-in-out;
}
.date-row {
@@ -536,42 +604,20 @@ const copyFlowFun = (flow:any) => {
font-size: 12px;
color: #64748b;
}
.no-approve {
color: #0366FF;
.dot {
background-color: #0366FF;
}
}
.approving {
color: #ED7B2F;
.dot {
background-color: #ED7B2F;
}
}
.approve-success {
color: #00A870;
.dot {
background-color: #00A870;
}
}
.approve-refuse {
color: #E34D59;
.dot {
background-color: #E34D59;
}
}
.dot {
/* 1. 设为内联块,才能设置宽高 */
display: inline-block;
/* 2. 宽高相等,控制圆点大小 */
width: 8px;
height: 8px;
/* 3. 圆角 50% 变成圆形 */
border-radius: 50%;
/* 4. 背景色(根据需求调整) */
// background-color: #42b983;
/* 可选:间距调整(与文字对齐) */
margin: 0 4px;
vertical-align: middle;
.no-approve {
background-color: #0366FF;
}
.approving {
background-color: #ED7B2F;
}
.approve-success {
background-color: #00A870;
}
.approve-refuse {
background-color: #E34D59;
}
</style>

View File

@@ -12,7 +12,7 @@
:loading="tableLoading"
>
<template #otherLeftOptions>
<el-form label-width="60px">
<el-form label-width="60">
<el-form-item label="阶段:" class="phase-content">
<el-select
class="phase-select"
@@ -162,7 +162,6 @@ const getPhaseListApi = async () => {
phaseUuid.value = phaseListOptions.value[0].value;
updatePhaseUuid(phaseListOptions.value[0].value);
}
}
} else {
phaseListOptions.value = [];

View File

@@ -7,9 +7,6 @@
<div class="project-name">
{{ projectName }}
</div>
<!-- <el-form-item label="项目名称:">
{{ projectName }}
</el-form-item> -->
</el-form>
<!-- <el-select v-model="nodeLevel2Uuid" placeholder="节点" style="margin-right: 10px">
@@ -29,10 +26,6 @@
<el-button icon="Lock">关闭</el-button>
</template>
</el-popconfirm>
<!-- <el-icon title="返回项目列表" @click="goProjectListFun"><ArrowLeft /></el-icon>
<el-icon title="编辑基本信息" @click="openEditBasicDialogFun"><Postcard /></el-icon>
<el-icon title="编辑阶段信息" @click="openEditNodeDialogFun"><SetUp /></el-icon>
<el-icon title="仿真任务策划" @click="openAddTaskDialogFun"><Grid /></el-icon> -->
</div>
</div>
@@ -77,7 +70,6 @@
dialogType="edit"
@completeFun="completeFun"
/>
<!-- v-if="showTaskDialog" -->
<TaskDialog
v-if="showTaskDialog"
v-model:showTaskDialog="showTaskDialog"

View File

@@ -16,9 +16,9 @@
<!-- 主内容区左右分栏 -->
<div class="main-content">
<!-- 左侧任务库列表 -->
<div class="left-panel">
<div class="left-panel" v-if="selectMethod === 'template'">
<div class="top-bar">
<el-form :inline="true" class="demo-form-inline">
<el-form :inline="true" class="left-form-inline">
<el-form-item label="工况清单库:">
<el-select
class="loadcase-lib"
@@ -49,33 +49,42 @@
</div>
<div class="left-table">
<loadCaseTable
ref="leftTableRef"
ref="leftPoolTableRef"
tableName="TASK_POOL"
:modalTableNameList="['TASK_POOL_CATEGORY','TASK_POOL_TASK','TASK_POOL_PERFORMANCE']"
:data="leftTableDataList"
:data="leftPoolTableDataList"
readonly
:loading="leftTableLoading"
>
</loadCaseTable>
<!-- <loadcase-pro-table
:loading="leftTableLoading"
ref="leftTableRef"
:columns="leftTableColumns"
:dataSource="leftTableDataList"
:checkStrictly="true"
:leftVisible="false"
:readonly="true"
:toolbarConfig="{
enabled: true,
custom: true,
slots: {
tools: 'toolbar_tools',
buttons: 'toolbar_buttons',
},
}"
:showHeader="false"
</div>
</div>
<!-- 左侧项目列表 -->
<div class="left-panel" v-else>
<div class="top-bar">
<el-form :inline="true" class="left-form-inline" >
<el-form-item label="项目:">
<ProjectSelect
v-model="leftCurrentProjectUuid"
></ProjectSelect>
</el-form-item>
<el-form-item label="阶段:">
<nodeLevel2Select
:projectUuid="leftCurrentProjectUuid"
:phaseUuid="leftCurrentPhaseUuid"
@change="changeLeftPhaseFun"
></nodeLevel2Select>
</el-form-item>
</el-form>
</div>
<div class="left-table">
<loadCaseTable
ref="leftProjectTableRef"
tableName="PROJECT_TASK_PLANNING"
:data="leftProjectTableDataList"
readonly
:loading="rightTableLoading"
>
</loadcase-pro-table> -->
</loadCaseTable>
</div>
</div>
@@ -87,7 +96,7 @@
<!-- 右侧项目任务列表 -->
<div class="right-panel">
<div class="right-top-bar">
<el-form :inline="true" class="demo-form-inline">
<el-form :inline="true" class="right-form-inline">
<el-form-item label="项目:">
{{ nodeLevel1Name }}
</el-form-item>
@@ -101,7 +110,14 @@
:value="item.uuid"
/>
</el-select>
<nodeLevel2Select ref="nodeLevel2SelectRef" class="phase" v-else :nodeLevel1Uuid="nodeLevel1Uuid" @update:nodeLevel2Uuid="updateNodeLevel2Uuid"></nodeLevel2Select>
<nodeLevel2Select
v-else
ref="nodeLevel2SelectRef"
class="phase"
:projectUuid="nodeLevel1Uuid"
:phaseUuid="nodeLevel2Uuid"
@change="updateNodeLevel2Uuid"
></nodeLevel2Select>
</el-form-item>
</el-form>
</div>
@@ -113,9 +129,9 @@
:modalTableNameList="['TASK_POOL_CATEGORY','PROJECT_TASK_MODAL','TASK_POOL_PERFORMANCE']"
:data="rightTableData"
:loading="rightTableLoading"
:needTranslateTag="true"
:projectUuid="nodeLevel1Uuid"
:phaseUuid="nodeLevel2Uuid"
:editMode="true"
>
</loadCaseTable>
<!-- <loadcase-pro-table
@@ -163,8 +179,9 @@ import { modifyNodeTaskPerformanceApi } from '@/api/project/node';
import { TASK_CALCULATE_STATUS, TASK_PROCESS_STATUS } from '@/utils/enum/task';
import dayjs from 'dayjs';
import loadCaseTable from '@/components/common/treeCaseTable/loadCaseTable.vue';
import { getMemberListStr } from '@/utils/task';
import { getMemberListIds } from '@/utils/task';
import { getUserTenantId } from '@/utils/user';
import ProjectSelect from '@/components/common/projectSelect/index.vue';
const props = defineProps<{
showTaskDialog: boolean;
@@ -186,7 +203,11 @@ const getRightVxeRef = () => {
};
const getLeftVxeRef = () => {
return leftTableRef?.value?.loadcaseTableRef?.TreeTableRef?.treeTableRef;
if (selectMethod.value === 'template') {
return leftPoolTableRef?.value?.loadcaseTableRef?.TreeTableRef?.treeTableRef;
} else {
return leftProjectTableRef?.value?.loadcaseTableRef?.TreeTableRef?.treeTableRef;
}
};
const loadingInterface = ref(false);
@@ -195,9 +216,26 @@ const emits = defineEmits(['update:showTaskDialog', 'prePageFun', 'completeFun',
const rightTableData = ref<any[]>();
const leftProjectTableRef = ref();
const leftCurrentProjectUuid = ref<string>('');
const leftCurrentPhaseUuid = ref<string>('');
const changeLeftPhaseFun = async(data:any) => {
// console.log('changeLeftPhaseFun data', data);
leftCurrentPhaseUuid.value = data.phaseUuid;
leftProjectTableDataList.value = await getTaskTreeFun(leftCurrentProjectUuid.value, leftCurrentPhaseUuid.value);
expandTree(leftProjectTableRef.value);
};
const nodeLevel2Uuid = ref('');
const nodeLevel2SelectRef = ref();
const updateNodeLevel2Uuid = async (value:string) => {
const updateNodeLevel2Uuid = async ({ phaseUuid, type }:any) => {
if (type === 'rollBack') {
return ;
}
const { insertRecords, removeRecords, updateRecords }: any =
await getRightVxeRef().getRecordset();
@@ -208,17 +246,17 @@ const updateNodeLevel2Uuid = async (value:string) => {
type: 'warning',
})
.then(async () => {
nodeLevel2Uuid.value = value;
getNodeLevel3TreeByLevel2Uuid();
nodeLevel2Uuid.value = phaseUuid;
await getNodeLevel3TreeByLevel2Uuid();
})
.catch(() => {
nodeLevel2SelectRef.value.rollBackValue(nodeLevel2Uuid.value);
});
} else {
nodeLevel2Uuid.value = value;
getNodeLevel3TreeByLevel2Uuid();
nodeLevel2Uuid.value = phaseUuid;
await getNodeLevel3TreeByLevel2Uuid();
}
expandTree(rightTableRef.value);
};
const getNodeLevel3TreeByLevel2Uuid = async() => {
@@ -236,6 +274,12 @@ const getNodeLevel3TreeByLevel2Uuid = async() => {
});
};
const expandTree = (treeRef:any) => {
setTimeout(() => {
treeRef.loadcaseTableRef.TreeTableRef.treeTableRef.setAllTreeExpand(true);
}, 200);
};
const selectMethod = ref('template'); // template 模板库 project 历史项目
const transferTask = async () => {
@@ -278,6 +322,7 @@ const transferTask = async () => {
// // 将左侧选中数据平铺再插入到右侧table
// leftInsertArr.push(...(await flattenTreeData([leftMultipleSelection[index]], nodeLevel2Uuid.value, nodeLevel2Uuid.value)));
// }
console.log('右侧没勾选时,直接导入到右侧顶层');
// 右侧没勾选时,直接导入到右侧顶层
leftInsertArr.push(...(flattenTreeData([leftMultipleSelection[index]], nodeLevel2Uuid.value, nodeLevel2Uuid.value)));
} else {
@@ -286,6 +331,7 @@ const transferTask = async () => {
}
}
else {
console.log(' 同类型的可以从左往右导入,不同类型的需要判断能否作为子节点导入');
// 同类型的可以从左往右导入,不同类型的需要判断能否作为子节点导入
if (
rightSelection[0].nodeType === leftMultipleSelection[index].nodeType
@@ -334,6 +380,7 @@ const leftInsertToRight = async(leftSelectList:any[], rightData:any) => {
for (let i = 0; i < leftSelectList.length; i++) {
// 同层级数据导入将选中数据的子节点数据导入右边的children中
if (leftSelectList[i].nodeType === rightData.nodeType) {
console.log('同层级数据导入将选中数据的子节点数据导入右边的children中');
const insertArr = await mergeArrays(cloneDeep(leftSelectList[i].children), cloneDeep(rightData.children), rightData.fakeId, rightData.uuid, [], rightData.tagKeyList);
console.log('最终插入的平铺list', insertArr);
@@ -341,6 +388,7 @@ const leftInsertToRight = async(leftSelectList:any[], rightData:any) => {
}
// 非同层级导入,将选中数据作为子节点数据导入右边
else {
console.log('非同层级导入,将选中数据作为子节点数据导入右边');
const insertArr = flattenTreeData([leftSelectList[i]], rightData.fakeId, rightData.uuid, rightData.tagKeyList);
console.log('不同层级insertAtArr', insertArr);
getRightVxeRef().insertAt(insertArr, -1);
@@ -493,8 +541,8 @@ const addOrEditTaskFun = async() => {
beginTime: item.planTime?.length > 0 ? item.planTime[0] : '',
endTime: item.planTime?.length > 0 ? item.planTime[1] : '',
tenantId: getUserTenantId(),
eMemberList: getMemberListStr(item.eMemberList),
pMemberList: getMemberListStr(item.pMemberList),
eMemberList: getMemberListIds(item.eMemberList),
pMemberList: getMemberListIds(item.pMemberList),
analyseSoftware: Array.isArray(item.analyseSoftware) ? item.analyseSoftware?.join() : item.analyseSoftware,
};
});
@@ -505,8 +553,8 @@ const addOrEditTaskFun = async() => {
beginTime: item.planTime?.length > 0 ? item.planTime[0] : '',
endTime: item.planTime?.length > 0 ? item.planTime[1] : '',
tenantId: getUserTenantId(),
eMemberList: getMemberListStr(item.eMemberList),
pMemberList: getMemberListStr(item.pMemberList),
eMemberList: getMemberListIds(item.eMemberList),
pMemberList: getMemberListIds(item.pMemberList),
analyseSoftware: Array.isArray(item.analyseSoftware) ? item.analyseSoftware?.join() : item.analyseSoftware,
};
});
@@ -656,8 +704,10 @@ const prePageFun = () => {
emits('prePageFun', 'taskPage');
};
const leftTableRef = ref();
const leftTableDataList = ref<any[]>([]);
const leftPoolTableRef = ref();
const leftPoolTableDataList = ref<any[]>([]);
const leftProjectTableDataList = ref<any>([]);
const rightTableRef = ref();
@@ -669,13 +719,15 @@ const currentLoadcaseLib = ref();
const currentLoadcaseLibVersionInfo = ref();
const loadcaseLibVersionList = ref();
const changeLoadcaseLibFun = (lib:any) => {
const changeLoadcaseLibFun = async(lib:any) => {
currentLoadcaseLib.value = lib;
queryLoadcaseLibVersionsFun();
await queryLoadcaseLibVersionsFun();
expandTree(leftPoolTableRef.value);
};
const changeLoadcaseVersionFun = () => {
queryTaskPoolFun();
const changeLoadcaseVersionFun = async() => {
await queryTaskPoolFun();
expandTree(leftPoolTableRef.value);
};
const queryPoolListFun = async () => {
@@ -719,13 +771,13 @@ const queryTaskPoolFun = async () => {
let tree = [];
if (res.code === 200 && res.data.poolBrief && res.data && res.data.nodes) {
tree = transformPoolNodesToTree(res.data.nodes);
leftTableDataList.value = tree;
leftPoolTableDataList.value = tree;
nextTick(() => {
// 待修改
// leftTableRef.value?.changeLevel('全部展开');
// leftPoolTableRef.value?.changeLevel('全部展开');
});
} else {
leftTableDataList.value = [];
leftPoolTableDataList.value = [];
}
leftTableLoading.value = false;
};
@@ -825,4 +877,22 @@ onMounted(async() => {
});
</script>
<style lang="scss">
.left-panel {
.left-form-inline {
width: 100%;
}
.el-form-item__content{
width: 120px;
}
}
.right-panel {
.right-form-inline {
width: 100%;
}
.el-form-item__content{
width: 120px;
}
}
</style>
<style lang="scss" scoped src="./taskDialog.scss"></style>

View File

@@ -140,7 +140,7 @@ import { ElMessage } from 'element-plus';
import { getTaskTreeFun } from '@/views/task/projectDetail/components/projectApi';
import { filterTask, getIdMap } from '@/views/task/projectDetail/components/project';
import { tagSortList } from '@/utils/enum/node';
import { getMemberListStr } from '@/utils/task';
import { getMemberListIds } from '@/utils/task';
import { issuedTaskApi } from '@/api/project/demand';
const props = defineProps({
@@ -205,7 +205,7 @@ const confirmFun = async() => {
tagProperty[item] = parentNodeInfo[item] ? parentNodeInfo[item].split(',') : [];
});
const idMap = getIdMap(demandItem.projectId, demandItem.phaseId);
const pMemberListStr = getMemberListStr(demandItem.pMemberList);
const pMemberListStr = getMemberListIds(demandItem.pMemberList);
if (demandItem.insertMode === 'lib') {
const addTaskList = demandItem.chooseTaskList.map((task:any) => {
return {
@@ -333,7 +333,7 @@ onMounted(async() => {
insertMode: 'lib',
taskName: item.demandName,
chooseTaskList: [],
eMemberList: getMemberListStr(item.eMemberList),
eMemberList: getMemberListIds(item.eMemberList),
planTime: [item.beginTime, item.endTime],
};
}));

View File

@@ -202,7 +202,7 @@ import { getTaskTreeFun } from '../../projectDetail/components/projectApi';
import { tagSortList } from '@/utils/enum/node';
import { filterTask, getIdMap } from '../../projectDetail/components/project';
import batchSendTask from './components/batchSendTask.vue';
import { getMemberListStr } from '@/utils/task';
import { getMemberListIds } from '@/utils/task';
// const commonStore = CommonStore();
const bachSendVisible = ref(false);
@@ -357,7 +357,7 @@ const sendTaskConfirmFun = () => {
tagProperty[item] = parentNodeInfo[item] ? parentNodeInfo[item].split(',') : [];
});
let params = {};
const pMemberListStr = getMemberListStr(sendForm.pMemberList);
const pMemberListStr = getMemberListIds(sendForm.pMemberList);
if (insertTaskMode.value === 'lib') {
const addTaskList = sendForm.chooseTaskList.map((item:any) => {
return {
@@ -417,7 +417,7 @@ const sendTaskFun = async(row:any) => {
}
}
sendForm.taskName = row.demandName;
sendForm.eMemberList = getMemberListStr(row.eMemberList);
sendForm.eMemberList = getMemberListIds(row.eMemberList);
console.log('sendForm', sendForm, row);
};

View File

@@ -68,7 +68,7 @@ import Dialog from '@/components/common/dialog/index.vue';
import TableForm from '@/components/common/table/tableForm.vue';
import { tableActionsLength } from '@/utils/common';
import dayjs from 'dayjs';
import { getMemberListStr } from '@/utils/task';
import { getMemberListIds } from '@/utils/task';
const exeTableRef = ref();
@@ -105,7 +105,7 @@ const editTaskFun = (row: any) => {
};
const setFormData = (row: any) => {
if (tableFormRef.value) {
tableFormRef.value.setFormDataFun({ ...row, achieveStatus: row.achieveStatus + '', eMemberList: getMemberListStr(row.eMemberList) });
tableFormRef.value.setFormDataFun({ ...row, achieveStatus: row.achieveStatus + '', eMemberList: getMemberListIds(row.eMemberList) });
}
};
@@ -176,7 +176,7 @@ const confirmFun = async() => {
exeStatus: fromData.exeStatus,
achieveStatus: fromData.achieveStatus,
process: fromData.progress,
pMemberList: getMemberListStr(fromData.pMemberList),
pMemberList: getMemberListIds(fromData.pMemberList),
nodeName: fromData.taskName,
},
};

View File

@@ -125,7 +125,7 @@ import { ElMessage } from 'element-plus';
import { dataDelFileApi, dataQueryDirApi } from '@/api/data/data';
import demandTable from '../components/demandTable.vue';
import { tableActionsLength } from '@/utils/common';
import { getMemberListStr } from '@/utils/task';
import { getMemberListIds } from '@/utils/task';
const env = import.meta.env;
const PREFIX = env.VITE_API_PREFIX_PROJECT;
@@ -207,7 +207,7 @@ const visibleDialog = async( visible:boolean, row?: any) => {
tableFormRef.value.setOptionsFun('simType', simList.A);
let pMemberList = '';
if (row.pMemberList) {
pMemberList = getMemberListStr(row.pMemberList);
pMemberList = getMemberListIds(row.pMemberList);
}
tableFormRef.value.setFormDataFun({ ...row, pMemberList });
});