63 lines
2.1 KiB
TypeScript
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;
|
|
}
|