返回博客

1. 方案概要
本方案实现了一个全自动的页面向导系统,主要特点包括:
- 路由驱动:基于 Vue Router 的导航守卫自动触发向导
- 集中配置:所有页面的向导内容统一管理在 TourContent.ts
- 版本控制:向导步骤支持版本过滤,只显示适用版本的内容
- 状态持久化:使用 localStorage 记录用户完成状态
- 响应式设计:自动适应不同页面布局和元素
核心组件
文件 | 功能 |
---|---|
App.vue | 应用入口,集成路由和向导组件 |
SystemTour.vue | 向导展示组件,负责渲染引导步骤 |
ViewManagement.ts | Pinia 存储,管理向导状态和逻辑 |
TourContent.ts | 向导内容配置,按页面组织步骤 |
2. 处理流程
2.1 整体流程图
2.2 详细步骤说明
- 路由导航
- 用户访问新页面
- Vue Router 触发 afterEach 钩子
- 视图更新
- 在 App.vue 中调用 viewManagementStore.setCurrentView()
- 更新当前视图名称
- 状态检查
- 检查该视图的向导是否已完成
- 比较完成版本与当前应用版本
- 向导加载
- 从 TourContent.ts 加载当前视图的向导配置
- 过滤出符合当前版本的步骤
- 更新状态存储中的向导步骤
- 向导显示
- SystemTour.vue 检测到步骤更新
- 延迟 1.5 秒确保 DOM 渲染完成
- 显示符合条件的向导步骤
- 向导完成
- 用户完成所有步骤
- 调用 viewManagementStore.setTourCompleted()
- 保存完成状态到 localStorage
3. 配置方法
3.1 向导内容配置 (TourContent.ts)
TourContent.ts
// 欢迎页面向导配置
tourSteps['welcome'] = [
{
title: '欢迎',
description: '欢迎使用系统...',
version: '1.0.0'
},
{
title: '创建学生信息',
description: '点击按钮创建学生...',
target: '#add-student',
version: '1.0.0'
}
]
// 成绩分析页面向导配置
tourSteps['performance_chart'] = [
{
title: '显示内容切换',
description: '点击按钮切换图表/数据视图...',
target: '#swith-modal',
version: '1.0.0'
}
]
3.2 配置参数说明
参数 | 类型 | 必填 | 说明 | 示例 |
---|---|---|---|---|
title | string | 是 | 步骤标题 | "欢迎使用" |
description | string | 是 | 步骤详细描述 | "这是系统引导的第一步" |
target | string | 否 | 目标元素选择器 | "#add-student" |
placement | string | 否 | 引导框位置 | "right", "bottom" |
version | string | 否 | 最低适用版本 | "1.0.0" |
3.3 版本控制规则
- 未设置版本:始终显示该步骤
- 设置了版本:
- 当前版本 ≥ 步骤版本:显示
- 当前版本 < 步骤版本:隐藏
- 版本格式:主版本.次版本.修订号(如 1.2.3)
- 比较逻辑:
// 版本比较函数
const compareVersions = (v1: string, v2: string): boolean => {
const parts1 = v1.split('.').map(Number)
const parts2 = v2.split('.').map(Number)
for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) {
const num1 = parts1[i] || 0
const num2 = parts2[i] || 0
if (num1 !== num2) return num1 >= num2
}
return true
}
3.4 状态存储配置 (ViewManagement.ts)
ViewManagement.ts
// 初始化状态
initState() {
const completedInfoStr = localStorage.getItem('CompletedTour')
this.completed = completedInfoStr ? JSON.parse(completedInfoStr) : {}
}
// 设置当前视图
setCurrentView(name: string) {
// 检查是否已完成
const completedVersion = this.completed[name]
const isCompleted = completedVersion &&
compareVersions(completedVersion, this.appVersion)
// 加载并过滤步骤
if (!isCompleted) {
const viewSteps = tourSteps[name] || []
this.viewTourSteps = viewSteps.filter(step =>
!step.version || compareVersions(step.version, this.appVersion)
)
}
this.currentView = name
}
// 标记向导完成
setTourCompleted() {
this.completed[this.currentView] = this.appVersion
localStorage.setItem('CompletedTour', JSON.stringify(this.completed))
this.viewTourSteps = []
}
3.5 向导组件集成 (App.vue)
App.vue
<script setup>
import { useRouter } from 'vue-router'
import { viewManagement } from '@renderer/stores/ViewManagement'
const router = useRouter()
const viewManagementStore = viewManagement()
router.afterEach((to) => {
if (to.name) {
nextTick(() => {
viewManagementStore.setCurrentView(to.name.toString())
})
}
})
</script>
<template>
<RouterView />
<SystemTour />
</template>
3.6 自定义向导样式 (SystemTour.vue)
SystemTour.vue
/* 渐变背景 */
.el-tour__content {
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
border: 1px solid rgba(255, 255, 255, 0.3);
backdrop-filter: blur(5px);
}
/* 标题样式 */
.el-tour__title {
color: #2c3e50;
font-weight: 600;
font-size: 18px;
}
/* 指示器激活状态 */
.el-tour__indicator--active {
background: linear-gradient(to right, #4facfe 0%, #00f2fe 100%);
width: 16px;
border-radius: 4px;
}