返回博客

Tuesday, August 5, 2025

【技术方案】全自动页面向导系统实现方案

cover

1. 方案概要

本方案实现了一个全自动的页面向导系统,主要特点包括:

  • 路由驱动:基于 Vue Router 的导航守卫自动触发向导
  • 集中配置:所有页面的向导内容统一管理在 TourContent.ts
  • 版本控制:向导步骤支持版本过滤,只显示适用版本的内容
  • 状态持久化:使用 localStorage 记录用户完成状态
  • 响应式设计:自动适应不同页面布局和元素
核心组件
文件功能
App.vue应用入口,集成路由和向导组件
SystemTour.vue向导展示组件,负责渲染引导步骤
ViewManagement.tsPinia 存储,管理向导状态和逻辑
TourContent.ts向导内容配置,按页面组织步骤

2. 处理流程

2.1 整体流程图

2.2 详细步骤说明

  1. 路由导航
    • 用户访问新页面
    • Vue Router 触发 afterEach 钩子
  2. 视图更新
    • 在 App.vue 中调用 viewManagementStore.setCurrentView()
    • 更新当前视图名称
  3. 状态检查
    • 检查该视图的向导是否已完成
    • 比较完成版本与当前应用版本
  4. 向导加载
    • 从 TourContent.ts 加载当前视图的向导配置
    • 过滤出符合当前版本的步骤
    • 更新状态存储中的向导步骤
  5. 向导显示
    • SystemTour.vue 检测到步骤更新
    • 延迟 1.5 秒确保 DOM 渲染完成
    • 显示符合条件的向导步骤
  6. 向导完成
    • 用户完成所有步骤
    • 调用 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 配置参数说明

参数类型必填说明示例
titlestring步骤标题"欢迎使用"
descriptionstring步骤详细描述"这是系统引导的第一步"
targetstring目标元素选择器"#add-student"
placementstring引导框位置"right", "bottom"
versionstring最低适用版本"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;
}