feat(功能用例): 用例评审脑图-模块操作

This commit is contained in:
teukkk 2024-07-09 12:02:34 +08:00 committed by 刘瑞斌
parent 106156a51f
commit 2de9d0534d
4 changed files with 131 additions and 98 deletions

View File

@ -11,57 +11,56 @@
:can-show-more-menu="canShowFloatMenu"
:can-show-enter-node="canShowEnterNode"
:can-show-more-menu-node-operation="false"
:more-menu-other-operation-list="canShowEnterNode ? [] : moreMenuOtherOperationList"
:more-menu-other-operation-list="canShowFloatMenu ? moreMenuOtherOperationList : []"
disabled
@node-select="handleNodeSelect"
@before-exec-command="handleBeforeExecCommand"
>
<template #extractMenu>
<template v-if="showCaseMenu">
<!-- 评审 查看详情 -->
<a-trigger
v-if="hasAnyPermission(['CASE_REVIEW:READ+REVIEW']) && isReviewer"
v-model:popup-visible="reviewVisible"
trigger="click"
position="bl"
:click-outside-to-close="false"
popup-container=".ms-minder-container"
>
<a-tooltip :content="t('caseManagement.caseReview.review')">
<MsButton
type="icon"
:class="[
'ms-minder-node-float-menu-icon-button',
`${reviewVisible ? 'ms-minder-node-float-menu-icon-button--focus' : ''}`,
]"
>
<MsIcon type="icon-icon_audit" class="text-[var(--color-text-4)]" />
</MsButton>
</a-tooltip>
<template #content>
<div class="w-[440px] rounded bg-white p-[16px] shadow-[0_0_10px_rgba(0,0,0,0.05)]">
<ReviewSubmit
:review-pass-rule="reviewPassRule"
:case-id="selectCaseId"
:review-id="route.query.id as string"
@done="handleReviewDone"
/>
</div>
</template>
</a-trigger>
<a-tooltip :content="t('common.detail')">
<!-- 评审 查看详情 -->
<a-trigger
v-if="hasAnyPermission(['CASE_REVIEW:READ+REVIEW']) && isReviewer"
v-model:popup-visible="reviewVisible"
trigger="click"
position="bl"
:click-outside-to-close="false"
popup-container=".ms-minder-container"
>
<a-tooltip :content="t('caseManagement.caseReview.review')">
<MsButton
type="icon"
:class="[
'ms-minder-node-float-menu-icon-button',
`${extraVisible ? 'ms-minder-node-float-menu-icon-button--focus' : ''}`,
`${reviewVisible ? 'ms-minder-node-float-menu-icon-button--focus' : ''}`,
]"
@click="toggleDetail"
>
<MsIcon type="icon-icon_describe_outlined" class="text-[var(--color-text-4)]" />
<MsIcon type="icon-icon_audit" class="text-[var(--color-text-4)]" />
</MsButton>
</a-tooltip>
</template>
<template #content>
<div class="w-[440px] rounded bg-white p-[16px] shadow-[0_0_10px_rgba(0,0,0,0.05)]">
<ReviewSubmit
:review-pass-rule="reviewPassRule"
:select-node="selectNode"
:user-id="props.viewFlag ? userStore.id || '' : ''"
:review-id="route.query.id as string"
@done="handleReviewDone"
/>
</div>
</template>
</a-trigger>
<a-tooltip v-if="canShowDetail" :content="t('common.detail')">
<MsButton
type="icon"
:class="[
'ms-minder-node-float-menu-icon-button',
`${extraVisible ? 'ms-minder-node-float-menu-icon-button--focus' : ''}`,
]"
@click="toggleDetail"
>
<MsIcon type="icon-icon_describe_outlined" class="text-[var(--color-text-4)]" />
</MsButton>
</a-tooltip>
</template>
<template #extractTabContent>
<MsDescription
@ -169,7 +168,7 @@
}>();
const emit = defineEmits<{
(e: 'operation', type: string, data: MinderJsonNodeData): void;
(e: 'operation', type: string, node: MinderJsonNode): void;
(e: 'handleReviewDone'): void;
}>();
@ -519,16 +518,16 @@
const isReviewer = ref(false); //
const caseReviewerList = ref<CaseReviewFunctionalCaseUserItem[]>([]);
const canShowEnterNode = ref(false);
const showCaseMenu = ref(false);
const canShowDetail = ref(false);
const moreMenuOtherOperationList = ref();
function setMoreMenuOtherOperationList(data: MinderJsonNodeData) {
function setMoreMenuOtherOperationList(node: MinderJsonNode) {
moreMenuOtherOperationList.value = [
{
value: 'changeReviewer',
label: t('caseManagement.caseReview.changeReviewer'),
permission: ['CASE_REVIEW:READ+UPDATE'],
onClick: () => {
emit('operation', 'changeReviewer', data);
emit('operation', 'changeReviewer', node);
},
},
{
@ -536,7 +535,7 @@
label: t('caseManagement.caseReview.reReview'),
permission: ['CASE_REVIEW:READ+UPDATE'],
onClick: () => {
emit('operation', 'reReview', data);
emit('operation', 'reReview', node);
},
},
{
@ -544,31 +543,16 @@
label: t('caseManagement.caseReview.disassociate'),
permission: ['CASE_REVIEW:READ+RELEVANCE'],
onClick: () => {
emit('operation', 'disassociate', data);
emit('operation', 'disassociate', node);
},
},
];
}
const selectCaseId = ref('');
const selectNode = ref();
const reviewVisible = ref(false);
function handleReviewDone(status: ReviewResultStatus) {
function handleReviewDone() {
reviewVisible.value = false;
let origin = window.minder.queryCommandValue('resource');
if (origin[0] !== caseTag) {
origin[0] = statusTagMap[status];
} else {
origin = [statusTagMap[status], ...origin];
}
window.minder.execCommand('resource', origin);
minderStore.dispatchEvent(
MinderEventName.SET_TAG,
undefined,
undefined,
undefined,
window.minder.getSelectedNodes()
);
setPriorityView(true, 'P');
emit('handleReviewDone');
}
@ -594,27 +578,34 @@
setPriorityView(true, 'P');
return;
}
// :
selectNode.value = node;
// :
if (
node.data?.resource?.includes(caseTag) ||
(node.data?.resource?.includes(moduleTag) && node.type !== 'root' && (node.children || []).length > 0)
(node.data?.resource?.includes(moduleTag) && (node.children || []).length > 0)
) {
canShowFloatMenu.value = true;
setMoreMenuOtherOperationList(node);
} else {
canShowFloatMenu.value = false;
}
// :
if (data?.resource?.includes(moduleTag)) {
if (data?.resource?.includes(moduleTag) && (node.children || []).length > 0 && node.type !== 'root') {
canShowEnterNode.value = true;
} else {
canShowEnterNode.value = false;
}
if (data?.resource?.includes(moduleTag) && (node.children || []).length > 0) {
isReviewer.value = true;
} else {
isReviewer.value = false;
}
if (data?.resource?.includes(caseTag)) {
showCaseMenu.value = true;
selectCaseId.value = node.data?.caseId ?? '';
setMoreMenuOtherOperationList(node.data as MinderJsonNodeData);
canShowDetail.value = true;
setIsReviewer(node.data);
if (extraVisible.value) {
toggleDetail(true);
@ -622,11 +613,11 @@
} else if (data?.resource?.includes(moduleTag) && data.count > 0 && data.isLoaded !== true) {
//
await initNodeCases(node);
showCaseMenu.value = false;
extraVisible.value = false;
canShowDetail.value = false;
} else {
showCaseMenu.value = false;
extraVisible.value = false;
canShowDetail.value = false;
resetExtractInfo();
removeFakeNode(node, 'fakeNode');
}

View File

@ -0,0 +1,37 @@
import type { MinderJsonNode } from '@/components/pure/ms-minder-editor/props';
import { useI18n } from '@/hooks/useI18n';
import { mapTree } from '@/utils';
const { t } = useI18n();
export function getMinderOffspringIds(node: MinderJsonNode) {
const offspringIds: string[] = [];
mapTree(node.children || [], (e) => {
if (e.data.resource?.includes(t('common.module')) && e.data.id !== 'fakeNode') {
offspringIds.push(e.data.id);
}
return e;
});
return offspringIds;
}
/**
*
* @param node
*/
export function getMinderOperationParams(node: MinderJsonNode) {
if (node.data?.resource?.includes(t('common.module'))) {
return {
selectIds: [],
selectAll: true,
condition: {},
moduleIds: node.data?.id === 'NONE' ? [] : [node.data?.id, ...getMinderOffspringIds(node)],
};
}
return {
selectIds: [node.data?.caseId],
selectAll: false,
condition: {},
};
}

View File

@ -143,7 +143,7 @@
:review-progress="props.reviewProgress"
:review-pass-rule="props.reviewPassRule"
@operation="handleMinderOperation"
@handle-review-done="emitRefresh"
@handle-review-done="handleReviewDone"
/>
</div>
<a-modal
@ -303,7 +303,7 @@
import { FilterFormItem, FilterResult, FilterType } from '@/components/pure/ms-advance-filter/type';
import MsButton from '@/components/pure/ms-button/index.vue';
import MsIcon from '@/components/pure/ms-icon-font/index.vue';
import type { MinderJsonNodeData } from '@/components/pure/ms-minder-editor/props';
import type { MinderJsonNode, MinderJsonNodeData } from '@/components/pure/ms-minder-editor/props';
import MsPopconfirm from '@/components/pure/ms-popconfirm/index.vue';
import MsRichText from '@/components/pure/ms-rich-text/MsRichText.vue';
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
@ -313,6 +313,7 @@
import { MsFileItem } from '@/components/pure/ms-upload/types';
import caseLevel from '@/components/business/ms-case-associate/caseLevel.vue';
import MsCaseReviewMinder from '@/components/business/ms-minders/caseReviewMinder/index.vue';
import { getMinderOperationParams } from '@/components/business/ms-minders/caseReviewMinder/utils';
import MsSelect from '@/components/business/ms-select';
import {
@ -367,7 +368,8 @@
const { t } = useI18n();
const { openModal } = useModal();
const minderSelectData = ref(); //
const minderSelectData = ref<MinderJsonNodeData>(); //
const minderParams = ref();
const keyword = ref('');
const filterRowCount = ref(0);
const filterConfigList = ref<FilterFormItem[]>([]);
@ -725,11 +727,7 @@
...batchParams.value,
...tableParams.value,
}
: {
selectIds: [minderSelectData.value.id],
selectAll: false,
condition: {},
}),
: minderParams.value),
});
Message.success(t('common.updateSuccess'));
dialogLoading.value = false;
@ -786,11 +784,7 @@
...batchParams.value,
...tableParams.value,
}
: {
selectIds: [minderSelectData.value.id],
selectAll: false,
condition: {},
}),
: minderParams.value),
});
Message.success(t('common.updateSuccess'));
dialogVisible.value = false;
@ -822,11 +816,7 @@
...tableParams.value,
selectIds: batchParams.value.selectIds.length > 0 ? batchParams.value.selectIds : [record.id],
}
: {
selectIds: [minderSelectData.value.id],
selectAll: false,
condition: {},
}),
: minderParams.value),
});
Message.success(t('common.updateSuccess'));
dialogVisible.value = false;
@ -927,11 +917,17 @@
}
//
function handleMinderOperation(type: string, data: MinderJsonNodeData) {
minderSelectData.value = data;
function handleMinderOperation(type: string, node: MinderJsonNode) {
minderSelectData.value = node.data;
minderParams.value = getMinderOperationParams(node);
handleOperation(type);
}
function handleReviewDone() {
refresh(false);
emitRefresh();
}
/**
* 处理表格选中后批量操作
* @param event 批量操作事件对象

View File

@ -34,23 +34,31 @@
import { useEventListener } from '@vueuse/core';
import { Message } from '@arco-design/web-vue';
import type { MinderJsonNode } from '@/components/pure/ms-minder-editor/props';
import { getMinderOperationParams } from '@/components/business/ms-minders/caseReviewMinder/utils';
import ReviewForm from './reviewFormRichText.vue';
import { saveCaseReviewResult } from '@/api/modules/case-management/caseReview';
import { batchReview } from '@/api/modules/case-management/caseReview';
import { useI18n } from '@/hooks/useI18n';
import useAppStore from '@/store/modules/app';
import { ReviewFormParams, ReviewPassRule, ReviewResult } from '@/models/caseManagement/caseReview';
import {
BatchReviewCaseParams,
ReviewFormParams,
ReviewPassRule,
ReviewResult,
} from '@/models/caseManagement/caseReview';
import { StartReviewStatus } from '@/enums/caseEnum';
const props = defineProps<{
caseId: string;
selectNode: MinderJsonNode;
reviewPassRule: ReviewPassRule;
reviewId: string;
userId: string;
}>();
const emit = defineEmits<{
(e: 'done', status: ReviewResult): void;
(e: 'done'): void;
}>();
const { t } = useI18n();
@ -84,7 +92,7 @@
});
watch(
() => props.caseId,
() => props.selectNode.data?.caseId,
() => {
form.value = { ...defaultForm };
}
@ -94,18 +102,19 @@
async function submit() {
try {
submitLoading.value = true;
const params = {
const params: BatchReviewCaseParams = {
projectId: appStore.currentProjectId,
caseId: props.caseId,
userId: props.userId,
reviewId: props.reviewId,
reviewPassRule: props.reviewPassRule,
...form.value,
notifier: form.value.notifiers?.join(';') ?? '',
...getMinderOperationParams(props.selectNode),
};
await saveCaseReviewResult(params);
await batchReview(params);
modalVisible.value = false;
Message.success(t('caseManagement.caseReview.reviewSuccess'));
emit('done', form.value.status);
emit('done');
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);