@robot-admin/layout 2.0.2 → 2.2.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.
- package/README.md +344 -604
- package/dist/index.cjs +3 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.d.ts +590 -0
- package/dist/index.js +2198 -431
- package/dist/index.js.map +1 -1
- package/package.json +76 -72
- package/src/styles/layouts.scss +706 -0
- package/src/styles/settings.scss +385 -385
package/README.md
CHANGED
|
@@ -1,604 +1,344 @@
|
|
|
1
|
-
# @robot-admin/layout
|
|
2
|
-
|
|
3
|
-
> 布局和设置管理系统 - 为 Robot Admin 提供完整的布局配置管理能力(含 UI 组件)
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
##
|
|
115
|
-
|
|
116
|
-
###
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
| 属性
|
|
231
|
-
|
|
232
|
-
| `
|
|
233
|
-
| `
|
|
234
|
-
| `
|
|
235
|
-
| `
|
|
236
|
-
| `
|
|
237
|
-
| `
|
|
238
|
-
| `
|
|
239
|
-
| `
|
|
240
|
-
| `
|
|
241
|
-
| `
|
|
242
|
-
| `
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
-
|
|
251
|
-
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
圆角尺寸映射表:
|
|
346
|
-
|
|
347
|
-
```typescript
|
|
348
|
-
{
|
|
349
|
-
small: '4px',
|
|
350
|
-
medium: '6px',
|
|
351
|
-
large: '8px'
|
|
352
|
-
}
|
|
353
|
-
```
|
|
354
|
-
|
|
355
|
-
## 🎨 CSS 变量
|
|
356
|
-
|
|
357
|
-
Store 会自动将配置同步到以下 CSS 变量,可直接在样式中使用:
|
|
358
|
-
|
|
359
|
-
```css
|
|
360
|
-
/* 主题色相关 */
|
|
361
|
-
--primary-color: #409eff;
|
|
362
|
-
--primary-color-hover: #66b1ff;
|
|
363
|
-
--primary-color-pressed: #3a8ee6;
|
|
364
|
-
|
|
365
|
-
/* 布局尺寸 */
|
|
366
|
-
--sidebar-width: 220px;
|
|
367
|
-
--sidebar-collapsed-width: 64px;
|
|
368
|
-
--header-height: 56px;
|
|
369
|
-
--tags-view-height: 40px;
|
|
370
|
-
--border-radius: 6px;
|
|
371
|
-
|
|
372
|
-
/* 使用示例 */
|
|
373
|
-
.my-button {
|
|
374
|
-
background: var(--primary-color);
|
|
375
|
-
border-radius: var(--border-radius);
|
|
376
|
-
height: var(--header-height);
|
|
377
|
-
}
|
|
378
|
-
```
|
|
379
|
-
|
|
380
|
-
## 📖 类型定义
|
|
381
|
-
|
|
382
|
-
```typescript
|
|
383
|
-
/** 布局模式 */
|
|
384
|
-
type LayoutMode =
|
|
385
|
-
| "side"
|
|
386
|
-
| "top"
|
|
387
|
-
| "mix"
|
|
388
|
-
| "mix-top"
|
|
389
|
-
| "reverse-horizontal-mix"
|
|
390
|
-
| "card-layout";
|
|
391
|
-
|
|
392
|
-
/** 页面动画类型 */
|
|
393
|
-
type TransitionType = "fade" | "slide" | "zoom" | "none";
|
|
394
|
-
|
|
395
|
-
/** 圆角大小 */
|
|
396
|
-
type BorderRadiusSize = "small" | "medium" | "large";
|
|
397
|
-
|
|
398
|
-
/** 标签页风格 */
|
|
399
|
-
type TagsViewStyle = "default" | "card" | "smart";
|
|
400
|
-
|
|
401
|
-
/** 主题模式(继承自 @robot-admin/theme) */
|
|
402
|
-
type ThemeMode = "light" | "dark" | "auto";
|
|
403
|
-
|
|
404
|
-
/** 主题预设 */
|
|
405
|
-
interface ThemePreset {
|
|
406
|
-
name: string;
|
|
407
|
-
icon: string;
|
|
408
|
-
primaryColor: string;
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
/** 设置状态 */
|
|
412
|
-
interface SettingsState {
|
|
413
|
-
// 外观
|
|
414
|
-
themeMode: ThemeMode;
|
|
415
|
-
primaryColor: string;
|
|
416
|
-
borderRadius: BorderRadiusSize;
|
|
417
|
-
transitionType: TransitionType;
|
|
418
|
-
enableTransition: boolean;
|
|
419
|
-
|
|
420
|
-
// 布局
|
|
421
|
-
layoutMode: LayoutMode;
|
|
422
|
-
fixedHeader: boolean;
|
|
423
|
-
showBreadcrumb: boolean;
|
|
424
|
-
showBreadcrumbIcon: boolean;
|
|
425
|
-
showTagsView: boolean;
|
|
426
|
-
tagsViewHeight: number;
|
|
427
|
-
tagsViewStyle: TagsViewStyle;
|
|
428
|
-
showFooter: boolean;
|
|
429
|
-
sidebarWidth: number;
|
|
430
|
-
sidebarCollapsedWidth: number;
|
|
431
|
-
headerHeight: number;
|
|
432
|
-
|
|
433
|
-
// 高级
|
|
434
|
-
enableHotkeys: boolean;
|
|
435
|
-
version: string;
|
|
436
|
-
}
|
|
437
|
-
```
|
|
438
|
-
|
|
439
|
-
## 🔧 完整示例
|
|
440
|
-
|
|
441
|
-
### 基础 Naive UI 项目集成
|
|
442
|
-
|
|
443
|
-
```typescript
|
|
444
|
-
// main.ts
|
|
445
|
-
import { createApp } from "vue";
|
|
446
|
-
import { createPinia } from "pinia";
|
|
447
|
-
import { setupLayout, SettingsDrawer } from "@robot-admin/layout";
|
|
448
|
-
import { useThemeStore } from "@robot-admin/theme";
|
|
449
|
-
import "@robot-admin/layout/style.scss";
|
|
450
|
-
import App from "./App.vue";
|
|
451
|
-
|
|
452
|
-
const app = createApp(App);
|
|
453
|
-
const pinia = createPinia();
|
|
454
|
-
|
|
455
|
-
app.use(pinia);
|
|
456
|
-
|
|
457
|
-
// 初始化主题
|
|
458
|
-
const themeStore = useThemeStore();
|
|
459
|
-
themeStore.init();
|
|
460
|
-
|
|
461
|
-
// 初始化布局(一行搞定)
|
|
462
|
-
setupLayout(app, {
|
|
463
|
-
onThemeModeChange: async (mode) => {
|
|
464
|
-
await themeStore.setMode(mode);
|
|
465
|
-
},
|
|
466
|
-
});
|
|
467
|
-
|
|
468
|
-
app.mount("#app");
|
|
469
|
-
```
|
|
470
|
-
|
|
471
|
-
```vue
|
|
472
|
-
<!-- App.vue -->
|
|
473
|
-
<template>
|
|
474
|
-
<NConfigProvider :theme="naiveTheme">
|
|
475
|
-
<NMessageProvider>
|
|
476
|
-
<div class="app-container">
|
|
477
|
-
<!-- 你的布局和内容 -->
|
|
478
|
-
<router-view />
|
|
479
|
-
|
|
480
|
-
<!-- 设置按钮 -->
|
|
481
|
-
<NButton
|
|
482
|
-
class="settings-trigger"
|
|
483
|
-
circle
|
|
484
|
-
size="large"
|
|
485
|
-
@click="showSettings = true"
|
|
486
|
-
>
|
|
487
|
-
<template #icon>
|
|
488
|
-
<NIcon><Settings /></NIcon>
|
|
489
|
-
</template>
|
|
490
|
-
</NButton>
|
|
491
|
-
|
|
492
|
-
<!-- 设置抽屉(开箱即用)-->
|
|
493
|
-
<SettingsDrawer v-model:show="showSettings" />
|
|
494
|
-
</div>
|
|
495
|
-
</NMessageProvider>
|
|
496
|
-
</NConfigProvider>
|
|
497
|
-
</template>
|
|
498
|
-
|
|
499
|
-
<script setup lang="ts">
|
|
500
|
-
import { ref, computed } from "vue";
|
|
501
|
-
import {
|
|
502
|
-
NConfigProvider,
|
|
503
|
-
NMessageProvider,
|
|
504
|
-
NButton,
|
|
505
|
-
NIcon,
|
|
506
|
-
darkTheme,
|
|
507
|
-
} from "naive-ui";
|
|
508
|
-
import { Settings } from "@vicons/tabler";
|
|
509
|
-
import { SettingsDrawer } from "@robot-admin/layout";
|
|
510
|
-
import { useThemeStore } from "@robot-admin/theme";
|
|
511
|
-
|
|
512
|
-
const themeStore = useThemeStore();
|
|
513
|
-
const showSettings = ref(false);
|
|
514
|
-
|
|
515
|
-
const naiveTheme = computed(() => {
|
|
516
|
-
return themeStore.isDark ? darkTheme : undefined;
|
|
517
|
-
});
|
|
518
|
-
</script>
|
|
519
|
-
|
|
520
|
-
<style>
|
|
521
|
-
.settings-trigger {
|
|
522
|
-
position: fixed;
|
|
523
|
-
right: 20px;
|
|
524
|
-
bottom: 80px;
|
|
525
|
-
z-index: 999;
|
|
526
|
-
}
|
|
527
|
-
</style>
|
|
528
|
-
```
|
|
529
|
-
|
|
530
|
-
### 高级:自定义配置
|
|
531
|
-
|
|
532
|
-
```typescript
|
|
533
|
-
// stores/settings.ts
|
|
534
|
-
import { createSettingsStore } from "@robot-admin/layout";
|
|
535
|
-
import { useThemeStore } from "@robot-admin/theme";
|
|
536
|
-
|
|
537
|
-
export const useSettingsStore = createSettingsStore({
|
|
538
|
-
// 自定义默认值
|
|
539
|
-
defaults: {
|
|
540
|
-
layoutMode: "mix",
|
|
541
|
-
primaryColor: "#722ed1",
|
|
542
|
-
showTagsView: false,
|
|
543
|
-
fixedHeader: true,
|
|
544
|
-
},
|
|
545
|
-
|
|
546
|
-
// 主题模式变化回调
|
|
547
|
-
onThemeModeChange: async (mode) => {
|
|
548
|
-
const themeStore = useThemeStore();
|
|
549
|
-
await themeStore.setMode(mode);
|
|
550
|
-
|
|
551
|
-
// 额外逻辑:通知后端
|
|
552
|
-
await fetch("/api/user/theme", {
|
|
553
|
-
method: "PUT",
|
|
554
|
-
body: JSON.stringify({ mode }),
|
|
555
|
-
});
|
|
556
|
-
},
|
|
557
|
-
});
|
|
558
|
-
```
|
|
559
|
-
|
|
560
|
-
## 🎯 最佳实践
|
|
561
|
-
|
|
562
|
-
### 1. 样式使用建议
|
|
563
|
-
|
|
564
|
-
- **推荐使用 SCSS**:可以自定义变量和主题
|
|
565
|
-
- **CSS 变量优先**:使用 `var(--primary-color)` 而非硬编码颜色
|
|
566
|
-
- **响应式设计**:利用 `var(--sidebar-width)` 等布局变量
|
|
567
|
-
|
|
568
|
-
### 2. 性能优化
|
|
569
|
-
|
|
570
|
-
```typescript
|
|
571
|
-
// 懒加载设置抽屉(仅在需要时加载)
|
|
572
|
-
const SettingsDrawer = defineAsyncComponent(() =>
|
|
573
|
-
import("@robot-admin/layout").then((m) => ({ default: m.SettingsDrawer })),
|
|
574
|
-
);
|
|
575
|
-
```
|
|
576
|
-
|
|
577
|
-
### 3. 类型安全
|
|
578
|
-
|
|
579
|
-
```typescript
|
|
580
|
-
import type { LayoutMode, SettingsState } from "@robot-admin/layout";
|
|
581
|
-
|
|
582
|
-
// 使用类型约束
|
|
583
|
-
const handleLayoutChange = (mode: LayoutMode) => {
|
|
584
|
-
settingsStore.layoutMode = mode;
|
|
585
|
-
};
|
|
586
|
-
```
|
|
587
|
-
|
|
588
|
-
## 🔗 相关链接
|
|
589
|
-
|
|
590
|
-
- [Robot Admin 完整项目](https://github.com/ChenyCHENYU/Robot_Admin)
|
|
591
|
-
- [@robot-admin/theme](https://www.npmjs.com/package/@robot-admin/theme)
|
|
592
|
-
- [Naive UI 文档](https://www.naiveui.com/)
|
|
593
|
-
|
|
594
|
-
## 📝 更新日志
|
|
595
|
-
|
|
596
|
-
查看 [CHANGELOG.md](./CHANGELOG.md) 了解详细更新记录。
|
|
597
|
-
|
|
598
|
-
## 🤝 贡献
|
|
599
|
-
|
|
600
|
-
欢迎提交 Issue 和 Pull Request!
|
|
601
|
-
|
|
602
|
-
## 📄 License
|
|
603
|
-
|
|
604
|
-
MIT © ChenYu
|
|
1
|
+
# @robot-admin/layout
|
|
2
|
+
|
|
3
|
+
> 布局和设置管理系统 - 为 Robot Admin 提供完整的布局配置管理能力(含 UI 组件)
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## ✨ 特性
|
|
8
|
+
|
|
9
|
+
- 🧠 **智能容器模式** - `C_LayoutContainer` 自动分发布局骨架,主项目只需提供业务插槽
|
|
10
|
+
- 🎨 **6 种布局模式** - 左侧 / 顶部 / 混合 / 顶部混合 / 反转混合 / 卡片布局
|
|
11
|
+
- 🎯 **6 套主题预设** - 科技蓝 / 清新绿 / 商务灰 / 活力橙 / 优雅紫 / 经典红
|
|
12
|
+
- 🧩 **开箱即用** - 提供 SettingsDrawer 设置抽屉,覆盖外观 / 布局 / 功能配置
|
|
13
|
+
- 🔌 **插槽系统** - 灵活的 slot 机制,主项目仅关注业务组件
|
|
14
|
+
- 🎨 **CSS 变量同步** - 配置变更自动同步到 CSS 变量,样式实时响应
|
|
15
|
+
- 🚀 **TypeScript** - 完整类型支持
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## 🏗️ 架构设计
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
┌──────────────────────────────────────┐
|
|
23
|
+
│ 主项目 (Robot_Admin) │
|
|
24
|
+
│ ├─ useLayoutBridge() 适配器 │
|
|
25
|
+
│ └─ 提供业务插槽 (Header/Menu/Tags) │
|
|
26
|
+
└──────────────┬───────────────────────┘
|
|
27
|
+
│ LayoutContext (provide/inject)
|
|
28
|
+
▼
|
|
29
|
+
┌──────────────────────────────────────┐
|
|
30
|
+
│ @robot-admin/layout │
|
|
31
|
+
│ ├─ C_LayoutContainer (智能容器) │
|
|
32
|
+
│ │ └─ 根据 layoutMode 自动调度 │
|
|
33
|
+
│ ├─ layouts/ (6 种布局骨架) │
|
|
34
|
+
│ │ ├─ SideLayout │
|
|
35
|
+
│ │ ├─ TopLayout │
|
|
36
|
+
│ │ ├─ MixLayout │
|
|
37
|
+
│ │ ├─ MixTopLayout │
|
|
38
|
+
│ │ ├─ ReverseHorizontalMixLayout │
|
|
39
|
+
│ │ └─ CardLayout │
|
|
40
|
+
│ └─ SettingsDrawer (设置 UI) │
|
|
41
|
+
└──────────────────────────────────────┘
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## 📁 目录结构
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
src/
|
|
50
|
+
├── index.ts # 主入口(统一导出)
|
|
51
|
+
├── setup.ts # 一键初始化 setupLayout()
|
|
52
|
+
├── components/
|
|
53
|
+
│ ├── C_LayoutContainer/ # 智能布局容器(主入口组件)
|
|
54
|
+
│ │ └── index.vue
|
|
55
|
+
│ ├── layouts/ # 📐 6 种布局骨架
|
|
56
|
+
│ │ ├── SideLayout/ # 左侧菜单布局
|
|
57
|
+
│ │ │ ├── index.vue
|
|
58
|
+
│ │ │ └── index.scss
|
|
59
|
+
│ │ ├── TopLayout/ # 顶部菜单布局
|
|
60
|
+
│ │ │ ├── index.vue
|
|
61
|
+
│ │ │ └── index.scss
|
|
62
|
+
│ │ ├── MixLayout/ # 左侧混合布局
|
|
63
|
+
│ │ │ ├── index.vue
|
|
64
|
+
│ │ │ └── index.scss
|
|
65
|
+
│ │ ├── MixTopLayout/ # 顶部混合布局
|
|
66
|
+
│ │ │ ├── index.vue
|
|
67
|
+
│ │ │ └── index.scss
|
|
68
|
+
│ │ ├── ReverseHorizontalMixLayout/ # 反转混合布局
|
|
69
|
+
│ │ │ ├── index.vue
|
|
70
|
+
│ │ │ └── index.scss
|
|
71
|
+
│ │ └── CardLayout/ # 卡片布局
|
|
72
|
+
│ │ ├── index.vue
|
|
73
|
+
│ │ └── index.scss
|
|
74
|
+
│ ├── SettingsDrawer/ # ⚙️ 设置抽屉
|
|
75
|
+
│ │ ├── index.vue
|
|
76
|
+
│ │ └── data.ts
|
|
77
|
+
│ ├── BrandLogo/ # 品牌 Logo
|
|
78
|
+
│ ├── ResponsiveMenu/ # 响应式水平菜单
|
|
79
|
+
│ ├── IconMenu/ # 一级图标菜单
|
|
80
|
+
│ ├── FloatingMenu/ # 悬浮二级菜单
|
|
81
|
+
│ ├── SideMenu/ # 右侧二级菜单
|
|
82
|
+
│ ├── DrawerMenu/ # 抽屉式网格菜单
|
|
83
|
+
│ └── MenuTrigger/ # 菜单触发区域
|
|
84
|
+
├── composables/
|
|
85
|
+
│ ├── useLayoutContext.ts # LayoutContext provide/inject
|
|
86
|
+
│ ├── useLayoutCache.ts # 页面缓存管理
|
|
87
|
+
│ └── useMenuSplit.ts # 菜单拆分(一级/二级分离)
|
|
88
|
+
├── stores/
|
|
89
|
+
│ └── settings.ts # 布局设置 Pinia Store
|
|
90
|
+
├── styles/
|
|
91
|
+
│ ├── layouts.scss # 布局骨架公共样式
|
|
92
|
+
│ └── settings.scss # 设置组件样式
|
|
93
|
+
├── constants/
|
|
94
|
+
│ └── index.ts # 预设常量
|
|
95
|
+
└── types/
|
|
96
|
+
├── index.ts # 类型定义
|
|
97
|
+
└── menu.ts # 菜单类型
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## 📦 安装
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
bun add @robot-admin/layout @robot-admin/theme naive-ui
|
|
106
|
+
# or
|
|
107
|
+
pnpm add @robot-admin/layout @robot-admin/theme naive-ui
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**Peer Dependencies**: `vue ^3.4` · `vue-router ^4.0` · `pinia ^2.0 || ^3.0` · `naive-ui ^2.38` · `@robot-admin/theme ^0.1`
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## 🚀 快速开始
|
|
115
|
+
|
|
116
|
+
### 1. 初始化
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
// main.ts
|
|
120
|
+
import { createApp } from "vue";
|
|
121
|
+
import { createPinia } from "pinia";
|
|
122
|
+
import { setupLayout } from "@robot-admin/layout";
|
|
123
|
+
import { useThemeStore } from "@robot-admin/theme";
|
|
124
|
+
import "@robot-admin/layout/style"; // 导入样式
|
|
125
|
+
import App from "./App.vue";
|
|
126
|
+
|
|
127
|
+
const app = createApp(App);
|
|
128
|
+
app.use(createPinia());
|
|
129
|
+
|
|
130
|
+
const themeStore = useThemeStore();
|
|
131
|
+
themeStore.init();
|
|
132
|
+
|
|
133
|
+
setupLayout(app, {
|
|
134
|
+
onThemeModeChange: (mode) => themeStore.setMode(mode),
|
|
135
|
+
defaults: {
|
|
136
|
+
layoutMode: "side",
|
|
137
|
+
primaryColor: "#409eff",
|
|
138
|
+
},
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
app.mount("#app");
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### 2. 使用布局容器
|
|
145
|
+
|
|
146
|
+
```vue
|
|
147
|
+
<!-- src/components/C_Layout/index.vue -->
|
|
148
|
+
<template>
|
|
149
|
+
<C_LayoutContainer>
|
|
150
|
+
<template #logo><AppLogo /></template>
|
|
151
|
+
<template #menu="{ collapsed }"><AppMenu :collapsed="collapsed" /></template>
|
|
152
|
+
<template #header><AppHeader /></template>
|
|
153
|
+
<template #tags-view><AppTags /></template>
|
|
154
|
+
<template #footer><AppFooter /></template>
|
|
155
|
+
</C_LayoutContainer>
|
|
156
|
+
</template>
|
|
157
|
+
|
|
158
|
+
<script setup lang="ts">
|
|
159
|
+
import { C_LayoutContainer } from "@robot-admin/layout";
|
|
160
|
+
</script>
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### 3. 添加设置抽屉
|
|
164
|
+
|
|
165
|
+
```vue
|
|
166
|
+
<script setup lang="ts">
|
|
167
|
+
import { ref } from "vue";
|
|
168
|
+
import { SettingsDrawer } from "@robot-admin/layout";
|
|
169
|
+
|
|
170
|
+
const visible = ref(false);
|
|
171
|
+
</script>
|
|
172
|
+
|
|
173
|
+
<template>
|
|
174
|
+
<button @click="visible = true">⚙️ 设置</button>
|
|
175
|
+
<SettingsDrawer v-model:show="visible" />
|
|
176
|
+
</template>
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## 📐 布局模式
|
|
182
|
+
|
|
183
|
+
| 模式 | 常量值 | 一级菜单 | 二级菜单 | 适用场景 |
|
|
184
|
+
|------|--------|----------|----------|----------|
|
|
185
|
+
| **左侧菜单** | `side` | 左侧栏 | 左侧栏(折叠) | 经典后台管理(ERP、CRM) |
|
|
186
|
+
| **顶部菜单** | `top` | 顶部横向 | 顶部下拉 | 菜单少,需更宽内容区 |
|
|
187
|
+
| **混合布局** | `mix` | 左侧图标栏 | 悬浮弹出 | 一级菜单少,二级多 |
|
|
188
|
+
| **顶部混合** | `mix-top` | 左侧图标栏 | 顶部横向 | 全局导航 + 侧边详情 |
|
|
189
|
+
| **反转混合** | `reverse-horizontal-mix` | 顶部横向 | 右侧栏 | 特殊需求,右手操作 |
|
|
190
|
+
| **卡片布局** | `card-layout` | hover 抽屉 | 网格铺开 | 应用首页 / 工作台 |
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## 🎨 主题预设
|
|
195
|
+
|
|
196
|
+
| 预设 | 主题色 | 图标 |
|
|
197
|
+
|------|--------|------|
|
|
198
|
+
| 科技蓝 | `#409eff` | 💙 |
|
|
199
|
+
| 清新绿 | `#52c41a` | 💚 |
|
|
200
|
+
| 商务灰 | `#595959` | 🖤 |
|
|
201
|
+
| 活力橙 | `#fa8c16` | 🧡 |
|
|
202
|
+
| 优雅紫 | `#722ed1` | 💜 |
|
|
203
|
+
| 经典红 | `#f5222d` | ❤️ |
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## ⚙️ Store API
|
|
208
|
+
|
|
209
|
+
### `useSettingsStore()`
|
|
210
|
+
|
|
211
|
+
```typescript
|
|
212
|
+
import { useSettingsStore } from "@robot-admin/layout";
|
|
213
|
+
|
|
214
|
+
const settings = useSettingsStore();
|
|
215
|
+
|
|
216
|
+
// 读取
|
|
217
|
+
settings.layoutMode; // 'side' | 'top' | 'mix' | ...
|
|
218
|
+
settings.primaryColor; // '#409eff'
|
|
219
|
+
settings.themeMode; // 'light' | 'dark' | 'auto'
|
|
220
|
+
|
|
221
|
+
// 修改
|
|
222
|
+
settings.layoutMode = "mix";
|
|
223
|
+
settings.updateThemeMode("dark");
|
|
224
|
+
settings.applyPreset(THEME_PRESETS[0]);
|
|
225
|
+
settings.resetSettings();
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### 设置属性一览
|
|
229
|
+
|
|
230
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
231
|
+
|------|------|--------|------|
|
|
232
|
+
| `themeMode` | `ThemeMode` | `'light'` | 主题模式 |
|
|
233
|
+
| `primaryColor` | `string` | `'#409eff'` | 主题色 |
|
|
234
|
+
| `layoutMode` | `LayoutMode` | `'side'` | 布局模式 |
|
|
235
|
+
| `borderRadius` | `BorderRadiusSize` | `'medium'` | 圆角大小 |
|
|
236
|
+
| `transitionType` | `TransitionType` | `'slide'` | 页面动画 |
|
|
237
|
+
| `fixedHeader` | `boolean` | `true` | 固定头部 |
|
|
238
|
+
| `showBreadcrumb` | `boolean` | `true` | 显示面包屑 |
|
|
239
|
+
| `showTagsView` | `boolean` | `true` | 显示标签页 |
|
|
240
|
+
| `showFooter` | `boolean` | `true` | 显示页脚 |
|
|
241
|
+
| `sidebarWidth` | `number` | `220` | 侧边栏宽度 (px) |
|
|
242
|
+
| `sidebarCollapsedWidth` | `number` | `64` | 折叠宽度 (px) |
|
|
243
|
+
| `headerHeight` | `number` | `56` | 头部高度 (px) |
|
|
244
|
+
|
|
245
|
+
### CSS 变量
|
|
246
|
+
|
|
247
|
+
配置变更自动同步到以下 CSS 变量:
|
|
248
|
+
|
|
249
|
+
```css
|
|
250
|
+
--primary-color: #409eff;
|
|
251
|
+
--primary-color-hover: #66b1ff;
|
|
252
|
+
--primary-color-pressed: #3a8ee6;
|
|
253
|
+
--sidebar-width: 220px;
|
|
254
|
+
--sidebar-collapsed-width: 64px;
|
|
255
|
+
--header-height: 56px;
|
|
256
|
+
--tags-view-height: 40px;
|
|
257
|
+
--border-radius: 6px;
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
## 🧩 C_LayoutContainer Slots
|
|
263
|
+
|
|
264
|
+
| Slot 名称 | 说明 | 适用布局 |
|
|
265
|
+
|-----------|------|----------|
|
|
266
|
+
| `#logo` | 品牌 Logo | 全部 |
|
|
267
|
+
| `#menu` | 垂直菜单 | Side |
|
|
268
|
+
| `#header` | 完整头部 | Side / Mix |
|
|
269
|
+
| `#header-extra` | 头部右侧操作区 | Top / MixTop / Reverse / Card |
|
|
270
|
+
| `#top-menu` | 水平菜单 | Top / MixTop / Reverse |
|
|
271
|
+
| `#tags-view` | 标签页 | 全部 |
|
|
272
|
+
| `#footer` | 页脚 | 全部 |
|
|
273
|
+
| `#brand` | 顶部品牌区 | MixTop |
|
|
274
|
+
| `#menu-trigger` | 菜单触发区 | Card |
|
|
275
|
+
| `#drawer-menu` | 抽屉菜单 | Card |
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
## 📖 类型定义
|
|
280
|
+
|
|
281
|
+
```typescript
|
|
282
|
+
type LayoutMode = "side" | "top" | "mix" | "mix-top" | "reverse-horizontal-mix" | "card-layout";
|
|
283
|
+
type TransitionType = "fade" | "slide" | "zoom" | "none";
|
|
284
|
+
type BorderRadiusSize = "small" | "medium" | "large";
|
|
285
|
+
type TagsViewStyle = "default" | "card" | "smart";
|
|
286
|
+
type ThemeMode = "light" | "dark" | "auto";
|
|
287
|
+
|
|
288
|
+
interface ThemePreset { name: string; icon: string; primaryColor: string; }
|
|
289
|
+
interface SettingsStoreOptions {
|
|
290
|
+
defaults?: Partial<SettingsState>;
|
|
291
|
+
onThemeModeChange?: (mode: ThemeMode) => void | Promise<void>;
|
|
292
|
+
}
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
## 🔧 高级用法
|
|
298
|
+
|
|
299
|
+
### 自定义 Settings Store
|
|
300
|
+
|
|
301
|
+
```typescript
|
|
302
|
+
import { createSettingsStore } from "@robot-admin/layout";
|
|
303
|
+
|
|
304
|
+
export const useSettingsStore = createSettingsStore({
|
|
305
|
+
defaults: { layoutMode: "mix", primaryColor: "#722ed1" },
|
|
306
|
+
onThemeModeChange: async (mode) => {
|
|
307
|
+
const themeStore = useThemeStore();
|
|
308
|
+
await themeStore.setMode(mode);
|
|
309
|
+
},
|
|
310
|
+
});
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
### 单独使用布局骨架
|
|
314
|
+
|
|
315
|
+
```typescript
|
|
316
|
+
import { SideLayout, TopLayout, MixLayout } from "@robot-admin/layout";
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
> ⚠️ 直接使用骨架组件需自行提供 `LayoutContext`(通过 `provide`),推荐使用 `C_LayoutContainer`
|
|
320
|
+
|
|
321
|
+
### 样式导入方式
|
|
322
|
+
|
|
323
|
+
```typescript
|
|
324
|
+
// 方式 1:编译后 CSS(推荐)
|
|
325
|
+
import "@robot-admin/layout/style";
|
|
326
|
+
|
|
327
|
+
// 方式 2:SCSS 源文件(可定制)
|
|
328
|
+
import "@robot-admin/layout/style.scss";
|
|
329
|
+
|
|
330
|
+
// 方式 3:仅布局骨架基础样式
|
|
331
|
+
import "@robot-admin/layout/layouts.scss";
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
---
|
|
335
|
+
|
|
336
|
+
## 🔗 相关链接
|
|
337
|
+
|
|
338
|
+
- [Robot Admin 主项目](https://github.com/ChenyCHENYU/Robot_Admin)
|
|
339
|
+
- [@robot-admin/theme](https://www.npmjs.com/package/@robot-admin/theme)
|
|
340
|
+
- [Naive UI](https://www.naiveui.com/)
|
|
341
|
+
|
|
342
|
+
## 📄 License
|
|
343
|
+
|
|
344
|
+
MIT © ChenYu
|