ThoughtChain 思维链 🔗
介绍
ThoughtChain
是一个用于展示AI思考过程的时间轴组件,支持 状态管理、内容展开/收起 和 动态样式配置。通过可视化的思考步骤序列,帮助用户直观理解复杂逻辑流程。组件内置多种状态反馈、过渡动画和扩展插槽,适用于智能对话、数据分析、流程引导等场景。
代码示例
通过 thinkingItems
传入一个数组控制渲染。
💌 消息
id
为必传字段。你还可以通过 rowKey
设置唯一标识的名称,默认为 id
。
vue
<script setup lang="ts">
import type { ThoughtChainItemProps } from '../types'
interface DataType {
codeId: string
title?: string
thinkTitle?: string
thinkContent?: string
status?: 'success' | 'loading' | 'error'
}
const thinkingItems: ThoughtChainItemProps<DataType>[] = [
{
codeId: '1',
status: 'success',
isCanExpand: true,
isDefaultExpand: true,
title: '成功-主标题',
thinkTitle: '思考内容标题-默认展开',
thinkContent: '进行搜索文字'.repeat(10),
},
{
codeId: '2',
title: '加载中-主标题',
status: 'loading',
isCanExpand: true,
isDefaultExpand: false,
thinkTitle: '思考内容标题',
thinkContent: '进行搜索文字'.repeat(10),
},
{
codeId: '3',
title: '失败-主标题',
status: 'error',
isCanExpand: true,
isDefaultExpand: false,
thinkTitle: '思考内容标题',
thinkContent: '进行搜索文字'.repeat(10),
},
{
codeId: '4',
title: '失败-主标题',
status: 'error',
isCanExpand: true,
isDefaultExpand: true,
thinkTitle: '思考内容标题',
thinkContent: '进行搜索文字'.repeat(10),
},
]
</script>
<template>
<ThoughtChain :thinking-items="thinkingItems" row-key="codeId" />
</template>
<style scoped lang="less">
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
默认值是 default
,可选值有 small
、default
、large
。
vue
<script setup lang="ts">
import type { ThoughtChainItemProps } from '../types'
interface DataType {
id: string
title?: string
thinkTitle?: string
thinkContent?: string
status?: 'success' | 'loading' | 'error'
hideTitle?: boolean
}
const thinkingItems: ThoughtChainItemProps<DataType>[] = [
{
id: '1',
status: 'success',
isCanExpand: true,
isDefaultExpand: true,
title: '成功-主标题',
thinkTitle: '思考内容标题-默认展开',
thinkContent: '进行搜索文字'.repeat(10),
},
{
id: '2',
title: '加载中-主标题',
status: 'loading',
isCanExpand: true,
isDefaultExpand: false,
thinkTitle: '思考内容标题',
thinkContent: '进行搜索文字'.repeat(10),
},
{
id: '3',
title: '失败-主标题',
status: 'error',
isCanExpand: true,
isDefaultExpand: false,
thinkTitle: '思考内容标题',
thinkContent: '进行搜索文字'.repeat(10),
},
{
id: '4',
hideTitle: true,
status: 'loading',
isCanExpand: true,
isDefaultExpand: true,
thinkTitle: '隐藏主标题,思考内容标题-默认展开',
thinkContent: '进行搜索文字'.repeat(10),
},
]
</script>
<template>
<ThoughtChain :thinking-items="thinkingItems" dot-size="small" />
<ThoughtChain :thinking-items="thinkingItems" dot-size="large" />
</template>
<style scoped lang="less">
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
设置 思维链的最大宽度,默认 '500px'。字符串类型,意味着你可以传入百分比,如 '50%'。或其他单位,甚至 css 计算宽度,如 'calc(100% - 200px)'。
vue
<script setup lang="ts">
import type { ThoughtChainItemProps } from '../types'
interface DataType {
id: string
title?: string
thinkTitle?: string
thinkContent?: string
status?: 'success' | 'loading' | 'error'
hideTitle?: boolean
}
const thinkingItems: ThoughtChainItemProps<DataType>[] = [
{
id: '1',
status: 'success',
isCanExpand: true,
isDefaultExpand: true,
title: '成功-主标题',
thinkTitle: '思考内容标题-默认展开',
thinkContent: '进行搜索文字'.repeat(20),
},
]
</script>
<template>
<ThoughtChain :thinking-items="thinkingItems" max-width="calc(100% - 300px)" />
</template>
<style scoped lang="less">
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
通过 titleKey
、thinkTitleKey
、thinkContentKey
属性,可以自定义节点的:标题、思考内容标题、思考内容 的 key 名称。
vue
<script setup lang="ts">
import type { ThoughtChainItemProps } from '../types'
interface DataType {
codeId: string
self_title?: string
self_thinkTitle?: string
self_thinkContent?: string
status?: 'success' | 'loading' | 'error'
}
const thinkingItems: ThoughtChainItemProps<DataType>[] = [
{
codeId: '1',
status: 'success',
isCanExpand: true,
isDefaultExpand: true,
self_title: '成功-主标题',
self_thinkTitle: '思考内容标题-默认展开',
self_thinkContent: '进行搜索文字'.repeat(10),
},
{
codeId: '2',
self_title: '加载中-主标题',
status: 'loading',
isCanExpand: true,
isDefaultExpand: false,
self_thinkTitle: '思考内容标题',
self_thinkContent: '进行搜索文字'.repeat(10),
},
{
codeId: '3',
self_title: '失败-主标题',
status: 'error',
isCanExpand: true,
isDefaultExpand: false,
self_thinkTitle: '思考内容标题',
self_thinkContent: '进行搜索文字'.repeat(10),
},
{
codeId: '4',
self_title: '谢谢-主标题',
status: 'success',
isCanExpand: true,
isDefaultExpand: true,
self_thinkTitle: '思考内容标题',
self_thinkContent: '进行搜索文字'.repeat(10),
},
]
</script>
<template>
<ThoughtChain
:thinking-items="thinkingItems"
row-key="codeId"
title-key="self_title"
think-title-key="self_thinkTitle"
think-content-key="self_thinkContent"
/>
</template>
<style scoped lang="less">
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
通过 #icon
插槽,可以自定义 不同状态的 图标。 通过 #icon={item}
可以获取到当前状态。
vue
<script setup lang="ts">
import type { ThoughtChainItemProps } from '../types'
import { CircleCloseFilled, Loading, SuccessFilled } from '@element-plus/icons-vue'
interface DataType {
codeId: string
self_title?: string
self_thinkTitle?: string
self_thinkContent?: string
status?: 'success' | 'loading' | 'error'
}
const thinkingItems: ThoughtChainItemProps<DataType>[] = [
{
codeId: '1',
status: 'success',
isCanExpand: true,
isDefaultExpand: true,
self_title: '成功-主标题',
self_thinkTitle: '思考内容标题-默认展开',
self_thinkContent: '进行搜索文字'.repeat(10),
},
{
codeId: '2',
self_title: '加载中-主标题',
status: 'loading',
isCanExpand: true,
isDefaultExpand: false,
self_thinkTitle: '思考内容标题',
self_thinkContent: '进行搜索文字'.repeat(10),
},
{
codeId: '3',
self_title: '失败-主标题',
status: 'error',
isCanExpand: true,
isDefaultExpand: false,
self_thinkTitle: '思考内容标题',
self_thinkContent: '进行搜索文字'.repeat(10),
},
{
codeId: '4',
self_title: '谢谢-主标题',
status: 'success',
isCanExpand: true,
isDefaultExpand: true,
self_thinkTitle: '思考内容标题',
self_thinkContent: '进行搜索文字'.repeat(10),
},
]
</script>
<template>
<ThoughtChain
:thinking-items="thinkingItems"
row-key="codeId"
title-key="self_title"
think-title-key="self_thinkTitle"
think-content-key="self_thinkContent"
>
<template #icon="{ item }">
<span
v-if="item.status === 'success'"
style="font-size: 18px; margin-left: 7px; color: var(--el-color-success);"
>
<el-icon><SuccessFilled /></el-icon>
</span>
<span
v-if="item.status === 'error'"
style="font-size: 18px; margin-left: 7px; color: var(--el-color-danger);"
>
<el-icon><CircleCloseFilled /></el-icon>
</span>
<span
v-if="item.status === 'loading'"
style="font-size: 18px; margin-left: 7px; "
>
<el-icon class="is-loading"><Loading /></el-icon>
</span>
</template>
</ThoughtChain>
</template>
<style scoped lang="less">
.is-loading {
animation: spin 1s infinite linear;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
通过 handleExpand 事件,可以获取到当前展开的节点数据。
vue
<script setup lang="ts">
import type { ThoughtChainItemProps } from '../types'
interface DataType {
codeId: string
self_title?: string
self_thinkTitle?: string
self_thinkContent?: string
status?: 'success' | 'loading' | 'error'
}
const thinkingItems: ThoughtChainItemProps<DataType>[] = [
{
codeId: '1',
status: 'success',
isCanExpand: true,
isDefaultExpand: true,
self_title: '成功-主标题',
self_thinkTitle: '思考内容标题-默认展开',
self_thinkContent: '进行搜索文字'.repeat(10),
},
{
codeId: '2',
self_title: '加载中-主标题',
status: 'loading',
isCanExpand: true,
isDefaultExpand: false,
self_thinkTitle: '思考内容标题',
self_thinkContent: '进行搜索文字'.repeat(10),
},
{
codeId: '3',
self_title: '失败-主标题',
status: 'error',
isCanExpand: true,
isDefaultExpand: false,
self_thinkTitle: '思考内容标题',
self_thinkContent: '进行搜索文字'.repeat(10),
},
{
codeId: '4',
self_title: '谢谢-主标题',
status: 'success',
isCanExpand: true,
isDefaultExpand: true,
self_thinkTitle: '思考内容标题',
self_thinkContent: '进行搜索文字'.repeat(10),
},
]
</script>
<template>
<ThoughtChain
:thinking-items="thinkingItems"
row-key="codeId"
title-key="self_title"
think-title-key="self_thinkTitle"
think-content-key="self_thinkContent"
@handle-expand="(data: DataType) => console.log(data)"
/>
</template>
<style scoped lang="less">
.is-loading {
animation: spin 1s infinite linear;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
属性
- 组件属性
参数名 | 类型 | 默认值 | 描述 |
---|---|---|---|
thinkingItems | Array<ThoughtChainItemBase> | [] | 思考项数组 |
dotSize | 'small'/'default'/'large' | 'default' | 时间轴点大小 |
maxWidth | string | '600px' | 最大宽度 |
lineGradient | boolean | false | 是否启用线条颜色渐变 |
rowKey | string | 'id' | 数据项唯一标识字段 |
titleKey | string | 'title' | 标题字段名 |
thinkTitleKey | string | 'thinkTitle' | 思考标题字段名 |
thinkContentKey | string | 'thinkContent' | 思考内容字段名 |
- ThoughtChainItemBase 数组子项的类型定义
参数名 | 类型 | 默认值 | 描述 |
---|---|---|---|
id | string | number | 必填 | 节点唯一标识 |
title | string | undefined | 主标题 |
thinkTitle | string | undefined | 折叠面板标题(思考标题) |
thinkContent | string | undefined | 展开时显示的详细内容 |
status | 'loading' | 'error' | 'success' | undefined | 节点状态标识(影响图标和颜色) |
isCanExpand | boolean | undefined | 是否允许展开节点内容 |
isDefaultExpand | boolean | undefined | 是否默认展开节点内容 |
isMarkdown | boolean | undefined | 是否启用Markdown格式渲染 |
typing | TypingConfig | undefined | 打字机效果配置(同打字器组件) |
事件
事件名 | 参数类型 | 说明 |
---|---|---|
handleExpand | item: ThoughtChainItemProps<T> | 展开状态变化时触发 |
插槽
插槽名 | 作用域参数 | 说明 |
---|---|---|
#icon | { item } | 自定义时间轴点图标 |
核心特性
多状态可视化
- 支持
loading
/success
/error
- 自动切换加载动画、图标和颜色反馈
- 支持
动态内容管理
- 支持内容折叠展开(可配置默认展开项)
- 内置打字机效果(Typewriter组件)
- 支持Markdown格式渲染
灵活样式配置
- 自定义时间轴宽度、点大小
- 动态颜色渐变线条
- CSS变量主题覆盖
响应式交互
- 平滑的过渡动画
- 支持动态增删思考项
- 展开状态双向绑定