@tfdesign/b-end 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (176) hide show
  1. package/AI_READ_FIRST.md +131 -0
  2. package/LICENSE +21 -0
  3. package/README.md +353 -0
  4. package/package.json +67 -0
  5. package/scripts/check-tfds-contract.mjs +334 -0
  6. package/scripts/check-tfds-integration.mjs +263 -0
  7. package/scripts/postinstall-cursor-skill.mjs +382 -0
  8. package/scripts/setup.mjs +520 -0
  9. package/skills/tfds/CHECKLIST.md +205 -0
  10. package/skills/tfds/COMMON_FAILURES.md +238 -0
  11. package/skills/tfds/DESIGN_PRINCIPLES.md +477 -0
  12. package/skills/tfds/GLOBAL_DESIGN_RULES.md +636 -0
  13. package/skills/tfds/LAYOUT_RECIPES.md +140 -0
  14. package/skills/tfds/LAYOUT_RULES.md +1355 -0
  15. package/skills/tfds/PAGE_ARCHETYPES.md +201 -0
  16. package/skills/tfds/SKILL.md +188 -0
  17. package/skills/tfds/components.index.json +7305 -0
  18. package/skills/tfds/components.summary.json +1809 -0
  19. package/src/_b_end_runtime/components/AiSuggestionShared.jsx +166 -0
  20. package/src/_b_end_runtime/components/Avatar.jsx +325 -0
  21. package/src/_b_end_runtime/components/Avatar.tokens.js +76 -0
  22. package/src/_b_end_runtime/components/AvatarGridPreview.jsx +56 -0
  23. package/src/_b_end_runtime/components/AvatarGroup.jsx +80 -0
  24. package/src/_b_end_runtime/components/AvatarGroup.tokens.js +28 -0
  25. package/src/_b_end_runtime/components/Button.jsx +144 -0
  26. package/src/_b_end_runtime/components/Button.tokens.js +90 -0
  27. package/src/_b_end_runtime/components/Card.jsx +460 -0
  28. package/src/_b_end_runtime/components/Card.tokens.js +124 -0
  29. package/src/_b_end_runtime/components/CardPreview.jsx +51 -0
  30. package/src/_b_end_runtime/components/ChatBubble.jsx +384 -0
  31. package/src/_b_end_runtime/components/ChatBubble.tokens.js +60 -0
  32. package/src/_b_end_runtime/components/ChatBubblePreview.jsx +129 -0
  33. package/src/_b_end_runtime/components/ChatInput.jsx +1399 -0
  34. package/src/_b_end_runtime/components/ChatInput.tokens.js +75 -0
  35. package/src/_b_end_runtime/components/ChatMessage.jsx +2215 -0
  36. package/src/_b_end_runtime/components/ChatMessage.tokens.js +257 -0
  37. package/src/_b_end_runtime/components/ChatMessagePreview.jsx +388 -0
  38. package/src/_b_end_runtime/components/Checkbox.jsx +317 -0
  39. package/src/_b_end_runtime/components/Checkbox.tokens.js +59 -0
  40. package/src/_b_end_runtime/components/ConversationList.jsx +1264 -0
  41. package/src/_b_end_runtime/components/ConversationList.tokens.js +135 -0
  42. package/src/_b_end_runtime/components/ConversationListPreview.jsx +108 -0
  43. package/src/_b_end_runtime/components/CustomerServiceWorkspaceFrame.jsx +324 -0
  44. package/src/_b_end_runtime/components/CustomerServiceWorkspaceFrame.tokens.js +69 -0
  45. package/src/_b_end_runtime/components/DatePicker.jsx +739 -0
  46. package/src/_b_end_runtime/components/DatePicker.tokens.js +99 -0
  47. package/src/_b_end_runtime/components/Empty.jsx +141 -0
  48. package/src/_b_end_runtime/components/Empty.tokens.js +40 -0
  49. package/src/_b_end_runtime/components/Form.jsx +609 -0
  50. package/src/_b_end_runtime/components/Form.tokens.js +77 -0
  51. package/src/_b_end_runtime/components/FormFieldStack.jsx +123 -0
  52. package/src/_b_end_runtime/components/FormFieldStack.tokens.js +12 -0
  53. package/src/_b_end_runtime/components/FormTitle.jsx +119 -0
  54. package/src/_b_end_runtime/components/FormTitle.tokens.js +87 -0
  55. package/src/_b_end_runtime/components/FullScreenPage.jsx +97 -0
  56. package/src/_b_end_runtime/components/FullScreenPage.tokens.js +19 -0
  57. package/src/_b_end_runtime/components/Icon.jsx +172 -0
  58. package/src/_b_end_runtime/components/Icon.tokens.js +26 -0
  59. package/src/_b_end_runtime/components/IconGridPreview.jsx +277 -0
  60. package/src/_b_end_runtime/components/InfoDisplayPanel.jsx +620 -0
  61. package/src/_b_end_runtime/components/InfoDisplayPanel.tokens.js +71 -0
  62. package/src/_b_end_runtime/components/InfoDisplayPanelPreview.jsx +133 -0
  63. package/src/_b_end_runtime/components/Input.jsx +258 -0
  64. package/src/_b_end_runtime/components/Input.tokens.js +68 -0
  65. package/src/_b_end_runtime/components/InputNumber.jsx +242 -0
  66. package/src/_b_end_runtime/components/InputNumber.tokens.js +55 -0
  67. package/src/_b_end_runtime/components/Modal.jsx +155 -0
  68. package/src/_b_end_runtime/components/Modal.tokens.js +73 -0
  69. package/src/_b_end_runtime/components/NavBar.jsx +842 -0
  70. package/src/_b_end_runtime/components/NavBar.tokens.js +97 -0
  71. package/src/_b_end_runtime/components/NavBarPreview.jsx +11 -0
  72. package/src/_b_end_runtime/components/Radio.jsx +227 -0
  73. package/src/_b_end_runtime/components/Radio.tokens.js +59 -0
  74. package/src/_b_end_runtime/components/Select.jsx +766 -0
  75. package/src/_b_end_runtime/components/Select.tokens.js +99 -0
  76. package/src/_b_end_runtime/components/Sheet.jsx +132 -0
  77. package/src/_b_end_runtime/components/Sheet.tokens.js +61 -0
  78. package/src/_b_end_runtime/components/Slider.jsx +346 -0
  79. package/src/_b_end_runtime/components/Slider.tokens.js +47 -0
  80. package/src/_b_end_runtime/components/Switch.jsx +124 -0
  81. package/src/_b_end_runtime/components/Switch.tokens.js +38 -0
  82. package/src/_b_end_runtime/components/Table.jsx +1338 -0
  83. package/src/_b_end_runtime/components/Table.tokens.js +147 -0
  84. package/src/_b_end_runtime/components/TablePreview.jsx +599 -0
  85. package/src/_b_end_runtime/components/Tabs.jsx +149 -0
  86. package/src/_b_end_runtime/components/Tabs.tokens.js +102 -0
  87. package/src/_b_end_runtime/components/Tag.jsx +199 -0
  88. package/src/_b_end_runtime/components/Tag.tokens.js +171 -0
  89. package/src/_b_end_runtime/components/TagBar.jsx +1134 -0
  90. package/src/_b_end_runtime/components/TagBar.tokens.js +75 -0
  91. package/src/_b_end_runtime/components/TagGridPreview.jsx +23 -0
  92. package/src/_b_end_runtime/components/TagInput.jsx +382 -0
  93. package/src/_b_end_runtime/components/TagInput.tokens.js +52 -0
  94. package/src/_b_end_runtime/components/TextArea.jsx +363 -0
  95. package/src/_b_end_runtime/components/TextArea.tokens.js +65 -0
  96. package/src/_b_end_runtime/components/TimePicker.jsx +444 -0
  97. package/src/_b_end_runtime/components/TimePicker.tokens.js +77 -0
  98. package/src/_b_end_runtime/components/Toast.jsx +120 -0
  99. package/src/_b_end_runtime/components/Toast.tokens.js +146 -0
  100. package/src/_b_end_runtime/components/Tooltip.jsx +282 -0
  101. package/src/_b_end_runtime/components/Tooltip.tokens.js +48 -0
  102. package/src/_b_end_runtime/components/TooltipPreview.jsx +50 -0
  103. package/src/_b_end_runtime/components/Upload.jsx +455 -0
  104. package/src/_b_end_runtime/components/Upload.tokens.js +47 -0
  105. package/src/_b_end_runtime/components/avatar-assets/avatar-default.png +0 -0
  106. package/src/_b_end_runtime/components/avatar-group-assets/avatar-group-1.png +0 -0
  107. package/src/_b_end_runtime/components/avatar-group-assets/avatar-group-2.png +0 -0
  108. package/src/_b_end_runtime/components/avatar-group-assets/avatar-group-3.png +0 -0
  109. package/src/_b_end_runtime/components/avatar-group-assets/avatar-group-4.png +0 -0
  110. package/src/_b_end_runtime/components/avatar-group-assets/avatar-group-5.png +0 -0
  111. package/src/_b_end_runtime/components/empty-assets/administrator-1.svg +40 -0
  112. package/src/_b_end_runtime/components/empty-assets/administrator-2.svg +33 -0
  113. package/src/_b_end_runtime/components/empty-assets/construction.svg +33 -0
  114. package/src/_b_end_runtime/components/empty-assets/failure.svg +49 -0
  115. package/src/_b_end_runtime/components/empty-assets/idle.svg +34 -0
  116. package/src/_b_end_runtime/components/empty-assets/no-access.svg +36 -0
  117. package/src/_b_end_runtime/components/empty-assets/no-content.svg +77 -0
  118. package/src/_b_end_runtime/components/empty-assets/no-result.svg +61 -0
  119. package/src/_b_end_runtime/components/empty-assets/not-found.svg +46 -0
  120. package/src/_b_end_runtime/components/empty-assets/success.svg +38 -0
  121. package/src/_b_end_runtime/components/file-type-assets/batch-report.png +0 -0
  122. package/src/_b_end_runtime/components/file-type-assets/catcat.svg +21 -0
  123. package/src/_b_end_runtime/components/file-type-assets/code.png +0 -0
  124. package/src/_b_end_runtime/components/file-type-assets/conversation.png +0 -0
  125. package/src/_b_end_runtime/components/file-type-assets/document.png +0 -0
  126. package/src/_b_end_runtime/components/file-type-assets/feishu-card.png +0 -0
  127. package/src/_b_end_runtime/components/file-type-assets/feishu-sheet.png +0 -0
  128. package/src/_b_end_runtime/components/file-type-assets/feishu.png +0 -0
  129. package/src/_b_end_runtime/components/file-type-assets/image.png +0 -0
  130. package/src/_b_end_runtime/components/file-type-assets/index.js +105 -0
  131. package/src/_b_end_runtime/components/file-type-assets/knowledge.png +0 -0
  132. package/src/_b_end_runtime/components/file-type-assets/pdf.png +0 -0
  133. package/src/_b_end_runtime/components/file-type-assets/pe.png +0 -0
  134. package/src/_b_end_runtime/components/file-type-assets/strategy.png +0 -0
  135. package/src/_b_end_runtime/components/file-type-assets/table.png +0 -0
  136. package/src/_b_end_runtime/components/file-type-assets/webpage.png +0 -0
  137. package/src/_b_end_runtime/components/file-type-assets/xmind.png +0 -0
  138. package/src/_b_end_runtime/components/icons/icon-data.js +12496 -0
  139. package/src/_b_end_runtime/components/nav-bar-assets/bytehi-logo-mark.svg +21 -0
  140. package/src/_b_end_runtime/components/table-assets/avatar.png +0 -0
  141. package/src/_b_end_runtime/components/table-assets/button.png +0 -0
  142. package/src/_b_end_runtime/components/table-assets/icon-chevron-down.png +0 -0
  143. package/src/_b_end_runtime/components/table-cell-assets/avatar.png +0 -0
  144. package/src/_b_end_runtime/components/table-cell-assets/button.png +0 -0
  145. package/src/_b_end_runtime/components/table-cell-assets/checkbox.png +0 -0
  146. package/src/_b_end_runtime/components/table-cell-assets/icon-chevron-right.png +0 -0
  147. package/src/_b_end_runtime/components/table-cell-assets/icon.png +0 -0
  148. package/src/_b_end_runtime/components/table-cell-assets/semi-icons-handle.png +0 -0
  149. package/src/_b_end_runtime/components/table-cell-assets/semi-icons-tree-triangle-right.png +0 -0
  150. package/src/_b_end_runtime/components/table-cell-assets/switch.png +0 -0
  151. package/src/_b_end_runtime/components/tagShared.js +3 -0
  152. package/src/_b_end_runtime/components/team-avatar-assets/chengcheng-murphy.png +0 -0
  153. package/src/_b_end_runtime/components/team-avatar-assets/duan-ran.png +0 -0
  154. package/src/_b_end_runtime/components/team-avatar-assets/guo-zhezhi.png +0 -0
  155. package/src/_b_end_runtime/components/team-avatar-assets/li-siru.png +0 -0
  156. package/src/_b_end_runtime/components/team-avatar-assets/liu-delin.png +0 -0
  157. package/src/_b_end_runtime/components.js +3499 -0
  158. package/src/_b_end_runtime/index.js +9 -0
  159. package/src/_b_end_runtime/page-patterns/BasePageFramePattern.jsx +395 -0
  160. package/src/_b_end_runtime/page-patterns/ChatConversationPattern.jsx +989 -0
  161. package/src/_b_end_runtime/page-patterns/ChatHomePagePattern.jsx +281 -0
  162. package/src/_b_end_runtime/page-patterns/CopilotPagePattern.jsx +380 -0
  163. package/src/_b_end_runtime/page-patterns/CustomerServiceWorkspaceFramePattern.jsx +392 -0
  164. package/src/_b_end_runtime/page-patterns/IMConversationPattern.jsx +590 -0
  165. package/src/_b_end_runtime/page-patterns/McpManagementPage.jsx +237 -0
  166. package/src/_b_end_runtime/page-patterns/StrategyListPage.jsx +189 -0
  167. package/src/_b_end_runtime/page-patterns/TabTopBarListPage.jsx +594 -0
  168. package/src/_b_end_runtime/page-patterns/VariableManagementPage.jsx +87 -0
  169. package/src/_b_end_runtime/page-patterns/pageListShared.jsx +177 -0
  170. package/src/_b_end_runtime/patterns.js +428 -0
  171. package/src/_b_end_runtime/preview-registry.jsx +4719 -0
  172. package/src/_b_end_runtime/teamMembers.js +56 -0
  173. package/src/_b_end_runtime/tokens.js +500 -0
  174. package/src/index.d.ts +1073 -0
  175. package/src/index.js +52 -0
  176. package/theme.css +350 -0
