feat(assets): migrate asset views and reconcile inventory drilldowns
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
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;
|
||||
}
|
||||
Reference in New Issue
Block a user