fix(全局): 部分 bug 修复

This commit is contained in:
baiqi 2024-06-19 18:58:51 +08:00 committed by Craftsman
parent 1b26df9c2d
commit 33929d6978
17 changed files with 201 additions and 124 deletions

View File

@ -85,7 +85,6 @@
} from '@/api/modules/case-management/featureCase'; } from '@/api/modules/case-management/featureCase';
import { useI18n } from '@/hooks/useI18n'; import { useI18n } from '@/hooks/useI18n';
import useAppStore from '@/store/modules/app'; import useAppStore from '@/store/modules/app';
import useFeatureCaseStore from '@/store/modules/case/featureCase';
import useMinderStore from '@/store/modules/components/minder-editor/index'; import useMinderStore from '@/store/modules/components/minder-editor/index';
import { MinderCustomEvent } from '@/store/modules/components/minder-editor/types'; import { MinderCustomEvent } from '@/store/modules/components/minder-editor/types';
import { filterTree, getGenerateId, mapTree, replaceNodeInTree } from '@/utils'; import { filterTree, getGenerateId, mapTree, replaceNodeInTree } from '@/utils';
@ -160,60 +159,66 @@
async function initCaseTree(notRemote = false) { async function initCaseTree(notRemote = false) {
try { try {
loading.value = true; loading.value = true;
let res: MinderJsonNode[]; if (!notRemote) {
if (notRemote) { const res = await getCaseMinderTree({
res = caseTree.value;
} else {
res = await getCaseMinderTree({
projectId: appStore.currentProjectId, projectId: appStore.currentProjectId,
moduleId: '', // moduleId: '', //
}); });
} caseTree.value = mapTree<MinderJsonNode>(res, (e) => ({
caseTree.value = mapTree<MinderJsonNode>(res, (e) => ({ ...e,
...e, data: {
data: { ...e.data,
id: e.id, id: e.id || e.data?.id || '',
text: e.name, text: e.name || e.data?.text || '',
resource: props.modulesCount[e.id] !== undefined ? [moduleTag] : e.data?.resource, resource: props.modulesCount[e.id] !== undefined ? [moduleTag] : e.data?.resource,
expandState: e.level === 1 ? 'expand' : 'collapse', expandState: e.level === 1 ? 'expand' : 'collapse',
count: props.modulesCount[e.id], count: props.modulesCount[e.id],
isNew: false, isNew: false,
changed: false, changed: false,
}, },
children: children:
props.modulesCount[e.id] > 0 && !e.children?.length props.modulesCount[e.id] > 0 && !e.children?.length
? [ ? [
{ {
data: { data: {
id: 'fakeNode', id: 'fakeNode',
text: 'fakeNode', text: 'fakeNode',
resource: ['fakeNode'], resource: ['fakeNode'],
isNew: false, isNew: false,
changed: false, changed: false,
},
}, },
}, ]
] : e.children,
: e.children, }));
})); importJson.value.root = {
importJson.value.root = { children: caseTree.value,
children: caseTree.value, data: {
data: { id: 'NONE',
id: 'NONE', text: t('ms.minders.allModule'),
text: t('ms.minders.allModule'), resource: [moduleTag],
resource: [moduleTag], disabled: true,
disabled: true, },
}, };
}; importJson.value.treePath = [];
importJson.value.treePath = []; window.minder.importJson(importJson.value);
window.minder.importJson(importJson.value); }
window.minder.execCommand('camera', window.minder.getRoot(), 100); if (notRemote) {
if (props.moduleId !== 'all') { if (props.moduleId !== 'all') {
// ID // ID
nextTick(() => { nextTick(() => {
minderStore.dispatchEvent(MinderEventName.ENTER_NODE, undefined, undefined, undefined, [ minderStore.dispatchEvent(MinderEventName.ENTER_NODE, undefined, undefined, undefined, [
window.minder.getNodeById(props.moduleId), window.minder.getNodeById(props.moduleId),
]); ]);
}); });
} else {
// ID
nextTick(() => {
minderStore.dispatchEvent(MinderEventName.ENTER_NODE, undefined, undefined, undefined, [
importJson.value.root,
]);
});
}
} }
} catch (error) { } catch (error) {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
@ -391,12 +396,13 @@
if ((!res || res.length === 0) && node.children?.length) { if ((!res || res.length === 0) && node.children?.length) {
// //
node.expand(); node.expand();
node.renderTree(); window.minder.renderNodeBatch(node.children);
node.layout(); node.layout();
data.isLoaded = true;
return; return;
} }
// TODO: // TODO:
const waitingRenderNodes: MinderJsonNode[] = []; let waitingRenderNodes: MinderJsonNode[] = [];
res.forEach((e) => { res.forEach((e) => {
// //
const child = window.minder.createNode( const child = window.minder.createNode(
@ -439,14 +445,14 @@
}); });
node.expand(); node.expand();
// node.renderTree(); // node.renderTree();
if (node.children && node.children.length > 0) {
waitingRenderNodes = waitingRenderNodes.concat(node.children);
}
window.minder.renderNodeBatch(waitingRenderNodes); window.minder.renderNodeBatch(waitingRenderNodes);
node.layout(); node.layout();
window.minder.execCommand('camera', node, 100); data.isLoaded = true;
if (node.data) {
node.data.isLoaded = true;
}
// importJson // importJson
replaceNodeInTree([importJson.value.root], node.data?.id || '', node, 'data', 'id'); replaceNodeInTree([importJson.value.root], node.data?.id || '', window.minder.exportNode(node), 'data', 'id');
} catch (error) { } catch (error) {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.log(error); console.log(error);
@ -458,11 +464,6 @@
extraVisible.value = false; extraVisible.value = false;
showDetailMenu.value = false; showDetailMenu.value = false;
resetExtractInfo(); resetExtractInfo();
if (node.children && node.children.length > 0 && node.data?.expandState === 'collapse') {
node.expand();
node.renderTree();
node.layout();
}
} }
setPriorityView(true, 'P'); setPriorityView(true, 'P');
} }
@ -524,7 +525,7 @@
if (!caseOffspringTags.some((e) => node.data?.resource?.includes(e))) { if (!caseOffspringTags.some((e) => node.data?.resource?.includes(e))) {
// //
tempMinderParams.value.deleteResourceList.push({ tempMinderParams.value.deleteResourceList.push({
id: node.data?.id || getGenerateId(), id: node.data?.id || '',
type: node.data?.resource?.[0] || moduleTag, type: node.data?.resource?.[0] || moduleTag,
}); });
} }
@ -556,12 +557,12 @@
* 解析用例节点信息 * 解析用例节点信息
* @param node 用例节点 * @param node 用例节点
*/ */
function getCaseNodeInfo(node: MinderJsonNode) { function getCaseNodeInfo(node?: MinderJsonNode) {
let textStep: MinderJsonNode | undefined; // let textStep: MinderJsonNode | undefined; //
let prerequisiteNode: MinderJsonNode | undefined; // let prerequisiteNode: MinderJsonNode | undefined; //
let remarkNode: MinderJsonNode | undefined; // let remarkNode: MinderJsonNode | undefined; //
const stepNodes: MinderJsonNode[] = []; // const stepNodes: MinderJsonNode[] = []; //
node.children?.forEach((item) => { node?.children?.forEach((item) => {
if (item.data?.resource?.includes(textDescTag)) { if (item.data?.resource?.includes(textDescTag)) {
textStep = item; textStep = item;
} else if (item.data?.resource?.includes(stepTag)) { } else if (item.data?.resource?.includes(stepTag)) {
@ -577,7 +578,7 @@
id: child.data?.id || getGenerateId(), id: child.data?.id || getGenerateId(),
num: i, num: i,
desc: child.data?.text || '', desc: child.data?.text || '',
result: child.children?.[0].data?.text || '', result: child.children?.[0]?.data?.text || '',
}; };
}); });
return { return {
@ -587,7 +588,7 @@
textDescription: textStep?.data?.text || '', textDescription: textStep?.data?.text || '',
expectedResult: textStep?.children?.[0]?.data?.text || '', expectedResult: textStep?.children?.[0]?.data?.text || '',
description: remarkNode?.data?.text || '', description: remarkNode?.data?.text || '',
priority: node.data?.priority, priority: node?.data?.priority,
}; };
} }
@ -612,6 +613,17 @@
}; };
} }
function resetMinderParams() {
tempMinderParams.value = {
projectId: appStore.currentProjectId,
versionId: '',
updateCaseList: [],
updateModuleList: [],
deleteResourceList: [],
additionalNodeList: [],
};
}
/** /**
* 生成脑图保存的入参 * 生成脑图保存的入参
*/ */
@ -675,28 +687,20 @@
await saveCaseMinder(makeMinderParams(fullJson)); await saveCaseMinder(makeMinderParams(fullJson));
extraVisible.value = false; extraVisible.value = false;
Message.success(t('common.saveSuccess')); Message.success(t('common.saveSuccess'));
tempMinderParams.value = { resetMinderParams();
projectId: appStore.currentProjectId,
versionId: '',
updateCaseList: [],
updateModuleList: [],
deleteResourceList: [],
additionalNodeList: [],
};
emit('save'); emit('save');
callback(); callback();
} catch (error) { } catch (error) {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.log(error); console.log(error);
resetMinderParams();
} finally { } finally {
loading.value = false; loading.value = false;
} }
} }
const featureCaseStore = useFeatureCaseStore();
watch( watch(
() => featureCaseStore.modulesCount, () => props.moduleId,
() => { () => {
initCaseTree(true); initCaseTree(true);
}, },

View File

@ -259,9 +259,10 @@ export default function useMinderBaseApi({ hasEditPermission }: { hasEditPermiss
if ( if (
Object.keys(node.data || {}).length === 0 || Object.keys(node.data || {}).length === 0 ||
node.data?.id === 'root' || node.data?.id === 'root' ||
(node.parent?.data?.resource || []).length === 0 (node.parent?.data?.resource || []).length === 0 ||
node.parent?.data?.id === 'NONE'
) { ) {
// 没有数据的节点、默认模块节点、父节点为文本节点的节点不可替换标签 // 没有数据的节点、默认模块节点、父节点为文本节点、父节点为NONE虚拟根节点的节点不可替换标签
return []; return [];
} }
if (node.data?.resource?.some((e) => topTags.includes(e))) { if (node.data?.resource?.some((e) => topTags.includes(e))) {

View File

@ -13,7 +13,7 @@
:can-show-priority-menu="false" :can-show-priority-menu="false"
:can-show-float-menu="canShowFloatMenu" :can-show-float-menu="canShowFloatMenu"
:can-show-delete-menu="canShowDeleteMenu" :can-show-delete-menu="canShowDeleteMenu"
:disable="!hasEditPermission" :disabled="!hasEditPermission"
custom-priority custom-priority
single-tag single-tag
tag-enable tag-enable
@ -86,7 +86,7 @@
</a-tooltip> </a-tooltip>
</div> </div>
<a-form ref="configFormRef" :model="configForm" :disabled="!hasEditPermission" layout="vertical"> <a-form ref="configFormRef" :model="configForm" :disabled="!hasEditPermission" layout="vertical">
<a-form-item v-if="hasEditPermission"> <a-form-item v-if="hasEditPermission && configForm.level === 2">
<template #label> <template #label>
<div class="flex items-center"> <div class="flex items-center">
<div>{{ t('testPlan.planForm.pickCases') }}</div> <div>{{ t('testPlan.planForm.pickCases') }}</div>
@ -127,27 +127,37 @@
</div> </div>
</div> </div>
</a-form-item> </a-form-item>
<template <template v-if="configForm.type !== PlanMinderCollectionType.FUNCTIONAL">
v-if="
configForm.type !== PlanMinderCollectionType.FUNCTIONAL &&
(configForm.level === 1 || !configForm.extended)
"
>
<a-form-item :label="t('system.project.resourcePool')"> <a-form-item :label="t('system.project.resourcePool')">
<a-select v-model:model-value="configForm.testResourcePoolId" :options="resourcePoolOptions"></a-select> <a-select
v-model:model-value="configForm.testResourcePoolId"
:options="resourcePoolOptions"
:disabled="configForm.level === 2 && configForm.extended"
></a-select>
</a-form-item> </a-form-item>
<a-form-item :label="t('project.environmental.env')"> <a-form-item :label="t('project.environmental.env')">
<a-select v-model:model-value="configForm.environmentId" :options="environmentOptions"></a-select> <a-select
v-model:model-value="configForm.environmentId"
:options="environmentOptions"
:disabled="configForm.level === 2 && configForm.extended"
></a-select>
</a-form-item> </a-form-item>
<a-form-item class="hidden-item"> <a-form-item class="hidden-item">
<a-radio-group v-model:model-value="configForm.executeMethod"> <a-radio-group
v-model:model-value="configForm.executeMethod"
:disabled="configForm.level === 2 && configForm.extended"
>
<a-radio :value="RunMode.SERIAL">{{ t('testPlan.testPlanIndex.serial') }}</a-radio> <a-radio :value="RunMode.SERIAL">{{ t('testPlan.testPlanIndex.serial') }}</a-radio>
<a-radio :value="RunMode.PARALLEL">{{ t('testPlan.testPlanIndex.parallel') }}</a-radio> <a-radio :value="RunMode.PARALLEL">{{ t('testPlan.testPlanIndex.parallel') }}</a-radio>
</a-radio-group> </a-radio-group>
</a-form-item> </a-form-item>
<a-form-item v-if="configForm.executeMethod === RunMode.SERIAL" class="hidden-item"> <a-form-item v-if="configForm.executeMethod === RunMode.SERIAL" class="hidden-item">
<div class="flex items-center gap-[8px]"> <div class="flex items-center gap-[8px]">
<a-switch v-model:model-value="configForm.stopOnFail" size="small"></a-switch> <a-switch
v-model:model-value="configForm.stopOnFail"
size="small"
:disabled="configForm.level === 2 && configForm.extended"
></a-switch>
<div>{{ t('ms.minders.failStop') }}</div> <div>{{ t('ms.minders.failStop') }}</div>
</div> </div>
</a-form-item> </a-form-item>
@ -206,7 +216,7 @@
class="hidden-item" class="hidden-item"
> >
<div class="flex items-center gap-[8px]"> <div class="flex items-center gap-[8px]">
<a-switch v-model:model-value="configForm.extended" size="small"></a-switch> <a-switch v-model:model-value="configForm.extended" size="small" @change="handleExtendChange"></a-switch>
<div>{{ t('ms.minders.extend') }}</div> <div>{{ t('ms.minders.extend') }}</div>
</div> </div>
</a-form-item> </a-form-item>
@ -270,6 +280,7 @@
const props = defineProps<{ const props = defineProps<{
planId: string; planId: string;
status: string;
}>(); }>();
const emit = defineEmits<{ const emit = defineEmits<{
(e: 'save'): void; (e: 'save'): void;
@ -297,7 +308,9 @@
const showConfigMenu = ref(false); const showConfigMenu = ref(false);
const canShowDeleteMenu = ref(false); const canShowDeleteMenu = ref(false);
const extraVisible = ref<boolean>(false); const extraVisible = ref<boolean>(false);
const hasEditPermission = hasAnyPermission(['PROJECT_TEST_PLAN:READ+UPDATE']); const hasEditPermission = computed(
() => props.status !== 'ARCHIVED' && hasAnyPermission(['PROJECT_TEST_PLAN:READ+UPDATE'])
);
/** /**
* 检测节点可展示的菜单项 * 检测节点可展示的菜单项
@ -306,13 +319,18 @@
function checkNodeCanShowMenu(node: PlanMinderNode) { function checkNodeCanShowMenu(node: PlanMinderNode) {
const { data } = node; const { data } = node;
if (!hasEditPermission && (data?.level === 1 || data?.level === 2)) { if (!hasEditPermission.value && (data?.level === 1 || data?.level === 2)) {
// //
if (data?.type === PlanMinderCollectionType.FUNCTIONAL) { if (data?.type === PlanMinderCollectionType.FUNCTIONAL) {
canShowFloatMenu.value = false; canShowFloatMenu.value = false;
} else { } else {
canShowFloatMenu.value = true; canShowFloatMenu.value = true;
showConfigMenu.value = true; showConfigMenu.value = true;
showAssociateCaseMenu.value = false;
canShowExecuteMethodMenu.value = false;
canShowDeleteMenu.value = false;
insertSiblingMenus.value = [];
insertSonMenus.value = [];
} }
return; return;
} }
@ -694,6 +712,39 @@
} }
} }
function handleExtendChange(val: string | number | boolean) {
if (val && configForm.value) {
const node: PlanMinderNode = window.minder.getNodeById(configForm.value.id);
if (node.parent?.data) {
const {
priority,
executeMethod,
grouped,
environmentId,
testResourcePoolId,
retryOnFail,
retryType,
retryTimes,
retryInterval,
stopOnFail,
} = node.parent.data;
configForm.value = {
...configForm.value,
priority,
executeMethod,
grouped,
environmentId,
testResourcePoolId,
retryOnFail,
retryType,
retryTimes,
retryInterval,
stopOnFail,
};
}
}
}
/** /**
* 初始化测试规划脑图 * 初始化测试规划脑图
*/ */
@ -762,6 +813,7 @@
loading.value = true; loading.value = true;
await editPlanMinder(makeMinderParams(fullJson)); await editPlanMinder(makeMinderParams(fullJson));
Message.success(t('common.saveSuccess')); Message.success(t('common.saveSuccess'));
clearSelectedCases();
handleConfigCancel(); handleConfigCancel();
initMinder(); initMinder();
callback(); callback();

View File

@ -90,7 +90,7 @@ export default function useEventListener(listener: UseEventListenerProps) {
// 监听脑图自定义事件 // 监听脑图自定义事件
watch( watch(
() => minderStore.event.timestamp, () => minderStore.event.eventId,
() => { () => {
if (listener.handleMinderEvent) { if (listener.handleMinderEvent) {
listener.handleMinderEvent(minderStore.event); listener.handleMinderEvent(minderStore.event);

View File

@ -1,6 +1,6 @@
<template> <template>
<div ref="mec" class="ms-minder-container"> <div ref="mec" class="ms-minder-container">
<minderHeader :icon-buttons="props.iconButtons" @save="save" /> <minderHeader :icon-buttons="props.iconButtons" :disabled="props.disabled" @save="save" />
<Navigator /> <Navigator />
<div <div
v-if="currentTreePath?.length > 0" v-if="currentTreePath?.length > 0"
@ -125,7 +125,6 @@
]); ]);
if (selectNodes.length > 0 && !notChangeCommands.has(event.commandName.toLocaleLowerCase())) { if (selectNodes.length > 0 && !notChangeCommands.has(event.commandName.toLocaleLowerCase())) {
minderStore.setMinderUnsaved(true); minderStore.setMinderUnsaved(true);
minderStore.dispatchEvent(MinderEventName.MINDER_CHANGED);
selectNodes.forEach((node: MinderJsonNode) => { selectNodes.forEach((node: MinderJsonNode) => {
markChangeNode(node); markChangeNode(node);
}); });
@ -155,7 +154,7 @@
* 切换脑图展示的节点层级 * 切换脑图展示的节点层级
* @param node 切换的节点 * @param node 切换的节点
*/ */
function switchNode(node: MinderJsonNode | MinderJsonNodeData) { function switchNode(node?: MinderJsonNode | MinderJsonNodeData) {
if (minderStore.minderUnsaved) { if (minderStore.minderUnsaved) {
// //
replaceNodeInTree( replaceNodeInTree(
@ -166,12 +165,12 @@
'id' 'id'
); );
} }
if (node.id === 'NONE') { if (node?.id === 'NONE') {
innerImportJson.value = importJson.value; innerImportJson.value = importJson.value;
} else if (node.data) { } else if (node?.data) {
innerImportJson.value = findNodePathByKey([importJson.value.root], node.data.id, 'data', 'id') as MinderJson; innerImportJson.value = findNodePathByKey([importJson.value.root], node.data.id, 'data', 'id') as MinderJson;
} else { } else {
innerImportJson.value = findNodePathByKey([importJson.value.root], node.id, 'data', 'id') as MinderJson; innerImportJson.value = findNodePathByKey([importJson.value.root], node?.id, 'data', 'id') as MinderJson;
} }
window.minder.importJson(innerImportJson.value); window.minder.importJson(innerImportJson.value);
const root: MinderJsonNode = window.minder.getRoot(); const root: MinderJsonNode = window.minder.getRoot();
@ -203,7 +202,7 @@
} }
watch( watch(
() => minderStore.event.timestamp, () => minderStore.event.eventId,
() => { () => {
if (minderStore.event.name === MinderEventName.HOTBOX && minderStore.event.nodePosition) { if (minderStore.event.name === MinderEventName.HOTBOX && minderStore.event.nodePosition) {
const nodeDomWidth = minderStore.event.nodeDom?.getBoundingClientRect().width || 0; const nodeDomWidth = minderStore.event.nodeDom?.getBoundingClientRect().width || 0;

View File

@ -11,7 +11,7 @@
<span></span> <span></span>
<template #content> <template #content>
<a-radio-group <a-radio-group
v-if="currentNodeTags.length > 0 && tags.length > 0" v-if="tags.length > 0"
v-model:model-value="currentNodeTags[0]" v-model:model-value="currentNodeTags[0]"
type="button" type="button"
size="mini" size="mini"
@ -212,7 +212,7 @@
const menuPopupOffset = ref<TriggerPopupTranslate>([0, 0]); const menuPopupOffset = ref<TriggerPopupTranslate>([0, 0]);
watch( watch(
() => minderStore.event.timestamp, () => minderStore.event.eventId,
async () => { async () => {
if (window.minder) { if (window.minder) {
let nodePosition: MinderNodePosition | undefined; let nodePosition: MinderNodePosition | undefined;

View File

@ -16,7 +16,7 @@ export interface MinderJsonNodeData {
text: string; text: string;
resource?: string[]; resource?: string[];
expandState?: 'collapse' | 'expand'; expandState?: 'collapse' | 'expand';
priority?: number | string; priority?: number;
// 前端渲染字段 // 前端渲染字段
isNew?: boolean; // 是否脑图新增节点,需要在初始化脑图数据时标记已存在节点为 false 以区分是否新增节点 isNew?: boolean; // 是否脑图新增节点,需要在初始化脑图数据时标记已存在节点为 false 以区分是否新增节点
changed?: boolean; // 脑图节点是否发生过变化 changed?: boolean; // 脑图节点是否发生过变化

View File

@ -13,7 +13,7 @@ const useMinderStore = defineStore('minder', {
state: (): MinderState => ({ state: (): MinderState => ({
event: { event: {
name: '' as MinderEventName, name: '' as MinderEventName,
timestamp: 0, eventId: '',
params: '', params: '',
nodePosition: { nodePosition: {
x: 0, x: 0,
@ -49,7 +49,7 @@ const useMinderStore = defineStore('minder', {
this.event = { this.event = {
name, name,
params, params,
timestamp: Date.now(), eventId: getGenerateId(),
nodePosition: position, nodePosition: position,
nodeDom, nodeDom,
nodes, nodes,

View File

@ -17,7 +17,7 @@ export interface MinderNodePosition {
export interface MinderCustomEvent { export interface MinderCustomEvent {
name: MinderEventName; name: MinderEventName;
timestamp: number; eventId: string;
params?: any; params?: any;
nodePosition?: MinderNodePosition; nodePosition?: MinderNodePosition;
nodeDom?: HTMLElement; nodeDom?: HTMLElement;

View File

@ -580,6 +580,7 @@ export function deleteNodes<T>(
treeArr: TreeNode<T>[], treeArr: TreeNode<T>[],
targetKeys: (string | number)[], targetKeys: (string | number)[],
deleteCondition?: (node: TreeNode<T>, parent?: TreeNode<T>) => boolean, deleteCondition?: (node: TreeNode<T>, parent?: TreeNode<T>) => boolean,
deleteCallBack?: (node: TreeNode<T>) => void,
customKey = 'key' customKey = 'key'
): boolean { ): boolean {
let hasDeleted = false; let hasDeleted = false;
@ -589,6 +590,9 @@ export function deleteNodes<T>(
const node = tree[i]; const node = tree[i];
if (targetKeysSet.has(node[customKey])) { if (targetKeysSet.has(node[customKey])) {
if (deleteCondition && deleteCondition(node, node.parent)) { if (deleteCondition && deleteCondition(node, node.parent)) {
if (deleteCallBack) {
deleteCallBack(node);
}
tree.splice(i, 1); // 直接删除当前节点 tree.splice(i, 1); // 直接删除当前节点
hasDeleted = true; hasDeleted = true;
targetKeysSet.delete(node[customKey]); // 删除后从集合中移除 targetKeysSet.delete(node[customKey]); // 删除后从集合中移除

View File

@ -927,7 +927,8 @@
return item; return item;
}); });
if ( if (
(!props.disabledExceptParam || !props.disabledParamValue) && !props.disabledExceptParam &&
!props.disabledParamValue &&
hasNoIdItem && hasNoIdItem &&
!filterKeyValParams(arr, defaultLineData.value, !props.selectable).lastDataIsDefault && !filterKeyValParams(arr, defaultLineData.value, !props.selectable).lastDataIsDefault &&
!props.isTreeTable !props.isTreeTable
@ -935,7 +936,7 @@
addTableLine(arr.length - 1, false, true); addTableLine(arr.length - 1, false, true);
} }
} else { } else {
if (props.disabledExceptParam) return; if (props.disabledExceptParam || props.disabledParamValue) return;
const id = getGenerateId(); const id = getGenerateId();
paramsData.value = [ paramsData.value = [
{ {

View File

@ -282,6 +282,9 @@
scenario.value.steps, scenario.value.steps,
checkedKeys.value, checkedKeys.value,
(node) => !node.isQuoteScenarioStep, (node) => !node.isQuoteScenarioStep,
(node) => {
delete scenario.value.stepDetails[node.id];
},
'uniqueId' 'uniqueId'
); );
if (deleteResult) { if (deleteResult) {

View File

@ -990,6 +990,7 @@
maskClosable: false, maskClosable: false,
onBeforeOk: async () => { onBeforeOk: async () => {
deleteNode(steps.value, node.uniqueId, 'uniqueId'); deleteNode(steps.value, node.uniqueId, 'uniqueId');
delete stepDetails.value[node.id];
scenario.value.unSaved = true; scenario.value.unSaved = true;
}, },
hideCancel: false, hideCancel: false,

View File

@ -219,7 +219,7 @@
:module-id="props.activeFolder" :module-id="props.activeFolder"
:modules-count="props.modulesCount" :modules-count="props.modulesCount"
:module-name="props.moduleName" :module-name="props.moduleName"
@save="emitTableParams" @save="handleMinderSave"
/> />
<MsDrawer v-model:visible="visible" :width="480" :mask="false"> <MsDrawer v-model:visible="visible" :width="480" :mask="false">
{{ nodeData.text }} {{ nodeData.text }}
@ -390,7 +390,7 @@
}>(); }>();
const emit = defineEmits<{ const emit = defineEmits<{
(e: 'init', params: CaseModuleQueryParams): void; (e: 'init', params: CaseModuleQueryParams, refreshModule?: boolean): void;
(e: 'import', type: 'Excel' | 'Xmind'): void; (e: 'import', type: 'Excel' | 'Xmind'): void;
}>(); }>();
@ -894,14 +894,22 @@
}; };
} }
// //
async function emitTableParams() { async function emitTableParams(refreshModule = false) {
const tableParams = await initTableParams(); const tableParams = await initTableParams();
emit('init', { emit(
...tableParams, 'init',
current: propsRes.value.msPagination?.current, {
pageSize: propsRes.value.msPagination?.pageSize, ...tableParams,
filter: propsRes.value.filter, current: propsRes.value.msPagination?.current,
}); pageSize: propsRes.value.msPagination?.pageSize,
filter: propsRes.value.filter,
},
refreshModule
);
}
function handleMinderSave() {
emitTableParams(true);
} }
const tableSelected = ref<(string | number)[]>([]); const tableSelected = ref<(string | number)[]>([]);

View File

@ -285,7 +285,10 @@
/** /**
* 右侧表格数据刷新后若当前展示的是模块则刷新模块树的统计数量 * 右侧表格数据刷新后若当前展示的是模块则刷新模块树的统计数量
*/ */
function initModulesCount(params: TableQueryParams) { function initModulesCount(params: TableQueryParams, refreshModule = false) {
if (refreshModule) {
caseTreeRef.value.initModules();
}
featureCaseStore.getCaseModulesCount(params); featureCaseStore.getCaseModulesCount(params);
featureCaseStore.getRecycleModulesCount(params); featureCaseStore.getRecycleModulesCount(params);
tableFilterParams.value = { ...params }; tableFilterParams.value = { ...params };

View File

@ -102,7 +102,7 @@
</MsCard> </MsCard>
<!-- special-height的174: 上面卡片高度158 + mt的16 --> <!-- special-height的174: 上面卡片高度158 + mt的16 -->
<MsCard class="mt-[16px]" :special-height="174" simple has-breadcrumb no-content-padding> <MsCard class="mt-[16px]" :special-height="174" simple has-breadcrumb no-content-padding>
<Plan v-if="activeTab === 'plan'" :plan-id="planId" @refresh="initDetail" /> <Plan v-if="activeTab === 'plan'" :plan-id="planId" :status="detail.status || 'PREPARED'" @refresh="initDetail" />
<FeatureCase <FeatureCase
v-if="activeTab === 'featureCase'" v-if="activeTab === 'featureCase'"
ref="featureCaseRef" ref="featureCaseRef"

View File

@ -2,7 +2,7 @@
<div class="flex h-full flex-col p-[16px]"> <div class="flex h-full flex-col p-[16px]">
<MsNotRemind tip="testPlan.planTip" class="mb-[16px]" type="info" visited-key="testPlanTip" /> <MsNotRemind tip="testPlan.planTip" class="mb-[16px]" type="info" visited-key="testPlanTip" />
<div class="flex-1 overflow-hidden"> <div class="flex-1 overflow-hidden">
<MsTestPlanMinder :plan-id="props.planId" @save="emit('refresh')" /> <MsTestPlanMinder :plan-id="props.planId" :status="props.status" @save="emit('refresh')" />
</div> </div>
</div> </div>
</template> </template>
@ -13,6 +13,7 @@
const props = defineProps<{ const props = defineProps<{
planId: string; planId: string;
status: string;
}>(); }>();
const emit = defineEmits<{ const emit = defineEmits<{
(e: 'refresh'): void; (e: 'refresh'): void;