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,1194 @@
1
+ /**
2
+ * LeaferJS 设计系统生成器 Pro 版
3
+ *
4
+ * 增强功能:
5
+ * - 更多组件(表格、模态框、下拉菜单、标签页、开关、单选/复选框)
6
+ * - 暗黑模式支持
7
+ * - 响应式设计
8
+ * - 交互热点支持
9
+ */
10
+
11
+ const fs = require('fs');
12
+ const path = require('path');
13
+
14
+ /**
15
+ * 主题配置类 - 支持亮色/暗色模式
16
+ */
17
+ class ThemeConfig {
18
+ constructor(options = {}) {
19
+ this.mode = options.mode || 'light';
20
+ this.name = options.name || 'My Design System';
21
+
22
+ // 基础颜色配置
23
+ this.colors = {
24
+ light: {
25
+ primary: options.primaryColor || '#667eea',
26
+ secondary: options.secondaryColor || '#764ba2',
27
+ success: '#48bb78',
28
+ warning: '#ed8936',
29
+ error: '#f56565',
30
+ info: '#4299e1',
31
+ background: '#ffffff',
32
+ surface: '#f9fafb',
33
+ border: '#e5e7eb',
34
+ text: {
35
+ primary: '#111827',
36
+ secondary: '#6b7280',
37
+ disabled: '#9ca3af',
38
+ inverse: '#ffffff'
39
+ }
40
+ },
41
+ dark: {
42
+ primary: '#818cf8',
43
+ secondary: '#a78bfa',
44
+ success: '#34d399',
45
+ warning: '#fbbf24',
46
+ error: '#f87171',
47
+ info: '#60a5fa',
48
+ background: '#111827',
49
+ surface: '#1f2937',
50
+ border: '#374151',
51
+ text: {
52
+ primary: '#f9fafb',
53
+ secondary: '#d1d5db',
54
+ disabled: '#6b7280',
55
+ inverse: '#111827'
56
+ }
57
+ }
58
+ };
59
+
60
+ // 字体配置
61
+ this.typography = {
62
+ fontFamily: options.fontFamily || 'Microsoft YaHei',
63
+ fontSize: {
64
+ xs: 12, sm: 14, base: 16, lg: 18, xl: 20,
65
+ '2xl': 24, '3xl': 30, '4xl': 36
66
+ },
67
+ fontWeight: {
68
+ light: 300, normal: 400, medium: 500,
69
+ semibold: 600, bold: 700
70
+ }
71
+ };
72
+
73
+ // 间距配置
74
+ this.spacing = {
75
+ 0: 0, 1: 4, 2: 8, 3: 12, 4: 16, 5: 20,
76
+ 6: 24, 8: 32, 10: 40, 12: 48, 16: 64
77
+ };
78
+
79
+ // 圆角配置
80
+ this.borderRadius = {
81
+ none: 0, sm: 2, md: 4, lg: 8, xl: 12, '2xl': 16, full: 9999
82
+ };
83
+
84
+ // 阴影配置
85
+ this.shadows = {
86
+ sm: { x: 0, y: 1, blur: 2, color: '#0000000d' },
87
+ md: { x: 0, y: 4, blur: 6, color: '#0000001a' },
88
+ lg: { x: 0, y: 10, blur: 15, color: '#00000026' },
89
+ xl: { x: 0, y: 20, blur: 25, color: '#00000026' }
90
+ };
91
+ }
92
+
93
+ getColors() {
94
+ return this.colors[this.mode];
95
+ }
96
+
97
+ setMode(mode) {
98
+ this.mode = mode;
99
+ }
100
+ }
101
+
102
+ /**
103
+ * 高级组件生成器
104
+ */
105
+ class AdvancedComponentGenerator {
106
+ constructor(config) {
107
+ this.config = config;
108
+ this.colors = config.getColors();
109
+ }
110
+
111
+ // 生成表格
112
+ generateTable(headers, rows, options = {}) {
113
+ const { width = 600, rowHeight = 40 } = options;
114
+ const colors = this.colors;
115
+
116
+ const elements = [];
117
+
118
+ // 表头背景
119
+ elements.push({
120
+ type: 'box',
121
+ x: 0, y: 0, width, height: rowHeight,
122
+ fill: colors.surface,
123
+ cornerRadius: { topLeft: 8, topRight: 8 }
124
+ });
125
+
126
+ // 表头文字
127
+ const colWidth = width / headers.length;
128
+ headers.forEach((header, i) => {
129
+ elements.push({
130
+ type: 'text',
131
+ x: i * colWidth + 16,
132
+ y: 12,
133
+ text: header,
134
+ fill: colors.text.primary,
135
+ fontSize: 14,
136
+ fontWeight: 600,
137
+ fontFamily: this.config.typography.fontFamily
138
+ });
139
+ });
140
+
141
+ // 数据行
142
+ rows.forEach((row, rowIndex) => {
143
+ const y = (rowIndex + 1) * rowHeight;
144
+ const isEven = rowIndex % 2 === 0;
145
+
146
+ // 行背景
147
+ elements.push({
148
+ type: 'box',
149
+ x: 0, y, width, height: rowHeight,
150
+ fill: isEven ? colors.background : colors.surface
151
+ });
152
+
153
+ // 行数据
154
+ row.forEach((cell, cellIndex) => {
155
+ elements.push({
156
+ type: 'text',
157
+ x: cellIndex * colWidth + 16,
158
+ y: y + 12,
159
+ text: String(cell),
160
+ fill: colors.text.secondary,
161
+ fontSize: 14,
162
+ fontFamily: this.config.typography.fontFamily
163
+ });
164
+ });
165
+ });
166
+
167
+ // 底部边框
168
+ elements.push({
169
+ type: 'box',
170
+ x: 0, y: (rows.length + 1) * rowHeight - 1,
171
+ width, height: 1,
172
+ fill: colors.border
173
+ });
174
+
175
+ return {
176
+ type: 'group',
177
+ x: options.x || 0,
178
+ y: options.y || 0,
179
+ children: elements
180
+ };
181
+ }
182
+
183
+ // 生成模态框
184
+ generateModal(title, content, options = {}) {
185
+ const { width = 480 } = options;
186
+ const colors = this.colors;
187
+
188
+ return {
189
+ type: 'group',
190
+ x: options.x || 0,
191
+ y: options.y || 0,
192
+ children: [
193
+ // 遮罩层
194
+ {
195
+ type: 'rect',
196
+ x: -1000, y: -1000,
197
+ width: 3000, height: 3000,
198
+ fill: '#00000080'
199
+ },
200
+ // 模态框背景
201
+ {
202
+ type: 'box',
203
+ x: 0, y: 0, width, height: 200,
204
+ fill: colors.background,
205
+ cornerRadius: 12,
206
+ shadow: this.config.shadows.xl
207
+ },
208
+ // 标题
209
+ {
210
+ type: 'text',
211
+ x: 24, y: 20,
212
+ text: title,
213
+ fill: colors.text.primary,
214
+ fontSize: 18,
215
+ fontWeight: 600,
216
+ fontFamily: this.config.typography.fontFamily
217
+ },
218
+ // 关闭按钮
219
+ {
220
+ type: 'text',
221
+ x: width - 40, y: 20,
222
+ text: '✕',
223
+ fill: colors.text.secondary,
224
+ fontSize: 20
225
+ },
226
+ // 分隔线
227
+ {
228
+ type: 'rect',
229
+ x: 0, y: 56, width, height: 1,
230
+ fill: colors.border
231
+ },
232
+ // 内容
233
+ {
234
+ type: 'text',
235
+ x: 24, y: 76,
236
+ text: content,
237
+ fill: colors.text.secondary,
238
+ fontSize: 14,
239
+ fontFamily: this.config.typography.fontFamily
240
+ },
241
+ // 按钮组
242
+ {
243
+ type: 'box',
244
+ x: width - 180, y: 140,
245
+ width: 80, height: 36,
246
+ fill: colors.surface,
247
+ cornerRadius: 6,
248
+ children: [{
249
+ type: 'text',
250
+ x: 24, y: 10,
251
+ text: '取消',
252
+ fill: colors.text.secondary,
253
+ fontSize: 14,
254
+ fontFamily: this.config.typography.fontFamily
255
+ }]
256
+ },
257
+ {
258
+ type: 'box',
259
+ x: width - 90, y: 140,
260
+ width: 70, height: 36,
261
+ fill: colors.primary,
262
+ cornerRadius: 6,
263
+ children: [{
264
+ type: 'text',
265
+ x: 24, y: 10,
266
+ text: '确认',
267
+ fill: colors.text.inverse,
268
+ fontSize: 14,
269
+ fontFamily: this.config.typography.fontFamily
270
+ }]
271
+ }
272
+ ]
273
+ };
274
+ }
275
+
276
+ // 生成下拉菜单
277
+ generateDropdown(label, items, options = {}) {
278
+ const { width = 200 } = options;
279
+ const colors = this.colors;
280
+ const itemHeight = 36;
281
+
282
+ const children = [
283
+ // 触发按钮
284
+ {
285
+ type: 'box',
286
+ x: 0, y: 0, width, height: 40,
287
+ fill: colors.background,
288
+ stroke: colors.border,
289
+ strokeWidth: 1,
290
+ cornerRadius: 6,
291
+ children: [
292
+ {
293
+ type: 'text',
294
+ x: 12, y: 12,
295
+ text: label,
296
+ fill: colors.text.primary,
297
+ fontSize: 14,
298
+ fontFamily: this.config.typography.fontFamily
299
+ },
300
+ {
301
+ type: 'text',
302
+ x: width - 24, y: 12,
303
+ text: '▼',
304
+ fill: colors.text.secondary,
305
+ fontSize: 10
306
+ }
307
+ ]
308
+ }
309
+ ];
310
+
311
+ // 下拉列表
312
+ if (options.isOpen) {
313
+ children.push({
314
+ type: 'box',
315
+ x: 0, y: 44, width,
316
+ height: items.length * itemHeight + 8,
317
+ fill: colors.background,
318
+ cornerRadius: 6,
319
+ shadow: this.config.shadows.lg
320
+ });
321
+
322
+ items.forEach((item, i) => {
323
+ children.push({
324
+ type: 'box',
325
+ x: 4, y: 48 + i * itemHeight,
326
+ width: width - 8, height: itemHeight,
327
+ fill: item.selected ? colors.primary + '15' : colors.background,
328
+ cornerRadius: 4,
329
+ children: [{
330
+ type: 'text',
331
+ x: 12, y: 10,
332
+ text: item.label,
333
+ fill: item.selected ? colors.primary : colors.text.primary,
334
+ fontSize: 14,
335
+ fontFamily: this.config.typography.fontFamily
336
+ }]
337
+ });
338
+ });
339
+ }
340
+
341
+ return {
342
+ type: 'group',
343
+ x: options.x || 0,
344
+ y: options.y || 0,
345
+ children
346
+ };
347
+ }
348
+
349
+ // 生成标签页
350
+ generateTabs(tabs, activeIndex = 0, options = {}) {
351
+ const colors = this.colors;
352
+ const tabWidth = options.tabWidth || 100;
353
+ const height = 40;
354
+
355
+ const children = [];
356
+
357
+ tabs.forEach((tab, i) => {
358
+ const isActive = i === activeIndex;
359
+ const x = i * tabWidth;
360
+
361
+ // 标签背景
362
+ children.push({
363
+ type: 'box',
364
+ x, y: 0,
365
+ width: tabWidth, height,
366
+ fill: isActive ? colors.background : colors.surface,
367
+ children: [
368
+ {
369
+ type: 'text',
370
+ x: tabWidth / 2, y: 12,
371
+ text: tab,
372
+ fill: isActive ? colors.primary : colors.text.secondary,
373
+ fontSize: 14,
374
+ fontWeight: isActive ? 500 : 400,
375
+ fontFamily: this.config.typography.fontFamily,
376
+ textAlign: 'center'
377
+ }
378
+ ]
379
+ });
380
+
381
+ // 激活指示器
382
+ if (isActive) {
383
+ children.push({
384
+ type: 'rect',
385
+ x, y: height - 2,
386
+ width: tabWidth, height: 2,
387
+ fill: colors.primary
388
+ });
389
+ }
390
+ });
391
+
392
+ // 底部边框
393
+ children.push({
394
+ type: 'rect',
395
+ x: 0, y: height,
396
+ width: tabs.length * tabWidth, height: 1,
397
+ fill: colors.border
398
+ });
399
+
400
+ return {
401
+ type: 'group',
402
+ x: options.x || 0,
403
+ y: options.y || 0,
404
+ children
405
+ };
406
+ }
407
+
408
+ // 生成开关
409
+ generateSwitch(isOn = false, options = {}) {
410
+ const colors = this.colors;
411
+ const width = 44;
412
+ const height = 24;
413
+
414
+ return {
415
+ type: 'group',
416
+ x: options.x || 0,
417
+ y: options.y || 0,
418
+ children: [
419
+ // 轨道
420
+ {
421
+ type: 'box',
422
+ x: 0, y: 0, width, height,
423
+ fill: isOn ? colors.primary : colors.border,
424
+ cornerRadius: height / 2
425
+ },
426
+ // 滑块
427
+ {
428
+ type: 'ellipse',
429
+ x: isOn ? width - height + 2 : 2,
430
+ y: 2,
431
+ width: height - 4, height: height - 4,
432
+ fill: colors.background
433
+ }
434
+ ]
435
+ };
436
+ }
437
+
438
+ // 生成复选框
439
+ generateCheckbox(checked = false, label = '', options = {}) {
440
+ const colors = this.colors;
441
+ const size = 18;
442
+
443
+ const children = [
444
+ // 复选框
445
+ {
446
+ type: 'box',
447
+ x: 0, y: 0, width: size, height: size,
448
+ fill: checked ? colors.primary : colors.background,
449
+ stroke: checked ? colors.primary : colors.border,
450
+ strokeWidth: 2,
451
+ cornerRadius: 4
452
+ }
453
+ ];
454
+
455
+ // 勾选标记
456
+ if (checked) {
457
+ children.push({
458
+ type: 'text',
459
+ x: 4, y: 2,
460
+ text: '✓',
461
+ fill: colors.text.inverse,
462
+ fontSize: 12,
463
+ fontWeight: 'bold'
464
+ });
465
+ }
466
+
467
+ // 标签
468
+ if (label) {
469
+ children.push({
470
+ type: 'text',
471
+ x: size + 8, y: 2,
472
+ text: label,
473
+ fill: colors.text.primary,
474
+ fontSize: 14,
475
+ fontFamily: this.config.typography.fontFamily
476
+ });
477
+ }
478
+
479
+ return {
480
+ type: 'group',
481
+ x: options.x || 0,
482
+ y: options.y || 0,
483
+ children
484
+ };
485
+ }
486
+
487
+ // 生成单选按钮
488
+ generateRadio(selected = false, label = '', options = {}) {
489
+ const colors = this.colors;
490
+ const size = 18;
491
+
492
+ const children = [
493
+ // 外圆
494
+ {
495
+ type: 'ellipse',
496
+ x: 0, y: 0, width: size, height: size,
497
+ fill: colors.background,
498
+ stroke: selected ? colors.primary : colors.border,
499
+ strokeWidth: 2
500
+ }
501
+ ];
502
+
503
+ // 内圆(选中状态)
504
+ if (selected) {
505
+ children.push({
506
+ type: 'ellipse',
507
+ x: 5, y: 5,
508
+ width: size - 10, height: size - 10,
509
+ fill: colors.primary
510
+ });
511
+ }
512
+
513
+ // 标签
514
+ if (label) {
515
+ children.push({
516
+ type: 'text',
517
+ x: size + 8, y: 2,
518
+ text: label,
519
+ fill: colors.text.primary,
520
+ fontSize: 14,
521
+ fontFamily: this.config.typography.fontFamily
522
+ });
523
+ }
524
+
525
+ return {
526
+ type: 'group',
527
+ x: options.x || 0,
528
+ y: options.y || 0,
529
+ children
530
+ };
531
+ }
532
+ }
533
+
534
+ /**
535
+ * 响应式模板生成器
536
+ */
537
+ class ResponsiveTemplateGenerator {
538
+ constructor(config) {
539
+ this.config = config;
540
+ this.componentGen = new AdvancedComponentGenerator(config);
541
+ }
542
+
543
+ // 移动端登录页
544
+ generateMobileLoginPage() {
545
+ const colors = this.config.getColors();
546
+ const w = 375; // iPhone 宽度
547
+ const h = 812; // iPhone 高度
548
+
549
+ return {
550
+ width: w,
551
+ height: h,
552
+ backgroundColor: colors.background,
553
+ elements: [
554
+ // 状态栏
555
+ {
556
+ type: 'rect',
557
+ x: 0, y: 0, width: w, height: 44,
558
+ fill: colors.background
559
+ },
560
+ {
561
+ type: 'text',
562
+ x: w / 2, y: 14,
563
+ text: '9:41',
564
+ fill: colors.text.primary,
565
+ fontSize: 14,
566
+ fontWeight: 600,
567
+ textAlign: 'center'
568
+ },
569
+ // Logo区域
570
+ {
571
+ type: 'ellipse',
572
+ x: w / 2 - 40, y: 120,
573
+ width: 80, height: 80,
574
+ fill: { type: 'linear', stops: [colors.primary, colors.secondary] }
575
+ },
576
+ {
577
+ type: 'text',
578
+ x: w / 2, y: 220,
579
+ text: '欢迎回来',
580
+ fill: colors.text.primary,
581
+ fontSize: 24,
582
+ fontWeight: 700,
583
+ textAlign: 'center',
584
+ fontFamily: this.config.typography.fontFamily
585
+ },
586
+ // 输入框
587
+ {
588
+ type: 'box',
589
+ x: 24, y: 280, width: w - 48, height: 48,
590
+ fill: colors.surface,
591
+ cornerRadius: 8,
592
+ children: [{
593
+ type: 'text',
594
+ x: 16, y: 16,
595
+ text: '手机号/邮箱',
596
+ fill: colors.text.disabled,
597
+ fontSize: 14,
598
+ fontFamily: this.config.typography.fontFamily
599
+ }]
600
+ },
601
+ {
602
+ type: 'box',
603
+ x: 24, y: 340, width: w - 48, height: 48,
604
+ fill: colors.surface,
605
+ cornerRadius: 8,
606
+ children: [{
607
+ type: 'text',
608
+ x: 16, y: 16,
609
+ text: '密码',
610
+ fill: colors.text.disabled,
611
+ fontSize: 14,
612
+ fontFamily: this.config.typography.fontFamily
613
+ }]
614
+ },
615
+ // 登录按钮
616
+ {
617
+ type: 'box',
618
+ x: 24, y: 420, width: w - 48, height: 48,
619
+ fill: colors.primary,
620
+ cornerRadius: 8,
621
+ children: [{
622
+ type: 'text',
623
+ x: (w - 48) / 2, y: 16,
624
+ text: '登录',
625
+ fill: colors.text.inverse,
626
+ fontSize: 16,
627
+ fontWeight: 600,
628
+ textAlign: 'center',
629
+ fontFamily: this.config.typography.fontFamily
630
+ }]
631
+ },
632
+ // 其他登录方式
633
+ {
634
+ type: 'text',
635
+ x: w / 2, y: 500,
636
+ text: '其他登录方式',
637
+ fill: colors.text.secondary,
638
+ fontSize: 12,
639
+ textAlign: 'center',
640
+ fontFamily: this.config.typography.fontFamily
641
+ },
642
+ // 社交登录图标
643
+ {
644
+ type: 'ellipse',
645
+ x: w / 2 - 60, y: 540, width: 40, height: 40,
646
+ fill: '#07C160'
647
+ },
648
+ {
649
+ type: 'ellipse',
650
+ x: w / 2 - 20, y: 540, width: 40, height: 40,
651
+ fill: '#FA5151'
652
+ },
653
+ {
654
+ type: 'ellipse',
655
+ x: w / 2 + 20, y: 540, width: 40, height: 40,
656
+ fill: '#10AEFF'
657
+ },
658
+ // 底部导航栏
659
+ {
660
+ type: 'rect',
661
+ x: 0, y: h - 34, width: w, height: 34,
662
+ fill: colors.background
663
+ }
664
+ ]
665
+ };
666
+ }
667
+
668
+ // 移动端首页
669
+ generateMobileHomePage() {
670
+ const colors = this.config.getColors();
671
+ const w = 375;
672
+ const h = 812;
673
+
674
+ return {
675
+ width: w,
676
+ height: h,
677
+ backgroundColor: colors.surface,
678
+ elements: [
679
+ // 状态栏
680
+ { type: 'rect', x: 0, y: 0, width: w, height: 44, fill: colors.background },
681
+ // 搜索栏
682
+ {
683
+ type: 'box',
684
+ x: 16, y: 54, width: w - 32, height: 36,
685
+ fill: colors.surface,
686
+ cornerRadius: 18,
687
+ children: [{
688
+ type: 'text',
689
+ x: 40, y: 10,
690
+ text: '搜索商品、品牌',
691
+ fill: colors.text.disabled,
692
+ fontSize: 14,
693
+ fontFamily: this.config.typography.fontFamily
694
+ }]
695
+ },
696
+ // Banner
697
+ {
698
+ type: 'box',
699
+ x: 16, y: 102, width: w - 32, height: 120,
700
+ fill: { type: 'linear', stops: [colors.primary, colors.secondary] },
701
+ cornerRadius: 12
702
+ },
703
+ // 分类图标
704
+ ...[0, 1, 2, 3, 4].map(i => ({
705
+ type: 'ellipse',
706
+ x: 30 + i * 65, y: 240,
707
+ width: 48, height: 48,
708
+ fill: colors.primary + '20'
709
+ })),
710
+ // 商品卡片
711
+ ...[0, 1].map(row => ({
712
+ type: 'box',
713
+ x: 16 + row * 175, y: 320,
714
+ width: 163, height: 220,
715
+ fill: colors.background,
716
+ cornerRadius: 8,
717
+ shadow: this.config.shadows.sm,
718
+ children: [
719
+ {
720
+ type: 'box',
721
+ x: 0, y: 0, width: 163, height: 163,
722
+ fill: colors.surface,
723
+ cornerRadius: { topLeft: 8, topRight: 8 }
724
+ },
725
+ {
726
+ type: 'text',
727
+ x: 12, y: 175,
728
+ text: '商品名称',
729
+ fill: colors.text.primary,
730
+ fontSize: 14,
731
+ fontFamily: this.config.typography.fontFamily
732
+ },
733
+ {
734
+ type: 'text',
735
+ x: 12, y: 195,
736
+ text: '¥199',
737
+ fill: colors.error,
738
+ fontSize: 16,
739
+ fontWeight: 600,
740
+ fontFamily: this.config.typography.fontFamily
741
+ }
742
+ ]
743
+ })),
744
+ // 底部导航
745
+ {
746
+ type: 'rect',
747
+ x: 0, y: h - 80, width: w, height: 80,
748
+ fill: colors.background,
749
+ shadow: { x: 0, y: -2, blur: 8, color: '#0000000d' }
750
+ },
751
+ ...['首页', '分类', '购物车', '我的'].map((tab, i) => ({
752
+ type: 'text',
753
+ x: w / 8 + i * (w / 4), y: h - 45,
754
+ text: tab,
755
+ fill: i === 0 ? colors.primary : colors.text.secondary,
756
+ fontSize: 12,
757
+ textAlign: 'center',
758
+ fontFamily: this.config.typography.fontFamily
759
+ }))
760
+ ]
761
+ };
762
+ }
763
+
764
+ // 平板布局仪表盘
765
+ generateTabletDashboard() {
766
+ const colors = this.config.getColors();
767
+ const w = 1024;
768
+ const h = 768;
769
+
770
+ return {
771
+ width: w,
772
+ height: h,
773
+ backgroundColor: colors.surface,
774
+ elements: [
775
+ // 侧边栏
776
+ {
777
+ type: 'box',
778
+ x: 0, y: 0, width: 200, height: h,
779
+ fill: colors.background,
780
+ shadow: { x: 2, y: 0, blur: 8, color: '#0000000d' }
781
+ },
782
+ {
783
+ type: 'text',
784
+ x: 24, y: 24,
785
+ text: 'Admin',
786
+ fill: colors.text.primary,
787
+ fontSize: 20,
788
+ fontWeight: 700,
789
+ fontFamily: this.config.typography.fontFamily
790
+ },
791
+ // 顶部栏
792
+ {
793
+ type: 'rect',
794
+ x: 200, y: 0, width: w - 200, height: 60,
795
+ fill: colors.background
796
+ },
797
+ // 统计卡片
798
+ ...[0, 1, 2, 3].map(i => ({
799
+ type: 'box',
800
+ x: 220 + (i % 2) * 390, y: 80 + Math.floor(i / 2) * 140,
801
+ width: 370, height: 120,
802
+ fill: colors.background,
803
+ cornerRadius: 8,
804
+ shadow: this.config.shadows.sm
805
+ })),
806
+ // 图表区域
807
+ {
808
+ type: 'box',
809
+ x: 220, y: 360, width: 560, height: 380,
810
+ fill: colors.background,
811
+ cornerRadius: 8,
812
+ shadow: this.config.shadows.sm
813
+ },
814
+ // 列表区域
815
+ {
816
+ type: 'box',
817
+ x: 800, y: 360, width: 204, height: 380,
818
+ fill: colors.background,
819
+ cornerRadius: 8,
820
+ shadow: this.config.shadows.sm
821
+ }
822
+ ]
823
+ };
824
+ }
825
+ }
826
+
827
+ /**
828
+ * 主生成器类
829
+ */
830
+ class DesignSystemProGenerator {
831
+ constructor(options = {}) {
832
+ this.config = new ThemeConfig(options);
833
+ this.componentGen = new AdvancedComponentGenerator(this.config);
834
+ this.templateGen = new ResponsiveTemplateGenerator(this.config);
835
+ this.templates = {};
836
+ }
837
+
838
+ // 生成完整设计系统
839
+ generate() {
840
+ return {
841
+ name: this.config.name,
842
+ version: '2.0.0',
843
+ theme: {
844
+ light: this.config.colors.light,
845
+ dark: this.config.colors.dark
846
+ },
847
+ typography: this.config.typography,
848
+ spacing: this.config.spacing,
849
+ borderRadius: this.config.borderRadius,
850
+ shadows: this.config.shadows,
851
+ components: this.generateAllComponents(),
852
+ templates: this.generateAllTemplates()
853
+ };
854
+ }
855
+
856
+ generateAllComponents() {
857
+ const colors = this.config.getColors();
858
+
859
+ return {
860
+ // 基础组件
861
+ buttons: this.generateButtonVariants(),
862
+ inputs: this.generateInputVariants(),
863
+
864
+ // 高级组件
865
+ table: this.componentGen.generateTable(
866
+ ['姓名', '邮箱', '角色', '状态'],
867
+ [
868
+ ['张三', 'zhangsan@example.com', '管理员', '活跃'],
869
+ ['李四', 'lisi@example.com', '编辑', '活跃'],
870
+ ['王五', 'wangwu@example.com', '访客', '离线']
871
+ ],
872
+ { width: 600 }
873
+ ),
874
+ modal: this.componentGen.generateModal(
875
+ '确认删除',
876
+ '确定要删除这条记录吗?此操作不可撤销。'
877
+ ),
878
+ dropdown: this.componentGen.generateDropdown(
879
+ '请选择',
880
+ [
881
+ { label: '选项一', selected: false },
882
+ { label: '选项二', selected: true },
883
+ { label: '选项三', selected: false }
884
+ ],
885
+ { isOpen: true }
886
+ ),
887
+ tabs: this.componentGen.generateTabs(
888
+ ['基本信息', '安全设置', '通知偏好'],
889
+ 0
890
+ ),
891
+ switch: this.componentGen.generateSwitch(true),
892
+ checkbox: this.componentGen.generateCheckbox(true, '记住我'),
893
+ radio: this.componentGen.generateRadio(true, '选项A')
894
+ };
895
+ }
896
+
897
+ generateButtonVariants() {
898
+ const variants = ['primary', 'secondary', 'success', 'warning', 'error', 'ghost', 'outline'];
899
+ return variants.map((variant, i) => ({
900
+ type: 'group',
901
+ x: i * 120,
902
+ y: 0,
903
+ children: this.generateButton(variant, 'md', variant)
904
+ }));
905
+ }
906
+
907
+ generateInputVariants() {
908
+ const states = ['default', 'focused', 'error', 'disabled'];
909
+ return states.map((state, i) => ({
910
+ type: 'group',
911
+ x: 0,
912
+ y: i * 60,
913
+ children: this.generateInput(state)
914
+ }));
915
+ }
916
+
917
+ generateButton(variant, size, text) {
918
+ // 复用之前的按钮生成逻辑
919
+ const colors = this.config.getColors();
920
+ const variantConfig = {
921
+ primary: { fill: colors.primary, textColor: colors.text.inverse },
922
+ secondary: { fill: colors.secondary, textColor: colors.text.inverse },
923
+ success: { fill: colors.success, textColor: colors.text.inverse },
924
+ warning: { fill: colors.warning, textColor: colors.text.inverse },
925
+ error: { fill: colors.error, textColor: colors.text.inverse },
926
+ ghost: { fill: 'transparent', textColor: colors.text.primary },
927
+ outline: { fill: 'transparent', textColor: colors.primary }
928
+ };
929
+
930
+ const config = variantConfig[variant] || variantConfig.primary;
931
+
932
+ return [{
933
+ type: 'box',
934
+ x: 0, y: 0, width: 100, height: 40,
935
+ fill: config.fill,
936
+ stroke: variant === 'outline' ? colors.primary : undefined,
937
+ strokeWidth: variant === 'outline' ? 1 : 0,
938
+ cornerRadius: 6,
939
+ children: [{
940
+ type: 'text',
941
+ x: 50, y: 12,
942
+ text: text || variant,
943
+ fill: config.textColor,
944
+ fontSize: 14,
945
+ textAlign: 'center',
946
+ fontFamily: this.config.typography.fontFamily
947
+ }]
948
+ }];
949
+ }
950
+
951
+ generateInput(state) {
952
+ const colors = this.config.getColors();
953
+ const stateConfig = {
954
+ default: { stroke: colors.border },
955
+ focused: { stroke: colors.primary },
956
+ error: { stroke: colors.error },
957
+ disabled: { stroke: colors.border, fill: colors.surface }
958
+ };
959
+
960
+ const config = stateConfig[state] || stateConfig.default;
961
+
962
+ return [{
963
+ type: 'box',
964
+ x: 0, y: 0, width: 240, height: 40,
965
+ fill: config.fill || colors.background,
966
+ stroke: config.stroke,
967
+ strokeWidth: 1,
968
+ cornerRadius: 6,
969
+ children: [{
970
+ type: 'text',
971
+ x: 12, y: 12,
972
+ text: state === 'disabled' ? '禁用状态' : '请输入内容...',
973
+ fill: state === 'disabled' ? colors.text.disabled : colors.text.secondary,
974
+ fontSize: 14,
975
+ fontFamily: this.config.typography.fontFamily
976
+ }]
977
+ }];
978
+ }
979
+
980
+ generateAllTemplates() {
981
+ return {
982
+ // 桌面端
983
+ desktop: {
984
+ login: this.generateLoginPage(),
985
+ dashboard: this.generateDashboardPage(),
986
+ showcase: this.generateShowcasePage()
987
+ },
988
+ // 移动端
989
+ mobile: {
990
+ login: this.templateGen.generateMobileLoginPage(),
991
+ home: this.templateGen.generateMobileHomePage()
992
+ },
993
+ // 平板
994
+ tablet: {
995
+ dashboard: this.templateGen.generateTabletDashboard()
996
+ }
997
+ };
998
+ }
999
+
1000
+ generateLoginPage() {
1001
+ // 复用之前的登录页生成逻辑
1002
+ return this.templateGen.generateMobileLoginPage();
1003
+ }
1004
+
1005
+ generateDashboardPage() {
1006
+ return this.templateGen.generateTabletDashboard();
1007
+ }
1008
+
1009
+ generateShowcasePage() {
1010
+ const colors = this.config.getColors();
1011
+ const w = 1200;
1012
+ const h = 1600;
1013
+
1014
+ return {
1015
+ width: w,
1016
+ height: h,
1017
+ backgroundColor: colors.surface,
1018
+ elements: [
1019
+ // 标题
1020
+ {
1021
+ type: 'text',
1022
+ x: 40, y: 40,
1023
+ text: this.config.name,
1024
+ fill: colors.text.primary,
1025
+ fontSize: 32,
1026
+ fontWeight: 700,
1027
+ fontFamily: this.config.typography.fontFamily
1028
+ },
1029
+ {
1030
+ type: 'text',
1031
+ x: 40, y: 80,
1032
+ text: '版本 2.0.0 | 组件库展示',
1033
+ fill: colors.text.secondary,
1034
+ fontSize: 14,
1035
+ fontFamily: this.config.typography.fontFamily
1036
+ },
1037
+ // 按钮展示
1038
+ {
1039
+ type: 'text',
1040
+ x: 40, y: 140,
1041
+ text: '按钮组件 (Buttons)',
1042
+ fill: colors.text.primary,
1043
+ fontSize: 18,
1044
+ fontWeight: 600,
1045
+ fontFamily: this.config.typography.fontFamily
1046
+ },
1047
+ ...['primary', 'secondary', 'success', 'warning', 'error', 'ghost', 'outline'].map((variant, i) => ({
1048
+ type: 'box',
1049
+ x: 40 + (i % 4) * 140, y: 180 + Math.floor(i / 4) * 60,
1050
+ width: 120, height: 40,
1051
+ fill: variant === 'outline' ? 'transparent' :
1052
+ variant === 'ghost' ? 'transparent' :
1053
+ colors[variant] || colors.primary,
1054
+ stroke: variant === 'outline' ? colors.primary : undefined,
1055
+ strokeWidth: variant === 'outline' ? 1 : 0,
1056
+ cornerRadius: 6,
1057
+ children: [{
1058
+ type: 'text',
1059
+ x: 60, y: 12,
1060
+ text: variant.charAt(0).toUpperCase() + variant.slice(1),
1061
+ fill: variant === 'ghost' ? colors.text.primary :
1062
+ variant === 'outline' ? colors.primary :
1063
+ colors.text.inverse,
1064
+ fontSize: 14,
1065
+ textAlign: 'center',
1066
+ fontFamily: this.config.typography.fontFamily
1067
+ }]
1068
+ })),
1069
+ // 表单组件展示
1070
+ {
1071
+ type: 'text',
1072
+ x: 40, y: 320,
1073
+ text: '表单组件 (Form Elements)',
1074
+ fill: colors.text.primary,
1075
+ fontSize: 18,
1076
+ fontWeight: 600,
1077
+ fontFamily: this.config.typography.fontFamily
1078
+ },
1079
+ // 开关
1080
+ {
1081
+ type: 'text',
1082
+ x: 40, y: 360,
1083
+ text: '开关:',
1084
+ fill: colors.text.secondary,
1085
+ fontSize: 14,
1086
+ fontFamily: this.config.typography.fontFamily
1087
+ },
1088
+ {
1089
+ type: 'group',
1090
+ x: 100, y: 358,
1091
+ children: this.componentGen.generateSwitch(true).children
1092
+ },
1093
+ // 复选框
1094
+ {
1095
+ type: 'text',
1096
+ x: 40, y: 400,
1097
+ text: '复选框:',
1098
+ fill: colors.text.secondary,
1099
+ fontSize: 14,
1100
+ fontFamily: this.config.typography.fontFamily
1101
+ },
1102
+ {
1103
+ type: 'group',
1104
+ x: 100, y: 398,
1105
+ children: this.componentGen.generateCheckbox(true, '选项').children
1106
+ },
1107
+ // 单选
1108
+ {
1109
+ type: 'text',
1110
+ x: 40, y: 440,
1111
+ text: '单选:',
1112
+ fill: colors.text.secondary,
1113
+ fontSize: 14,
1114
+ fontFamily: this.config.typography.fontFamily
1115
+ },
1116
+ {
1117
+ type: 'group',
1118
+ x: 100, y: 438,
1119
+ children: this.componentGen.generateRadio(true, '选项').children
1120
+ }
1121
+ ]
1122
+ };
1123
+ }
1124
+
1125
+ // 导出设计系统
1126
+ export(outputDir) {
1127
+ const designSystem = this.generate();
1128
+
1129
+ // 确保输出目录存在
1130
+ if (!fs.existsSync(outputDir)) {
1131
+ fs.mkdirSync(outputDir, { recursive: true });
1132
+ }
1133
+
1134
+ // 保存设计系统配置
1135
+ fs.writeFileSync(
1136
+ path.join(outputDir, 'design-system-pro.json'),
1137
+ JSON.stringify(designSystem, null, 2)
1138
+ );
1139
+
1140
+ // 保存各个模板
1141
+ const templatesDir = path.join(outputDir, 'templates');
1142
+ if (!fs.existsSync(templatesDir)) {
1143
+ fs.mkdirSync(templatesDir, { recursive: true });
1144
+ }
1145
+
1146
+ // 导出桌面端模板
1147
+ Object.entries(designSystem.templates.desktop).forEach(([name, template]) => {
1148
+ fs.writeFileSync(
1149
+ path.join(templatesDir, `desktop-${name}.json`),
1150
+ JSON.stringify(template, null, 2)
1151
+ );
1152
+ });
1153
+
1154
+ // 导出移动端模板
1155
+ Object.entries(designSystem.templates.mobile).forEach(([name, template]) => {
1156
+ fs.writeFileSync(
1157
+ path.join(templatesDir, `mobile-${name}.json`),
1158
+ JSON.stringify(template, null, 2)
1159
+ );
1160
+ });
1161
+
1162
+ // 导出平板模板
1163
+ Object.entries(designSystem.templates.tablet).forEach(([name, template]) => {
1164
+ fs.writeFileSync(
1165
+ path.join(templatesDir, `tablet-${name}.json`),
1166
+ JSON.stringify(template, null, 2)
1167
+ );
1168
+ });
1169
+
1170
+ console.log(`\n✅ Pro 设计系统已导出到: ${outputDir}`);
1171
+ console.log(`📁 包含 ${Object.keys(designSystem.templates).length} 个设备类型的模板`);
1172
+
1173
+ return designSystem;
1174
+ }
1175
+ }
1176
+
1177
+ // 导出模块
1178
+ module.exports = {
1179
+ DesignSystemProGenerator,
1180
+ ThemeConfig,
1181
+ AdvancedComponentGenerator,
1182
+ ResponsiveTemplateGenerator
1183
+ };
1184
+
1185
+ // CLI 支持
1186
+ if (require.main === module) {
1187
+ const generator = new DesignSystemProGenerator({
1188
+ name: 'Pro Design System',
1189
+ primaryColor: '#667eea',
1190
+ secondaryColor: '#764ba2'
1191
+ });
1192
+
1193
+ generator.export('./my-design-system-pro');
1194
+ }