forked from mengyxu/noob-components
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
206 lines
5.0 KiB
206 lines
5.0 KiB
|
3 months ago
|
# Head Components
|
||
|
|
|
||
|
|
> Header and menu navigation components.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Overview
|
||
|
|
|
||
|
|
Head components provide the top-level navigation and layout structure for the management UI. They handle menu rendering, user controls, and responsive layout adjustments.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Components
|
||
|
|
|
||
|
|
| Component | File | Purpose |
|
||
|
|
|-----------|------|---------|
|
||
|
|
| Head | `head/head.vue` | Main header with logo, title, user info |
|
||
|
|
| MenuTree | `head/menu-tree.vue` | Menu navigation with router integration |
|
||
|
|
| Personal | `head/personal.vue` | Personal settings panel |
|
||
|
|
| Fullscreen | `head/fullscreen.vue` | Fullscreen toggle button |
|
||
|
|
| StyleChange | `head/style-change.vue` | Theme/style switcher |
|
||
|
|
| LangChange | `head/lang-change.vue` | Language switcher |
|
||
|
|
| SizeChange | `head/size-change.vue` | UI size (small/medium/large) switcher |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Head Component (`head.vue`)
|
||
|
|
|
||
|
|
Main header wrapper with slots for left/right content.
|
||
|
|
|
||
|
|
### Props
|
||
|
|
|
||
|
|
| Prop | Type | Default | Description |
|
||
|
|
|------|------|---------|-------------|
|
||
|
|
| `closeAble` | Boolean | false | Show/hide aside toggle |
|
||
|
|
| `title` | String | null | Custom title text |
|
||
|
|
| `logo` | String | null | Logo image URL |
|
||
|
|
| `username` | String | null | Display username |
|
||
|
|
|
||
|
|
### Slots
|
||
|
|
|
||
|
|
| Slot | Description |
|
||
|
|
|------|-------------|
|
||
|
|
| `left` | Left side content before actions |
|
||
|
|
| `default` | Right side content (actions) |
|
||
|
|
|
||
|
|
### Behavior
|
||
|
|
|
||
|
|
- `closeAble` toggles aside width between `0px` and original width
|
||
|
|
- Uses Vuex `state.size` for responsive sizing with CSS `v-bind`
|
||
|
|
|
||
|
|
### Example
|
||
|
|
|
||
|
|
```vue
|
||
|
|
<NoobHead :closeAble="true" :title="appTitle" :logo="logo" :username="username">
|
||
|
|
<Fullscreen />
|
||
|
|
<StyleChange />
|
||
|
|
<LangChange />
|
||
|
|
<SizeChange />
|
||
|
|
<Personal />
|
||
|
|
</NoobHead>
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## MenuTree Component (`menu-tree.vue`)
|
||
|
|
|
||
|
|
Dynamic menu navigation with router integration.
|
||
|
|
|
||
|
|
### Props
|
||
|
|
|
||
|
|
| Prop | Type | Default | Description |
|
||
|
|
|------|------|---------|-------------|
|
||
|
|
| `mode` | String | 'vertical' | Menu mode ('vertical' or 'horizontal') |
|
||
|
|
| `data` | Array | null | Menu items (uses Vuex if null) |
|
||
|
|
| `logo` | String | null | Logo image URL |
|
||
|
|
| `title` | String | null | Title text |
|
||
|
|
|
||
|
|
### Menu Data Structure
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
interface MenuItem {
|
||
|
|
path: string; // Route path
|
||
|
|
title?: string; // Display title
|
||
|
|
i18n?: string; // i18n key for title
|
||
|
|
icon?: string; // Icon component name
|
||
|
|
children?: MenuItem[]; // Sub-menu items
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Menu Definition (views/index.ts)
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
const menus = {
|
||
|
|
buff: { i18n: 'preMenu.operator.0', path: 'buffer', icon: 'Warning' },
|
||
|
|
config: { i18n: 'preMenu.operator.1', path: 'config', icon: 'EditPen' },
|
||
|
|
dictionary: { i18n: 'preMenu.operator.2', path: 'dictionary', icon: 'Collection' },
|
||
|
|
permission: { i18n: 'preMenu.operator.3', path: 'permission', icon: 'Unlock' },
|
||
|
|
role: { i18n: 'preMenu.operator.4', path: 'role', icon: 'User' },
|
||
|
|
user: { i18n: 'preMenu.operator.5', path: 'user', icon: 'User' },
|
||
|
|
status: { i18n: 'preMenu.operator.6', path: 'status', icon: 'Setting' },
|
||
|
|
log: { i18n: 'preMenu.operator.7', path: 'log', icon: 'Document' },
|
||
|
|
};
|
||
|
|
```
|
||
|
|
|
||
|
|
### Behavior
|
||
|
|
|
||
|
|
- Reads active route from `router.currentRoute.value.path`
|
||
|
|
- Prefixes paths with `/` if not present
|
||
|
|
- Uses `el-menu` with `router` prop for automatic routing
|
||
|
|
- Supports nested menus via `el-sub-menu`
|
||
|
|
|
||
|
|
### Style Integration
|
||
|
|
|
||
|
|
Uses Vuex state for dynamic theming:
|
||
|
|
|
||
|
|
```scss
|
||
|
|
.el-menu {
|
||
|
|
:background-color: v-bind('state.style.menuBg');
|
||
|
|
:text-color: v-bind('state.style.menuColor');
|
||
|
|
:active-text-color: v-bind('state.style.menuActiveColor');
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Fullscreen Component (`fullscreen.vue`)
|
||
|
|
|
||
|
|
Toggle browser fullscreen mode.
|
||
|
|
|
||
|
|
### Implementation
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
import { ref } from 'vue';
|
||
|
|
|
||
|
|
const isFullscreen = ref(false);
|
||
|
|
|
||
|
|
const toggle = () => {
|
||
|
|
if (!document.fullscreenElement) {
|
||
|
|
document.documentElement.requestFullscreen();
|
||
|
|
isFullscreen.value = true;
|
||
|
|
} else {
|
||
|
|
document.exitFullscreen();
|
||
|
|
isFullscreen.value = false;
|
||
|
|
}
|
||
|
|
};
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## StyleChange Component (`style-change.vue`)
|
||
|
|
|
||
|
|
Theme/style switcher - typically opens a style configuration panel.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## LangChange Component (`lang-change.vue`)
|
||
|
|
|
||
|
|
Language switcher - switches i18n locale.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## SizeChange Component (`size-change.vue`)
|
||
|
|
|
||
|
|
UI component size switcher (small/medium/large/default).
|
||
|
|
|
||
|
|
### Integration
|
||
|
|
|
||
|
|
Updates Vuex `state.size.size` which propagates to all Element Plus components.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Common Patterns
|
||
|
|
|
||
|
|
### Vuex State Usage
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
const { state, commit, dispatch } = useStore();
|
||
|
|
|
||
|
|
// Accessing size settings
|
||
|
|
state.size.headHeight
|
||
|
|
state.size.asideWidth
|
||
|
|
state.size.size
|
||
|
|
|
||
|
|
// Accessing style settings
|
||
|
|
state.style.menuBg
|
||
|
|
state.style.menuColor
|
||
|
|
state.style.menuActiveColor
|
||
|
|
```
|
||
|
|
|
||
|
|
### CSS Dynamic Bindings
|
||
|
|
|
||
|
|
```scss
|
||
|
|
height: v-bind('state.size.headHeight');
|
||
|
|
width: v-bind('state.size.asideWidth');
|
||
|
|
font-size: v-bind('state.size.fontSize');
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Anti-Patterns
|
||
|
|
|
||
|
|
1. **Do not directly mutate `state.size`** - Use `commit("initSize")` after changes
|
||
|
|
2. **Do not hardcode pixel values** - Use Vuex state for responsive design
|
||
|
|
3. **Do not skip path prefix check** - Always ensure paths start with `/`
|