npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

bms-admin-layout

v0.1.9

Published

Reusable admin layout for BMS React applications

Readme

bms-admin-layout

BMS 后台项目的共享布局组件。菜单选中、菜单搜索、侧栏折叠与宽度、面包屑、最近访问菜单、tabs、移动端适配等状态均由组件内部维护。

最小接入

import BmsAdminLayout from "bms-admin-layout";

export default function AppLayout({ menus }) {
    return (
        <BmsAdminLayout
            menus={menus}
            title="运营系统"
            icon="/logo.png"
            userName="管理员"
            onLogout={logout}
        />
    );
}

必要参数:

  • menus: 菜单树,叶子节点至少包含 keytextpath
  • title: 软件名称
  • icon: 软件 Logo,可传图片地址或 React 节点
  • onLogout: 退出登录事件

可选参数:

  • layout: side-menutop-side-menutop-menu
  • showSide: 是否显示侧栏
  • globalLoadingglobalLoadingTip: 全局加载状态
  • menusLoading: 菜单加载状态。没有可用菜单时会显示内置骨架屏;已有缓存菜单时不会阻塞刷新
  • menusCacheKey: 菜单缓存 key,默认 bms-admin-layout:menus,传 false 可关闭缓存
  • fetchMenus: 可选的菜单刷新函数,返回菜单数组或 { menus }
  • onMenusChange: fetchMenus 返回后回调,方便业务同步 Redux 或其他状态
  • menusReloadKey: 改变该值可触发 fetchMenus 重新执行
  • showMenuSkeleton: 是否启用无菜单加载骨架屏
  • pageTitle: 浏览器页签标题
  • showTabs: 是否显示多页签
  • keepalive: 需要缓存的路由。可传字符串、字符串数组、{ path, keepAlive } 数组、正则或函数;仅作用于作为 BmsAdminLayout 子节点传入的路由内容
  • onMenuSelect: 需要由业务接管菜单跳转时使用
  • userMenuItemsonUserMenuClick: 扩展用户菜单
  • showAuthCart: 是否显示权限购物车,默认 true
  • authStorageKeys: 权限购物车本地缓存 key,默认 { auth: "all_apply_auth", area: "all_apply_area" }
  • onAuthCartSubmit: 提交权限购物车时触发,参数为 { module_ids, bigareas, reason }
  • showResetPassword: 是否在用户菜单中显示重置密码,默认 true
  • onResetPassword: 保存重置密码时触发,参数为表单值 { password, repassword }
  • showLanguageSwitch: 是否显示语言切换,默认 true
  • languageItemsonLanguageChange: 自定义语言选项及切换事件
  • request: 可选通用请求函数;未传 onAuthCartSubmitonResetPassword 时,会分别调用 authApplyEndpointresetPasswordEndpoint
  • clearLoginCacheOnLogout: 点击内置 logout 菜单时是否先清理登录缓存,默认 true
  • clearLogoutCookies: 清理登录缓存时是否清理当前页面可访问 cookies,默认 true
  • logoutStorageKeys: 退出时需要从 localStorage 删除的 key 列表。默认包含常见登录用户、uid、token key

权限购物车默认读取 localStorage.all_apply_authlocalStorage.all_apply_area,数据结构兼容 BMS 项目里的权限申请缓存。布局组件会监听同页面对这两个 key 的 localStorage.setItem/removeItem,加入购物车后会自动刷新 header 数量。业务页面也可手动派发事件刷新:

window.dispatchEvent(new Event("bms-admin-layout-auth-cart-change"));

组件依赖 React Router v5,并通过 withRouter 获取路由状态。消费项目需要提供 package.json 中列出的 peer dependencies。

路由缓存

需要缓存页面组件状态时,把业务 Switch/Route 放进 BmsAdminLayout,并传入 keepalive 指定需要缓存的路由:

import BmsAdminLayout from "bms-admin-layout";
import { keepAlives } from "src/pages/page-routes";

export default function AppLayout({ menus }) {
    return (
        <BmsAdminLayout menus={menus} keepalive={keepAlives}>
            <Switch>
                {routes.map(item => (
                    <Route key={item.path} path={item.path} component={item.component} />
                ))}
            </Switch>
        </BmsAdminLayout>
    );
}

keepalive 支持以下形式:

keepalive="/operate/list";
keepalive={["/operate/list", "/audit/:id"]};
keepalive={[{ path: "/operate/list", keepAlive: true }]};
keepalive={["new/lesscode/common?guid=vipsendrecord"]};
keepalive={/^\/lesscode\/common/};
keepalive={({ fullPath, pathname }) => pathname === "/operate/list"};

缓存页面会按完整路径缓存,包含 query 参数;关闭布局 tab 时,对应缓存也会被移除。对于 /lesscode/common?guid=xxx/nocode/preview?ncid=xxx 这类同 path 多页面,传带 query 的完整地址后,仅命中该完整地址时才缓存,同 path 下未列入 keepalive 的其它参数页面不会缓存。缓存 tab 会显示“缓存”标志,右键当前高亮缓存 tab 可通过“刷新”重建页面实例。viteRouteGeneratorPlugin 生成的 keepAlives 可直接传给 keepalive

构建与发布

npm install
npm run build
npm run pack:check
npm publish

构建产物位于 dist

  • index.js: ESM
  • index.cjs: CommonJS
  • *.map: source map

组件样式已内联到 JavaScript 产物,导入组件时会自动注入到页面,无需单独导入 CSS。

npm publish 会通过 prepublishOnly 自动重新构建。

页面可使用组件导出的命令更新动态标题或关闭当前页:

import {
    closeAdminLayoutCurrentTab,
    setAdminLayoutCurrentTabTitle
} from "bms-admin-layout";

setAdminLayoutCurrentTabTitle("编辑用户");
closeAdminLayoutCurrentTab();

复用路由生成与页面配置 HOC

Vite 项目可复用自动路由插件:

import { viteRouteGeneratorPlugin } from "bms-admin-layout/vite-route-generator";

export default defineConfig({
    plugins: [
        viteRouteGeneratorPlugin({
            root: __dirname,
            pagesDir: path.resolve(__dirname, "src/pages")
        })
    ]
});

页面配置 HOC 通过工厂注入业务依赖,baseName 不再依赖固定的 src/config

import PubSub from "pubsub-js";
import { createConfigHoc } from "bms-admin-layout/config-hoc";

const config = createConfigHoc({
    ajaxHoc,
    connect: reduxConnect,
    eventHoc,
    getBaseName: () => process.env.BASE_NAME || "",
    modalHoc,
    pubSub: PubSub,
    pubSubHoc,
    queryHoc,
    withRouter
});

export default config;