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

urit-qf-ui

v0.2.5

Published

基于 ElementPlus 的业务组件库(UMenu / TableRender / FormRender / UInput 等)

Readme

urit-qf-ui

基于 ElementPlus 的业务组件库(UMenu / TableRender / FormRender / UInput 等)

读者:接手这个前端底座的使用方开发者 / AI 编码助手。 本文只讲**「怎么把它装进你的工程、样式从哪来、踩了什么坑怎么修」**。 各组件的字段级用法见:doc/菜单渲染器使用手册.mddoc/表格渲染器使用手册.mddoc/表单渲染器使用手册.md


0. 四条铁律

  1. 引 npm 包时,样式必须显式引入import 'urit-qf-ui/style.css'。不写这行 → 组件功能正常、样式全丢(最容易踩、且控制台无任何报错)。
  2. peerDependencies 要自己装,包管理器不会自动装。至少:vueelement-plus@element-plus/icons-vueaxiosmittmqttdayjs
  3. 引源码(alias 到 qfui/src)时不需要引 style.css,样式随 SFC 自带;但必须配 resolve.dedupe,否则会出现两份 Vue / element-plus 实例。
  4. 从「引源码的工程」往「引 npm 包的工程」拷页面时,样式不会跟着过去,一定要回目标工程的 main.ts 补第 1 条那行 import。

0.5 后端地址:默认「免配」,也可以配 baseUrl

库里的 Httpsrc/qf/http.ts)按这个优先级决定接口往哪发:

| 优先级 | 来源 | 什么时候用 | |--------|------|-----------| | 1 | QfOptions.baseUrlpublic/config/config.jsonqfOptions.baseUrl) | 前后端不同机/不同端口/走网关 —— 配了就以它为准 | | 2 | document.baseURI 的 origin | 免配默认值:后端 = 前端的 IP + 端口 | | 3 | window.$wujie.location.origin | 无界沙箱里取不到 <base> 时的兜底 | | 4 | window.location.origin | 最后兜底 |

// 想改地址,只动 config.json(不用改代码)
{ "qfOptions": { "baseUrl": "http://192.168.1.9:8085", ... } }

需要自己发请求、或想拿「本应用自己的根地址」时,用库里导出的同一个函数:

import {resolveBaseUrl} from 'urit-qf-ui'
const root = resolveBaseUrl()   // 独立运行 = 本站 origin;被无界嵌入 = 子应用自己的 origin

⚠️ 被无界(wujie)以微前端方式嵌入时,绝对不能用 window.location.origin 拼接口地址。 沙箱 iframe 的 srcblob: 空页(与主应用同源),子应用里的 window.location.origin 拿到的是主应用的域名/端口 → 请求会打到主应用去。实测(主应用 8111、子应用 8009):

| 写法 | 无界里 resolveBaseUrl() | 免配请求实际打到 | |------|--------------------------|------------------| | window.location.origin(≤0.2.4 的老写法) | http://127.0.0.1:8111 ❌ | http://127.0.0.1:8111/api/...(主应用) | | document.baseURI0.2.5 起) | http://127.0.0.1:8009 ✅ | http://127.0.0.1:8009/api/...(子应用自己) |

无界会给子应用注入正确的 <base>,所以 document.baseURI 在「独立运行」和「被嵌入」两种态下都指向应用自己。


1. 安装

npm i urit-qf-ui

# peerDependencies(不会自动安装)
npm i vue element-plus @element-plus/icons-vue axios mitt mqtt dayjs

2. 引入(两种方式,二选一)

方式 A · 引 npm 包(正式工程用这个)

// main.ts
import 'element-plus/dist/index.css'
import 'urit-qf-ui/style.css'        // ← 必须!少这行 = 只有 DOM 没有样式
<!-- 页面里 -->
<script setup lang="ts">
import {UMenu, TableRender, FormRender} from 'urit-qf-ui'
import type {MenuClickPayload} from 'urit-qf-ui'
</script>

