npm package: @portalx/core
Description: # 1. 状态管理
Latest version: 0.0.52

# <center>@portalx/core 说明文档</center>

# 1. 状态管理

## 说明

- **主动调用**

  - 使用方式和使用【函数】一样，获取的是调用的那个时间的 `state` 值
  - 可以使用在任意的 js 文件中(js、jsx、ts、tsx)

  ```ts
  const { menuTree, menuList, getMenu } = useStoreMenu.getState();
  ```

- **被动监听**

  - 使用方式和使用【useSelector】一样，数据发生变化时，强制更新组件
  - 只能使用在组件中

  ```ts
  const menuTree = useStoreMenu((store) => store.menuTree);
  ...
  const getMenu = useStoreMenu((store) => store.getMenu);
  ```

## 1.1 Menu

- 数据结构

  ```ts
  // 后端返回的菜单原始数据
  type IRawMenuAttr = {
    // 通用
    iconUrl?: string; // 菜单图标
    partyId: number; // key值
    partyName: string; // 菜单名称
    portalId: number;
    seq: number; // 同层级的排序
    state: CommonStateEnum;
    stateDate: string;
    type: MenuType; // 菜单类型
    // 叶子菜单独有
    menuType?: MenuOpenType; // 菜单打开类型
    parentId?: number; // 父级菜单id
    parentName?: string; // 父级菜单name
    privCode?: string; // code码，用于生成path
    url?: string;
  };
  // 菜单属性
  type IMenuAttr = IRawMenuAttr & {
    path?: string;
    name: string;
    children?: IMenuAttr[];
    idPath: Array<number>; // 从父级开始的菜单id列表（有层级顺序）
    namePath: Array<string>; // 从父级开始的菜单name列表（有层级顺序）
  };
  ```

- 【数据】`menuTree`
  ```ts
  Array<IMenuAttr>; // 当前菜单树
  ```
- 【数据】`menuList`
  ```ts
  Array<IMenuAttr>; // 当前菜单列表，平铺
  ```
- 【函数】`generateMenuTree`
  ```ts
  // 生成菜单树，并进行部分数据填充数据填充，包含children列表
  (rawMenuList: Array<IRawMenuAttr>) => Array<IMenuAttr>;
  ```
- 【函数】`generateMenuList`
  ```ts
  // 根据菜单树，生成扁平化菜单列表，不包含children列表
  (menuTree: Array<IMenuAttr>) => Array<IMenuAttr>;
  ```
- 【函数】`init`
  ```ts
  // 初始化
  () => Promise<void>;
  ```
- 【函数】`getMenu`

  ```ts
  // 获取菜单的参数
  type IGetMenuOpt = {
    menuId?: number;
    menuUrl?: string;
    path?: string;
    privCode?: string;
  };
  ...
  // 根据参数或对应的菜单
  (opt: IGetMenuOpt) => IMenuAttr | undefined;
  ```

- 【函数】`getRootMenuNode`

  ```ts
  // 获取根节点
  () => IMenuAttr;
  ```

- 【函数】`getFirstMenuLeaf`
  ```ts
  // 获取第一个菜单叶子节点
  () => IMenuAttr | undefined;
  ```

## 1.2 MenuTab

- 数据结构

  ```ts
  // 菜单Tab结构
  type IMenuTabAttr = {
    menuId: number | string; // 菜单ID，一般注册的菜单是number，临时菜单是string
    menuUrl: string; // 菜单url，截取完参数之后的纯净url
    menuType: MenuOpenType; // 菜单类型
    menuName: string | ReactNode; // 菜单名称
    path: string; // 菜单显示的path
    privCode: string; // 菜单唯一码，若为临时菜单，则取menuId一致
    state?: IMenuTabStateAttr; // 菜单携带的路由中的state内容
    comprivList?: Array<IComprivAttr>; // 菜单上的不可见组件列表
    closable?: boolean; // 可否关闭
  };
  ```

