feat(功能用例): 用例评审-根节点取消关联后回到上一级模块

This commit is contained in:
teukkk 2024-07-09 19:43:51 +08:00 committed by Craftsman
parent 4df37e5a6f
commit 41816c034f
6 changed files with 95 additions and 54 deletions

View File

@ -3,9 +3,11 @@ import type { MinderJsonNode } from '@/components/pure/ms-minder-editor/props';
import { useI18n } from '@/hooks/useI18n'; import { useI18n } from '@/hooks/useI18n';
import { mapTree } from '@/utils'; import { mapTree } from '@/utils';
import { BatchApiParams } from '@/models/common';
const { t } = useI18n(); const { t } = useI18n();
export function getMinderOffspringIds(node: MinderJsonNode) { export function getMinderOffspringIds(node: MinderJsonNode): string[] {
const offspringIds: string[] = []; const offspringIds: string[] = [];
mapTree(node.children || [], (e) => { mapTree(node.children || [], (e) => {
if (e.data.resource?.includes(t('common.module')) && e.data.id !== 'fakeNode') { if (e.data.resource?.includes(t('common.module')) && e.data.id !== 'fakeNode') {
@ -20,7 +22,7 @@ export function getMinderOffspringIds(node: MinderJsonNode) {
* *
* @param node * @param node
*/ */
export function getMinderOperationParams(node: MinderJsonNode) { export function getMinderOperationParams(node: MinderJsonNode): BatchApiParams {
if (node.data?.resource?.includes(t('common.module'))) { if (node.data?.resource?.includes(t('common.module'))) {
return { return {
selectIds: [], selectIds: [],
@ -30,8 +32,9 @@ export function getMinderOperationParams(node: MinderJsonNode) {
}; };
} }
return { return {
selectIds: [node.data?.caseId], selectIds: [node.data?.id as string],
selectAll: false, selectAll: false,
condition: {}, condition: {},
moduleIds: [],
}; };
} }

View File

@ -1,16 +1,44 @@
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
import { getReviewDetailModuleCount } from '@/api/modules/case-management/caseReview'; import { getReviewDetailModuleCount, getReviewDetailModuleTree } from '@/api/modules/case-management/caseReview';
import { mapTree } from '@/utils';
import type { ReviewDetailCaseListQueryParams } from '@/models/caseManagement/caseReview'; import type { ReviewDetailCaseListQueryParams } from '@/models/caseManagement/caseReview';
import { ModuleTreeNode } from '@/models/common';
const useCaseReviewStore = defineStore('caseReview', { const useCaseReviewStore = defineStore('caseReview', {
state: (): { state: (): {
modulesCount: Record<string, any>; // 用例树模块数量 modulesCount: Record<string, any>; // 用例树模块数量
moduleTree: ModuleTreeNode[]; // 用例树
loading: boolean;
} => ({ } => ({
modulesCount: {}, modulesCount: {},
moduleTree: [],
loading: false,
}), }),
actions: { actions: {
// 初始化模块树
async initModules(id: string) {
try {
this.loading = true;
const res = await getReviewDetailModuleTree(id);
this.moduleTree = mapTree<ModuleTreeNode>(res, (node) => {
return {
...node,
count: this.modulesCount?.[node.id] || 0,
};
});
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);
} finally {
this.loading = false;
}
},
// 设置模块树
setModulesTree(tree: ModuleTreeNode[]) {
this.moduleTree = tree;
},
async getModuleCount(params: ReviewDetailCaseListQueryParams) { async getModuleCount(params: ReviewDetailCaseListQueryParams) {
try { try {
this.modulesCount = await getReviewDetailModuleCount(params); this.modulesCount = await getReviewDetailModuleCount(params);

View File

@ -138,7 +138,7 @@
:module-id="props.activeFolder" :module-id="props.activeFolder"
:view-flag="props.onlyMine" :view-flag="props.onlyMine"
:view-status-flag="onlyMineStatus" :view-status-flag="onlyMineStatus"
:module-tree="props.moduleTree" :module-tree="moduleTree"
:review-progress="props.reviewProgress" :review-progress="props.reviewProgress"
:review-pass-rule="props.reviewPassRule" :review-pass-rule="props.reviewPassRule"
@operation="handleMinderOperation" @operation="handleMinderOperation"
@ -337,7 +337,7 @@
import { hasAnyPermission } from '@/utils/permission'; import { hasAnyPermission } from '@/utils/permission';
import { ReviewCaseItem, ReviewItem, ReviewPassRule, ReviewResult } from '@/models/caseManagement/caseReview'; import { ReviewCaseItem, ReviewItem, ReviewPassRule, ReviewResult } from '@/models/caseManagement/caseReview';
import { BatchApiParams, ModuleTreeNode, TableQueryParams } from '@/models/common'; import { BatchApiParams, TableQueryParams } from '@/models/common';
import { CaseManagementRouteEnum } from '@/enums/routeEnum'; import { CaseManagementRouteEnum } from '@/enums/routeEnum';
import { TableKeyEnum } from '@/enums/tableEnum'; import { TableKeyEnum } from '@/enums/tableEnum';
import { FilterSlotNameEnum } from '@/enums/tableFilterEnum'; import { FilterSlotNameEnum } from '@/enums/tableFilterEnum';
@ -354,10 +354,9 @@
onlyMine: boolean; onlyMine: boolean;
reviewPassRule: ReviewPassRule; // reviewPassRule: ReviewPassRule; //
offspringIds: string[]; // id offspringIds: string[]; // id
moduleTree: ModuleTreeNode[];
reviewProgress: string; // reviewProgress: string; //
}>(); }>();
const emit = defineEmits(['refresh', 'link']); const emit = defineEmits(['refresh', 'link', 'selectParentNode']);
const router = useRouter(); const router = useRouter();
const route = useRoute(); const route = useRoute();
@ -378,10 +377,14 @@
const showType = ref<'list' | 'minder'>('list'); const showType = ref<'list' | 'minder'>('list');
const msCaseReviewMinderRef = ref<InstanceType<typeof MsCaseReviewMinder>>(); const msCaseReviewMinderRef = ref<InstanceType<typeof MsCaseReviewMinder>>();
const moduleTree = computed(() => unref(caseReviewStore.moduleTree));
async function initModules() {
await caseReviewStore.initModules(route.query.id as string);
}
const moduleNamePath = computed(() => { const moduleNamePath = computed(() => {
return props.activeFolder === 'all' return props.activeFolder === 'all'
? t('caseManagement.featureCase.allCase') ? t('caseManagement.featureCase.allCase')
: findNodeByKey<Record<string, any>>(props.moduleTree, props.activeFolder, 'id')?.name; : findNodeByKey<Record<string, any>>(moduleTree.value, props.activeFolder, 'id')?.name;
}); });
const hasOperationPermission = computed(() => const hasOperationPermission = computed(() =>
@ -523,12 +526,16 @@
current: propsRes.value.msPagination?.current, current: propsRes.value.msPagination?.current,
pageSize: propsRes.value.msPagination?.pageSize, pageSize: propsRes.value.msPagination?.pageSize,
total: propsRes.value.msPagination?.total, total: propsRes.value.msPagination?.total,
moduleIds: [],
}; };
} else { } else {
params = { moduleIds: [props.activeFolder], projectId: appStore.currentProjectId, pageSize: 10, current: 1 }; params = { projectId: appStore.currentProjectId, pageSize: 10, current: 1 };
} }
await caseReviewStore.getModuleCount({ ...params, viewFlag: props.onlyMine, reviewId: route.query.id as string }); await caseReviewStore.getModuleCount({
...params,
moduleIds: [],
viewFlag: props.onlyMine,
reviewId: route.query.id as string,
});
} }
function searchCase(filter?: FilterResult) { function searchCase(filter?: FilterResult) {
@ -650,6 +657,7 @@
try { try {
disassociateLoading.value = true; disassociateLoading.value = true;
await disassociateReviewCase(route.query.id as string, record.caseId); await disassociateReviewCase(route.query.id as string, record.caseId);
initModules();
emit('refresh'); emit('refresh');
if (done) { if (done) {
done(); done();
@ -719,9 +727,16 @@
}); });
Message.success(t('common.updateSuccess')); Message.success(t('common.updateSuccess'));
dialogLoading.value = false; dialogLoading.value = false;
refresh(); const folderTree = cloneDeep(moduleTree.value);
emit('refresh'); emit('refresh');
// TODO: await initModules();
await getModuleCount();
if (!Object.keys(modulesCount.value).includes(props.activeFolder)) {
//
emit('selectParentNode', folderTree);
} else {
refresh(false);
}
} catch (error) { } catch (error) {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.log(error); console.log(error);
@ -809,6 +824,7 @@
}); });
Message.success(t('common.updateSuccess')); Message.success(t('common.updateSuccess'));
dialogVisible.value = false; dialogVisible.value = false;
emit('refresh');
refresh(); refresh();
} catch (error) { } catch (error) {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console

View File

@ -54,8 +54,8 @@
import MsTree from '@/components/business/ms-tree/index.vue'; import MsTree from '@/components/business/ms-tree/index.vue';
import type { MsTreeNodeData } from '@/components/business/ms-tree/types'; import type { MsTreeNodeData } from '@/components/business/ms-tree/types';
import { getReviewDetailModuleTree } from '@/api/modules/case-management/caseReview';
import { useI18n } from '@/hooks/useI18n'; import { useI18n } from '@/hooks/useI18n';
import useCaseReviewStore from '@/store/modules/case/caseReview';
import { mapTree } from '@/utils'; import { mapTree } from '@/utils';
import { ModuleTreeNode } from '@/models/common'; import { ModuleTreeNode } from '@/models/common';
@ -66,10 +66,11 @@
isExpandAll?: boolean; // isExpandAll?: boolean; //
selectedKeys: string[]; // key selectedKeys: string[]; // key
}>(); }>();
const emit = defineEmits(['init', 'folderNodeSelect']); const emit = defineEmits(['folderNodeSelect']);
const route = useRoute(); const route = useRoute();
const { t } = useI18n(); const { t } = useI18n();
const caseReviewStore = useCaseReviewStore();
const virtualListProps = computed(() => { const virtualListProps = computed(() => {
return { return {
@ -97,8 +98,8 @@
} }
const moduleKeyword = ref(''); const moduleKeyword = ref('');
const folderTree = ref<ModuleTreeNode[]>([]); const folderTree = computed(() => caseReviewStore.moduleTree);
const loading = ref(false); const loading = computed(() => caseReviewStore.loading);
const selectedKeys = useVModel(props, 'selectedKeys', emit); const selectedKeys = useVModel(props, 'selectedKeys', emit);
@ -106,22 +107,7 @@
* 初始化模块树 * 初始化模块树
*/ */
async function initModules() { async function initModules() {
try { await caseReviewStore.initModules(route.query.id as string);
loading.value = true;
const res = await getReviewDetailModuleTree(route.query.id as string);
folderTree.value = mapTree<ModuleTreeNode>(res, (node) => {
return {
...node,
count: props.modulesCount?.[node.id] || 0,
};
});
emit('init', folderTree.value);
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);
} finally {
loading.value = false;
}
} }
/** /**
@ -137,6 +123,24 @@
emit('folderNodeSelect', _selectedKeys, offspringIds); emit('folderNodeSelect', _selectedKeys, offspringIds);
} }
/**
* 选中父节点
* @param tree 原来的模块树
*/
function selectParentNode(tree: ModuleTreeNode[]) {
if (tree[0].parentId) {
mapTree(tree || [], (e) => {
if (e.id === selectedKeys.value[0]) {
selectedKeys.value = [e.parentId];
folderNodeSelect([e.parentId], e.parent);
}
return e;
});
} else {
setActiveFolder('all');
}
}
onBeforeMount(() => { onBeforeMount(() => {
initModules(); initModules();
}); });
@ -147,17 +151,19 @@
watch( watch(
() => props.modulesCount, () => props.modulesCount,
(obj) => { (obj) => {
folderTree.value = mapTree<ModuleTreeNode>(folderTree.value, (node) => { const tree = mapTree<ModuleTreeNode>(folderTree.value, (node) => {
return { return {
...node, ...node,
count: obj?.[node.id] || 0, count: obj?.[node.id] || 0,
}; };
}); });
caseReviewStore.setModulesTree(tree);
allCount.value = obj?.all || 0; allCount.value = obj?.all || 0;
} }
); );
defineExpose({ defineExpose({
initModules, initModules,
selectParentNode,
}); });
</script> </script>

View File

@ -42,12 +42,7 @@
import { useI18n } from '@/hooks/useI18n'; import { useI18n } from '@/hooks/useI18n';
import useAppStore from '@/store/modules/app'; import useAppStore from '@/store/modules/app';
import { import { BatchReviewCaseParams, ReviewFormParams, ReviewPassRule } from '@/models/caseManagement/caseReview';
BatchReviewCaseParams,
ReviewFormParams,
ReviewPassRule,
ReviewResult,
} from '@/models/caseManagement/caseReview';
import { StartReviewStatus } from '@/enums/caseEnum'; import { StartReviewStatus } from '@/enums/caseEnum';
const props = defineProps<{ const props = defineProps<{

View File

@ -114,7 +114,6 @@
:modules-count="modulesCount" :modules-count="modulesCount"
:selected-keys="selectedKeys" :selected-keys="selectedKeys"
@folder-node-select="handleFolderNodeSelect" @folder-node-select="handleFolderNodeSelect"
@init="initModuleTree"
/> />
</div> </div>
</template> </template>
@ -127,9 +126,9 @@
:offspring-ids="offspringIds" :offspring-ids="offspringIds"
:modules-count="modulesCount" :modules-count="modulesCount"
:review-progress="reviewProgress" :review-progress="reviewProgress"
:module-tree="moduleTree" @refresh="initDetail()"
@refresh="handleRefresh"
@link="associateDrawerVisible = true" @link="associateDrawerVisible = true"
@select-parent-node="selectParentNode"
></CaseTable> ></CaseTable>
</template> </template>
</MsSplitBox> </MsSplitBox>
@ -223,6 +222,10 @@
}); });
const caseTableRef = ref<InstanceType<typeof CaseTable>>(); const caseTableRef = ref<InstanceType<typeof CaseTable>>();
function selectParentNode(folderTree: ModuleTreeNode[]) {
folderTreeRef.value?.selectParentNode(folderTree);
}
function handleFolderNodeSelect(ids: string[], _offspringIds: string[]) { function handleFolderNodeSelect(ids: string[], _offspringIds: string[]) {
[activeFolderId.value] = ids; [activeFolderId.value] = ids;
offspringIds.value = [..._offspringIds]; offspringIds.value = [..._offspringIds];
@ -370,16 +373,6 @@
}); });
} }
function handleRefresh() {
initDetail();
folderTreeRef.value?.initModules();
}
const moduleTree = ref<ModuleTreeNode[]>([]);
function initModuleTree(tree: ModuleTreeNode[]) {
moduleTree.value = unref(tree);
}
onMounted(() => { onMounted(() => {
initDetail(); initDetail();
}); });