若打包器不认 exports 字段,退回写完整路径 import 'urit-qf-ui/dist/style.css'

方式 B · 引源码(改库时要热更新调试时用)

// vite.config.ts
resolve: {
    dedupe: ['vue', 'vue-router', 'element-plus', '@element-plus/icons-vue', 'mitt', 'axios', 'dayjs'],
    alias: {
        'urit-qf-ui': fileURLToPath(new URL('../../sw_cp_qfui/qfui/src', import.meta.url)),
        // 或简写成 'qfui',手册里的示例代码用的是这个短名
    }
}

此方式不需要style.css(每个 SFC 自带 <style scoped lang="scss">),改组件后热更新即时生效。


3. 为什么 npm 包必须手写那行 import(事实,不是玄学)

库用 Vite lib 模式打包,产物是:

| 文件 | 内容 | |------|------| | dist/index.js | 纯 JS。各 SFC 的 <style scoped> 已被抽取走,文件里没有任何 CSS 注入代码(style.css / appendChild / document.head 出现次数均为 0),只保留了对外部依赖 element-plus/dist/index.css 的 import | | dist/style.css | 全部组件样式(约 11.8 KB,23 个 data-v-* scopeId) | | package.json | 未配 style 字段、未声明 CSS 副作用 → 没有任何工具会自动帮你引 |

所以 import {UMenu} from 'urit-qf-ui' 拿到的是"无壳组件"。这与 Element Plus 需要 import 'element-plus/dist/index.css' 是完全同一回事。

引源码为什么没事:组件源码里 <style scoped> 和 template 在同一文件,Vite 编译 SFC 时样式自动注入。


4. 排错表(现象 → 原因 → 修法)

| 现象 | 原因 | 修法 | |------|------|------| | 功能正常、样式全丢:左侧菜单没宽度/背景、菜单项挤在左上角、搜索表单 label 与输入框重叠、表格无边框、按钮错位,控制台零报错 | 引了 npm 包但没引它的样式 | 目标工程 main.tsimport 'urit-qf-ui/style.css' | | 引了 style.css 但样式仍不对 | 工程里存在两份 urit-qf-ui(或 dist 与 src 混用),data-v-* scopeId 对不上 | 统一只留一种引入方式;用下面的命令核对 scopeId | | Failed to resolve import "mqtt" | mqtt 是 peerDependency,未自动安装,但产物里有 import mqtt | npm i mqtt@^5.15.2 → 删 node_modules/.vite → 重启 dev server | | <el-select> 下拉选项一个都不显示,且无任何报错 | 出现两个 Vue / element-plus 实例(alias 引源码时,qfui/src 里的 import 'vue' 解析到了 qfui/node_modules 的另一份) | resolve.dedupe 加上 vuevue-routerelement-plus@element-plus/icons-vuemittaxiosdayjs | | 弹层(下拉 / 日期 / 消息框)被挡住不显示 | 页面引了 Quasar 的 quasar.css.fullscreenposition:fixed; z-index:6000 | 自己项目的 css 里覆盖 .fullscreen{z-index:auto !important};根容器别加 .fullscreen 类 | | 改完库源码,页面没变化 | 工程引的是 npm 包node_modules 里的旧 dist),不是源码 | 要么改成 alias 引源码(方式 B),要么重新 npm run build + 覆盖 dist + 删 node_modules/.vite | | 每页条数一多(≥20)表格就一路撑长,分页条被顶出容器、点不到;机构详情里的子表也把面板撑长 | 0.2.3 的 .table-gridTableGrid.vue 根节点)没参与 .table-container 的 flex 分配,而 EP 的 .el-table 默认 height: fit-content | 升级到 0.2.4+(该规则已内置到 TableRender.vue)。仍在旧版就在项目全局样式里补:.table-render .table-container .table-grid{flex:1;min-height:0;max-height:var(--table-grid-max-height,none)} + .table-render .table-container .table-grid>.el-table{height:100%};详见《表格渲染器使用手册》第 8 节 | | 被无界嵌入后,接口全打到主应用去(浏览器 Network 里请求域名/端口 = 主应用,改 config.jsonbaseUrl 又能通) | ≤0.2.4 的 Httpwindow.location.origin 兜底,而无界沙箱 iframe 是 blob:(与主应用同源)→ 拿到的是主应用 origin | 升级到 0.2.5+(改用 document.baseURI),见 §0.5;临时可在页面里自己拼地址并显式传 baseUrl | | 详情面板给了 #detail-extra 插槽后,YAML 里配的字段列表不见了 | 0.2.5 起 detail-extra 改为接管语义(默认 replace) | 想「字段列表 + 插槽共存」就加 detail-extra-mode="append";详见《表格渲染器使用手册》5.4 | | 点表单弹窗「取消」,对话框高度先塌一截再淡出 | 内容被 v-if="visible" 立刻卸载,而 el-dialog 是「先播退场动画、播完才移除 DOM」 | 升级到 0.2.5+(库内已改为内容常驻、清状态放 @closed);详见《表单渲染器使用手册》附录 A #9 | | 点「预览」(action: preview)/ 关详情抽屉,浮层唰一下就没、完全没有滑出动画 | 预览抽屉写成了 <el-drawer v-if="previewVisible" :model-value="true"> —— v-if 挂在可见性上:关的时候组件当场被卸载,el-drawer 的退场过渡根本没机会播(实测:leave-active 那一帧抽屉已不在,内容项数 4 → 0) | 升级到 0.2.5+(库内已改为「挂载开关 previewMounted」与「显隐开关 previewVisible」分离,内容清理放 @closed)。自己项目里若也有这类 v-if="visible" 的浮层,按同样思路拆开 |

