From ca069cb570cb2fdc43456e8008e9749006257b6b Mon Sep 17 00:00:00 2001 From: Marvin Zhang Date: Wed, 11 Jun 2025 18:04:51 +0800 Subject: [PATCH] feat: implement navigation list management in store and detail layout --- .../src/interfaces/store/index.d.ts | 4 ++ .../layouts/content/detail/DetailLayout.vue | 15 ++-- .../src/layouts/content/detail/useDetail.ts | 23 +++++-- frontend/crawlab-ui/src/utils/store.ts | 69 +++++++------------ 4 files changed, 57 insertions(+), 54 deletions(-) diff --git a/frontend/crawlab-ui/src/interfaces/store/index.d.ts b/frontend/crawlab-ui/src/interfaces/store/index.d.ts index 78e733aa..cd6bb0fd 100644 --- a/frontend/crawlab-ui/src/interfaces/store/index.d.ts +++ b/frontend/crawlab-ui/src/interfaces/store/index.d.ts @@ -85,6 +85,7 @@ export declare global { actionsCollapsed: boolean; tabs: NavItem[]; disabledTabKeys: string[]; + navList: T[]; afterSave: (() => Promise)[]; } @@ -130,6 +131,8 @@ export declare global { setTabs: StoreMutation; setDisabledTabKeys: StoreMutation; resetDisabledTabKeys: StoreMutation; + setNavList: StoreMutation, T[]>; + resetNavList: StoreMutation>; setAfterSave: StoreMutation, (() => Promise)[]>; } @@ -144,6 +147,7 @@ export declare global { createList: StoreAction, T[]>; updateList: StoreAction, BatchRequestPayloadWithData>; deleteList: StoreAction, BatchRequestPayload>; + getNavList: StoreAction, string>; } type StoreActionContext< diff --git a/frontend/crawlab-ui/src/layouts/content/detail/DetailLayout.vue b/frontend/crawlab-ui/src/layouts/content/detail/DetailLayout.vue index a586ad6a..31e08b49 100644 --- a/frontend/crawlab-ui/src/layouts/content/detail/DetailLayout.vue +++ b/frontend/crawlab-ui/src/layouts/content/detail/DetailLayout.vue @@ -26,6 +26,7 @@ const { activeTabName, getForm, navLoading, + navItems, onNavSelect, onNavTabsSelect, onBack, @@ -37,13 +38,17 @@ const computedTabs = computed(() => tabs.value.map((tab: NavItem) => ({ ...tab })) ); -// get form before mount +// Fetch the form data when the component is mounted onBeforeMount(getForm); +// Fetch navigation list before mounting the component +onBeforeMount(() => store.dispatch(`${ns.value}/getNavList`)); + // reset form before unmount onBeforeUnmount(() => { if (!activeTabName.value) { store.commit(`${ns.value}/resetForm`); + store.commit(`${ns.value}/resetNavList`); } }); @@ -70,10 +75,10 @@ defineOptions({ name: 'ClDetailLayout' }); @change="onNavSelect" > diff --git a/frontend/crawlab-ui/src/layouts/content/detail/useDetail.ts b/frontend/crawlab-ui/src/layouts/content/detail/useDetail.ts index 5885af5c..1ad3f8a6 100644 --- a/frontend/crawlab-ui/src/layouts/content/detail/useDetail.ts +++ b/frontend/crawlab-ui/src/layouts/content/detail/useDetail.ts @@ -23,16 +23,29 @@ const useDetail = (ns: ListStoreNamespace) => { const showActionsToggleTooltip = ref(false); - const navItems = computed[]>(() => { - // TODO: implement - return []; - }); - const activeId = computed(() => { const { id } = route.params; return (id as string) || form._id || ''; }); + const navItems = computed[]>(() => { + const items = state.navList.map(item => { + return { + id: item._id, + label: item['name'] || item._id, + data: item, + }; + }) as NavItem[]; + if (!items.some(item => item.id === activeId.value)) { + // if activeId is not in navList, add it + items.unshift({ + id: activeId.value, + label: form.name || activeId.value, + }); + } + return items; + }); + const activeTabName = computed(() => getTabName(router)); const tabs = computed(() => { diff --git a/frontend/crawlab-ui/src/utils/store.ts b/frontend/crawlab-ui/src/utils/store.ts index 443b6cfd..97dd29ba 100644 --- a/frontend/crawlab-ui/src/utils/store.ts +++ b/frontend/crawlab-ui/src/utils/store.ts @@ -8,6 +8,7 @@ import { saveNamespaceLocalStorage, } from '@/utils/storage'; import { getMd5 } from '@/utils/hash'; +import { FILTER_OP_CONTAINS } from '@/constants'; // i18n const t = translate; @@ -50,6 +51,7 @@ export const getDefaultStoreState = ( actionsCollapsed: false, tabs: [{ id: 'overview', title: t('common.tabs.overview') }], disabledTabKeys: [], + navList: [], afterSave: [], }; }; @@ -199,6 +201,12 @@ export const getDefaultStoreMutations = (): BaseStoreMutations => { resetDisabledTabKeys: (state: BaseStoreState) => { state.disabledTabKeys = []; }, + setNavList: (state: BaseStoreState, navList: T[]) => { + state.navList = navList; + }, + resetNavList: (state: BaseStoreState) => { + state.navList = []; + }, setAfterSave: (state: BaseStoreState, fnList) => { state.afterSave = fnList; }, @@ -207,50 +215,7 @@ export const getDefaultStoreMutations = (): BaseStoreMutations => { export const getDefaultStoreActions = ( endpoint: string -): { - deleteList: ( - { commit }: StoreActionContext>, - ids: string[] - ) => Promise; - createList: ( - { state, commit }: StoreActionContext>, - data: T[] - ) => Promise>; - getById: ( - { commit }: StoreActionContext>, - id: string - ) => Promise>; - getList: ({ - state, - commit, - }: StoreActionContext>) => Promise>; - deleteById: ( - { commit }: StoreActionContext>, - id: string - ) => Promise; - create: ( - { commit }: StoreActionContext>, - form: T - ) => Promise>; - getListWithParams: ( - _: StoreActionContext>, - params?: ListRequestParams - ) => Promise>; - updateById: ( - { commit }: StoreActionContext>, - { - id, - form, - }: { - id: string; - form: T; - } - ) => Promise>; - updateList: ( - { state, commit }: StoreActionContext>, - { ids, data, fields }: BatchRequestPayloadWithData - ) => Promise; -} => { +): BaseStoreActions => { const { getById, create, @@ -335,5 +300,21 @@ export const getDefaultStoreActions = ( ) => { return await deleteList(ids); }, + getNavList: async ( + { commit }: StoreActionContext>, + query?: string + ) => { + const res = await getList({ + size: 100, + conditions: query + ? JSON.stringify([ + { key: 'name', op: FILTER_OP_CONTAINS, value: query }, + ] as FilterConditionData[]) + : undefined, + }); + if (res.data) { + commit('setNavList', res.data); + } + }, }; };