-
Notifications
You must be signed in to change notification settings - Fork 5
feat(steps): 实现 Steps 步骤条组件 #43
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Walkthrough本次更改在 Skiyee Uni UI 组件库中引入了完整的Steps(步骤)组件系统,包括核心的 Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant SkSteps
participant SkStep as SkStep<br/>(Child)
participant Parent as Parent Context
User->>SkSteps: Mount component
SkSteps->>Parent: provide(SK_STEPS_KEY, stepsContext)
SkStep->>SkStep: Mount SkStep instance
SkStep->>Parent: inject(SK_STEPS_KEY) to get context
SkStep->>SkSteps: registerStep(uid) on mount
SkSteps->>SkSteps: Track step in steps list
User->>SkStep: Click step
SkStep->>SkSteps: onStepClick(index)
SkSteps->>SkSteps: Update active, emit events
SkSteps->>SkSteps: emit('update:active', new index)<br/>emit('change', index)<br/>emit('clickStep', index)
SkSteps->>SkStep: Reactive update via context
SkStep->>User: Re-render with new status
SkStep->>SkSteps: unregisterStep(uid) on unmount
SkSteps->>SkSteps: Remove step from tracking
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Poem
Pre-merge checks and finishing touches✅ Passed checks (2 passed)
✨ 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 |
✅ Deploy Preview for skiyee-ui ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
♻️ Duplicate comments (6)
examples/uni/src/pages-info/steps/vertical.vue (1)
44-70: 样式重复与
description.vue中的样式完全相同,请参考该文件中关于提取共享样式的建议。examples/uni/src/pages-info/steps/icon.vue (1)
59-85: 样式重复与其他步骤条示例文件中的样式相同,建议统一提取。
examples/uni/src/pages-info/steps/base.vue (1)
78-111: 样式重复与其他步骤条示例文件中的样式相同,建议统一提取到共享样式文件。
examples/uni/src/pages-info/steps/clickable.vue (1)
72-108: 样式重复与其他步骤条示例文件中的样式相同,建议统一提取。
examples/uni/src/pages-info/steps/size.vue (1)
145-189: 样式重复虽然此文件包含额外的尺寸对比样式(
.size-compare、.size-item、.size-label),但.page、.demo-section、.demo-title、.demo-desc等通用样式仍与其他示例文件重复,建议提取共享部分。examples/uni/src/pages-info/steps/status.vue (1)
100-126: 样式重复与其他步骤条示例文件中的样式相同,建议统一提取到共享样式文件。
🧹 Nitpick comments (2)
examples/uni/src/pages-info/steps/description.vue (1)
123-149: 建议提取共享样式以减少重复代码这些样式代码(
.page、.demo-section、.demo-title、.demo-desc)在所有步骤条示例文件中完全相同。建议将这些共享样式提取到公共样式文件或通过全局样式类复用,以提高可维护性。examples/uni/src/pages-info/steps/base.vue (1)
6-9: 可选优化:避免硬编码的边界值当前使用硬编码的
3作为最大步骤索引。如果未来步骤数量发生变化,需要同步更新此处。建议从实际步骤数量动态计算最大值(例如:步骤总数 - 1)。
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (17)
examples/uni/src/pages-info/steps/base.vue(1 hunks)examples/uni/src/pages-info/steps/clickable.vue(1 hunks)examples/uni/src/pages-info/steps/custom.vue(1 hunks)examples/uni/src/pages-info/steps/description.vue(1 hunks)examples/uni/src/pages-info/steps/icon.vue(1 hunks)examples/uni/src/pages-info/steps/size.vue(1 hunks)examples/uni/src/pages-info/steps/status.vue(1 hunks)examples/uni/src/pages-info/steps/vertical.vue(1 hunks)packages/skiyee-uni-ui/src/components/sk-step.vue(1 hunks)packages/skiyee-uni-ui/src/components/sk-steps.vue(1 hunks)packages/skiyee-uni-ui/src/constants/index.ts(1 hunks)packages/skiyee-uni-ui/src/constants/steps.ts(1 hunks)packages/skiyee-uni-ui/src/styles/index.ts(1 hunks)packages/skiyee-uni-ui/src/styles/sk-step.ts(1 hunks)packages/skiyee-uni-ui/src/styles/sk-steps.ts(1 hunks)packages/skiyee-uni-ui/src/types/index.ts(1 hunks)packages/skiyee-uni-ui/src/types/steps.ts(1 hunks)
🔇 Additional comments (5)
packages/skiyee-uni-ui/src/styles/sk-steps.ts (1)
1-33: 实现正确样式组件定义结构清晰,正确使用了 UnoCSS 的 variants 机制来支持横向和纵向布局,TypeScript 类型定义完善。
examples/uni/src/pages-info/steps/clickable.vue (1)
7-9: 确认空函数是否为预期行为
handleStepClick函数当前为空实现(仅包含注释)。如果这是示例代码的预期行为,建议添加注释说明这是演示占位符;如果需要实现具体逻辑(例如日志输出或状态更新),请补充相应代码。packages/skiyee-uni-ui/src/types/steps.ts (1)
1-48: 类型定义清晰完整类型定义结构合理,包含了步骤条所需的所有状态和上下文接口。文档注释完善,有助于开发者理解和使用。
packages/skiyee-uni-ui/src/components/sk-step.vue (1)
181-191: 检查点击处理的逻辑条件Line 182 的条件判断逻辑可能存在问题:
if (isDisabled.value || (!props.clickable && !parent?.props.disabled))这个条件的第二部分
(!props.clickable && !parent?.props.disabled)表示"当不可点击且父组件未禁用时"就返回,这个逻辑看起来有些奇怪。请确认预期的行为:
- 如果
props.clickable为false,是否应该始终阻止点击?- 还是说只有当
props.clickable为true时才允许点击?建议的修正逻辑可能是:
-if (isDisabled.value || (!props.clickable && !parent?.props.disabled)) { +if (isDisabled.value || !props.clickable) { return }或者如果需要考虑父组件的禁用状态:
-if (isDisabled.value || (!props.clickable && !parent?.props.disabled)) { +if (isDisabled.value || !props.clickable) { return }examples/uni/src/pages-info/steps/custom.vue (1)
1-334: 示例页面展示完善演示页面涵盖了步骤条组件的多种自定义方式,包括样式定制、图标插槽、标题描述插槽以及完全自定义的场景,有助于开发者理解组件的使用方法。
| const isLast = computed(() => { | ||
| if (!parent || !instance) { | ||
| return false | ||
| } | ||
| const allSteps = parent.getStepIndex.length | ||
| return currentIndex.value === allSteps - 1 | ||
| }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
修复 isLast 计算逻辑错误
Line 110 访问 parent.getStepIndex.length 存在错误,getStepIndex 是一个函数而不是数组,因此 .length 将返回函数的参数个数(始终为 1),而非步骤总数。这会导致 isLast 的判断始终不正确。
需要在父组件上下文中添加一个方法来获取步骤总数,或者直接暴露 stepUids 数组:
const isLast = computed(() => {
if (!parent || !instance) {
return false
}
- const allSteps = parent.getStepIndex.length
- return currentIndex.value === allSteps - 1
+ // 需要父组件提供获取步骤总数的方法
+ // 例如: return parent.getStepCount() - 1 === currentIndex.value
+ // 或者: return parent.isLastStep(instance.uid)
})建议在 StepsContext 中添加 getStepCount() 方法,或者 isLastStep(uid: number) 方法。
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In packages/skiyee-uni-ui/src/components/sk-step.vue around lines 106 to 112,
isLast wrongly reads parent.getStepIndex.length (getStepIndex is a function), so
replace that with a correct step count accessor: either call a new
parent.getStepCount() or use parent.stepUids.length (or add and call
parent.isLastStep(currentUid)). Update the StepsContext to expose getStepCount()
(returning stepUids.length) or isLastStep(uid) and then change the computed to
call that method (or compare currentIndex.value to parent.getStepCount() - 1);
ensure null checks for parent/instance remain.
| const stepsContext = readonly({ | ||
| props: reactive(computed(() => ({ | ||
| active: props.active, | ||
| direction: props.direction, | ||
| size: props.size, | ||
| activeColor: props.activeColor, | ||
| inactiveColor: props.inactiveColor, | ||
| disabled: props.disabled, | ||
| }))), | ||
| getStepIndex, | ||
| registerStep, | ||
| unregisterStep, | ||
| onStepClick, | ||
| }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
添加获取步骤总数的方法
为了支持子组件正确判断是否为最后一个步骤(参见 sk-step.vue 中 isLast 的问题),建议在 stepsContext 中添加一个获取步骤总数的方法。
+/**
+ * 获取步骤总数
+ */
+function getStepCount(): number {
+ return stepUids.value.length
+}
+
// 提供给子组件的上下文
const stepsContext = readonly({
props: reactive(computed(() => ({
active: props.active,
direction: props.direction,
size: props.size,
activeColor: props.activeColor,
inactiveColor: props.inactiveColor,
disabled: props.disabled,
}))),
getStepIndex,
+ getStepCount,
registerStep,
unregisterStep,
onStepClick,
})同时需要在 packages/skiyee-uni-ui/src/types/steps.ts 的 StepsContext 接口中添加对应的类型定义:
export interface StepsContext {
props: { ... };
getStepIndex: (uid: number) => number;
getStepCount: () => number; // 新增
registerStep: (uid: number) => void;
unregisterStep: (uid: number) => void;
onStepClick: (index: number) => void;
}🤖 Prompt for AI Agents
In packages/skiyee-uni-ui/src/components/sk-steps.vue around lines 153 to 166,
add a getStepCount method to the stepsContext that returns the current number of
registered steps (e.g., returns steps.length or equivalent internal collection
size) and include that method in the readonly object alongside
getStepIndex/registerStep/unregisterStep/onStepClick; also update
packages/skiyee-uni-ui/src/types/steps.ts to add getStepCount: () => number to
the StepsContext interface so child components (like sk-step.vue) can determine
if they are the last step.
🛠️ Refactor suggestion | 🟠 Major
简化 stepsContext 的响应式包装
Line 154 使用了 reactive(computed(...)) 的模式,这是不必要且可能引起问题的:
computed()已经返回一个响应式引用- 将其包装在
reactive()中是多余的 - 这可能导致响应式追踪出现意外行为
建议直接使用 computed 或 reactive,而不是两者嵌套:
方案 1(推荐):直接使用对象,props 部分使用 toRefs
+import { computed, readonly, ref, toRefs } from 'vue'
// 提供给子组件的上下文
const stepsContext = readonly({
- props: reactive(computed(() => ({
+ props: toRefs(props),
- active: props.active,
- direction: props.direction,
- size: props.size,
- activeColor: props.activeColor,
- inactiveColor: props.inactiveColor,
- disabled: props.disabled,
- }))),
getStepIndex,
registerStep,
unregisterStep,
onStepClick,
})方案 2:如果需要精确控制,使用 computed 返回整个对象
// 提供给子组件的上下文
-const stepsContext = readonly({
+const stepsContext = computed(() => readonly({
- props: reactive(computed(() => ({
+ props: {
active: props.active,
direction: props.direction,
size: props.size,
activeColor: props.activeColor,
inactiveColor: props.inactiveColor,
disabled: props.disabled,
- }))),
+ },
getStepIndex,
registerStep,
unregisterStep,
onStepClick,
-})
+}))📝 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.
| const stepsContext = readonly({ | |
| props: reactive(computed(() => ({ | |
| active: props.active, | |
| direction: props.direction, | |
| size: props.size, | |
| activeColor: props.activeColor, | |
| inactiveColor: props.inactiveColor, | |
| disabled: props.disabled, | |
| }))), | |
| getStepIndex, | |
| registerStep, | |
| unregisterStep, | |
| onStepClick, | |
| }) | |
| const stepsContext = computed(() => readonly({ | |
| props: { | |
| active: props.active, | |
| direction: props.direction, | |
| size: props.size, | |
| activeColor: props.activeColor, | |
| inactiveColor: props.inactiveColor, | |
| disabled: props.disabled, | |
| }, | |
| getStepIndex, | |
| registerStep, | |
| unregisterStep, | |
| onStepClick, | |
| })) |
| horizontal: { | ||
| root: 'flex-col', | ||
| container: 'flex-col items-center', | ||
| content: 'sk-variant:mt-12 sk-variant:ml-0 items-center text-center', | ||
| line: 'sk-variant:left-1/2 sk-variant:translate-x-1/2 sk-variant:top-0 sk-variant:h-full sk-variant:w-2', | ||
| }, | ||
| vertical: { | ||
| root: 'flex-row', | ||
| line: 'sk-variant:top-1/2 sk-variant:-translate-y-1/2 sk-variant:left-0 sk-variant:w-full sk-variant:h-2', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
修复水平/垂直连线的方向与对齐
目前 direction.horizontal 下的 line 使用了竖向尺寸(h-full w-2 + translate-x-1/2),而 direction.vertical 则使用了横向尺寸(w-full h-2)。这会导致:
- 水平步骤的连线呈竖直方向,无法横向连接到下一步;
- 垂直步骤的连线呈水平方向,同样无法正确向下延展;
- 水平步骤中的
translate-x-1/2还会把线条从中心向右偏移。
请交换两种方向下的连线尺寸/定位并把水平步骤的平移改为-translate-x-1/2,使两种布局都能按主轴正确对齐。
horizontal: {
root: 'flex-col',
container: 'flex-col items-center',
content: 'sk-variant:mt-12 sk-variant:ml-0 items-center text-center',
- line: 'sk-variant:left-1/2 sk-variant:translate-x-1/2 sk-variant:top-0 sk-variant:h-full sk-variant:w-2',
+ line: 'sk-variant:top-1/2 sk-variant:-translate-y-1/2 sk-variant:left-0 sk-variant:w-full sk-variant:h-2',
},
vertical: {
root: 'flex-row',
- line: 'sk-variant:top-1/2 sk-variant:-translate-y-1/2 sk-variant:left-0 sk-variant:w-full sk-variant:h-2',
+ line: 'sk-variant:left-1/2 sk-variant:-translate-x-1/2 sk-variant:top-0 sk-variant:h-full sk-variant:w-2',
},📝 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.
| horizontal: { | |
| root: 'flex-col', | |
| container: 'flex-col items-center', | |
| content: 'sk-variant:mt-12 sk-variant:ml-0 items-center text-center', | |
| line: 'sk-variant:left-1/2 sk-variant:translate-x-1/2 sk-variant:top-0 sk-variant:h-full sk-variant:w-2', | |
| }, | |
| vertical: { | |
| root: 'flex-row', | |
| line: 'sk-variant:top-1/2 sk-variant:-translate-y-1/2 sk-variant:left-0 sk-variant:w-full sk-variant:h-2', | |
| horizontal: { | |
| root: 'flex-col', | |
| container: 'flex-col items-center', | |
| content: 'sk-variant:mt-12 sk-variant:ml-0 items-center text-center', | |
| line: 'sk-variant:top-1/2 sk-variant:-translate-y-1/2 sk-variant:left-0 sk-variant:w-full sk-variant:h-2', | |
| }, | |
| vertical: { | |
| root: 'flex-row', | |
| line: 'sk-variant:left-1/2 sk-variant:-translate-x-1/2 sk-variant:top-0 sk-variant:h-full sk-variant:w-2', |
🤖 Prompt for AI Agents
In packages/skiyee-uni-ui/src/styles/sk-step.ts around lines 33 to 41, the line
classes for horizontal and vertical directions are swapped and the horizontal
translate is wrong; swap the line size/position values between
direction.horizontal and direction.vertical so horizontal uses w-full h-2 and
horizontal positioning uses left-0 top-1/2 with -translate-y-1/2 (or equivalent
horizontal-centering), while vertical uses left-1/2 top-0 with -translate-x-1/2
removed/adjusted to center vertically; specifically exchange the width/height
and positioning class sets between the two blocks and change the horizontal
translate-x-1/2 to -translate-x-1/2 so the connector aligns along the main axis
for each direction.
#42
Summary by CodeRabbit
发布说明