- 【数据】`menuTabMap`

  ```ts
  Map<string, IMenuTabAttr>; // 当前已打开的菜单tab的Map，key为path
  ```

- 【数据】`activeMenuId`

  ```ts
  string | number; // 当前激活菜单tab的Id
  ```

- 【数据】`activePath`

  ```ts
  string; // 当前激活的菜单tab的path
  ```

- 【数据】`homeMenuTab`

  ```ts
  IMenuTabAttr; // 首页菜单tab
  ```

- 【数据】`removedPathList`

  ```ts
  Array<string>; // 已被删除的菜单tab的path
  ```

- 【函数】`init`

  ```ts
  type IRootMenuAttr = {
  menuUrl?: string;
  menuType?: MenuOpenType;
  };
  ...
  // 初始化，设置首页，并挂载兼容函数
  (opt?: IRootMenuAttr) => void;
  ```

- 【函数】`updateMenuTab`

  ```ts
  // 更新目标菜单tab
  (targetMenu: IMenuTabAttr) => void;
  ```

- 【函数】`updateActivePath`

  ```ts
  // 更新当前激活的菜单tab的path
  (path: string) => void;
  ```

- 【函数】`updateRemovedPathList`

  ```ts
  // 更新已被删除的菜单tab的path的列表
  (pathList: Array<string>) => void;
  ```

- 【函数】`findExistMenuTab`

  ```ts
  type ISearchMenuAttr = {
  menuId?: number | string | null;
  menuUrl?: string; // 菜单原始url
  menuType?: MenuOpenType;
  menuName?: string;
  path?: string; // 前端路由
  params?: Record<string, any>;
  urlSearchParams?: string;
  };
  ...
  // 查找缓存中是否存在对应的菜单tab; exact 是否精确匹配
  // 有path，直接返回对应的path
  // 没有或者没有找到，则根据menuId去查找
  // 还没有找到，则根据 menuUrl、menuType和menuName三者来找（exact模式）或者根据menuUrl来查找
  // 最后若是 exact 模式，则会更新路由上的 state
  (searchOpt: ISearchMenuAttr, exact?: boolean) => IMenuTabAttr | undefined;
  ```

- 【函数】`createMenuTab`

  ```ts
  // 根据参数生成菜单tab对象 (精确匹配模式)
  (opt: ISearchMenuAttr) => IMenuTabAttr | undefined;
  ```

- 【函数】`openMenuTab`

  ```ts
  // 打开对应的菜单tab (精确匹配模式)
  // 若成功打开，则自动将新打开的菜单作为激活态菜单tab
  (opt: ISearchMenuAttr) => void;
  ```

- 【函数】`closeMenuTab`

  ```ts
  // 删除对应的菜单tab (非精确匹配模式)
  // 删除成功后，若激活态菜单tab未删除，则激活态菜单tab的path不变
  // 删除成功后，若激活态菜单tab已删除，则激活态菜单tab的path变为之前的tab所在的下标位置的菜单tab的path，或者最后一个菜单tab的path
  (removeOptList: Array<ISearchMenuAttr>) => void;
  ```

- 【函数】`retainMenuTab`
  ```ts
  // 保留对应的菜单tab，其余都删除 (内部调用closeMenuTab)
  (retainOptList: Array<ISearchMenuAttr>) => void;
  ```

# 2. 通用函数

## 2.1 api 拦截器

- 请求拦截器
  - 自动添加部分头
    - 【X-Requested-With】避免后端不识别 ajax
    - 【csrf token】
    - 【数字签名】（具体参照 @whalecloud/foundation）
  - 自动添加【时间戳】
- 响应拦截器
  - 返回通用结构体
  ```ts
  type ICommonRes<T = any> = {
    success?: boolean; // 是否成功
    data: T; // 实际返回结构
    stack?: string;
    message?: string; // 错误信息
    code?: number; // 错误码
    resultCode?: string;
    resultObject?: object;
    resultMsg?: string;
  };
  ```
  - 显示通用错误 notication
  - 特殊错误自动【重定向】