mcp-probe-kit 2.3.0 → 2.5.0

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 (186) hide show
  1. package/README.md +131 -48
  2. package/build/index.js +1 -7
  3. package/build/lib/guidance.d.ts +8 -0
  4. package/build/lib/guidance.js +30 -0
  5. package/build/lib/orchestration-guidance.d.ts +8 -0
  6. package/build/lib/orchestration-guidance.js +16 -0
  7. package/build/lib/template-loader.d.ts +25 -0
  8. package/build/lib/template-loader.js +473 -0
  9. package/build/lib/toolset-manager.d.ts +4 -4
  10. package/build/lib/toolset-manager.js +10 -13
  11. package/build/schemas/code-analysis-tools.d.ts +0 -18
  12. package/build/schemas/code-analysis-tools.js +0 -19
  13. package/build/schemas/doc-util-tools.d.ts +0 -9
  14. package/build/schemas/doc-util-tools.js +0 -10
  15. package/build/schemas/index.d.ts +46 -47
  16. package/build/schemas/orchestration-tools.d.ts +42 -2
  17. package/build/schemas/orchestration-tools.js +42 -2
  18. package/build/schemas/output/core-tools.d.ts +1 -117
  19. package/build/schemas/output/core-tools.js +1 -60
  20. package/build/schemas/output/index.d.ts +5 -4
  21. package/build/schemas/output/index.js +6 -4
  22. package/build/schemas/output/product-design-tools.d.ts +160 -0
  23. package/build/schemas/output/product-design-tools.js +75 -0
  24. package/build/schemas/output/project-tools.d.ts +1 -217
  25. package/build/schemas/output/project-tools.js +1 -103
  26. package/build/schemas/project-tools.d.ts +4 -18
  27. package/build/schemas/project-tools.js +4 -19
  28. package/build/schemas/structured-output.d.ts +309 -99
  29. package/build/schemas/structured-output.js +174 -72
  30. package/build/schemas/ui-ux-schemas.d.ts +26 -0
  31. package/build/schemas/ui-ux-schemas.js +26 -0
  32. package/build/tools/__tests__/add_feature.template.test.d.ts +4 -0
  33. package/build/tools/__tests__/add_feature.template.test.js +47 -0
  34. package/build/tools/__tests__/start_bugfix.unit.test.d.ts +4 -0
  35. package/build/tools/__tests__/start_bugfix.unit.test.js +85 -0
  36. package/build/tools/__tests__/start_feature.unit.test.d.ts +4 -0
  37. package/build/tools/__tests__/start_feature.unit.test.js +83 -0
  38. package/build/tools/__tests__/start_ui.integration.test.js +4 -3
  39. package/build/tools/__tests__/start_ui.loop.test.d.ts +4 -0
  40. package/build/tools/__tests__/start_ui.loop.test.js +24 -0
  41. package/build/tools/__tests__/start_ui.unit.test.js +39 -1
  42. package/build/tools/add_feature.js +184 -406
  43. package/build/tools/ask_user.js +18 -5
  44. package/build/tools/code_review.js +8 -1
  45. package/build/tools/estimate.js +9 -2
  46. package/build/tools/fix_bug.js +9 -2
  47. package/build/tools/gen_mock.js +8 -1
  48. package/build/tools/gen_prd.d.ts +1 -7
  49. package/build/tools/gen_prd.js +41 -27
  50. package/build/tools/gen_prototype.d.ts +1 -7
  51. package/build/tools/gen_prototype.js +47 -27
  52. package/build/tools/genapi.js +8 -1
  53. package/build/tools/genchangelog.js +8 -1
  54. package/build/tools/gencommit.d.ts +1 -1
  55. package/build/tools/gencommit.js +49 -18
  56. package/build/tools/gendoc.js +9 -1
  57. package/build/tools/genpr.js +8 -1
  58. package/build/tools/genreadme.js +8 -1
  59. package/build/tools/gensql.js +8 -1
  60. package/build/tools/gentest.js +8 -1
  61. package/build/tools/index.d.ts +0 -3
  62. package/build/tools/index.js +0 -3
  63. package/build/tools/interview.d.ts +1 -13
  64. package/build/tools/interview.js +96 -31
  65. package/build/tools/perf.js +8 -1
  66. package/build/tools/refactor.js +8 -1
  67. package/build/tools/resolve_conflict.js +8 -1
  68. package/build/tools/security_scan.js +9 -2
  69. package/build/tools/start_api.js +44 -4
  70. package/build/tools/start_bugfix.js +377 -15
  71. package/build/tools/start_doc.js +40 -4
  72. package/build/tools/start_feature.js +287 -92
  73. package/build/tools/start_onboard.js +83 -100
  74. package/build/tools/start_product.d.ts +1 -1
  75. package/build/tools/start_product.js +183 -6
  76. package/build/tools/start_ralph.js +51 -2
  77. package/build/tools/start_refactor.js +39 -4
  78. package/build/tools/start_release.js +33 -4
  79. package/build/tools/start_review.js +39 -4
  80. package/build/tools/start_ui.js +669 -52
  81. package/build/utils/design-reasoning-engine.d.ts +5 -0
  82. package/build/utils/design-reasoning-engine.js +85 -5
  83. package/docs/data/tools.js +308 -478
  84. package/docs/index.html +1 -1
  85. package/docs/pages/all-tools.html +37 -22
  86. package/docs/pages/examples.html +100 -35
  87. package/docs/pages/getting-started.html +43 -3
  88. package/docs/pages/migration.html +14 -8
  89. package/package.json +79 -79
  90. package/build/lib/analysis-tasks.d.ts +0 -35
  91. package/build/lib/analysis-tasks.js +0 -788
  92. package/build/lib/elicitation-helper.d.ts +0 -73
  93. package/build/lib/elicitation-helper.js +0 -130
  94. package/build/lib/task-generator.d.ts +0 -11
  95. package/build/lib/task-generator.js +0 -109
  96. package/build/lib/template-generator.d.ts +0 -14
  97. package/build/lib/template-generator.js +0 -62
  98. package/build/lib/templates/backend-templates.d.ts +0 -8
  99. package/build/lib/templates/backend-templates.js +0 -26
  100. package/build/resources/index.d.ts +0 -4
  101. package/build/resources/index.js +0 -4
  102. package/build/resources/tool-params-guide.d.ts +0 -571
  103. package/build/resources/tool-params-guide.js +0 -488
  104. package/build/tools/analyze_project.d.ts +0 -1
  105. package/build/tools/analyze_project.js +0 -566
  106. package/build/tools/check_deps.d.ts +0 -1
  107. package/build/tools/check_deps.js +0 -213
  108. package/build/tools/convert.d.ts +0 -13
  109. package/build/tools/convert.js +0 -599
  110. package/build/tools/css_order.d.ts +0 -13
  111. package/build/tools/css_order.js +0 -81
  112. package/build/tools/debug.d.ts +0 -1
  113. package/build/tools/debug.js +0 -133
  114. package/build/tools/design2code.d.ts +0 -20
  115. package/build/tools/design2code.js +0 -426
  116. package/build/tools/detect_shell.d.ts +0 -6
  117. package/build/tools/detect_shell.js +0 -151
  118. package/build/tools/explain.d.ts +0 -13
  119. package/build/tools/explain.js +0 -390
  120. package/build/tools/fix.d.ts +0 -13
  121. package/build/tools/fix.js +0 -303
  122. package/build/tools/gen_skill.d.ts +0 -13
  123. package/build/tools/gen_skill.js +0 -560
  124. package/build/tools/genui.d.ts +0 -13
  125. package/build/tools/genui.js +0 -803
  126. package/build/tools/init_setting.d.ts +0 -13
  127. package/build/tools/init_setting.js +0 -47
  128. package/build/tools/split.d.ts +0 -13
  129. package/build/tools/split.js +0 -599
  130. package/build/tools/templates/architecture-template.d.ts +0 -5
  131. package/build/tools/templates/architecture-template.js +0 -42
  132. package/build/tools/templates/coding-standards-template.d.ts +0 -5
  133. package/build/tools/templates/coding-standards-template.js +0 -41
  134. package/build/tools/templates/dependencies-template.d.ts +0 -5
  135. package/build/tools/templates/dependencies-template.js +0 -38
  136. package/build/tools/templates/index-template.d.ts +0 -5
  137. package/build/tools/templates/index-template.js +0 -64
  138. package/build/tools/templates/tech-stack-template.d.ts +0 -5
  139. package/build/tools/templates/tech-stack-template.js +0 -35
  140. package/build/tools/templates/workflows-template.d.ts +0 -5
  141. package/build/tools/templates/workflows-template.js +0 -31
  142. package/docs/specs/algorithm-enhancement/roadmap.md +0 -619
  143. package/docs/specs/project-context-modular/design.md +0 -722
  144. package/docs/specs/project-context-modular/example-output.md +0 -123
  145. package/docs/specs/project-context-modular/implementation-v2.md +0 -275
  146. package/docs/specs/project-context-modular/requirements.md +0 -234
  147. package/docs/specs/project-context-modular/tasks.md +0 -386
  148. package/docs/specs/v2.1-planning.md +0 -335
  149. package/docs/specs/vnext-upgrade/00-OVERVIEW.md +0 -258
  150. package/docs/specs/vnext-upgrade/BETA_RELEASE_GUIDE.md +0 -328
  151. package/docs/specs/vnext-upgrade/GITHUB_DISCUSSION_TEMPLATE.md +0 -236
  152. package/docs/specs/vnext-upgrade/M8.9-PROGRESS-UPDATE.md +0 -248
  153. package/docs/specs/vnext-upgrade/PROGRESS-SUMMARY.md +0 -195
  154. package/docs/specs/vnext-upgrade/QUICK_REFERENCE.md +0 -338
  155. package/docs/specs/vnext-upgrade/README.md +0 -125
  156. package/docs/specs/vnext-upgrade/STATUS-UPDATE-2026-01-26.md +0 -230
  157. package/docs/specs/vnext-upgrade/TOOL_CLEANUP.md +0 -343
  158. package/docs/specs/vnext-upgrade/completed/M1-M2-SUMMARY.md +0 -27
  159. package/docs/specs/vnext-upgrade/completed/M3_COMPLETION_SUMMARY.md +0 -273
  160. package/docs/specs/vnext-upgrade/completed/M4-SUMMARY.md +0 -19
  161. package/docs/specs/vnext-upgrade/completed/M5_COMPLETION_SUMMARY.md +0 -0
  162. package/docs/specs/vnext-upgrade/completed/M8.1-SUMMARY.md +0 -247
  163. package/docs/specs/vnext-upgrade/completed/M8.2-SUMMARY.md +0 -296
  164. package/docs/specs/vnext-upgrade/completed/M8.3-SUMMARY.md +0 -241
  165. package/docs/specs/vnext-upgrade/completed/M8.3-TEST-SUMMARY.md +0 -216
  166. package/docs/specs/vnext-upgrade/completed/M8.4-SUMMARY.md +0 -217
  167. package/docs/specs/vnext-upgrade/completed/M8.4-TEST-SUMMARY.md +0 -198
  168. package/docs/specs/vnext-upgrade/completed/M8.5-SUMMARY.md +0 -202
  169. package/docs/specs/vnext-upgrade/completed/M8.5-TEST-SUMMARY.md +0 -223
  170. package/docs/specs/vnext-upgrade/completed/M8.6-SUMMARY.md +0 -299
  171. package/docs/specs/vnext-upgrade/completed/M8.8-TEST-SUMMARY.md +0 -216
  172. package/docs/specs/vnext-upgrade/completed/TOOL-CLEANUP-SUMMARY.md +0 -210
  173. package/docs/specs/vnext-upgrade/design.md +0 -848
  174. package/docs/specs/vnext-upgrade/requirements.md +0 -221
  175. package/docs/specs/vnext-upgrade/tasks/00-INDEX.md +0 -335
  176. package/docs/specs/vnext-upgrade/tasks/M8.1-SCHEMA-DEFINITION.md +0 -300
  177. package/docs/specs/vnext-upgrade/tasks/M8.2-P1-TOOLS.md +0 -249
  178. package/docs/specs/vnext-upgrade/tasks/M8.3-GENERATION-TOOLS.md +0 -49
  179. package/docs/specs/vnext-upgrade/tasks/M8.4-ORCHESTRATION-TOOLS.md +0 -28
  180. package/docs/specs/vnext-upgrade/tasks/M8.5-PROJECT-TOOLS.md +0 -29
  181. package/docs/specs/vnext-upgrade/tasks/M8.6-UI-TOOLS.md +0 -66
  182. package/docs/specs/vnext-upgrade/tasks/M8.7-HELPER-TOOLS.md +0 -24
  183. package/docs/specs/vnext-upgrade/tasks/M8.8-INTEGRATION-TESTS.md +0 -90
  184. package/docs/specs/vnext-upgrade/tasks/M8.9-DOCUMENTATION.md +0 -103
  185. package/docs/vnext/MCP_2025-11-25_GUIDE.md +0 -276
  186. package/docs/vnext/vNext-PRD.md +0 -488
@@ -1,803 +0,0 @@
1
- import { parseArgs, getString } from "../utils/parseArgs.js";
2
- // genui 工具实现
3
- export async function genui(args) {
4
- try {
5
- // 智能参数解析,支持自然语言输入
6
- const parsedArgs = parseArgs(args, {
7
- defaultValues: {
8
- description: "",
9
- framework: "react",
10
- },
11
- primaryField: "description", // 纯文本输入默认映射到 description 字段
12
- fieldAliases: {
13
- description: ["requirement", "spec", "需求", "组件描述"],
14
- framework: ["lib", "library", "框架", "前端框架"],
15
- },
16
- });
17
- const description = getString(parsedArgs.description);
18
- const framework = getString(parsedArgs.framework) || "react"; // react, vue, html
19
- const message = `请生成以下 UI 组件:
20
-
21
- 📝 **组件描述**:
22
- ${description || "请描述需要的 UI 组件"}
23
-
24
- ⚛️ **框架**:${framework}
25
-
26
- ---
27
-
28
- ## UI 组件生成指南
29
-
30
- ### 第一步:理解需求
31
-
32
- **组件类型**:
33
- - 基础组件(Button, Input, Card)
34
- - 表单组件(Form, Select, Checkbox)
35
- - 数据展示(Table, List, Grid)
36
- - 反馈组件(Modal, Toast, Loading)
37
- - 导航组件(Menu, Tabs, Breadcrumb)
38
- - 布局组件(Layout, Container, Flex)
39
-
40
- ### 第二步:设计原则
41
-
42
- **1️⃣ 组件化**
43
- - 单一职责
44
- - 可复用
45
- - 可组合
46
-
47
- **2️⃣ 可访问性(A11y)**
48
- - 语义化 HTML
49
- - ARIA 属性
50
- - 键盘导航
51
- - 屏幕阅读器支持
52
-
53
- **3️⃣ 响应式**
54
- - 移动端优先
55
- - 断点设计
56
- - 弹性布局
57
-
58
- **4️⃣ 性能**
59
- - 懒加载
60
- - 虚拟滚动
61
- - 防抖节流
62
-
63
- ---
64
-
65
- ## React 组件示例
66
-
67
- ### 基础 Button 组件
68
- \`\`\`tsx
69
- import React from 'react';
70
- import { cva, type VariantProps } from 'class-variance-authority';
71
-
72
- const buttonVariants = cva(
73
- // 基础样式
74
- "inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
75
- {
76
- variants: {
77
- variant: {
78
- default: "bg-blue-600 text-white hover:bg-blue-700",
79
- destructive: "bg-red-600 text-white hover:bg-red-700",
80
- outline: "border border-gray-300 bg-transparent hover:bg-gray-100",
81
- ghost: "hover:bg-gray-100",
82
- link: "text-blue-600 underline-offset-4 hover:underline",
83
- },
84
- size: {
85
- default: "h-10 px-4 py-2",
86
- sm: "h-9 px-3",
87
- lg: "h-11 px-8",
88
- icon: "h-10 w-10",
89
- },
90
- },
91
- defaultVariants: {
92
- variant: "default",
93
- size: "default",
94
- },
95
- }
96
- );
97
-
98
- export interface ButtonProps
99
- extends React.ButtonHTMLAttributes<HTMLButtonElement>,
100
- VariantProps<typeof buttonVariants> {
101
- isLoading?: boolean;
102
- }
103
-
104
- const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
105
- ({ className, variant, size, isLoading, children, ...props }, ref) => {
106
- return (
107
- <button
108
- className={buttonVariants({ variant, size, className })}
109
- ref={ref}
110
- disabled={isLoading || props.disabled}
111
- {...props}
112
- >
113
- {isLoading && (
114
- <svg
115
- className="mr-2 h-4 w-4 animate-spin"
116
- xmlns="http://www.w3.org/2000/svg"
117
- fill="none"
118
- viewBox="0 0 24 24"
119
- >
120
- <circle
121
- className="opacity-25"
122
- cx="12"
123
- cy="12"
124
- r="10"
125
- stroke="currentColor"
126
- strokeWidth="4"
127
- />
128
- <path
129
- className="opacity-75"
130
- fill="currentColor"
131
- d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
132
- />
133
- </svg>
134
- )}
135
- {children}
136
- </button>
137
- );
138
- }
139
- );
140
-
141
- Button.displayName = "Button";
142
-
143
- export { Button, buttonVariants };
144
- \`\`\`
145
-
146
- **使用示例:**
147
- \`\`\`tsx
148
- <Button variant="default" size="lg">
149
- 提交
150
- </Button>
151
-
152
- <Button variant="outline" isLoading>
153
- 加载中...
154
- </Button>
155
-
156
- <Button variant="ghost" size="icon">
157
- <Icon />
158
- </Button>
159
- \`\`\`
160
-
161
- ---
162
-
163
- ### 表单输入组件
164
- \`\`\`tsx
165
- import React from 'react';
166
- import { useController, Control } from 'react-hook-form';
167
-
168
- interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
169
- label?: string;
170
- error?: string;
171
- helperText?: string;
172
- control?: Control<any>;
173
- name: string;
174
- }
175
-
176
- export const Input = React.forwardRef<HTMLInputElement, InputProps>(
177
- ({ label, error, helperText, className, control, name, ...props }, ref) => {
178
- const { field } = useController({
179
- name,
180
- control,
181
- defaultValue: props.defaultValue || '',
182
- });
183
-
184
- return (
185
- <div className="w-full space-y-2">
186
- {label && (
187
- <label
188
- htmlFor={name}
189
- className="text-sm font-medium text-gray-700"
190
- >
191
- {label}
192
- {props.required && <span className="text-red-500 ml-1">*</span>}
193
- </label>
194
- )}
195
-
196
- <input
197
- {...field}
198
- {...props}
199
- ref={ref}
200
- id={name}
201
- aria-invalid={!!error}
202
- aria-describedby={error ? \`\${name}-error\` : undefined}
203
- className={\`
204
- w-full px-3 py-2 border rounded-md
205
- focus:outline-none focus:ring-2 focus:ring-blue-500
206
- disabled:bg-gray-100 disabled:cursor-not-allowed
207
- \${error ? 'border-red-500' : 'border-gray-300'}
208
- \${className || ''}
209
- \`}
210
- />
211
-
212
- {error && (
213
- <p id={\`\${name}-error\`} className="text-sm text-red-600">
214
- {error}
215
- </p>
216
- )}
217
-
218
- {helperText && !error && (
219
- <p className="text-sm text-gray-500">{helperText}</p>
220
- )}
221
- </div>
222
- );
223
- }
224
- );
225
-
226
- Input.displayName = 'Input';
227
- \`\`\`
228
-
229
- ---
230
-
231
- ### Modal 弹窗组件
232
- \`\`\`tsx
233
- import React, { useEffect } from 'react';
234
- import { createPortal } from 'react-dom';
235
-
236
- interface ModalProps {
237
- isOpen: boolean;
238
- onClose: () => void;
239
- title?: string;
240
- children: React.ReactNode;
241
- size?: 'sm' | 'md' | 'lg' | 'xl';
242
- }
243
-
244
- export const Modal: React.FC<ModalProps> = ({
245
- isOpen,
246
- onClose,
247
- title,
248
- children,
249
- size = 'md',
250
- }) => {
251
- // ESC 关闭
252
- useEffect(() => {
253
- const handleEsc = (e: KeyboardEvent) => {
254
- if (e.key === 'Escape') onClose();
255
- };
256
-
257
- if (isOpen) {
258
- document.addEventListener('keydown', handleEsc);
259
- document.body.style.overflow = 'hidden';
260
- }
261
-
262
- return () => {
263
- document.removeEventListener('keydown', handleEsc);
264
- document.body.style.overflow = 'unset';
265
- };
266
- }, [isOpen, onClose]);
267
-
268
- if (!isOpen) return null;
269
-
270
- const sizeClasses = {
271
- sm: 'max-w-md',
272
- md: 'max-w-lg',
273
- lg: 'max-w-2xl',
274
- xl: 'max-w-4xl',
275
- };
276
-
277
- return createPortal(
278
- <div
279
- className="fixed inset-0 z-50 flex items-center justify-center"
280
- onClick={onClose}
281
- >
282
- {/* 背景遮罩 */}
283
- <div className="absolute inset-0 bg-black/50 backdrop-blur-sm" />
284
-
285
- {/* 弹窗内容 */}
286
- <div
287
- className={\`
288
- relative bg-white rounded-lg shadow-xl
289
- w-full mx-4 \${sizeClasses[size]}
290
- max-h-[90vh] flex flex-col
291
- animate-in fade-in slide-in-from-bottom-4
292
- \`}
293
- onClick={(e) => e.stopPropagation()}
294
- role="dialog"
295
- aria-modal="true"
296
- aria-labelledby={title ? 'modal-title' : undefined}
297
- >
298
- {/* 头部 */}
299
- {title && (
300
- <div className="px-6 py-4 border-b">
301
- <h2 id="modal-title" className="text-xl font-semibold">
302
- {title}
303
- </h2>
304
- </div>
305
- )}
306
-
307
- {/* 关闭按钮 */}
308
- <button
309
- onClick={onClose}
310
- className="absolute top-4 right-4 text-gray-400 hover:text-gray-600"
311
- aria-label="关闭"
312
- >
313
- <svg className="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
314
- <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
315
- </svg>
316
- </button>
317
-
318
- {/* 内容 */}
319
- <div className="px-6 py-4 overflow-y-auto flex-1">
320
- {children}
321
- </div>
322
- </div>
323
- </div>,
324
- document.body
325
- );
326
- };
327
- \`\`\`
328
-
329
- ---
330
-
331
- ### Table 数据表格
332
- \`\`\`tsx
333
- import React from 'react';
334
-
335
- interface Column<T> {
336
- key: keyof T | string;
337
- title: string;
338
- render?: (value: any, record: T, index: number) => React.ReactNode;
339
- width?: string;
340
- align?: 'left' | 'center' | 'right';
341
- }
342
-
343
- interface TableProps<T> {
344
- columns: Column<T>[];
345
- data: T[];
346
- rowKey: keyof T;
347
- loading?: boolean;
348
- onRowClick?: (record: T) => void;
349
- }
350
-
351
- export function Table<T extends Record<string, any>>({
352
- columns,
353
- data,
354
- rowKey,
355
- loading,
356
- onRowClick,
357
- }: TableProps<T>) {
358
- if (loading) {
359
- return <div className="text-center py-8">加载中...</div>;
360
- }
361
-
362
- if (data.length === 0) {
363
- return <div className="text-center py-8 text-gray-500">暂无数据</div>;
364
- }
365
-
366
- return (
367
- <div className="overflow-x-auto">
368
- <table className="min-w-full divide-y divide-gray-200">
369
- <thead className="bg-gray-50">
370
- <tr>
371
- {columns.map((col, index) => (
372
- <th
373
- key={String(col.key) || index}
374
- style={{ width: col.width }}
375
- className={\`
376
- px-6 py-3 text-xs font-medium text-gray-500 uppercase tracking-wider
377
- text-\${col.align || 'left'}
378
- \`}
379
- >
380
- {col.title}
381
- </th>
382
- ))}
383
- </tr>
384
- </thead>
385
- <tbody className="bg-white divide-y divide-gray-200">
386
- {data.map((record, rowIndex) => (
387
- <tr
388
- key={String(record[rowKey])}
389
- onClick={() => onRowClick?.(record)}
390
- className={onRowClick ? 'cursor-pointer hover:bg-gray-50' : ''}
391
- >
392
- {columns.map((col, colIndex) => {
393
- const value = col.key in record ? record[col.key as keyof T] : undefined;
394
- return (
395
- <td
396
- key={colIndex}
397
- className={\`px-6 py-4 whitespace-nowrap text-sm text-\${col.align || 'left'}\`}
398
- >
399
- {col.render ? col.render(value, record, rowIndex) : String(value)}
400
- </td>
401
- );
402
- })}
403
- </tr>
404
- ))}
405
- </tbody>
406
- </table>
407
- </div>
408
- );
409
- }
410
- \`\`\`
411
-
412
- ---
413
-
414
- ## Tailwind CSS 配置
415
-
416
- \`\`\`js
417
- // tailwind.config.js
418
- module.exports = {
419
- content: ['./src/**/*.{js,ts,jsx,tsx}'],
420
- theme: {
421
- extend: {
422
- keyframes: {
423
- 'fade-in': {
424
- from: { opacity: 0 },
425
- to: { opacity: 1 },
426
- },
427
- 'slide-in-from-bottom': {
428
- from: { transform: 'translateY(1rem)' },
429
- to: { transform: 'translateY(0)' },
430
- },
431
- },
432
- animation: {
433
- 'fade-in': 'fade-in 0.2s ease-out',
434
- 'slide-in-from-bottom-4': 'slide-in-from-bottom 0.3s ease-out',
435
- },
436
- },
437
- },
438
- plugins: [],
439
- };
440
- \`\`\`
441
-
442
- ---
443
-
444
- ## Vue 3 组件示例
445
-
446
- ### 基础 Button 组件 (Vue 3 + TypeScript)
447
- \`\`\`vue
448
- <template>
449
- <button
450
- :class="buttonClasses"
451
- :disabled="isLoading || disabled"
452
- v-bind="$attrs"
453
- >
454
- <svg
455
- v-if="isLoading"
456
- class="mr-2 h-4 w-4 animate-spin"
457
- xmlns="http://www.w3.org/2000/svg"
458
- fill="none"
459
- viewBox="0 0 24 24"
460
- >
461
- <circle
462
- class="opacity-25"
463
- cx="12"
464
- cy="12"
465
- r="10"
466
- stroke="currentColor"
467
- stroke-width="4"
468
- />
469
- <path
470
- class="opacity-75"
471
- fill="currentColor"
472
- d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
473
- />
474
- </svg>
475
- <slot />
476
- </button>
477
- </template>
478
-
479
- <script setup lang="ts">
480
- import { computed } from 'vue';
481
-
482
- interface Props {
483
- variant?: 'default' | 'destructive' | 'outline' | 'ghost' | 'link';
484
- size?: 'default' | 'sm' | 'lg' | 'icon';
485
- isLoading?: boolean;
486
- disabled?: boolean;
487
- }
488
-
489
- const props = withDefaults(defineProps<Props>(), {
490
- variant: 'default',
491
- size: 'default',
492
- isLoading: false,
493
- disabled: false,
494
- });
495
-
496
- const buttonClasses = computed(() => {
497
- const base = 'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50';
498
-
499
- const variants = {
500
- default: 'bg-blue-600 text-white hover:bg-blue-700',
501
- destructive: 'bg-red-600 text-white hover:bg-red-700',
502
- outline: 'border border-gray-300 bg-transparent hover:bg-gray-100',
503
- ghost: 'hover:bg-gray-100',
504
- link: 'text-blue-600 underline-offset-4 hover:underline',
505
- };
506
-
507
- const sizes = {
508
- default: 'h-10 px-4 py-2',
509
- sm: 'h-9 px-3',
510
- lg: 'h-11 px-8',
511
- icon: 'h-10 w-10',
512
- };
513
-
514
- return \`\${base} \${variants[props.variant]} \${sizes[props.size]}\`;
515
- });
516
- </script>
517
- \`\`\`
518
-
519
- **使用示例:**
520
- \`\`\`vue
521
- <template>
522
- <div>
523
- <Button variant="default" size="lg">提交</Button>
524
- <Button variant="outline" :is-loading="true">加载中...</Button>
525
- <Button variant="ghost" size="icon">
526
- <Icon />
527
- </Button>
528
- </div>
529
- </template>
530
-
531
- <script setup lang="ts">
532
- import Button from '@/components/Button.vue';
533
- </script>
534
- \`\`\`
535
-
536
- ---
537
-
538
- ### Vue 3 Input 组件
539
- \`\`\`vue
540
- <template>
541
- <div class="w-full space-y-2">
542
- <label
543
- v-if="label"
544
- :for="inputId"
545
- class="text-sm font-medium text-gray-700"
546
- >
547
- {{ label }}
548
- <span v-if="required" class="text-red-500 ml-1">*</span>
549
- </label>
550
-
551
- <input
552
- :id="inputId"
553
- v-model="model"
554
- :type="type"
555
- :placeholder="placeholder"
556
- :required="required"
557
- :disabled="disabled"
558
- :aria-invalid="!!error"
559
- :aria-describedby="error ? \`\${inputId}-error\` : undefined"
560
- :class="inputClasses"
561
- v-bind="$attrs"
562
- />
563
-
564
- <p v-if="error" :id="\`\${inputId}-error\`" class="text-sm text-red-600">
565
- {{ error }}
566
- </p>
567
-
568
- <p v-else-if="helperText" class="text-sm text-gray-500">
569
- {{ helperText }}
570
- </p>
571
- </div>
572
- </template>
573
-
574
- <script setup lang="ts">
575
- import { computed, useAttrs } from 'vue';
576
-
577
- interface Props {
578
- modelValue?: string | number;
579
- label?: string;
580
- type?: string;
581
- placeholder?: string;
582
- error?: string;
583
- helperText?: string;
584
- required?: boolean;
585
- disabled?: boolean;
586
- }
587
-
588
- const props = withDefaults(defineProps<Props>(), {
589
- type: 'text',
590
- required: false,
591
- disabled: false,
592
- });
593
-
594
- const emit = defineEmits<{
595
- 'update:modelValue': [value: string | number];
596
- }>();
597
-
598
- const attrs = useAttrs();
599
- const inputId = computed(() => attrs.id as string || \`input-\${Math.random().toString(36).slice(2)}\`);
600
-
601
- const model = computed({
602
- get: () => props.modelValue,
603
- set: (value) => emit('update:modelValue', value),
604
- });
605
-
606
- const inputClasses = computed(() => {
607
- return \`
608
- w-full px-3 py-2 border rounded-md
609
- focus:outline-none focus:ring-2 focus:ring-blue-500
610
- disabled:bg-gray-100 disabled:cursor-not-allowed
611
- \${props.error ? 'border-red-500' : 'border-gray-300'}
612
- \`;
613
- });
614
- </script>
615
- \`\`\`
616
-
617
- ---
618
-
619
- ### Vue 3 Modal 组件
620
- \`\`\`vue
621
- <template>
622
- <Teleport to="body">
623
- <Transition name="modal">
624
- <div
625
- v-if="modelValue"
626
- class="fixed inset-0 z-50 flex items-center justify-center"
627
- @click="handleClose"
628
- >
629
- <!-- 背景遮罩 -->
630
- <div class="absolute inset-0 bg-black/50 backdrop-blur-sm" />
631
-
632
- <!-- 弹窗内容 -->
633
- <div
634
- :class="modalClasses"
635
- @click.stop
636
- role="dialog"
637
- aria-modal="true"
638
- :aria-labelledby="title ? 'modal-title' : undefined"
639
- >
640
- <!-- 头部 -->
641
- <div v-if="title" class="px-6 py-4 border-b">
642
- <h2 id="modal-title" class="text-xl font-semibold">
643
- {{ title }}
644
- </h2>
645
- </div>
646
-
647
- <!-- 关闭按钮 -->
648
- <button
649
- @click="handleClose"
650
- class="absolute top-4 right-4 text-gray-400 hover:text-gray-600"
651
- aria-label="关闭"
652
- >
653
- <svg class="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
654
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
655
- </svg>
656
- </button>
657
-
658
- <!-- 内容 -->
659
- <div class="px-6 py-4 overflow-y-auto flex-1">
660
- <slot />
661
- </div>
662
- </div>
663
- </div>
664
- </Transition>
665
- </Teleport>
666
- </template>
667
-
668
- <script setup lang="ts">
669
- import { computed, watch } from 'vue';
670
- import { onKeyStroke } from '@vueuse/core';
671
-
672
- interface Props {
673
- modelValue: boolean;
674
- title?: string;
675
- size?: 'sm' | 'md' | 'lg' | 'xl';
676
- }
677
-
678
- const props = withDefaults(defineProps<Props>(), {
679
- size: 'md',
680
- });
681
-
682
- const emit = defineEmits<{
683
- 'update:modelValue': [value: boolean];
684
- }>();
685
-
686
- const handleClose = () => {
687
- emit('update:modelValue', false);
688
- };
689
-
690
- // ESC 关闭
691
- onKeyStroke('Escape', () => {
692
- if (props.modelValue) {
693
- handleClose();
694
- }
695
- });
696
-
697
- // 锁定 body 滚动
698
- watch(() => props.modelValue, (isOpen) => {
699
- document.body.style.overflow = isOpen ? 'hidden' : '';
700
- });
701
-
702
- const modalClasses = computed(() => {
703
- const sizeClasses = {
704
- sm: 'max-w-md',
705
- md: 'max-w-lg',
706
- lg: 'max-w-2xl',
707
- xl: 'max-w-4xl',
708
- };
709
-
710
- return \`
711
- relative bg-white rounded-lg shadow-xl
712
- w-full mx-4 \${sizeClasses[props.size]}
713
- max-h-[90vh] flex flex-col
714
- \`;
715
- });
716
- </script>
717
-
718
- <style scoped>
719
- .modal-enter-active,
720
- .modal-leave-active {
721
- transition: opacity 0.3s ease;
722
- }
723
-
724
- .modal-enter-from,
725
- .modal-leave-to {
726
- opacity: 0;
727
- }
728
- </style>
729
- \`\`\`
730
-
731
- ---
732
-
733
- ## 组件库推荐
734
-
735
- ### 🎨 React UI 组件库
736
- - **shadcn/ui** - 可定制的 React 组件
737
- - **Radix UI** - 无样式的可访问组件
738
- - **Headless UI** - Tailwind 官方无样式组件
739
- - **Ant Design** - 企业级 UI 设计语言
740
- - **Material-UI** - Google Material Design
741
-
742
- ### 🎨 Vue UI 组件库
743
- - **Element Plus** - 基于 Vue 3 的企业级组件库
744
- - **Naive UI** - 完整的 TypeScript 支持
745
- - **Ant Design Vue** - Vue 版本的 Ant Design
746
- - **Vuetify** - Material Design 组件框架
747
- - **PrimeVue** - 丰富的 UI 组件集合
748
-
749
- ### 🎭 动画库
750
- - **Framer Motion** - React 动画库
751
- - **React Spring** - 基于物理的动画
752
- - **GSAP** - 高性能动画引擎(React/Vue 通用)
753
- - **@vueuse/motion** - Vue 3 组合式动画
754
-
755
- ### 📱 响应式工具
756
- - **Tailwind CSS** - 实用优先的 CSS 框架
757
- - **UnoCSS** - 即时原子化 CSS 引擎
758
- - **CSS Modules** - 局部作用域 CSS
759
-
760
- ---
761
-
762
- ---
763
-
764
- ## ⚠️ 边界约束
765
-
766
- - ❌ 仅输出组件代码,不自动创建文件
767
- - ❌ 不执行代码或命令
768
- - ✅ 默认跟随项目现有前端栈与组件风格
769
- - ✅ 输出完整可用的组件代码
770
-
771
- 现在请根据需求生成完整的 UI 组件代码,包括:
772
- 1. 组件实现(TypeScript)
773
- 2. 样式(Tailwind CSS)
774
- 3. 使用示例
775
- 4. Props 接口定义
776
- 5. 可访问性说明
777
-
778
- **根据框架选择:**
779
- - **React**: 使用 Hooks、forwardRef、TypeScript
780
- - **Vue 3**: 使用 Composition API、script setup、TypeScript
781
- - **HTML**: 使用原生 JavaScript 和 Web Components`;
782
- return {
783
- content: [
784
- {
785
- type: "text",
786
- text: message,
787
- },
788
- ],
789
- };
790
- }
791
- catch (error) {
792
- const errorMessage = error instanceof Error ? error.message : String(error);
793
- return {
794
- content: [
795
- {
796
- type: "text",
797
- text: `❌ 生成 UI 组件失败: ${errorMessage}`,
798
- },
799
- ],
800
- isError: true,
801
- };
802
- }
803
- }