feat: 页面缓存功能实现

This commit is contained in:
xinxin.wu 2024-08-29 14:48:49 +08:00 committed by Craftsman
parent fe3c5dd672
commit 26f1f82686
26 changed files with 510 additions and 68 deletions

View File

@ -0,0 +1,23 @@
<template>
<div>
<slot></slot>
</div>
</template>
<script lang="ts">
// : vue3使 defineOptions() 访 setup()
export default {
name: '',
props: {
cacheName: {
type: String,
required: true,
},
},
created() {
this.$options.name = this.cacheName;
},
};
</script>
<style scoped></style>

View File

@ -0,0 +1,8 @@
export enum CacheTabTypeEnum {
API_TEST_API_TABLE = 'API_TEST_API_TABLE', // 接口测试-定义-API列表
API_TEST_CASE_TABLE = 'API_TEST_CASE_TABLE', // 接口测试-定义-CASE列表
API_TEST_MOCK_TABLE = 'API_TEST_MOCK_TABLE', // 接口测试-定义-MOCK列表
API_SCENARIO_TABLE = 'API_SCENARIO_TABLE', // 接口测试-场景-场景列表
}
export default {};

View File

@ -10,21 +10,64 @@
]"
>
<!-- TODO 实验性组件以后优化 -->
<Suspense v-if="!route.meta.isCache">
<!-- <Suspense v-if="!route.meta.isCache">
<component :is="Component" :key="route.fullPath" />
</Suspense> -->
<Suspense>
<keep-alive :include="cacheStore.cacheViews">
<component :is="Component" :key="route.fullPath" />
</keep-alive>
</Suspense>
<keep-alive v-else>
<component :is="Component" :key="route.fullPath" />
</keep-alive>
</div>
</transition>
</router-view>
</template>
<script lang="ts" setup>
import { useRoute, useRouter } from 'vue-router';
import useCacheStore from '@/store/modules/cache/cache';
import useLicenseStore from '@/store/modules/setting/license';
const licenseStore = useLicenseStore();
const cacheStore = useCacheStore();
const router = useRouter();
const route = useRoute();
watch(
() => route.name,
(newName) => {
const cachePath = cacheStore.cachePath.find((item) => item.cacheName === newName);
if (cachePath && cachePath.type === 'ROUTE' && !cacheStore.cacheViews.includes(newName as string)) {
cacheStore.setCache(cachePath.cacheName);
}
}
);
const handleRouteLeave = (to: any, from: any) => {
if (to.name === from.name) {
return;
}
// TABTAB
const isRemoveTab = cacheStore.cachePath.find(
(item) => item.type === 'TAB' && cacheStore.cacheViews.includes(item.cacheName)
);
if (isRemoveTab) {
cacheStore.removeCache(isRemoveTab.cacheName);
return;
}
//
const namesToRemove = cacheStore.cacheViews.filter((name) => {
const cachePath = cacheStore.cachePath.find((item) => item.cacheName === name);
return cachePath && !(cachePath.toPathName || []).includes(to.name);
});
namesToRemove.forEach((name) => cacheStore.removeCache(name));
};
router.afterEach(handleRouteLeave);
</script>
<style lang="less" scoped>

View File

