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

@usethink/cf-admin-fe

v0.2.8

Published

Vue 3 frontend admin kit for CF product family — composables, shell, ConfigField, list loader, login chrome, request/token/raw factories, error/batch helpers, system-config engine, nav helpers, i18n seeds, recipes (FE only; not cf-core)

Downloads

570

Readme

@usethink/cf-admin-fe

面向 Cloudflare 产品家族(cf-shopcf-lotterycf-auth 以及未来的 CF 管理端应用)的 Vue 3 管理端基础套件(admin foundation)

状态: 0.2.8 — P0 三件套:resolveAdminT / tKit、AdminShell/ConfigField/MetadataDetail 契约测、size-report。完整用法见 docs/002_cf-admin-fe使用说明书与注意事项.md;起步清单见 recipes/README.md;路线图见 docs/003_cf-admin-fe极致化方案与取舍_2026-08-05.md

核心目标: 最大化共享 管理端前端基础套件,让 CF 产品快速搭建 — 通过克隆业务页面实现,也 强迫每个产品套用 shop 的 Bearer 模式。

| 会话模型 | 套件 | 线上消费方 | |---|---|---| | Bearer JWT + localStorage TTL | createAdminTokenSession | cf-shop, cf-lottery | | Cookie HTTP 会话 + 本地守卫标志 | createAdminFlagSession + credentials: 'include' + 可选 onSuccess | cf-auth(验证方,非克隆目标) |

| 分层 | 包 | 内容 | |---|---|---| | Workers / 基础设施 | @usethink/cf-core | HTTP、crypto、media、secrets 等 | | 管理端 UI 套件 | @usethink/cf-admin-fe | 表格 UX、shell、ConfigField、request/token 工厂、导航助手、i18n 种子、recipes、CSS |

