feat: implement navigation list management in store and detail layout

This commit is contained in:
Marvin Zhang
2025-06-11 18:04:51 +08:00
parent de69c2b01b
commit ca069cb570
4 changed files with 57 additions and 54 deletions

View File

@@ -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<BaseStoreState, NavItem[]>;
setDisabledTabKeys: StoreMutation<BaseStoreState, string[]>;
resetDisabledTabKeys: StoreMutation<BaseStoreState, string[]>;
setNavList: StoreMutation<BaseStoreState<T>, T[]>;
resetNavList: StoreMutation<BaseStoreState<T>>;
setAfterSave: StoreMutation<BaseStoreState<T>, (() => Promise)[]>;
}
@@ -144,6 +147,7 @@ export declare global {
createList: StoreAction<BaseStoreState<T>, T[]>;
updateList: StoreAction<BaseStoreState<T>, BatchRequestPayloadWithData<T>>;
deleteList: StoreAction<BaseStoreState<T>, BatchRequestPayload>;
getNavList: StoreAction<BaseStoreState<T>, string>;
}
type StoreActionContext<

View File

@@ -26,6 +26,7 @@ const {
activeTabName,
getForm,
navLoading,
navItems,
onNavSelect,
onNavTabsSelect,
onBack,
@@ -37,13 +38,17 @@ const computedTabs = computed<NavItem[]>(() =>
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"
>
<el-option
v-for="op in computedAllListSelectOptions"
:key="op.value"
:label="op.label"
:value="op.value"
v-for="item in navItems"
:key="item.id"
:label="item.label"
:value="item.id"
/>
</el-select>
</div>

View File

@@ -23,16 +23,29 @@ const useDetail = <T extends BaseModel>(ns: ListStoreNamespace) => {
const showActionsToggleTooltip = ref<boolean>(false);
const navItems = computed<NavItem<T>[]>(() => {
// TODO: implement
return [];
});
const activeId = computed<string>(() => {
const { id } = route.params;
return (id as string) || form._id || '';
});
const navItems = computed<NavItem<T>[]>(() => {
const items = state.navList.map(item => {
return {
id: item._id,
label: item['name'] || item._id,
data: item,
};
}) as NavItem<T>[];
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<string>(() => getTabName(router));
const tabs = computed(() => {

View File

@@ -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 = <T = any>(
actionsCollapsed: false,
tabs: [{ id: 'overview', title: t('common.tabs.overview') }],
disabledTabKeys: [],
navList: [],
afterSave: [],
};
};
@@ -199,6 +201,12 @@ export const getDefaultStoreMutations = <T = any>(): BaseStoreMutations<T> => {
resetDisabledTabKeys: (state: BaseStoreState<T>) => {
state.disabledTabKeys = [];
},
setNavList: (state: BaseStoreState<T>, navList: T[]) => {
state.navList = navList;
},
resetNavList: (state: BaseStoreState<T>) => {
state.navList = [];
},
setAfterSave: (state: BaseStoreState<T>, fnList) => {
state.afterSave = fnList;
},
@@ -207,50 +215,7 @@ export const getDefaultStoreMutations = <T = any>(): BaseStoreMutations<T> => {
export const getDefaultStoreActions = <T = any>(
endpoint: string
): {
deleteList: (
{ commit }: StoreActionContext<BaseStoreState<T>>,
ids: string[]
) => Promise<Response>;
createList: (
{ state, commit }: StoreActionContext<BaseStoreState<T>>,
data: T[]
) => Promise<ResponseWithListData<T>>;
getById: (
{ commit }: StoreActionContext<BaseStoreState<T>>,
id: string
) => Promise<ResponseWithData<T>>;
getList: ({
state,
commit,
}: StoreActionContext<BaseStoreState<T>>) => Promise<ResponseWithListData<T>>;
deleteById: (
{ commit }: StoreActionContext<BaseStoreState<T>>,
id: string
) => Promise<Response>;
create: (
{ commit }: StoreActionContext<BaseStoreState<T>>,
form: T
) => Promise<ResponseWithData<T>>;
getListWithParams: (
_: StoreActionContext<BaseStoreState<T>>,
params?: ListRequestParams
) => Promise<ResponseWithListData<T>>;
updateById: (
{ commit }: StoreActionContext<BaseStoreState<T>>,
{
id,
form,
}: {
id: string;
form: T;
}
) => Promise<ResponseWithData<T>>;
updateList: (
{ state, commit }: StoreActionContext<BaseStoreState<T>>,
{ ids, data, fields }: BatchRequestPayloadWithData
) => Promise<Response>;
} => {
): BaseStoreActions => {
const {
getById,
create,
@@ -335,5 +300,21 @@ export const getDefaultStoreActions = <T = any>(
) => {
return await deleteList(ids);
},
getNavList: async (
{ commit }: StoreActionContext<BaseStoreState<T>>,
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);
}
},
};
};