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

keel-uni-app-kit

v0.0.1

Published

uni-app 项目基础设施工具包 — HTTP 客户端、AES-256-CBC+HMAC-SHA256 加密、状态管理、路由、通用组件、通用工具等

Readme

keel-uni-app-kit

uni-app 项目基础设施工具包 — 为 Vue 3 + TypeScript + uni-app 项目提供开箱即用的核心能力。

特性

  • HTTP 客户端 — 基于 uni.request 封装,支持重试、取消、拦截器、加密
  • AES-256-CBC + HMAC-SHA256 加密 — 环境自动检测:H5 使用 Web Crypto API(性能最优),小程序降级到 crypto-js(兼容性最好)
  • 通用组件 — 18 个开箱即用的 UI 组件(空状态、弹窗、导航栏、列表容器等)
  • 通用工具 — 缓存、存储、日志、错误处理、HTML 清理、格式化、验证
  • Vue Composables — 屏幕信息、分页列表、登录守卫、定时器、防抖、倒计时等
  • Store 辅助 — Pinia 初始化 + uni-app 持久化适配器 + 用户/应用 Store 工厂
  • 路由模块 — 路由拦截器框架、RouteHelper 基类
  • Tabbar — 自定义 Tabbar 状态管理
  • 配置工厂 — UnoCSS / Vite / TypeScript / ESLint / Commitlint 共享配置
  • 共享样式 — 主题变量、通用样式、骨架屏、响应式工具、mixins

安装

# pnpm workspace 本地引用
pnpm add keel-uni-app-kit

# 需要的 peer dependencies
pnpm add @dcloudio/uni-app dayjs vue-i18n pinia pinia-plugin-persistedstate

0.0.2 迁移说明

  • KitLoadMore 移除 loading / noMore 布尔兼容入参,仅保留 statusloading | noMore | error | more)。
  • setAutoCurIdx() 不再依赖 getCurrentPages() 回退检查,未命中时直接归零,行为更可预测。
  • createUnoConfig() 移除 @unocss/preset-legacy-compat 预设,项目侧可删除该依赖。
  • components 子路径类型导出改为 src/components/index.ts 内联导出,不再从 .vue 文件透传类型。

模块导入路径

