Skip to content

Releases: virtualman333/vui

v1.5.0

Choose a tag to compare

@virtualman333 virtualman333 released this 20 Sep 21:29

v1.5.0

修了什么

vui-calendar 的三个日期属性(modelValue / minDate / maxDate)以前是直接跟格子里的 YYYY-MM-DD 比字符串,而组件自己产出的日期是逐段补零的 —— 两边只有在「宿主也补零」时才可比。实测两种写法都会坏:

  • minDate="2026-9-1":'2026-09-01' < '2026-9-1' 成立(第 6 位 0 < 9),整个月的格子全部 disabled,一天都点不动,页面上没有任何报错;
  • modelValue="2026-9-01":选中项存的是宿主原文,跟格子的补零写法永远不相等,一格都不高亮(点一下之后又会自己「好」—— 最难查的那种)。

现在三个日期入参先解析、再收敛成组件自己的定长写法,边界比较与选中判等只发生在组件自己产出的字符串之间。

同族的三处一并修掉:

  • parseDate 补归一化守卫:越界日期不再静默滚到另一天(2026-02-30 → 3 月 2 日、2026-13-01 → 2027-01-01、2026-00-10 → 2025-12-10),一律返回 null;
  • startWeek 归一到 0~6(JS 里负数取模还是负的):传 -1 时表头只剩 6 个字、第一列空着,而格子按「周六开头」排 —— 表头与格子静默错开一位;13 / -8 这类写法还会算出负偏移把整张网格错位;
  • watch(modelValue) 对非法值不再原样塞进选中项。

测试

check:logic 接进 vui-calendar:78 → 91 条断言(登记 11 个组件),覆盖网格永远整周 / 首格偏移与表头同源 / 补位格跨月跨年 / 边界当天可选 / 禁用格不发事件 / 跨年翻页 / watch 归一化。

另加一条宽扫:拿宿主手写日期串直接跟组件自己产出的日期串比的组件,脚本里必须能看到日期收敛 —— 配判据自证,防宽扫恒假。

安装

npm i vui-uniapp@1.5.0

vui-uniapp v1.4.2

Choose a tag to compare

@virtualman333 virtualman333 released this 19 Sep 17:44

修复

vui-upload 预览打开的不是用户点的那一张

onPreview(index) 原先把「全量列表」和「过滤掉空 url 之后的列表」当作两个数组各按下标取值:

const urls = this.list.map((f) => this.fileUrl(f)).filter((u) => !!u);
uni.previewImage({ urls, current: urls[index] || urls[0] });

只要列表里有一个条目拿不到 url(fileUrl 是 url || path || ''),.filter() 就会把后面的下标整体前移——urls[index] 指向的已经不是被点击的那一张;越界时还会静默退回 urls[0]。表现是「点第 3 张,打开的是别的图」,且不报错。

现在改为逐项配对({ url, at })再筛空,按原始下标找回目标位置;仅当被点的那一张自身也拿不到 url 时才退回第一张。

内部

  • check:logic 的真跑面从 3 个组件扩到 4 个(新增 vui-upload),断言 35 → 36 条。
  • 修掉该检查自己的一处假锁:组件枚举原先手抄成数组,「少抄一个组件」只会让循环少跑一圈、静默通过。现在组件路径是唯一登记处,并新增反向对账(文件里每声明一条 uni_modules/... 路径常量,都必须登记进枚举)。

自测

  • npm run check:all 15 条全绿
  • npm run check:h5:真构建 + 真浏览器渲染 5 个页面 + 探针页,全部留下组件痕迹
  • 负向验证:6 处单缺陷注入全部命中,源码 sha256 逐字节还原

v1.4.1 —— 三个纯函数组件算错了值

Choose a tag to compare

@virtualman333 virtualman333 released this 18 Sep 19:35

三个纯函数组件算错了值

都是「不影响语法、不影响产物生成、不影响文档登记,只影响用户拿到手的那个数字」的缺陷 ——
此前的校验链(含此前唯一会执行组件代码的 check:markdown)一条都拦不住。

vui-slider

  • 步长网格的锚点从 0 改为 min:min=10 / max=20 / step=3 的合法刻度是 10 / 13 / 16 / 19,
    旧实现按 0 对齐会算出 12 —— 拖出来的每一个值都不是你设的刻度,而且把滑块拖到最左边也拿不到
    min(拖到 0% 得 12、拖到 100% 得 18)。负区间(min=-5 / max=5 / step=2)同理。
  • 精度按 step 的小数位取:此前写死 2 位,step=0.001 时 0.123 被抹成 0.12(刻度直接被抹平);
    step=0.1 时也不会再产出 0.30000000000000004 这类浮点毛刺。
  • 默认 props(min=0)下行为与之前完全一致 —— 这是一次纯修复,不是行为变更。

