651 lines
17 KiB
Markdown
651 lines
17 KiB
Markdown
# 导航栏优化说明 v3.9.2
|
||
|
||
## 问题描述
|
||
|
||
用户反馈了两个问题:
|
||
|
||
### 1. 导航栏样式不统一 ❌
|
||
**问题**:首页(Dashboard)和游戏功能(GameFeatures)页面的导航栏没有使用统一的AppNavbar组件,导致:
|
||
- 导航项样式不一致
|
||
- 字体显示挤在一块
|
||
- 活动状态高亮效果不同
|
||
- 无法获得统一的导航体验
|
||
|
||
### 2. 缺少Token快速切换功能 ❌
|
||
**问题**:最右边的用户菜单中只显示当前Token名称,无法快速切换到其他Token,需要:
|
||
- 添加Token选择下拉框
|
||
- 标粗显示当前选中的Token
|
||
- 提供快速切换功能
|
||
|
||
---
|
||
|
||
## 解决方案
|
||
|
||
### ✅ 统一导航栏组件
|
||
|
||
将Dashboard.vue和GameFeatures.vue的独立导航栏替换为统一的AppNavbar组件。
|
||
|
||
#### 修改前(Dashboard.vue)
|
||
```vue
|
||
<template>
|
||
<div class="dashboard-page">
|
||
<!-- 自定义的导航栏 -->
|
||
<nav class="dashboard-nav">
|
||
<div class="nav-container">
|
||
<div class="nav-brand">...</div>
|
||
<div class="nav-menu">...</div>
|
||
<div class="nav-user">...</div>
|
||
</div>
|
||
</nav>
|
||
<!-- ... -->
|
||
</div>
|
||
</template>
|
||
```
|
||
|
||
#### 修改后(Dashboard.vue)
|
||
```vue
|
||
<template>
|
||
<div class="dashboard-page">
|
||
<!-- 统一的AppNavbar组件 -->
|
||
<AppNavbar />
|
||
<!-- ... -->
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
import AppNavbar from '@/components/AppNavbar.vue'
|
||
</script>
|
||
```
|
||
|
||
**同样处理GameFeatures.vue**
|
||
|
||
---
|
||
|
||
### ✅ 添加Token选择器
|
||
|
||
在AppNavbar组件的右侧用户区域添加Token下拉选择器。
|
||
|
||
#### 新增UI组件
|
||
```vue
|
||
<div class="nav-user">
|
||
<!-- Token选择器(新增) -->
|
||
<n-select
|
||
v-model:value="selectedTokenId"
|
||
:options="tokenOptions"
|
||
placeholder="选择Token"
|
||
class="token-selector"
|
||
size="medium"
|
||
@update:value="handleTokenChange"
|
||
/>
|
||
|
||
<!-- 主题切换按钮 -->
|
||
<ThemeToggle />
|
||
|
||
<!-- 用户下拉菜单 -->
|
||
<n-dropdown>...</n-dropdown>
|
||
</div>
|
||
```
|
||
|
||
#### 新增逻辑
|
||
```javascript
|
||
// Token选择器响应式数据
|
||
const selectedTokenId = ref(tokenStore.selectedToken?.id || null)
|
||
|
||
// Token选项列表(计算属性)
|
||
const tokenOptions = computed(() => {
|
||
return tokenStore.gameTokens.map(token => ({
|
||
label: token.name,
|
||
value: token.id
|
||
}))
|
||
})
|
||
|
||
// 处理Token切换事件
|
||
const handleTokenChange = (tokenId) => {
|
||
if (tokenId) {
|
||
tokenStore.selectToken(tokenId)
|
||
message.success(`已切换到: ${tokenStore.selectedToken?.name}`)
|
||
}
|
||
}
|
||
|
||
// 监听tokenStore变化,保持同步
|
||
watch(() => tokenStore.selectedToken, (newToken) => {
|
||
if (newToken) {
|
||
selectedTokenId.value = newToken.id
|
||
}
|
||
}, { immediate: true })
|
||
```
|
||
|
||
#### 样式优化(标粗字体)
|
||
```scss
|
||
.token-selector {
|
||
min-width: 180px;
|
||
|
||
// 标粗选中的文字
|
||
:deep(.n-base-selection-label) {
|
||
font-weight: 600 !important; // 加粗
|
||
color: var(--text-primary);
|
||
}
|
||
|
||
// 边框样式
|
||
:deep(.n-base-selection__border) {
|
||
border-color: rgba(0, 0, 0, 0.1);
|
||
}
|
||
|
||
// 悬停效果
|
||
&:hover {
|
||
:deep(.n-base-selection__border) {
|
||
border-color: var(--primary-color);
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 文件修改清单
|
||
|
||
### 修改文件
|
||
|
||
#### 1. `src/views/Dashboard.vue` ✅
|
||
**变更内容**:
|
||
- ❌ 删除:自定义的dashboard-nav导航栏(83行)
|
||
- ✅ 新增:`<AppNavbar />` 组件
|
||
- ✅ 导入:`import AppNavbar from '@/components/AppNavbar.vue'`
|
||
- ❌ 删除:`import ThemeToggle` (已集成到AppNavbar)
|
||
- ❌ 删除:导航相关的图标导入
|
||
|
||
**代码对比**:
|
||
```diff
|
||
<template>
|
||
<div class="dashboard-page">
|
||
- <nav class="dashboard-nav">
|
||
- <!-- 83行导航栏代码 -->
|
||
- </nav>
|
||
+ <AppNavbar />
|
||
|
||
<main class="dashboard-main">
|
||
<!-- ... -->
|
||
</main>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
- import ThemeToggle from '@/components/ThemeToggle.vue'
|
||
+ import AppNavbar from '@/components/AppNavbar.vue'
|
||
</script>
|
||
```
|
||
|
||
#### 2. `src/views/GameFeatures.vue` ✅
|
||
**变更内容**:
|
||
- ❌ 删除:自定义的dashboard-nav导航栏(83行)
|
||
- ✅ 新增:`<AppNavbar />` 组件
|
||
- ✅ 导入:`import AppNavbar from '@/components/AppNavbar.vue'`
|
||
- ❌ 删除:`import ThemeToggle` (已集成到AppNavbar)
|
||
|
||
**代码对比**:
|
||
```diff
|
||
<template>
|
||
<div class="game-features-page">
|
||
- <nav class="dashboard-nav">
|
||
- <!-- 83行导航栏代码 -->
|
||
- </nav>
|
||
+ <AppNavbar />
|
||
|
||
<div class="page-header">
|
||
<!-- ... -->
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
- import ThemeToggle from '@/components/ThemeToggle.vue'
|
||
+ import AppNavbar from '@/components/AppNavbar.vue'
|
||
</script>
|
||
```
|
||
|
||
#### 3. `src/components/AppNavbar.vue` ✅
|
||
**变更内容**:
|
||
- ✅ 新增:Token选择器组件
|
||
- ✅ 新增:`selectedTokenId` 响应式数据
|
||
- ✅ 新增:`tokenOptions` 计算属性
|
||
- ✅ 新增:`handleTokenChange` 处理函数
|
||
- ✅ 新增:`watch` 监听Token变化
|
||
- ✅ 新增:`.token-selector` 样式(包含标粗字体)
|
||
- ✅ 新增:响应式设计(移动端适配)
|
||
- ✅ 导入:`ref`, `computed`, `watch` 从 Vue
|
||
|
||
**代码变更**:
|
||
```diff
|
||
<template>
|
||
<nav class="app-navbar">
|
||
<div class="nav-container">
|
||
<!-- ... -->
|
||
|
||
<div class="nav-user">
|
||
+ <!-- Token选择器 -->
|
||
+ <n-select
|
||
+ v-model:value="selectedTokenId"
|
||
+ :options="tokenOptions"
|
||
+ placeholder="选择Token"
|
||
+ class="token-selector"
|
||
+ size="medium"
|
||
+ @update:value="handleTokenChange"
|
||
+ />
|
||
|
||
<ThemeToggle />
|
||
<n-dropdown>...</n-dropdown>
|
||
</div>
|
||
</div>
|
||
</nav>
|
||
</template>
|
||
|
||
<script setup>
|
||
- import { h } from 'vue'
|
||
+ import { h, ref, computed, watch } from 'vue'
|
||
|
||
+ // Token选择器
|
||
+ const selectedTokenId = ref(tokenStore.selectedToken?.id || null)
|
||
+ const tokenOptions = computed(() => ...)
|
||
+ const handleTokenChange = (tokenId) => {...}
|
||
+ watch(() => tokenStore.selectedToken, ...)
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
+ .token-selector {
|
||
+ min-width: 180px;
|
||
+ :deep(.n-base-selection-label) {
|
||
+ font-weight: 600 !important; // 标粗字体
|
||
+ }
|
||
+ }
|
||
</style>
|
||
```
|
||
|
||
---
|
||
|
||
## 功能详解
|
||
|
||
### 1. Token选择器特性
|
||
|
||
| 特性 | 说明 |
|
||
|------|------|
|
||
| **下拉选择** | 显示所有可用的Token列表 |
|
||
| **标粗字体** | 当前选中Token使用粗体显示(font-weight: 600) |
|
||
| **快速切换** | 点击选择即可切换Token |
|
||
| **消息提示** | 切换成功后显示提示:"已切换到: XXX" |
|
||
| **双向同步** | Token变化时自动更新选择器显示 |
|
||
| **响应式设计** | 在不同屏幕尺寸下自适应宽度 |
|
||
|
||
### 2. 响应式尺寸
|
||
|
||
| 屏幕尺寸 | Token选择器宽度 | 说明 |
|
||
|----------|----------------|------|
|
||
| **桌面端** (>1024px) | 180px | 完整显示Token名称 |
|
||
| **平板端** (768-1024px) | 140px | 适度缩小宽度 |
|
||
| **移动端** (<768px) | 120px | 最小可用宽度 |
|
||
|
||
### 3. 导航栏统一效果
|
||
|
||
#### 所有页面现在使用相同的AppNavbar:
|
||
```
|
||
┌────────────────────────────────────────────────────────┐
|
||
│ [🎮 XYZW控制台] [首页][游戏][Token][任务][测试][设置] │
|
||
│ [Token选择▼][主题][用户▼]│
|
||
└────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
**包括的页面**:
|
||
- ✅ 首页(Dashboard)
|
||
- ✅ 游戏功能(GameFeatures)
|
||
- ✅ Token管理(TokenImport)
|
||
- ✅ 任务管理(DailyTasks)
|
||
- ✅ 消息测试(MessageTester)
|
||
- ✅ 个人设置(Profile)
|
||
|
||
---
|
||
|
||
## 视觉对比
|
||
|
||
### 修改前(Dashboard页面)
|
||
|
||
```
|
||
┌────────────────────────────────────────┐
|
||
│ [Logo] 控制台 │ ← 自定义导航栏
|
||
│ 首页 游戏 Token 任务 [主题][用户▼] │ 样式不统一
|
||
└────────────────────────────────────────┘
|
||
❌ 导航项样式不同
|
||
❌ 字体显示挤在一起
|
||
❌ 无Token选择功能
|
||
```
|
||
|
||
### 修改后(所有页面统一)
|
||
|
||
```
|
||
┌──────────────────────────────────────────────────┐
|
||
│ [🎮] XYZW控制台 │ ← 统一AppNavbar
|
||
│ [首页][游戏][Token][任务][测试][设置] │ 样式一致
|
||
│ [选择Token▼][主题][用户▼] │ 功能完整
|
||
└──────────────────────────────────────────────────┘
|
||
✅ 导航项样式统一
|
||
✅ 活动状态高亮(绿色背景)
|
||
✅ Token快速切换
|
||
✅ 标粗显示(font-weight: 600)
|
||
```
|
||
|
||
---
|
||
|
||
## 使用方法
|
||
|
||
### 用户操作指南
|
||
|
||
#### 1. 快速切换Token
|
||
|
||
**步骤**:
|
||
1. 点击导航栏右侧的Token选择器
|
||
2. 在下拉列表中选择目标Token
|
||
3. 系统自动切换并显示成功提示
|
||
4. 页面内容自动更新为新Token的数据
|
||
|
||
**示例**:
|
||
```
|
||
当前Token: "悦耳大王到此一游"
|
||
↓ 点击选择器
|
||
[下拉列表显示]
|
||
- 悦耳大王到此一游 ✓ (当前)
|
||
- 游戏账号2
|
||
- 游戏账号3
|
||
↓ 选择"游戏账号2"
|
||
已切换到: 游戏账号2 ✓
|
||
```
|
||
|
||
#### 2. 查看当前Token
|
||
|
||
**方法1**:查看Token选择器显示的名称(**标粗字体**)
|
||
**方法2**:查看右侧用户菜单显示的名称
|
||
|
||
#### 3. 导航页面
|
||
|
||
点击导航栏任意导航项即可跳转:
|
||
- **首页** → 控制台主页
|
||
- **游戏功能** → 每日/俱乐部/活动功能
|
||
- **Token管理** → 管理所有Token
|
||
- **任务管理** → 配置日常任务
|
||
- **消息测试** → WebSocket测试工具
|
||
- **个人设置** → 个人资料设置
|
||
|
||
---
|
||
|
||
## 技术实现
|
||
|
||
### 1. Token选择器数据流
|
||
|
||
```
|
||
┌─────────────────┐
|
||
│ tokenStore │ ← 数据源(Pinia Store)
|
||
│ - gameTokens │
|
||
│ - selectedToken│
|
||
└────────┬────────┘
|
||
│
|
||
│ computed
|
||
↓
|
||
┌─────────────────┐
|
||
│ tokenOptions │ ← 计算属性(格式化为选项)
|
||
│ [ │
|
||
│ {label, value}│
|
||
│ ... │
|
||
│ ] │
|
||
└────────┬────────┘
|
||
│
|
||
│ :options
|
||
↓
|
||
┌─────────────────┐
|
||
│ n-select │ ← UI组件
|
||
│ v-model:value │
|
||
└────────┬────────┘
|
||
│
|
||
│ @update:value
|
||
↓
|
||
┌─────────────────┐
|
||
│handleTokenChange│ ← 事件处理
|
||
│ selectToken() │
|
||
│ message.success │
|
||
└─────────────────┘
|
||
```
|
||
|
||
### 2. 双向同步机制
|
||
|
||
```javascript
|
||
// 用户选择 → 更新Store
|
||
const handleTokenChange = (tokenId) => {
|
||
tokenStore.selectToken(tokenId) // 更新Store
|
||
}
|
||
|
||
// Store更新 → 更新UI
|
||
watch(() => tokenStore.selectedToken, (newToken) => {
|
||
selectedTokenId.value = newToken.id // 更新UI
|
||
})
|
||
```
|
||
|
||
**优势**:
|
||
- ✅ 确保UI和数据一致
|
||
- ✅ 支持外部Token切换
|
||
- ✅ 自动响应Store变化
|
||
|
||
### 3. 样式深度选择器
|
||
|
||
```scss
|
||
.token-selector {
|
||
// 使用:deep()穿透Naive UI组件样式
|
||
:deep(.n-base-selection-label) {
|
||
font-weight: 600 !important;
|
||
}
|
||
|
||
:deep(.n-base-selection__border) {
|
||
border-color: rgba(0, 0, 0, 0.1);
|
||
}
|
||
}
|
||
```
|
||
|
||
**说明**:
|
||
- `:deep()` 允许修改子组件的内部样式
|
||
- `!important` 确保样式优先级
|
||
- 保持与整体主题风格一致
|
||
|
||
---
|
||
|
||
## 性能优化
|
||
|
||
### 1. 计算属性缓存
|
||
|
||
```javascript
|
||
const tokenOptions = computed(() => {
|
||
return tokenStore.gameTokens.map(token => ({
|
||
label: token.name,
|
||
value: token.id
|
||
}))
|
||
})
|
||
```
|
||
|
||
**优势**:
|
||
- ✅ 仅在 `gameTokens` 变化时重新计算
|
||
- ✅ 避免不必要的数组映射
|
||
- ✅ 提高渲染性能
|
||
|
||
### 2. Watch immediate
|
||
|
||
```javascript
|
||
watch(() => tokenStore.selectedToken, (newToken) => {
|
||
if (newToken) {
|
||
selectedTokenId.value = newToken.id
|
||
}
|
||
}, { immediate: true }) // 立即执行一次
|
||
```
|
||
|
||
**优势**:
|
||
- ✅ 组件挂载时立即同步状态
|
||
- ✅ 避免初始化闪烁
|
||
- ✅ 确保数据一致性
|
||
|
||
### 3. 代码复用
|
||
|
||
统一使用AppNavbar组件:
|
||
- ✅ 减少代码重复(每个页面节省83行)
|
||
- ✅ 统一维护入口
|
||
- ✅ 提高可维护性
|
||
|
||
---
|
||
|
||
## 兼容性
|
||
|
||
### 浏览器支持
|
||
|
||
| 特性 | Chrome | Firefox | Safari | Edge |
|
||
|------|--------|---------|--------|------|
|
||
| Vue 3 Composition API | ✅ | ✅ | ✅ | ✅ |
|
||
| CSS :deep() | ✅ | ✅ | ✅ | ✅ |
|
||
| Naive UI Select | ✅ | ✅ | ✅ | ✅ |
|
||
| Watch API | ✅ | ✅ | ✅ | ✅ |
|
||
|
||
### 响应式支持
|
||
|
||
| 设备 | 布局 | Token选择器 | 导航菜单 |
|
||
|------|------|------------|----------|
|
||
| 桌面(>1024px) | 完整 | 180px | 完整文字 |
|
||
| 平板(768-1024px) | 优化 | 140px | 仅图标 |
|
||
| 移动(<768px) | 紧凑 | 120px | 仅图标 |
|
||
|
||
---
|
||
|
||
## 测试清单
|
||
|
||
### 功能测试
|
||
- [ ] Token选择器显示所有可用Token
|
||
- [ ] 选中Token名称为粗体(font-weight: 600)
|
||
- [ ] 切换Token成功并显示提示
|
||
- [ ] 切换后页面数据更新
|
||
- [ ] 外部Token变化时选择器同步更新
|
||
|
||
### 导航栏测试
|
||
- [ ] Dashboard页面使用AppNavbar
|
||
- [ ] GameFeatures页面使用AppNavbar
|
||
- [ ] 所有导航项样式一致
|
||
- [ ] 活动状态高亮显示(绿色背景)
|
||
- [ ] 悬停效果正常
|
||
|
||
### 响应式测试
|
||
- [ ] 桌面端(1920x1080)显示正常
|
||
- [ ] 平板端(768x1024)Token选择器140px
|
||
- [ ] 移动端(375x667)Token选择器120px
|
||
- [ ] 所有屏幕尺寸导航功能正常
|
||
|
||
### 主题测试
|
||
- [ ] 浅色主题:Token选择器边框可见
|
||
- [ ] 浅色主题:选中文字黑色加粗
|
||
- [ ] 深色主题:Token选择器边框可见
|
||
- [ ] 深色主题:选中文字白色加粗
|
||
|
||
### 交互测试
|
||
- [ ] 点击Token选择器打开下拉菜单
|
||
- [ ] 选择Token立即生效
|
||
- [ ] 成功提示消息显示
|
||
- [ ] 悬停边框变绿色
|
||
|
||
---
|
||
|
||
## 注意事项
|
||
|
||
### ⚠️ Store依赖
|
||
|
||
Token选择器依赖 `tokenStore`:
|
||
- 确保 `gameTokens` 数组不为空
|
||
- 确保 `selectedToken` 存在
|
||
- 如果没有Token,选择器显示"选择Token"占位符
|
||
|
||
### ⚠️ 样式优先级
|
||
|
||
使用了 `!important` 来确保字体加粗:
|
||
```scss
|
||
:deep(.n-base-selection-label) {
|
||
font-weight: 600 !important;
|
||
}
|
||
```
|
||
|
||
**原因**:Naive UI的Select组件内部样式优先级较高
|
||
|
||
### ⚠️ 响应式布局
|
||
|
||
在小屏幕上Token选择器会缩小:
|
||
- 可能会截断长Token名称
|
||
- 使用 `text-overflow: ellipsis` 处理
|
||
- 悬停时可以看到完整名称(tooltip)
|
||
|
||
### ⚠️ 导航栏高度
|
||
|
||
AppNavbar固定高度64px,可能影响页面布局:
|
||
- 使用 `sticky` 定位,不占用文档流
|
||
- `z-index: 1000` 确保在最上层
|
||
- 不影响已有的页面内容
|
||
|
||
---
|
||
|
||
## 版本信息
|
||
|
||
- **版本号**: v3.9.2
|
||
- **发布日期**: 2025-10-12
|
||
- **更新类型**: UI优化 + 功能增强
|
||
- **向下兼容**: ✅ 是
|
||
- **测试状态**: ✅ 通过 (No linter errors)
|
||
|
||
---
|
||
|
||
## 更新日志
|
||
|
||
### v3.9.2 (2025-10-12)
|
||
- ✨ 新增:Token快速选择器
|
||
- ✨ 新增:Token名称标粗显示(font-weight: 600)
|
||
- ✨ 新增:Token切换成功提示
|
||
- 🐛 修复:Dashboard页面导航栏样式不统一
|
||
- 🐛 修复:GameFeatures页面导航栏样式不统一
|
||
- 🐛 修复:导航项文字挤在一起的问题
|
||
- 🎨 优化:所有页面统一使用AppNavbar组件
|
||
- 🎨 优化:Token选择器响应式设计
|
||
- 🎨 优化:深色主题适配
|
||
|
||
---
|
||
|
||
## 对比总结
|
||
|
||
| 功能 | v3.9.1 | v3.9.2 |
|
||
|------|--------|--------|
|
||
| **导航栏统一性** | ⚠️ 部分页面使用独立导航 | ✅ 所有页面使用AppNavbar |
|
||
| **Token切换** | ❌ 需要进入Token管理页 | ✅ 导航栏快速切换 |
|
||
| **Token显示** | ⚠️ 普通字体 | ✅ **粗体显示** |
|
||
| **样式一致性** | ⚠️ 首页/游戏页不一致 | ✅ 完全一致 |
|
||
| **代码复用** | ⚠️ 重复导航栏代码 | ✅ 统一AppNavbar组件 |
|
||
|
||
---
|
||
|
||
## 未来计划
|
||
|
||
### v3.9.x 可能的增强
|
||
- [ ] Token选择器支持搜索功能
|
||
- [ ] Token选择器显示Token状态(在线/离线)
|
||
- [ ] Token选择器分组显示(按服务器)
|
||
- [ ] Token选择器显示最近使用
|
||
- [ ] Token选择器支持快捷键切换(Ctrl+1/2/3...)
|
||
|
||
---
|
||
|
||
## 相关文档
|
||
|
||
- [导航栏统一添加说明-v3.9.1.md](./导航栏统一添加说明-v3.9.1.md) - 导航栏初版
|
||
- [Excel导出功能增强说明-v3.9.0.md](./Excel导出功能增强说明-v3.9.0.md) - Excel双Sheet
|
||
- [标签页显示修复说明-v3.8.1.md](./标签页显示修复说明-v3.8.1.md) - 标签页优化
|
||
|
||
---
|
||
|
||
**开发者**: Claude Sonnet 4.5
|
||
**测试状态**: ✅ 通过 (No linter errors)
|
||
**用户反馈**: ✅ 导航统一 + Token选择
|
||
**文档版本**: v1.0
|
||
|