| 模块 | 导入路径 | 说明 | |------|----------|------| | HTTP 客户端 | keel-uni-app-kit/http | createHttpClient, 请求辅助 | | AES-256-CBC + HMAC-SHA256 加密 | keel-uni-app-kit/encrypt | createAESCBCHMACAdapter, getCryptoProvider, isUsingNativeProvider | | 通用工具 | keel-uni-app-kit/utils | storage, logger, debounce 等 | | Composables | keel-uni-app-kit/composables | useScreen, usePaginatedList 等 | | Store 辅助 | keel-uni-app-kit/store | createUserStore, createAppStore | | 路由 | keel-uni-app-kit/router | createRouteInterceptor, RouteHelper | | Tabbar | keel-uni-app-kit/tabbar | registerTabbarPaths, setCurIdx | | i18n | keel-uni-app-kit/locale | createAppI18n | | 插件 | keel-uni-app-kit/plugins | createPluginInstaller | | 组件 | keel-uni-app-kit/components | KitEmptyState, KitCustomModal 等 | | 常量 | keel-uni-app-kit/constants | API_CONSTANTS, PAGINATION 等 | | 样式 | keel-uni-app-kit/style/* | SCSS 文件 | | 配置工厂 | keel-uni-app-kit/config/* | vite, eslint, commitlint, uno | | Vite 插件 | keel-uni-app-kit/vite-plugins | 原生资源复制, manifest 同步 | | 类型定义 | keel-uni-app-kit/types | PageReq, PageRes 等 | | Tabbar 配置 | keel-uni-app-kit/tabbar/config | TABBAR_STRATEGY_MAP |


新项目接入指南

第 1 步:添加依赖

cd your-uni-app
pnpm add keel-uni-app-kit
# 或本地链接
pnpm link ../../keel-uni-app-kit

第 2 步:配置 ESLint + Commitlint

// eslint.config.mjs
export { default } from 'keel-uni-app-kit/config/eslint'

// .commitlintrc.cjs
module.exports = require('keel-uni-app-kit/config/commitlint')

第 3 步:配置 Vite

// vite.config.ts
import {
  getBuildConfig,
  getCrossOriginIsolationHeaders,
  getEsbuildConfig,
  getServerProxy,
  getVueDefineFlags,
} from 'keel-uni-app-kit/config/vite';

export default defineConfig(({ mode }) => ({
  build: getBuildConfig(mode),
  esbuild: getEsbuildConfig(VITE_DELETE_CONSOLE === 'true'),
  define: getVueDefineFlags(),
  server: {
    headers: getCrossOriginIsolationHeaders(),
    proxy: getServerProxy(VITE_SERVER_BASEURL, VITE_API_PREFIX),
  },
}));

第 4 步:引入共享样式

App.vue 中引入(仅在此处引入一次,勿在 style/index.scss 中重复引入):

<style lang="scss">
// SDK 共享样式(主题变量、通用工具类、响应式工具)
@import 'keel-uni-app-kit/style/index.scss';
// 项目自有样式(覆盖 SDK 默认值)
@import '@/style/common.scss';
</style>

第 5 步:初始化核心模块

// src/utils/auth.ts — 创建认证工具
import { createAuthUtils } from 'keel-uni-app-kit/utils';

export const { getSessionId, setSessionId, clearSessionId, isSessionValid } = createAuthUtils({
  sessionDuration: 30 * 24 * 60 * 60 * 1000,
  storageKeys: { sessionId: 'SESSION_ID', sessionExpiry: 'SESSION_EXPIRE' },
});

// src/http/client.ts — 创建 HTTP 客户端
import { createHttpClient, createAESCBCHMACAdapter } from 'keel-uni-app-kit/http';

export const { http, httpGet, httpPost } = createHttpClient({
  baseUrl: () => import.meta.env.VITE_SERVER_BASEURL,
  auth: {
    headerName: 'Authorization',
    getSessionId: () => getSessionId(),
    setSessionId: (id) => setSessionId(id),
    clearSession: () => clearSessionId(),
  },
  encryption: createAESCBCHMACAdapter({
    requestKeyHex: import.meta.env.VITE_AES_REQUEST_KEY_HEX,
    responseKeyHex: import.meta.env.VITE_AES_RESPONSE_KEY_HEX,
  }),
});

// src/store/user.ts — 创建用户 Store
import { createUserStore } from 'keel-uni-app-kit/store';

export const useUserStore = createUserStore({
  loginApi: AuthApi.loginByPassword,
  profileApi: AuthApi.getCurrentUser,
  wxLoginApi: AuthApi.wxMiniappLogin,
  logoutApi: AuthApi.logout,
  mapProfileToState: (profile) => ({
    nickName: profile.nickName,
    avatarUrl: profile.avatarUrl,
    phone: profile.phone,
  }),
});

组件使用指南

可用组件列表

| 组件名 | 导入标识 | 说明 | |--------|----------|------| | 空状态 | KitEmptyState | 预设类型(搜索、网络、错误等),支持主题和变体 | | 自定义弹窗 | KitCustomModal | 多类型(success/warning/error/info/login/confirm) | | 导航栏 | KitNavBar | 状态栏适配,固定定位,支持沉浸式 | | 列表容器 | KitListContainer | 加载状态、空状态、加载更多、错误重试 | | 加载更多 | KitLoadMore | 四种状态(loading/noMore/error/more) | | 筛选弹窗 | KitFilterPopup | 多分组、单选/多选、重置 | | 标签页 | KitTabs | 可滚动标签,下划线指示器 | | 筛选标签 | KitFilterTabs | 水平滚动筛选 | | 搜索栏 | KitSearchBar | 输入框 + 防抖搜索,支持地区选择、fixed、glass/transparent 变体 | | 操作栏 | KitActionBar | 底部操作栏,支持 fixed/placeholder/border、left 插槽、buttons 模式 | | 菜单项 | KitMenuItem | 列表菜单项,左图标/标题/右箭头 | | 倒计时 | KitCountdown | 时间/格式化/slot 自定义 | | 价格展示 | KitPriceDisplay | 分转元、划线价、面议 | | 状态标签 | KitStatusTag | 多颜色类型(primary/success/warning/danger) | | 骨架屏 | KitSkeletonLoader | 可配置行数和动画 | | 加载状态 | KitLoadingState | 全页面加载 spinner | | 图片占位 | KitImagePlaceholder | 图片加载中/失败占位 | | 自定义 TabBar | KitTabBar | 完整自定义底部导航 |

组件引入方式(推荐)

方式一:模板包装层(推荐) — 在项目中创建一个包装组件,通过 <template> 渲染 kit 组件:

<!-- src/components/common/empty-state/index.vue -->
<!-- 无插槽的组件 -->
<template>
  <KitEmptyState v-bind="$attrs" />
</template>

<script setup lang="ts">
import { KitEmptyState } from 'keel-uni-app-kit/components';

defineOptions({ inheritAttrs: false });
</script>
<!-- src/components/common/custom-modal/index.vue -->
<!-- 有插槽的组件:需要显式转发每个插槽 -->
<template>
  <KitCustomModal v-bind="$attrs">
    <template #default><slot /></template>
  </KitCustomModal>
</template>

<script setup lang="ts">
import { KitCustomModal } from 'keel-uni-app-kit/components';

defineOptions({ inheritAttrs: false });
</script>
<!-- src/components/common/nav-bar/index.vue -->
<!-- 多插槽组件:需要转发所有具名插槽 -->
<template>
  <KitNavBar v-bind="$attrs">
    <template #default><slot /></template>
    <template #left><slot name="left" /></template>
    <template #right><slot name="right" /></template>
  </KitNavBar>
</template>

<script setup lang="ts">
import { KitNavBar } from 'keel-uni-app-kit/components';

defineOptions({ inheritAttrs: false });
</script>

重要:小程序编译器要求每个组件都必须有 <template> 生成对应的 WXML。纯 JS export default KitXxx 不会生成模板文件,会导致 "component not found" 错误。v-bind="$attrs" 会自动透传所有 props 和事件监听器,配合 inheritAttrs: false 避免重复绑定。

建议:项目页面与业务组件统一只导入本地包装层 .vue;仅包装层中从 keel-uni-app-kit/components 导入,避免小程序组件解析不稳定。

方式二:直接引入 .vue 文件 — 适用于页面中直接使用(非组件注册场景):

<script setup lang="ts">
import KitEmptyState from 'keel-uni-app-kit/src/components/empty-state.vue';
</script>

<template>
  <KitEmptyState preset="search" action-text="重新搜索" @action="handleRetry" />
</template>

类型导入

import type {
  KitModalType,
  LoadMoreStatus,
  FilterTabOption,
  FilterOption,
  FilterGroup,
  FilterValues,
  StatusType,
  KitTabItem,
  ButtonConfig,
  SearchBarVariant,
  EmptyPreset,
  EmptyVariant,
} from 'keel-uni-app-kit/components';

工具函数与 Composables 使用指南

推荐的导出模式

在项目中统一通过 index.ts 桶文件管理导出,避免创建纯 re-export 中间文件:

// src/utils/index.ts
export * from './auth';                    // 有业务定制
export * from './format';                  // 有业务定制
export * from './page';                    // 有业务定制

// 直接从 kit re-export(无需中间文件)
export { debounce, throttle } from 'keel-uni-app-kit/utils';
export { logger, createLogger } from 'keel-uni-app-kit/utils';
export { storage } from 'keel-uni-app-kit/utils';
export { stripHtmlTags } from 'keel-uni-app-kit/utils';
export { handleError } from 'keel-uni-app-kit/utils';
// src/composables/common/index.ts
export { useCustomModal } from './use-custom-modal';  // 有业务定制

// 直接从 kit re-export(无需中间文件)
export { useScreen, getSafeAreaBottom } from 'keel-uni-app-kit/composables';
export { useDebounce } from 'keel-uni-app-kit/composables';
export { useInterval } from 'keel-uni-app-kit/composables';
export { useTimeout } from 'keel-uni-app-kit/composables';
export { usePaginatedList } from 'keel-uni-app-kit/composables';
export { useCountdown } from 'keel-uni-app-kit/composables';
export { useForm } from 'keel-uni-app-kit/composables';

判断何时需要中间文件

| 场景 | 是否需要中间文件 | 示例 | |------|----------------|------| | 纯 re-export,无任何业务逻辑 | 不需要 — 直接在 index.ts 从 kit 导出 | debounce, logger, storage | | 使用工厂函数注入业务配置 | 需要 | auth.ts(注入 storageKeys), http/client.ts(注入 auth adapter) | | 继承/扩展基类 | 需要 | router/routes.ts(继承 RouteHelper) | | 组合 kit 能力 + 业务逻辑 | 需要 | use-theme.ts(注入 AppStore + 颜色配置) | | 有大量直接引用者的转发文件 | 保留 — 改动引用路径风险高 | error-handler.ts(30+ 处引用) |


Store 模块使用

createUserStore — 用户 Store 工厂

import { createUserStore } from 'keel-uni-app-kit/store';

export const useUserStore = createUserStore({
  loginApi: AuthApi.loginByPassword,
  profileApi: AuthApi.getCurrentUser,
  wxLoginApi: AuthApi.wxMiniappLogin,
  logoutApi: AuthApi.logout,
  mapProfileToState: (profile) => ({
    nickName: profile.nickName,
    avatarUrl: profile.avatarUrl,
  }),
  extraState: {
    customField: '',
  },
  persistPaths: ['token', 'customField'],
});

createAppStore — 应用 Store 工厂

import { createAppStore } from 'keel-uni-app-kit/store';

export const useAppStore = createAppStore({
  extraState: {
    inviteConfig: null,
  },
});

createStoreSetup — Store 初始化

import { createStoreSetup, uniStorageAdapter } from 'keel-uni-app-kit/store';

export const setupStores = createStoreSetup({
  storageAdapter: uniStorageAdapter,
  afterSetup: () => {
    // 注册认证处理器到 HTTP 模块
  },
});

路由模块使用

// src/router/interceptor.ts
import { createRouteInterceptor } from 'keel-uni-app-kit/router';

export const initRouteInterceptor = createRouteInterceptor({
  needLoginPaths: ['/pages-user/*'],
  loginPath: '/pages/common/login/index',
  isLoggedIn: () => useUserStore().isLoggedIn,
  onNeedLogin: (redirectPath) => {
    uni.navigateTo({ url: `/pages/common/login/index?redirect=${redirectPath}` });
  },
});

// src/router/routes.ts
import { RouteHelper } from 'keel-uni-app-kit/router';

class AppRoutes extends RouteHelper {
  toHome() { this.switchTab('/pages/tab/home/index'); }
  toDetail(id: string) { this.navigateTo(`/pages/detail/index?id=${id}`); }
}

export const routes = new AppRoutes();

Tabbar 模块使用

// src/tabbar/store.ts
import {
  curIdx,
  tabbarItems,
  registerTabbarPaths,
  isPageTabbar,
  setCurIdx,
  setAutoCurIdx,
} from 'keel-uni-app-kit/tabbar';

// 注册 Tab 路径
registerTabbarPaths(
  ['/pages/tab/home/index', '/pages/tab/list/index', '/pages/tab/user/index'],
  {
    persist: true,
    storage: { getJSON: storage.getJSON, setJSON: storage.setJSON },
    items: [
      { pagePath: '/pages/tab/home/index', text: '首页', icon: 'i-home' },
      { pagePath: '/pages/tab/list/index', text: '列表', icon: 'i-list' },
      { pagePath: '/pages/tab/user/index', text: '我的', icon: 'i-user' },
    ],
  },
);

样式使用注意事项

  1. 仅在 App.vue 中引入一次 kit 样式,勿在 style/index.scss 中重复引入,否则会产生冗余 CSS:

    <!-- App.vue -->
    <style lang="scss">
    @import 'keel-uni-app-kit/style/index.scss';
    @import '@/style/common.scss';
    </style>
  2. 主题变量覆盖:在项目的 style/variables.scss 中覆盖 kit 的 CSS 变量:

    page {
      --theme-primary: #6366f1;
      --theme-primary-light: #818cf8;
      --theme-bg-color: #ffffff;
    }
  3. 响应式工具:kit 提供 Pad 适配的 CSS 变量和工具类:

    // 使用 kit 的 mixins
    @use 'keel-uni-app-kit/style/_mixins' as *;
    
    .my-component {
      @include spinner;        // 加载动画
      @include spinner-sm;     // 小尺寸加载动画
    }

发布与开发指南

依赖引用策略

本项目采用 link 开发 + 版本发布 双模式:

  • 日常开发:消费项目使用 "keel-uni-app-kit": "link:../../keel-uni-app-kit" 本地链接,改动即时生效,无需发版
  • 生产发布:通过 deploy.py 脚本一键发布到 npm,脚本会自动处理 link ↔ 版本号的切换

本包为源码分发包(直接发布 TypeScript 源码),消费项目通过自身的 Vite 工具链编译,无需构建步骤。

一键发布(推荐)

cd keel-uni-app-kit

# 自动 patch +1 并发布(0.0.1 → 0.0.2)
python deploy.py patch

# 自动 minor +1 并发布(0.0.2 → 0.1.0)
python deploy.py minor

# 指定版本号发布
python deploy.py 1.0.0

# 模拟发布(不实际执行)
python deploy.py patch --dry-run

# 发布 beta 版本
python deploy.py patch --tag beta

deploy.py 会自动:① 更新版本号 → ② 将消费项目 link: 切为 ^x.y.z → ③ 发布到 npm → ④ 恢复消费项目为 link: 。无需手动操作。

本地开发联调

消费项目 package.json 中默认已配置 link:,直接开发即可:

# 源码包,改动直接生效,无需 watch
cd ruiying/ruiying-app
pnpm dev

常规操作步骤

新增工具函数

  1. src/utils/ 下创建文件(如 my-util.ts
  2. src/utils/index.ts 中添加导出
  3. 消费项目中通过 import { myFunc } from 'keel-uni-app-kit/utils' 使用

新增 Composable

  1. src/composables/ 下创建文件(如 use-my-hook.ts
  2. src/composables/index.ts 中添加导出
  3. 消费项目中通过 import { useMyHook } from 'keel-uni-app-kit/composables' 使用

新增组件

  1. src/components/ 下创建 .vue 文件
  2. src/components/index.ts 中添加组件和类型导出
  3. 消费项目中创建薄包装文件或直接导入

修改共享样式

  1. 修改 src/style/ 下的 SCSS 文件
  2. 注意不要引入破坏性变更(如删除 CSS 变量),优先新增
  3. 所有消费项目会自动获取变更

修改共享配置

  1. 修改 config/ 下的配置文件
  2. 注意:config/vite.mjs 是正式导出文件,config/vite.ts 仅作为 TypeScript 源码参考

消费此包的项目

| 项目 | 路径 | 说明 | |------|------|------| | ruiying-app | ruiying/ruiying-app | 无人机俱乐部 uni-app | | mc-revenue-guide-app | mc-guide/mc-revenue-guide-app | 创收指南 uni-app |


目录结构

keel-uni-app-kit/
├── config/                  # 共享配置
│   ├── vite.mjs             # Vite 配置辅助函数(正式导出)
│   ├── vite.ts              # Vite 配置 TypeScript 源码
│   ├── eslint.mjs           # ESLint 配置
│   ├── commitlint.cjs       # Commitlint 配置
│   ├── uno.ts               # UnoCSS 配置
│   └── tsconfig.base.json   # TypeScript 基础配置
├── vite-plugins/            # Vite 插件
│   ├── copy-native-resources.ts
│   └── sync-manifest-plugins.ts
├── src/
│   ├── components/          # 通用 UI 组件(18 个)
│   ├── composables/         # Vue Composables(24 个)
│   ├── constants/           # 常量定义
│   ├── encrypt/             # AES-256-CBC + HMAC-SHA256 加密模块(环境自动检测)
│   │   ├── crypto-native.ts      # Web Crypto API 原生实现(H5 性能优化)
│   │   ├── crypto-provider.ts   # crypto-js 降级实现(小程序兼容)
│   │   ├── crypto-provider-factory.ts  # 加密器工厂(环境自动检测)
│   │   ├── aes-cbc-hmac.ts    # 加密适配器
│   │   ├── config.ts           # 白名单与配置
│   │   ├── hash.ts             # 密码哈希
│   │   └── types.ts            # 类型定义
│   ├── http/                # HTTP 客户端
│   ├── locale/              # i18n 初始化
│   ├── plugins/             # 插件安装器
│   ├── router/              # 路由拦截器
│   ├── store/               # Store 工厂
│   ├── style/               # SCSS 共享样式
│   ├── tabbar/              # Tabbar 状态管理
│   ├── types/               # TypeScript 类型
│   └── utils/               # 工具函数(26 个)
├── scripts/                 # 脚本工具
├── templates/               # 模板文件
├── package.json
├── README.md
└── CHANGELOG.md

技术栈

  • Vue 3.5+ / TypeScript 5.9+
  • uni-app 3.0+
  • Pinia 2.1+ / vue-i18n 9.0+
  • UnoCSS / Vite 5+
  • AES-256-CBC + HMAC-SHA256 加密(环境自动检测:H5 使用 Web Crypto API,小程序降级到 crypto-js)

加密方案说明

SDK 自动检测运行环境并选择最优加密实现:

| 环境 | 使用的实现 | 性能 | 兼容性 | |------|-----------|------|--------| | H5(支持 Web Crypto API) | Web Crypto API 原生 | ⚡ 性能最优 | ✅ 现代浏览器 | | H5(不支持 Web Crypto API) | crypto-js 纯 JS | 🟢 性能中等 | ✅ 全浏览器 | | 小程序 / App | crypto-js 纯 JS | 🟢 性能中等 | ✅ 全端兼容 |

检测 API

import { getCryptoProvider, isUsingNativeProvider, getProviderType } from 'keel-uni-app-kit/encrypt';

// 获取当前加密器类型
const providerType = getProviderType(); // 'native' | 'fallback'

// 检测是否使用原生加密器
if (isUsingNativeProvider()) {
  console.log('H5 端使用 Web Crypto API(性能最优)');
} else {
  console.log('使用 crypto-js 降级方案(兼容性最好)');
}

License

MIT