vui-time-picker

  • min / max 先收成组件自己的精度再比较:边界允许写成 HH:mm 或 HH:mm:ss,而组件的精度由
    showSeconds 决定,直接比字符串会错 —— max="14:30:00" 会让一个不显示秒的组件吐出带秒的值
    (父组件收到的字符串与界面上看到的不是一个精度);min="09:00:30" 同理。
  • 现在不显示秒时上界向下取整、下界向上进位,两个方向都保证「收完之后仍然不越界」。

vui-pagination

  • current 同时收上下界:此前只收下界。条数变少之后(筛选、删掉一行)父组件手里的页码可能比
    总页数大,而页码列表里的页号最大只到 pageCount —— 两边对不上时一页都不会被高亮,
    用户看到的是「一页都没选中」;点「上一页」还会从那个越界值减 1,一次点击直接跳到最后一页。
  • 收窄只影响展示与高亮,update() 抛给父组件的值不变。

新增 check:logic

scripts/check-logic.js(26 条断言,已进 check:all)—— 与 check:markdown 同一套
@vue/compiler-sfc 求值方式,直接调上述三个组件的纯函数入口。脚本里记着两个「探针自己撒谎」的坑:
sliderAt 必须默认 modelValue: null(否则组件里的 if (value === this.modelValue) return
让「拖到 0」一次都不 emit)、pagination 那条必须单开实例(if (target === this.current) return
会把同一个 vm 上的第二次调用挡掉)。

修掉一处「不会响的检查」

check:rules 的 jsdoc-first 此前只判「export default 之前有没有 /**」,而辅助函数的注释同样
满足这个形状 —— 本轮把 decimalsOf 的 /** 排在组件描述之前时它一次都没响过,而产物侧已经印出
辅助函数的第一行(README / API.md 的描述列)且 8 个 prop 全部报「JSDoc 里没有对应的 @property」。
AGENTS.md 第四节本来就写着「首块 JSDoc 必须存在且是 <script> 中第一个 /** */ 块」——
文档没错,是检查只做了前半句。现在拆成两向(jsdoc-first / jsdoc-desc-is-first),
负向注入已验证两条都会红。


自测:npm run check:all 15 条全部通过。未做 H5 / 真机实跑(见 AGENTS.md 第八节末)。

vui-uniapp 1.4.0 —— 新增 vui-source-list,并把「数量声称」钉到独立真值上

Choose a tag to compare

@virtualman333 virtualman333 released this 17 Sep 22:02

新增组件

vui-source-list —— 引用来源列表(第 49 个组件)

展示 AI 回答引用的来源(RAG / 联网检索),补齐对话链路上「回答提到了出处,界面却没地方显示」这一环。

能力 说明
两种入参 直接给 URL 字符串,或给 { title, url, domain, snippet, tag, id } 对象;空标题 / 非对象一律丢弃,不渲染空壳
序号角标 showIndex,与正文里的 [1] 角标对得上
站点名 优先用 domain,否则从 url 取主机名并去掉 www.
多行截断 maxTitleLines / maxSnippetLines,传 0 表示不截断
紧凑形态 variant="compact" 收成单行标签流,适合放在回答下方
角标联动 activeIndex 可传序号(从 1 开始)或来源 id,与正文角标联动高亮
不代开链接 组件只发 select 事件,开不开、怎么开由使用方决定(H5 window.open / 小程序 web-view 页)

顺带修掉一条已经真实发生过的漂移

README 特性列表里的「N 个 AI 组件」此前是生成器模板里手抄的字面量。加第 48 个组件(vui-count-to)时它没跟着动,于是同一份 README 里「48 个组件」与「11 个 AI 组件」并存 —— 而 AI 分类下已经有 12 个。

check:gen 查不出来:它只比对「重新生成 vs 已提交」,两边带着同一个错数字。现在改为 %(ai_count)d,与 comp_count 同源。

check:category 新增第 5 条不变量:数量声称 vs 独立真值

  • 抓出 README 里每处「N 个组件 / N 个 AI 组件」(含 **加粗** 与中间带修饰语的形态),与别处的真值对账:组件数取自文件系统、AI 组件数取自 CATEGORY 白名单;
  • 演示页 pages/demo/ai.vue 的 hero 文案是同一种声称、但没有生成器兜底,一并钉住;
  • 扫描面为空(正则失灵)时直接失败,绝不在空集上全绿;
  • 属性 / 事件两个数故意不对账:它们由同一个表达式算出来直接填进同一句话,没有第二个来源可比,硬造一份只会得到一条恒真的断言。

自测

  • npm run check:all 13 条全绿(check:markdown 79 项);
  • 负向注入 15 处单缺陷全中,含 1 处反向对照(把新断言改成恒真后,手抄数字的注入不再被判出),逐字节 sha256 还原。

完整变更:v1.3.0...v1.4.0

v1.3.0 · 换肤时不再有组件掉队

Choose a tag to compare

@virtualman333 virtualman333 released this 16 Sep 17:03

v1.3.0 · 换肤时不再有组件掉队

npm i vui-uniapp@1.3.0

这一版修的是什么

check:theme 建立时就记下 12 处历史硬编码色值作为「只减不增」的棘轮基线。
它们正是「颜色不走主题变量」这个问题的活样本:用户改 uni.scss 换肤之后,
这几处不会跟着变,而且不报错。

