diff --git a/frontend/src/components/business/ms-minders/featureCaseMinder/attachment.vue b/frontend/src/components/business/ms-minders/featureCaseMinder/attachment.vue index b4581b533f..aa22d5471a 100644 --- a/frontend/src/components/business/ms-minders/featureCaseMinder/attachment.vue +++ b/frontend/src/components/business/ms-minders/featureCaseMinder/attachment.vue @@ -2,6 +2,7 @@ {{ t('common.update') }} @@ -125,6 +127,7 @@ import useModal from '@/hooks/useModal'; import useAppStore from '@/store/modules/app'; import { downloadByteFile } from '@/utils'; + import { hasAnyPermission } from '@/utils/permission'; import { AssociatedList } from '@/models/caseManagement/featureCase'; import { TableQueryParams } from '@/models/common'; @@ -151,6 +154,7 @@ hiddenIds: [], }, }); + const hasEditPermission = hasAnyPermission(['FUNCTIONAL_CASE:READ+UPDATE']); // 监视文件列表处理关联和本地文件 watch( diff --git a/frontend/src/components/business/ms-minders/featureCaseMinder/basInfo.vue b/frontend/src/components/business/ms-minders/featureCaseMinder/basInfo.vue index 395aa2f252..e61cd4a372 100644 --- a/frontend/src/components/business/ms-minders/featureCaseMinder/basInfo.vue +++ b/frontend/src/components/business/ms-minders/featureCaseMinder/basInfo.vue @@ -6,7 +6,7 @@ - + -
+
(); const baseInfoForm = ref({ name: '', diff --git a/frontend/src/components/business/ms-minders/featureCaseMinder/bugList.vue b/frontend/src/components/business/ms-minders/featureCaseMinder/bugList.vue index c9985b7923..a8b19570c4 100644 --- a/frontend/src/components/business/ms-minders/featureCaseMinder/bugList.vue +++ b/frontend/src/components/business/ms-minders/featureCaseMinder/bugList.vue @@ -1,6 +1,6 @@
; @@ -79,6 +81,8 @@ const { t } = useI18n(); const { openModal } = useModal(); + const hasEditPermission = hasAnyPermission(['FUNCTIONAL_CASE:READ+COMMENT']); + async function handleUploadImage(file: File) { const { data } = await editorUploadFile({ fileList: [file], diff --git a/frontend/src/components/business/ms-minders/featureCaseMinder/index.vue b/frontend/src/components/business/ms-minders/featureCaseMinder/index.vue index 7daa0d14e0..60b4c720ef 100644 --- a/frontend/src/components/business/ms-minders/featureCaseMinder/index.vue +++ b/frontend/src/components/business/ms-minders/featureCaseMinder/index.vue @@ -11,6 +11,7 @@ :priority-disable-check="priorityDisableCheck" :after-tag-edit="afterTagEdit" :extract-content-tab-list="extractContentTabList" + :can-show-float-menu="canShowFloatMenu()" :can-show-enter-node="canShowEnterNode" :insert-sibling-menus="insertSiblingMenus" :insert-son-menus="insertSonMenus" @@ -18,6 +19,7 @@ :can-show-more-menu="canShowMoreMenu()" :can-show-priority-menu="canShowPriorityMenu()" :priority-tooltip="t('caseManagement.caseReview.caseLevel')" + :disabled="!hasEditPermission" single-tag tag-enable sequence-enable @@ -89,6 +91,7 @@ import useMinderStore from '@/store/modules/components/minder-editor/index'; import { MinderCustomEvent } from '@/store/modules/components/minder-editor/types'; import { filterTree, getGenerateId, mapTree, replaceNodeInTree } from '@/utils'; + import { hasAnyPermission } from '@/utils/permission'; import { FeatureCaseMinderEditType, @@ -114,6 +117,7 @@ const { t } = useI18n(); const minderStore = useMinderStore(); + const hasEditPermission = hasAnyPermission(['FUNCTIONAL_CASE:READ+MINDER']); const { caseTag, moduleTag, @@ -127,13 +131,14 @@ insertNode, handleBeforeExecCommand, stopPaste, + canShowFloatMenu, checkNodeCanShowMenu, canShowMoreMenu, canShowPriorityMenu, handleContentChange, replaceableTags, priorityDisableCheck, - } = useMinderBaseApi(); + } = useMinderBaseApi({ hasEditPermission }); const importJson = ref({ root: {} as MinderJsonNode, template: 'default', @@ -220,61 +225,6 @@ }); const baseInfoRef = ref>(); - - /** - * 解析用例节点信息 - * @param node 用例节点 - */ - function getCaseNodeInfo(node: MinderJsonNode) { - let textStep: MinderJsonNode | undefined; // 文本描述 - let prerequisiteNode: MinderJsonNode | undefined; // 前置条件 - let remarkNode: MinderJsonNode | undefined; // 备注 - const stepNodes: MinderJsonNode[] = []; // 步骤描述 - node.children?.forEach((item) => { - if (item.data?.resource?.includes(textDescTag)) { - textStep = item; - } else if (item.data?.resource?.includes(stepTag)) { - stepNodes.push(item); - } else if (item.data?.resource?.includes(prerequisiteTag)) { - prerequisiteNode = item; - } else if (item.data?.resource?.includes(remarkTag)) { - remarkNode = item; - } - }); - const steps: FeatureCaseMinderStepItem[] = stepNodes.map((child, i) => { - return { - id: child.data?.id || getGenerateId(), - num: i, - desc: child.data?.text || '', - result: child.children?.[0].data?.text || '', - }; - }); - return { - prerequisite: prerequisiteNode?.data?.text || '', - caseEditType: steps.length > 0 ? 'STEP' : ('TEXT' as FeatureCaseMinderEditType), - steps: JSON.stringify(steps), - textDescription: textStep?.data?.text || '', - expectedResult: textStep?.children?.[0]?.data?.text || '', - description: remarkNode?.data?.text || '', - }; - } - - /** - * 获取节点的移动信息 - * @param node 节点 - * @param parent 父节点 - */ - function getNodeMoveInfo(nodeIndex: number, parent?: MinderJsonNode): { moveMode: MoveMode; targetId?: string } { - const moveMode = nodeIndex === 0 ? 'BEFORE' : 'AFTER'; // 除了第一个以外,其他都是在目标节点后面插入 - return { - moveMode, - targetId: - moveMode === 'BEFORE' - ? parent?.children?.[1]?.data?.id - : parent?.children?.[(nodeIndex || parent.children.length - 1) - 1]?.data?.id, - }; - } - const baseInfoLoading = ref(false); const formRules = ref([]); @@ -603,6 +553,65 @@ } } + /** + * 解析用例节点信息 + * @param node 用例节点 + */ + function getCaseNodeInfo(node: MinderJsonNode) { + let textStep: MinderJsonNode | undefined; // 文本描述 + let prerequisiteNode: MinderJsonNode | undefined; // 前置条件 + let remarkNode: MinderJsonNode | undefined; // 备注 + const stepNodes: MinderJsonNode[] = []; // 步骤描述 + node.children?.forEach((item) => { + if (item.data?.resource?.includes(textDescTag)) { + textStep = item; + } else if (item.data?.resource?.includes(stepTag)) { + stepNodes.push(item); + } else if (item.data?.resource?.includes(prerequisiteTag)) { + prerequisiteNode = item; + } else if (item.data?.resource?.includes(remarkTag)) { + remarkNode = item; + } + }); + const steps: FeatureCaseMinderStepItem[] = stepNodes.map((child, i) => { + return { + id: child.data?.id || getGenerateId(), + num: i, + desc: child.data?.text || '', + result: child.children?.[0].data?.text || '', + }; + }); + return { + prerequisite: prerequisiteNode?.data?.text || '', + caseEditType: steps.length > 0 ? 'STEP' : ('TEXT' as FeatureCaseMinderEditType), + steps: JSON.stringify(steps), + textDescription: textStep?.data?.text || '', + expectedResult: textStep?.children?.[0]?.data?.text || '', + description: remarkNode?.data?.text || '', + }; + } + + /** + * 获取节点的移动信息 + * @param node 节点 + * @param parent 父节点 + */ + function getNodeMoveInfo(nodeIndex: number, parent?: MinderJsonNode): { moveMode: MoveMode; targetId?: string } { + const moveMode = nodeIndex === 0 ? 'BEFORE' : 'AFTER'; // 除了第一个以外,其他都是在目标节点后面插入 + if (!parent) { + // 没有父节点的话,说明是根节点下的子节点 + parent = importJson.value.root; + } + + return { + moveMode, + targetId: + moveMode === 'BEFORE' + ? parent?.children?.[1]?.data?.id + : parent?.children?.[(nodeIndex || parent.children.length - 1) - 1]?.data?.id, + }; + } + /** * 生成脑图保存的入参 */ diff --git a/frontend/src/components/business/ms-minders/featureCaseMinder/useMinderBaseApi.ts b/frontend/src/components/business/ms-minders/featureCaseMinder/useMinderBaseApi.ts index fb63d42e27..544202f7f0 100644 --- a/frontend/src/components/business/ms-minders/featureCaseMinder/useMinderBaseApi.ts +++ b/frontend/src/components/business/ms-minders/featureCaseMinder/useMinderBaseApi.ts @@ -13,7 +13,7 @@ import { getGenerateId } from '@/utils'; * 封装用例脑图基础功能,包含菜单显隐判断、节点插入、节点替换、节点拖拽等 * @returns API 集合 */ -export default function useMinderBaseApi() { +export default function useMinderBaseApi({ hasEditPermission }: { hasEditPermission: boolean }) { const { t } = useI18n(); const minderStore = useMinderStore(); @@ -29,6 +29,22 @@ export default function useMinderBaseApi() { const caseChildTags = [prerequisiteTag, stepTag, textDescTag, remarkTag]; const caseOffspringTags = [...caseChildTags, stepTag, stepExpectTag, textDescTag, remarkTag]; + /** + * 是否可展示浮动菜单 + */ + function canShowFloatMenu() { + if (window.minder) { + const node: MinderJsonNode = window.minder.getSelectedNode(); + if (node.data?.resource?.includes(caseTag)) { + return true; + } + if (!hasEditPermission) { + return false; + } + } + return false; + } + const insertSiblingMenus = ref([]); const insertSonMenus = ref([]); @@ -37,6 +53,11 @@ export default function useMinderBaseApi() { * @param node 选中节点 */ function checkNodeCanShowMenu(node: MinderJsonNode) { + if (!hasEditPermission) { + insertSiblingMenus.value = []; + insertSonMenus.value = []; + return; + } const { data } = node; if (data?.resource?.includes(moduleTag)) { // 模块节点 @@ -191,6 +212,9 @@ export default function useMinderBaseApi() { * 是否可展示更多菜单 */ function canShowMoreMenu() { + if (!hasEditPermission) { + return false; + } if (window.minder) { const node: MinderJsonNode = window.minder.getSelectedNode(); // 选中节点不为虚拟根节点时,可展示更多菜单 @@ -203,6 +227,9 @@ export default function useMinderBaseApi() { * 是否可展示优先级菜单 */ function canShowPriorityMenu() { + if (!hasEditPermission) { + return false; + } if (window.minder) { const node: MinderJsonNode = window.minder.getSelectedNode(); // 选中节点是用例节点时,可展示优先级菜单 @@ -280,6 +307,9 @@ export default function useMinderBaseApi() { * 检查节点是否可打优先级 */ function priorityDisableCheck(node: MinderJsonNode) { + if (!hasEditPermission) { + return false; + } if (node.data?.resource?.includes(caseTag)) { return false; } @@ -678,6 +708,7 @@ export default function useMinderBaseApi() { handleBeforeExecCommand, stopPaste, checkNodeCanShowMenu, + canShowFloatMenu, canShowMoreMenu, canShowPriorityMenu, handleContentChange, diff --git a/frontend/src/components/business/ms-minders/testPlanMinder/index.vue b/frontend/src/components/business/ms-minders/testPlanMinder/index.vue index 35e9b9fe2f..f12eb6c237 100644 --- a/frontend/src/components/business/ms-minders/testPlanMinder/index.vue +++ b/frontend/src/components/business/ms-minders/testPlanMinder/index.vue @@ -13,6 +13,7 @@ :can-show-priority-menu="false" :can-show-float-menu="canShowFloatMenu" :can-show-delete-menu="canShowDeleteMenu" + :disable="!hasEditPermission" custom-priority single-tag tag-enable @@ -20,7 +21,6 @@ @node-select="(node) => handleNodeSelect(node as PlanMinderNode)" @before-exec-command="handleBeforeExecCommand" @save="handleMinderSave" - @float-menu-close="handleFloatMenuClose" >