@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,237 @@
1
+ import { useMemo, useState } from 'react';
2
+ import Button from '../components/Button';
3
+ import Icon from '../components/Icon';
4
+ import Sheet from '../components/Sheet';
5
+ import Table from '../components/Table';
6
+ import TagBar from '../components/TagBar';
7
+ import {
8
+ FilterBar,
9
+ LIST_COLUMNS,
10
+ PAGE_CONTEXT_LABEL,
11
+ PageHeader,
12
+ WHITE_CARD_STYLE,
13
+ buildListDataSource,
14
+ } from './pageListShared';
15
+
16
+ /**
17
+ * McpManagementPage — B 端"MCP 工具管理"列表页模板(双白卡 + TagBar 版)
18
+ *
19
+ * 模板结构(横向两个白卡):
20
+ * · 左侧白卡:可拖拽调宽的辅助大卡,内部承载 TagBar 标签树(业务切换 + 多级标签)
21
+ * · 右侧白卡:主工作区白卡,承载标题栏 + 筛选栏 + 表格,并弹性占满剩余空间
22
+ * · 选中标签节点 → 右侧列表自动按 tagIds 过滤
23
+ *
24
+ * 规则语义:
25
+ * · 该页是“横向大卡工作区默认支持宽度拖拽”的标准示例
26
+ * · 主卡始终 `flex-1 min-w-0`,左侧辅助卡通过 `width + onWidthChange + minWidth + maxWidth`
27
+ * 在边界内自由调宽
28
+ * · 左卡外层保持 `overflow-visible`,确保拖拽把手不会被裁切
29
+ *
30
+ * 业务接入:
31
+ * · MCP_TAG_TREE 替换为业务真实分类树
32
+ * · MCP_DATA 每条增加 tagIds 关联
33
+ * · 其他文案(标题/筛选项/创建按钮)按业务调整
34
+ */
35
+
36
+ const PAGE_TITLE = 'MCP 工具管理';
37
+ const MCP_FILTERS = ['MCP 类型', '创建人', '状态'];
38
+ const MCP_TAGBAR_WIDTH_LIMITS = {
39
+ initial: 260,
40
+ min: 200,
41
+ max: 360,
42
+ };
43
+
44
+ /* ── 左侧 TagBar:业务切换 ── */
45
+ const MCP_BUSINESSES = [
46
+ { id: 'douyin-local-services', label: '抖音生活服务', iconSrc: 'icon-logo-douyin' },
47
+ { id: 'douyin-community', label: '抖音社区', iconSrc: 'icon-logo-douyin' },
48
+ { id: 'douyin-ecommerce', label: '抖音电商', iconSrc: 'icon-logo-douyin' },
49
+ ];
50
+
51
+ /* ── 左侧 TagBar:标签树(决定 MCP 列表的筛选维度) ── */
52
+ const MCP_TAG_TREE = [
53
+ {
54
+ id: 'data',
55
+ label: '数据中台',
56
+ iconName: 'database-01-stroked',
57
+ iconBgToken: 'blue-50',
58
+ children: [
59
+ { id: 'data-poi', label: 'POI 数据' },
60
+ { id: 'data-user', label: '用户数据' },
61
+ { id: 'data-order', label: '订单数据' },
62
+ ],
63
+ },
64
+ {
65
+ id: 'marketing',
66
+ label: '营销中台',
67
+ iconName: 'gift-01-stroked',
68
+ iconBgToken: 'orange-50',
69
+ children: [
70
+ { id: 'marketing-coupon', label: '券与活动' },
71
+ { id: 'marketing-content', label: '内容审核' },
72
+ ],
73
+ },
74
+ {
75
+ id: 'algo',
76
+ label: '算法服务',
77
+ iconName: 'cpu-chip-01-stroked',
78
+ iconBgToken: 'purple-50',
79
+ children: [
80
+ { id: 'algo-recommend', label: '推荐召回' },
81
+ { id: 'algo-rank', label: '排序与策略' },
82
+ ],
83
+ },
84
+ ];
85
+
86
+ const MCP_DEFAULT_TAG_ID = 'data';
87
+ const MCP_DEFAULT_EXPANDED_IDS = ['data', 'marketing', 'algo'];
88
+
89
+ const MCP_DATA = [
90
+ { name: 'POI 数据 MCP', tag: '数据接入', desc: '统一调用 POI 基础信息、坐标、营业时间等字段。', tagIds: ['data', 'data-poi'] },
91
+ { name: '门店地理 MCP', tag: '数据接入', desc: '门店所在城市、商圈、行政区编码的批量查询能力。', tagIds: ['data', 'data-poi'] },
92
+ { name: '用户画像 MCP', tag: '画像服务', desc: '封装画像中台的标签查询、人群圈选能力。', tagIds: ['data', 'data-user'] },
93
+ { name: '用户行为 MCP', tag: '行为分析', desc: '近 30 天浏览、点击、下单等行为聚合查询。', tagIds: ['data', 'data-user'] },
94
+ { name: '订单查询 MCP', tag: '订单服务', desc: '聚合主站、本地推、抖音生服等多端订单数据。', tagIds: ['data', 'data-order'] },
95
+ { name: '履约状态 MCP', tag: '订单服务', desc: '物流节点、配送进度与异常订单的实时识别。', tagIds: ['data', 'data-order'] },
96
+ { name: '营销中台 MCP', tag: '营销服务', desc: '券、活动、补贴等核心营销动作的统一入口。', tagIds: ['marketing', 'marketing-coupon'] },
97
+ { name: '优惠券核销 MCP', tag: '营销服务', desc: '券码核销、回写与异常订单的自动回收处理。', tagIds: ['marketing', 'marketing-coupon'] },
98
+ { name: '内容审核 MCP', tag: '内容安全', desc: '文本 / 图片 / 视频审核能力,支持送审与复审。', tagIds: ['marketing', 'marketing-content'] },
99
+ { name: '素材审核 MCP', tag: '内容安全', desc: '达人投稿物料的风险识别与一键复检流程。', tagIds: ['marketing', 'marketing-content'] },
100
+ { name: '推荐引擎 MCP', tag: '推荐服务', desc: '在线召回、排序与多场景策略调用接口。', tagIds: ['algo', 'algo-recommend'] },
101
+ { name: '召回服务 MCP', tag: '推荐服务', desc: '兴趣 / 协同 / 热度多路召回的统一封装。', tagIds: ['algo', 'algo-recommend'] },
102
+ { name: '排序策略 MCP', tag: '策略服务', desc: '提供多目标排序、人群定向与冷启动策略。', tagIds: ['algo', 'algo-rank'] },
103
+ { name: 'AB 实验 MCP', tag: '策略服务', desc: '实验创建、分流、效果指标的统一查询入口。', tagIds: ['algo', 'algo-rank'] },
104
+ ];
105
+
106
+ /* MCP_TAG_TREE 中所有合法 tag id 的扁平集合,用于过滤判定(业务 id 不参与筛选) */
107
+ const MCP_TAG_ID_SET = (function collectIds(items) {
108
+ const bucket = new Set();
109
+ function walk(list) {
110
+ list.forEach((item) => {
111
+ bucket.add(item.id);
112
+ if (Array.isArray(item.children)) walk(item.children);
113
+ });
114
+ }
115
+ walk(items);
116
+ return bucket;
117
+ })(MCP_TAG_TREE);
118
+
119
+ function filterMcpByTag(list, selectedTagId) {
120
+ if (!selectedTagId || !MCP_TAG_ID_SET.has(selectedTagId)) return list;
121
+ return list.filter((item) => Array.isArray(item.tagIds) && item.tagIds.includes(selectedTagId));
122
+ }
123
+
124
+ export default function McpManagementPage() {
125
+ const [selectedTagId, setSelectedTagId] = useState(MCP_DEFAULT_TAG_ID);
126
+ const [sheetOpen, setSheetOpen] = useState(false);
127
+ const [tagBarWidth, setTagBarWidth] = useState(MCP_TAGBAR_WIDTH_LIMITS.initial);
128
+
129
+ const dataSource = useMemo(
130
+ () => buildListDataSource('mcp', filterMcpByTag(MCP_DATA, selectedTagId)),
131
+ [selectedTagId],
132
+ );
133
+
134
+ return (
135
+ <div
136
+ className="flex flex-1 min-h-0 min-w-0 relative"
137
+ style={{ margin: '16px', gap: '8px' }}
138
+ >
139
+ {/* 新建 MCP Sheet 侧边抽屉 */}
140
+ {sheetOpen && (
141
+ <div
142
+ className="absolute inset-0 z-50 flex justify-end"
143
+ style={{ background: 'rgba(0,0,0,0.4)', borderRadius: '12px' }}
144
+ onClick={() => setSheetOpen(false)}
145
+ >
146
+ <div
147
+ style={{ height: '100%' }}
148
+ onClick={(e) => e.stopPropagation()}
149
+ >
150
+ <Sheet
151
+ size="md"
152
+ title="新建 MCP"
153
+ subtitle="配置一个新的 MCP 工具接入"
154
+ confirmText="创建"
155
+ cancelText="取消"
156
+ onClose={() => setSheetOpen(false)}
157
+ onCancel={() => setSheetOpen(false)}
158
+ onConfirm={() => setSheetOpen(false)}
159
+ >
160
+ <div className="flex flex-1 min-h-0" />
161
+ </Sheet>
162
+ </div>
163
+ </div>
164
+ )}
165
+ {/* 左侧辅助大卡:默认支持拖拽调宽,与布局规则中的双白卡标准示例保持一致 */}
166
+ <div
167
+ className="flex shrink-0 overflow-visible"
168
+ style={{
169
+ ...WHITE_CARD_STYLE,
170
+ width: `${tagBarWidth}px`,
171
+ }}
172
+ >
173
+ <TagBar
174
+ businesses={MCP_BUSINESSES}
175
+ defaultBusinessId="douyin-local-services"
176
+ items={MCP_TAG_TREE}
177
+ selectedItemId={selectedTagId}
178
+ onSelect={(id) => setSelectedTagId(id)}
179
+ defaultExpandedIds={MCP_DEFAULT_EXPANDED_IDS}
180
+ width={tagBarWidth}
181
+ onWidthChange={setTagBarWidth}
182
+ minWidth={MCP_TAGBAR_WIDTH_LIMITS.min}
183
+ maxWidth={MCP_TAGBAR_WIDTH_LIMITS.max}
184
+ resizable
185
+ collapsible={false}
186
+ /* 作为独立辅助大卡展示:白卡外层负责容器层级,TagBar 内部不再额外画右分割线 */
187
+ className="!border-r-0"
188
+ style={{ background: 'transparent' }}
189
+ />
190
+ </div>
191
+
192
+ {/* 右侧主白卡:保持弹性撑满剩余空间,不参与固定宽计算 */}
193
+ <div
194
+ className="flex flex-1 min-h-0 min-w-0 flex-col overflow-hidden"
195
+ style={{
196
+ ...WHITE_CARD_STYLE,
197
+ }}
198
+ >
199
+ <div
200
+ className="flex flex-1 min-h-0 min-w-0 flex-col"
201
+ style={{ padding: '24px', gap: '16px' }}
202
+ >
203
+ <PageHeader
204
+ title={PAGE_TITLE}
205
+ contextLabel={PAGE_CONTEXT_LABEL}
206
+ actions={
207
+ <Button
208
+ variant="primary"
209
+ icon={<Icon name="plus-stroked" />}
210
+ onClick={() => setSheetOpen(true)}
211
+ >
212
+ 新建MCP
213
+ </Button>
214
+ }
215
+ />
216
+
217
+ <FilterBar filters={MCP_FILTERS} />
218
+
219
+ <div className="flex flex-1 min-h-0">
220
+ <Table
221
+ className="h-full"
222
+ columns={LIST_COLUMNS}
223
+ dataSource={dataSource}
224
+ fixedColumnsMode="last"
225
+ pagination={{
226
+ current: 1,
227
+ pageSize: 10,
228
+ total: dataSource.length,
229
+ pageSizeOptions: [10, 20],
230
+ }}
231
+ />
232
+ </div>
233
+ </div>
234
+ </div>
235
+ </div>
236
+ );
237
+ }
@@ -0,0 +1,189 @@
1
+ import { useState } from 'react';
2
+ import Modal from '../components/Modal';
3
+ import Button from '../components/Button';
4
+ import Icon from '../components/Icon';
5
+ import Input from '../components/Input';
6
+ import Table from '../components/Table';
7
+ import { PAGE_CONTEXT_LABEL, PageHeader, WHITE_CARD_STYLE } from './pageListShared';
8
+
9
+ /**
10
+ * StrategyListPage — 策略管理列表页(页面示例0)
11
+ *
12
+ * 对应 Figma:OLA3.0 / node 14729:119273
13
+ * 结构:顶部筛选栏 + Table 卡片型表单(父行 + 版本子行) + 底部分页
14
+ */
15
+
16
+ const MOCK_STRATEGIES = [
17
+ {
18
+ id: 'experience-1',
19
+ title: '抖音体验与服务-账号绑定进线流程',
20
+ status: '线上生效',
21
+ subtitle: '用户进线后的路由编排',
22
+ quoteCount: '99+',
23
+ channels: '智能客服、人工坐席',
24
+ description: '面向账号绑定咨询的体验服务流程,负责识别意图、补充信息和转接路径。',
25
+ category: '账号服务',
26
+ updatedAt: '2026-04-21 10:30',
27
+ versions: [
28
+ { v: 4, title: '优化身份校验引导', status: '草稿中', completion: '96%', execCount: 128, satisfaction: '94%', humanRate: '8%' },
29
+ { v: 3, title: '新增绑定失败兜底', status: '实验中', completion: '93%', execCount: 276, satisfaction: '91%', humanRate: '11%' },
30
+ { v: 2, title: '更新账号申诉链路', status: '已发布', completion: '98%', execCount: 512, satisfaction: '95%', humanRate: '7%' },
31
+ ],
32
+ },
33
+ {
34
+ id: 'experience-2',
35
+ title: '抖音体验与服务-创作者权益申诉',
36
+ status: '实验中',
37
+ subtitle: '权益问题自动分流处理',
38
+ quoteCount: '0',
39
+ channels: '在线客服、服务工单',
40
+ description: '用于创作者权益申诉的服务分流,覆盖权益识别、证据补充和工单跟进。',
41
+ category: '权益申诉',
42
+ updatedAt: '2026-04-20 18:45',
43
+ versions: [
44
+ { v: 2, title: '补充权益类型识别', status: '草稿中', completion: '88%', execCount: 74, satisfaction: '89%', humanRate: '15%' },
45
+ { v: 1, title: '上线申诉工单模板', status: '已发布', completion: '92%', execCount: 188, satisfaction: '90%', humanRate: '13%' },
46
+ ],
47
+ },
48
+ {
49
+ id: 'experience-3',
50
+ title: '抖音体验与服务-违规处罚解释',
51
+ status: '暂未生效',
52
+ subtitle: '处罚原因说明与安抚',
53
+ quoteCount: '0',
54
+ channels: '智能客服、人工坐席',
55
+ description: '面向账号处罚咨询,提供处罚原因解释、规则说明和申诉入口引导。',
56
+ category: '账号处罚',
57
+ updatedAt: '2026-04-19 14:12',
58
+ versions: [
59
+ { v: 3, title: '更新处罚解释口径', status: '已发布', completion: '97%', execCount: 342, satisfaction: '93%', humanRate: '9%' },
60
+ { v: 2, title: '增加申诉材料提示', status: '实验中', completion: '90%', execCount: 126, satisfaction: '88%', humanRate: '16%' },
61
+ { v: 1, title: '下线旧版规则说明', status: '已下线', completion: '84%', execCount: 61, satisfaction: '82%', humanRate: '21%' },
62
+ ],
63
+ },
64
+ {
65
+ id: 'experience-4',
66
+ title: '抖音体验与服务-直播间举报处理',
67
+ status: '线上生效',
68
+ subtitle: '举报受理与风险分级',
69
+ quoteCount: '76',
70
+ channels: '在线客服、审核工单',
71
+ description: '用于直播间举报场景的自动受理,支持风险分级、证据收集和处理进度同步。',
72
+ category: '举报处理',
73
+ updatedAt: '2026-04-18 09:20',
74
+ versions: [
75
+ { v: 2, title: '优化高危举报分级', status: '已发布', completion: '95%', execCount: 238, satisfaction: '92%', humanRate: '12%' },
76
+ { v: 1, title: '补充直播证据采集', status: '实验中', completion: '89%', execCount: 105, satisfaction: '87%', humanRate: '18%' },
77
+ ],
78
+ },
79
+ {
80
+ id: 'experience-5',
81
+ title: '抖音体验与服务-订单售后协同',
82
+ status: '草稿中',
83
+ subtitle: '售后咨询与工单协同',
84
+ quoteCount: '32',
85
+ channels: '服务工单、人工坐席',
86
+ description: '面向订单售后咨询,沉淀退款、补偿、进度查询和跨团队协同处理流程。',
87
+ category: '售后协同',
88
+ updatedAt: '2026-04-17 16:05',
89
+ versions: [
90
+ { v: 2, title: '新增补偿协同节点', status: '草稿中', completion: '78%', execCount: 42, satisfaction: '85%', humanRate: '19%' },
91
+ { v: 1, title: '搭建售后查询流程', status: '已发布', completion: '91%', execCount: 214, satisfaction: '90%', humanRate: '14%' },
92
+ ],
93
+ },
94
+ ];
95
+
96
+ const STRATEGY_FILTERS = ['管理员', '发布状态', '策略类型'];
97
+
98
+ export default function StrategyListPage() {
99
+ const [expandedId, setExpandedId] = useState('experience-1');
100
+ const [fullModalOpen, setFullModalOpen] = useState(false);
101
+
102
+ return (
103
+ <div
104
+ className="flex flex-1 min-h-0 min-w-0 flex-col overflow-hidden"
105
+ style={{
106
+ margin: '16px',
107
+ ...WHITE_CARD_STYLE,
108
+ }}
109
+ >
110
+ <div
111
+ className="flex flex-1 min-h-0 min-w-0 flex-col"
112
+ style={{ padding: '24px', gap: '16px' }}
113
+ >
114
+ {fullModalOpen && (
115
+ <div
116
+ className="absolute inset-0 z-50 flex flex-col"
117
+ style={{ background: 'rgba(0,0,0,0.4)', borderRadius: '12px' }}
118
+ >
119
+ <Modal
120
+ layout="fullscreen"
121
+ className="mt-auto"
122
+ title="新建策略"
123
+ subtitle={null}
124
+ showFooterHint={false}
125
+ confirmText="创建"
126
+ cancelText="取消"
127
+ onClose={() => setFullModalOpen(false)}
128
+ onCancel={() => setFullModalOpen(false)}
129
+ onConfirm={() => setFullModalOpen(false)}
130
+ >
131
+ <div className="flex flex-1 min-h-0" />
132
+ </Modal>
133
+ </div>
134
+ )}
135
+
136
+ <PageHeader
137
+ title="策略管理"
138
+ contextLabel={PAGE_CONTEXT_LABEL}
139
+ actions={
140
+ <Button variant="primary" icon={<Icon name="plus-stroked" />} onClick={() => setFullModalOpen(true)}>
141
+ 新建策略
142
+ </Button>
143
+ }
144
+ />
145
+
146
+ <StrategyFilterBar filters={STRATEGY_FILTERS} />
147
+
148
+ <Table
149
+ variant="card-form"
150
+ className="min-h-0 flex-1"
151
+ dataSource={MOCK_STRATEGIES}
152
+ rowKey="id"
153
+ expandedRowKeys={expandedId ? [expandedId] : []}
154
+ onExpandedRowKeysChange={(keys) => setExpandedId(keys[keys.length - 1] || null)}
155
+ pagination={{
156
+ current: 1,
157
+ pageSize: 20,
158
+ total: MOCK_STRATEGIES.length,
159
+ pageSizeOptions: [10, 20],
160
+ }}
161
+ />
162
+ </div>
163
+ </div>
164
+ );
165
+ }
166
+
167
+ function StrategyFilterBar({ filters = [] }) {
168
+ return (
169
+ <div className="flex shrink-0 flex-wrap items-center gap-2">
170
+ <Input
171
+ placeholder="搜索"
172
+ prefix={<Icon name="search-md-stroked" />}
173
+ className="max-w-full"
174
+ style={{ flex: '0 1 240px', width: '240px', minWidth: '200px', '--size-input-width': '100%' }}
175
+ />
176
+
177
+ {filters.map((label) => (
178
+ <button
179
+ key={label}
180
+ type="button"
181
+ className="inline-flex h-8 shrink-0 cursor-pointer items-center gap-2 rounded-full border border-border-default bg-white px-3 text-sm [font-weight:var(--font-semibold)] text-blueGrey-800 transition-colors duration-150 hover:bg-fill"
182
+ >
183
+ <span>{label}</span>
184
+ <Icon name="chevron-down-stroked" className="text-blueGrey-600" />
185
+ </button>
186
+ ))}
187
+ </div>
188
+ );
189
+ }