基线现在归零,抓到的是:

  • 5 个组件各写了一遍 #f2f3f5 分隔线(主题层本来就有 $vui-bg-color-hover);
    棘轮归零后又抓出第 13 处(vui-card 的 border-top)—— 旧基线按
    组件名|字面量 计数,同一个组件里的第二处被同一条白名单顺带豁免了;
  • vui-scrollbar 的 #c0c4cc 就是 $vui-text-color-placeholder,值完全相同;
  • vui-voice-input 的 rgba(228,61,51,0.9) 就是 rgba($vui-error, .9);
  • vui-code 与 vui-markdown 各写了一份逐字相同的代码块配色
    (#282c34 / #abb2bf)—— 现在抽成 $vui-code-bg / $vui-code-color 一对变量;
  • vui-calendar 的禁用态文字 #e4e7ed 主题层没有等值变量,新增 $vui-text-color-disabled。

顺带修掉两个会让「走主题变量」自我拆台的缺陷

  1. inject-theme.py 只注入、不更新('$vui-primary:' in body 即跳过):
    主题层新增的变量永远进不了已有 48 个组件的兜底块,而 check:sfc 单独编译
    组件样式块(不预置 uni.scss)—— 老组件一旦引用新变量就报 Undefined variable。
    现改为与 THEME_BLOCK 不一致就刷新(幂等,重复跑输出「已是当前版本: 48」)。
  2. check-theme.js 把变量派生的色值判成硬编码:rgba($vui-error, .9) 第一个
    通道解析出 NaN → 判为非中性 → 报违规。也就是说「把硬编码改成变量」反而会让
    校验变红,等于把人逼回硬编码。现在识别 $ 通道并单独计数。

现在是一律失败,没有豁免通道

check-theme.js 从 inject-theme.py 的 THEME_BLOCK 解析变量清单,逐个组件比对
「兜底块变量清单 == 主题层清单」(此前无人保证,也不报错);解析不出来时
直接失败而不是打一行警告 —— 检查自己静默消失是本仓最贵的一类回归。

BASELINE 现在是空对象。这不是关掉检查:它是无条件失败,从此没有白名单。

自测

  • npm run check:all 8 道校验全绿(含 SFC / 类型 / 产物一致性 / tarball 清单)。
  • 7 处单缺陷注入逐条命中对应结论,含一条反向对照:把「硬编码 + 基线豁免」原样
    重建 → 必须仍然放行,证明棘轮归零没有变成「一律报错」。源码 sha256 逐字节还原。
  • prepublishOnly 已随本次发布跑过完整校验链。

v1.2.0 — 新增数字滚动组件 vui-count-to

Choose a tag to compare

@virtualman333 virtualman333 released this 16 Sep 00:48

新增第 48 个组件 vui-count-to。此前 47 个组件里没有任何数据展示型组件 —— Progress 是唯一沾边的,但它表达的是「比例」而不是「数值」,金额 / 用量 / 统计数字这类需要滚动动画的场景只能自己写。

新增 <vui-count-to>

场景 写法
金额 <vui-count-to :end="1234567.89" :decimals="2" separator="," prefix="¥" /> → ¥1,234,567.89
用量 <vui-count-to :end="98304" separator="," suffix=" tokens" />
  • 属性:start / end / duration(传 0 直接显示终值)/ decimals / separator(千分位)/ prefix / suffix / autoplay / easing(linear、easeOutQuad、easeOutCubic)/ color / fontSize / bold
  • 方法:restart() 重播、reset() 立即跳终值
  • 事件:finish(带终值)、click

两个刻意的实现选择

  1. 用 setTimeout 递归而非 requestAnimationFrame —— 后者在小程序 / app-nvue 各端实现不一致,setTimeout 跨端最稳;
  2. 用 Date.now() 时间差而非帧计数推进进度,掉帧时动画不会变慢或超时。

数字用 tabular-nums 等宽渲染,滚动过程中整串数字不会左右抖动。重复调用 restart() 会先清掉上一轮定时器;卸载时清理定时器,不泄漏。

其它

  • 演示页 pages/demo/demo.vue 增加 CountTo 卡片(含重播按钮)
  • scripts/gen-docs.py 的 CATEGORY 登记该组件(API 文档与 README 清单由它驱动)
  • 版本 1.1.0 → 1.2.0(新增组件属 minor),48 个组件 package.json 同步

自测

  • 组件真实逻辑 34 项断言全通过(用 @vue/compiler-sfc 解析出选项对象后在 Node 里驱动真实逻辑)
  • npm run check:sfc 48/48、check:template 48/48、check 通过
  • npm pack 产物含 uni_modules/vui-count-to(581.3 kB)

npm registry 上的 1.2.0 尚未发布(本环境不允许执行 npm publish)。需要时执行 npm publish --access public。
建议先 publish 1.2.0 再跑 npm run release —— release.js 是无条件递增版本的,直接跑会升到 1.2.1 而跳过 1.2.0。