Skip to content

Conversation

@skiyee
Copy link
Owner

@skiyee skiyee commented Oct 23, 2025

#23

Summary by CodeRabbit

发布说明

  • 新功能

    • 发布标签页(Tabs)组件,支持动画效果、可滚动、禁用状态、受控/非受控模式、自定义指示线宽度等功能。
    • 提供多个交互式使用示例展示不同的实现场景。
  • 文档

    • 标签页组件文档升级至Beta状态。
    • 补充完整的代码示例和使用指南。

@coderabbitai
Copy link

coderabbitai bot commented Oct 23, 2025

总结

Walkthrough

该 PR 添加了一个完整的 Tabs 制表符导航组件系统,包括核心 Vue 组件实现(SkTabs 和 SkTab)、相关类型定义、样式配置、八个示例演示页面和更新的文档说明。

Changes

Cohort / File(s) 变更摘要
文档更新
docs/content/docs/2.components/5.navigation/01.tabs.md
元数据从 Dev 更新至 Beta;扩展作者信息块;更新源代码链接路径;删除警告通知;添加多个 CodePreview 示例和代码片段,展示默认值、受控模式、可滚动、线宽、动画、禁用等多种用法
配置文件
docs/nuxt.config.ts
公开运行时配置从 'bundle' 变更为 'http://localhost:5173/#/'
示例页面
examples/uni/src/pages-navigation/tabs/\\*.vue
新增八个 Vue SFC 示例文件:base.vue(基础用法)、default-value.vue(默认值)、controlled.vue(受控模式)、scrollable.vue(可滚动)、line.vue(线宽配置)、animated.vue(动画演示)、disabled.vue(禁用状态)、events.vue(事件日志)
示例路由配置
examples/uni/src/pages.json
添加新的 pages-navigation 子包含八个制表符示例页面的路由入口
类型声明
examples/uni/types/components.d.ts
移除 14 个组件声明(SkBadge、SkCheckbox 等);添加三个新声明:SkTab、SkTabItem、SkTabs
页面类型扩展
examples/uni/types/pages.d.ts
在 NavigateToOptions 接口中添加九个新的导航路由字面量类型,对应八个 Tabs 示例页面
核心组件实现
packages/skiyee-uni-ui/src/components/sk-tabs.vue
新增 Tabs 容器组件,实现制表符导航功能,包含受控/非受控模式、可滚动、动画指示线、禁用状态等特性
子组件实现
packages/skiyee-uni-ui/src/components/sk-tab.vue
新增 Tab 项组件,通过注入上下文与父容器关联,支持禁用状态和条件渲染
样式配置
packages/skiyee-uni-ui/src/styles/sk-tabs.ts
新增 Tabs 组件的 UCV 样式定义,包含根、滚动包装、导航、制表符、内容、指示线、面板等元素,以及可滚动、动画、活跃、禁用等变体
样式清理
packages/skiyee-uni-ui/src/styles/sk-tab.ts
已删除过时的 SkTabUcv 样式组件定义
常量导出
packages/skiyee-uni-ui/src/constants/tabs.ts
新增 Tabs 相关常量定义,导出 SK_TABS_KEY 作为 Vue 注入键
常量索引
packages/skiyee-uni-ui/src/constants/index.ts
添加 ./tabs 模块的公开导出
类型定义
packages/skiyee-uni-ui/src/types/tabs.ts
新增 TabsContext 接口,定义制表符上下文 API,包含 props、setActiveIndex、registerTabItem、unregisterTabItem 等
样式导出
packages/skiyee-uni-ui/src/styles/index.ts
添加 SkTabsUcv 组件和 SkTabsUcvProps 类型的公开导出

Sequence Diagram(s)

