feat(脑图): 标签&优先级&添加交互规则
This commit is contained in:
parent
318b7fc950
commit
3209249045
|
@ -467,7 +467,7 @@
|
||||||
.arco-radio-button {
|
.arco-radio-button {
|
||||||
@apply bg-transparent;
|
@apply bg-transparent;
|
||||||
|
|
||||||
margin: 1px;
|
line-height: 20px;
|
||||||
}
|
}
|
||||||
.arco-radio-checked {
|
.arco-radio-checked {
|
||||||
@apply bg-white;
|
@apply bg-white;
|
||||||
|
|
|
@ -0,0 +1,313 @@
|
||||||
|
<template>
|
||||||
|
<MsMinderEditor
|
||||||
|
:tags="tags"
|
||||||
|
:import-json="props.importJson"
|
||||||
|
:replaceable-tags="replaceableTags"
|
||||||
|
:insert-node="insertNode"
|
||||||
|
:priority-disable-check="priorityDisableCheck"
|
||||||
|
:after-tag-edit="afterTagEdit"
|
||||||
|
single-tag
|
||||||
|
tag-enable
|
||||||
|
sequence-enable
|
||||||
|
@click="handleNodeClick"
|
||||||
|
>
|
||||||
|
</MsMinderEditor>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import MsMinderEditor from '@/components/pure/ms-minder-editor/minderEditor.vue';
|
||||||
|
import type { MinderJson, MinderJsonNode, MinderJsonNodeData } from '@/components/pure/ms-minder-editor/props';
|
||||||
|
|
||||||
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
import { getGenerateId } from '@/utils';
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
importJson: MinderJson;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const caseTag = t('common.case');
|
||||||
|
const moduleTag = t('common.module');
|
||||||
|
const topTags = [moduleTag, caseTag];
|
||||||
|
const descTags = [t('ms.minders.stepDesc'), t('ms.minders.textDesc')];
|
||||||
|
const tags = [...topTags, t('ms.minders.precondition'), ...descTags, t('ms.minders.stepExpect'), t('common.remark')];
|
||||||
|
const visible = ref<boolean>(false);
|
||||||
|
const nodeData = ref<any>({});
|
||||||
|
|
||||||
|
function handleNodeClick(data: any) {
|
||||||
|
if (data.resource && data.resource.includes(caseTag)) {
|
||||||
|
visible.value = true;
|
||||||
|
nodeData.value = data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已选中节点的可替换标签判断
|
||||||
|
* @param node 选中节点
|
||||||
|
*/
|
||||||
|
function replaceableTags(node: MinderJsonNode) {
|
||||||
|
if (node.data?.resource?.some((e) => topTags.includes(e))) {
|
||||||
|
// 选中节点属于顶级节点,可替换为除自身外的顶级标签
|
||||||
|
return !node.children || node.children.length === 0
|
||||||
|
? topTags.filter((tag) => !node.data?.resource?.includes(tag))
|
||||||
|
: [];
|
||||||
|
}
|
||||||
|
if (node.data?.resource?.some((e) => descTags.includes(e))) {
|
||||||
|
// 选中节点属于描述节点,可替换为除自身外的描述标签
|
||||||
|
return descTags.filter((tag) => !node.data?.resource?.includes(tag));
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
(!node.data?.resource || node.data?.resource?.length === 0) &&
|
||||||
|
(!node.parent?.data?.resource ||
|
||||||
|
node.parent?.data?.resource.length === 0 ||
|
||||||
|
node.parent?.data?.resource?.some((e) => topTags.includes(e)))
|
||||||
|
) {
|
||||||
|
// 选中节点无标签,且父节点为顶级节点,可替换为顶级标签
|
||||||
|
// 如果选中节点子级含有用例节点或模块节点,则不可将选中节点标记为用例
|
||||||
|
return node.children &&
|
||||||
|
(node.children.some((e) => e.data?.resource?.includes(caseTag)) ||
|
||||||
|
node.children.some((e) => e.data?.resource?.includes(moduleTag)))
|
||||||
|
? topTags.filter((e) => e !== caseTag)
|
||||||
|
: topTags;
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
function execInert(command: string, node?: MinderJsonNodeData) {
|
||||||
|
if (window.minder.queryCommandState(command) !== -1) {
|
||||||
|
window.minder.execCommand(command, node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插入前置条件
|
||||||
|
* @param node 目标节点
|
||||||
|
* @param type 插入类型
|
||||||
|
*/
|
||||||
|
function inertPrecondition(node: MinderJsonNode, type: string) {
|
||||||
|
const child: MinderJsonNode = {
|
||||||
|
parent: node,
|
||||||
|
data: {
|
||||||
|
id: getGenerateId(),
|
||||||
|
text: t('ms.minders.precondition'),
|
||||||
|
resource: [t('ms.minders.precondition')],
|
||||||
|
expandState: 'expand',
|
||||||
|
},
|
||||||
|
children: [],
|
||||||
|
};
|
||||||
|
const sibling = {
|
||||||
|
parent: child,
|
||||||
|
data: {
|
||||||
|
id: getGenerateId(),
|
||||||
|
text: '',
|
||||||
|
resource: [],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
execInert(type, child.data);
|
||||||
|
nextTick(() => {
|
||||||
|
execInert('AppendChildNode', sibling.data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插入备注
|
||||||
|
* @param node 目标节点
|
||||||
|
* @param type 插入类型
|
||||||
|
*/
|
||||||
|
function insetRemark(node: MinderJsonNode, type: string) {
|
||||||
|
const child = {
|
||||||
|
parent: node,
|
||||||
|
data: {
|
||||||
|
id: getGenerateId(),
|
||||||
|
text: t('common.remark'),
|
||||||
|
resource: [t('common.remark')],
|
||||||
|
},
|
||||||
|
children: [],
|
||||||
|
};
|
||||||
|
execInert(type, child.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// function insertTextDesc(node: MinderJsonNode, type: string) {
|
||||||
|
// const child = {
|
||||||
|
// parent: node,
|
||||||
|
// data: {
|
||||||
|
// id: getGenerateId(),
|
||||||
|
// text: t('ms.minders.textDesc'),
|
||||||
|
// resource: [t('ms.minders.textDesc')],
|
||||||
|
// },
|
||||||
|
// children: [],
|
||||||
|
// };
|
||||||
|
// const sibling = {
|
||||||
|
// parent: child,
|
||||||
|
// data: {
|
||||||
|
// id: getGenerateId(),
|
||||||
|
// text: t('ms.minders.stepExpect'),
|
||||||
|
// resource: [t('ms.minders.stepExpect')],
|
||||||
|
// },
|
||||||
|
// };
|
||||||
|
// execInert(type, {
|
||||||
|
// ...child,
|
||||||
|
// children: [sibling],
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插入步骤描述
|
||||||
|
* @param node 目标节点
|
||||||
|
* @param type 插入类型
|
||||||
|
*/
|
||||||
|
function insetStepDesc(node: MinderJsonNode, type: string) {
|
||||||
|
const child = {
|
||||||
|
parent: node,
|
||||||
|
data: {
|
||||||
|
id: getGenerateId(),
|
||||||
|
text: t('ms.minders.stepDesc'),
|
||||||
|
resource: [t('ms.minders.stepDesc')],
|
||||||
|
},
|
||||||
|
children: [],
|
||||||
|
};
|
||||||
|
const sibling = {
|
||||||
|
parent: child,
|
||||||
|
data: {
|
||||||
|
id: getGenerateId(),
|
||||||
|
text: t('ms.minders.stepExpect'),
|
||||||
|
resource: [t('ms.minders.stepExpect')],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
execInert(type, child.data);
|
||||||
|
nextTick(() => {
|
||||||
|
execInert('AppendChildNode', sibling.data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插入预期结果
|
||||||
|
* @param node 目标节点
|
||||||
|
* @param type 插入类型
|
||||||
|
*/
|
||||||
|
function insertExpect(node: MinderJsonNode, type: string) {
|
||||||
|
const child = {
|
||||||
|
parent: node,
|
||||||
|
data: {
|
||||||
|
id: getGenerateId(),
|
||||||
|
text: t('ms.minders.stepExpect'),
|
||||||
|
resource: [t('ms.minders.stepExpect')],
|
||||||
|
},
|
||||||
|
children: [],
|
||||||
|
};
|
||||||
|
execInert(type, child.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插入节点
|
||||||
|
* @param node 目标节点
|
||||||
|
* @param type 插入类型
|
||||||
|
*/
|
||||||
|
function insertNode(node: MinderJsonNode, type: string) {
|
||||||
|
switch (type) {
|
||||||
|
case 'AppendChildNode':
|
||||||
|
if (node.data?.resource?.includes(moduleTag)) {
|
||||||
|
execInert('AppendChildNode');
|
||||||
|
} else if (node.data?.resource?.includes(caseTag)) {
|
||||||
|
// 给用例插入子节点
|
||||||
|
if (!node.children || node.children.length === 0) {
|
||||||
|
// 当前用例还没有子节点,默认添加一个前置条件
|
||||||
|
inertPrecondition(node, type);
|
||||||
|
} else if (node.children.length > 0) {
|
||||||
|
// 当前用例有子节点
|
||||||
|
let hasPreCondition = false;
|
||||||
|
let hasTextDesc = false;
|
||||||
|
let hasRemark = false;
|
||||||
|
for (let i = 0; i < node.children.length; i++) {
|
||||||
|
const child = node.children[i];
|
||||||
|
if (child.data?.resource?.includes(t('ms.minders.precondition'))) {
|
||||||
|
hasPreCondition = true;
|
||||||
|
} else if (child.data?.resource?.includes(t('ms.minders.textDesc'))) {
|
||||||
|
hasTextDesc = true;
|
||||||
|
} else if (child.data?.resource?.includes(t('common.remark'))) {
|
||||||
|
hasRemark = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!hasPreCondition) {
|
||||||
|
// 没有前置条件,则默认添加一个前置条件
|
||||||
|
inertPrecondition(node, type);
|
||||||
|
} else if (!hasRemark) {
|
||||||
|
// 没有备注,则默认添加一个备注
|
||||||
|
insetRemark(node, type);
|
||||||
|
} else if (!hasTextDesc) {
|
||||||
|
// 没有文本描述,则默认添加一个步骤描述
|
||||||
|
insetStepDesc(node, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (
|
||||||
|
(node.data?.resource?.includes(t('ms.minders.stepDesc')) ||
|
||||||
|
node.data?.resource?.includes(t('ms.minders.textDesc'))) &&
|
||||||
|
(!node.children || node.children.length === 0)
|
||||||
|
) {
|
||||||
|
// 当前节点是步骤描述或文本描述,且没有子节点,则默认添加一个预期结果
|
||||||
|
insertExpect(node, 'AppendChildNode');
|
||||||
|
} else if (node.data?.resource?.includes(t('ms.minders.precondition'))) {
|
||||||
|
// 当前节点是前置条件,则默认添加一个文本节点
|
||||||
|
execInert('AppendChildNode');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'AppendParentNode':
|
||||||
|
execInert('AppendParentNode');
|
||||||
|
break;
|
||||||
|
case 'AppendSiblingNode':
|
||||||
|
if (node.parent?.data?.resource?.includes(caseTag) && node.parent?.children) {
|
||||||
|
// 当前节点的父节点是用例
|
||||||
|
let hasPreCondition = false;
|
||||||
|
let hasTextDesc = false;
|
||||||
|
let hasRemark = false;
|
||||||
|
for (let i = 0; i < node.parent.children.length; i++) {
|
||||||
|
const sibling = node.parent.children[i];
|
||||||
|
if (sibling.data?.resource?.includes(t('ms.minders.precondition'))) {
|
||||||
|
hasPreCondition = true;
|
||||||
|
} else if (sibling.data?.resource?.includes(t('common.remark'))) {
|
||||||
|
hasRemark = true;
|
||||||
|
} else if (sibling.data?.resource?.includes(t('ms.minders.textDesc'))) {
|
||||||
|
hasTextDesc = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!hasPreCondition) {
|
||||||
|
// 没有前置条件,则默认添加一个前置条件
|
||||||
|
inertPrecondition(node, type);
|
||||||
|
} else if (!hasRemark) {
|
||||||
|
// 没有备注,则默认添加一个备注
|
||||||
|
insetRemark(node, type);
|
||||||
|
} else if (!hasTextDesc) {
|
||||||
|
// 没有文本描述,则默认添加一个步骤描述
|
||||||
|
insetStepDesc(node, type);
|
||||||
|
}
|
||||||
|
} else if (node.parent?.data?.resource?.includes(moduleTag) || !node.parent?.data?.resource) {
|
||||||
|
// 当前节点的父节点是模块或没有标签,则默认添加一个文本节点
|
||||||
|
execInert('AppendSiblingNode');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function priorityDisableCheck(node: MinderJsonNode) {
|
||||||
|
if (node.data?.resource?.includes(caseTag)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 标签编辑后,如果将标签修改为模块,则删除已添加的优先级
|
||||||
|
* @param node 选中节点
|
||||||
|
* @param tag 更改后的标签
|
||||||
|
*/
|
||||||
|
function afterTagEdit(node: MinderJsonNode, tag: string) {
|
||||||
|
if (tag === moduleTag && node.data) {
|
||||||
|
window.minder.execCommand('priority');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped></style>
|
|
@ -0,0 +1,15 @@
|
||||||
|
<template>
|
||||||
|
<FeatureCaseMinder :import-json="props.importJson" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { MinderJson } from '@/components/pure/ms-minder-editor/props';
|
||||||
|
import FeatureCaseMinder from '@/components/business/ms-minders/featureCaseMinder.vue';
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
minderType: 'FeatureCase';
|
||||||
|
importJson: MinderJson;
|
||||||
|
}>();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped></style>
|
|
@ -0,0 +1,6 @@
|
||||||
|
export default {
|
||||||
|
'ms.minders.precondition': 'Precondition',
|
||||||
|
'ms.minders.stepDesc': 'Step Description',
|
||||||
|
'ms.minders.stepExpect': 'Expected Result',
|
||||||
|
'ms.minders.textDesc': 'Text Description',
|
||||||
|
};
|
|
@ -0,0 +1,6 @@
|
||||||
|
export default {
|
||||||
|
'ms.minders.precondition': '前置条件',
|
||||||
|
'ms.minders.stepDesc': '步骤描述',
|
||||||
|
'ms.minders.stepExpect': '预期结果',
|
||||||
|
'ms.minders.textDesc': '文本描述',
|
||||||
|
};
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="flex flex-row items-center justify-between">
|
<div class="flex flex-row items-center justify-between">
|
||||||
<slot name="left"></slot>
|
<slot name="left"></slot>
|
||||||
<div class="flex flex-row gap-[8px]">
|
<div class="flex flex-row gap-[12px]">
|
||||||
<a-input-search
|
<a-input-search
|
||||||
v-model:modelValue="innerKeyword"
|
v-model:modelValue="innerKeyword"
|
||||||
size="small"
|
size="small"
|
||||||
|
|
|
@ -1,7 +1,22 @@
|
||||||
<template>
|
<template>
|
||||||
<header>
|
<!-- <div class="ms-minder-editor-header">
|
||||||
|
<a-tooltip v-for="item of props.iconButtons" :key="item.eventTag" :content="t(item.tooltip)">
|
||||||
|
<MsButton type="icon" class="ms-minder-editor-header-icon-button" @click="emit('click', item.eventTag)">
|
||||||
|
<MsIcon :type="item.icon" class="text-[var(--color-text-4)]" />
|
||||||
|
</MsButton>
|
||||||
|
</a-tooltip>
|
||||||
|
<a-divider v-if="props.iconButtons?.length" direction="vertical" :margin="8"></a-divider>
|
||||||
|
<a-tooltip :content="isFullScreen ? t('common.offFullScreen') : t('common.fullScreen')">
|
||||||
|
<MsButton v-if="isFullScreen" type="icon" class="ms-minder-editor-header-icon-button" @click="toggleFullScreen">
|
||||||
|
<MsIcon type="icon-icon_off_screen" class="text-[var(--color-text-4)]" />
|
||||||
|
</MsButton>
|
||||||
|
<MsButton v-else type="icon" class="ms-minder-editor-header-icon-button" @click="toggleFullScreen">
|
||||||
|
<MsIcon type="icon-icon_full_screen_one" class="text-[var(--color-text-4)]" />
|
||||||
|
</MsButton>
|
||||||
|
</a-tooltip>
|
||||||
|
</div> -->
|
||||||
<div class="mind-tab-panel">
|
<div class="mind-tab-panel">
|
||||||
<edit-menu
|
<editMenu
|
||||||
:minder="minder"
|
:minder="minder"
|
||||||
:move-enable="props.moveEnable"
|
:move-enable="props.moveEnable"
|
||||||
:move-confirm="props.moveConfirm"
|
:move-confirm="props.moveConfirm"
|
||||||
|
@ -17,18 +32,24 @@
|
||||||
:tags="props.tags"
|
:tags="props.tags"
|
||||||
:distinct-tags="props.distinctTags"
|
:distinct-tags="props.distinctTags"
|
||||||
:del-confirm="props.delConfirm"
|
:del-confirm="props.delConfirm"
|
||||||
|
:replaceable-tags="props.replaceableTags"
|
||||||
|
:single-tag="props.singleTag"
|
||||||
|
:insert-node="props.insertNode"
|
||||||
|
:after-tag-edit="props.afterTagEdit"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" name="headerVue" setup>
|
<script lang="ts" setup>
|
||||||
|
// import MsButton from '@/components/pure/ms-button/index.vue';
|
||||||
|
// import MsIcon from '@/components/pure/ms-icon-font/index.vue';
|
||||||
import editMenu from '../menu/edit/editMenu.vue';
|
import editMenu from '../menu/edit/editMenu.vue';
|
||||||
|
|
||||||
import { delProps, editMenuProps, moleProps, priorityProps, tagProps, viewMenuProps } from '../props';
|
import { delProps, editMenuProps, insertProps, moleProps, priorityProps, tagProps, viewMenuProps } from '../props';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
...editMenuProps,
|
...editMenuProps,
|
||||||
|
...insertProps,
|
||||||
...moleProps,
|
...moleProps,
|
||||||
...priorityProps,
|
...priorityProps,
|
||||||
...tagProps,
|
...tagProps,
|
||||||
|
@ -36,6 +57,21 @@
|
||||||
...viewMenuProps,
|
...viewMenuProps,
|
||||||
minder: null,
|
minder: null,
|
||||||
});
|
});
|
||||||
|
// import useFullScreen from '@/hooks/useFullScreen';
|
||||||
|
// import { useI18n } from '@/hooks/useI18n';
|
||||||
|
|
||||||
|
// import { headerProps } from '../props';
|
||||||
|
|
||||||
|
// const props = defineProps({
|
||||||
|
// ...headerProps,
|
||||||
|
// });
|
||||||
|
// const emit = defineEmits<{
|
||||||
|
// (e: 'click', eventTag: string): void;
|
||||||
|
// }>();
|
||||||
|
|
||||||
|
// const { t } = useI18n();
|
||||||
|
|
||||||
|
// const { toggleFullScreen, isFullScreen } = useFullScreen(document.querySelector('.ms-minder-editor-container'));
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
|
@ -46,4 +82,21 @@
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// .ms-minder-editor-header {
|
||||||
|
// @apply absolute z-10 flex items-center bg-white;
|
||||||
|
|
||||||
|
// top: 24px;
|
||||||
|
// right: 0;
|
||||||
|
// padding: 4px 8px;
|
||||||
|
// border-radius: var(--border-radius-small);
|
||||||
|
// box-shadow: 0 4px 10px -1px rgb(100 100 102 / 15%);
|
||||||
|
// .ms-minder-editor-header-icon-button {
|
||||||
|
// &:hover {
|
||||||
|
// background-color: rgb(var(--primary-1)) !important;
|
||||||
|
// .arco-icon {
|
||||||
|
// color: rgb(var(--primary-4)) !important;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div ref="mec" class="minder-container" :style="{ height: `${props.height}px` }">
|
<div ref="mec" class="minder-container">
|
||||||
<a-button type="primary" :disabled="props.disabled" class="save-btn bottom-[30px] right-[30px]" @click="save">
|
<a-button type="primary" :disabled="props.disabled" class="save-btn bottom-[30px] right-[30px]" @click="save">
|
||||||
{{ t('minder.main.main.save') }}
|
{{ t('minder.main.main.save') }}
|
||||||
</a-button>
|
</a-button>
|
||||||
|
@ -92,13 +92,13 @@
|
||||||
import useMinderStore from '@/store/modules/components/minder-editor';
|
import useMinderStore from '@/store/modules/components/minder-editor';
|
||||||
import { findNodePathByKey } from '@/utils';
|
import { findNodePathByKey } from '@/utils';
|
||||||
|
|
||||||
import { editMenuProps, mainEditorProps, priorityProps, tagProps } from '../props';
|
import { editMenuProps, insertProps, mainEditorProps, MinderJsonNode, priorityProps, tagProps } from '../props';
|
||||||
import Editor from '../script/editor';
|
import Editor from '../script/editor';
|
||||||
import { markChangeNode, markDeleteNode } from '../script/tool/utils';
|
import { markChangeNode, markDeleteNode } from '../script/tool/utils';
|
||||||
import type { Ref } from 'vue';
|
import type { Ref } from 'vue';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const props = defineProps({ ...editMenuProps, ...mainEditorProps, ...tagProps, ...priorityProps });
|
const props = defineProps({ ...editMenuProps, ...insertProps, ...mainEditorProps, ...tagProps, ...priorityProps });
|
||||||
|
|
||||||
const emit = defineEmits({
|
const emit = defineEmits({
|
||||||
afterMount: () => ({}),
|
afterMount: () => ({}),
|
||||||
|
@ -246,6 +246,17 @@
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
function execInsertCommand(command: string) {
|
||||||
|
const node: MinderJsonNode = window.minder.getSelectedNode();
|
||||||
|
if (props.insertNode) {
|
||||||
|
props.insertNode(node, command);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (window.minder.queryCommandState(command) !== -1) {
|
||||||
|
window.minder.execCommand(command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function handleMinderMenuSelect(val: string | number | Record<string, any> | undefined) {
|
function handleMinderMenuSelect(val: string | number | Record<string, any> | undefined) {
|
||||||
const selectedNode = window.minder.getSelectedNode();
|
const selectedNode = window.minder.getSelectedNode();
|
||||||
switch (val) {
|
switch (val) {
|
||||||
|
@ -257,13 +268,13 @@
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'insetParent':
|
case 'insetParent':
|
||||||
window.minder.execCommand('AppendParentNode');
|
execInsertCommand('AppendParentNode');
|
||||||
break;
|
break;
|
||||||
case 'insetSon':
|
case 'insetSon':
|
||||||
window.minder.execCommand('AppendChildNode');
|
execInsertCommand('AppendChildNode');
|
||||||
break;
|
break;
|
||||||
case 'insetBrother':
|
case 'insetBrother':
|
||||||
window.minder.execCommand('AppendSiblingNode');
|
execInsertCommand('AppendSiblingNode');
|
||||||
break;
|
break;
|
||||||
case 'copy':
|
case 'copy':
|
||||||
window.minder.execCommand('Copy');
|
window.minder.execCommand('Copy');
|
||||||
|
@ -292,7 +303,9 @@
|
||||||
@apply !absolute;
|
@apply !absolute;
|
||||||
}
|
}
|
||||||
.minder-container {
|
.minder-container {
|
||||||
@apply relative;
|
@apply relative !bg-white;
|
||||||
|
|
||||||
|
height: calc(100% - 60px);
|
||||||
}
|
}
|
||||||
.minder-dropdown {
|
.minder-dropdown {
|
||||||
.arco-dropdown-list-wrapper {
|
.arco-dropdown-list-wrapper {
|
||||||
|
|
|
@ -18,18 +18,19 @@
|
||||||
{{ t('minder.menu.expand.folding') }}
|
{{ t('minder.menu.expand.folding') }}
|
||||||
</div>
|
</div>
|
||||||
<move-box :move-enable="props.moveEnable" :move-confirm="props.moveConfirm" />
|
<move-box :move-enable="props.moveEnable" :move-confirm="props.moveConfirm" />
|
||||||
<insert-box />
|
<insert-box :insert-node="props.insertNode" />
|
||||||
<edit-del :del-confirm="props.delConfirm" />
|
<edit-del :del-confirm="props.delConfirm" />
|
||||||
</div>
|
</div>
|
||||||
<div class="menu-group">
|
|
||||||
<tag-box
|
<tag-box
|
||||||
v-if="props.tagEnable"
|
v-if="props.tagEnable"
|
||||||
:tags="props.tags"
|
:tags="props.tags"
|
||||||
:tag-disable-check="props.tagDisableCheck"
|
:tag-disable-check="props.tagDisableCheck"
|
||||||
:tag-edit-check="props.tagEditCheck"
|
:tag-edit-check="props.tagEditCheck"
|
||||||
:distinct-tags="props.distinctTags"
|
:distinct-tags="props.distinctTags"
|
||||||
|
:replaceable-tags="props.replaceableTags"
|
||||||
|
:single-tag="props.singleTag"
|
||||||
|
:after-tag-edit="props.afterTagEdit"
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
<div class="menu-group">
|
<div class="menu-group">
|
||||||
<sequence-box
|
<sequence-box
|
||||||
v-if="props.sequenceEnable"
|
v-if="props.sequenceEnable"
|
||||||
|
@ -55,10 +56,11 @@
|
||||||
|
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
|
||||||
import { delProps, editMenuProps, moleProps, priorityProps, tagProps, viewMenuProps } from '../../props';
|
import { delProps, editMenuProps, insertProps, moleProps, priorityProps, tagProps, viewMenuProps } from '../../props';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
...editMenuProps,
|
...editMenuProps,
|
||||||
|
...insertProps,
|
||||||
...priorityProps,
|
...priorityProps,
|
||||||
...tagProps,
|
...tagProps,
|
||||||
...delProps,
|
...delProps,
|
||||||
|
|
|
@ -26,8 +26,13 @@
|
||||||
|
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
|
||||||
|
import { insertProps, MinderJsonNode } from '../../props';
|
||||||
import { isDisableNode } from '../../script/tool/utils';
|
import { isDisableNode } from '../../script/tool/utils';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
...insertProps,
|
||||||
|
});
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const minder = ref<any>({});
|
const minder = ref<any>({});
|
||||||
|
@ -58,6 +63,11 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
function execCommand(command: string) {
|
function execCommand(command: string) {
|
||||||
|
const node: MinderJsonNode = minder.value.getSelectedNode();
|
||||||
|
if (props.insertNode) {
|
||||||
|
props.insertNode(node, command);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (minder.value.queryCommandState(command) !== -1) {
|
if (minder.value.queryCommandState(command) !== -1) {
|
||||||
minder.value.execCommand(command);
|
minder.value.execCommand(command);
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,7 @@
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (props.priorityDisableCheck) {
|
if (props.priorityDisableCheck) {
|
||||||
return props.priorityDisableCheck();
|
return props.priorityDisableCheck(node);
|
||||||
}
|
}
|
||||||
return !!minder.queryCommandState && minder.queryCommandState('priority') === -1;
|
return !!minder.queryCommandState && minder.queryCommandState('priority') === -1;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="flex items-center">
|
<div v-if="tagList.length > 0" class="menu-group flex items-center">
|
||||||
<a-tag
|
<a-tag
|
||||||
v-for="item in props.tags"
|
v-for="item in tagList"
|
||||||
:key="item"
|
:key="item"
|
||||||
:color="getResourceColor(item)"
|
:color="getResourceColor(item)"
|
||||||
:class="commandDisabled ? 'disabledTag' : ''"
|
:class="commandDisabled ? 'disabledTag' : ''"
|
||||||
|
@ -15,7 +15,7 @@
|
||||||
<script lang="ts" name="TagBox" setup>
|
<script lang="ts" name="TagBox" setup>
|
||||||
import { nextTick, onMounted, reactive, ref } from 'vue';
|
import { nextTick, onMounted, reactive, ref } from 'vue';
|
||||||
|
|
||||||
import { tagProps } from '../../props';
|
import { MinderJsonNode, tagProps } from '../../props';
|
||||||
import { isDisableNode, isTagEnable } from '../../script/tool/utils';
|
import { isDisableNode, isTagEnable } from '../../script/tool/utils';
|
||||||
|
|
||||||
const props = defineProps(tagProps);
|
const props = defineProps(tagProps);
|
||||||
|
@ -34,11 +34,21 @@
|
||||||
return !!minder.queryCommandState && minder.queryCommandState('resource') === -1;
|
return !!minder.queryCommandState && minder.queryCommandState('resource') === -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const tagList = ref(props.tags);
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
minder = window.minder;
|
minder = window.minder;
|
||||||
minder.on('selectionchange', () => {
|
minder.on('selectionchange', () => {
|
||||||
commandDisabled.value = isDisable();
|
commandDisabled.value = isDisable();
|
||||||
|
const node: MinderJsonNode = minder.getSelectedNode();
|
||||||
|
if (commandDisabled.value) {
|
||||||
|
tagList.value = [];
|
||||||
|
} else if (props.replaceableTags) {
|
||||||
|
tagList.value = props.replaceableTags(node);
|
||||||
|
} else {
|
||||||
|
tagList.value = [];
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -54,7 +64,8 @@
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (props.tagEditCheck) {
|
if (props.tagEditCheck) {
|
||||||
if (!props.tagEditCheck(resourceName)) {
|
const node: MinderJsonNode = minder.getSelectedNode();
|
||||||
|
if (!props.tagEditCheck(node, resourceName)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,6 +73,9 @@
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const origin = window.minder.queryCommandValue('resource');
|
const origin = window.minder.queryCommandValue('resource');
|
||||||
|
if (props.singleTag) {
|
||||||
|
origin.splice(0, origin.length, resourceName);
|
||||||
|
} else {
|
||||||
const index = origin.indexOf(resourceName);
|
const index = origin.indexOf(resourceName);
|
||||||
// 先删除排他的标签
|
// 先删除排他的标签
|
||||||
if (props.distinctTags.indexOf(resourceName) > -1) {
|
if (props.distinctTags.indexOf(resourceName) > -1) {
|
||||||
|
@ -77,7 +91,15 @@
|
||||||
} else {
|
} else {
|
||||||
origin.push(resourceName);
|
origin.push(resourceName);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
window.minder.execCommand('resource', origin);
|
window.minder.execCommand('resource', origin);
|
||||||
|
const node: MinderJsonNode = minder.getSelectedNode();
|
||||||
|
if (props.replaceableTags) {
|
||||||
|
tagList.value = props.replaceableTags(node);
|
||||||
|
}
|
||||||
|
if (props.afterTagEdit) {
|
||||||
|
props.afterTagEdit(node, resourceName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="main-container">
|
<div class="ms-minder-editor-container">
|
||||||
<header-menu
|
<minderHeader
|
||||||
:sequence-enable="props.sequenceEnable"
|
:sequence-enable="props.sequenceEnable"
|
||||||
:tag-enable="props.tagEnable"
|
:tag-enable="props.tagEnable"
|
||||||
:progress-enable="props.progressEnable"
|
:progress-enable="props.progressEnable"
|
||||||
|
@ -20,9 +20,13 @@
|
||||||
:mold-enable="props.moldEnable"
|
:mold-enable="props.moldEnable"
|
||||||
:font-enable="props.fontEnable"
|
:font-enable="props.fontEnable"
|
||||||
:style-enable="props.styleEnable"
|
:style-enable="props.styleEnable"
|
||||||
|
:replaceable-tags="props.replaceableTags"
|
||||||
|
:single-tag="props.singleTag"
|
||||||
|
:insert-node="props.insertNode"
|
||||||
|
:after-tag-edit="props.afterTagEdit"
|
||||||
@mold-change="handleMoldChange"
|
@mold-change="handleMoldChange"
|
||||||
/>
|
/>
|
||||||
<main-editor
|
<mainEditor
|
||||||
:disabled="props.disabled"
|
:disabled="props.disabled"
|
||||||
:sequence-enable="props.sequenceEnable"
|
:sequence-enable="props.sequenceEnable"
|
||||||
:tag-enable="props.tagEnable"
|
:tag-enable="props.tagEnable"
|
||||||
|
@ -38,6 +42,7 @@
|
||||||
:priority-count="props.priorityCount"
|
:priority-count="props.priorityCount"
|
||||||
:priority-prefix="props.priorityPrefix"
|
:priority-prefix="props.priorityPrefix"
|
||||||
:priority-start-with-zero="props.priorityStartWithZero"
|
:priority-start-with-zero="props.priorityStartWithZero"
|
||||||
|
:insert-node="props.insertNode"
|
||||||
@after-mount="emit('afterMount')"
|
@after-mount="emit('afterMount')"
|
||||||
@save="save"
|
@save="save"
|
||||||
@enter-node="handleEnterNode"
|
@enter-node="handleEnterNode"
|
||||||
|
@ -48,10 +53,20 @@
|
||||||
<script lang="ts" name="minderEditor" setup>
|
<script lang="ts" name="minderEditor" setup>
|
||||||
import { onMounted } from 'vue';
|
import { onMounted } from 'vue';
|
||||||
|
|
||||||
import headerMenu from './main/header.vue';
|
import minderHeader from './main/header.vue';
|
||||||
import mainEditor from './main/mainEditor.vue';
|
import mainEditor from './main/mainEditor.vue';
|
||||||
|
|
||||||
import { delProps, editMenuProps, mainEditorProps, moleProps, priorityProps, tagProps, viewMenuProps } from './props';
|
import {
|
||||||
|
delProps,
|
||||||
|
editMenuProps,
|
||||||
|
headerProps,
|
||||||
|
insertProps,
|
||||||
|
mainEditorProps,
|
||||||
|
moleProps,
|
||||||
|
priorityProps,
|
||||||
|
tagProps,
|
||||||
|
viewMenuProps,
|
||||||
|
} from './props';
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'moldChange', data: number): void;
|
(e: 'moldChange', data: number): void;
|
||||||
|
@ -62,6 +77,8 @@
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
...headerProps,
|
||||||
|
...insertProps,
|
||||||
...editMenuProps,
|
...editMenuProps,
|
||||||
...mainEditorProps,
|
...mainEditorProps,
|
||||||
...moleProps,
|
...moleProps,
|
||||||
|
@ -103,3 +120,9 @@
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.ms-minder-editor-container {
|
||||||
|
@apply relative h-full;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -2,9 +2,35 @@
|
||||||
* Api 列表
|
* Api 列表
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import type { PropType } from 'vue';
|
||||||
|
|
||||||
|
export interface MinderIconButtonItem {
|
||||||
|
icon: string;
|
||||||
|
tooltip: string;
|
||||||
|
eventTag: string;
|
||||||
|
}
|
||||||
|
export interface MinderJsonNodeData {
|
||||||
|
id: string;
|
||||||
|
text: string;
|
||||||
|
resource?: string[];
|
||||||
|
expandState?: string;
|
||||||
|
priority?: number;
|
||||||
|
}
|
||||||
|
export interface MinderJsonNode {
|
||||||
|
parent?: MinderJsonNode;
|
||||||
|
data?: MinderJsonNodeData;
|
||||||
|
children?: MinderJsonNode[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MinderJson {
|
||||||
|
root: MinderJsonNode;
|
||||||
|
template: string;
|
||||||
|
treePath: Record<string, MinderJsonNode>[];
|
||||||
|
}
|
||||||
|
|
||||||
export const mainEditorProps = {
|
export const mainEditorProps = {
|
||||||
importJson: {
|
importJson: {
|
||||||
type: Object,
|
type: Object as PropType<MinderJson>,
|
||||||
default() {
|
default() {
|
||||||
return {
|
return {
|
||||||
root: {},
|
root: {},
|
||||||
|
@ -20,6 +46,12 @@ export const mainEditorProps = {
|
||||||
disabled: Boolean,
|
disabled: Boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const headerProps = {
|
||||||
|
iconButtons: {
|
||||||
|
type: [] as PropType<MinderIconButtonItem[]>,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
export const priorityProps = {
|
export const priorityProps = {
|
||||||
priorityCount: {
|
priorityCount: {
|
||||||
type: Number,
|
type: Number,
|
||||||
|
@ -39,27 +71,45 @@ export const priorityProps = {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'P',
|
default: 'P',
|
||||||
},
|
},
|
||||||
priorityDisableCheck: Function,
|
priorityDisableCheck: Function as PropType<(node: MinderJsonNode) => boolean>,
|
||||||
operators: [],
|
operators: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export interface MinderReplaceTag {
|
||||||
|
tags: string[];
|
||||||
|
condition: (node: MinderJsonNode, tags: string[]) => boolean;
|
||||||
|
}
|
||||||
export const tagProps = {
|
export const tagProps = {
|
||||||
tags: {
|
tags: {
|
||||||
// 自定义标签
|
// 自定义标签
|
||||||
type: Array<string>,
|
type: Array<string>,
|
||||||
default() {
|
default() {
|
||||||
return [] as string[];
|
return [];
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
distinctTags: {
|
distinctTags: {
|
||||||
// 个别标签二选一
|
// 个别标签二选一
|
||||||
type: Array<string>,
|
type: Array<string>,
|
||||||
default() {
|
default() {
|
||||||
return [] as string[];
|
return [];
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
singleTag: {
|
||||||
|
// 单标签
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
replaceableTags: Function as PropType<(node: MinderJsonNode) => string[]>,
|
||||||
tagDisableCheck: Function,
|
tagDisableCheck: Function,
|
||||||
tagEditCheck: Function,
|
tagEditCheck: Function as PropType<(node: MinderJsonNode, tag: string) => boolean>,
|
||||||
|
afterTagEdit: Function as PropType<(node: MinderJsonNode, tag: string) => void>,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const insertProps = {
|
||||||
|
insertNode: {
|
||||||
|
type: Function as PropType<(node: MinderJsonNode, type: string) => void>,
|
||||||
|
default: undefined,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const editMenuProps = {
|
export const editMenuProps = {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
@import 'dropdown-list.less';
|
@import 'dropdown-list.less';
|
||||||
.mind-tab-panel {
|
.mind-tab-panel {
|
||||||
@apply h-full w-full;
|
@apply w-full;
|
||||||
.menu-container {
|
.menu-container {
|
||||||
@apply flex;
|
@apply flex;
|
||||||
|
|
||||||
|
|
|
@ -754,6 +754,9 @@
|
||||||
.arco-table-td-content {
|
.arco-table-td-content {
|
||||||
@apply justify-center;
|
@apply justify-center;
|
||||||
}
|
}
|
||||||
|
.arco-table-cell {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
:deep(.ms-table-select-all) {
|
:deep(.ms-table-select-all) {
|
||||||
.dropdown-icon {
|
.dropdown-icon {
|
||||||
|
|
|
@ -173,4 +173,6 @@ export default {
|
||||||
'common.fakeError': 'Fake error',
|
'common.fakeError': 'Fake error',
|
||||||
'common.belongModule': 'Belong module',
|
'common.belongModule': 'Belong module',
|
||||||
'common.moreSetting': 'More settings',
|
'common.moreSetting': 'More settings',
|
||||||
|
'common.remark': 'Remark',
|
||||||
|
'common.case': 'Case',
|
||||||
};
|
};
|
||||||
|
|
|
@ -176,4 +176,6 @@ export default {
|
||||||
'common.executionResult': '执行结果',
|
'common.executionResult': '执行结果',
|
||||||
'common.detail': '详情',
|
'common.detail': '详情',
|
||||||
'common.baseInfo': '基本信息',
|
'common.baseInfo': '基本信息',
|
||||||
|
'common.remark': '备注',
|
||||||
|
'common.case': '用例',
|
||||||
};
|
};
|
||||||
|
|
|
@ -252,7 +252,7 @@
|
||||||
JSONPath({
|
JSONPath({
|
||||||
json: parseJson.value,
|
json: parseJson.value,
|
||||||
path: expressionForm.value.expression,
|
path: expressionForm.value.expression,
|
||||||
})?.map((e: any) => JSON.stringify(e).replace(/"Number\(([^)]+)\)"|Number\(([^)]+)\)/g, '$1$2')) || [];
|
})?.map((e: any) => JSON.stringify(e).replace(/Number\(([^)]+)\)|Number\(([^)]+)\)/g, '$1$2')) || [];
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
matchResult.value = JSONPath({ json: props.response || '', path: expressionForm.value.expression }) || [];
|
matchResult.value = JSONPath({ json: props.response || '', path: expressionForm.value.expression }) || [];
|
||||||
}
|
}
|
||||||
|
|
|
@ -184,8 +184,6 @@
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
width: 150,
|
width: 150,
|
||||||
titleSlotName: 'typeTitle',
|
|
||||||
typeTitleTooltip: t('apiScenario.params.typeTooltip'),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'apiScenario.params.paramValue',
|
title: 'apiScenario.params.paramValue',
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
<!-- eslint-disable prefer-destructuring -->
|
<!-- eslint-disable prefer-destructuring -->
|
||||||
<template>
|
<template>
|
||||||
|
<div class="h-full">
|
||||||
<!-- 用例表开始 -->
|
<!-- 用例表开始 -->
|
||||||
|
<template v-if="showType === 'list'">
|
||||||
<MsAdvanceFilter
|
<MsAdvanceFilter
|
||||||
v-model:keyword="keyword"
|
v-model:keyword="keyword"
|
||||||
:filter-config-list="filterConfigList"
|
:filter-config-list="filterConfigList"
|
||||||
|
@ -28,15 +30,17 @@
|
||||||
</a-popover>
|
</a-popover>
|
||||||
</template>
|
</template>
|
||||||
<template #right>
|
<template #right>
|
||||||
<!-- TODO 暂时先不展示了 -->
|
<a-radio-group v-model:model-value="showType" type="button" size="small" class="list-show-type">
|
||||||
<!-- <a-radio-group v-model:model-value="showType" type="button" class="file-show-type">
|
<a-radio value="list" class="show-type-icon !m-[2px]">
|
||||||
<a-radio value="list" class="show-type-icon p-[2px]"><MsIcon type="icon-icon_view-list_outlined" /></a-radio>
|
<MsIcon :size="14" type="icon-icon_view-list_outlined" />
|
||||||
<a-radio value="xMind" class="show-type-icon p-[2px]"><MsIcon type="icon-icon_mindnote_outlined" /></a-radio>
|
</a-radio>
|
||||||
</a-radio-group> -->
|
<a-radio value="xMind" class="show-type-icon !m-[2px]">
|
||||||
|
<MsIcon :size="14" type="icon-icon_mindnote_outlined" />
|
||||||
|
</a-radio>
|
||||||
|
</a-radio-group>
|
||||||
</template>
|
</template>
|
||||||
</MsAdvanceFilter>
|
</MsAdvanceFilter>
|
||||||
<ms-base-table
|
<ms-base-table
|
||||||
v-if="showType === 'list'"
|
|
||||||
v-bind="propsRes"
|
v-bind="propsRes"
|
||||||
ref="tableRef"
|
ref="tableRef"
|
||||||
filter-icon-align-left
|
filter-icon-align-left
|
||||||
|
@ -50,7 +54,9 @@
|
||||||
@cell-click="handleCellClick"
|
@cell-click="handleCellClick"
|
||||||
>
|
>
|
||||||
<template #num="{ record }">
|
<template #num="{ record }">
|
||||||
<span type="text" class="one-line-text cursor-pointer px-0 text-[rgb(var(--primary-5))]">{{ record.num }}</span>
|
<span type="text" class="one-line-text cursor-pointer px-0 text-[rgb(var(--primary-5))]">{{
|
||||||
|
record.num
|
||||||
|
}}</span>
|
||||||
</template>
|
</template>
|
||||||
<template #name="{ record }">
|
<template #name="{ record }">
|
||||||
<div class="one-line-text">{{ characterLimit(record.name) }}</div>
|
<div class="one-line-text">{{ characterLimit(record.name) }}</div>
|
||||||
|
@ -80,14 +86,6 @@
|
||||||
<ExecuteStatusTag :execute-result="filterContent.value" />
|
<ExecuteStatusTag :execute-result="filterContent.value" />
|
||||||
</template>
|
</template>
|
||||||
<!-- 评审结果 -->
|
<!-- 评审结果 -->
|
||||||
<template #[FilterSlotNameEnum.CASE_MANAGEMENT_REVIEW_RESULT]="{ filterContent }">
|
|
||||||
<MsIcon
|
|
||||||
:type="statusIconMap[filterContent.value]?.icon"
|
|
||||||
class="mr-1"
|
|
||||||
:class="[statusIconMap[filterContent.value].color]"
|
|
||||||
></MsIcon>
|
|
||||||
<span>{{ statusIconMap[filterContent.value]?.statusText }} </span>
|
|
||||||
</template>
|
|
||||||
<template #reviewStatus="{ record }">
|
<template #reviewStatus="{ record }">
|
||||||
<MsIcon
|
<MsIcon
|
||||||
:type="statusIconMap[record.reviewStatus]?.icon || ''"
|
:type="statusIconMap[record.reviewStatus]?.icon || ''"
|
||||||
|
@ -97,7 +95,7 @@
|
||||||
<span>{{ statusIconMap[record.reviewStatus]?.statusText || '' }} </span>
|
<span>{{ statusIconMap[record.reviewStatus]?.statusText || '' }} </span>
|
||||||
</template>
|
</template>
|
||||||
<template #lastExecuteResult="{ record }">
|
<template #lastExecuteResult="{ record }">
|
||||||
<ExecuteStatusTag :execute-result="record.lastExecuteResult" />
|
<executeResult :execute-result="record.lastExecuteResult" />
|
||||||
</template>
|
</template>
|
||||||
<template #moduleId="{ record }">
|
<template #moduleId="{ record }">
|
||||||
<a-tree-select
|
<a-tree-select
|
||||||
|
@ -186,20 +184,48 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</ms-base-table>
|
</ms-base-table>
|
||||||
|
</template>
|
||||||
<!-- 用例表结束 -->
|
<!-- 用例表结束 -->
|
||||||
|
<div v-else class="h-full">
|
||||||
|
<div class="flex flex-row items-center justify-between">
|
||||||
|
<a-popover title="" position="bottom">
|
||||||
|
<div class="show-table-top-title">
|
||||||
|
<div class="one-line-text max-h-[32px] max-w-[300px] text-[var(--color-text-1)]">
|
||||||
|
{{ moduleNamePath }}
|
||||||
|
</div>
|
||||||
|
<span class="text-[var(--color-text-4)]"> ({{ props.modulesCount[props.activeFolder] || 0 }})</span>
|
||||||
|
</div>
|
||||||
|
<template #content>
|
||||||
|
<div class="max-w-[400px] text-[14px] font-medium text-[var(--color-text-1)]">
|
||||||
|
{{ moduleNamePath }}
|
||||||
|
<span class="text-[var(--color-text-4)]">({{ props.modulesCount[props.activeFolder] || 0 }})</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</a-popover>
|
||||||
|
<div class="flex items-center gap-[12px]">
|
||||||
|
<a-radio-group v-model:model-value="showType" type="button" size="small" class="list-show-type">
|
||||||
|
<a-radio value="list" class="show-type-icon !m-[2px]">
|
||||||
|
<MsIcon :size="14" type="icon-icon_view-list_outlined" />
|
||||||
|
</a-radio>
|
||||||
|
<a-radio value="xMind" class="show-type-icon !m-[2px]">
|
||||||
|
<MsIcon :size="14" type="icon-icon_mindnote_outlined" />
|
||||||
|
</a-radio>
|
||||||
|
</a-radio-group>
|
||||||
|
<MsTag no-margin size="large" class="cursor-pointer" theme="outline" @click="fetchData">
|
||||||
|
<MsIcon class="text-[16px] text-[var(color-text-4)]" :size="32" type="icon-icon_reset_outlined" />
|
||||||
|
</MsTag>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="h-[calc(100%-32px)]">
|
||||||
<!-- 脑图开始 -->
|
<!-- 脑图开始 -->
|
||||||
<MinderEditor
|
<MsMinder minder-type="FeatureCase" :import-json="importJson" @node-click="handleNodeClick" />
|
||||||
v-else
|
|
||||||
:import-json="importJson"
|
|
||||||
:tags="['模块', '用例', '前置条件', '备注', '步骤', '预期结果']"
|
|
||||||
tag-enable
|
|
||||||
sequence-enable
|
|
||||||
@node-click="handleNodeClick"
|
|
||||||
/>
|
|
||||||
<MsDrawer v-model:visible="visible" :width="480" :mask="false">
|
<MsDrawer v-model:visible="visible" :width="480" :mask="false">
|
||||||
{{ nodeData.text }}
|
{{ nodeData.text }}
|
||||||
</MsDrawer>
|
</MsDrawer>
|
||||||
<!-- 脑图结束 -->
|
<!-- 脑图结束 -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<a-modal
|
<a-modal
|
||||||
v-model:visible="showBatchMoveDrawer"
|
v-model:visible="showBatchMoveDrawer"
|
||||||
title-align="start"
|
title-align="start"
|
||||||
|
@ -292,14 +318,13 @@
|
||||||
import MsButton from '@/components/pure/ms-button/index.vue';
|
import MsButton from '@/components/pure/ms-button/index.vue';
|
||||||
import MsDrawer from '@/components/pure/ms-drawer/index.vue';
|
import MsDrawer from '@/components/pure/ms-drawer/index.vue';
|
||||||
import MsIcon from '@/components/pure/ms-icon-font/index.vue';
|
import MsIcon from '@/components/pure/ms-icon-font/index.vue';
|
||||||
import MinderEditor from '@/components/pure/ms-minder-editor/minderEditor.vue';
|
|
||||||
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
||||||
import type { BatchActionParams, BatchActionQueryParams, MsTableColumn } from '@/components/pure/ms-table/type';
|
import type { BatchActionParams, BatchActionQueryParams, MsTableColumn } from '@/components/pure/ms-table/type';
|
||||||
import useTable from '@/components/pure/ms-table/useTable';
|
import useTable from '@/components/pure/ms-table/useTable';
|
||||||
import MsTableMoreAction from '@/components/pure/ms-table-more-action/index.vue';
|
import MsTableMoreAction from '@/components/pure/ms-table-more-action/index.vue';
|
||||||
import { ActionsItem } from '@/components/pure/ms-table-more-action/types';
|
import { ActionsItem } from '@/components/pure/ms-table-more-action/types';
|
||||||
import caseLevel from '@/components/business/ms-case-associate/caseLevel.vue';
|
import caseLevel from '@/components/business/ms-case-associate/caseLevel.vue';
|
||||||
import ExecuteStatusTag from '@/components/business/ms-case-associate/executeResult.vue';
|
import executeResult from '@/components/business/ms-case-associate/executeResult.vue';
|
||||||
import BatchEditModal from './batchEditModal.vue';
|
import BatchEditModal from './batchEditModal.vue';
|
||||||
import CaseDetailDrawer from './caseDetailDrawer.vue';
|
import CaseDetailDrawer from './caseDetailDrawer.vue';
|
||||||
import FeatureCaseTree from './caseTree.vue';
|
import FeatureCaseTree from './caseTree.vue';
|
||||||
|
@ -337,7 +362,6 @@
|
||||||
DemandItem,
|
DemandItem,
|
||||||
DragCase,
|
DragCase,
|
||||||
} from '@/models/caseManagement/featureCase';
|
} from '@/models/caseManagement/featureCase';
|
||||||
import type { TableQueryParams } from '@/models/common';
|
|
||||||
import { ModuleTreeNode } from '@/models/common';
|
import { ModuleTreeNode } from '@/models/common';
|
||||||
import { CaseManagementRouteEnum } from '@/enums/routeEnum';
|
import { CaseManagementRouteEnum } from '@/enums/routeEnum';
|
||||||
import { ColumnEditTypeEnum, TableKeyEnum } from '@/enums/tableEnum';
|
import { ColumnEditTypeEnum, TableKeyEnum } from '@/enums/tableEnum';
|
||||||
|
@ -1566,4 +1590,10 @@
|
||||||
width: 200px !important;
|
width: 200px !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.list-show-type {
|
||||||
|
padding: 0;
|
||||||
|
:deep(.arco-radio-button-content) {
|
||||||
|
padding: 4px 6px;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -105,7 +105,7 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #second>
|
<template #second>
|
||||||
<div class="p-[16px_16px]">
|
<div class="h-full p-[16px_16px]">
|
||||||
<CaseTable
|
<CaseTable
|
||||||
ref="caseTableRef"
|
ref="caseTableRef"
|
||||||
:active-folder="activeFolder"
|
:active-folder="activeFolder"
|
||||||
|
|
Loading…
Reference in New Issue