feat(功能用例): 用例评审脑图右侧tab

This commit is contained in:
teukkk 2024-07-03 19:05:40 +08:00 committed by 刘瑞斌
parent 2fc5db0745
commit 3e49eab864
11 changed files with 93 additions and 40 deletions

View File

@ -1,4 +1,5 @@
@import url('./arco-reset.less'); @import url('./arco-reset.less');
@import url('@/components/business/ms-comment/style.less');
:root { :root {
--border-radius-mini: 2px; --border-radius-mini: 2px;
} }

View File

@ -5,8 +5,8 @@
border-radius: 4px; border-radius: 4px;
} }
.markdown-body { .markdown-body {
font-size: 14px; font-size: 14px !important;
line-height: 22px; line-height: 22px !important;
color: var(--color-text-2) !important; color: var(--color-text-2) !important;
ul { ul {
list-style: disc !important; list-style: disc !important;

View File

@ -8,22 +8,17 @@
:extract-content-tab-list="extractContentTabList" :extract-content-tab-list="extractContentTabList"
:can-show-float-menu="canShowFloatMenu" :can-show-float-menu="canShowFloatMenu"
:can-show-priority-menu="false" :can-show-priority-menu="false"
:can-show-more-menu="showCaseMenu" :can-show-more-menu="canShowFloatMenu"
:can-show-enter-node="canShowEnterNode"
:can-show-more-menu-node-operation="false" :can-show-more-menu-node-operation="false"
:more-menu-other-operation-list="moreMenuOtherOperationList" :more-menu-other-operation-list="canShowEnterNode ? [] : moreMenuOtherOperationList"
disabled disabled
single-tag single-tag
@node-select="handleNodeSelect" @node-select="handleNodeSelect"
> >
<template #extractMenu> <template #extractMenu>
<!-- 进入当前节点 -->
<template v-if="canShowEnterNode">
<MsButton type="text" class="!text-[var(--color-text-1)]" @click="handleEnterNode">
{{ t('minder.hotboxMenu.enterNode') }}
</MsButton>
</template>
<template v-if="showCaseMenu"> <template v-if="showCaseMenu">
<!-- 评审 查看详情 更多 --> <!-- 评审 查看详情 -->
<a-tooltip :content="t('caseManagement.caseReview.review')"> <a-tooltip :content="t('caseManagement.caseReview.review')">
<MsButton type="icon" class="ms-minder-node-float-menu-icon-button"> <MsButton type="icon" class="ms-minder-node-float-menu-icon-button">
<MsIcon type="icon-icon_audit" class="text-[var(--color-text-4)]" /> <MsIcon type="icon-icon_audit" class="text-[var(--color-text-4)]" />
@ -46,6 +41,7 @@
:loading="baseInfoLoading" :loading="baseInfoLoading"
:descriptions="descriptions" :descriptions="descriptions"
label-width="90px" label-width="90px"
class="pl-[16px]"
/> />
<Attachment <Attachment
v-else-if="activeExtraKey === 'attachment'" v-else-if="activeExtraKey === 'attachment'"
@ -53,15 +49,20 @@
not-show-add-button not-show-add-button
:active-case="activeCaseInfo" :active-case="activeCaseInfo"
/> />
<div v-else> <div v-else class="pl-[16px]">
<div v-if="props.reviewPassRule === 'MULTIPLE'" class="flex justify-between"> <div v-if="props.reviewPassRule === 'MULTIPLE'" class="mb-[8px] flex justify-between">
<div class="text-[12px]"> <div class="text-[12px]">
<span class="text-[var(--color-text-4)]">{{ t('caseManagement.caseReview.progress') }}</span> <span class="text-[var(--color-text-4)]">{{ t('caseManagement.caseReview.progress') }}</span>
{{ props.passRate }} {{ props.reviewProgress }}
</div> </div>
<!-- TODO 下拉 --> <!-- TODO 总结果 hover展示单个 -->
<ReviewResult :status="activeCaseInfo.reviewStatus" />
</div> </div>
<ReviewCommentList :review-comment-list="reviewHistoryList" active-comment="reviewComment" /> <ReviewCommentList
:review-comment-list="reviewHistoryList"
active-comment="reviewComment"
not-show-review-name
/>
</div> </div>
</template> </template>
</MsMinderEditor> </MsMinderEditor>
@ -80,6 +81,7 @@
import { MsFileItem } from '@/components/pure/ms-upload/types'; import { MsFileItem } from '@/components/pure/ms-upload/types';
import Attachment from '@/components/business/ms-minders/featureCaseMinder/attachment.vue'; import Attachment from '@/components/business/ms-minders/featureCaseMinder/attachment.vue';
import ReviewCommentList from '@/views/case-management/caseManagementFeature/components/tabContent/tabComment/reviewCommentList.vue'; import ReviewCommentList from '@/views/case-management/caseManagementFeature/components/tabContent/tabComment/reviewCommentList.vue';
import ReviewResult from '@/views/case-management/caseReview/components/reviewResult.vue';
import { getCaseReviewHistoryList, getCaseReviewMinder } from '@/api/modules/case-management/caseReview'; import { getCaseReviewHistoryList, getCaseReviewMinder } from '@/api/modules/case-management/caseReview';
import { getCaseDetail } from '@/api/modules/case-management/featureCase'; import { getCaseDetail } from '@/api/modules/case-management/featureCase';
@ -99,7 +101,7 @@
modulesCount: Record<string, number>; // modulesCount: Record<string, number>; //
viewFlag: boolean; // viewFlag: boolean; //
viewStatusFlag: boolean; // viewStatusFlag: boolean; //
passRate: string; reviewProgress: string;
reviewPassRule: ReviewPassRule; // reviewPassRule: ReviewPassRule; //
moduleTree: ModuleTreeNode[]; moduleTree: ModuleTreeNode[];
}>(); }>();
@ -345,7 +347,7 @@
async function initCaseDetail(data: MinderJsonNodeData) { async function initCaseDetail(data: MinderJsonNodeData) {
try { try {
baseInfoLoading.value = true; baseInfoLoading.value = true;
const res = await getCaseDetail(data?.id || activeCaseInfo.value.id); const res = await getCaseDetail(data?.caseId || activeCaseInfo.value.caseId);
activeCaseInfo.value = res; activeCaseInfo.value = res;
// //
descriptions.value = [ descriptions.value = [
@ -401,7 +403,7 @@
const reviewHistoryList = ref<ReviewHistoryItem[]>([]); const reviewHistoryList = ref<ReviewHistoryItem[]>([]);
async function initReviewHistoryList(data: MinderJsonNodeData) { async function initReviewHistoryList(data: MinderJsonNodeData) {
try { try {
const res = await getCaseReviewHistoryList(route.query.id as string, data?.id || activeCaseInfo.value.id); const res = await getCaseReviewHistoryList(route.query.id as string, data?.caseId || activeCaseInfo.value.caseId);
reviewHistoryList.value = res; reviewHistoryList.value = res;
} catch (error) { } catch (error) {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
@ -505,14 +507,6 @@
setPriorityView(true, 'P'); setPriorityView(true, 'P');
} }
/**
* 进入当前节点
*/
function handleEnterNode() {
const selectedNodes: MinderJsonNode[] = window.minder.getSelectedNodes();
minderStore.dispatchEvent(MinderEventName.ENTER_NODE, undefined, undefined, undefined, [selectedNodes[0]]);
}
defineExpose({ defineExpose({
initNodeCases, initNodeCases,
}); });

View File

@ -134,13 +134,13 @@
</MsButton> </MsButton>
</a-tooltip> </a-tooltip>
<template #content> <template #content>
<a-doption v-if="props.canShowEnterNode" value="enterNode">
<div class="flex items-center">
<div>{{ t('minder.hotboxMenu.enterNode') }}</div>
<!-- <div class="ml-[4px] text-[var(--color-text-4)]">(Ctrl+ Enter)</div> -->
</div>
</a-doption>
<template v-if="props.canShowMoreMenuNodeOperation"> <template v-if="props.canShowMoreMenuNodeOperation">
<a-doption v-if="props.canShowEnterNode" value="enterNode">
<div class="flex items-center">
<div>{{ t('minder.hotboxMenu.enterNode') }}</div>
<!-- <div class="ml-[4px] text-[var(--color-text-4)]">(Ctrl+ Enter)</div> -->
</div>
</a-doption>
<a-doption value="copy"> <a-doption value="copy">
<div class="flex items-center"> <div class="flex items-center">
<div>{{ t('minder.hotboxMenu.copy') }}</div> <div>{{ t('minder.hotboxMenu.copy') }}</div>

View File

@ -163,6 +163,10 @@
width: 0; width: 0;
transition: all 300ms ease-in-out; transition: all 300ms ease-in-out;
:deep(.ms-tab--button-item) {
flex: 1;
text-align: center;
}
.ms-minder-editor-extra-content { .ms-minder-editor-extra-content {
@apply relative flex-1 overflow-y-auto; @apply relative flex-1 overflow-y-auto;
.ms-scroll-bar(); .ms-scroll-bar();

View File

@ -155,7 +155,7 @@ export const floatMenuProps = {
type: Boolean, type: Boolean,
default: true, default: true,
}, },
// 是否显示更多菜单里的[进入、复制、粘贴、剪切、删除]操作 // 是否显示更多菜单里的[复制、粘贴、剪切、删除]操作
canShowMoreMenuNodeOperation: { canShowMoreMenuNodeOperation: {
type: Boolean, type: Boolean,
default: true, default: true,

View File

@ -37,7 +37,7 @@
{{ t('common.fail') }} {{ t('common.fail') }}
</div> </div>
</div> </div>
<div class="markdown-body" v-html="item.contentText"></div> <div class="markdown-body mt-[4px]" v-html="item.contentText"></div>
<div class="mt-[8px] flex text-[12px] leading-[16px] text-[var(--color-text-4)]"> <div class="mt-[8px] flex text-[12px] leading-[16px] text-[var(--color-text-4)]">
{{ dayjs(item.createTime).format('YYYY-MM-DD HH:mm:ss') }} {{ dayjs(item.createTime).format('YYYY-MM-DD HH:mm:ss') }}
<div v-if="props.activeComment === 'reviewComment'"> <div v-if="props.activeComment === 'reviewComment'">
@ -47,7 +47,7 @@
</span> </span>
<span <span
v-else v-if="!item.deleted && !props.notShowReviewName"
class="one-line-text ml-[16px] max-w-[300px] cursor-pointer break-words break-all text-[rgb(var(--primary-5))]" class="one-line-text ml-[16px] max-w-[300px] cursor-pointer break-words break-all text-[rgb(var(--primary-5))]"
@click="review(item)" @click="review(item)"
> >
@ -94,6 +94,7 @@
const props = defineProps<{ const props = defineProps<{
reviewCommentList: any[]; reviewCommentList: any[];
activeComment: string; activeComment: string;
notShowReviewName?: boolean;
}>(); }>();
const router = useRouter(); const router = useRouter();

View File

@ -140,7 +140,7 @@
:view-status-flag="onlyMineStatus" :view-status-flag="onlyMineStatus"
:module-tree="props.moduleTree" :module-tree="props.moduleTree"
:modules-count="props.modulesCount" :modules-count="props.modulesCount"
:pass-rate="props.passRate" :review-progress="props.reviewProgress"
:review-pass-rule="props.reviewPassRule" :review-pass-rule="props.reviewPassRule"
/> />
</div> </div>
@ -352,7 +352,7 @@
offspringIds: string[]; // id offspringIds: string[]; // id
moduleTree: ModuleTreeNode[]; moduleTree: ModuleTreeNode[];
modulesCount: Record<string, number>; // modulesCount: Record<string, number>; //
passRate: string; reviewProgress: string; //
}>(); }>();
const emit = defineEmits(['init', 'refresh', 'link']); const emit = defineEmits(['init', 'refresh', 'link']);

View File

@ -119,6 +119,10 @@
((props.reviewDetail.passCount + props.reviewDetail.unPassCount) / props.reviewDetail.caseCount) * 100; ((props.reviewDetail.passCount + props.reviewDetail.unPassCount) / props.reviewDetail.caseCount) * 100;
return `${Number.isNaN(result) ? 0 : result.toFixed(2)}%`; return `${Number.isNaN(result) ? 0 : result.toFixed(2)}%`;
}); });
defineExpose({
progress,
});
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>

View File

@ -0,0 +1,42 @@
<template>
<div v-if="props.status" class="flex items-center">
<MsIcon
:type="resultMap[props.status]?.icon || ''"
class="mr-[4px]"
:size="16"
:style="{ color: resultMap[props.status]?.color }"
></MsIcon>
{{ t(resultMap[props.status]?.label) }}
</div>
</template>
<script setup lang="ts">
import MsIcon from '@/components/pure/ms-icon-font/index.vue';
import { reviewResultMap } from '@/config/caseManagement';
import { useI18n } from '@/hooks/useI18n';
import { ReviewResult } from '@/models/caseManagement/caseReview';
const { t } = useI18n();
const props = defineProps<{
status?: ReviewResult;
isPart?: boolean; // true'UNDER_REVIEWED'''
}>();
const resultMap = computed(() =>
props.isPart
? {
...reviewResultMap,
...{
UNDER_REVIEWED: {
label: 'caseManagement.caseReview.suggestion',
color: 'rgb(var(--warning-6))',
icon: 'icon-icon_warning_filled',
},
},
}
: reviewResultMap
);
</script>

View File

@ -89,7 +89,12 @@
</span> </span>
</div> </div>
</div> </div>
<passRateLine :review-detail="reviewDetail" height="8px" radius="var(--border-radius-mini)" /> <passRateLine
ref="passRateLineRef"
:review-detail="reviewDetail"
height="8px"
radius="var(--border-radius-mini)"
/>
</div> </div>
</template> </template>
<!-- <div class="px-[24px]"> <!-- <div class="px-[24px]">
@ -121,7 +126,7 @@
:review-pass-rule="reviewDetail.reviewPassRule" :review-pass-rule="reviewDetail.reviewPassRule"
:offspring-ids="offspringIds" :offspring-ids="offspringIds"
:modules-count="modulesCount" :modules-count="modulesCount"
:pass-rate="reviewDetail.status === 'PREPARED' ? '-' : `${reviewDetail.passRate}%`" :review-progress="reviewProgress"
:module-tree="moduleTree" :module-tree="moduleTree"
@init="initModulesCount" @init="initModulesCount"
@refresh="handleRefresh" @refresh="handleRefresh"
@ -191,6 +196,8 @@
...reviewDefaultDetail, ...reviewDefaultDetail,
}); });
const reviewId = ref(route.query.id as string); const reviewId = ref(route.query.id as string);
const passRateLineRef = ref<InstanceType<typeof passRateLine>>();
const reviewProgress = computed(() => passRateLineRef.value?.progress ?? '');
async function initDetail() { async function initDetail() {
try { try {