sequenceDiagram
    participant User as 用户交互
    participant SkTabs as SkTabs 容器
    participant SkTab as SkTab 项
    participant Context as 注入上下文

    User->>SkTabs: 点击制表符
    SkTabs->>SkTabs: setActiveIndex(index)
    SkTabs->>SkTabs: 发送 'change' 事件
    SkTabs->>SkTabs: 更新指示线位置/动画
    SkTabs->>Context: 提供 activeIndex 更新
    Context->>SkTab: 更新所有子项的 isActive
    SkTab->>SkTab: 基于 isActive 条件渲染内容
    SkTabs->>User: 显示选中制表符内容

    Note over SkTabs,SkTab: 若启用可滚动模式
    SkTabs->>SkTabs: 计算 scrollLeft 以居中活跃制表符
    SkTabs->>SkTabs: 平滑滚动到目标位置
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

本变更涉及多个相关的新文件和更新,但变更具有一致的模式性。核心逻辑在两个主要组件(SkTabs 和 SkTab)中,需要审查注入上下文的父子通信、动画指示线计算和可滚动功能。八个示例文件遵循相似模式,但每个展示不同用例。类型定义和配置更新较为直接。变更的同质性(大多围绕 Tabs 功能)降低了整体审查复杂度。

Poem

🐰 新的制表符闪闪发光,
指示线优雅地舞动,
八个示例齐声唱,
可滚动且动画绚烂,
组件完美组合,
导航从未如此流畅!✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed 拉取请求的标题 feat(tabs): 实现 Tabs 标签页组件 清晰而准确地总结了变更集的主要内容。根据原始总结,该 PR 的核心目的是实现 Tabs 标签页组件,包括添加 SkTabs 和 SkTab 等核心组件、相关文档、多个使用示例以及配套的类型定义和样式文件。标题采用了标准的 Conventional Commits 格式,具有高度的一致性和可读性,不包含任何模糊或无意义的表述。
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/tabs

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@netlify
Copy link

netlify bot commented Oct 23, 2025

Deploy Preview for skiyee-ui ready!

Name Link
🔨 Latest commit 45df429
🔍 Latest deploy log https://app.netlify.com/projects/skiyee-ui/deploys/68fa1c7f31334a0008ef4f0d
😎 Deploy Preview https://deploy-preview-34--skiyee-ui.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (4)
examples/uni/src/pages-navigation/tabs/events.vue (1)

7-21: 事件处理逻辑正确!

handleChange 方法正确实现了日志记录和用户反馈功能,通过 unshift 添加新日志并限制数组长度为 5 条。逻辑清晰,功能完整。

如果希望代码更简洁,可以考虑使用数组切片:

 function handleChange(index: number) {
   const message = `切换到标签 ${index + 1}`
-  logs.value.unshift(message)
-
-  // 最多保留 5 条日志
-  if (logs.value.length > 5) {
-    logs.value.pop()
-  }
+  logs.value = [message, ...logs.value].slice(0, 5)

   uni.showToast({
     title: message,
     icon: 'none',
     duration: 1500,
   })
 }

不过当前实现也完全可以接受。

packages/skiyee-uni-ui/src/components/sk-tabs.vue (3)

174-177: 建议改进类型安全性

TabData 接口中的 props 字段使用了 any 类型,降低了类型安全性。

可以改为:

 interface TabData {
   uid: number;
-  props: any;
+  props: SkTabProps;
 }

类似地,boundingClientRect 回调中的 rectrects 参数(Line 213, 228, 231)也可以定义更精确的类型接口。


290-339: 建议增强无障碍访问性

当前 Tabs 组件缺少无障碍访问性支持,包括 ARIA 属性和键盘导航功能。

建议添加:

  1. ARIA 属性

    • 标签导航栏添加 role="tablist"
    • 每个标签添加 role="tab"aria-selectedaria-controls
    • 面板区域添加 role="tabpanel"aria-labelledby
  2. 键盘导航

    • 左右箭头键切换标签
    • Home/End 键跳转到首尾标签
    • Tab 键管理焦点

参考实现:

<view
  role="tab"
  :aria-selected="activeIndex === idx"
  :aria-controls="`panel-${tab.uid}`"
  tabindex="0"
  @keydown="handleKeydown"
>

这将显著提升组件的可用性和包容性。


202-222: 建议添加查询错误处理

scrollToActiveTab 函数使用选择器查询但未处理查询失败的情况(Line 213-221)。如果 DOM 元素未找到或组件在查询期间被销毁,rect 可能为 nullundefined

