Repository navigation
Releases: virtualman333/vui
Release list
v1.5.0
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
修复
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:all15 条全绿npm run check:h5:真构建 + 真浏览器渲染 5 个页面 + 探针页,全部留下组件痕迹- 负向验证:6 处单缺陷注入全部命中,源码 sha256 逐字节还原
v1.4.1 —— 三个纯函数组件算错了值
三个纯函数组件算错了值
都是「不影响语法、不影响产物生成、不影响文档登记,只影响用户拿到手的那个数字」的缺陷 ——
此前的校验链(含此前唯一会执行组件代码的 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,并把「数量声称」钉到独立真值上
新增组件
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:all13 条全绿(check:markdown79 项);- 负向注入 15 处单缺陷全中,含 1 处反向对照(把新断言改成恒真后,手抄数字的注入不再被判出),逐字节 sha256 还原。
完整变更:v1.3.0...v1.4.0
v1.3.0 · 换肤时不再有组件掉队
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。
顺带修掉两个会让「走主题变量」自我拆台的缺陷
inject-theme.py只注入、不更新('$vui-primary:' in body即跳过):
主题层新增的变量永远进不了已有 48 个组件的兜底块,而check:sfc单独编译
组件样式块(不预置uni.scss)—— 老组件一旦引用新变量就报 Undefined variable。
现改为与 THEME_BLOCK 不一致就刷新(幂等,重复跑输出「已是当前版本: 48」)。check-theme.js把变量派生的色值判成硬编码:rgba($vui-error, .9)第一个
通道解析出 NaN → 判为非中性 → 报违规。也就是说「把硬编码改成变量」反而会让
校验变红,等于把人逼回硬编码。现在识别$通道并单独计数。
现在是一律失败,没有豁免通道
check-theme.js 从 inject-theme.py 的 THEME_BLOCK 解析变量清单,逐个组件比对
「兜底块变量清单 == 主题层清单」(此前无人保证,也不报错);解析不出来时
直接失败而不是打一行警告 —— 检查自己静默消失是本仓最贵的一类回归。
BASELINE 现在是空对象。这不是关掉检查:它是无条件失败,从此没有白名单。
自测
npm run check:all8 道校验全绿(含 SFC / 类型 / 产物一致性 / tarball 清单)。- 7 处单缺陷注入逐条命中对应结论,含一条反向对照:把「硬编码 + 基线豁免」原样
重建 → 必须仍然放行,证明棘轮归零没有变成「一律报错」。源码 sha256 逐字节还原。 prepublishOnly已随本次发布跑过完整校验链。
v1.2.0 — 新增数字滚动组件 vui-count-to
新增第 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
两个刻意的实现选择
- 用
setTimeout递归而非requestAnimationFrame—— 后者在小程序 / app-nvue 各端实现不一致,setTimeout跨端最稳; - 用
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:sfc48/48、check:template48/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。