@@ -0,0 +1,257 @@
1
+ /**
2
+ * ChatMessage — TOKEN_MAP(供平台属性面板展示)
3
+ *
4
+ * 分组顺序:文本元素 → 容器区域 → 尺寸布局 → 引用组件
5
+ */
6
+ export const CHAT_MESSAGE_TOKEN_MAP = {
7
+ base: [],
8
+ 标题行: [
9
+ { label: '标题色', cssProp: 'color', token: '--color-neutral', value: '#343B3A' },
10
+ { label: '字号', cssProp: 'font-size', token: '--text-sm', value: '14px' },
11
+ { label: '字重', cssProp: 'font-weight', token: '--font-semibold', value: '600(运行时使用 [font-weight:var(--font-semibold)])' },
12
+ { label: '行高', cssProp: 'line-height', token: '--leading-5', value: '20px' },
13
+ { label: '完成色', cssProp: 'color', token: '--color-brand-500', value: '#56D3BC' },
14
+ { label: '旋转渐变', cssProp: 'background', value: 'conic-gradient(var(--color-cyan-300) → var(--color-purple-300))' },
15
+ { label: '旋转动效', cssProp: 'animation', value: 'spin 1.1s linear infinite' },
16
+ { label: '折叠色', cssProp: 'color', token: '--color-neutral-500', value: '#858595' },
17
+ ],
18
+ 执行说明: [
19
+ { label: '文字色', cssProp: 'color', token: '--color-neutral', value: '#343B3A' },
20
+ { label: '字号', cssProp: 'font-size', token: '--text-sm', value: '14px' },
21
+ { label: '字重', cssProp: 'font-weight', token: '--font-normal', value: '400' },
22
+ { label: '行高', cssProp: 'line-height', token: '--leading-5', value: '20px' },
23
+ ],
24
+ 最终结果: [
25
+ { label: '文字色', cssProp: 'color', token: '--color-neutral', value: '#343B3A' },
26
+ { label: '字号', cssProp: 'font-size', token: '--text-sm', value: '14px' },
27
+ { label: '字重', cssProp: 'font-weight', token: '--font-normal', value: '400' },
28
+ { label: '行高', cssProp: 'line-height', token: '--leading-5', value: '20px' },
29
+ { label: '换行策略', cssProp: 'word-break', value: 'break-words / multi-line' },
30
+ ],
31
+ 产物文字: [
32
+ { label: '标题色', cssProp: 'color', token: '--color-neutral', value: '#343B3A' },
33
+ { label: '次信息色', cssProp: 'color', token: '--color-neutral-500', value: '#858595' },
34
+ { label: '字号', cssProp: 'font-size', token: '--text-xs', value: '12px' },
35
+ { label: '字重', cssProp: 'font-weight', token: '--font-semibold', value: '600(运行时使用 [font-weight:var(--font-semibold)])', state: 'title' },
36
+ { label: '行高', cssProp: 'line-height', token: '--leading-4', value: '16px' },
37
+ ],
38
+ 操作卡片: [
39
+ { label: '背景色', cssProp: 'background', token: '--color-chat-incoming', value: 'rgba(52,59,57,0.05)' },
40
+ { label: '描边色', cssProp: 'border-color', token: '--color-border-line-light', value: 'rgba(22,24,35,0.08)' },
41
+ { label: '宽度策略', cssProp: 'width/max-width', value: 'fit-content / max-width: 100%' },
42
+ { label: '圆角', cssProp: 'border-radius', token: '--radius-md', value: '8px' },
43
+ { label: '左内边距', cssProp: 'padding-left', token: '--spacing-2', value: '8px' },
44
+ { label: '右内边距', cssProp: 'padding-right', token: '--spacing-3', value: '12px' },
45
+ { label: '纵向内距', cssProp: 'padding-block', token: '--spacing-2', value: '8px' },
46
+ { label: '元素间距', cssProp: 'gap', token: '--spacing-2', value: '8px' },
47
+ ],
48
+ 卡片文字: [
49
+ { label: '主文案色', cssProp: 'color', token: '--color-neutral', value: '#343B3A' },
50
+ { label: '次文案色', cssProp: 'color', token: '--color-neutral-500', value: '#858595' },
51
+ { label: '字号', cssProp: 'font-size', token: '--text-xs', value: '12px' },
52
+ { label: '字重', cssProp: 'font-weight', token: '--font-normal', value: '400' },
53
+ { label: '行高', cssProp: 'line-height', token: '--leading-4', value: '16px' },
54
+ { label: '溢出处理', cssProp: 'text-overflow', value: 'ellipsis / nowrap / hidden' },
55
+ ],
56
+ 处理中: [
57
+ { label: '轨道描边', cssProp: 'border-color', token: '--color-border-line-light', value: 'rgba(22,24,35,0.08)' },
58
+ { label: '底色', cssProp: 'background', token: '--tfds-ai-execution-processing-fill', value: 'rgba(52,59,57,0.04)' },
59
+ { label: '扫光渐变', cssProp: 'background-image', token: '--tfds-ai-execution-processing-shimmer', value: 'linear-gradient(90deg, rgba(52,59,57,0.045) 0%, rgba(52,59,57,0.05) 28%, rgba(255,255,255,0.18) 50%, rgba(52,59,57,0.05) 72%, rgba(52,59,57,0.045) 100%)' },
60
+ { label: '旋转渐变', cssProp: 'background', value: 'conic-gradient(var(--color-brand-500) → var(--color-purple-300))' },
61
+ { label: '生成动效', cssProp: 'animation', value: 'spin 1.1s linear infinite / shimmer 3s linear infinite' },
62
+ ],
63
+ 确认卡片: [
64
+ { label: '描边色', cssProp: 'border-color', token: '--color-border-default', value: '#E4E7EC', semanticRef: 'border-default' },
65
+ { label: '背景色', cssProp: 'background', token: '--color-fill', value: 'rgba(83, 96, 143, 0.07)' },
66
+ { label: '标题字重', cssProp: 'font-weight', token: '--font-semibold', value: '600(运行时使用 [font-weight:var(--font-semibold)])', state: 'header' },
67
+ { label: '正文描边', cssProp: 'border-color', token: '--color-white', value: '#FFFFFF', state: 'body' },
68
+ { label: '正文底色', cssProp: 'background', token: '--color-card-secondary', value: 'rgba(255,255,255,0.65)', state: 'body' },
69
+ ],
70
+ 确认按钮: [
71
+ { label: '主背景', cssProp: 'background', token: '--color-neutral', value: '#343B3A', state: 'primary' },
72
+ { label: '主文字', cssProp: 'color', token: '--color-white', value: '#FFFFFF', state: 'primary' },
73
+ { label: '主字重', cssProp: 'font-weight', token: '--font-semibold', value: '600(运行时使用 [font-weight:var(--font-semibold)])', state: 'primary' },
74
+ { label: '次描边', cssProp: 'border-color', token: '--color-border-default', value: '#E4E7EC', state: 'secondary', semanticRef: 'border-default' },
75
+ { label: '次背景', cssProp: 'background', token: '--color-surface', value: '#FFFFFF', state: 'secondary' },
76
+ { label: '次文字', cssProp: 'color', token: '--color-foreground-secondary', value: '#475467', state: 'secondary' },
77
+ { label: '次字重', cssProp: 'font-weight', token: '--font-semibold', value: '600(运行时使用 [font-weight:var(--font-semibold)])', state: 'secondary' },
78
+ ],
79
+ 结果产物: [
80
+ { label: '卡片背景', cssProp: 'background', token: '--color-surface', value: '#FFFFFF' },
81
+ { label: '描边色', cssProp: 'border-color', token: '--color-border-line-light', value: 'rgba(22,24,35,0.08)' },
82
+ { label: '卡片宽度', cssProp: 'width', value: '300px / max-width: 100%' },
83
+ { label: '圆角', cssProp: 'border-radius', token: '--radius-md', value: '8px' },
84
+ { label: '内边距', cssProp: 'padding', value: '12px' },
85
+ { label: '元素间距', cssProp: 'gap', token: '--spacing-2', value: '8px' },
86
+ ],
87
+ 产物图标: [
88
+ { label: '尺寸', cssProp: 'width/height', value: '32px' },
89
+ { label: '来源', cssProp: 'component', value: 'ArtifactIcon (PNG 资源)' },
90
+ { label: '资源路径', cssProp: 'src', value: 'components/file-type-assets/*.png' },
91
+ { label: '颜色来源', cssProp: 'style', value: '图标自带配色,不建立 token' },
92
+ ],
93
+ 图标容器: [
94
+ { label: '尺寸', cssProp: 'width/height', value: '24px' },
95
+ { label: '背景渐变', cssProp: 'background-image', token: '--tfds-ai-execution-icon-gradient', value: 'linear-gradient(180deg, rgba(200,214,210,0.09) 0%, rgba(52,59,57,0.09) 100%)' },
96
+ { label: '描边色', cssProp: 'border-color', token: '--color-border-line-light', value: 'rgba(22,24,35,0.08)' },
97
+ { label: '圆角', cssProp: 'border-radius', token: '--radius-md', value: '8px' },
98
+ { label: '图标尺寸', cssProp: 'width/height', token: '--size-icon-14', value: '14px' },
99
+ ],
100
+ 连接线: [
101
+ { label: '线色', cssProp: 'background', token: '--color-border-line-light', value: 'rgba(22,24,35,0.08)' },
102
+ { label: '线宽', cssProp: 'width', value: '1px' },
103
+ { label: '轨道宽度', cssProp: 'width', token: '--spacing-4', value: '16px' },
104
+ ],
105
+ 布局: [
106
+ { label: '标题间距', cssProp: 'gap', token: '--spacing-3', value: '12px' },
107
+ { label: '最小高度', cssProp: 'min-height', value: '80px' },
108
+ { label: '内容间距', cssProp: 'gap', token: '--spacing-1', value: '4px' },
109
+ { label: '预览宽度', cssProp: 'width/max-width', value: 'fit-content / max-width: calc(100% - 48px)' },
110
+ ],
111
+ AI头像: [
112
+ { label: '头像尺寸', cssProp: 'width/height', value: '20px' },
113
+ { label: '头像来源', cssProp: 'src', value: 'catcat.svg(OLA AI 渐变猫头像)' },
114
+ { label: '名称色', cssProp: 'color', token: '--color-neutral', value: '#343B3A' },
115
+ { label: '名称字号', cssProp: 'font-size', token: '--text-sm', value: '14px' },
116
+ { label: '名称字重', cssProp: 'font-weight', token: '--font-semibold', value: '600(运行时使用 [font-weight:var(--font-semibold)])' },
117
+ { label: '名称行高', cssProp: 'line-height', token: '--leading-5', value: '20px' },
118
+ { label: '元素间距', cssProp: 'gap', token: '--spacing-2', value: '8px' },
119
+ ],
120
+ 请求中: [
121
+ { label: '圆点尺寸', cssProp: 'width/height', value: '6px' },
122
+ { label: '圆点底色', cssProp: 'background', token: '--color-neutral-500', value: '#858595' },
123
+ { label: '圆点静止透明度', cssProp: 'opacity', value: '0.3' },
124
+ { label: '圆点跳动动效', cssProp: 'animation', value: 'tfds-ai-dot-bounce 1.2s ease-in-out infinite' },
125
+ { label: '圆点错峰间隔', cssProp: 'animation-delay', value: '0 / 0.15s / 0.3s' },
126
+ { label: '圆点间距', cssProp: 'gap', value: '4px' },
127
+ ],
128
+ 深度思考: [
129
+ { label: '标题色', cssProp: 'color', token: '--color-neutral-500', value: '#858595' },
130
+ { label: '标题字号', cssProp: 'font-size', token: '--text-xs', value: '12px' },
131
+ { label: '标题行高', cssProp: 'line-height', token: '--leading-4', value: '16px' },
132
+ { label: '展开/收起图标', cssProp: 'icon', value: 'chevron-up/down-stroked / 16px' },
133
+ { label: '思考引用线', cssProp: 'background', token: '--color-border-line-light', value: 'rgba(22,24,35,0.08)' },
134
+ { label: '引用线宽', cssProp: 'width', value: '1px' },
135
+ { label: '思考文本色', cssProp: 'color', token: '--color-neutral-500', value: '#858595' },
136
+ { label: '思考文本字号', cssProp: 'font-size', token: '--text-xs', value: '12px' },
137
+ { label: '思考文本行高', cssProp: 'line-height', token: '--leading-5', value: '20px' },
138
+ { label: '展开模式', cssProp: 'state', value: 'thinking 思考中 / completed 完成' },
139
+ ],
140
+ 任务规划卡片: [
141
+ { label: '外框背景', cssProp: 'background', token: '--color-fill', value: 'rgba(83,96,143,0.07)' },
142
+ { label: '外框描边', cssProp: 'border', token: '--color-border-line-light', value: 'rgba(22,24,35,0.08) / 0.5px' },
143
+ { label: '外框圆角', cssProp: 'border-radius', token: '--radius-lg', value: '12px' },
144
+ { label: '外框内边距', cssProp: 'padding', value: '12px 16px' },
145
+ { label: '头部图标容器', cssProp: 'size', value: '32px / 渐变灰底 / 0.5px 描边 / 8px 圆角' },
146
+ { label: '任务数徽章背景', cssProp: 'background', value: 'rgba(255,255,255,0.6)' },
147
+ { label: '任务数徽章描边', cssProp: 'border', token: '--color-white', value: '#FFFFFF' },
148
+ { label: '任务数徽章字号', cssProp: 'font-size', token: '--text-xs', value: '12px' },
149
+ { label: '内容卡背景', cssProp: 'background', value: 'rgba(255,255,255,0.6)' },
150
+ { label: '内容卡描边', cssProp: 'border', token: '--color-white', value: '#FFFFFF' },
151
+ { label: '内容卡内边距', cssProp: 'padding', value: '16px 20px' },
152
+ { label: '任务编号背景', cssProp: 'background', value: 'linear-gradient violet 浅渐变' },
153
+ { label: '任务编号描边', cssProp: 'border-color', token: '--color-violet-200', value: '#BBACE8' },
154
+ { label: '任务编号文字色', cssProp: 'color', token: '--color-violet-500', value: '#6D45C5' },
155
+ { label: '任务标题字号', cssProp: 'font-size', token: '--text-sm', value: '14px' },
156
+ { label: '任务标题字重', cssProp: 'font-weight', token: '--font-semibold', value: '600(运行时使用 [font-weight:var(--font-semibold)])' },
157
+ { label: '子项圆点', cssProp: 'background', token: '--color-neutral-300', value: '#C7C8D5 / 8px' },
158
+ { label: '子项文字色', cssProp: 'color', token: '--color-neutral-700', value: '#404150' },
159
+ { label: '主操作按钮', cssProp: 'background', token: '--color-neutral', value: '#343B3A / 黑底白字 / 32px 高' },
160
+ ],
161
+ 追问按钮组: [
162
+ { label: '按钮背景', cssProp: 'background', token: '--color-surface', value: '#FFFFFF' },
163
+ { label: '按钮描边', cssProp: 'border', token: '--color-border-line-light', value: 'rgba(22,24,35,0.08)' },
164
+ { label: '按钮圆角', cssProp: 'border-radius', token: '--radius-md', value: '8px' },
165
+ { label: '按钮高度', cssProp: 'height', value: '40px' },
166
+ { label: '按钮内边距', cssProp: 'padding', value: '8px 12px' },
167
+ { label: '按钮文字色', cssProp: 'color', token: '--color-neutral', value: '#343B3A' },
168
+ { label: '按钮字号', cssProp: 'font-size', token: '--text-sm', value: '14px' },
169
+ { label: '按钮间距', cssProp: 'gap', token: '--spacing-2', value: '8px' },
170
+ { label: 'hover 背景', cssProp: 'background', token: '--color-blueGrey-50', value: '#F4F7FB' },
171
+ ],
172
+ 消息操作组: [
173
+ { label: '按钮尺寸', cssProp: 'width/height', value: '24px' },
174
+ { label: '按钮内边距', cssProp: 'padding', value: '4px' },
175
+ { label: '按钮圆角', cssProp: 'border-radius', token: '--radius-button', value: '6px' },
176
+ { label: '图标尺寸', cssProp: 'icon-size', value: '16px' },
177
+ { label: '图标色', cssProp: 'color', token: '--color-neutral-500', value: '#858595' },
178
+ { label: '复制次数色', cssProp: 'color', token: '--color-neutral-500', value: '#858595' },
179
+ { label: '时间戳色', cssProp: 'color', token: '--color-neutral-500', value: '#858595' },
180
+ { label: '时间戳字号', cssProp: 'font-size', token: '--text-xs', value: '12px' },
181
+ { label: '组内间距', cssProp: 'gap', token: '--spacing-3', value: '12px' },
182
+ { label: '图标列表', cssProp: 'icon', value: 'copy-06-stroked / message-square-01-stroked / thumbs-up-stroked / thumbs-down-stroked' },
183
+ { label: 'historyMode 占位', cssProp: 'opacity / height', value: 'opacity:0 默认 + 父消息 hover/group/chat-msg → opacity:1,height 始终保留(避免历史消息抖动)' },
184
+ { label: 'historyMode 过渡', cssProp: 'transition', value: 'opacity 150ms(与 button hover 等节奏对齐)' },
185
+ ],
186
+ 任务进行中徽章: [
187
+ { label: '背景色', cssProp: 'background', token: '--color-indigo-50', value: '#ECEFF7' },
188
+ { label: '描边色', cssProp: 'border-color', token: '--color-indigo-100', value: '#D1D6F0' },
189
+ { label: '文字色', cssProp: 'color', token: '--color-indigo-400', value: '#5D6DC2' },
190
+ { label: '图标色', cssProp: 'color', token: '--color-indigo-400', value: '#5D6DC2' },
191
+ { label: '圆角', cssProp: 'border-radius', token: '--radius-md', value: '8px' },
192
+ { label: '内边距', cssProp: 'padding', value: '4px 8px' },
193
+ { label: '图标', cssProp: 'icon', value: 'star-04-stroked / 14px' },
194
+ ],
195
+ 用户气泡: [
196
+ { label: '自动背景策略(userBubbleTone=auto)', cssProp: 'logic', value: '父级白色 / --color-surface → bg-fill 灰气泡;父级浅灰 / 蓝灰 / 非白背景 → bg-surface 白气泡' },
197
+ { label: '浅灰背景上气泡背景(userBubbleTone=surface)', cssProp: 'background', token: '--color-surface', value: '#FFFFFF', semanticRef: 'bg-surface' },
198
+ { label: '白色背景上气泡背景(userBubbleTone=fill)', cssProp: 'background', token: '--color-fill', value: 'rgba(83, 96, 143, 0.07)', semanticRef: 'fill-default' },
199
+ { label: '气泡圆角', cssProp: 'border-radius', value: '12px 0 12px 12px(右上不圆,指向用户头像)' },
200
+ { label: '气泡内边距', cssProp: 'padding', value: '12px 16px' },
201
+ { label: '气泡宽度', cssProp: 'width', value: 'w-fit + max-width:100%(按内容自适应,附件多时换行)' },
202
+ { label: '右对齐缩进', cssProp: 'padding-left', value: '8% 容器宽(500px 容器 ≈ 40px / 760px 容器 ≈ 60px)' },
203
+ { label: '正文色', cssProp: 'color', token: '--color-neutral', value: '#343B3A' },
204
+ { label: '正文字号', cssProp: 'font-size', token: '--text-sm', value: '14px' },
205
+ { label: '正文行高', cssProp: 'line-height', value: '26px' },
206
+ { label: '富文本间距', cssProp: 'gap', value: 'x:8px / y:4px' },
207
+ { label: '附件行间距', cssProp: 'gap', token: '--spacing-2', value: '8px(附件 wrap 多列时行/列同步 8px)' },
208
+ ],
209
+ 用户附件卡: [
210
+ { label: '卡片宽', cssProp: 'width', value: '180px(与 ChatInput 已选附件卡同规格,从输入到发送视觉零跳变)' },
211
+ { label: '卡片背景', cssProp: 'background', token: '--color-fill', value: 'rgba(2, 33, 17, 0.04)' },
212
+ { label: '卡片描边', cssProp: 'border-color', token: '--color-border-default', value: '#E4E7EC', semanticRef: 'border-default' },
213
+ { label: '卡片圆角', cssProp: 'border-radius', token: '--radius-lg', value: '8px' },
214
+ { label: '卡片内边距', cssProp: 'padding', value: '8px' },
215
+ { label: '卡片左右间距', cssProp: 'gap', token: '--spacing-2', value: '8px' },
216
+ { label: '文件图标盒', cssProp: 'width/height', value: '32×34px' },
217
+ { label: '文件图标', cssProp: 'src', value: 'pdf.svg 兜底(按后缀映射,与 ChatInput 共用 FILE_TYPE_ICONS 字典)' },
218
+ { label: '文件名色', cssProp: 'color', token: '--color-foreground', value: '#182230' },
219
+ { label: '文件名字号', cssProp: 'font-size', token: '--text-xs', value: '12px / 16px' },
220
+ { label: '文件名截断', cssProp: 'text-overflow', value: 'truncate(鼠标 hover title 看全名)' },
221
+ { label: '文件大小色', cssProp: 'color', token: '--color-neutral-500', value: '#858595' },
222
+ { label: '文件大小字号', cssProp: 'font-size', value: '10px / 12px' },
223
+ ],
224
+ 用户引用条: [
225
+ { label: '标题色', cssProp: 'color', token: '--color-foreground', value: '#182230', semanticRef: 'text-primary' },
226
+ { label: '标题字号', cssProp: 'font-size', token: '--text-xs', value: '12px' },
227
+ { label: '标题字重', cssProp: 'font-weight', token: '--font-semibold', value: '600(运行时使用 [font-weight:var(--font-semibold)])' },
228
+ { label: '标题行高', cssProp: 'line-height', token: '--leading-4', value: '16px' },
229
+ { label: '描述色', cssProp: 'color', token: '--color-foreground-muted', value: '#667085', semanticRef: 'text-tertiary' },
230
+ { label: '描述字号', cssProp: 'font-size', token: '--text-xs', value: '12px' },
231
+ { label: '描述行高', cssProp: 'line-height', token: '--leading-4', value: '16px' },
232
+ ],
233
+ 实体TAG: [
234
+ { label: 'teal 背景', cssProp: 'background', token: '--color-brand-50', value: '#EAFAF6', state: 'teal' },
235
+ { label: 'teal 描边', cssProp: 'border-color', token: '--color-brand-100', value: '#CFF3EA', state: 'teal' },
236
+ { label: 'teal 图标色', cssProp: 'color', token: '--color-brand-700', value: '#18B49D', state: 'teal' },
237
+ { label: 'indigo 背景', cssProp: 'background', token: '--color-indigo-50', value: '#ECEFF7', state: 'indigo' },
238
+ { label: 'indigo 描边', cssProp: 'border-color', token: '--color-indigo-100', value: '#D1D6F0', state: 'indigo' },
239
+ { label: 'indigo 文字色', cssProp: 'color', token: '--color-indigo-400', value: '#5D6DC2', state: 'indigo' },
240
+ { label: 'violet 背景', cssProp: 'background', token: '--color-violet-50', value: '#F1EEF9', state: 'violet' },
241
+ { label: 'violet 描边', cssProp: 'border-color', token: '--color-violet-100', value: '#DCD4F3', state: 'violet' },
242
+ { label: 'violet 文字色', cssProp: 'color', token: '--color-violet-500', value: '#6D45C5', state: 'violet' },
243
+ { label: '圆角', cssProp: 'border-radius', token: '--radius-md', value: '8px' },
244
+ { label: '高度', cssProp: 'height', value: '26px' },
245
+ { label: '内边距', cssProp: 'padding', value: '4px 8px' },
246
+ { label: '元素间距', cssProp: 'gap', token: '--spacing-2', value: '8px' },
247
+ ],
248
+ 引用组件: [
249
+ { label: '状态图标', cssProp: '—', value: 'Icon sm' },
250
+ { label: '步骤图标', cssProp: '—', value: 'Icon 14px' },
251
+ { label: '产物图标', cssProp: '—', value: 'Icon 32px / 产物图标分类' },
252
+ { label: 'AI 头像', cssProp: '—', value: 'img 20px / catcat.svg' },
253
+ { label: '消息操作图标', cssProp: '—', value: 'Icon 16px / 复制 引用 赞 踩' },
254
+ { label: '实体 TAG 图标', cssProp: '—', value: 'Icon 14px / message-chat-square 等' },
255
+ { label: '用户附件卡图标', cssProp: '—', value: 'img 32×34 / pdf.svg(与 ChatInput 共用资源)' },
256
+ ],
257
+ };
@@ -0,0 +1,388 @@
1
+ import { useState } from 'react';
2
+ import ChatMessage, {
3
+ ALL_ARTIFACT_TYPES,
4
+ ArtifactIcon,
5
+ DEFAULT_CHAT_ACTIONS,
6
+ DEFAULT_CHAT_ARTIFACT_GROUP,
7
+ DEFAULT_CHAT_CONFIRMS,
8
+ DEFAULT_CHAT_FOLLOW_UPS,
9
+ DEFAULT_CHAT_PLAN,
10
+ DEFAULT_CHAT_RESULT,
11
+ DEFAULT_CHAT_RESULT_ARTIFACTS,
12
+ DEFAULT_CHAT_STEPS,
13
+ DEFAULT_CHAT_TASK_GROUPS,
14
+ DEFAULT_CHAT_THINKING,
15
+ DEFAULT_CHAT_TITLE,
16
+ DEFAULT_CHAT_USER_ATTACHMENTS,
17
+ DEFAULT_CHAT_USER_CONTENT,
18
+ DEFAULT_CHAT_USER_QUOTE,
19
+ ResultArtifactCard,
20
+ ResultArtifactGroup,
21
+ useStreamingTaskGroups,
22
+ } from './ChatMessage';
23
+
24
+ /* 模拟 500px 消息容器,让 8% 缩进对齐 40px */
25
+ const MESSAGE_CONTAINER_STYLE = { width: '500px', maxWidth: '100%' };
26
+
27
+ /* 操作栏默认常显 props */
28
+ const ACTIONS = { ...DEFAULT_CHAT_ACTIONS, historyMode: false };
29
+
30
+ const TOOLTIP_TEST_TASK_GROUPS = DEFAULT_CHAT_TASK_GROUPS.map((group, groupIndex) => ({
31
+ ...group,
32
+ steps: group.steps.map((step, stepIndex) => ({
33
+ ...step,
34
+ actionDetail: stepIndex === 0
35
+ ? `${step.actionDetail} / long_path/business_service/customer_support/policy_center/version_${groupIndex + 1}_pending_review_records`
36
+ : step.actionDetail,
37
+ })),
38
+ }));
39
+
40
+ /**
41
+ * 根据 subComponent + variant 返回 ChatMessage props
42
+ */
43
+ function getProps(subComponent, variant, options = {}) {
44
+ const userBubbleTone = options.userBubbleTone || 'auto';
45
+ switch (subComponent) {
46
+
47
+ /* ── 执行流(多任务组:每组可独立折叠;processing 组的最后一步显示扫光) ── */
48
+ case 'execution-flow': {
49
+ if (variant === 'running') {
50
+ return {
51
+ role: 'ai',
52
+ taskGroups: TOOLTIP_TEST_TASK_GROUPS,
53
+ };
54
+ }
55
+ return {
56
+ role: 'ai',
57
+ taskGroups: TOOLTIP_TEST_TASK_GROUPS.map((g) => ({ ...g, status: 'completed' })),
58
+ };
59
+ }
60
+
61
+ /* ── 文本回复(仅结果文本) ── */
62
+ case 'text-reply':
63
+ return {
64
+ role: 'ai', title: '', steps: null,
65
+ resultText: '收到,我先去拉平台规则和商家补充条款,分析完会给你一份统一答复口径。',
66
+ };
67
+
68
+ /* ── 深度思考(仅思考块) ── */
69
+ case 'deep-thinking':
70
+ if (variant === 'thinking') {
71
+ return {
72
+ role: 'ai', status: 'thinking', steps: null,
73
+ thinking: { state: 'thinking', inProgressLabel: '深度思考中 ...' },
74
+ };
75
+ }
76
+ return {
77
+ role: 'ai', title: '', steps: null,
78
+ thinking: {
79
+ ...DEFAULT_CHAT_THINKING,
80
+ state: 'completed',
81
+ defaultExpanded: variant !== 'collapsed',
82
+ },
83
+ };
84
+
85
+ /* ── 卡片(同一组件,含任务规划 / 配置表单两个变体) ── */
86
+ case 'card':
87
+ if (variant === 'config-form') {
88
+ return {
89
+ role: 'ai', title: '', steps: null,
90
+ /* 预览只展示卡片本体,去掉默认数据里的前导引导文本 introText */
91
+ confirms: DEFAULT_CHAT_CONFIRMS.map(({ introText, ...rest }) => rest),
92
+ };
93
+ }
94
+ return {
95
+ role: 'ai', title: '', steps: null,
96
+ plan: DEFAULT_CHAT_PLAN,
97
+ };
98
+
99
+ /* ── 用户消息(仅气泡,无操作栏) ── */
100
+ case 'user-message':
101
+ if (variant === 'mixed-tag') {
102
+ return {
103
+ role: 'user',
104
+ userBubbleTone,
105
+ userContent: DEFAULT_CHAT_USER_CONTENT,
106
+ };
107
+ }
108
+ if (variant === 'with-attachment') {
109
+ /* 附件不含在气泡内:附件 → 气泡 两个独立行右对齐 */
110
+ return {
111
+ role: 'user',
112
+ userBubbleTone,
113
+ userContent: [{ type: 'text', value: '附件里是售后规则汇编,请基于这两份文件输出统一答复口径' }],
114
+ userAttachments: DEFAULT_CHAT_USER_ATTACHMENTS,
115
+ };
116
+ }
117
+ if (variant === 'with-quote') {
118
+ /* 紫色划词条 / 引用:在气泡上方独立显示 */
119
+ return {
120
+ role: 'user',
121
+ userBubbleTone,
122
+ userContent: [{ type: 'text', value: '请帮我复盘这次服务的完整链路,并着重分析[用户评价未解决]的原因。生成飞书文档和一份完整的前端页面' }],
123
+ userQuote: DEFAULT_CHAT_USER_QUOTE,
124
+ };
125
+ }
126
+ return {
127
+ role: 'user',
128
+ userBubbleTone,
129
+ userContent: [{ type: 'text', value: '帮我整理一下抖音电商的售后政策,重点是退货退款、换货和拒收的判责口径' }],
130
+ };
131
+
132
+ /* ── AI 头像+名称(仅头像行) ── */
133
+ case 'ai-avatar':
134
+ if (variant === 'loading') {
135
+ return { role: 'ai', header: true, status: 'requesting', steps: null };
136
+ }
137
+ return { role: 'ai', header: true, title: '', steps: null };
138
+
139
+ /* ── 对话流(多 ChatMessage 拼接,专用 __renderMode 走下方多消息分支) ──
140
+ * ai-rich · AI 头像 + 文本 + 产物 + 控制条 + 追问(单条)
141
+ * multi-turn · 2 轮 [人 → AI] 文本对话;仅最新一条常显操作栏,其余 historyMode
142
+ * ai-task-plan· AI 头像 + 文本 + 任务规划卡片(单条)
143
+ */
144
+ case 'conversation': {
145
+ const HISTORY_ACTIONS = { ...DEFAULT_CHAT_ACTIONS, historyMode: true };
146
+
147
+ if (variant === 'multi-turn') {
148
+ return {
149
+ __renderMode: 'conversation',
150
+ messages: [
151
+ {
152
+ role: 'user',
153
+ userBubbleTone,
154
+ userContent: [{ type: 'text', value: '帮我整理一下抖音电商的售后政策,重点是退货退款、换货和拒收的判责口径' }],
155
+ actions: HISTORY_ACTIONS,
156
+ timestamp: '14:02',
157
+ },
158
+ {
159
+ role: 'ai', header: true, title: '', steps: null,
160
+ resultText: '收到,我先去拉平台规则和商家补充条款,分析完会给你一份统一答复口径。',
161
+ actions: HISTORY_ACTIONS,
162
+ timestamp: '14:02',
163
+ },
164
+ {
165
+ role: 'user',
166
+ userBubbleTone,
167
+ userContent: [{ type: 'text', value: '再补充一句:拒收场景也要分商家原因和用户原因,分别给到处理路径' }],
168
+ actions: HISTORY_ACTIONS,
169
+ timestamp: '14:05',
170
+ },
171
+ {
172
+ role: 'ai', header: true, title: '', steps: null,
173
+ resultText: '好的,我会把拒收的两类责任划分单独开一节,并补上对应的客服话术模板。',
174
+ actions: ACTIONS,
175
+ timestamp: '14:05',
176
+ },
177
+ ],
178
+ };
179
+ }
180
+
181
+ if (variant === 'ai-task-plan') {
182
+ /* 走独立的有状态预览:点击"开始执行任务"会追加用户消息 + AI 执行流加载 */
183
+ return { __renderMode: 'conversation-task-plan-interactive' };
184
+ }
185
+
186
+ /* 默认 ai-rich:AI 头像 + 文本 + 产物 + 控制条 + 追问 */
187
+ return {
188
+ __renderMode: 'conversation',
189
+ messages: [
190
+ {
191
+ role: 'ai', header: true, title: '', steps: null,
192
+ resultText: DEFAULT_CHAT_RESULT,
193
+ resultArtifacts: DEFAULT_CHAT_RESULT_ARTIFACTS,
194
+ actions: ACTIONS,
195
+ followUps: DEFAULT_CHAT_FOLLOW_UPS,
196
+ timestamp: '18:16',
197
+ },
198
+ ],
199
+ };
200
+ }
201
+
202
+ /* ── 产物(拆 3 层:图标 atom / 单卡 molecule / 产物组 organism) ──
203
+ * 这里先返回标记,由下方 PreviewSwitch 走专用渲染分支(脱离 ChatMessage 容器)
204
+ */
205
+ case 'artifact':
206
+ if (variant === 'icon') {
207
+ return { __renderMode: 'artifact-icon-grid' };
208
+ }
209
+ if (variant === 'card') {
210
+ return { __renderMode: 'artifact-single-card' };
211
+ }
212
+ return { __renderMode: 'artifact-group' };
213
+
214
+ /* ── 操作栏(仅操作栏行) ── */
215
+ case 'action-bar':
216
+ return {
217
+ role: 'ai', title: '', steps: null,
218
+ actions: ACTIONS,
219
+ timestamp: '18:16',
220
+ };
221
+
222
+ /* ── 追问(仅追问按钮组) ── */
223
+ case 'follow-up':
224
+ return {
225
+ role: 'ai', title: '', steps: null,
226
+ followUps: DEFAULT_CHAT_FOLLOW_UPS,
227
+ };
228
+
229
+ default:
230
+ return {
231
+ role: 'ai', header: true,
232
+ title: DEFAULT_CHAT_TITLE,
233
+ steps: DEFAULT_CHAT_STEPS,
234
+ };
235
+ }
236
+ }
237
+
238
+ export default function ChatMessagePreview({
239
+ subComponent = 'execution-flow',
240
+ variant = 'completed',
241
+ userBubbleTone = 'auto',
242
+ }) {
243
+ const props = getProps(subComponent, variant, { userBubbleTone });
244
+ const reactKey = `${subComponent}:${variant}:${userBubbleTone}`;
245
+
246
+ /* ── 产物 atom 预览:图标网格(5 列 × 3 行 = 15 个 PNG 图标) ── */
247
+ if (props.__renderMode === 'artifact-icon-grid') {
248
+ return (
249
+ <div className="flex h-full w-full min-w-0 items-start justify-center overflow-y-auto p-4">
250
+ <div className="grid w-full max-w-[500px] grid-cols-5 gap-3" style={MESSAGE_CONTAINER_STYLE}>
251
+ {ALL_ARTIFACT_TYPES.map((a) => (
252
+ <div
253
+ key={a.id}
254
+ className="flex flex-col items-center gap-1 rounded-md border border-border-line-light p-2"
255
+ title={a.type}
256
+ >
257
+ <ArtifactIcon type={a.type} size={32} />
258
+ <span className="truncate text-[10px] leading-3 text-foreground-muted">{a.type}</span>
259
+ </div>
260
+ ))}
261
+ </div>
262
+ </div>
263
+ );
264
+ }
265
+
266
+ /* ── 产物 molecule 预览:单张卡片(默认取第一类 PDF) ── */
267
+ if (props.__renderMode === 'artifact-single-card') {
268
+ return (
269
+ <div className="flex h-full w-full min-w-0 items-start justify-center overflow-y-auto p-4">
270
+ <div className="flex w-full max-w-[500px] flex-col" style={MESSAGE_CONTAINER_STYLE}>
271
+ <ResultArtifactCard artifact={ALL_ARTIFACT_TYPES[0]} />
272
+ </div>
273
+ </div>
274
+ );
275
+ }
276
+
277
+ /* ── 产物 organism 预览:产物组(枚举所有 15 种类型) ── */
278
+ if (props.__renderMode === 'artifact-group') {
279
+ return (
280
+ <div className="flex h-full w-full min-w-0 items-start justify-center overflow-y-auto p-4">
281
+ <div className="flex w-full max-w-[500px] flex-col" style={MESSAGE_CONTAINER_STYLE}>
282
+ <ResultArtifactGroup artifacts={DEFAULT_CHAT_ARTIFACT_GROUP} />
283
+ </div>
284
+ </div>
285
+ );
286
+ }
287
+
288
+ /* ── 对话流预览:把 messages 数组按顺序渲染成多 ChatMessage,消息间留 16px 间距
289
+ * 每条 ChatMessage 自己是一个 group/chat-msg,hover 隔离不会跨条;
290
+ * 历史消息 historyMode=true 默认隐藏操作栏,hover 当条才显示
291
+ */
292
+ if (props.__renderMode === 'conversation') {
293
+ return (
294
+ <div className="flex h-full w-full min-w-0 items-start justify-center overflow-y-auto p-3">
295
+ <div className="flex w-full max-w-[500px] flex-col gap-4" style={MESSAGE_CONTAINER_STYLE}>
296
+ {props.messages.map((msg, idx) => (
297
+ <ChatMessage key={`${reactKey}-${idx}`} {...msg} />
298
+ ))}
299
+ </div>
300
+ </div>
301
+ );
302
+ }
303
+
304
+ /* ── 对话流·任务规划交互预览:点击"开始执行任务"追加 用户消息 + AI 执行流加载中 ── */
305
+ if (props.__renderMode === 'conversation-task-plan-interactive') {
306
+ return <TaskPlanInteractivePreview key={reactKey} userBubbleTone={userBubbleTone} />;
307
+ }
308
+
309
+ /* requesting / thinking 状态无时间戳 */
310
+ if (props.status === 'requesting' || props.status === 'thinking') {
311
+ props.timestamp = '';
312
+ }
313
+
314
+ return (
315
+ <div className="flex h-full w-full min-w-0 items-start justify-center overflow-y-auto p-3">
316
+ <div className="flex w-full max-w-[500px] flex-col" style={MESSAGE_CONTAINER_STYLE}>
317
+ <ChatMessage key={reactKey} {...props} />
318
+ </div>
319
+ </div>
320
+ );
321
+ }
322
+
323
+ /**
324
+ * TaskPlanInteractivePreview — AI 任务规划变体的有状态对话流预览
325
+ *
326
+ * 初始:1 条 AI 消息(头像 + 引导文本"我开始规划啦,请稍后..." + 任务规划卡片)
327
+ * 点击"开始执行任务"后追加:
328
+ * 1. 用户消息 "开始执行任务"
329
+ * 2. AI 消息(头像 + 执行流加载中:第 1 组完成、第 2 组进行中)
330
+ */
331
+ function TaskPlanInteractivePreview({ userBubbleTone = 'auto' }) {
332
+ const HISTORY_ACTIONS = { ...DEFAULT_CHAT_ACTIONS, historyMode: true };
333
+ const ACTIONS_LOCAL = { ...DEFAULT_CHAT_ACTIONS, historyMode: false };
334
+ const [started, setStarted] = useState(false);
335
+
336
+ const taskPlanMessage = {
337
+ role: 'ai',
338
+ header: true,
339
+ title: '',
340
+ steps: null,
341
+ leadText: '我开始规划啦,请稍后...',
342
+ plan: {
343
+ ...DEFAULT_CHAT_PLAN,
344
+ onPrimaryAction: () => setStarted(true),
345
+ },
346
+ /* 处理后该消息会变成历史消息 → historyMode;未处理时操作栏自动隐藏 */
347
+ actions: started ? HISTORY_ACTIONS : ACTIONS_LOCAL,
348
+ timestamp: '18:16',
349
+ };
350
+
351
+ return (
352
+ <div className="flex h-full w-full min-w-0 items-start justify-center overflow-y-auto p-3">
353
+ <div className="flex w-full max-w-[500px] flex-col gap-4" style={MESSAGE_CONTAINER_STYLE}>
354
+ <ChatMessage {...taskPlanMessage} />
355
+ {started ? (
356
+ <>
357
+ <ChatMessage
358
+ role="user"
359
+ userBubbleTone={userBubbleTone}
360
+ userContent={[{ type: 'text', value: '开始执行任务' }]}
361
+ actions={HISTORY_ACTIONS}
362
+ timestamp="18:16"
363
+ />
364
+ {/* 流式执行流:每 600ms 推一个 step,组完成后切下一组 */}
365
+ <StreamingChatMessage taskGroups={DEFAULT_CHAT_TASK_GROUPS} />
366
+ </>
367
+ ) : null}
368
+ </div>
369
+ </div>
370
+ );
371
+ }
372
+
373
+ /**
374
+ * StreamingChatMessage — 把执行流的 taskGroups 接到 useStreamingTaskGroups
375
+ * 使其挂载即开始按 600ms 节奏一条一条刷出;AI 正在执行,最新一条不显示操作栏
376
+ */
377
+ function StreamingChatMessage({ taskGroups }) {
378
+ const streamed = useStreamingTaskGroups(taskGroups, { intervalMs: 600 });
379
+ return (
380
+ <ChatMessage
381
+ role="ai"
382
+ header
383
+ title=""
384
+ steps={null}
385
+ taskGroups={streamed}
386
+ />
387
+ );
388
+ }