Files
ln-bi/src/modules/assets/library/useAssetHash.ts
T

63 lines
2.1 KiB
TypeScript

import { useEffect, useState } from "react";
const TAB_IDS = ["overview", "department", "region", "customer"] as const;
const SECTION_IDS = ["inventory", "models", "flow"] as const;
export type AssetTab = (typeof TAB_IDS)[number];
export type AssetSection = (typeof SECTION_IDS)[number];
interface AssetHashState {
tab: AssetTab;
section: AssetSection;
}
const DEFAULT_STATE: AssetHashState = { tab: "overview", section: "inventory" };
const isTab = (value: string | undefined): value is AssetTab =>
Boolean(value) && (TAB_IDS as readonly string[]).includes(value as string);
const isSection = (value: string | undefined): value is AssetSection =>
Boolean(value) && (SECTION_IDS as readonly string[]).includes(value as string);
function parseHash(): AssetHashState {
const [first, second, third] = window.location.hash.slice(1).split("/");
if (first !== "assets") return DEFAULT_STATE;
return {
tab: isTab(second) ? second : "overview",
section: isSection(third) ? third : "inventory",
};
}
function writeHash(tab: AssetTab, section: AssetSection) {
const parts = ["assets", tab];
// 默认子页签不写入,保持 `#assets/<tab>` 简洁。
if (tab === "overview" && section !== "inventory") parts.push(section);
const hash = `#${parts.join("/")}`;
window.history.replaceState(
null,
"",
`${window.location.pathname}${window.location.search}${hash}`,
);
}
/**
* 资产模块页签状态 ↔ URL hash 二级/三级段(`#assets/<tab>[/<section>]`)。
* 默认值不写入 hash,刷新可恢复,链接可分享;与 Shell 的一级模块段兼容。
*/
export function useAssetHash() {
const [state, setState] = useState<AssetHashState>(parseHash);
useEffect(() => {
const onChange = () => setState(parseHash());
window.addEventListener("hashchange", onChange);
return () => window.removeEventListener("hashchange", onChange);
}, []);
const update = (next: Partial<AssetHashState>) => {
const merged = { ...state, ...next };
writeHash(merged.tab, merged.section);
setState(merged);
};
return [state, update] as const;
}