Conversation
- loading 状态:开启后图标内容被 spinner SVG 替换,自动开 spin 动画并挂 aria-busy="true",常用于异步操作中按钮的图标占位 - disabled 状态:仅对 clickable=true 生效,自动阻止 click 和键盘激活, 挂 aria-disabled="true" + tabindex="-1",外观降透明 + cursor: not-allowed - themePrefixMap:按 theme 自动映射 Iconify 前缀 (比如 outlined 走 material-symbols、filled 走 mdi),优先级 name 含 ':' > themePrefixMap 命中 > iconifyPrefix - 文档:新增加载状态、禁用状态、主题→Iconify 前缀映射 共 3 个章节, Props 表加 loading / disabled / themePrefixMap 三个新字段 - 测试:从 26 个扩展到 33 个,新增 loading 替换内容+spin+aria-busy、disabled 阻止 click 和键盘、disabled 不挂在非 clickable、themePrefixMap 命中前缀、 themePrefixMap 命中失败回退 iconifyPrefix、含冒号忽略两个映射、loading + spinDirection=ccw - 状态:components-diff.md / sidebar.ts / icon/index.ts 全部 95% -> 100% / 已完成 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… tagsDraggable) - optionLabelProp:已选展示用独立字段,下拉项仍按 label 渲染。字段缺失 回退到 label。多选 / tags 模式 tag 文本也走该字段 - showSearch:filterable 别名,与社区 API 对齐;与 filterOption=false 组合可作为远程搜索语义糖 - transitionName:浮层用 Vue <Transition> 包裹,默认 ccui-select-fade (淡入 + 4px 上滑),可换任意 transition 名搭配自定义 CSS;appear:true 让初次打开也走 enter 动画,配合 Teleport 时仍能正确触发 - tagsDraggable:多选 / tags 模式下用户可拖拽 tag 调整顺序,被拖中 tag 降透明,drop 目标高亮边框,松开后 update:modelValue 直接给出新顺序; use-select 内新增 reorderTagValue helper - 文档:新增 optionLabelProp、showSearch 别名、自定义浮层动画、拖拽排序 已选 tag 共 4 个章节,Props 表加 4 个新字段 - 测试:从 49 个扩展到 59 个,新增 optionLabelProp 单选展示、字段缺失回退、 多选 tag 显示、showSearch 启用搜索框、showSearch+filterOption=false 不过滤、transitionName 不破坏 dropdown、tagsDraggable 挂 draggable+grab 类、拖拽 reorder modelValue、同 tag drop noop、tagsDraggable=false 不挂 draggable - 状态:components-diff.md / sidebar.ts / select/index.ts 全部 95% -> 100% / 已完成 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- 键盘导航:↑/↓ 上下移动焦点;→ 展开节点或进入第一个子节点;← 折叠或回到
父节点;Home/End 跳首末可见节点;Enter / Space 触发选中(或勾选,当
checkable=true)
- roving tabindex:聚焦节点 tabindex=0,其它 -1;未聚焦时根容器可 Tab 进入
- focusedKey 受控:支持 v-model:focused-key,新增 update:focusedKey 和
focus-change 事件;prop 受控时内部 ref 不写
- 虚拟滚动:virtualScroll 启用后只渲染可视区 + 缓冲,每项 absolute 摆放;
新增 virtualItemHeight / virtualMaxHeight props
- autoScroll:聚焦变化后自动滚到可见区——虚拟模式用 virtual.scrollToIndex,
非虚拟用 el.focus({ preventScroll: false }),对 jsdom 没有 CSS.escape 兜底
- 抽公共 hook:把 use-virtual-list 从 select 移到 shared/hooks,
Select / Tree 共用,后续 TreeSelect / Cascader 也能复用
- 文档:新增键盘导航、虚拟滚动 2 章节;Props 表加 4 个新字段,事件表加
update:focused-key 和 focus-change
- 测试:从 31 个扩展到 43 个,新增 ↑/↓ 移焦点、→ 展开/移子节点、← 折叠/
移父节点、Enter 选中、Space + checkable 勾选、Home/End 跳首末、roving
tabindex、虚拟滚动只渲染可视区、disabled 阻止键盘、focusedKey 受控行为
- 状态:components-diff.md / sidebar.ts / tree/index.ts 全部 80% -> 95%
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ta 错误重试)
- showLine:每个节点按祖先深度自动渲染垂直连接线(绝对定位 __guide
span),新增 connector 插槽允许消费者替换每根 guide 内容
- 拖拽 hover 自动展开:dragover 在 inside 区超过 dragHoverExpandDelay
(默认 600ms)后自动 triggerExpand;drop / dragend / 离开 inside 都
会清掉计时器;视觉上挂 --hover-expand 类
- 拖拽 auto-scroll:dragAutoScroll 启用时(默认 true),dragover 接近
滚动容器顶/底 dragAutoScrollEdge(默认 32px)以内时按
dragAutoScrollSpeed(默认 12px/帧)滚动;用 requestAnimationFrame
持续推进,drop / dragend / 离边缘自动停
- loadData 错误状态 + retryLoad:runLoadData 抽出 try/catch,失败的
节点进 loadErrorKeys 集合并 emit load-error;switcher 渲染为红色
感叹号按钮,点击 retry。expose({ retryLoad, isNodeLoading,
hasLoadError }) 让父组件编程式重试
- switcher slot 扩展:除 expanded / node 外新增 loading / loadFailed,
让自定义 switcher 也能展示加载和错误态
- computePosition 对 jsdom 的 0 高度 rect 兜底为 'inside',避免 NaN
比较推到 'after' 导致测试假阴性
- onUnmounted 清理 hover 计时器和 auto-scroll RAF
- 文档:新增 showLine、拖拽 hover 自动展开、拖拽 auto-scroll、loadData
错误重试 共 4 章节;Props 加 4 个新字段、事件加 load-error、插槽加
connector、新增"组件方法"小节列出 expose 的 3 个 API
- 测试:从 43 个扩展到 50 个,新增 showLine 渲染 N 个 guide、connector
slot 自定义、drag hover-expand 在 delay 后展开、drop / dragend 取消
hover 计时、loadData 失败 emit load-error 和错误 switcher、点击错误
switcher 触发 retry、expose retryLoad / isNodeLoading / hasLoadError
- 状态:components-diff.md / sidebar.ts / tree/index.ts 全部 95% -> 100% / 已完成
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- 通用 / 导航 / 反馈 / 数据录入 / 数据展示 / 布局 / 其他 共 60 个组件 全部列出,旧版只列了 ~30 个 - Form (80%) 和 Table (85%) 标注剩余项 - Icon / Select / Tree 三个最近推到 100% 的标注关键能力 - 新增"还没交付的常见组件"表,列 P1-P3 路线图组件 - 在介绍段链到 docs-notes/components-diff/references/components-diff.md 作为详细的覆盖度记录 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Form.List:默认作用域插槽 (fields, { add, remove, move }),按 name path 自动拼接父级前缀,稳定 key 在 move 后不丢;支持 initialValue 与受控/非受控数组。
- Form.Provider:forms 注册表 + form-change / form-finish 聚合;getFieldsValue 暴露在 FormInstance 上。
- preserve:form-level 默认 true,item-level preserve 优先;卸载时按策略 deleteValueByPath 清理。
- FormItem 增加 formList prefix 注入与 onChangeCapture -> notifyFieldChange,驱动 Provider 联动。
- 文档增 Form.List / Provider / preserve 三段示例与参数表,sidebar 标 95%。
- vue-ccui.ts 增 FormList / FormProvider 运行时导出。
- 测试 32 -> 44(+12):动态字段、prefix 拼接、move/remove/批量删除、preserve 三档、Provider finish/change/forms 注册表。
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- column.fixed='left'|'right':按列宽累加偏移生成 sticky left/right;selection 列与 expand 列在存在左固定列或显式 fixed 时自动跟随;新增 has-fixed-left / has-fixed-right 阴影修饰类。
- expandable.expandedRowRender:受控 expandedRowKeys(v-model:expandedRowKeys + onChange)、defaultExpandedRowKeys、defaultExpandAllRows、rowExpandable、expandRowByClick、columnWidth/fixed;额外发出 expand 事件 (expanded, record)。
- column.onCell / column.onHeaderCell:返回 { rowSpan, colSpan, style, class };rowSpan === 0 / colSpan === 0 时跳过被吞并单元格不渲染。
- scroll: { x, y } 控制容器溢出和最小宽度,与固定列联动。
- 文档增固定列、展开行、合并单元格三段示例与完整参数/事件表,sidebar 标 95%。
- 测试 52 -> 64(+12):列重排顺序、左右偏移累加、selection 跟随、展开行受控/默认全展开/rowExpandable/expandRowByClick、onCell rowSpan/colSpan=0、onHeaderCell colSpan。
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- README 把 Form / Table 的备注从 "80%/85% 待补" 改为已交付能力清单。 - components-diff 头部 timestamp 增加本批次摘要(Form 44 用例 +12、Table 64 用例 +12),表格行从 80% / 85% 改为已完成,并在备注中列出 Form.List / Form.Provider / preserve、固定列 / 展开行 / onCell+onHeaderCell 的具体口径。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- packages/docs/index.md:首页 hero 四张特性卡换成「Vite 8 + Rolldown / 60 个组件 / TS + 800+ 单测 / SeedToken+MapToken」实际能力描述。 - components-diff.md:补 Batch 18(Form 44 用例 / Form.List + Provider + preserve)与 Batch 19(Table 64 用例 / 固定列 + 展开行 + 合并单元格)两段批次说明,把「P0:补齐核心复杂组件」标题改成「P0:核心复杂组件(已收口)」并列出每个组件的批次锚点,剩余低频项收进 P0 长尾,不再阻塞 P1。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
vp check --fix 把上一轮 Form / Table 95% 文档遗漏的格式补齐:TS 内联对象类型分隔符 `,` 改成 prettier 偏好的 `;`、Markdown 表格列宽重新对齐。仅格式调整,无内容变更。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Affix 此前 \`category: '其他'\` 不在 \`packages/cli/shared/constant.js\` 的 \`VITEPRESS_SIDEBAR_CATEGORY\`(通用 / 导航 / 反馈 / 数据录入 / 数据展示 / 布局)里。\`packages/cli/templates/vitepress-sidebar.js\` 走 \`categoryMap.has(info.category)\` 判断,命中不到只打一个 warning 就把组件跳过,导致 vitepress sidebar 一直没有 Affix 入口。 - \`packages/ccui/ui/affix/index.ts\`:修源头 category。 - \`packages/docs/.vitepress/config/sidebar.ts\`:在 导航 分类首项加 Affix 入口,保持手写风格(2 空格 / 单引号 / 无分号 / 尾随逗号),不让生成器机器排版覆盖。 - \`README.md\`:把 Affix 移到 \`### 导航\` 段,删除只剩 Affix 一个组件的 \`### 其他\` 段。 - \`docs-notes/components-diff/references/components-diff.md\`:表格 Affix / ConfigProvider / Util 三行从「其他」改成实际分类(导航 / 通用 / 通用),与代码 \`index.ts\` 一致;同时被 prettier 重新对齐了状态列列宽。 验证:从 \`packages/docs\` 跑 \`node ../cli/index.js create -t ccui --ignore-parse-error\` 不再有 \`组件 Affix 的分类 其他 不存在\` warning;从 \`packages/ccui\` 跑 \`pnpm test ui/affix --run\` 10 个用例通过。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
P1 第一项落地。新增 packages/ccui/ui/shared/utils/date.ts 作为后续 TimePicker / Range / Cascader 的共享底座,避免每个日期组件各自散用 dayjs:
- toDayjs(value, format?):把 string / number / Date / Dayjs / null 统一成 Dayjs,按 format 严格解析(dayjs/plugin/customParseFormat),失败返回 null。
- emitValue(dayjs, 'string' | 'date' | 'number', format):把内部 Dayjs 输出为外部 v-model 期望形态,避免把 dayjs 类型暴露给业务层。
- generateMonthGrid(viewMonth, weekStart):6×7 = 42 格 cell { date, day, isCurrentMonth, isToday },weekStart 0 周日开头、1 周一开头。
- isSameDay / isSameMonth / isToday 比较谓词。
DatePicker 80% 范围(packages/ccui/ui/date-picker/):
- v-model 受控/非受控 + valueFormat 三档:默认 'string' 按 format 输出;'date' 输出原生 Date;'number' 输出毫秒时间戳。
- format(默认 YYYY-MM-DD,dayjs token)/ placeholder / disabled / clearable(默认 true)/ size 三档 / status / autoFocus / inputReadOnly / popupClassName / transitionName / weekStart。
- disabledDate(current: Dayjs) => boolean 屏蔽不可选日期,禁用 cell 加 --disabled modifier 并不响应 click。
- placement 4 个方位(bottomLeft / bottomRight / topLeft / topRight,对齐 Ant Design 命名),内部常量表 PLACEMENT_TO_FLOATING 映射到 floating-ui 的 bottom-start / top-end,便于以后切定位库。
- popupAppendToBody / 自定义 getPopupContainer,复用 Select 同款 Teleport + Transition 模式 + @floating-ui/vue 的 flip + shift({ padding: 8 }) + offset(4)。
- Form 联动:通过 formItemInjectionKey inject validateStatus 合到 mergedStatus,FormItem 校验失败 root 自动加 --status-error;emitChange 同步触发 formItem.validate('change')。
- 同一天再点不重发 change(仅关闭面板,避免重复校验回路);打开时把 viewMonth 重置到选中月。
测试 40 用例(packages/ccui/ui/date-picker/test/date-picker.test.ts)覆盖:基础渲染、popup open/close、selection 三种 valueFormat、disabledDate、clearable 5 种组合、月/年 4 个箭头、grid 结构 + today 唯一 + 周日/周一两套周标签 + outside 月格子、size + status modifier、Form integration(findComponent.vm.$.exposed)、Teleport 两种容器。
文档(packages/docs/components/date-picker/index.md):基础 / 显示已选值 / 自定义格式(含 valueFormat 三档 demo)/ 禁用日期 / 三种尺寸 / 禁用与不可清除 / 表单联动 / 弹层容器;API Props 表 18 行 + Events 表 5 行 + 已知限制清单。
未交付(计入 P0 / P1 长尾):range 区间、week / month / year / quarter mode、showTime + TimePicker、presets / renderExtraFooter / showToday、locale 切换、键盘导航。
收口:
- packages/ccui/ui/vue-ccui.ts:DatePickerInstall + DatePicker 三处插入,按字母序对齐 ConfigProvider / Descriptions 之间。
- packages/docs/.vitepress/config/sidebar.ts:手写风格 +5 行加进 数据录入 分类(CheckBox 与 Form 之间)。
- README:### 数据录入 加 DatePicker 条目,组件计数 60 → 61,「还没交付的常见组件」表把 DatePicker / TimePicker 改成单条 TimePicker。
- components-diff.md:表格 +1 行 (DatePicker 数据录入 80%),组件计数 60 → 61,缺失清单复杂组件改 9 项 → 8 项剩余 + 1 项进行中,新增 Batch 20 写明能力 / 工程决策 / 验证结果,时间戳更新到 2026-05-09。
验证:
- vp check 通过(467 文件 prettier、294 文件 lint/type 全干净)。
- 从 packages/ccui 跑 pnpm test ui/date-picker --run 通过 40/40。
- 从 packages/docs 跑 node ../cli/index.js 没有 分类不存在 warning,DatePicker 出现在 sidebar 数据录入分类 status=80%。
- 仓库内 pnpm test --run 全量 879/881 通过;2 个失败(statistic countdown 11ms 时钟精度、float-button backTop window mock)在本提交前就已存在,单独跑 ui/statistic / ui/float-button 复现,与本次改动无关。
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
P1 第二项落地。复用 DatePicker 同款 dayjs 工具层(toDayjs / emitValue),扩展 packages/ccui/ui/shared/utils/date.ts 加一个通用列构造函数:
- buildTimeColumnValues(range, step, disabledValues?):输出 { value, disabled }[],TimePicker 三列(hour 0-23 / minute 0-59 / second 0-59)和未来 DatePicker showTime 都共用。step <= 0 兜底成 1,disabledValues 用 Set 标记。
TimePicker 80% 范围(packages/ccui/ui/time-picker/):
- v-model 受控/非受控 + valueFormat 三档('string' / 'date' / 'number',与 DatePicker 同款 emitValue 协议)。
- format 默认 HH:mm:ss(dayjs token)/ placeholder / disabled / clearable / size 三档 / status / placement 4 个方位(映射到 floating-ui) / popupAppendToBody / 自定义 getPopupContainer / autoFocus / inputReadOnly / popupClassName / transitionName。
- 三列控制:showHour / showMinute / showSecond 任意组合(关到只剩 1 列也能用);hourStep / minuteStep / secondStep 控制每列步长;disabledHours / disabledMinutes(hour) / disabledSeconds(hour, minute) 三层联动屏蔽。
- footer 双按钮 + showOk 行为分流:showOk=true(默认)点击单元格只更 pending、不 emit、面板不关,等点确定才提交并关;showOk=false 点击单元格立即 emit + 关。showNow 控制「此刻」按钮,showOk=false 模式下「此刻」也立即 emit + 关;两按钮都关时 footer 整段不渲染。
- pending 状态机:内部 shallowRef pendingDayjs,watch(selectedDayjs) 同步外部受控值变化,openPopup 时把 pending 重置到当前 selected(外部无值时回 dayjs().startOf('day')),避免上次面板状态泄漏。
- Form 联动:与 DatePicker 同套机制——formItemInjectionKey inject validateStatus,校验失败 root 加 --status-error;emitChange 同步触发 formItem.validate('change')。
测试 45 用例(packages/ccui/ui/time-picker/test/time-picker.test.ts)覆盖:基础渲染(默认/自定义 placeholder、3 类 modelValue + format + 无效值);popup open/close(click 切换 / outside / disabled / autoFocus);columns(默认 3 列、3 种 show-X 关闭、24 cells 全集、3 种 step 验证 cells 数 + 文本、selected modifier 三列定位);disabled values(disabledHours 命中、disabledMinutes 联动、disabled cell click 不变 pending);selection showOk=false 急切 emit 三档 valueFormat;footer showOk=true(hour click 只更 pending、ok 提交、now 设 pending 不关、now+ok 提交、showOk=false 时 now 立即 emit、both off 不渲染、自定义文案);clearable 4 种组合 + size 三档 + status;Form integration + Teleport 两种容器 + 外部 v-model 回写。
文档(packages/docs/components/time-picker/index.md):基础(默认 showOk)/ 选中即提交(showOk=false)/ 自定义格式(含 valueFormat 三档 demo)/ 步长 / 屏蔽时间(含 hour-minute 联动)/ 隐藏某列 / 三种尺寸 / 表单联动 / 弹层容器;API Props 表 27 行 + Events 表 5 行 + 已知限制清单(12 小时制 / 键盘 / 范围 / showTime / 滚轮 snap)。
未交付(计入 P1 / 后续批次):12 小时制 use12Hours、键盘导航、range 区间、showTime 嵌入 DatePicker、滚轮 snap。
收口:
- packages/ccui/ui/vue-ccui.ts:TimePickerInstall + TimePicker 三处插入,按字母序对齐 Tag / Timeline 之间。
- packages/docs/.vitepress/config/sidebar.ts:手写风格 +5 行加进 数据录入 分类(Switch 之后)。
- README:### 数据录入 加 TimePicker 条目,组件计数 61 → 62,「还没交付的常见组件」表删掉 TimePicker 行。
- components-diff.md:表格 +1 行 (TimePicker 数据录入 80%),组件计数 61 → 62,缺失清单复杂组件改 8 项剩余 → 7 项剩余 + 2 项推进中(DatePicker / TimePicker),新增 Batch 21 写明能力 / 工程决策 / 验证。
工程决策:
- 复用 DatePicker 的内部抽象但不抽 use-popup hook:DatePicker / TimePicker 的 popup 渲染内容差别足够大(grid vs columns),抽象 hook 会要传入太多 render slot,损可读性。先保持两份相似代码,等推第三个浮层组件(Cascader / TreeSelect)再回头抽。
- showOk=true 是默认:与 Ant Design TimePicker 默认行为一致——避免每次微调都 emit 触发外部 reactive / Form rules。showOk=false 留给「快速选时间」场景。
- buildTimeColumnValues 输出 cell list 而不是 disabled 函数:数据规模小(最多 60 cell),用 Set 一次性求值后直接当 cell.disabled 用,computed 缓存命中也轻松。
- 不引入 dayjs 默认插件外的额外插件:date.ts 已经 extend customParseFormat,TimePicker 用的 hour() / minute() / second() / .hour(x) 都是核心 API,与上一批次工具层口径一致。
验证:
- vp check 通过(473 文件 prettier、298 文件 lint/type 全干净)。
- 从 packages/ccui 跑 pnpm test ui/time-picker --run 通过 45/45。
- 生成器 (node ../cli/index.js create -t ccui --ignore-parse-error) 无 warning,TimePicker 出现在数据录入分类。
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
P1 第三项落地。独立组件 packages/ccui/ui/range-picker/,复用 DatePicker 同款 dayjs 工具层(toDayjs / emitValue / generateMonthGrid / isSameDay)与 @floating-ui/vue popup 模式,零新增工具层。
设计:独立 c-range-picker 而非在 DatePicker 上加 mode='range'。现有 DatePicker 80% props 已不少,叠 range mode 会让 modelValue 类型分裂、disabledDate 签名分裂、hover 状态新增成 props,损耗 single 单选用户的可读性与测试隔离。Ant Design 也是分两个组件。
协议:
- v-model 是 [start, end] 数组,与 DatePicker 同款 valueFormat 三档:'string' → [string, string],'date' → [Date, Date],'number' → [ms, ms],全空时 v-model = null。
- change(value, [startStr, endStr]) 同时 emit 数组值与格式化字符串对。
- disabledDate(current: Dayjs) => boolean 一份共用,对 start/end 都生效(独立 disabledDate 留下一切片)。
双面板:
- 左 viewMonth,右 viewMonth + 1。一个 viewMonth 控制左面板,右面板永远 +1 跟随,避免左右独立 viewMonth 的同步成本。
- 左 panel header 只有 ‹ 上月 / « 上年;右 panel header 只有 下月 › / 下年 »。中间 label 不可点。
状态机 phase: 'start' | 'end':
- 打开面板时 phase=start;click end input 直接 phase=end。
- 第一次点击设 pendingStart、phase 切到 end、pendingEnd 重置为 null,不 emit、面板不关。
- 第二次点击若 cell.isBefore(pendingStart) 则 [s,e] = [e,s] 自动调换;emit + close。两次提交都满足 start <= end。
- 输出永远满足 start <= end。
hover in-range 预览:
- phase=end 且 pendingStart 已选时,cell mouseenter 把 hoverDate 设为该 cell;isCellInHoverRange 计算 min(start, hover) 与 max(start, hover) 之间(不含两端)的 cell 加 --in-hover-range 给用户「此刻提交将选这一段」的视觉反馈。
- mouseleave 不立即清空(避免 1px 间隙抖动),下次 mouseenter 覆盖;closePopup / phase 切换时统一清。
已确认 in-range:
- pendingStart && pendingEnd 都有时,两端之间的 cell 加 --in-range;两端本身加 --range-start / --range-end 与 --in-range 浅蓝背景配合画出连续段。
input 显示分流:
- 打开期间 startInputDisplay 显示 pendingStart、endInputDisplay 显示 pendingEnd——选 start 后右 input 立即换上 pendingEnd 状态,UI 反馈直观。
- 关闭时回退到 selectedStart / selectedEnd 受控值。
Teleport / Form 联动:与 DatePicker 同套机制(formItemInjectionKey + popupAppendToBody + getPopupContainer + floating-ui placement 4 个方位映射)。
测试 38 用例(packages/ccui/ui/range-picker/test/range-picker.test.ts)覆盖:基础渲染(默认/自定义 placeholder + separator + 3 类 modelValue + format + null);popup(start/end input 都能打开、outside 关、disabled 不开、双面板月相邻、autoFocus 落 start input);selection flow(首次只设 pending、二次 emit + close、end<start 自动调换、跨月 start-left-end-right、valueFormat 三档输出 + 类型校验);hover preview(in-hover-range 数量精确、phase=start 阶段无高亮、已确认 in-range 数量、range-start/end modifier 文本);disabledDate;月切换(左 prev、右 next 联动);clearable 4 种 + size 三档 + status;Form integration + Teleport 两种容器 + 外部 v-model 回写。
文档(packages/docs/components/range-picker/index.md):基础 / 显示已选 / 自定义格式(valueFormat 三档)/ 自动调换 / 禁用日期 / 自定义分隔符与占位 / 三种尺寸 / 表单联动 / 弹层容器;API Props 18 行 + Events 5 行 + 已知限制(preset / showTime / 独立 disabledDate / 键盘 / 响应式单面板)。
未交付(计入下一切片):preset 快捷预设、showTime 时间联动、start/end 独立 disabledDate、键盘导航、响应式单面板。
收口:
- packages/ccui/ui/vue-ccui.ts:RangePickerInstall + RangePicker 三处插入,按字母序对齐 Radio / Rate 之间。
- packages/docs/.vitepress/config/sidebar.ts:手写风格 +5 行加进 数据录入 分类(Radio 与 Select 之间)。
- README:### 数据录入 加 RangePicker 条目,组件计数 62 → 63。
- components-diff.md:表格 +1 行(RangePicker 数据录入 80%),组件计数 62 → 63,缺失清单复杂组件改 7 项剩余 + 2 项推进中 → 7 项剩余 + 3 项推进中(DatePicker 备注里说明 range 拆为独立组件,新增 RangePicker 单独一行),新增 Batch 22 写明协议 / 工程决策 / 验证。
工程决策:
- 不抽 use-date-popup 通用 hook:DatePicker / RangePicker / TimePicker 三个组件 popup 的 cell 渲染差异(grid / 双 grid / columns)足够大,emit 协议又不同(单值 / 数组 / 单值),抽出来要传一堆 render slot 反而损可读。等做第四个浮层组件(Cascader / TreeSelect)时再回头评估。
- emit 路径仅在第二次点击触发:第一次点击只更 pending,不发 update:modelValue 也不调 formItem.validate('change'),避免「点了 start 还没选完 end,Form rules 已经判半成品无效」这种回路。
- hover 不立即清空:mouseleave 不清 hoverDate,避免 1px 间隙抖动;closePopup / phase 切换统一清。
- isBefore 而不是 <:所有比较走 dayjs 的 isBefore(other, 'day') / isAfter(other, 'day'),按"日"粒度比较,防止外部 Date 携带时分秒导致同日误判。
验证:
- vp check 通过(302 文件 lint/type 全干净)。
- 从 packages/ccui 跑 pnpm test ui/range-picker --run 通过 38/38。
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
P1 第四项落地。复用 DatePicker / RangePicker / TimePicker 三个 P1 组件已经验证过的 popup 模式(@floating-ui/vue + Teleport + formItemInjectionKey 联动 + click outside),不抽公共 hook。
数据结构与 fieldNames:
- options 是递归 children 的树。fieldNames: { label?, value?, children?, disabled? } 把字段名映射到任意业务字段(默认 'label' / 'value' / 'children' / 'disabled')。
- 组件内统一通过 getOptionLabel / getOptionValue / getOptionChildren / isOptionDisabled 4 个 helper 读字段,所有渲染分支共用。
路径数组 v-model:
- v-model 永远是 (string | number)[] | null。findOptionPath 沿 options 一级一级查匹配 value 的节点,构造 selectedPath: CascaderOption[]。
- 任一级 value 在 options 中找不到则降级为空路径(input 显示空),避免外部脏数据导致渲染崩。
多列联动渲染:
- 内部 activePath 决定渲染哪几列。第 0 列永远是顶级 options,第 i 列是 activePath[i-1].children。
- 点击非叶子:activePath = activePath.slice(0, columnIndex).push(item.raw),自动截掉更深的列,下一列填新 children。
- 点击叶子:emit 完整路径数组 + close。
changeOnSelect:默认 false。开启后中间节点点击时也 emit 一次 update:modelValue 与 change,但不关闭面板,让用户继续展开下一级。任一时刻 v-model 总是反映「当前已确定的最深路径」。
change 事件双参:第一个参数是 (string | number)[] | null,第二个参数是 selectedOptions: CascaderOption[] 原始路径节点数组。
displayRender:默认 labels.join(separator),separator 默认 ' / '。传 displayRender(labels, selectedOptions) 完全自定义展示文本。
Teleport / Form 联动:与 DatePicker / RangePicker / TimePicker 同套(popupAppendToBody + 自定义 getPopupContainer + formItemInjectionKey 注入校验状态 + emit 时同步触发 formItem.validate('change'))。
空数据兜底:传 options: [] 时面板首列显示 notFoundContent(默认 '暂无数据')。
测试 39 用例(packages/ccui/ui/cascader/test/cascader.test.ts)覆盖:
- 基础渲染(默认/自定义 placeholder + separator + displayRender、modelValue 路径解析、找不到路径降级、null 兜底)
- popup(click 切换 / outside / disabled / autoFocus)
- column expansion(无值时 1 列、有值时 N+1 列、点击非叶子展开下一列、切换 sibling 截深列、active modifier 三列定位、expand-icon 仅非叶子有)
- selection(叶子提交完整路径并关、非叶子 changeOnSelect=false 不 emit、changeOnSelect=true 每级都 emit 但不关到叶子才关、change 第二参数是原始 options 数组、disabled item click 不 emit)
- fieldNames 自定义;clearable 4 种;size 三档;status;Form integration;Teleport 两种容器;外部 v-model 回写;notFoundContent 默认 + 自定义。
文档(packages/docs/components/cascader/index.md):基础 / changeOnSelect / fieldNames / 禁用某项 / 自定义 displayRender / 三种尺寸 / 表单联动 / 弹层容器;API Props 19 行 + Events 5 行 + 已知限制(multiple / showSearch / loadData / hover trigger / 键盘)。
未交付(计入下一切片):multiple 多选、showSearch 搜索、loadData 异步、expandTrigger='hover'、键盘导航。
收口:
- packages/ccui/ui/vue-ccui.ts:CascaderInstall + Cascader 三处插入,按字母序对齐 Card / CheckBox 之间。
- packages/docs/.vitepress/config/sidebar.ts:手写风格 +5 行加进 数据录入 分类(CheckBox 之前)。
- README:### 数据录入 加 Cascader 条目,组件计数 63 → 64,「还没交付的常见组件」表把 Cascader / TreeSelect 合行改为单条 TreeSelect。
- components-diff.md:表格 +1 行(Cascader 数据录入 80%),组件计数 63 → 64,缺失清单复杂组件改 7 项剩余 + 3 项推进中 → 6 项剩余 + 4 项推进中(Cascader 备注更新为已交付 80%),新增 Batch 23 写明协议 / 工程决策 / 验证。
工程决策:
- activePath 与 selectedPath 解耦:selectedPath 是从 modelValue 推导的「确定」路径,activePath 是面板上「悬停 / 编辑」中的路径。点击非叶子时只改 activePath,不动 selectedPath;只有叶子点击或 changeOnSelect=true 时才 emit 让 selectedPath 通过 modelValue 回写。这种解耦让用户可以在面板里自由展开探索,不会污染 v-model 的「确定」状态。
- watch(selectedPath, ...) 同步 activePath:外部 modelValue 变化时把 activePath 同步到新的 selectedPath,避免外部 setState 后面板上还停留在旧路径的展开状态。
- getOptionLabel 显式判 string/number/boolean:而不是直接 String(v)——后者对 object 会返回 [object Object] 这种无意义字符串。显式列出三种基础类型与 Select 的 labelAsString 一致。
- 不引入公共 popup hook:DatePicker / TimePicker / RangePicker / Cascader 四个浮层组件 popup 内部内容差异巨大(grid / columns / 双 grid / 多列 menu),抽出来要传太多 render slot 反而损可读性。同款决策第 4 次复用,等推到 5 个+ 浮层组件再回头评估抽离。
- 空 options 不进入选择流程:第 0 列直接渲染 notFoundContent 占位,避免空 ul + click 后进入"半空状态"。
验证:
- vp check 通过(306 文件 lint/type 全干净,485 文件 prettier 全干净)。
- 从 packages/ccui 跑 pnpm test ui/cascader --run 通过 39/39。
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
P1 数据录入复杂组件最后一项落地。本次最大的工程红利:popup 直接复用现有 c-tree 当浮层内容,TreeSelect 只做「外壳 + 状态桥接 + 输入框渲染」。
架构:
- TreeSelect 不重写 Tree 渲染,直接 h(Tree, props) 当 popup 内容。c-tree 已经支持 selectable / multiple / checkable / checkStrictly / selectedKeys / checkedKeys / expandedKeys / defaultExpandAll / fieldNames / blockNode / disabled 全套能力。
- fieldNames 双层映射:TreeSelect 对外暴露 { label, value, children, disabled }(与 Cascader / Select 一致),通过 toTreeFieldNames 内部转 c-tree 的 { title, key, children, disabled }。业务端只用一套字段名习惯。
v-model 类型分支:
- 单选 (multiple=false):modelValue 是 string | number | null
- 多选 (multiple=true):modelValue 是 (string | number)[] | null
- normalizeMultipleValue 把单值包成数组喂给 c-tree 的 selectedKeys / checkedKeys;emit 时单选只取 keys.at(-1),多选回数组(empty 转 null 与其他 picker 一致)。
三种交互模式:
- 单选 (multiple=false 默认):c-tree selectable + selectedKeys=[v]。点击任意节点(含父节点)→ emit + close。
- 多选 checkable (multiple=true treeCheckable=true 默认):c-tree checkable + checkedKeys=v + selectable=false。监听 check 事件 emit 数组,select 不响应。父子节点联动除非 treeCheckStrictly=true。
- 多选 selectable (multiple=true treeCheckable=false):c-tree multiple selectable + selectedKeys=v。监听 select emit 数组,不显示 checkbox。
多选 tags 渲染:
- buildNodeIndex 一次性扁平化整棵 treeData 成 Map<key, {label, disabled}>,从 modelValue 反查 label 拼成 tags。
- 超过 maxTagCount 折叠成 "+ N" 占位 tag。
- 单 tag 移除:removeTag(e, key) e.stopPropagation() 不触发面板打开,emitChange(filtered.length === 0 ? null : filtered)。
clear 一键清空:单选 / 多选都 emit null(与 Cascader / DatePicker 一致),stopPropagation 不触发面板打开。
Teleport / Form 联动:与前 4 个 P1 组件同套(popupAppendToBody + 自定义 getPopupContainer + formItemInjectionKey 注入校验状态 + emitChange 同步触发 formItem.validate('change'))。
空数据兜底:treeData: [] 时面板渲染 notFoundContent(默认 '暂无数据'),不触发 c-tree mount。
测试 43 用例(packages/ccui/ui/tree-select/test/tree-select.test.ts)覆盖:
- 基础渲染(默认/自定义 placeholder + modelValue label 反查 + 单值未知降级 + null 兜底)
- 多选渲染(tags 数量 + 内容、placeholder 占位、+N 折叠 tag、多选模式无 input 元素、tag close 单移除 + stopPropagation、最后一个移除 emit null、disabled 时无 close 按钮)
- popup(click 切换 / outside / disabled / empty + 自定义 notFoundContent)
- single selection(叶子提交 + close、change 带 labels 数组、父节点单选可选)
- multiple checkable(check emit 数组、追加 keys、uncheck 退出、checkable 模式渲染 checkbox、treeCheckable=false 不渲染、selectable 模式不关面板)
- fieldNames 自定义 + emit 路径
- clearable 5 种 + size 三档 + status + is-multiple modifier
- Form integration + Teleport 两种容器 + 单选外部 v-model 回写
文档(packages/docs/components/tree-select/index.md):单选 / 多选 / treeCheckStrictly / 多选 selectable / fieldNames / 三种尺寸 / 表单联动 / 弹层容器;API Props 23 行 + Events 5 行 + 已知限制(showSearch / loadData / showCheckedStrategy / 键盘 / halfCheckedKeys 输出)。
未交付(计入下一切片):showSearch 搜索过滤、loadData 异步加载、showCheckedStrategy 切换、键盘导航、halfCheckedKeys v-model 输出。
收口:
- packages/ccui/ui/vue-ccui.ts:TreeSelectInstall + TreeSelect 三处插入,按字母序对齐 Tree / Typography 之间。
- packages/docs/.vitepress/config/sidebar.ts:手写风格 +5 行加进 数据录入 分类(TimePicker 之后)。
- README:### 数据录入 加 TreeSelect 条目,组件计数 64 → 65,「还没交付的常见组件」表删 TreeSelect 行(Cascader 已在前一批次删除)。
- components-diff.md:表格 +1 行(TreeSelect 数据录入 80%),组件计数 64 → 65,缺失清单复杂组件改 6 项剩余 + 4 项推进中 → 5 项剩余 + 5 项推进中(P1 数据录入 5/5 收口里程碑),新增 Batch 24 写明协议 / 工程决策 / 验证 + P1 数据录入复杂组件全景表(5 个组件 / 205 个新增用例)。
工程决策:
- 不在 c-tree 上加 wrapper component,直接 h(Tree, props):TreeSelect 对 c-tree 的需求是 props 驱动 + 事件透传,没有自定义渲染需求。
- buildNodeIndex 一次性扁平化:tags 渲染需要 value→label 反查,每次 modelValue 变化逐节点 walk 是 O(N)。treeData 大时可加 memoize,80% 切片不优化。
- treeCheckable=true 是默认:与 Ant Design TreeSelect 常用模式一致——多选场景下用户期望看到 checkbox。
- 不在 v-model 中输出 halfCheckedKeys:业务可监听 c-tree-select 自身的 change 事件或直接渲染 c-tree 处理;把半选状态放进 v-model 会让类型膨胀。
P1 数据录入复杂组件全景(5/5 全部 80%,累计 205 个新增用例):
- DatePicker (40 用例) — shared/utils/date.ts + popup 模式 + valueFormat 三档
- TimePicker (45 用例) — shared/utils/date.ts (buildTimeColumnValues) + popup 模式
- RangePicker (38 用例) — shared/utils/date.ts + popup 模式 + 双面板 hover 预览
- Cascader (39 用例) — popup 模式 + 多列联动 + 路径数组 v-model
- TreeSelect (43 用例) — popup 模式 + c-tree 复用
5 个组件共享:@floating-ui/vue placement / Teleport + Transition / Form formItemInjectionKey 联动 / click outside 关闭 / emit 同步 validate('change')。
验证:
- vp check 通过(310 文件 lint/type 全干净)。
- 从 packages/ccui 跑 pnpm test ui/tree-select --run 通过 43/43。
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
P1 数据录入复杂组件 5/5 全部 80% 收口(DatePicker / TimePicker / RangePicker / Cascader / TreeSelect)后,首页 hero 的 feature card 同步更新: - "60 个组件" → "65 个组件 / 工具入口(含 P1 数据录入 5 大复杂组件 80%)" - "800+ 定向单测" → "1000+ 定向单测" Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…e + 命令式 expose) P2 启动批次。Carousel 一次性把 23 个用例打底:scrollx + fade 双 effect、autoplay + pauseOnHover、4 向 dots、infinite wrap、arrows、受控/非受控双模、prev/next/goTo expose。 中等复杂度剩余从 3 项降到 2 项(QRCode / ColorPicker)。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
P2 第二个组件。基于 qrcode-generator (3KB) 提供矩阵数据,组件层用 horizontal-run 合并 path 自渲 SVG,比 N×N rect 节点轻一个数量级。 17 个用例打底:viewBox 模块数随 errorLevel 单调递增、color/bgColor/size/bordered、icon 30% 截断、status 四态遮罩 + refresh emit + statusRender slot、value/errorLevel reactivity、empty value 兜底。 中等复杂度剩余从 2 项降到 1 项(仅余 ColorPicker)。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
P2 中等复杂度收口批次。25 个用例分两层:5 个覆盖 shared/utils/color.ts 互转(含 alpha 8 位 hex round-trip),20 个覆盖组件层。 新增 shared/utils/color.ts(与 date.ts 同款 utility-first 风格,零外部颜色库);ColorPicker 自渲 SV 三层叠加 + 棋盘格 alpha 轨道;hex 输入 edit-on-blur;preset 色板;disabledAlpha 三处守门;与 P1 五件套同款 popup 模式 + Form 联动。 中等复杂度剩余清零(QRCode + Carousel + ColorPicker 共 3 项 80% 全收口)。65→68 组件。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
P3 第一个组件。本质是「Input + 浮层下拉」,区别于 Select 在于值可以是任意字符串。
24 个用例:options 兼容 string[] / {value,label,disabled}[]、filterOption 三态(true/false/function)+ caseSensitive、ArrowUp/Down/Enter/Esc 键盘导航跳过 disabled、allowClear、Form 联动 + Teleport、空数据 notFoundContent、受控/非受控双模、option 自定义 slot。
不复用 c-select 内部实现(语义对立),共享 popup 模式(floating-ui + Teleport + formItemInjectionKey + click outside)。
68→69 组件。
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
P1 5/5 之后追加 P2 中等复杂度三件套(Carousel / QRCode / ColorPicker)+ P3 第一个 AutoComplete,新增 89 个用例。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
P2 大件第一项。24 个用例:partition 顺序按 targetKeys、跨列 selectedKeys 单源、header indeterminate 三态、disabled 单项不进统计、move 自动清除被移动的勾选、filterOption + 两列独立搜索、render slot + prop 双入口、Form 联动。 69→70 组件。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
P3 体验型组件第一项。19 个用例。 4 块 div 围出 target 矩形做镂空(不用 SVG/clip-path),highlight 蓝色光晕;无 target 时浮层退化为居中模态。 v-model:open + v-model:current 双键,末步 finish emit + 自动关闭,Esc / 蒙层点击 / × 同一条 close 路径。 70→71 组件。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
P2 大件第二项。22 个用例。 不内置 HTTP 上传 —— 业务监听 change 自己发请求、回写 fileList 状态。组件只负责 UI + 状态机 + 三层守门(maxSize → maxCount → beforeUpload)。 拖拽四件套(dragenter/over/leave/drop)+ 隐藏 input + input.value 重置技巧 + size 格式化 B/KB/MB + 受控/非受控双模 + reject emit。 71→72 组件,P2 大件只剩 Mentions。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
P3 体验型组件最后一项,至此 P2 大件 + P3 全部 80% 收口。31 个用例(含 7 个 findActiveMention 纯函数测例覆盖 email-style 防误触发等边界)。 textarea + 浮层模式(不用 contenteditable);refreshMatch 在 input/keyup/click 三处刷新;selectOption 字符串拼接 + setSelectionRange 光标后置;多 prefix 选最近;filterOption 三态;Form blur/change validate。 72→73 组件。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Transfer / Tour / Upload / Mentions 四件 P2 大件 + P3 体验组件全部 80% 落地,新增 96 个用例。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- vite.config.ts: vueJsx({ tsTransform: 'built-in' }) 修复 64 个 TSX 文件 import-analysis 加载失败
- slider.test.ts: 重写 30→32 个用例,消除 wrapper.vm.* 内部访问,改为 emitted/DOM/ARIA 断言
- statistic.test.ts: countdown 毫秒断言改为 ±50ms 范围,消除 setInterval 粒度漂移
- back-top.tsx: getScrollTop/scrollTo 增加 t === window 判断,修复 jsdom instanceof Window 为 false
- float-button.test.ts: window.scrollY mock 改用 defineProperty + 属性恢复
- 全量 74/74 文件通过、1220/1220 测试通过
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…dient/toDataURL) Carousel 95%: - 键盘导航 ArrowLeft/Right/Up/Down/Home/End - ARIA 增强 role=region, aria-roledescription=carousel, aria-live=polite, role=tabpanel - swipe 手势 pointerdown/up + swipeThreshold + 横竖自适应 - afterChange 事件在 duration 后触发 - customDot 作用域插槽自定义指示器 - 39 个测试全通过(+14) QRCode 95%: - dotRadius 圆角点阵(0=方形,0.5=正圆) - gradient 渐变前景色(linearGradient + 6 向 direction) - toDataURL expose(SVG→canvas→dataURL) - 25 个测试全通过(+8) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ear)
- RGB 三联 number input(R/G/B 独立编辑,0~255 范围,自动 commit HSV)
- trigger 作用域插槽({ color, open, disabled } 自定义触发器)
- SV/hue/alpha 键盘 Arrow 微调(±1,Shift ±10),三区域 tabindex=0
- allowClear prop + clear 按钮(emit null + stopPropagation)
- 34 个测试全通过(+9)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- 加「其他」组,把 ConfigProvider/Util 从「通用」搬过去(基建非 UI 原子) - Tag/CheckableTag → 通用、Dropdown → 通用、Status → 数据展示、Calendar/Rate/Segmented → 数据录入,归位错置 - 调整分类顺序:通用→布局→导航→数据录入→数据展示→反馈→其他 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- 提取 Vue 状态语义 + 测试优先级到 decisions/testing-principles.md - 删除已烂的「后续任务入口」(statistic 组件不存在、覆盖率数字过期、TODO 状态不明),按 docs-notes/README 规则 3「修复记录/批次记录不再单独写」处理 - docs-notes/README.md 索引补一行 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- introduce.md 收回为「ccui 是什么 / 设计取向 / token 概念」,不再夹杂安装步骤 - 新增 quick-start.md,承载安装 / 完整引入 / 按需引入 / CDN - sidebar 模板 root 改名「指南 / Guide」,新增「快速开始」入口 - home hero 主按钮改指向 /quick-start,「简介」做次按钮;feature 卡片「六大类 83」同步改为「七大类 84」 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- offset-path rect(round 100px) + mask 边框环实现,过弯平滑 - color 支持单色 / 渐变停靠点数组,停靠点映射进前 70% 预留拖尾 - 内置 6 套配色预设(ocean/sunset/aurora/forest/ember/nebula)并导出 - 文档含 card 包裹、预设切换、调速、外扩等 demo;16 个单测 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- 删除 archive/ 整目录(roadmap / components-diff / per-component / 审查报告) - decisions 剥离 commit 哈希 / Batch / 测试 delta 等实现历史,保留决策、理由、不变性约束与 TODO - config-provider-locale 重写为接口契约 + 约束 + Drawer 未决项 - README 移除 archive 索引,过期内容改为直接删除靠 git 溯源 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- README 移除过期组件清单(含未交付的幽灵条目与进度括注),改为引导至文档站 - 统一组件数与测试数字,软化对标措辞为 honest 致敬 - date-picker / upload / table-summary 文档去除进度标注式措辞 - cli 生成器注入 CCUI_VERSION(读 ccui package.json),修复库误报 cli 版本 - 补 Tabs 组件 status 徽标 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
按 docs-notes/issue.md 逐项定位根因并修复: 间距/对齐 - Space 水平方向默认 align-items:center,不再撑高 Tag/Button - Tag 多彩标签示例改用 c-space 提供间距 - ColorPicker trigger 加 vertical-align:middle 与文字对齐 - Steps 连接线两端等距,补 small/dot/vertical 变体覆盖 - Badge __sup 提 z-index 并贴合右上角;移除 BadgeRibbon 缎带示例 - Carousel/Upload 首项偏上 → docs-theme 统一复位 vp-doc li margin 渗透 - Spin 延迟示例两按钮用 c-space 对齐 图标一致性(统一走 renderIconNode/mdi,消除 Unicode 字形回退) - 新增 renderIconWithFallback helper;Select/InputSearch/TimePicker/ TimeRangePicker/Transfer/TreeSelect/DatePicker/RangePicker 统一图标 - InputSearch primary 按钮内图标改白色并上调字号 - TimePicker 修 input min-width:0,图标回到边框内 - TimePicker 新增 showSuffix prop;TimeRangePicker 仅外层渲染单个时钟/清除 - 图标字号统一用 $ccui-font-size-icon 行为修复 - Anchor 高亮对应、Affix 0px 固定核对修正 - Watermark 防篡改:观察 style/class 属性改动,disconnect-around-writes 避免自触发 - Tooltip 采用 flip 后的实际 placement,箭头随翻转;offset 下调 - Popover/Tooltip 箭头仅保留指向侧边框,消除明显边框 结构调整(硬删除/硬重命名,无废弃别名) - 删除 UploadDragger(Upload 已内置 drag)、AvatarGroup - ImagePreviewGroup → ImagePreview(图片预览组 → 图片预览) - resolver 组件表同步;重新生成入口/侧边栏 文档 - 示例小节标题「基本用法」统一为「基本使用」 - Watermark 图片水印 / Empty 自定义图片:替换抄自蚂蚁的 CDN 图片为 自带中性 base64 SVG 测试:ccui 2029 passed / 94 files,resolver 26 passed,vp check 0 errors Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
与 Tooltip 同源问题:popover 的箭头方位(哪两条边透明、静态边偏移) 此前基于请求的 props.placement,flip() 翻转后未更新——「12 个出现位置」 示例中 bottom 触发元素下方无空间翻到上方时,箭头仍停在上方、指向错误。 修复(对齐 Tooltip 的做法): - useFloating 解构响应式 placement,传 toRef(props,'placement') - 新增 actualSide(翻转后实际方位),arrowStyles 静态边与箭头 __arrow--<side> class 均改用 actualSide - popperClass 仍用 props.placement(保留 __popper--<placement> 断言) - scss 把透明边规则从 __popper--<side> .__arrow 迁到 __arrow--<side>, 由 actualSide 驱动;位置偏移完全交给 inline arrowStyles 浏览器验证:bottom 触发元素贴近视口底部时翻到上方,arrow class 变为 __arrow--top、落在浮层底部指向触发元素。ccui 2029 passed。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- transfer: 操作按钮用 flex 居中并放大 icon(13px→16px) - select: __arrow 放大到 20px,修正 mdi:menu-down 视觉偏小 - steps: 垂直连接线改挂 item 并用 top/bottom 双向锚定,两端间距对称(含 small 覆写) - docs showcase: 间距规则改用 :has(~ …),最后/唯一组件不再带 trailing 右下边距 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…出、Badge 间距修正锚点、收敛 showcase 间距修正 ColorPicker 对齐 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
删除 packages/ccui/ui/status 组件与文档页,同步清理 resolver 映射、 install.test.ts 静态导入;vue-ccui/sidebar 等生成入口重新生成后不再含 Status。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- bundle-size-baseline: 重跑 pnpm build:lib 刷新快照(2026-06-02 @ eafddf9); css 产物更名 ccui-cli.css→style.css,子 bundle 57→82,主包/各 chunk 体积重测 - releasing.md: 补全 publish.mjs 实际流程(工作区检查 + bumpp 自动 bump、 --release/--skip-bump 等 flag),版本号管理章节同步 - 修正 4 处过期包名 vue3-ccui→@vaebe/ccui,design-values 移除已删的 Status 引用 - 删除 issue.md(bug 已全部修复并入库,靠 git 历史溯源) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Important Review skippedToo many files! This PR contains 300 files, which is 150 over the limit of 150. To get a review, narrow the scope: ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (300)
You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
pnpm/action-setup@v4 同时收到 with.version 与 package.json packageManager (pnpm@10.33.2) 两个来源会报 ERR_PNPM_BAD_PM_VERSION。删掉 workflow 里的 version(test/buildComponents 为 10、deploy 误写为 9),单一 source of truth。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- test: vue3-ccui → @vaebe/ccui(vue3-ccui 包不存在,该步一直空跑) - buildComponents: cli → ccui-cli(pnpm --filter 按包名匹配,cli 匹配不到) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
两者都是 gitignored 产物,全新 checkout 不存在;既无 postinstall 也无 prepare 去构建。组件 icon.tsx 的 @vaebe/ccui-icons/install 副作用 import 与 style-var 经 @vaebe/ccui-theme/theme 的 @forward 因此解析失败。 test / buildComponents 在 pnpm install 后补一步 icons build + generate:theme (与 docs predev 一致)。本地从干净态复现验证:2023 用例全绿 + build:components 通过。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
新增 root bootstrap 脚本(pnpm --filter @vaebe/ccui-icons build && pnpm --filter ccui-cli generate:theme),挂到 postinstall。这样全新 git clone + pnpm install 即可开箱跑 test / build,无需手动构建这两个 gitignored 产物。CI 的 test/buildComponents 随之去掉显式 prepare 步, 统一由 pnpm install 兜底。本地 wipe + pnpm install 验证:postinstall 正确重建 icons dist(15 文件) 与 theme.scss。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
概述
ccui 2.0 正式版。将
2.x合并入main,对应已发布到 npmlatest的v2.0.0。相对
main(1.2.2):275 commits / 649 files / +90619 −9905,含 108 feat、26 fix、19 refactor、66 docs。三个公开包(@vaebe/ccui/@vaebe/ccui-icons/@vaebe/unplugin-vue-components-ccui)版本对齐2.0.0。亮点
工程 / 发包
.d.ts一次到位(@vaebe/unplugin-vue-components-ccuiresolver)@vaebe/ccui-icons内置 mdi collection,组件图标默认离线可用(无网 / 内网环境不空白)组件能力
variant形态(12 组件)、classNames/styles语义化 DOM 钩子(24 组件)、自定义图标钩子(8 组件)、status与 Form item 双向联动useModal/useMessage/useNotificationcomposables;message / notification 增强(duration 秒制、多 placement、maxCount、stack、pauseOnHover)theme.algorithm(default/dark/compact)与locale全部接通,不留死接口文档
feat(pkg)!发包链路重做:导入路径 / 产物结构变化,按需引入改用新 resolverfeat(tree)!Tree 推翻重写,按 80% 目标重新设计协议(prop / slot 不向后兼容 1.x)迁移
提供 v1 → v2 自动迁移 codemod,覆盖 26 项命名变更(详见
packages/cli迁移脚本与文档站迁移说明)。发布状态
v2.0.0已发布到 npm(dist-taglatest),tagv2.0.0已推送@vaebe/ccui93 文件 / 2023 用例全绿docs-notes/bundle-size-baseline.md(2026-06-02 快照)🤖 Generated with Claude Code
claude code 含量90%