feat(功能用例): 用例评审-根节点取消关联后回到上一级模块
This commit is contained in:
parent
4df37e5a6f
commit
41816c034f
|
@ -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: [],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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<{
|
||||||
|
|
|
@ -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();
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue