leafer-x-design-system 2.0.1

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.
@@ -0,0 +1,1102 @@
1
+ /**
2
+ * LeaferJS UI 设计系统生成器
3
+ *
4
+ * 专家级工具 - 自动生成完整的设计系统、组件库和 UI 原型
5
+ *
6
+ * 功能:
7
+ * - 主题配置系统(颜色、字体、间距、阴影)
8
+ * - 基础组件生成(Button、Input、Card、Modal 等)
9
+ * - 完整页面模板(Dashboard、Login、Profile 等)
10
+ * - 导出为 LeaferJS JSON 格式
11
+ * - 直接渲染为图片
12
+ *
13
+ * @author LeaferJS Expert
14
+ * @version 1.0.0
15
+ */
16
+
17
+ const fs = require('fs');
18
+ const path = require('path');
19
+
20
+ /**
21
+ * 设计系统配置
22
+ */
23
+ class DesignSystemConfig {
24
+ constructor(options = {}) {
25
+ this.name = options.name || 'My Design System';
26
+ this.version = options.version || '1.0.0';
27
+
28
+ // 颜色系统
29
+ this.colors = {
30
+ primary: options.primaryColor || '#667eea',
31
+ secondary: options.secondaryColor || '#764ba2',
32
+ success: '#48bb78',
33
+ warning: '#ed8936',
34
+ error: '#f56565',
35
+ info: '#4299e1',
36
+ gray: {
37
+ 50: '#f9fafb',
38
+ 100: '#f3f4f6',
39
+ 200: '#e5e7eb',
40
+ 300: '#d1d5db',
41
+ 400: '#9ca3af',
42
+ 500: '#6b7280',
43
+ 600: '#4b5563',
44
+ 700: '#374151',
45
+ 800: '#1f2937',
46
+ 900: '#111827'
47
+ },
48
+ ...options.colors
49
+ };
50
+
51
+ // 字体系统
52
+ this.typography = {
53
+ fontFamily: options.fontFamily || 'Microsoft YaHei',
54
+ fontSize: {
55
+ xs: 12,
56
+ sm: 14,
57
+ base: 16,
58
+ lg: 18,
59
+ xl: 20,
60
+ '2xl': 24,
61
+ '3xl': 30,
62
+ '4xl': 36
63
+ },
64
+ fontWeight: {
65
+ light: 300,
66
+ normal: 400,
67
+ medium: 500,
68
+ semibold: 600,
69
+ bold: 700
70
+ },
71
+ lineHeight: {
72
+ tight: 1.25,
73
+ normal: 1.5,
74
+ relaxed: 1.75
75
+ }
76
+ };
77
+
78
+ // 间距系统
79
+ this.spacing = {
80
+ 0: 0,
81
+ 1: 4,
82
+ 2: 8,
83
+ 3: 12,
84
+ 4: 16,
85
+ 5: 20,
86
+ 6: 24,
87
+ 8: 32,
88
+ 10: 40,
89
+ 12: 48,
90
+ 16: 64
91
+ };
92
+
93
+ // 圆角系统
94
+ this.borderRadius = {
95
+ none: 0,
96
+ sm: 2,
97
+ md: 4,
98
+ lg: 8,
99
+ xl: 12,
100
+ '2xl': 16,
101
+ full: 9999
102
+ };
103
+
104
+ // 阴影系统
105
+ this.shadows = {
106
+ sm: { x: 0, y: 1, blur: 2, color: '#0000000d' },
107
+ md: { x: 0, y: 4, blur: 6, color: '#0000001a' },
108
+ lg: { x: 0, y: 10, blur: 15, color: '#0000001a' },
109
+ xl: { x: 0, y: 20, blur: 25, color: '#00000026' },
110
+ inner: { x: 0, y: 2, blur: 4, color: '#0000000d' }
111
+ };
112
+
113
+ // 断点系统
114
+ this.breakpoints = {
115
+ sm: 640,
116
+ md: 768,
117
+ lg: 1024,
118
+ xl: 1280,
119
+ '2xl': 1536
120
+ };
121
+ }
122
+
123
+ /**
124
+ * 导出配置为 JSON
125
+ */
126
+ toJSON() {
127
+ return {
128
+ name: this.name,
129
+ version: this.version,
130
+ colors: this.colors,
131
+ typography: this.typography,
132
+ spacing: this.spacing,
133
+ borderRadius: this.borderRadius,
134
+ shadows: this.shadows,
135
+ breakpoints: this.breakpoints
136
+ };
137
+ }
138
+
139
+ /**
140
+ * 保存配置到文件
141
+ */
142
+ save(outputPath) {
143
+ const configPath = path.join(outputPath, 'design-system.json');
144
+ fs.writeFileSync(configPath, JSON.stringify(this.toJSON(), null, 2));
145
+ console.log(`[Design System] Config saved to: ${configPath}`);
146
+ return configPath;
147
+ }
148
+ }
149
+
150
+ /**
151
+ * 组件生成器
152
+ */
153
+ class ComponentGenerator {
154
+ constructor(config) {
155
+ this.config = config;
156
+ }
157
+
158
+ /**
159
+ * 生成按钮组件
160
+ */
161
+ generateButton(variant = 'primary', size = 'md', text = 'Button') {
162
+ const { colors, typography, spacing, borderRadius, shadows } = this.config;
163
+
164
+ // 尺寸配置
165
+ const sizeConfig = {
166
+ sm: { height: 32, padding: spacing[2], fontSize: typography.fontSize.sm },
167
+ md: { height: 40, padding: spacing[4], fontSize: typography.fontSize.base },
168
+ lg: { height: 48, padding: spacing[6], fontSize: typography.fontSize.lg }
169
+ };
170
+
171
+ // 变体配置
172
+ const variantConfig = {
173
+ primary: { fill: colors.primary, textColor: '#ffffff' },
174
+ secondary: { fill: colors.secondary, textColor: '#ffffff' },
175
+ success: { fill: colors.success, textColor: '#ffffff' },
176
+ warning: { fill: colors.warning, textColor: '#ffffff' },
177
+ error: { fill: colors.error, textColor: '#ffffff' },
178
+ ghost: { fill: 'transparent', textColor: colors.primary },
179
+ outline: { fill: 'transparent', textColor: colors.primary, stroke: colors.primary, strokeWidth: 2 }
180
+ };
181
+
182
+ const sizeProps = sizeConfig[size] || sizeConfig.md;
183
+ const variantProps = variantConfig[variant] || variantConfig.primary;
184
+
185
+ return {
186
+ type: 'box',
187
+ width: 'auto',
188
+ height: sizeProps.height,
189
+ fill: variantProps.fill,
190
+ stroke: variantProps.stroke || undefined,
191
+ strokeWidth: variantProps.strokeWidth || undefined,
192
+ cornerRadius: borderRadius.md,
193
+ shadow: shadows.md,
194
+ children: [
195
+ {
196
+ type: 'text',
197
+ text: text,
198
+ fill: variantProps.textColor,
199
+ fontSize: sizeProps.fontSize,
200
+ fontWeight: typography.fontWeight.medium,
201
+ fontFamily: typography.fontFamily,
202
+ textAlign: 'center',
203
+ verticalAlign: 'middle'
204
+ }
205
+ ]
206
+ };
207
+ }
208
+
209
+ /**
210
+ * 生成输入框组件
211
+ */
212
+ generateInput(placeholder = '请输入...', width = 240) {
213
+ const { colors, typography, spacing, borderRadius } = this.config;
214
+
215
+ return {
216
+ type: 'box',
217
+ width: width,
218
+ height: 40,
219
+ fill: '#ffffff',
220
+ stroke: colors.gray[300],
221
+ strokeWidth: 1,
222
+ cornerRadius: borderRadius.md,
223
+ children: [
224
+ {
225
+ type: 'text',
226
+ x: spacing[3],
227
+ y: 12,
228
+ text: placeholder,
229
+ fill: colors.gray[400],
230
+ fontSize: typography.fontSize.base,
231
+ fontFamily: typography.fontFamily
232
+ }
233
+ ]
234
+ };
235
+ }
236
+
237
+ /**
238
+ * 生成卡片组件
239
+ */
240
+ generateCard(title = 'Card Title', content = 'Card content goes here...') {
241
+ const { colors, typography, spacing, borderRadius, shadows } = this.config;
242
+
243
+ return {
244
+ type: 'box',
245
+ width: 320,
246
+ height: 'auto',
247
+ fill: '#ffffff',
248
+ cornerRadius: borderRadius.lg,
249
+ shadow: shadows.lg,
250
+ padding: spacing[6],
251
+ children: [
252
+ {
253
+ type: 'text',
254
+ text: title,
255
+ fill: colors.gray[900],
256
+ fontSize: typography.fontSize.lg,
257
+ fontWeight: typography.fontWeight.semibold,
258
+ fontFamily: typography.fontFamily,
259
+ marginBottom: spacing[3]
260
+ },
261
+ {
262
+ type: 'text',
263
+ text: content,
264
+ fill: colors.gray[600],
265
+ fontSize: typography.fontSize.base,
266
+ fontFamily: typography.fontFamily,
267
+ lineHeight: typography.lineHeight.relaxed
268
+ }
269
+ ]
270
+ };
271
+ }
272
+
273
+ /**
274
+ * 生成徽章组件
275
+ */
276
+ generateBadge(text = 'Badge', color = 'primary') {
277
+ const { colors, typography, spacing, borderRadius } = this.config;
278
+
279
+ const colorMap = {
280
+ primary: colors.primary,
281
+ success: colors.success,
282
+ warning: colors.warning,
283
+ error: colors.error,
284
+ info: colors.info
285
+ };
286
+
287
+ return {
288
+ type: 'box',
289
+ height: 24,
290
+ fill: colorMap[color] || colorMap.primary,
291
+ cornerRadius: borderRadius.full,
292
+ padding: [spacing[1], spacing[3]],
293
+ children: [
294
+ {
295
+ type: 'text',
296
+ text: text,
297
+ fill: '#ffffff',
298
+ fontSize: typography.fontSize.xs,
299
+ fontWeight: typography.fontWeight.medium,
300
+ fontFamily: typography.fontFamily
301
+ }
302
+ ]
303
+ };
304
+ }
305
+
306
+ /**
307
+ * 生成头像组件
308
+ */
309
+ generateAvatar(name = 'User', size = 'md') {
310
+ const { colors, typography } = this.config;
311
+
312
+ const sizeMap = {
313
+ sm: 32,
314
+ md: 40,
315
+ lg: 48,
316
+ xl: 64
317
+ };
318
+
319
+ const sizeValue = sizeMap[size] || sizeMap.md;
320
+ const initial = name.charAt(0).toUpperCase();
321
+
322
+ return {
323
+ type: 'ellipse',
324
+ width: sizeValue,
325
+ height: sizeValue,
326
+ fill: colors.primary,
327
+ children: [
328
+ {
329
+ type: 'text',
330
+ text: initial,
331
+ fill: '#ffffff',
332
+ fontSize: sizeValue * 0.4,
333
+ fontWeight: typography.fontWeight.bold,
334
+ fontFamily: typography.fontFamily,
335
+ textAlign: 'center',
336
+ verticalAlign: 'middle'
337
+ }
338
+ ]
339
+ };
340
+ }
341
+
342
+ /**
343
+ * 生成进度条组件
344
+ */
345
+ generateProgress(progress = 65, width = 200) {
346
+ const { colors, borderRadius } = this.config;
347
+ const height = 8;
348
+
349
+ return {
350
+ type: 'group',
351
+ width: width,
352
+ height: height,
353
+ children: [
354
+ // 背景
355
+ {
356
+ type: 'rect',
357
+ width: width,
358
+ height: height,
359
+ fill: colors.gray[200],
360
+ cornerRadius: borderRadius.full
361
+ },
362
+ // 进度
363
+ {
364
+ type: 'rect',
365
+ width: width * (progress / 100),
366
+ height: height,
367
+ fill: progress >= 100 ? colors.success : colors.primary,
368
+ cornerRadius: borderRadius.full
369
+ }
370
+ ]
371
+ };
372
+ }
373
+
374
+ /**
375
+ * 生成所有组件示例
376
+ */
377
+ generateAllComponents() {
378
+ return {
379
+ buttons: {
380
+ primary: this.generateButton('primary', 'md', 'Primary'),
381
+ secondary: this.generateButton('secondary', 'md', 'Secondary'),
382
+ success: this.generateButton('success', 'md', 'Success'),
383
+ warning: this.generateButton('warning', 'md', 'Warning'),
384
+ error: this.generateButton('error', 'md', 'Error'),
385
+ ghost: this.generateButton('ghost', 'md', 'Ghost'),
386
+ outline: this.generateButton('outline', 'md', 'Outline')
387
+ },
388
+ inputs: {
389
+ default: this.generateInput('请输入内容...'),
390
+ search: this.generateInput('搜索...', 300)
391
+ },
392
+ cards: {
393
+ default: this.generateCard(),
394
+ feature: this.generateCard('功能特性', '这是一个功能特性卡片,展示产品的主要功能点。')
395
+ },
396
+ badges: {
397
+ primary: this.generateBadge('Primary', 'primary'),
398
+ success: this.generateBadge('Success', 'success'),
399
+ warning: this.generateBadge('Warning', 'warning'),
400
+ error: this.generateBadge('Error', 'error')
401
+ },
402
+ avatars: {
403
+ sm: this.generateAvatar('张三', 'sm'),
404
+ md: this.generateAvatar('李四', 'md'),
405
+ lg: this.generateAvatar('王五', 'lg')
406
+ },
407
+ progress: {
408
+ low: this.generateProgress(25),
409
+ medium: this.generateProgress(50),
410
+ high: this.generateProgress(75),
411
+ complete: this.generateProgress(100)
412
+ }
413
+ };
414
+ }
415
+ }
416
+
417
+ /**
418
+ * 页面模板生成器
419
+ */
420
+ class PageTemplateGenerator {
421
+ constructor(config, componentGenerator) {
422
+ this.config = config;
423
+ this.components = componentGenerator;
424
+ }
425
+
426
+ /**
427
+ * 生成登录页面
428
+ */
429
+ generateLoginPage() {
430
+ const { colors, typography, spacing, borderRadius, shadows } = this.config;
431
+
432
+ return {
433
+ width: 800,
434
+ height: 600,
435
+ backgroundColor: colors.gray[100],
436
+ elements: [
437
+ // 背景装饰
438
+ {
439
+ type: 'ellipse',
440
+ x: -100, y: -100,
441
+ width: 400, height: 400,
442
+ fill: { type: 'radial', stops: [colors.primary + '20', colors.primary + '00'] }
443
+ },
444
+ {
445
+ type: 'ellipse',
446
+ x: 500, y: 300,
447
+ width: 500, height: 500,
448
+ fill: { type: 'radial', stops: [colors.secondary + '20', colors.secondary + '00'] }
449
+ },
450
+ // 登录卡片
451
+ {
452
+ type: 'box',
453
+ x: 200, y: 100,
454
+ width: 400, height: 400,
455
+ fill: '#ffffff',
456
+ cornerRadius: borderRadius['2xl'],
457
+ shadow: shadows.xl,
458
+ children: [
459
+ // 标题
460
+ {
461
+ type: 'text',
462
+ x: 40, y: 40,
463
+ text: '欢迎登录',
464
+ fill: colors.gray[900],
465
+ fontSize: typography.fontSize['3xl'],
466
+ fontWeight: typography.fontWeight.bold,
467
+ fontFamily: typography.fontFamily
468
+ },
469
+ // 副标题
470
+ {
471
+ type: 'text',
472
+ x: 40, y: 85,
473
+ text: '请输入您的账号和密码',
474
+ fill: colors.gray[500],
475
+ fontSize: typography.fontSize.base,
476
+ fontFamily: typography.fontFamily
477
+ },
478
+ // 用户名输入框
479
+ {
480
+ type: 'box',
481
+ x: 40, y: 130,
482
+ width: 320, height: 48,
483
+ fill: '#ffffff',
484
+ stroke: colors.gray[300],
485
+ strokeWidth: 1,
486
+ cornerRadius: borderRadius.lg,
487
+ children: [
488
+ {
489
+ type: 'text',
490
+ x: 16, y: 16,
491
+ text: '用户名',
492
+ fill: colors.gray[400],
493
+ fontSize: typography.fontSize.base,
494
+ fontFamily: typography.fontFamily
495
+ }
496
+ ]
497
+ },
498
+ // 密码输入框
499
+ {
500
+ type: 'box',
501
+ x: 40, y: 190,
502
+ width: 320, height: 48,
503
+ fill: '#ffffff',
504
+ stroke: colors.gray[300],
505
+ strokeWidth: 1,
506
+ cornerRadius: borderRadius.lg,
507
+ children: [
508
+ {
509
+ type: 'text',
510
+ x: 16, y: 16,
511
+ text: '密码',
512
+ fill: colors.gray[400],
513
+ fontSize: typography.fontSize.base,
514
+ fontFamily: typography.fontFamily
515
+ }
516
+ ]
517
+ },
518
+ // 登录按钮
519
+ {
520
+ type: 'box',
521
+ x: 40, y: 260,
522
+ width: 320, height: 48,
523
+ fill: colors.primary,
524
+ cornerRadius: borderRadius.lg,
525
+ shadow: shadows.md,
526
+ children: [
527
+ {
528
+ type: 'text',
529
+ x: 160, y: 16,
530
+ text: '登录',
531
+ fill: '#ffffff',
532
+ fontSize: typography.fontSize.base,
533
+ fontWeight: typography.fontWeight.semibold,
534
+ fontFamily: typography.fontFamily,
535
+ textAlign: 'center'
536
+ }
537
+ ]
538
+ },
539
+ // 注册链接
540
+ {
541
+ type: 'text',
542
+ x: 160, y: 330,
543
+ text: '还没有账号?立即注册',
544
+ fill: colors.primary,
545
+ fontSize: typography.fontSize.sm,
546
+ fontFamily: typography.fontFamily,
547
+ textAlign: 'center'
548
+ }
549
+ ]
550
+ }
551
+ ]
552
+ };
553
+ }
554
+
555
+ /**
556
+ * 生成 Dashboard 页面
557
+ */
558
+ generateDashboardPage() {
559
+ const { colors, typography, spacing, borderRadius, shadows } = this.config;
560
+
561
+ return {
562
+ width: 1200,
563
+ height: 800,
564
+ backgroundColor: colors.gray[50],
565
+ elements: [
566
+ // 侧边栏
567
+ {
568
+ type: 'box',
569
+ x: 0, y: 0,
570
+ width: 240, height: 800,
571
+ fill: '#ffffff',
572
+ shadow: shadows.md,
573
+ children: [
574
+ // Logo
575
+ {
576
+ type: 'text',
577
+ x: 24, y: 24,
578
+ text: 'Dashboard',
579
+ fill: colors.gray[900],
580
+ fontSize: typography.fontSize.xl,
581
+ fontWeight: typography.fontWeight.bold,
582
+ fontFamily: typography.fontFamily
583
+ },
584
+ // 菜单项
585
+ ...['概览', '分析', '用户', '设置'].map((item, index) => ({
586
+ type: 'box',
587
+ x: 16, y: 80 + index * 48,
588
+ width: 208, height: 40,
589
+ fill: index === 0 ? colors.primary + '15' : 'transparent',
590
+ cornerRadius: borderRadius.md,
591
+ children: [
592
+ {
593
+ type: 'text',
594
+ x: 16, y: 12,
595
+ text: item,
596
+ fill: index === 0 ? colors.primary : colors.gray[600],
597
+ fontSize: typography.fontSize.base,
598
+ fontWeight: index === 0 ? typography.fontWeight.medium : typography.fontWeight.normal,
599
+ fontFamily: typography.fontFamily
600
+ }
601
+ ]
602
+ }))
603
+ ]
604
+ },
605
+ // 顶部栏
606
+ {
607
+ type: 'box',
608
+ x: 240, y: 0,
609
+ width: 960, height: 64,
610
+ fill: '#ffffff',
611
+ shadow: shadows.sm,
612
+ children: [
613
+ // 搜索框
614
+ {
615
+ type: 'box',
616
+ x: 24, y: 12,
617
+ width: 320, height: 40,
618
+ fill: colors.gray[100],
619
+ cornerRadius: borderRadius.md,
620
+ children: [
621
+ {
622
+ type: 'text',
623
+ x: 16, y: 12,
624
+ text: '搜索...',
625
+ fill: colors.gray[400],
626
+ fontSize: typography.fontSize.sm,
627
+ fontFamily: typography.fontFamily
628
+ }
629
+ ]
630
+ },
631
+ // 头像
632
+ {
633
+ type: 'ellipse',
634
+ x: 880, y: 12,
635
+ width: 40, height: 40,
636
+ fill: colors.primary
637
+ }
638
+ ]
639
+ },
640
+ // 统计卡片
641
+ ...[
642
+ { title: '总用户', value: '12,345', change: '+12%', color: colors.primary },
643
+ { title: '活跃用户', value: '8,234', change: '+8%', color: colors.success },
644
+ { title: '收入', value: '¥45,678', change: '+23%', color: colors.warning },
645
+ { title: '转化率', value: '3.45%', change: '-2%', color: colors.error }
646
+ ].map((stat, index) => ({
647
+ type: 'box',
648
+ x: 280 + (index % 4) * 220, y: 100 + Math.floor(index / 4) * 140,
649
+ width: 200, height: 120,
650
+ fill: '#ffffff',
651
+ cornerRadius: borderRadius.lg,
652
+ shadow: shadows.md,
653
+ children: [
654
+ {
655
+ type: 'text',
656
+ x: 20, y: 20,
657
+ text: stat.title,
658
+ fill: colors.gray[500],
659
+ fontSize: typography.fontSize.sm,
660
+ fontFamily: typography.fontFamily
661
+ },
662
+ {
663
+ type: 'text',
664
+ x: 20, y: 50,
665
+ text: stat.value,
666
+ fill: colors.gray[900],
667
+ fontSize: typography.fontSize['2xl'],
668
+ fontWeight: typography.fontWeight.bold,
669
+ fontFamily: typography.fontFamily
670
+ },
671
+ {
672
+ type: 'box',
673
+ x: 20, y: 85,
674
+ width: 60, height: 24,
675
+ fill: stat.change.startsWith('+') ? colors.success + '20' : colors.error + '20',
676
+ cornerRadius: borderRadius.full,
677
+ children: [
678
+ {
679
+ type: 'text',
680
+ x: 30, y: 6,
681
+ text: stat.change,
682
+ fill: stat.change.startsWith('+') ? colors.success : colors.error,
683
+ fontSize: typography.fontSize.xs,
684
+ fontWeight: typography.fontWeight.medium,
685
+ fontFamily: typography.fontFamily,
686
+ textAlign: 'center'
687
+ }
688
+ ]
689
+ }
690
+ ]
691
+ })),
692
+ // 图表区域
693
+ {
694
+ type: 'box',
695
+ x: 280, y: 260,
696
+ width: 640, height: 300,
697
+ fill: '#ffffff',
698
+ cornerRadius: borderRadius.lg,
699
+ shadow: shadows.md,
700
+ children: [
701
+ {
702
+ type: 'text',
703
+ x: 24, y: 24,
704
+ text: '访问趋势',
705
+ fill: colors.gray[900],
706
+ fontSize: typography.fontSize.lg,
707
+ fontWeight: typography.fontWeight.semibold,
708
+ fontFamily: typography.fontFamily
709
+ },
710
+ // 模拟图表柱状图
711
+ ...[65, 45, 80, 55, 90, 70, 85].map((value, index) => ({
712
+ type: 'rect',
713
+ x: 60 + index * 80, y: 250 - value * 2,
714
+ width: 40, height: value * 2,
715
+ fill: colors.primary,
716
+ cornerRadius: [4, 4, 0, 0]
717
+ }))
718
+ ]
719
+ }
720
+ ]
721
+ };
722
+ }
723
+
724
+ /**
725
+ * 生成组件展示页面
726
+ */
727
+ generateComponentShowcase() {
728
+ const { colors, typography, spacing, borderRadius, shadows } = this.config;
729
+ const allComponents = this.components.generateAllComponents();
730
+
731
+ return {
732
+ width: 1200,
733
+ height: 1600,
734
+ backgroundColor: colors.gray[50],
735
+ elements: [
736
+ // 页面标题
737
+ {
738
+ type: 'box',
739
+ x: 0, y: 0,
740
+ width: 1200, height: 120,
741
+ fill: '#ffffff',
742
+ shadow: shadows.sm,
743
+ children: [
744
+ {
745
+ type: 'text',
746
+ x: 60, y: 40,
747
+ text: this.config.name,
748
+ fill: colors.gray[900],
749
+ fontSize: typography.fontSize['3xl'],
750
+ fontWeight: typography.fontWeight.bold,
751
+ fontFamily: typography.fontFamily
752
+ },
753
+ {
754
+ type: 'text',
755
+ x: 60, y: 80,
756
+ text: `版本 ${this.config.version} | 组件库展示`,
757
+ fill: colors.gray[500],
758
+ fontSize: typography.fontSize.base,
759
+ fontFamily: typography.fontFamily
760
+ }
761
+ ]
762
+ },
763
+
764
+ // 按钮组件展示
765
+ {
766
+ type: 'box',
767
+ x: 60, y: 160,
768
+ width: 1100, height: 200,
769
+ fill: '#ffffff',
770
+ cornerRadius: borderRadius.lg,
771
+ shadow: shadows.md,
772
+ children: [
773
+ {
774
+ type: 'text',
775
+ x: 30, y: 30,
776
+ text: '按钮组件 (Buttons)',
777
+ fill: colors.gray[900],
778
+ fontSize: typography.fontSize.xl,
779
+ fontWeight: typography.fontWeight.semibold,
780
+ fontFamily: typography.fontFamily
781
+ },
782
+ // 按钮示例
783
+ ...Object.entries(allComponents.buttons).map(([name, config], index) => ({
784
+ type: 'box',
785
+ x: 30 + (index % 4) * 260, y: 80 + Math.floor(index / 4) * 60,
786
+ width: 100, height: 40,
787
+ fill: config.fill,
788
+ stroke: config.stroke,
789
+ strokeWidth: config.strokeWidth,
790
+ cornerRadius: config.cornerRadius,
791
+ shadow: config.shadow,
792
+ children: [
793
+ {
794
+ type: 'text',
795
+ x: 50, y: 12,
796
+ text: name.charAt(0).toUpperCase() + name.slice(1),
797
+ fill: config.children[0].fill,
798
+ fontSize: 14,
799
+ fontWeight: 500,
800
+ fontFamily: typography.fontFamily,
801
+ textAlign: 'center'
802
+ }
803
+ ]
804
+ }))
805
+ ]
806
+ },
807
+
808
+ // 输入框组件展示
809
+ {
810
+ type: 'box',
811
+ x: 60, y: 390,
812
+ width: 540, height: 200,
813
+ fill: '#ffffff',
814
+ cornerRadius: borderRadius.lg,
815
+ shadow: shadows.md,
816
+ children: [
817
+ {
818
+ type: 'text',
819
+ x: 30, y: 30,
820
+ text: '输入框组件 (Inputs)',
821
+ fill: colors.gray[900],
822
+ fontSize: typography.fontSize.xl,
823
+ fontWeight: typography.fontWeight.semibold,
824
+ fontFamily: typography.fontFamily
825
+ },
826
+ {
827
+ type: 'box',
828
+ x: 30, y: 80,
829
+ width: 240, height: 48,
830
+ fill: '#ffffff',
831
+ stroke: colors.gray[300],
832
+ strokeWidth: 1,
833
+ cornerRadius: borderRadius.md,
834
+ children: [
835
+ {
836
+ type: 'text',
837
+ x: 16, y: 16,
838
+ text: '请输入内容...',
839
+ fill: colors.gray[400],
840
+ fontSize: typography.fontSize.base,
841
+ fontFamily: typography.fontFamily
842
+ }
843
+ ]
844
+ }
845
+ ]
846
+ },
847
+
848
+ // 卡片组件展示
849
+ {
850
+ type: 'box',
851
+ x: 620, y: 390,
852
+ width: 540, height: 200,
853
+ fill: '#ffffff',
854
+ cornerRadius: borderRadius.lg,
855
+ shadow: shadows.md,
856
+ children: [
857
+ {
858
+ type: 'text',
859
+ x: 30, y: 30,
860
+ text: '卡片组件 (Cards)',
861
+ fill: colors.gray[900],
862
+ fontSize: typography.fontSize.xl,
863
+ fontWeight: typography.fontWeight.semibold,
864
+ fontFamily: typography.fontFamily
865
+ },
866
+ {
867
+ type: 'box',
868
+ x: 30, y: 70,
869
+ width: 320, height: 100,
870
+ fill: '#ffffff',
871
+ stroke: colors.gray[200],
872
+ strokeWidth: 1,
873
+ cornerRadius: borderRadius.lg,
874
+ shadow: shadows.sm,
875
+ children: [
876
+ {
877
+ type: 'text',
878
+ x: 20, y: 20,
879
+ text: '卡片标题',
880
+ fill: colors.gray[900],
881
+ fontSize: typography.fontSize.lg,
882
+ fontWeight: typography.fontWeight.semibold,
883
+ fontFamily: typography.fontFamily
884
+ },
885
+ {
886
+ type: 'text',
887
+ x: 20, y: 50,
888
+ text: '这是卡片的内容描述...',
889
+ fill: colors.gray[600],
890
+ fontSize: typography.fontSize.base,
891
+ fontFamily: typography.fontFamily
892
+ }
893
+ ]
894
+ }
895
+ ]
896
+ },
897
+
898
+ // 徽章组件展示
899
+ {
900
+ type: 'box',
901
+ x: 60, y: 620,
902
+ width: 540, height: 150,
903
+ fill: '#ffffff',
904
+ cornerRadius: borderRadius.lg,
905
+ shadow: shadows.md,
906
+ children: [
907
+ {
908
+ type: 'text',
909
+ x: 30, y: 30,
910
+ text: '徽章组件 (Badges)',
911
+ fill: colors.gray[900],
912
+ fontSize: typography.fontSize.xl,
913
+ fontWeight: typography.fontWeight.semibold,
914
+ fontFamily: typography.fontFamily
915
+ },
916
+ // 徽章示例
917
+ ...[
918
+ { text: 'Primary', color: colors.primary },
919
+ { text: 'Success', color: colors.success },
920
+ { text: 'Warning', color: colors.warning },
921
+ { text: 'Error', color: colors.error }
922
+ ].map((badge, index) => ({
923
+ type: 'box',
924
+ x: 30 + index * 120, y: 80,
925
+ width: 80, height: 28,
926
+ fill: badge.color,
927
+ cornerRadius: borderRadius.full,
928
+ children: [
929
+ {
930
+ type: 'text',
931
+ x: 40, y: 7,
932
+ text: badge.text,
933
+ fill: '#ffffff',
934
+ fontSize: typography.fontSize.xs,
935
+ fontWeight: typography.fontWeight.medium,
936
+ fontFamily: typography.fontFamily,
937
+ textAlign: 'center'
938
+ }
939
+ ]
940
+ }))
941
+ ]
942
+ },
943
+
944
+ // 进度条组件展示
945
+ {
946
+ type: 'box',
947
+ x: 620, y: 620,
948
+ width: 540, height: 150,
949
+ fill: '#ffffff',
950
+ cornerRadius: borderRadius.lg,
951
+ shadow: shadows.md,
952
+ children: [
953
+ {
954
+ type: 'text',
955
+ x: 30, y: 30,
956
+ text: '进度条组件 (Progress)',
957
+ fill: colors.gray[900],
958
+ fontSize: typography.fontSize.xl,
959
+ fontWeight: typography.fontWeight.semibold,
960
+ fontFamily: typography.fontFamily
961
+ },
962
+ // 进度条背景
963
+ {
964
+ type: 'rect',
965
+ x: 30, y: 70,
966
+ width: 200, height: 8,
967
+ fill: colors.gray[200],
968
+ cornerRadius: borderRadius.full
969
+ },
970
+ // 进度条填充
971
+ {
972
+ type: 'rect',
973
+ x: 30, y: 70,
974
+ width: 130, height: 8,
975
+ fill: colors.primary,
976
+ cornerRadius: borderRadius.full
977
+ },
978
+ {
979
+ type: 'text',
980
+ x: 240, y: 68,
981
+ text: '65%',
982
+ fill: colors.gray[600],
983
+ fontSize: typography.fontSize.sm,
984
+ fontFamily: typography.fontFamily
985
+ }
986
+ ]
987
+ }
988
+ ]
989
+ };
990
+ }
991
+ }
992
+
993
+ /**
994
+ * 主生成器类
995
+ */
996
+ class DesignSystemGenerator {
997
+ constructor(options = {}) {
998
+ this.config = new DesignSystemConfig(options);
999
+ this.components = new ComponentGenerator(this.config);
1000
+ this.templates = new PageTemplateGenerator(this.config, this.components);
1001
+ }
1002
+
1003
+ /**
1004
+ * 生成完整的设计系统
1005
+ */
1006
+ generate(options = {}) {
1007
+ const output = {
1008
+ config: this.config.toJSON(),
1009
+ components: this.components.generateAllComponents(),
1010
+ templates: {}
1011
+ };
1012
+
1013
+ // 生成页面模板
1014
+ if (options.includeLogin !== false) {
1015
+ output.templates.login = this.templates.generateLoginPage();
1016
+ }
1017
+
1018
+ if (options.includeDashboard !== false) {
1019
+ output.templates.dashboard = this.templates.generateDashboardPage();
1020
+ }
1021
+
1022
+ if (options.includeShowcase !== false) {
1023
+ output.templates.showcase = this.templates.generateComponentShowcase();
1024
+ }
1025
+
1026
+ return output;
1027
+ }
1028
+
1029
+ /**
1030
+ * 导出为文件
1031
+ */
1032
+ export(outputDir = './design-system') {
1033
+ // 创建输出目录
1034
+ if (!fs.existsSync(outputDir)) {
1035
+ fs.mkdirSync(outputDir, { recursive: true });
1036
+ }
1037
+
1038
+ // 生成设计系统
1039
+ const designSystem = this.generate();
1040
+
1041
+ // 保存配置文件
1042
+ this.config.save(outputDir);
1043
+
1044
+ // 保存组件库
1045
+ const componentsPath = path.join(outputDir, 'components.json');
1046
+ fs.writeFileSync(componentsPath, JSON.stringify(designSystem.components, null, 2));
1047
+ console.log(`[Design System] Components saved to: ${componentsPath}`);
1048
+
1049
+ // 保存模板
1050
+ const templatesDir = path.join(outputDir, 'templates');
1051
+ if (!fs.existsSync(templatesDir)) {
1052
+ fs.mkdirSync(templatesDir, { recursive: true });
1053
+ }
1054
+
1055
+ Object.entries(designSystem.templates).forEach(([name, template]) => {
1056
+ const templatePath = path.join(templatesDir, `${name}.json`);
1057
+ fs.writeFileSync(templatePath, JSON.stringify(template, null, 2));
1058
+ console.log(`[Design System] Template "${name}" saved to: ${templatePath}`);
1059
+ });
1060
+
1061
+ console.log(`\n✅ Design system generated successfully at: ${outputDir}`);
1062
+ return designSystem;
1063
+ }
1064
+
1065
+ /**
1066
+ * 渲染模板为图片(通过 MCP 服务)
1067
+ */
1068
+ async renderTemplate(templateName, mcpServiceUrl = 'http://localhost:3001') {
1069
+ const template = this.templates[`generate${templateName.charAt(0).toUpperCase() + templateName.slice(1)}Page`]?.();
1070
+
1071
+ if (!template) {
1072
+ throw new Error(`Template "${templateName}" not found`);
1073
+ }
1074
+
1075
+ // 这里可以通过 HTTP 请求发送到 MCP 服务进行渲染
1076
+ // 返回渲染后的图片 URL
1077
+ return {
1078
+ template: templateName,
1079
+ data: template,
1080
+ renderUrl: `${mcpServiceUrl}/api/v1/ui/render`
1081
+ };
1082
+ }
1083
+ }
1084
+
1085
+ // 导出模块
1086
+ module.exports = {
1087
+ DesignSystemGenerator,
1088
+ DesignSystemConfig,
1089
+ ComponentGenerator,
1090
+ PageTemplateGenerator
1091
+ };
1092
+
1093
+ // CLI 支持
1094
+ if (require.main === module) {
1095
+ const generator = new DesignSystemGenerator({
1096
+ name: 'My Awesome Design System',
1097
+ primaryColor: '#667eea',
1098
+ secondaryColor: '#764ba2'
1099
+ });
1100
+
1101
+ generator.export('./my-design-system');
1102
+ }