验证样式真的进来了(10 秒)

# 1) 确认产物里 JS 与 CSS 是配套的:输出应为 "23 []" —— 23 个 scopeId 全部能在 index.js 里找到
node -e "const fs=require('fs');const c=fs.readFileSync('node_modules/urit-qf-ui/dist/style.css','utf8'),j=fs.readFileSync('node_modules/urit-qf-ui/dist/index.js','utf8');const h=[...new Set([...c.matchAll(/data-v-([0-9a-f]{8})/g)].map(m=>m[1]))];console.log(h.length, h.filter(x=>!j.includes('data-v-'+x)))"

# 2) 跑起页面后,F12 → Elements 里搜 data-v- ,能看到 .u-menu[data-v-xxxx] 这类规则就说明样式进来了

5. 开发调试(改本库源码)

预览组件效果

组件源码在 src/components/,预览页面在 examples/

cd qfui
npm install
npm run example

然后访问 http://localhost:5173/examples/

examples/App.vue 中添加或修改组件预览。

添加新组件

  1. src/components/ 创建组件文件
  2. src/index.ts 中导出组件
  3. examples/App.vue 中添加预览
  4. 运行 npm run example 查看效果

构建发布

# 构建 npm 包
npm run build

# 发布到 npm
npm publish

发布前检查清单

  1. release.bat(= release.py:先 npm run build,再让你选 patch / minor / major 并发布);手动发布才需要自己改 package.jsonversionnpm publish
  2. 确保 src/index.ts 导出了所有组件
  3. 运行 npm run build 构建
  4. 确认 dist/style.css 已生成且非空(本库样式全靠它,缺失 = 使用方全部无样式)
  5. 运行 npm publish 发布
  6. 发布后提醒使用方:升级版本 → 删各自 node_modules/.vite → 重启 dev server(vite 会把依赖 CSS 内联进预构建产物,不清缓存会继续用旧样式)
  7. (可选但推荐)发布后拉 tarball 核验产物:版本号对 ≠ 内容对。把 https://registry.npmjs.org/urit-qf-ui/-/urit-qf-ui-<版本>.tgz 下载解压,比对 dist/index.jsdist/index.umd.cjsdist/style.css 三个文件与本地 dist 的 md5 —— 必须全等,否则说明发布的是另一份构建