From cc241d92c82bd5d88fd946ccabad28a6dc7b1497 Mon Sep 17 00:00:00 2001 From: vaebe <18137693952@163.com> Date: Thu, 13 Nov 2025 20:41:31 +0800 Subject: [PATCH 01/10] =?UTF-8?q?feat:=20=E5=9F=BA=E6=9C=AC=E9=80=BB?= =?UTF-8?q?=E8=BE=91=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ccui/ui/shared/hooks/use-namespace.ts | 3 + packages/ccui/ui/timeline/index.ts | 24 +++ .../ccui/ui/timeline/src/timeline-item.tsx | 103 ++++++++++ .../ccui/ui/timeline/src/timeline-types.ts | 79 ++++++++ packages/ccui/ui/timeline/src/timeline.scss | 157 ++++++++++++++ packages/ccui/ui/timeline/src/timeline.tsx | 28 +++ .../ccui/ui/timeline/test/timeline.test.ts | 141 +++++++++++++ packages/docs/components/timeline/index.md | 191 ++++++++++++++++++ 8 files changed, 726 insertions(+) create mode 100644 packages/ccui/ui/timeline/index.ts create mode 100644 packages/ccui/ui/timeline/src/timeline-item.tsx create mode 100644 packages/ccui/ui/timeline/src/timeline-types.ts create mode 100644 packages/ccui/ui/timeline/src/timeline.scss create mode 100644 packages/ccui/ui/timeline/src/timeline.tsx create mode 100644 packages/ccui/ui/timeline/test/timeline.test.ts create mode 100644 packages/docs/components/timeline/index.md diff --git a/packages/ccui/ui/shared/hooks/use-namespace.ts b/packages/ccui/ui/shared/hooks/use-namespace.ts index 33391d46..2e20e447 100644 --- a/packages/ccui/ui/shared/hooks/use-namespace.ts +++ b/packages/ccui/ui/shared/hooks/use-namespace.ts @@ -3,6 +3,7 @@ export interface UseNamespace { e: (el: string) => string m: (mo: string) => string em: (el: string, mo: string) => string + is: (name: string) => string } function createBem( @@ -35,10 +36,12 @@ export function useNamespace(block: string, needDot = false): UseNamespace { modifier ? createBem(namespace, '', modifier) : '' const em = (element: string, modifier: string) => element && modifier ? createBem(namespace, element, modifier) : '' + const is = (name: string) => `is-${name}` return { b, e, m, em, + is, } } diff --git a/packages/ccui/ui/timeline/index.ts b/packages/ccui/ui/timeline/index.ts new file mode 100644 index 00000000..61fe68bb --- /dev/null +++ b/packages/ccui/ui/timeline/index.ts @@ -0,0 +1,24 @@ +import type { App } from 'vue' +import Timeline from './src/timeline' +import TimelineItem from './src/timeline-item' + +Timeline.install = function (app: App): void { + app.component(Timeline.name || 'CTimeline', Timeline) + app.component(TimelineItem.name || 'CTimelineItem', TimelineItem) +} + +TimelineItem.install = function (app: App): void { + app.component(TimelineItem.name || 'CTimelineItem', TimelineItem) +} + +export { Timeline, TimelineItem } + +export default { + title: 'Timeline 时间线', + category: '数据展示', + status: '100%', + install(app: App): void { + app.component(Timeline.name || 'CTimeline', Timeline) + app.component(TimelineItem.name || 'CTimelineItem', TimelineItem) + }, +} diff --git a/packages/ccui/ui/timeline/src/timeline-item.tsx b/packages/ccui/ui/timeline/src/timeline-item.tsx new file mode 100644 index 00000000..de4028f6 --- /dev/null +++ b/packages/ccui/ui/timeline/src/timeline-item.tsx @@ -0,0 +1,103 @@ +import type { TimelineItemProps } from './timeline-types' +import { computed, defineComponent, h } from 'vue' +import { useNamespace } from '../../shared/hooks/use-namespace' +import { timelineItemProps } from './timeline-types' + +export default defineComponent({ + name: 'CTimelineItem', + props: timelineItemProps, + emits: [], + setup(props: TimelineItemProps, { slots }) { + const ns = useNamespace('timeline-item') + + // 计算节点的样式类名 + const nodeClasses = computed(() => { + return [ + ns.e('node'), + ns.em('node', props.size), + props.type && ns.em('node', props.type), + props.hollow && ns.is('hollow'), + ].filter(Boolean) + }) + + // 计算时间戳的样式类名 + const timestampClasses = computed(() => { + return [ + ns.e('timestamp'), + ns.is(props.placement), + ] + }) + + // 渲染图标 + const renderIcon = () => { + if (props.icon) { + if (typeof props.icon === 'string') { + return + } + else { + // 如果是组件,使用 h 函数渲染 + return h(props.icon, { class: ns.e('icon') }) + } + } + return null + } + + // 渲染节点 + const renderNode = () => { + if (slots.dot) { + return ( +
+ {slots.dot()} +
+ ) + } + + return ( +
+ {renderIcon()} +
+ ) + } + + // 渲染时间戳 + const renderTimestamp = () => { + if (props.hideTimestamp) + return null + + return ( +
+ {props.timestamp} +
+ ) + } + + return () => { + return ( +
  • + {/* 连接线 */} +
    + + {/* 节点 */} + {renderNode()} + + {/* 内容区域 */} +
    + {/* 顶部时间戳 */} + {props.placement === 'top' && renderTimestamp()} + + {/* 内容 */} +
    + {slots.default && slots.default()} +
    + + {/* 底部时间戳 */} + {props.placement === 'bottom' && renderTimestamp()} +
    +
  • + ) + } + }, +}) diff --git a/packages/ccui/ui/timeline/src/timeline-types.ts b/packages/ccui/ui/timeline/src/timeline-types.ts new file mode 100644 index 00000000..32f74b4c --- /dev/null +++ b/packages/ccui/ui/timeline/src/timeline-types.ts @@ -0,0 +1,79 @@ +import type { Component, ExtractPropTypes, PropType } from 'vue' + +// Timeline 主组件的 props +export const timelineProps = { + // 暂时没有特殊的 props,主要通过插槽传递 TimelineItem +} as const + +export type TimelineProps = ExtractPropTypes + +// TimelineItem 组件的 props +export const timelineItemProps = { + /** + * 时间戳内容 + */ + timestamp: { + type: String, + default: '', + }, + /** + * 是否隐藏时间戳 + */ + hideTimestamp: { + type: Boolean, + default: false, + }, + /** + * 是否垂直居中 + */ + center: { + type: Boolean, + default: false, + }, + /** + * 时间戳位置 + */ + placement: { + type: String as PropType<'top' | 'bottom'>, + default: 'bottom', + validator: (value: string) => ['top', 'bottom'].includes(value), + }, + /** + * 节点类型 + */ + type: { + type: String as PropType<'primary' | 'success' | 'warning' | 'danger' | 'info' | ''>, + default: '', + validator: (value: string) => ['primary', 'success', 'warning', 'danger', 'info', ''].includes(value), + }, + /** + * 节点颜色 + */ + color: { + type: String, + default: '', + }, + /** + * 节点尺寸 + */ + size: { + type: String as PropType<'normal' | 'large'>, + default: 'normal', + validator: (value: string) => ['normal', 'large'].includes(value), + }, + /** + * 自定义图标 + */ + icon: { + type: [String, Object] as PropType, + }, + /** + * 是否空心点 + */ + hollow: { + type: Boolean, + default: false, + }, +} as const + +export type TimelineItemProps = ExtractPropTypes diff --git a/packages/ccui/ui/timeline/src/timeline.scss b/packages/ccui/ui/timeline/src/timeline.scss new file mode 100644 index 00000000..de1090ed --- /dev/null +++ b/packages/ccui/ui/timeline/src/timeline.scss @@ -0,0 +1,157 @@ +.ccui-timeline { + margin: 0; + font-size: 14px; + list-style: none; + padding: 0; + + // 最后一个时间线项目不显示尾部连接线 + .ccui-timeline-item:last-child { + .ccui-timeline-item__tail { + display: none; + } + } + + // 垂直居中的时间线项目 + .ccui-timeline-item__center { + display: flex; + align-items: center; + + .ccui-timeline-item__wrapper { + width: 100%; + } + + .ccui-timeline-item__tail { + top: 0; + } + } + + // 第一个垂直居中项目的特殊处理 + .ccui-timeline-item__center:first-child { + .ccui-timeline-item__tail { + height: calc(50% + 10px); + top: calc(50% - 10px); + } + } + + // 最后一个垂直居中项目的特殊处理 + .ccui-timeline-item__center:last-child { + .ccui-timeline-item__tail { + display: block; + height: calc(50% - 10px); + } + } +} + +.ccui-timeline-item { + position: relative; + padding-bottom: 20px; + + // 内容包装器 + &__wrapper { + position: relative; + padding-left: 28px; + top: -3px; + } + + // 连接线 + &__tail { + position: absolute; + left: 4px; + height: 100%; + border-left: 2px solid #e4e7ed; + } + + // 图标样式 + &__icon { + color: #ffffff; + font-size: 12px; + } + + // 节点 + &__node { + position: absolute; + background-color: #e4e7ed; + border-color: #e4e7ed; + border-radius: 50%; + box-sizing: border-box; + display: flex; + justify-content: center; + align-items: center; + + // 普通尺寸 + &--normal { + left: -1px; + width: 12px; + height: 12px; + } + + // 大尺寸 + &--large { + left: -2px; + width: 14px; + height: 14px; + } + + // 空心样式 + &.is-hollow { + background: #ffffff; + border-style: solid; + border-width: 2px; + } + + // 不同类型的颜色 + &--primary { + background-color: #409eff; + border-color: #409eff; + } + + &--success { + background-color: #67c23a; + border-color: #67c23a; + } + + &--warning { + background-color: #e6a23c; + border-color: #e6a23c; + } + + &--danger { + background-color: #f56c6c; + border-color: #f56c6c; + } + + &--info { + background-color: #909399; + border-color: #909399; + } + } + + // 自定义节点 + &__dot { + position: absolute; + display: flex; + justify-content: center; + align-items: center; + } + + // 内容区域 + &__content { + color: #303133; + } + + // 时间戳 + &__timestamp { + color: #909399; + line-height: 1; + font-size: 12px; + + &.is-top { + margin-bottom: 8px; + padding-top: 4px; + } + + &.is-bottom { + margin-top: 8px; + } + } +} diff --git a/packages/ccui/ui/timeline/src/timeline.tsx b/packages/ccui/ui/timeline/src/timeline.tsx new file mode 100644 index 00000000..9524a061 --- /dev/null +++ b/packages/ccui/ui/timeline/src/timeline.tsx @@ -0,0 +1,28 @@ +import type { TimelineProps } from './timeline-types' +import { defineComponent, provide } from 'vue' +import { useNamespace } from '../../shared/hooks/use-namespace' +import { timelineProps } from './timeline-types' +import './timeline.scss' + +// Timeline 注入的 key,用于 TimelineItem 获取父组件信息 +export const TIMELINE_INJECTION_KEY = Symbol('timeline') + +export default defineComponent({ + name: 'CTimeline', + props: timelineProps, + emits: [], + setup(props: TimelineProps, { slots }) { + const ns = useNamespace('timeline') + + // 向子组件提供 Timeline 的插槽信息 + provide(TIMELINE_INJECTION_KEY, slots) + + return () => { + return ( +
      + {slots.default && slots.default()} +
    + ) + } + }, +}) diff --git a/packages/ccui/ui/timeline/test/timeline.test.ts b/packages/ccui/ui/timeline/test/timeline.test.ts new file mode 100644 index 00000000..fa36863f --- /dev/null +++ b/packages/ccui/ui/timeline/test/timeline.test.ts @@ -0,0 +1,141 @@ +import { mount } from '@vue/test-utils' +import { describe, expect, it } from 'vitest' +import { Timeline, TimelineItem } from '../index' + +describe('timeline', () => { + it('should render', () => { + const wrapper = mount(Timeline) + expect(wrapper.exists()).toBe(true) + expect(wrapper.classes()).toContain('ccui-timeline') + }) + + it('should render timeline items', () => { + const wrapper = mount(Timeline, { + slots: { + default: ` + Test content 1 + Test content 2 + `, + }, + }) + + expect(wrapper.element.tagName).toBe('UL') + }) +}) + +describe('timelineItem', () => { + it('should render with timestamp', () => { + const wrapper = mount(TimelineItem, { + props: { + timestamp: '2018/4/12', + }, + slots: { + default: 'Test content', + }, + }) + + expect(wrapper.exists()).toBe(true) + expect(wrapper.classes()).toContain('ccui-timeline-item') + expect(wrapper.find('.ccui-timeline-item__timestamp').text()).toBe('2018/4/12') + expect(wrapper.find('.ccui-timeline-item__content').text()).toBe('Test content') + }) + + it('should hide timestamp when hideTimestamp is true', () => { + const wrapper = mount(TimelineItem, { + props: { + timestamp: '2018/4/12', + hideTimestamp: true, + }, + slots: { + default: 'Test content', + }, + }) + + expect(wrapper.find('.ccui-timeline-item__timestamp').exists()).toBe(false) + }) + + it('should render with different types', () => { + const wrapper = mount(TimelineItem, { + props: { + timestamp: '2018/4/12', + type: 'primary', + }, + slots: { + default: 'Test content', + }, + }) + + expect(wrapper.find('.ccui-timeline-item__node--primary').exists()).toBe(true) + }) + + it('should render with custom color', () => { + const wrapper = mount(TimelineItem, { + props: { + timestamp: '2018/4/12', + color: '#ff0000', + }, + slots: { + default: 'Test content', + }, + }) + + const node = wrapper.find('.ccui-timeline-item__node') + expect(node.attributes('style')).toContain('background-color: rgb(255, 0, 0)') + }) + + it('should render with large size', () => { + const wrapper = mount(TimelineItem, { + props: { + timestamp: '2018/4/12', + size: 'large', + }, + slots: { + default: 'Test content', + }, + }) + + expect(wrapper.find('.ccui-timeline-item__node--large').exists()).toBe(true) + }) + + it('should render with hollow style', () => { + const wrapper = mount(TimelineItem, { + props: { + timestamp: '2018/4/12', + hollow: true, + }, + slots: { + default: 'Test content', + }, + }) + + expect(wrapper.find('.ccui-timeline-item__node.is-hollow').exists()).toBe(true) + }) + + it('should render timestamp at top when placement is top', () => { + const wrapper = mount(TimelineItem, { + props: { + timestamp: '2018/4/12', + placement: 'top', + }, + slots: { + default: 'Test content', + }, + }) + + expect(wrapper.find('.ccui-timeline-item__timestamp.is-top').exists()).toBe(true) + }) + + it('should render with center alignment', () => { + const wrapper = mount(TimelineItem, { + props: { + timestamp: '2018/4/12', + center: true, + }, + slots: { + default: 'Test content', + }, + }) + + expect(wrapper.classes()).toContain('ccui-timeline-item__center') + }) +}) diff --git a/packages/docs/components/timeline/index.md b/packages/docs/components/timeline/index.md new file mode 100644 index 00000000..e1a960de --- /dev/null +++ b/packages/docs/components/timeline/index.md @@ -0,0 +1,191 @@ +# Timeline 时间线 + +可视化地呈现时间流信息。 + +### 何时使用 + +- 当有一系列信息需按时间排列时 +- 需要有一条时间轴进行视觉上的串联时 + +### 基本用法 + +Timeline 可拆分成多个按照时间戳排列的活动,时间戳是其区分于其他控件的重要特征。 + +:::demo + +```vue + + + +``` + +::: + +### 自定义节点样式 + +可根据实际场景自定义节点尺寸、颜色,或直接使用图标。 + +:::demo + +```vue + + + +``` + +::: + +### 自定义时间戳 + +当内容在垂直方向上过高时,可将时间戳置于内容之上。 + +:::demo + +```vue + + + +``` + +::: + +### 垂直居中 + +垂直居中样式的 Timeline-Item。 + +:::demo + +```vue + + + +``` + +::: + +## Timeline API + +### Timeline 插槽 + +| 插槽名 | 说明 | 子标签 | +| ---- | ---- | ---- | +| default | timeline 组件的自定义默认内容 | Timeline-Item | + +## Timeline-Item API + +### Timeline-Item 属性 + +| 参数 | 类型 | 默认值 | 说明 | +| ---- | ---- | ---- | ---- | +| timestamp | string | '' | 时间戳 | +| hide-timestamp | boolean | false | 是否隐藏时间戳 | +| center | boolean | false | 是否垂直居中 | +| placement | 'top' \| 'bottom' | 'bottom' | 时间戳位置 | +| type | 'primary' \| 'success' \| 'warning' \| 'danger' \| 'info' \| '' | '' | 节点类型 | +| color | string | '' | 节点颜色 | +| size | 'normal' \| 'large' | 'normal' | 节点尺寸 | +| icon | string \| Component | — | 自定义图标 | +| hollow | boolean | false | 是否空心点 | + +### Timeline-Item 插槽 + +| 插槽名 | 说明 | +| ---- | ---- | +| default | 自定义内容 | +| dot | 自定义节点 | + From 77139e59beb220675ba61cd50a175a4e7e2ab885 Mon Sep 17 00:00:00 2001 From: vaebe <18137693952@163.com> Date: Thu, 13 Nov 2025 20:50:30 +0800 Subject: [PATCH 02/10] =?UTF-8?q?style:=20=E5=A2=9E=E5=8A=A0=E6=B7=B1?= =?UTF-8?q?=E8=89=B2=E4=B8=BB=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/ccui/ui/timeline/src/timeline.scss | 44 +++++++++++---------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/packages/ccui/ui/timeline/src/timeline.scss b/packages/ccui/ui/timeline/src/timeline.scss index de1090ed..abf880c4 100644 --- a/packages/ccui/ui/timeline/src/timeline.scss +++ b/packages/ccui/ui/timeline/src/timeline.scss @@ -1,6 +1,8 @@ +@use '../../style-var/index.scss' as *; + .ccui-timeline { margin: 0; - font-size: 14px; + font-size: $ccui-font-size-lg; list-style: none; padding: 0; @@ -58,20 +60,20 @@ position: absolute; left: 4px; height: 100%; - border-left: 2px solid #e4e7ed; + border-left: 2px solid $ccui-dividing-line; } // 图标样式 &__icon { - color: #ffffff; - font-size: 12px; + color: $ccui-light-text; + font-size: $ccui-font-size-sm; } // 节点 &__node { position: absolute; - background-color: #e4e7ed; - border-color: #e4e7ed; + background-color: $ccui-dividing-line; + border-color: $ccui-dividing-line; border-radius: 50%; box-sizing: border-box; display: flex; @@ -94,35 +96,35 @@ // 空心样式 &.is-hollow { - background: #ffffff; + background: $ccui-base-bg; border-style: solid; border-width: 2px; } // 不同类型的颜色 &--primary { - background-color: #409eff; - border-color: #409eff; + background-color: $ccui-primary; + border-color: $ccui-primary; } &--success { - background-color: #67c23a; - border-color: #67c23a; + background-color: $ccui-success; + border-color: $ccui-success; } &--warning { - background-color: #e6a23c; - border-color: #e6a23c; + background-color: $ccui-warning; + border-color: $ccui-warning; } &--danger { - background-color: #f56c6c; - border-color: #f56c6c; + background-color: $ccui-danger; + border-color: $ccui-danger; } &--info { - background-color: #909399; - border-color: #909399; + background-color: $ccui-info; + border-color: $ccui-info; } } @@ -136,14 +138,14 @@ // 内容区域 &__content { - color: #303133; + color: $ccui-text; } // 时间戳 &__timestamp { - color: #909399; - line-height: 1; - font-size: 12px; + color: $ccui-aide-text; + line-height: $ccui-line-height-base; + font-size: $ccui-font-size-sm; &.is-top { margin-bottom: 8px; From 7cc64c535579be8d66c5555233ef5e6aaad03934 Mon Sep 17 00:00:00 2001 From: vaebe <18137693952@163.com> Date: Thu, 13 Nov 2025 20:53:53 +0800 Subject: [PATCH 03/10] =?UTF-8?q?style:=20=E6=A0=B7=E5=BC=8F=E4=BC=98?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/ccui/ui/timeline/src/timeline.scss | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/packages/ccui/ui/timeline/src/timeline.scss b/packages/ccui/ui/timeline/src/timeline.scss index abf880c4..5068d438 100644 --- a/packages/ccui/ui/timeline/src/timeline.scss +++ b/packages/ccui/ui/timeline/src/timeline.scss @@ -47,6 +47,16 @@ .ccui-timeline-item { position: relative; padding-bottom: 20px; + list-style: none; + + // 确保隐藏所有列表标记 + &::marker { + display: none; + } + + &::before { + display: none; + } // 内容包装器 &__wrapper { From cf0da348246b24c7f63c6c1e3384e926b60733ed Mon Sep 17 00:00:00 2001 From: vaebe <18137693952@163.com> Date: Thu, 13 Nov 2025 21:09:49 +0800 Subject: [PATCH 04/10] =?UTF-8?q?style:=20=E6=9B=B4=E6=96=B0=E6=A0=B7?= =?UTF-8?q?=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/ccui/ui/timeline/src/timeline.scss | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/ccui/ui/timeline/src/timeline.scss b/packages/ccui/ui/timeline/src/timeline.scss index 5068d438..2a34b624 100644 --- a/packages/ccui/ui/timeline/src/timeline.scss +++ b/packages/ccui/ui/timeline/src/timeline.scss @@ -69,7 +69,8 @@ &__tail { position: absolute; left: 4px; - height: 100%; + top: 0; + height: calc(100% + 20px); border-left: 2px solid $ccui-dividing-line; } @@ -93,6 +94,7 @@ // 普通尺寸 &--normal { left: -1px; + top: 0; width: 12px; height: 12px; } @@ -100,6 +102,7 @@ // 大尺寸 &--large { left: -2px; + top: 0; width: 14px; height: 14px; } @@ -141,6 +144,8 @@ // 自定义节点 &__dot { position: absolute; + top: 0; + left: -6px; display: flex; justify-content: center; align-items: center; From 3102a1075412493ba768d0ea33befb461e86407d Mon Sep 17 00:00:00 2001 From: vaebe <18137693952@163.com> Date: Thu, 13 Nov 2025 21:13:34 +0800 Subject: [PATCH 05/10] =?UTF-8?q?style:=20=E4=BF=AE=E5=A4=8D=E6=A0=B7?= =?UTF-8?q?=E5=BC=8F=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/ccui/ui/timeline/src/timeline.scss | 27 +++++++++++++++------ 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/packages/ccui/ui/timeline/src/timeline.scss b/packages/ccui/ui/timeline/src/timeline.scss index 2a34b624..4f2ab091 100644 --- a/packages/ccui/ui/timeline/src/timeline.scss +++ b/packages/ccui/ui/timeline/src/timeline.scss @@ -14,32 +14,45 @@ } // 垂直居中的时间线项目 - .ccui-timeline-item__center { + .ccui-timeline-item.ccui-timeline-item__center { display: flex; align-items: center; + min-height: 60px; .ccui-timeline-item__wrapper { width: 100%; } .ccui-timeline-item__tail { - top: 0; + top: 6px; + height: calc(100% + 14px); + } + + .ccui-timeline-item__node { + top: 50%; + transform: translateY(-50%); + } + + .ccui-timeline-item__dot { + top: 50%; + transform: translateY(-50%); } } // 第一个垂直居中项目的特殊处理 - .ccui-timeline-item__center:first-child { + .ccui-timeline-item.ccui-timeline-item__center:first-child { .ccui-timeline-item__tail { - height: calc(50% + 10px); - top: calc(50% - 10px); + top: 50%; + height: calc(50% + 20px); } } // 最后一个垂直居中项目的特殊处理 - .ccui-timeline-item__center:last-child { + .ccui-timeline-item.ccui-timeline-item__center:last-child { .ccui-timeline-item__tail { display: block; - height: calc(50% - 10px); + height: 50%; + top: 6px; } } } From 7ff7790916ed8dd000049962b18432bf663f3390 Mon Sep 17 00:00:00 2001 From: vaebe <18137693952@163.com> Date: Thu, 13 Nov 2025 21:41:42 +0800 Subject: [PATCH 06/10] =?UTF-8?q?feat:=20=E6=96=87=E6=A1=A3=E5=AE=8C?= =?UTF-8?q?=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ccui/ui/timeline/src/timeline-types.ts | 4 +- packages/docs/components/divider/index.md | 2 +- packages/docs/components/timeline/index.md | 262 ++++++++++++------ 3 files changed, 177 insertions(+), 91 deletions(-) diff --git a/packages/ccui/ui/timeline/src/timeline-types.ts b/packages/ccui/ui/timeline/src/timeline-types.ts index 32f74b4c..b170587c 100644 --- a/packages/ccui/ui/timeline/src/timeline-types.ts +++ b/packages/ccui/ui/timeline/src/timeline-types.ts @@ -7,6 +7,8 @@ export const timelineProps = { export type TimelineProps = ExtractPropTypes +export type TimelineItemType = 'primary' | 'success' | 'warning' | 'danger' | 'info' | '' + // TimelineItem 组件的 props export const timelineItemProps = { /** @@ -42,7 +44,7 @@ export const timelineItemProps = { * 节点类型 */ type: { - type: String as PropType<'primary' | 'success' | 'warning' | 'danger' | 'info' | ''>, + type: String as PropType, default: '', validator: (value: string) => ['primary', 'success', 'warning', 'danger', 'info', ''].includes(value), }, diff --git a/packages/docs/components/divider/index.md b/packages/docs/components/divider/index.md index 088052e0..88c21799 100644 --- a/packages/docs/components/divider/index.md +++ b/packages/docs/components/divider/index.md @@ -82,7 +82,7 @@ export default defineComponent({ | color | string | -- | 设置分隔线的颜色 | | direction | [DirectionType](#directiontype) | horizontal | 设置分隔线方向 | | border-style | [BorderStyleType](#borderstyletype) | solid | 设置分隔符样式 | -| content-position | [ContentPositionType](#Contentpositiontype) | center | 设置分隔线文案的位置 | +| content-position | [ContentPositionType](#contentpositiontype) | center | 设置分隔线文案的位置 | | content-color | string | -- | 设置分隔线文案的颜色 | | content-background-color | string | -- | 设置分隔线文案的背景颜色 | diff --git a/packages/docs/components/timeline/index.md b/packages/docs/components/timeline/index.md index e1a960de..728370ef 100644 --- a/packages/docs/components/timeline/index.md +++ b/packages/docs/components/timeline/index.md @@ -2,32 +2,18 @@ 可视化地呈现时间流信息。 -### 何时使用 +## 何时使用 - 当有一系列信息需按时间排列时 - 需要有一条时间轴进行视觉上的串联时 -### 基本用法 +## 基本用法 Timeline 可拆分成多个按照时间戳排列的活动,时间戳是其区分于其他控件的重要特征。 :::demo ```vue - - + + + + ``` ::: -### 自定义节点样式 +## 自定义节点样式 可根据实际场景自定义节点尺寸、颜色,或直接使用图标。 :::demo ```vue - - + + + + ``` ::: -### 自定义时间戳 +## 自定义时间戳 当内容在垂直方向上过高时,可将时间戳置于内容之上。 :::demo ```vue - - + + + + ``` ::: -### 垂直居中 +## 垂直居中 垂直居中样式的 Timeline-Item。 :::demo ```vue + + + +``` + +::: + +## 自定义节点 + +可以通过插槽自定义节点。 + +:::demo + +```vue + + + + ``` ::: -## Timeline API +## API + +### Timeline Props -### Timeline 插槽 +| 参数 | 说明 | 类型 | 可选值 | 默认值 | +| ---- | ---- | ---- | ---- | ---- | +| — | — | — | — | — | + +### Timeline Events + +| 事件名 | 说明 | 回调参数 | +| ---- | ---- | ---- | +| — | — | — | + +### Timeline Slots | 插槽名 | 说明 | 子标签 | | ---- | ---- | ---- | | default | timeline 组件的自定义默认内容 | Timeline-Item | -## Timeline-Item API +### Timeline-Item Props + +| 参数 | 说明 | 类型 | 可选值 | 默认值 | +| ---- | -------- | ---- | ---- | ---- | +| timestamp | 时间戳 | string | — | '' | +| hide-timestamp | 是否隐藏时间戳 | boolean | — | false | +| center | 是否垂直居中 | boolean | — | false | +| placement | 时间戳位置 | string | top/bottom | bottom | +| type | 节点类型 | string | [TimelineItemType](#timelineitemtype) | — | +| color | 节点颜色 | string | — | — | +| size | 节点尺寸 | string | normal/large | normal | +| icon | 自定义图标 | string/Component | — | — | +| hollow | 是否空心点 | boolean | — | false | -### Timeline-Item 属性 +### Timeline-Item Events -| 参数 | 类型 | 默认值 | 说明 | -| ---- | ---- | ---- | ---- | -| timestamp | string | '' | 时间戳 | -| hide-timestamp | boolean | false | 是否隐藏时间戳 | -| center | boolean | false | 是否垂直居中 | -| placement | 'top' \| 'bottom' | 'bottom' | 时间戳位置 | -| type | 'primary' \| 'success' \| 'warning' \| 'danger' \| 'info' \| '' | '' | 节点类型 | -| color | string | '' | 节点颜色 | -| size | 'normal' \| 'large' | 'normal' | 节点尺寸 | -| icon | string \| Component | — | 自定义图标 | -| hollow | boolean | false | 是否空心点 | +| 事件名 | 说明 | 回调参数 | +| ---- | ---- | ---- | +| — | — | — | -### Timeline-Item 插槽 +### Timeline-Item Slots | 插槽名 | 说明 | | ---- | ---- | | default | 自定义内容 | | dot | 自定义节点 | +## Divider类型定义 + +### TimelineItemType + +```ts +export type TimelineItemType = 'primary' | 'success' | 'warning' | 'danger' | 'info' | '' +``` From c05e39c7e43962b66695b53bc2a236b66c53b2d9 Mon Sep 17 00:00:00 2001 From: vaebe <18137693952@163.com> Date: Thu, 13 Nov 2025 21:51:31 +0800 Subject: [PATCH 07/10] =?UTF-8?q?feat:=20=E8=B7=9F=E6=96=B0=E6=A0=B7?= =?UTF-8?q?=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/docs/components/timeline/index.md | 50 ++++++++-------------- 1 file changed, 19 insertions(+), 31 deletions(-) diff --git a/packages/docs/components/timeline/index.md b/packages/docs/components/timeline/index.md index 728370ef..1704db37 100644 --- a/packages/docs/components/timeline/index.md +++ b/packages/docs/components/timeline/index.md @@ -27,13 +27,13 @@ export default defineComponent({