为什么叫 cf-admin-fe(而不是 cf-admin

仅前端。 -fe 后缀使 UI 套件代码与 Worker/API 基础设施保持区分。

不是业务中间层:不包含订单、抽奖、RBAC 产品页面或支付 UI。

边界(新增 API 前请先阅读)

cf-admin-fe管理端基础套件,不是通用 Vue 组件库,也不是 Element Plus。

| 应做 | 不应做 | |---|---| | AdminPagination、AdminModal、ConfirmDialog、Toast、AdminShell、ConfigField | 日期选择器、级联、树、富文本、数据网格框架 | | 已被 ≥2 个线上消费方 验证的纯函数助手(或经验证的第三条路径,如 cookie 认证) | “以后可能有用”的抽象 | | 轻量 request/session 工厂 + 列表加载器 + 导航助手 | 业务页面、OAuth 流程、抽奖 L3、商城结算 |

心智成本才是真正的成本。 每次套件变更都必须让 cf-shop、cf-lottery、cf-auth 保持绿色(测试 + 类型检查)。有 3 个管理端时该成本可以摊销;只有 1 个管理端时就不值得。

提取气味的检验标准

  • 好:两个产品已经复制粘贴了同样的 10 行 → 提取。
  • 坏:只有 cf-lottery 需要 → 留在产品内。
  • 坏:为了“一致性”而包装第三方日期选择器 → 在产品里用轻量专用库。

安装

# monorepo / 兄弟模板(开发期推荐)
npm install file:../cf-admin-fe

# 或发布后
npm install @usethink/cf-admin-fe

Peer 依赖:vue ^3.4。可选 peer 依赖:vue-i18n(组件在存在时会调用 $t)。


批量复制剧本(几分钟搭建新管理端)

快速路径:复制 recipes

包在 recipes/ 下提供 复制即用的起步代码(monorepo 中也可通过 @usethink/cf-admin-fe/recipes/* import 路径阅读):

| Recipe | 用途 | |---|---| | recipes/README.md | 有序检查清单 | | recipes/reexports/* | 轻量 composable/组件/utils 再导出 | | recipes/useAdminAuth.shop.ts | 单键 Bearer 会话 | | recipes/useAdminRequest.ts | createAdminRequest + 401 处理器 | | recipes/AdminLayout.vue | AdminShell + 产品菜单 hooks | | recipes/router-guard.snippet.ts | decideAdminRouteAccess 守卫 | | recipes/i18n-merge.snippet.ts | mergeAdminKitMessages | | recipes/main-styles.snippet.ts | CSS 入口选项 |

参考线上消费方:cf-shop(Bearer)、cf-lottery(Bearer + L3 胶水)、cf-auth(cookie + flag — 用于 验证 套件 cookie 路径,不要复制其 OAuth/业务页面)。

1. 接入包 + 样式 + 全局 toast

// main.ts
import { createApp } from 'vue'
import App from './App.vue'
import '@usethink/cf-admin-fe/styles' // 或仅 primitives,见 assets/admin.css
createApp(App).use(router).use(i18n).mount('#app')
<!-- App.vue:根节点挂一次 -->
<ToastContainer />

2. 导入清单(最大化复用套件——不要重新实现)

| 需求 | 从哪导入 | 备注 | |---|---|---| | 表格分页/每页条数 | useTablePagination | /composables | | 多选 + shift 连选 | useTableSelection | | | 确认 + 可选复选框 | useConfirmDialog + ConfirmDialog | | | Toast 队列 | useToast + ToastContainer | | | 顺序批量操作 | useAdminBatchOperation | | | 剪贴板 | copyWithToast(管理端主路径)/ copyText(按钮反馈)/ writeClipboardText(静默或降级) | | | 弹窗 / 分页外壳 | AdminModal / AdminPagination | | | 系统配置卡片 | ConfigField | 枚举 + 分单位金额的超集 | | 侧边栏外壳 | AdminShell + useAdminSidebar | 菜单数据留在产品中 | | Bearer token 会话 | createAdminTokenSession | 多 key / 伪装 = 产品侧 | | Cookie 本地守卫标志 | createAdminFlagSession | HTTP cookie 是产品侧;flag 属于套件 | | 管理端 fetch | createAdminRequest | http-ok | ok-envelope;cookie:credentials + onSuccess | | 401 → 登录页 | createAdminUnauthorizedHandler | 只注入 clearSession | | 路由守卫 | decideAdminRouteAccess | 之后再加产品专属规则 | | 登录重定向 | resolveAdminLoginRedirect | 防开放重定向 | | i18n 种子 | mergeAdminKitMessages | /i18n — 宿主覆盖优先 | | 日期 | formatDate 等 | /utils | | 异常转字符串 | toErrorMessage | toast / loader onError | | 批量 toast 色调 | resolveBatchToastType / buildBatchToast | 纯函数;产品保留 i18n 键 | | 批量数量上限守卫 | checkAdminBatchLimit | 默认 20 = auth 风格;对接 max(N) 的 API 须传 { limit: N }(如 shop 批量删 200) | | 列表 limit/offset(字符串) | buildAdminOffsetParams / applyAdminOffsetParams | URLSearchParams / query string;产出 { limit: string, offset: string } | | CSV 导出 | downloadCsv, safeCsvCell | 防公式注入 | | 遮罩滚动锁 | lockBodyScroll / unlockBodyScroll | 引用计数 | | 分 ↔ 元 | formatCents, parseYuanToCents | 多币种仍属产品侧 |

分页形态(必读,防误用):

| 后端契约 | 做法 | 参考 | |---|---|---| | Query:limit/offset 字符串URLSearchParams) | buildAdminOffsetParams(page, limit)applyAdminOffsetParams | cf-lottery 平台审计 / 租户 / webhook / 兑换码 | | Body 或类型化 filter:limit/offset 数字 | 产品手写 offset: (page - 1) * limit(数字) | cf-shop Balance / Recharges / Vouchers 等 | | Cursor | 产品自管;勿套 offset helper | shop 部分订单/日志列表 |

不要为了「用上 helper」把 number body 改成 string query。number 形态 helper 仅当 ≥2 产品 同形复制时再提案(观察期,见 docs/002 §5.8)。

优先使用 子路径 导入(/composables/utils/components/*.vue/i18n),避免 Vitest 解析根 SFC 桶文件。

3. 最小产品胶水层(保持精简)

// useAdminAuth — shop 简化版(见 recipes/useAdminAuth.shop.ts)
import { createAdminTokenSession } from '@usethink/cf-admin-fe/composables'
const session = createAdminTokenSession({ storageKey: 'admin_token' })
export const readAdminToken = () => session.readToken()
export function useAdminAuth() {
  return { token: session.token, isLoggedIn: session.isLoggedIn, setToken: session.setToken, clearToken: session.clearToken }
}
// useAdminRequest — 尽量复用套件工厂
import { createAdminRequest } from '@usethink/cf-admin-fe/composables'
import { createAdminUnauthorizedHandler } from '@usethink/cf-admin-fe/utils'
import { readAdminToken, useAdminAuth } from './useAdminAuth'

const onUnauthorized = createAdminUnauthorizedHandler({
  clearSession: () => useAdminAuth().clearToken(),
})

export const adminRequest = createAdminRequest({
  getToken: () => readAdminToken(),
  resultMode: 'ok-envelope', // shop 风格 body 可用 'http-ok'
  errorField: 'message',
  onUnauthorized,
})
// i18n — 填补套件键;菜单/品牌文案留产品
import { mergeAdminKitMessages } from '@usethink/cf-admin-fe/i18n'
messages: {
  'zh-CN': mergeAdminKitMessages(zhHost, 'zh-CN'),
  en: mergeAdminKitMessages(enHost, 'en'),
}
// router — 先走共享门禁
import { decideAdminRouteAccess } from '@usethink/cf-admin-fe/utils'
const d = decideAdminRouteAccess({ hasToken: !!readAdminToken(), requiresAuth: to.meta.requiresAuth, requiresGuest: to.meta.requiresGuest, fullPath: to.fullPath })
if (d.type === 'login') return { name: 'AdminLogin', query: { redirect: d.redirect }, replace: true }
if (d.type === 'home') return { name: 'AdminDashboard', replace: true }
// 产品专属:引导 / 平台角色 / …

产品可将路径别名(@/composables/*)保留为 再导出,这样视图无需大规模改写。

4. 必须留在产品侧的内容(不要强行塞进套件)

  • 业务管理端页面views/admin/*、抽奖 views/platform/* 页面主体)
  • 菜单项列表、页面标题、品牌名(传入 AdminShell
  • 业务 API 模块(api/admin.ts方法面 / 业务 DTO)— 只有传输层使用 createAdminRequest
  • 多租户伪装 / 平台角色键(抽奖 L3);使用 AdminShell 上的 #banner / #nav-extra 插槽
  • Cookie-flag 管理端(cf-auth)— 认证模型不同;仍可使用分页/toast/弹窗/utils
  • 订单状态 / 多币种金额库(@shared/money、订单状态映射)
  • 抽奖列表 UX 启发式(admin-list-ux
  • 产品错误类型(AdminApiError)与业务下载方法签名(围绕 createAdminRequestRaw 的 token 优先包装)
  • 套件原语之外的业务专属 CSS(伪装横幅、语言选择、平台导航强调色)

5. i18n

推荐: mergeAdminKitMessages(host, locale),这样新产品永远不会遗漏套件键。

宿主仍应提供产品菜单(adminLayout.menu*)与业务字符串。字段级配置文案:adminConfig.fields.<key>.{label,description,effect} — 缺失时 ConfigField 通过 $te 回退到后端文本。


公开 API 面

根 / composables

  • useTablePaginationuseTableSelectionuseConfirmDialoguseToastMAX_TOASTS
  • useAdminBatchOperationwriteClipboardTextcopyTextcopyWithToast(剪贴板 + 成功/失败 toast;与按钮内反馈的 copyText 互补)
  • createAdminTokenSessionuseAdminTokenSessionparseStoredAdminTokenreadAdminTokenFromStorageDEFAULT_ADMIN_TOKEN_TTL_MS
  • createAdminRequestcreateAdminRequestRawAdminRequestError
  • useAdminSidebar
  • useAdminListLoader — 列表页的竞态安全 loading / loadError / 序列

Utils(@usethink/cf-admin-fe/utils

  • 日期时间:formatDatetoDateTimeLocalValuedateTimeLocalToIsoisoToDateTimeLocalformatIpFingerprint
  • CSV:downloadCsvsafeCsvCell
  • 滚动:lockBodyScrollunlockBodyScrollisBodyScrollLocked
  • 金额最小单位:normalizeCentsformatCentsparseYuanToCents
  • 导航:createAdminUnauthorizedHandlerdecideAdminRouteAccessresolveAdminLoginRedirect
  • 错误:toErrorMessage
  • 批量 UX 纯函数:buildBatchToastresolveBatchToastTypeformatBatchCountsMessageformatDefaultBatchMixedMessagehasBatchFailurescheckAdminBatchLimitDEFAULT_ADMIN_BATCH_LIMIT默认 20;产品 max(N) 须显式 limit
  • 列表查询:buildAdminOffsetParamsapplyAdminOffsetParams(1-based 页码 → limit/offset 字符串,面向 URLSearchParams;不是 number body filter)
  • 日志元数据:formatMetadata(安全 JSON.stringify,抗循环引用;旧页可只用纯函数)
  • 系统配置引擎(纯函数):groupDefinitionsByNamecountSectionItemsbuildActiveGroupedDefinitionscountAdvancedItemsresolveSystemConfigSectionIdgetSystemConfigSectionlistedSystemConfigGroupsauditSystemConfigSectionCoverage — 分节 id 联合、分组列表、危险区、API 由产品侧负责

i18n(@usethink/cf-admin-fe/i18n

  • adminKitMessagesadminKitMessagesZhCNadminKitMessagesEnmergeAdminKitMessages

组件(@usethink/cf-admin-fe/components

  • AdminPaginationAdminModalConfirmDialogToastContainer
  • ConfigField(boolean / 枚举多选 / integer / cents / sensitive / textarea)
  • AdminShell(响应式侧边栏 + header / nav-extra / banner 插槽)
  • AdminLoginShell(展示型登录卡片外壳;认证表单由产品侧实现)
  • AdminMetadataDetail(审计日志详情弹层;依赖宿主 adminLogs.* i18n 键;新页优先;已有自研详情 markup 的旧页不必强迁)

类型(@usethink/cf-admin-fe/types

  • AdminSystemConfigFieldDefinition / 别名 AdminSystemConfigDefinitionConfigFieldStatus

样式

import '@usethink/cf-admin-fe/styles'
// 或按需:
import '@usethink/cf-admin-fe/styles/tokens.css'
import '@usethink/cf-admin-fe/styles/admin-primitives.css' // 含 .lang-select
import '@usethink/cf-admin-fe/styles/login-primitives.css'  // .admin-login / .login-card

Recipes

参见 recipes/README.md。列表骨架见 recipes/list-page.snippet.ts(含 string vs number offset、批量 limit 注释)。

说明书与接线对照

开发与封包

npm install
npm test
npm run type-check
npm run clean    # 清空 dist/,避免过期声明混入
npm run build    # clean + 仅生成 composables/utils/types 的 .d.ts
npm pack         # 触发 prepack→build;入口仍以 src/ 为准

封包注意:

  • filessrcdistrecipesREADME.mdLICENSE
  • dist/.gitignore 中,由 prepack 现场生成;不要手写或提交旧版根 dist/index.d.ts
  • 运行时 exports 指向 src/(Vue SFC + TS 源);dist 仅为声明辅助

版本记录

  • 0.1.x — 表格/toast/弹窗/分页原语
  • 0.2.0 — 深度提取:ConfigField、AdminShell、token/request 工厂、日期时间/CSV/滚动/分位金额工具
  • 0.2.1 — 导航助手、i18n 合并种子、recipes
  • 0.2.2 — 系统配置纯函数引擎、createAdminRequestRawAdminSystemConfigDefinition 别名
  • 0.2.3useAdminListLoaderAdminLoginShell + login-primitives CSS、原语中的 .lang-select
  • 0.2.4 — OTP 助手、更深化的 recipes
  • 0.2.5createAdminFlagSession、request onSuccess / credentials、cookie recipes(cf-auth 验证)
  • 0.2.6toErrorMessage、批量 toast/数量上限;formatMetadata + AdminMetadataDetailbuildAdminOffsetParams / applyAdminOffsetParamscopyWithToastrecipes/list-page.snippet.ts;封包 clean/prepack/LICENSE;完整说明书 docs/002_…
  • 0.2.6 文档收口(无 API 变更) — README/recipes/001/002 对齐:string vs number offset、batch limit 须跟后端 max、shop §5.8 接线对照、MetadataDetail「新页优先」
  • 0.2.7.table-wrap 去掉 scrollbar-gutter: stable,消除无溢出时表格右侧缺口
  • 0.2.8resolveAdminT / tKit;AdminShell / ConfigField / AdminMetadataDetail 契约测;npm run size-report(CSS/源码规模 + runtime dep 门禁)

许可证

MIT(见仓库根目录 LICENSE