Files
SPDM/src/components/common/treeCaseTable/nodeDetailDialog.vue
2026-01-29 20:29:39 +08:00

396 lines
12 KiB
Vue

<template>
<div class="node-detail">
<Dialog
v-model="visible"
show-footer
show-cancel-button
show-confirm-button
:diaTitle="localDiaTitle"
:confirm-closable="false"
:width="formData?.nodeType === NODE_TYPE.TASK ? 800 : 400"
>
<template #default>
<TableForm
v-if="visible"
:colNum="formData?.nodeType === NODE_TYPE.TASK ? 2 : 1"
ref="tableFormRef"
:tableName="localTableName"
v-model:data="formData"
:formAttrs="{
nodeCode: { disabled: formData.nodeType === NODE_TYPE.DISCIPLINE },
englishName: { disabled: formData.nodeType === NODE_TYPE.DISCIPLINE },
nodeType: { disabled: localOperationType === 'edit' },
}"
:rule-data="ruleData"
:itemNum="localItemNum"
@change="onFormChangeFun"
>
<template #form-nodeName>
<nodeNameMixed
v-model="formData.nodeName"
:nodeType="formData.nodeType"
:editable="true"
/>
</template>
<template #form-flowTemplate>
<flowTemplateSelect v-model="selectedFlowTemplate" />
</template>
<template #form-standard>
<knowledgeSelect v-model="standard" v-model:modelName="formData.standardName" />
</template>
</TableForm>
</template>
<template #footer>
<div>
<el-button @click="onCancelFun">{{ $t('通用.取消') }}</el-button>
<el-button type="primary" @click="onConfirmFun">{{ $t('通用.确定') }}</el-button>
</div>
</template>
</Dialog>
</div>
</template>
<script setup lang="ts">
import { ref, computed, nextTick, watch, onMounted } 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 { disposeTaskMembers } from '@/utils/task';
import { disposeTagKey } from '@/views/task/projectDetail/components/project';
import { isCategoryType, isCategoryNodeType, validateCategoryLevel } from '@/utils/node';
import flowTemplateSelect from './flowTemplateSelect.vue';
import knowledgeSelect from './knowledgeSelect.vue';
import nodeNameMixed from './nodeNameMixed.vue';
import { TABLE_NAME } from '@/utils/enum/tableName';
import { useDict } from '@/utils/useDict';
import { useI18n } from 'vue-i18n';
import { useTaskStore } from '@/stores/taskPool';
const taskStore = useTaskStore();
enum OPERATION_TYPE {
ADD = 'add',
EDIT = 'edit',
}
interface Props {
modelValue: boolean;
tableName?: string;
detail?: any;
operationType: OPERATION_TYPE | string;
nodeType?: string;
modalTableNameList?: string[];
itemNumList?: number[];
belongProject?: boolean;
parentCategoryPath?: string[];
existingNodeCodes?: string[];
}
const props = withDefaults(defineProps<Props>(), {
modelValue: false,
tableName: '',
operationType: OPERATION_TYPE.ADD,
nodeType: '',
modalTableNameList: () => [
TABLE_NAME.TASK_POOL_CATEGORY,
TABLE_NAME.PROJECT_TASK_MODAL,
TABLE_NAME.TASK_POOL_PERFORMANCE,
],
itemNumList: () => [3, 18, 7],
detail: null,
belongProject: false,
parentCategoryPath: () => [],
existingNodeCodes: () => [],
});
const emits = defineEmits(['update:modelValue', 'confirm']);
const visible = computed({
get: () => props.modelValue,
set: (val) => emits('update:modelValue', val),
});
const tableFormRef = ref<any>();
const { t } = useI18n();
const localDiaTitle = ref('');
const localOperationType = ref<OPERATION_TYPE | string>(OPERATION_TYPE.ADD);
const localTableName = ref(props.tableName || '');
const localItemNum = ref(props.itemNumList?.[1] || 4);
// 流程模板相关
const selectedFlowTemplate = ref<any>(null);
const standard = ref();
const tagSortOrderList = ref<string[]>([]);
const tagNameMap = ref<Map<string, string>>(new Map());
const formData = ref<any>({});
watch(
() => props.modelValue,
(val) => {
if (val) {
if (localOperationType.value === OPERATION_TYPE.ADD) {
resetFun();
}
nextTick(() => {
if (formData.value) {
standard.value = formData.value.standard;
if (formData.value.flowTemplate) {
selectedFlowTemplate.value = formData.value.flowTemplate;
} else {
selectedFlowTemplate.value = null;
}
}
});
taskStore.fetchTemplates(true);
}
}
);
const resetFun = () => {
standard.value = null;
selectedFlowTemplate.value = null;
tableFormRef.value?.resetFun();
};
const onFormChangeFun = (data: any) => {
if (data.key === 'nodeType') {
formData.value.nodeName = null;
formData.value.nodeCode = null;
formData.value.englishName = null;
}
// if (data.key === 'eMemberList') {
// formData.value.eMemberListArr = data.val;
// }
// if (data.key === 'pMemberList') {
// formData.value.pMemberListArr = data.val;
// }
// if (data.key === 'payAttentionMemberList') {
// formData.value.payAttentionMemberListArr = data.val;
// }
const memberKeys = disposeTaskMembers('tableFormChangeFun', data);
for (const key in memberKeys) {
formData.value[key] = memberKeys[key];
}
};
const onCancelFun = () => {
visible.value = false;
};
const onConfirmFun = async () => {
const valid = await tableFormRef.value?.validateFun();
if (valid) {
const submitData = { ...formData.value };
submitData.standard = standard.value;
submitData.standardName = formData.value.standardName;
if (selectedFlowTemplate.value) {
submitData.flowTemplate = selectedFlowTemplate.value;
}
if (formData.value?.tagKeyList) {
disposeTagKey(submitData, formData.value?.tagKeyList || [], getTagKeyMap());
} else {
submitData.tagKeyList = [];
}
// 处理时间范围
if (submitData.planTime) {
submitData.beginTime = submitData.planTime[0];
submitData.endTime = submitData.planTime[1];
}
// submitData.pMemberIds = '';
// if (submitData.pMemberList?.length > 0) {
// submitData.pMemberIds = submitData.pMemberList;
// }
// submitData.eMemberIds = '';
// if (submitData.eMemberList?.length > 0) {
// submitData.eMemberIds = submitData.eMemberList;
// }
// submitData.payAttentionMemberIds = '';
// if (submitData.payAttentionMemberList?.length > 0) {
// submitData.payAttentionMemberIds = submitData.payAttentionMemberList;
// }
disposeTaskMembers('setListToIdsNoTranslate', submitData);
emits('confirm', submitData);
}
};
const prepareFromProps = () => {
const nodeType = props.nodeType;
const operation = props.operationType;
const detail = props.detail;
let text = operation === OPERATION_TYPE.ADD ? t('通用.新增') : t('通用.编辑');
let targetTableName = props.modalTableNameList?.[1] || '';
let targetItemNum = props.itemNumList?.[1] || 4;
switch (nodeType) {
case NODE_TYPE.CATEGORY:
text += t('工况库.分类');
targetTableName = props.modalTableNameList?.[0] || targetTableName;
targetItemNum = props.itemNumList?.[0] || targetItemNum;
break;
case NODE_TYPE.TASK:
if (props.belongProject) {
text += t('通用.任务');
} else {
text += t('工况库.工况');
}
targetTableName = props.modalTableNameList?.[1] || targetTableName;
targetItemNum = props.itemNumList?.[1] || targetItemNum;
break;
case NODE_TYPE.PERFORMANCE:
text += t('工况库.指标');
targetTableName = props.modalTableNameList?.[2] || targetTableName;
targetItemNum = props.itemNumList?.[2] || targetItemNum;
break;
}
if (isCategoryNodeType(nodeType)) {
text += t('工况库.分类');
targetTableName = props.modalTableNameList?.[0] || targetTableName;
targetItemNum = props.itemNumList?.[0] || targetItemNum;
}
localDiaTitle.value = text;
localOperationType.value = operation;
localTableName.value = targetTableName;
localItemNum.value = targetItemNum;
if (operation === OPERATION_TYPE.ADD) {
const initData: any = {};
if (isCategoryType(nodeType)) {
initData.nodeType = null;
} else {
initData.nodeType = nodeType;
}
formData.value = initData;
} else {
formData.value = detail
? {
...detail,
...disposeTaskMembers('getIds', detail),
// eMemberList: getMemberListIds(detail.eMemberList),
// pMemberList: getMemberListIds(detail.pMemberList),
// payAttentionMemberList: getMemberListIds(detail.payAttentionMemberList),
}
: {};
}
};
watch(
() => props.modelValue,
(val) => {
if (val) {
prepareFromProps();
} else {
formData.value = {};
}
}
);
watch(
() => formData.value.nodeName,
(val) => {
if (formData.value.nodeType === NODE_TYPE.DISCIPLINE) {
formData.value.nodeCode = val;
formData.value.englishName = val;
}
}
);
const ruleData = computed(() => ({
nodeCode: [
// {
// message: t('工况库.编号已存在'),
// trigger: 'blur',
// validator: (val: unknown) => {
// if (!val) return true;
// if (formData.value.nodeType === NODE_TYPE.DISCIPLINE) return true;
// return !props.existingNodeCodes?.includes(val as string);
// },
// },
],
nodeType: [
{
message: computed(() => {
if (tagSortOrderList.value.length === 0) {
return t('工况库.需按照配置顺序逐层添加');
}
const orderNames = tagSortOrderList.value
.filter((type) => isCategoryNodeType(type))
.map((type) => tagNameMap.value.get(type) || type)
.join(' → ');
return t('工况库.请按照顺序添加', { order: orderNames });
}),
trigger: 'blur',
validator: (val: unknown) => {
if (localOperationType.value === OPERATION_TYPE.EDIT) {
return true;
}
if (!isCategoryNodeType(val as string)) {
return true;
}
if (!props.parentCategoryPath || props.parentCategoryPath.length === 0) {
return true;
}
if (tagSortOrderList.value.length === 0) {
return true;
}
return validateCategoryLevel(
val as string,
props.parentCategoryPath,
tagSortOrderList.value
);
},
},
],
highValue: [
{
message: t('工况库.指标类型为数值时目标值应为数字'),
trigger: 'change',
validator: (val: unknown) => {
if (val === null || val === undefined || val === '') {
return true;
}
if (formData.value.nodeType === NODE_TYPE.PERFORMANCE) {
if (formData.value.performanceType === '1') {
const s = String(val ?? '').trim();
return s !== '' && Number.isFinite(Number(s));
} else if (formData.value.performanceType === '2') {
return true;
} else {
return true;
}
}
return true;
},
},
],
}));
const initDictData = () => {
const { TAG_TYPE_MAP_LIST, POOL_CATEGORY_TYPE } = useDict(
'TAG_TYPE_MAP_LIST',
'POOL_CATEGORY_TYPE'
);
tagSortOrderList.value =
TAG_TYPE_MAP_LIST?.value?.A?.reduce((acc: string[], curr: { value: string }) => {
acc.push(curr.value);
return acc;
}, []) || [];
const categoryTypeList = POOL_CATEGORY_TYPE?.value.A || [];
categoryTypeList.forEach((item: { value: string; label: string }) => {
tagNameMap.value.set(item.value, item.label);
});
};
onMounted(() => {
initDictData();
});
</script>
<style lang="scss" scoped>
.upload {
width: 100%;
}
.node-detail {
:deep(.full) {
width: 100%;
}
}
</style>