建议添加更严格的检查:

 query.select('.sk-tabs-scroll-view').boundingClientRect((rect: any) => {
-  if (rect) {
+  if (rect && rect.width) {
     const containerWidth = rect.width
     const tabCenter = currentTabInfo.offsetLeft + currentTabInfo.width / 2
     const scrollPosition = tabCenter - containerWidth / 2
 
     scrollLeft.value = Math.max(0, scrollPosition)
+  } else {
+    console.warn('[SkTabs] Failed to query scroll-view dimensions')
   }
 }).exec()

类似的检查也应该应用于 updateTabItemsInfo 函数(Line 228-243)。

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1a3d38b and 45df429.

📒 Files selected for processing (21)
  • docs/content/docs/2.components/5.navigation/01.tabs.md (2 hunks)
  • docs/nuxt.config.ts (1 hunks)
  • examples/uni/src/pages-navigation/tabs/animated.vue (1 hunks)
  • examples/uni/src/pages-navigation/tabs/base.vue (1 hunks)
  • examples/uni/src/pages-navigation/tabs/controlled.vue (1 hunks)
  • examples/uni/src/pages-navigation/tabs/default-value.vue (1 hunks)
  • examples/uni/src/pages-navigation/tabs/disabled.vue (1 hunks)
  • examples/uni/src/pages-navigation/tabs/events.vue (1 hunks)
  • examples/uni/src/pages-navigation/tabs/line.vue (1 hunks)
  • examples/uni/src/pages-navigation/tabs/scrollable.vue (1 hunks)
  • examples/uni/src/pages.json (1 hunks)
  • examples/uni/types/components.d.ts (1 hunks)
  • examples/uni/types/pages.d.ts (1 hunks)
  • packages/skiyee-uni-ui/src/components/sk-tab.vue (1 hunks)
  • packages/skiyee-uni-ui/src/components/sk-tabs.vue (1 hunks)
  • packages/skiyee-uni-ui/src/constants/index.ts (1 hunks)
  • packages/skiyee-uni-ui/src/constants/tabs.ts (1 hunks)
  • packages/skiyee-uni-ui/src/styles/index.ts (1 hunks)
  • packages/skiyee-uni-ui/src/styles/sk-tab.ts (0 hunks)
  • packages/skiyee-uni-ui/src/styles/sk-tabs.ts (1 hunks)
  • packages/skiyee-uni-ui/src/types/tabs.ts (1 hunks)
💤 Files with no reviewable changes (1)
  • packages/skiyee-uni-ui/src/styles/sk-tab.ts
🧰 Additional context used
🧬 Code graph analysis (3)
packages/skiyee-uni-ui/src/styles/sk-tabs.ts (1)
packages/skiyee-uni-ui/src/styles/index.ts (2)
  • SkTabsUcv (58-58)
  • SkTabsUcvProps (57-57)
packages/skiyee-uni-ui/src/types/tabs.ts (2)
packages/skiyee-uni-ui/src/types/form.ts (2)
  • FormContext (98-122)
  • FormFieldState (20-96)
packages/skiyee-uni-ui/src/types/roller.ts (1)
  • RollerGroupContext (13-18)
packages/skiyee-uni-ui/src/constants/tabs.ts (1)
packages/skiyee-uni-ui/src/types/tabs.ts (1)
  • TabsContext (18-49)
🪛 LanguageTool
docs/content/docs/2.components/5.navigation/01.tabs.md

[locale-violation] ~122-~122: Possible error ortogràfic. Aquesta forma verbal no es correspon amb la varietat seleccionada (central).
Context: ...---------| | scrollable | boolean | false | 是否可横向滚动 | ::CodePreview{path="/page...

(EXIGEIX_VERBS_CENTRAL)


[locale-violation] ~235-~235: Possible error ortogràfic. Aquesta forma verbal no es correspon amb la varietat seleccionada (central).
Context: ...-----------| | disabled | boolean | false | 是否禁用整个标签页 | ::CodePreview{path="/pa...

(EXIGEIX_VERBS_CENTRAL)


[style] ~284-~284: Anglicisme innecessari. Considereu fer servir una altra paraula.
Context: ...odePreview{path="/pages-navigation/tabs/events" height="300"} <!-- automd:file src=".....

(CA_SIMPLE_REPLACE_ANGLICISM_EVENTS)


[locale-violation] ~336-~336: Possible error ortogràfic. Aquesta forma verbal no es correspon amb la varietat seleccionada (central).
Context: ... scrollable | boolean | false | 详见 [Scrollable 横向滚动](#scrollable-横向...

(EXIGEIX_VERBS_CENTRAL)


[locale-violation] ~339-~339: Possible error ortogràfic. Aquesta forma verbal no es correspon amb la varietat seleccionada (central).
Context: ... disabled | boolean | false | 详见 Disabled 禁用状态 ...

(EXIGEIX_VERBS_CENTRAL)


[locale-violation] ~346-~346: Possible error ortogràfic. «Index» és correcte com a forma balear (1a personal singular, present d’indicatiu).
Context: ...--------|----------------| | change | (index: number) | 切换标签时触发 | | click | `(in...

(EXIGEIX_VERBS_CENTRAL)


[locale-violation] ~347-~347: Possible error ortogràfic. «Index» és correcte com a forma balear (1a personal singular, present d’indicatiu).
Context: ...ndex: number)| 切换标签时触发 | |click |(index: number)` | 点击标签时触发 | ### Slots | 插槽名...

(EXIGEIX_VERBS_CENTRAL)


[style] ~353-~353: Anglicisme innecessari. Considereu fer servir una altra paraula.
Context: ...-----|------------------------------| | default | 标签内容,放置 SkTab 组件 | ## 接口 (Tab) #...

(CA_SIMPLE_REPLACE_ANGLICISM_DEFAULT)


[locale-violation] ~362-~362: Possible error ortogràfic. Aquesta forma verbal no es correspon amb la varietat seleccionada (central).
Context: ...abel-标签文本) | | disabled | boolean | false | 是否禁用该标签 | #...

(EXIGEIX_VERBS_CENTRAL)


[style] ~368-~368: Anglicisme innecessari. Considereu fer servir una altra paraula.
Context: ... | |-----------|----------------| | default | 标签面板内容 | ## 交互 正在完善中,敬请期待!😊

(CA_SIMPLE_REPLACE_ANGLICISM_DEFAULT)

🔇 Additional comments (16)
examples/uni/src/pages.json (1)

714-750: LGTM!

新增的 pages-navigation 子包配置结构合理,与现有的子包配置保持一致。8 个标签页示例的路径定义清晰,类型声明正确。

packages/skiyee-uni-ui/src/types/tabs.ts (1)

1-49: LGTM!

TabsContext 接口定义完整且结构清晰,与项目中其他上下文接口(如 FormContext、RollerGroupContext)的设计模式保持一致。文档注释详尽,类型定义准确。

packages/skiyee-uni-ui/src/constants/index.ts (1)

14-14: LGTM!

新增的 tabs 常量导出与现有的导出模式保持一致,正确扩展了公共 API。

examples/uni/src/pages-navigation/tabs/default-value.vue (1)

1-42: LGTM!

示例代码清晰地展示了 default-value 属性在非受控模式下的使用。代码结构良好,文档说明充分。

examples/uni/src/pages-navigation/tabs/animated.vue (1)

1-82: LGTM!

示例代码有效地对比了启用和禁用动画的效果。使用两个独立的状态变量进行对比展示是合理的设计,代码结构清晰。

examples/uni/src/pages-navigation/tabs/base.vue (1)

1-39: LGTM!

基础示例简洁明了,正确展示了 v-model 双向绑定的基本用法。代码易于理解,是用户入门的良好起点。

packages/skiyee-uni-ui/src/styles/index.ts (1)

57-59: 导出格式正确!

新增的 Tabs 样式导出遵循了现有的命名和组织模式,与其他组件导出保持一致。

examples/uni/src/pages-navigation/tabs/scrollable.vue (1)

1-35: 可滚动标签页示例实现良好!

这个示例清晰地展示了可滚动标签页的用法,使用 v-model 实现双向绑定,并正确处理了 8 个标签项的渲染和状态显示。

packages/skiyee-uni-ui/src/constants/tabs.ts (1)

1-13: 注入键定义规范!

使用 Symbol 确保键的唯一性,并正确声明为 InjectionKey<Readonly<TabsContext>> 类型,符合 Vue 3 provide/inject 的最佳实践。

examples/uni/src/pages-navigation/tabs/disabled.vue (1)

1-86: 禁用状态示例完整!

示例很好地展示了两种禁用场景:单个标签禁用和整体禁用,清晰地演示了 disabled 属性在不同层级的使用方式。

examples/uni/src/pages-navigation/tabs/line.vue (1)

1-76: 指示器宽度配置示例设计精妙!

通过使用不同长度的标签文本(标签1、标签二、标签三三三),能够清晰地展示自动宽度和固定宽度的视觉差异,示例设计考虑周到。

examples/uni/src/pages-navigation/tabs/controlled.vue (1)

1-69: 受控模式示例实现正确!

示例清晰地展示了如何通过 v-model 实现受控模式,以及如何通过编程方式(setTab 方法)控制标签切换。handleChange 作为占位符在示例中是合理的。

packages/skiyee-uni-ui/src/styles/sk-tabs.ts (1)

21-72: 样式配置设计完善!

ucv 配置涵盖了标签页组件的所有关键元素和状态,包括滚动、动画、激活和禁用等变体。使用 sk-unitsk-elementsk-variant 前缀实现了灵活的样式组合,设计合理。

examples/uni/src/pages-navigation/tabs/events.vue (1)

28-82: 事件监听示例实现完整!

模板部分正确绑定了 @change@click 事件,日志显示区域妥善处理了空状态和列表渲染,示例清晰地展示了如何监听和响应标签页的切换事件。

packages/skiyee-uni-ui/src/components/sk-tabs.vue (2)

225-244: 验证指示器定位计算的准确性

当前实现通过累加 tab 宽度来手动计算 offsetLeft(Line 230-237),而不是使用 boundingClientRect 返回的实际位置信息。这种方式假设所有标签是紧密排列的,不存在间距。

如果标签之间存在 margin/padding,或者第一个标签距离容器左边缘有偏移,手动累加的 offsetLeft 会与实际位置不符,导致指示器位置错位。

建议验证以下场景下指示器位置是否正确:

  1. 标签之间存在 margin 或 gap
  2. 第一个标签设置了 padding-left
  3. 容器内部存在 padding

可以考虑使用相对于容器的实际位置来计算:

// 先获取容器位置
const query = uni.createSelectorQuery().in(instance)
query.select('.sk-tabs-scroll-view').boundingClientRect((containerRect: any) => {
  query.selectAll('.sk-tab-item').boundingClientRect((rects: any) => {
    if (Array.isArray(rects) && containerRect) {
      tabItemsInfo.value = rects.map((rect: any) => ({
        offsetLeft: rect.left - containerRect.left,
        width: rect.width,
      }))
      scrollToActiveTab()
    }
  }).exec()
}).exec()

这样可以获得相对于容器的准确位置,避免手动累加带来的潜在问题。


77-288: 组件整体架构设计良好!

SkTabs 组件的整体实现展现了良好的架构设计:

  • 正确处理受控/非受控模式(Line 115-127)
  • 清晰的标签注册/注销机制(Line 246-261)
  • 合理使用 computed 优化性能(Line 141-152, 155-171)
  • 适当的响应式状态管理和上下文共享(Line 264-274)

除了上述提到的具体问题外,整体实现质量较高。

runtimeConfig: {
public: {
demo: 'bundle',
demo: 'http://localhost:5173/#/',
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

避免硬编码 localhost URL

将 demo URL 硬编码为 http://localhost:5173/#/ 会在生产环境或其他开发环境中失效。

建议使用环境变量配置:

   runtimeConfig: {
     public: {
-      demo: 'http://localhost:5173/#/',
+      demo: process.env.DEMO_URL || 'http://localhost:5173/#/',
     },
   },

或在项目根目录创建 .env 文件:

DEMO_URL=http://localhost:5173/#/
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
demo: 'http://localhost:5173/#/',
demo: process.env.DEMO_URL || 'http://localhost:5173/#/',
🤖 Prompt for AI Agents
In docs/nuxt.config.ts around line 9 the demo URL is hardcoded as
"http://localhost:5173/#/" which breaks in non-local environments; replace the
hardcoded string with a value read from an environment variable (e.g.
process.env.DEMO_URL or via Nuxt runtime/config) and ensure you provide a
default fallback for local dev, add instructions to create a .env file with
DEMO_URL if needed, and update project docs or README to document the new
DEMO_URL environment variable.

Comment on lines +17 to +19
SkTab: typeof import('@skiyee/uni-ui/components/sk-tab.vue')['default']
SkTabItem: typeof import('@skiyee/uni-ui/components/sk-tab-item.vue')['default']
SkTabs: typeof import('@skiyee/uni-ui/components/sk-tabs.vue')['default']
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

验证组件移除的影响

AI 摘要提到移除了多个组件声明(SkBadge, SkCheckbox, SkDialog 等),但仅保留了标签页相关组件。由于这是自动生成的文件,请确认这些被移除的组件在代码库中确实未被使用,或者它们已迁移到其他位置。

运行以下脚本验证被移除的组件是否仍在使用:


🏁 Script executed:

#!/bin/bash
# 搜索可能仍在使用已移除组件的位置
echo "检查 SkBadge 使用情况:"
rg -nP --type=vue -C2 '<SkBadge' examples/uni/src/

echo "检查 SkCheckbox 使用情况:"
rg -nP --type=vue -C2 '<SkCheckbox' examples/uni/src/

echo "检查 SkDialog 使用情况:"
rg -nP --type=vue -C2 '<SkDialog' examples/uni/src/

echo "检查 SkForm 使用情况:"
rg -nP --type=vue -C2 '<SkForm' examples/uni/src/

Length of output: 182


我来用更正确的脚本方式重新验证这些被移除组件的使用情况。<!-- [scratchpad_update]
Web search confirms that ripgrep supports .vue files via --type js (since *.vue is included in JS type) or using --glob '*.vue'. The initial script failed because --type=vue is not a defined type, but we can use glob patterns instead.

[actions_update]
Run corrected script using glob patterns to search for removed components in examples/uni/src/
[scratchpad_update_end] -->


🏁 Script executed:

#!/bin/bash
# 使用 glob 模式搜索可能仍在使用已移除组件的位置
echo "检查 SkBadge 使用情况:"
rg -nP -g '*.vue' -g '*.ts' -g '*.js' '<SkBadge' examples/uni/src/ 2>/dev/null | head -20

echo -e "\n检查 SkCheckbox 使用情况:"
rg -nP -g '*.vue' -g '*.ts' -g '*.js' '<SkCheckbox' examples/uni/src/ 2>/dev/null | head -20

echo -e "\n检查 SkDialog 使用情况:"
rg -nP -g '*.vue' -g '*.ts' -g '*.js' '<SkDialog' examples/uni/src/ 2>/dev/null | head -20

echo -e "\n检查 SkForm 使用情况:"
rg -nP -g '*.vue' -g '*.ts' -g '*.js' '<SkForm' examples/uni/src/ 2>/dev/null | head -20

echo -e "\n检查 SkTab/SkTabItem/SkTabs 使用情况 (应该存在):"
rg -nP -g '*.vue' -g '*.ts' -g '*.js' '<Sk(Tab|TabItem|Tabs)' examples/uni/src/ 2>/dev/null | head -20

Length of output: 7200


🏁 Script executed:

#!/bin/bash
# 检查 SkTabItem 的具体使用情况
echo "检查 SkTabItem 使用情况:"
rg -nP -g '*.vue' -g '*.ts' -g '*.js' '<SkTabItem' examples/uni/src/ 2>/dev/null | head -20

echo -e "\n检查 components.d.ts 文件内容确认:"
cat examples/uni/types/components.d.ts | head -30

Length of output: 1108


修复被移除组件的类型声明

验证确认:SkBadge、SkCheckbox、SkDialog、SkForm 这四个组件在源代码中被广泛使用,但其类型声明已被从 components.d.ts 中移除。

  • SkBadge:在 examples/uni/src/pages-basic/badge/ 下至少 20+ 处使用
  • SkCheckbox:在 examples/uni/src/pages-form/checkbox/form/ 下至少 15+ 处使用
  • SkDialog:在 examples/uni/src/pages-feedback/dialog/ 下至少 3 处使用
  • SkForm:在 examples/uni/src/pages-form/form/ 下至少 12+ 处使用

这会导致 TypeScript 类型检查失败和 IDE 代码补全丧失。应在 components.d.ts 中恢复这四个组件的类型声明:

SkBadge: typeof import('@skiyee/uni-ui/components/sk-badge.vue')['default']
SkCheckbox: typeof import('@skiyee/uni-ui/components/sk-checkbox.vue')['default']
SkDialog: typeof import('@skiyee/uni-ui/components/sk-dialog.vue')['default']
SkForm: typeof import('@skiyee/uni-ui/components/sk-form.vue')['default']
🤖 Prompt for AI Agents
In examples/uni/types/components.d.ts around lines 17 to 19, four component type
declarations (SkBadge, SkCheckbox, SkDialog, SkForm) were removed causing
TypeScript errors and lost IDE completion; restore their declarations by adding
entries mapping each to the corresponding default export in @skiyee/uni-ui
(sk-badge.vue, sk-checkbox.vue, sk-dialog.vue, sk-form.vue) following the
existing pattern used for SkTab/SkTabItem/SkTabs so the file includes all four
lines with the same typeof import(...)[ 'default' ] shape.

Comment on lines +182 to +199
function setActiveIndex(index: number) {
const tab = tabs.value[index]
if (props.disabled || tab?.props.disabled) {
return
}
if (index === activeIndex.value) {
return
}
activeIndex.value = index
emits('change', index)
emits('click', index)
nextTick(() => {
scrollToActiveTab()
})
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

修正 click 事件的触发逻辑

根据文档说明,click 事件应该在"点击标签时触发",而 change 事件在"切换标签时触发"。但当前实现中,如果点击的是已激活的标签(Line 188-190),会提前返回而不触发 click 事件。这导致 click 事件仅在标签切换时才触发,与文档描述不符。

建议调整事件触发顺序:

 function setActiveIndex(index: number) {
   const tab = tabs.value[index]
   if (props.disabled || tab?.props.disabled) {
     return
   }
 
+  emits('click', index)
+
   if (index === activeIndex.value) {
     return
   }
 
   activeIndex.value = index
   emits('change', index)
-  emits('click', index)
 
   nextTick(() => {
     scrollToActiveTab()
   })
 }

这样可以确保:

  • click 事件在每次点击时触发(除非被禁用)
  • change 事件仅在标签实际切换时触发
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function setActiveIndex(index: number) {
const tab = tabs.value[index]
if (props.disabled || tab?.props.disabled) {
return
}
if (index === activeIndex.value) {
return
}
activeIndex.value = index
emits('change', index)
emits('click', index)
nextTick(() => {
scrollToActiveTab()
})
}
function setActiveIndex(index: number) {
const tab = tabs.value[index]
if (props.disabled || tab?.props.disabled) {
return
}
emits('click', index)
if (index === activeIndex.value) {
return
}
activeIndex.value = index
emits('change', index)
nextTick(() => {
scrollToActiveTab()
})
}
🤖 Prompt for AI Agents
In packages/skiyee-uni-ui/src/components/sk-tabs.vue around lines 182-199, the
function currently returns early for clicks on the already-active tab and
therefore never emits the 'click' event as documented; change the logic so that
after the disabled checks you always emit 'click' for the clicked tab, then
check if the index equals activeIndex and only return if it does (so 'change' is
only emitted when the active index actually changes). If the index differs, set
activeIndex, emit 'change', and run nextTick(() => scrollToActiveTab()) as
before.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants