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

admin-scaffold

v1.0.2

Published

通用后台管理系统脚手架 - 组件、请求、工具、架构、权限、

Readme

admin-scaffold

通用后台管理系统脚手架 —— 组件、请求、工具、架构、权限、布局一站式解决方案。

特性

| 特性 | 说明 | |------|------| | Monorepo 架构 | pnpm workspace 管理多包 | | TypeScript 支持 | 完整类型定义,IDE 智能提示 | | ESM + CJS | 同时支持两种模块格式 | | Tree Shaking | 按需加载,不增加额外体积 | | React 18/19 | 支持 React >= 18.0.0 | | Ant Design 5/6 | 支持 antd >= 5.0.0 | | 版本管理 | changesets 自动化版本发布 | | 零业务耦合 | 不包含任何业务逻辑,一切由配置注入 |

安装

pnpm add admin-scaffold
# 或
npm install admin-scaffold

peerDependencies

脚手架不打包以下库,由消费项目自行安装:

pnpm add react react-dom react-router-dom antd @ant-design/icons axios dayjs zustand

快速开始

1. 初始化配置

在应用入口(如 src/main.tsx)进行全局配置:

import { configure, registerServices, setNavigateCallback } from 'admin-scaffold';
import { useNavigate } from 'react-router-dom';

// 注册 API 键名映射
registerServices({
  'user.login': '/api/auth/user/login',
  'user.list': 'GET /api/user/list',
  'user.detail': '/api/user/detail',
  // ... 更多接口
});

// 全局配置
configure({
  // —— 请求配置 ——
  request: {
    baseURL: import.meta.env.VITE_API_BASE_URL,
    timeout: 20000,
    headers: { 'x-channel': 'my-app' },
    getToken: () => localStorage.getItem('my_token'),
    clearAuth: () => { localStorage.removeItem('my_token'); },
    loginPath: '/login',
    // 注入公共参数(如品牌编码)
    injectParams: (config) => ({ brandCode: getBrandCode() }),
  },

  // —— 权限配置 ——
  auth: {
    hasPermission: (key) => authStore.getState().hasPermission(key),
    getUserInfo: () => authStore.getState().userInfo,
    fetchPermissionKeys: async () => {
      const res = await request('user.permissions');
      return { menuKeyList: res.data.menuKeys, permissionKeyList: res.data.authKeys };
    },
  },

  // —— 路由配置 ——
  router: {
    homePath: '/dashboard',
    loginPath: '/login',
  },

  // —— 常量覆盖 ——
  constants: {
    DEFAULT_PAGE_SIZE: 20,
    PAGE_SIZE_OPTIONS: [20, 50, 100],
    STORAGE_KEYS: {
      TOKEN: 'my_app_token',
      USER_INFO: 'my_app_user_info',
    },
  },
});

2. 设置导航回调

import { setNavigateCallback } from 'admin-scaffold';
import { useNavigate } from 'react-router-dom';

function App() {
  const navigate = useNavigate();
  useEffect(() => {
    setNavigateCallback(navigate);
  }, [navigate]);

  return <YourRoutes />;
}

3. 使用组件

完整组件文档(Props 表格 / 使用示例 / Ref 方法)见 COMPONENTS.md

TablePage - 列表页

import { TablePage, registerServices } from 'admin-scaffold';

registerServices({ 'order.list': 'GET /api/order/list' });

function OrderList() {
  return (
    <TablePage
      apiKey="order.list"
      searchFields={[
        { name: 'orderNo', label: '订单号', type: 'input' },
        { name: 'status', label: '状态', type: 'select', options: [
          { label: '待支付', value: 0 },
          { label: '已完成', value: 1 },
        ]},
      ]}
      columns={[
        { title: '订单号', dataIndex: 'orderNo' },
        { title: '金额', dataIndex: 'amount' },
        { title: '状态', dataIndex: 'status' },
        { title: '操作', render: (_, record) => <a onClick={() => navigate(`/order/${record.id}`)}>详情</a> },
      ]}
    />
  );
}

FormPage - 表单页

import { FormPage, FormPageRef } from 'admin-scaffold';

function OrderEdit() {
  const formRef = useRef<FormPageRef>(null);

  return (
    <FormPage
      title="编辑订单"
      formItems={[
        { name: 'orderNo', label: '订单号', type: 'input', rules: [{ required: true }] },
        { name: 'amount', label: '金额', type: 'number', rules: [{ required: true }] },
        { name: 'remark', label: '备注', type: 'textarea' },
      ]}
      onSubmit={(values) => console.log('提交:', values)}
      showSaveButton
    />
  );
}

FormModal - 弹窗表单

import { FormModal, FormModalRef } from 'admin-scaffold';

function CreateModal({ visible, onOk, onCancel }) {
  const modalRef = useRef<FormModalRef>(null);

  return (
    <FormModal
      ref={modalRef}
      visible={visible}
      title="新增"
      formItems={[
        { name: 'name', label: '名称', type: 'input', rules: [{ required: true }] },
        { name: 'type', label: '类型', type: 'select', options: [...] },
      ]}
      onOk={(values) => onOk(values)}
      onCancel={onCancel}
    />
  );
}

SearchBar - 搜索栏

import { SearchBar } from 'admin-scaffold';

<SearchBar
  items={[
    { name: 'keyword', label: '关键词', type: 'input', span: 1 },
    { name: 'status', label: '状态', type: 'select', options: [...], span: 1 },
    { name: 'dateRange', label: '日期', type: 'daterange', span: 2 },
  ]}
  onSearch={(values) => console.log(values)}
  onReset={() => console.log('reset')}
/>

ApiSelect - 远程数据选择器

import { ApiSelect } from 'admin-scaffold';

// 注册预设类型
ApiSelect.registerTypes({
  shop: {
    apiKey: 'common.shop.list',
    valueField: 'shopCode',
    labelField: 'shopName',
    placeholder: '请选择门店',
  },
});

// 使用
<ApiSelect type="shop" />
// 或直接使用
<ApiSelect apiKey="common.shop.list" valueField="id" labelField="name" />

权限控制

import { AuthButton, AuthPage } from 'admin-scaffold';

// 按钮级权限
<AuthButton authKey="order.delete">
  <Button danger>删除</Button>
</AuthButton>

// 页面级权限
const OrderPage = AuthPage(OrderComponent, {
  add: 'order.add',
  edit: 'order.edit',
  default: 'order.view',
});

布局

布局类组件(MainLayout / Sidebar / Header / TabBar / Breadcrumb)尚在规划中,暂未随包导出。 消费方可基于 antd Layout 自行封装,应用名称等可通过 configure({ constants: { APP_NAME } }) 注入。

完整 API

配置

| 函数 | 说明 | |------|------| | configure(config) | 全局配置(应用启动时调用一次) | | getConfig() | 获取完整配置 | | getRequestConfig() | 获取请求配置 | | getAuthConfig() | 获取权限配置 | | getRouterConfig() | 获取路由配置 | | getConstants() | 获取常量配置 | | getHomePath() / getLoginPath() | 获取首页 / 登录页路径 |

服务注册(API 键名系统)

| 函数 | 说明 | |------|------| | registerServices(map) | 注册 API 键名映射(可多次调用,自动合并) | | setServices(map) | 覆盖全部 API 映射 | | getApiUrl(key) | 根据键名获取接口地址 | | getAllApiKeys() / getAllServices() | 获取全部键名 / 映射表 |

请求

| 函数 | 说明 | |------|------| | request(urlOrKey, data?, config?) | POST 请求 | | request.get(urlOrKey, params?, config?) | GET 请求 | | request.post(...) | POST | | request.put(...) | PUT | | request.delete(...) | DELETE | | request.download(urlOrKey, data?, filename?) | 下载文件 | | get(urlOrKey, params?) / post(...) / put(...) / del(...) | 命名导出的便捷方法 | | recreateRequestInstance() | 配置变更后重建 axios 实例 |

导航

| 函数 | 说明 | |------|------| | navigate(path, options?) | 编程式导航 | | navigateTo(path, query?) | 带查询参数导航 | | goBack() | 返回上一页 | | goForward() | 前进 | | setNavigateCallback(fn) | 设置导航回调 |

认证

| 函数 | 说明 | |------|------| | getToken() / setToken(t) / removeToken() | Token 管理 | | getUserInfo() / setUserInfo(info) / removeUserInfo() | 用户信息 | | clearAuth() | 清除认证 | | saveRedirectUrl(url) / getAndClearRedirectUrl() | 重定向管理 |

状态管理

脚手架不内置任何 Store。认证、标签页、面包屑等状态由消费方自行管理, 通过 configure({ auth }) 注入回调接入,例如 hasPermission / getUserInfo / fetchPermissionKeys

Hooks

| Hook | 说明 | |------|------| | usePermission() | 权限检查(返回 { checkPermission, isSuperAdmin }) | | useWindowSize() | 窗口尺寸 | | useRequest(apiFn, deps) | 异步请求(返回 { data, loading, run }) | | useQueryParams() | URL 查询参数 |

组件

各组件完整 Props 与示例见 COMPONENTS.md

| 组件 | 说明 | |------|------| | TablePage | 列表页(搜索 + 表格 + 分页 + Tab + 列设置) | | FormPage | 表单页(多分区 + 提交 + 重置) | | FormModal | 弹窗表单 | | FormTemplate | 表单项渲染引擎 | | SearchBar | 搜索栏(可折叠) | | ApiSelect | 远程数据选择器 | | ApiCascader | 远程级联选择 | | ApiTreeSelect | 远程树选择 | | EditTable | 可编辑表格 | | ModalTableSelect | 弹窗表格选择器 | | ModalTreeSelector | 弹窗树选择器 | | FileUpload | 文件上传(图片/文件) | | FilePreview | 文件预览 | | CopyText | 复制文本 | | Empty | 空状态 | | QuestionTip | 帮助提示 | | PlaceholderPage | 占位页 | | AuthButton | 按钮权限 | | AuthPage | 页面权限 HOC | | renderActions(actions) | 表格操作列渲染 |

工具函数

| 函数 | 说明 | |------|------| | sleep(ms) | 延时 | | debounce(fn, delay) | 防抖 | | throttle(fn, delay) | 节流 | | deepClone(obj) | 深拷贝 | | mul(a, b) / add(a, b) / sub(a, b) / div(a, b) | 精确计算 | | round(num, decimals) | 精确四舍五入 | | formatMoney(num, decimals) | 格式化金额 |

开发

# 安装依赖
pnpm install

# 开发模式(监听文件变化)
pnpm dev

# 构建
pnpm build

# 类型检查
pnpm type-check

# 发布版本
pnpm changeset
pnpm version
pnpm release

License

MIT