@ -0,0 +1,102 @@
import { defineStore } from 'pinia';
import { CacheTabTypeEnum } from '@/enums/cacheTabEnum';
import { RouteEnum } from '@/enums/routeEnum';
export interface CachePath {
cacheName: string; // 缓存名称
toPathName?: string[]; // 跳转不被清空缓存的下一级
type?: string;
}
const useCacheStore = defineStore('cache', {
state: (): { cachePath: CachePath[]; cacheViews: string[] } => ({
cachePath: [
// 功能用例
{
cacheName: RouteEnum.CASE_MANAGEMENT_CASE,
toPathName: [RouteEnum.CASE_MANAGEMENT_CASE_DETAIL, RouteEnum.CASE_MANAGEMENT_CASE_CREATE_SUCCESS],
type: 'ROUTE',
},
// 用例评审
{
cacheName: RouteEnum.CASE_MANAGEMENT_REVIEW,
toPathName: [
RouteEnum.CASE_MANAGEMENT_REVIEW_CREATE,
RouteEnum.CASE_MANAGEMENT_REVIEW_DETAIL,
RouteEnum.CASE_MANAGEMENT_REVIEW_DETAIL_CASE_DETAIL,
],
type: 'ROUTE',
},
// 用例评审详情
{
cacheName: RouteEnum.CASE_MANAGEMENT_REVIEW_DETAIL,
toPathName: [RouteEnum.CASE_MANAGEMENT_REVIEW_DETAIL_CASE_DETAIL],
type: 'ROUTE',
},
// 缺陷管理
{
cacheName: RouteEnum.BUG_MANAGEMENT_INDEX,
toPathName: [RouteEnum.BUG_MANAGEMENT_DETAIL, RouteEnum.BUG_MANAGEMENT_CREATE_SUCCESS],
type: 'ROUTE',
},
// 测试计划首页
{
cacheName: RouteEnum.TEST_PLAN_INDEX,
toPathName: [RouteEnum.TEST_PLAN_INDEX_DETAIL, RouteEnum.TEST_PLAN_INDEX_DETAIL_FEATURE_CASE_DETAIL],
type: 'ROUTE',
},
// 测试计划详情
{
cacheName: RouteEnum.TEST_PLAN_INDEX_DETAIL,
toPathName: [RouteEnum.TEST_PLAN_INDEX_DETAIL_FEATURE_CASE_DETAIL],
type: 'ROUTE',
},
// 测试计划报告
{
cacheName: RouteEnum.TEST_PLAN_REPORT,
toPathName: [RouteEnum.TEST_PLAN_REPORT_DETAIL],
type: 'ROUTE',
},
// 接口测试-定义-API
{
cacheName: CacheTabTypeEnum.API_TEST_API_TABLE,
type: 'TAB',
},
// 接口测试-定义-CASE
{
cacheName: CacheTabTypeEnum.API_TEST_CASE_TABLE,
type: 'TAB',
},
// 接口测试-定义-MOCK
{
cacheName: CacheTabTypeEnum.API_TEST_MOCK_TABLE,
type: 'TAB',
},
// 接口测试-场景列表
{
cacheName: CacheTabTypeEnum.API_SCENARIO_TABLE,
type: 'TAB',
},
],
cacheViews: [], // 缓存列表
}),
actions: {
// 设置缓存
setCache(name: string) {
this.cacheViews.push(name);
},
// 移除缓存
removeCache(name: string) {
if (this.cacheViews.includes(name)) {
this.cacheViews = this.cacheViews.filter((item) => item !== name);
}
},
// 清空缓存
clearCache() {
this.cacheViews = [];
},
},
});
export default useCacheStore;

View File

@ -287,6 +287,7 @@
import useModal from '@/hooks/useModal';
import useTableStore from '@/hooks/useTableStore';
import useAppStore from '@/store/modules/app';
import useCacheStore from '@/store/modules/cache/cache';
import { characterLimit, downloadByteFile, operationWidth } from '@/utils';
import { hasAnyPermission } from '@/utils/permission';
@ -294,9 +295,15 @@
import { ApiDefinitionDetail, ApiDefinitionGetModuleParams } from '@/models/apiTest/management';
import { DragSortParams } from '@/models/common';
import { RequestDefinitionStatus, RequestMethods } from '@/enums/apiEnum';
import { CacheTabTypeEnum } from '@/enums/cacheTabEnum';
import { TableKeyEnum } from '@/enums/tableEnum';
import { FilterRemoteMethodsEnum, FilterSlotNameEnum } from '@/enums/tableFilterEnum';
const cacheStore = useCacheStore();
defineOptions({
name: CacheTabTypeEnum.API_TEST_API_TABLE,
});
const props = defineProps<{
class?: string;
activeModule: string;
@ -664,11 +671,27 @@
}
}
onBeforeMount(() => {
function onMountedLoad() {
initProtocolList();
if (props.selectedProtocols.length > 0) {
loadApiList(true);
}
}
const isActivated = computed(() => cacheStore.cacheViews.includes(CacheTabTypeEnum.API_TEST_API_TABLE));
onBeforeMount(() => {
cacheStore.clearCache();
if (!isActivated.value) {
onMountedLoad();
cacheStore.setCache(CacheTabTypeEnum.API_TEST_API_TABLE);
}
});
onActivated(() => {
if (isActivated.value) {
onMountedLoad();
}
});
const tableSelected = ref<(string | number)[]>([]);

View File

@ -1,7 +1,9 @@
<template>
<div class="flex flex-1 flex-col overflow-hidden">
<div v-if="activeApiTab.id === 'all' && currentTab === 'api'" class="flex-1 pt-[8px]">
<keep-alive :include="cacheStore.cacheViews">
<apiTable
v-if="activeApiTab.id === 'all' && currentTab === 'api'"
class="flex-1 pt-[8px]"
:active-module="props.activeModule"
:offspring-ids="props.offspringIds"
:selected-protocols="props.selectedProtocols"
@ -13,8 +15,8 @@
@import="() => emit('import')"
@open-edit-api-tab="openApiTab"
/>
</div>
<div v-else-if="activeApiTab.id !== 'all'" class="flex-1 overflow-hidden">
</keep-alive>
<div v-if="activeApiTab.id !== 'all'" class="flex-1 overflow-hidden">
<div class="mt-[8px] flex items-center justify-between px-[16px]">
<MsTab
v-model:activeKey="activeApiTab.definitionActiveKey"
@ -130,6 +132,7 @@
import { useI18n } from '@/hooks/useI18n';
import useModal from '@/hooks/useModal';
import useAppStore from '@/store/modules/app';
import useCacheStore from '@/store/modules/cache/cache';
import useUserStore from '@/store/modules/user';
import { hasAnyPermission } from '@/utils/permission';
@ -158,6 +161,9 @@
} from '@/views/api-test/components/config';
import type { RequestParam } from '@/views/api-test/components/requestComposition/index.vue';
import { parseRequestBodyFiles } from '@/views/api-test/components/utils';
const cacheStore = useCacheStore();
// requestComposition
const requestComposition = defineAsyncComponent(
() => import('@/views/api-test/components/requestComposition/index.vue')

View File

@ -360,6 +360,7 @@
import useModal from '@/hooks/useModal';
import useTableStore from '@/hooks/useTableStore';
import useAppStore from '@/store/modules/app';
import useCacheStore from '@/store/modules/cache/cache';
import { characterLimit, operationWidth } from '@/utils';
import { hasAnyPermission } from '@/utils/permission';
@ -367,6 +368,7 @@
import { ApiCaseDetail } from '@/models/apiTest/management';
import { DragSortParams } from '@/models/common';
import { RequestCaseStatus } from '@/enums/apiEnum';
import { CacheTabTypeEnum } from '@/enums/cacheTabEnum';
import { ReportEnum, ReportStatus } from '@/enums/reportEnum';
import { TableKeyEnum } from '@/enums/tableEnum';
import { FilterRemoteMethodsEnum, FilterSlotNameEnum } from '@/enums/tableFilterEnum';
@ -375,6 +377,9 @@
import type { RequestParam } from '@/views/api-test/components/requestComposition/index.vue';
import { parseRequestBodyFiles } from '@/views/api-test/components/utils';
defineOptions({
name: CacheTabTypeEnum.API_TEST_CASE_TABLE,
});
const props = defineProps<{
isApi: boolean; // case tab
activeModule: string;
@ -384,6 +389,7 @@
memberOptions: { label: string; value: string }[];
heightUsed?: number;
}>();
const cacheStore = useCacheStore();
const caseExecute = ref(false);
@ -658,8 +664,20 @@
loadCaseList();
}
const isActivated = computed(() => cacheStore.cacheViews.includes(CacheTabTypeEnum.API_TEST_CASE_TABLE));
onBeforeMount(() => {
loadCaseList();
cacheStore.clearCache();
if (!isActivated.value) {
loadCaseList();
cacheStore.setCache(CacheTabTypeEnum.API_TEST_CASE_TABLE);
}
});
onActivated(() => {
if (isActivated.value) {
loadCaseList();
}
});
watch(

View File

@ -1,17 +1,24 @@
<template>
<div class="flex flex-1 flex-col overflow-hidden">
<div v-if="activeApiTab.id === 'all' && currentTab === 'case'" class="flex-1 overflow-hidden">
<caseTable
ref="caseTableRef"
:offspring-ids="props.offspringIds"
:is-api="false"
:active-module="props.activeModule"
:selected-protocols="props.selectedProtocols"
:member-options="memberOptions"
@open-case-tab="openCaseTab"
@open-case-tab-and-execute="openCaseTabAndExecute"
/>
</div>
<keep-alive :include="cacheStore.cacheViews">
<MsCacheWrapper
v-if="activeApiTab.id === 'all' && currentTab === 'case'"
class="flex-1 overflow-hidden"
:cache-name="CacheTabTypeEnum.API_TEST_CASE_TABLE"
>
<caseTable
ref="caseTableRef"
key="API_TEST_CASE_TABLE"
:offspring-ids="props.offspringIds"
:is-api="false"
:active-module="props.activeModule"
:selected-protocols="props.selectedProtocols"
:member-options="memberOptions"
@open-case-tab="openCaseTab"
@open-case-tab-and-execute="openCaseTabAndExecute"
/>
</MsCacheWrapper>
</keep-alive>
<div v-if="activeApiTab.id !== 'all'" class="flex-1 overflow-hidden">
<caseDetail
v-model:execute-case="caseExecute"
@ -29,19 +36,23 @@
import { useRoute } from 'vue-router';
import { cloneDeep } from 'lodash-es';
import MsCacheWrapper from '@/components/pure/ms-cache-wrapper/index.vue';
import { TabItem } from '@/components/pure/ms-editable-tab/types';
import caseTable from './caseTable.vue';
import { getCaseDetail } from '@/api/modules/api-test/management';
import useCacheStore from '@/store/modules/cache/cache';
import { ApiCaseDetail } from '@/models/apiTest/management';
import { ModuleTreeNode } from '@/models/common';
import { CacheTabTypeEnum } from '@/enums/cacheTabEnum';
import type { RequestParam } from '@/views/api-test/components/requestComposition/index.vue';
import { parseRequestBodyFiles } from '@/views/api-test/components/utils';
//
const caseDetail = defineAsyncComponent(() => import('./caseDetail.vue'));
const cacheStore = useCacheStore();
const props = defineProps<{
activeModule: string;

View File

@ -70,14 +70,17 @@
:member-options="memberOptions"
@delete-case="(id) => handleDeleteApiFromModuleTree(id)"
/>
<MockTable
v-if="activeApiTab.id === 'all' && currentTab === 'mock'"
:active-module="props.activeModule"
:offspring-ids="props.offspringIds"
:selected-protocols="props.selectedProtocols"
:definition-detail="activeApiTab"
@debug="handleMockDebug"
/>
<keep-alive :include="cacheStore.cacheViews">
<MockTable
v-if="activeApiTab.id === 'all' && currentTab === 'mock'"
:key="CacheTabTypeEnum.API_TEST_MOCK_TABLE"
:active-module="props.activeModule"
:offspring-ids="props.offspringIds"
:selected-protocols="props.selectedProtocols"
:definition-detail="activeApiTab"
@debug="handleMockDebug"
/>
</keep-alive>
</template>
<script setup lang="ts">
@ -98,6 +101,7 @@
import useLeaveTabUnSaveCheck from '@/hooks/useLeaveTabUnSaveCheck';
import useRequestCompositionStore from '@/store/modules/api/requestComposition';
import useAppStore from '@/store/modules/app';
import useCacheStore from '@/store/modules/cache/cache';
import { hasAnyPermission } from '@/utils/permission';
import { ProtocolItem } from '@/models/apiTest/common';
@ -111,6 +115,7 @@
RequestMethods,
ResponseComposition,
} from '@/enums/apiEnum';
import { CacheTabTypeEnum } from '@/enums/cacheTabEnum';
import { defaultBodyParams, defaultResponse, defaultResponseItem } from '@/views/api-test/components/config';
@ -131,6 +136,7 @@
const route = useRoute();
const { t } = useI18n();
const requestCompositionStore = useRequestCompositionStore();
const cacheStore = useCacheStore();
const setActiveApi: ((params: RequestParam) => void) | undefined = inject('setActiveApi');
const memberOptions = ref<{ label: string; value: string }[]>([]);

View File

@ -229,14 +229,19 @@
import useModal from '@/hooks/useModal';
import useTableStore from '@/hooks/useTableStore';
import useAppStore from '@/store/modules/app';
import useCacheStore from '@/store/modules/cache/cache';
import { characterLimit, operationWidth } from '@/utils';
import { hasAnyPermission } from '@/utils/permission';
import { ApiDefinitionMockDetail } from '@/models/apiTest/management';
import { MockDetail } from '@/models/apiTest/mock';
import { RequestComposition } from '@/enums/apiEnum';
import { CacheTabTypeEnum } from '@/enums/cacheTabEnum';
import { TableKeyEnum } from '@/enums/tableEnum';
defineOptions({
name: CacheTabTypeEnum.API_TEST_MOCK_TABLE,
});
const props = defineProps<{
isApi?: boolean; // case tab
class?: string;
@ -254,6 +259,7 @@
}>();
const appStore = useAppStore();
const cacheStore = useCacheStore();
const tableStore = useTableStore();
const { t } = useI18n();
const { openModal } = useModal();
@ -430,6 +436,22 @@
{ immediate: true }
);
const isActivated = computed(() => cacheStore.cacheViews.includes(CacheTabTypeEnum.API_TEST_MOCK_TABLE));
onBeforeMount(() => {
cacheStore.clearCache();
if (!isActivated.value) {
loadMockList();
cacheStore.setCache(CacheTabTypeEnum.API_TEST_MOCK_TABLE);
}
});
onActivated(() => {
if (isActivated.value) {
loadMockList();
}
});
async function handleBeforeEnableChange(record: ApiDefinitionMockDetail) {
try {
await updateMockStatusPage(record.id);

View File

@ -525,6 +525,7 @@
import useModal from '@/hooks/useModal';
import useTableStore from '@/hooks/useTableStore';
import useAppStore from '@/store/modules/app';
import useCacheStore from '@/store/modules/cache/cache';
import { characterLimit, operationWidth } from '@/utils';
import { translateTextToPX } from '@/utils/css';
import { hasAnyPermission } from '@/utils/permission';
@ -540,6 +541,7 @@
import { DragSortParams } from '@/models/common';
import { ResourcePoolItem } from '@/models/setting/resourcePool';
import { ApiScenarioStatus } from '@/enums/apiEnum';
import { CacheTabTypeEnum } from '@/enums/cacheTabEnum';
import { ReportEnum, ReportStatus } from '@/enums/reportEnum';
import { TableKeyEnum } from '@/enums/tableEnum';
import { FilterRemoteMethodsEnum, FilterSlotNameEnum } from '@/enums/tableFilterEnum';
@ -560,6 +562,8 @@
const memberOptions = ref<{ label: string; value: string }[]>([]);
const appStore = useAppStore();
const cacheStore = useCacheStore();
const { t } = useI18n();
const { openModal } = useModal();
const tableRecord = ref<ApiScenarioTableItem>();
@ -1433,9 +1437,22 @@
}
}
const isActivated = computed(() => cacheStore.cacheViews.includes(CacheTabTypeEnum.API_SCENARIO_TABLE));
onBeforeMount(() => {
loadScenarioList();
cacheStore.clearCache();
if (!isActivated.value) {
loadScenarioList();
cacheStore.setCache(CacheTabTypeEnum.API_SCENARIO_TABLE);
}
});
onActivated(() => {
if (isActivated.value) {
loadScenarioList();
}
});
watch(
() => props.activeModule,
() => {

View File

@ -65,17 +65,24 @@
</div>
</div>
<a-divider class="!my-0" />
<div v-if="activeScenarioTab.id === 'all'" class="pageWrap overflow-x-hidden">
<ScenarioTable
ref="apiTableRef"
:active-module="activeModule"
:offspring-ids="offspringIds"
@refresh-module-tree="refreshTree"
@open-scenario="openScenarioTab"
@create-scenario="() => newTab()"
/>
</div>
<div v-else-if="activeScenarioTab.isNew" class="pageWrap">
<keep-alive :include="cacheStore.cacheViews">
<MsCacheWrapper
v-if="activeScenarioTab.id === 'all'"
:key="CacheTabTypeEnum.API_SCENARIO_TABLE"
class="pageWrap overflow-x-hidden"
:cache-name="CacheTabTypeEnum.API_SCENARIO_TABLE"
>
<ScenarioTable
ref="apiTableRef"
:active-module="activeModule"
:offspring-ids="offspringIds"
@refresh-module-tree="refreshTree"
@open-scenario="openScenarioTab"
@create-scenario="() => newTab()"
/>
</MsCacheWrapper>
</keep-alive>
<div v-if="activeScenarioTab.isNew && activeScenarioTab.id !== 'all'" class="pageWrap">
<create
ref="createRef"
v-model:scenario="activeScenarioTab"
@ -83,7 +90,7 @@
@batch-debug="realExecute($event, false)"
></create>
</div>
<div v-else class="pageWrap">
<div v-if="!activeScenarioTab.isNew && activeScenarioTab.id !== 'all'" class="pageWrap">
<detail
ref="detailRef"
v-model:scenario="activeScenarioTab"
@ -106,6 +113,7 @@
import { cloneDeep } from 'lodash-es';
import dayjs from 'dayjs';
import MsCacheWrapper from '@/components/pure/ms-cache-wrapper/index.vue';
import MsCard from '@/components/pure/ms-card/index.vue';
import MsEditableTab from '@/components/pure/ms-editable-tab/index.vue';
import { TabItem } from '@/components/pure/ms-editable-tab/types';
@ -130,6 +138,7 @@
import useLeaveTabUnSaveCheck from '@/hooks/useLeaveTabUnSaveCheck';
import router from '@/router';
import useAppStore from '@/store/modules/app';
import useCacheStore from '@/store/modules/cache/cache';
import { filterTree, getGenerateId, mapTree } from '@/utils';
import { hasAnyPermission } from '@/utils/permission';
@ -144,6 +153,7 @@
} from '@/models/apiTest/scenario';
import { ModuleTreeNode } from '@/models/common';
import { ScenarioExecuteStatus, ScenarioStepRefType, ScenarioStepType } from '@/enums/apiEnum';
import { CacheTabTypeEnum } from '@/enums/cacheTabEnum';
import { ApiTestRouteEnum } from '@/enums/routeEnum';
import { defaultCsvParamItem, defaultNormalParamItem, defaultScenario } from './components/config';
@ -162,6 +172,8 @@
const route = useRoute();
const appStore = useAppStore();
const cacheStore = useCacheStore();
const { t } = useI18n();
const scenarioTabs = ref<ScenarioParams[]>([

View File

@ -194,6 +194,7 @@
import useModal from '@/hooks/useModal';
import router from '@/router';
import { useAppStore, useTableStore } from '@/store';
import useCacheStore from '@/store/modules/cache/cache';
import { customFieldDataToTableData, customFieldToColumns, downloadByteFile } from '@/utils';
import { hasAnyPermission } from '@/utils/permission';
@ -203,6 +204,9 @@
import { makeColumns } from '@/views/case-management/caseManagementFeature/components/utils';
defineOptions({
name: RouteEnum.BUG_MANAGEMENT_INDEX,
});
const { t } = useI18n();
const MsExportDrawer = defineAsyncComponent(() => import('@/components/pure/ms-export-drawer/index.vue'));
const DeleteModal = defineAsyncComponent(() => import('./components/deleteModal.vue'));
@ -231,6 +235,7 @@
const { openDeleteModal } = useModal();
const route = useRoute();
const severityFilterOptions = ref<BugOptionItem[]>([]);
const cacheStore = useCacheStore();
//
const isComplete = ref(false);
@ -801,7 +806,7 @@
await initFilterOptions();
await tableStore.initColumn(TableKeyEnum.BUG_MANAGEMENT, columns.concat(customColumns), 'drawer');
onMounted(() => {
function mountedLoad() {
setLoadListParams({ projectId: projectId.value });
setCurrentPlatform();
setExportOptionData();
@ -810,6 +815,19 @@
//
handleShowDetail(route.query.id as string, -1);
}
}
const isActivated = computed(() => cacheStore.cacheViews.includes(RouteEnum.BUG_MANAGEMENT_INDEX));
onMounted(() => {
if (!isActivated.value) {
mountedLoad();
}
});
onActivated(() => {
if (isActivated.value) {
mountedLoad();
}
});
onBeforeUnmount(() => {

View File

@ -415,6 +415,7 @@
import { useI18n } from '@/hooks/useI18n';
import useModal from '@/hooks/useModal';
import { useAppStore, useTableStore } from '@/store';
import useCacheStore from '@/store/modules/cache/cache';
import useFeatureCaseStore from '@/store/modules/case/featureCase';
import useMinderStore from '@/store/modules/components/minder-editor';
import {
@ -437,13 +438,15 @@
DragCase,
} from '@/models/caseManagement/featureCase';
import { ModuleTreeNode } from '@/models/common';
import { CaseManagementRouteEnum } from '@/enums/routeEnum';
import { CaseManagementRouteEnum, RouteEnum } from '@/enums/routeEnum';
import { ColumnEditTypeEnum, TableKeyEnum } from '@/enums/tableEnum';
import { FilterRemoteMethodsEnum, FilterSlotNameEnum } from '@/enums/tableFilterEnum';
import { executionResultMap, getCaseLevels, getTableFields, statusIconMap } from './utils';
import { LabelValue } from '@arco-design/web-vue/es/tree-select/interface';
const cacheStore = useCacheStore();
const MsExportDrawer = defineAsyncComponent(() => import('@/components/pure/ms-export-drawer/index.vue'));
const { openModal } = useModal();
@ -1745,8 +1748,6 @@
}
}
const statusFilterVisible = ref(false);
//
onBeforeMount(async () => {
try {
@ -1769,14 +1770,14 @@
emitTableParams();
}
onMounted(async () => {
async function mountedLoad() {
if (route.query.id) {
showCaseDetail(route.query.id as string, -1);
}
await initFilter();
initData();
getCaseExportData();
});
}
watch(
() => showType.value,
@ -1797,10 +1798,24 @@
}
);
const isActivated = computed(() => cacheStore.cacheViews.includes(RouteEnum.CASE_MANAGEMENT_CASE));
onBeforeUnmount(() => {
showDetailDrawer.value = false;
});
onMounted(() => {
if (!isActivated.value) {
mountedLoad();
}
});
onActivated(() => {
if (isActivated.value) {
mountedLoad();
}
});
defineExpose({
emitTableParams,
initData,

View File

@ -122,6 +122,10 @@
import Message from '@arco-design/web-vue/es/message';
defineOptions({
name: CaseManagementRouteEnum.CASE_MANAGEMENT_CASE,
});
const route = useRoute();
const router = useRouter();

View File

@ -366,6 +366,7 @@
import useModal from '@/hooks/useModal';
import useTableStore from '@/hooks/useTableStore';
import useAppStore from '@/store/modules/app';
import useCacheStore from '@/store/modules/cache/cache';
import useCaseReviewStore from '@/store/modules/case/caseReview';
import useUserStore from '@/store/modules/user';
import { characterLimit, findNodeByKey } from '@/utils';
@ -396,6 +397,7 @@
const router = useRouter();
const route = useRoute();
const cacheStore = useCacheStore();
const appStore = useAppStore();
const userStore = useUserStore();
@ -608,13 +610,27 @@
loadList();
getModuleCount();
}
const isActivated = computed(() =>
cacheStore.cacheViews.includes(CaseManagementRouteEnum.CASE_MANAGEMENT_REVIEW_DETAIL)
);
const reviewerTitlePopupVisible = ref(true);
onBeforeMount(() => {
function loadReviewCase() {
searchCase();
setTimeout(() => {
reviewerTitlePopupVisible.value = false;
}, 5000);
}
onBeforeMount(() => {
if (!isActivated.value) {
loadReviewCase();
}
});
onActivated(() => {
if (isActivated.value) {
loadReviewCase();
}
});
/**
@ -1032,7 +1048,7 @@
});
}
onBeforeMount(async () => {
async function mountedLoad() {
const [, memberRes] = await Promise.all([
initReviewers(),
getProjectMemberCommentOptions(appStore.currentProjectId, keyword.value),
@ -1080,6 +1096,18 @@
},
},
];
}
onBeforeMount(() => {
if (!isActivated.value) {
mountedLoad();
}
});
onActivated(() => {
if (isActivated.value) {
mountedLoad();
}
});
defineExpose({

View File

@ -198,6 +198,7 @@
import useModal from '@/hooks/useModal';
import useTableStore from '@/hooks/useTableStore';
import useAppStore from '@/store/modules/app';
import useCacheStore from '@/store/modules/cache/cache';
import useUserStore from '@/store/modules/user';
import { hasAllPermission, hasAnyPermission } from '@/utils/permission';
@ -232,6 +233,8 @@
}>();
const userStore = useUserStore();
const appStore = useAppStore();
const cacheStore = useCacheStore();
const router = useRouter();
const { t } = useI18n();
const { openModal } = useModal();
@ -254,8 +257,9 @@
};
});
});
const isActivated = computed(() => cacheStore.cacheViews.includes(CaseManagementRouteEnum.CASE_MANAGEMENT_REVIEW));
onBeforeMount(async () => {
async function mountedLoad() {
try {
const [userRes, memberRes] = await Promise.all([
getReviewUsers(appStore.currentProjectId, keyword.value),
@ -384,7 +388,7 @@
// eslint-disable-next-line no-console
console.log(error);
}
});
}
const hasOperationPermission = computed(() =>
hasAnyPermission(['CASE_REVIEW:READ+UPDATE', 'CASE_REVIEW:READ+DELETE'])
@ -573,10 +577,6 @@
});
}
onBeforeMount(() => {
searchReview();
});
watch(
() => innerShowType.value,
() => {
@ -769,6 +769,20 @@
});
}
onBeforeMount(() => {
if (!isActivated.value) {
mountedLoad();
searchReview();
}
});
onActivated(() => {
if (isActivated.value) {
mountedLoad();
searchReview();
}
});
defineExpose({
searchReview,
});

View File

@ -174,6 +174,9 @@
import { ModuleTreeNode } from '@/models/common';
import { CaseManagementRouteEnum } from '@/enums/routeEnum';
defineOptions({
name: CaseManagementRouteEnum.CASE_MANAGEMENT_REVIEW_DETAIL,
});
const router = useRouter();
const route = useRoute();
const userStore = useUserStore();

View File

@ -49,6 +49,9 @@
import { ModuleTreeNode } from '@/models/common';
import { CaseManagementRouteEnum } from '@/enums/routeEnum';
defineOptions({
name: CaseManagementRouteEnum.CASE_MANAGEMENT_REVIEW,
});
const router = useRouter();
type ShowType = 'all' | 'reviewByMe' | 'createByMe';

View File

@ -111,6 +111,7 @@
import useModal from '@/hooks/useModal';
import { useTableStore } from '@/store';
import useAppStore from '@/store/modules/app';
import useCacheStore from '@/store/modules/cache/cache';
import { characterLimit } from '@/utils';
import { hasAnyPermission } from '@/utils/permission';
@ -125,6 +126,8 @@
const appStore = useAppStore();
const tableStore = useTableStore();
const cacheStore = useCacheStore();
const { t } = useI18n();
const keyword = ref<string>('');
const router = useRouter();
@ -436,6 +439,7 @@
},
});
}
const isActivated = computed(() => cacheStore.cacheViews.includes(TestPlanRouteEnum.TEST_PLAN_REPORT));
onBeforeMount(() => {
if (route.query.id) {
@ -443,6 +447,15 @@
}
initData();
});
onActivated(() => {
if (isActivated.value) {
if (route.query.id) {
showReportDetail(route.query.id as string, route.query.type === 'GROUP');
}
initData();
}
});
</script>
<style lang="less" scoped>

View File

@ -5,9 +5,15 @@
</MsCard>
</template>
<script setup lang="ts">
<script setup lang="ts" name="testPlanReport">
import MsCard from '@/components/pure/ms-card/index.vue';
import ReportList from './component/reportList.vue';
import { RouteEnum } from '@/enums/routeEnum';
defineOptions({
name: RouteEnum.TEST_PLAN_REPORT,
});
</script>
<style scoped lang="less">

View File

@ -414,6 +414,7 @@
import { useI18n } from '@/hooks/useI18n';
import useModal from '@/hooks/useModal';
import { useAppStore, useTableStore } from '@/store';
import useCacheStore from '@/store/modules/cache/cache';
import { characterLimit } from '@/utils';
import { hasAnyPermission } from '@/utils/permission';
@ -429,7 +430,7 @@
TestPlanItem,
} from '@/models/testPlan/testPlan';
import { LastExecuteResults } from '@/enums/caseEnum';
import { TestPlanRouteEnum } from '@/enums/routeEnum';
import { RouteEnum, TestPlanRouteEnum } from '@/enums/routeEnum';
import { ColumnEditTypeEnum, TableKeyEnum } from '@/enums/tableEnum';
import { FilterSlotNameEnum } from '@/enums/tableFilterEnum';
import { testPlanTypeEnum } from '@/enums/testPlanEnum';
@ -437,6 +438,8 @@
import { planStatusOptions } from '../config';
import { getModules } from '@/views/case-management/caseManagementFeature/components/utils';
const cacheStore = useCacheStore();
const tableStore = useTableStore();
const appStore = useAppStore();
const router = useRouter();
@ -1505,10 +1508,6 @@
}
);
onBeforeMount(() => {
fetchData();
});
const planData = computed(() => {
return propsRes.value.data;
});
@ -1606,6 +1605,20 @@
fetchData();
}
const isActivated = computed(() => cacheStore.cacheViews.includes(RouteEnum.TEST_PLAN_INDEX));
onBeforeMount(() => {
if (!isActivated.value) {
fetchData();
}
});
onActivated(() => {
if (isActivated.value) {
fetchData();
}
});
defineExpose({
fetchData,
emitTableParams,

View File

@ -290,6 +290,8 @@
const hasOperationPermission = computed(
() => hasAnyPermission(['PROJECT_TEST_PLAN:READ+EXECUTE', 'PROJECT_TEST_PLAN:READ+ASSOCIATION']) && props.canEdit
);
const isActivated = inject<Ref<boolean>>('isActivated', ref(false));
const columns = computed<MsTableColumn>(() => [
{
title: 'ID',
@ -591,6 +593,12 @@
loadCaseList();
});
onActivated(() => {
if (isActivated.value) {
loadCaseList();
}
});
const modulesCount = computed(() => testPlanFeatureCaseStore.modulesCount);
async function getModuleCount() {

View File

@ -220,7 +220,7 @@
<EditCaseDetailDrawer v-model:visible="editCaseVisible" :case-id="activeCaseId" @load-case="loadCase" />
<LinkDefectDrawer
v-model:visible="showLinkDrawer"
:case-id="activeCaseId"
:case-id="activeId"
:drawer-loading="drawerLoading"
:show-selector-all="false"
:load-api="AssociatedBugApiTypeEnum.TEST_PLAN_BUG_LIST"

View File

@ -174,6 +174,7 @@
import { useI18n } from '@/hooks/useI18n';
import useModal from '@/hooks/useModal';
import useAppStore from '@/store/modules/app';
import useCacheStore from '@/store/modules/cache/cache';
import useMinderStore from '@/store/modules/components/minder-editor';
import useUserStore from '@/store/modules/user';
import { characterLimit } from '@/utils';
@ -184,6 +185,11 @@
import { TestPlanRouteEnum } from '@/enums/routeEnum';
import { testPlanTypeEnum } from '@/enums/testPlanEnum';
defineOptions({
name: TestPlanRouteEnum.TEST_PLAN_INDEX_DETAIL,
});
const cacheStore = useCacheStore();
const userStore = useUserStore();
const appStore = useAppStore();
const { openModal } = useModal();
@ -562,13 +568,28 @@
}
}
);
const isActivated = computed(() => cacheStore.cacheViews.includes(TestPlanRouteEnum.TEST_PLAN_INDEX_DETAIL));
provide('isActivated', isActivated);
onBeforeMount(() => {
if (route.query.type === 'featureCase') {
activeTab.value = 'featureCase';
if (!isActivated.value) {
if (route.query.type === 'featureCase') {
activeTab.value = 'featureCase';
}
initDetail();
initPlanTree();
}
});
onActivated(() => {
if (isActivated.value) {
if (route.query.type === 'featureCase') {
activeTab.value = 'featureCase';
}
initDetail();
initPlanTree();
}
initDetail();
initPlanTree();
});
</script>

View File

@ -135,10 +135,15 @@
import type { CreateOrUpdateModule } from '@/models/caseManagement/featureCase';
import { ModuleTreeNode, TableQueryParams } from '@/models/common';
import type { TestPlanItem } from '@/models/testPlan/testPlan';
import { RouteEnum } from '@/enums/routeEnum';
import { testPlanTypeEnum } from '@/enums/testPlanEnum';
import Message from '@arco-design/web-vue/es/message';
defineOptions({
name: RouteEnum.TEST_PLAN_INDEX,
});
const appStore = useAppStore();
const { t } = useI18n();
const currentProjectId = computed(() => appStore.currentProjectId);