《金融行业前端探索》(2)使用electron-vite-vue 搭建一个金融终端框架

申明:本文为稀土掘金技术社区首发签约文章,30天内禁止转载,30天后未获授权禁止转载,侵权必究!

前言

《金融行业前端探索》专题系列文章将构建现代化金融应用的技术与实践,提供理论知识和技术原理,还通过丰富的案例和实例,带大家一步步实现一个简易的金融终端系统,帮助读者将所学知识应用于实际项目中。此系列文章,适用于对金融行业前端感兴趣的同学,以及对前端跨端、可视化、AI技术、大数据等方面感兴趣的同学。需要提前了解技术:electron、vite、vue,canvas和其他前端基础知识等。

本文为《金融行业前端探索》第2篇文章 :使用electron-vite-vue 搭建一个金融终端框架,包含以下内容:

【1】前文《金融行业前端探索》第1篇回顾之登录到系统框架(闪烁问题优化)

【2】系统框架导航和菜单(基于ElementUI实现)

【3】系统底部内容轮播功能设计和实现(纯CSS3方案)

【4】系统实现新手引导功能的设计和实现(canvas遮罩层+DOM方案)

本项目完整代码地址:electron-vite-vue-ft(持续更新代码)

图片来源

下一篇: 《金融行业前端探索》(2)行情图

一、前文回顾之登录到系统框架-解决登录闪烁问题

上回我们在《金融行业前端探索:开篇使用electron-vite-vue 搭建一个金融终端框架之登录功能》 中讲到了登录,我们要跳转到系统的框架页面。这里我们正常思维是,点击登录按钮做登录校验,随后跳到系统框架页面,使用 Electron 的 remote 模块来获取对主进程中 BrowserWindow 实例的引用,并调用其 setSize 方法来更改宽度和高度。同时,使用 screen 模块获取屏幕尺寸,并计算出居中显示时的坐标位置。

js 复制代码
const { remote, screen } = require('electron');

const button = document.getElementById('resizeButton');
button.addEventListener('click', () => {
  const { BrowserWindow } = remote;
  const mainWindow = BrowserWindow.getFocusedWindow();
  if (mainWindow) {
    const { width, height } = screen.getPrimaryDisplay().workAreaSize;
    const newWidth = 800; // 设置新的宽度
    const newHeight = 600; // 设置新的高度
    const x = Math.floor((width - newWidth) / 2); // 计算居中的 x 坐标
    const y = Math.floor((height - newHeight) / 2); // 计算居中的 y 坐标
    mainWindow.setSize(newWidth, newHeight); // 设置新的宽度和高度
    mainWindow.setPosition(x, y); // 设置窗口位置为居中
  }
});

但现实中我们运行的时候发现,从登录页面到首页框架加载页面时出现出现闪烁

于是我们正常思维使用隐藏和显示的方式:在加载新页面之前,将窗口隐藏起来,然后在新页面加载完成后再显示窗口。这样,用户将不会看到加载过程中的闪烁。

js 复制代码
// 
function handleButtonClick() {
  // 隐藏窗口
  mainWindow.hide();
  // 加载新的页面
  mainWindow.loadURL(winURL);
  // 监听新页面加载完成事件
  mainWindow.webContents.once('did-finish-load', () => {
    // 显示窗口
    mainWindow.show();
  });
}

通过验证,这个方式并不理想,于是就使用了另外一个方案,登录和首页实例进行拆分进行处理。在登录切换页面的时候,把登录页面的实例销毁。这样相比看起来体验好一些

js 复制代码
  ipcMain.on('openMainWindow', () => {
    if (!mainWindow) {
      createMainWindow()
    }
    loginWindow.destroy()
    loginWindow = null
  })

二、系统框架导航和菜单

导航栏的默认状态让界面整体的信息从左到右呈现出疏密布局,当用户需更大限度利用屏幕空间浏览内容时,可调整导航栏的宽窄状态,可以拉伸导航栏展示。让内容区域可以最大范围展示出来。

菜单的获取和用户角色对应起来,不同的角色可以配置不同的菜单,所以关于菜单需要有一套配套的用户中心系统搭配。这里是基于ElementUI plusel-menu组件 做了一个简单的实现

实现可以参考代码src\renderer\src\components\Layout\leftMenu.vue

三、系统底部功能实现

底部左侧滚动轮播内容功能

底部左侧功能通常为指数行情或者一些新闻滚动功能。当鼠标经过的时候,内容区域不再滚动,方便使用者看到实时的相关数据。

这里推荐一个最简单的实用css方案,我们以指数行情为例,我们将元素的文本内容水平展示在一行中不换行,并对元素应用名为 myAnimation 的动画效果。该动画效果将在持续 50 秒的时间内,以线性的速度循环播放,从元素的初始位置开始,没有延迟。当鼠标经过的时候动画效果停止在当前内容上。

css 复制代码
@keyframes myAnimation {
  0% {
    transform: translate(0);
  } /* 初始状态 */
  100% {
    transform: translate(-50%);
  } /* 结束状态 */
}
....

    .left-market {
      display: flex;
      align-items: center;
      white-space: nowrap;
      transform: translate(0);
      animation: myAnimation 50s linear 0s infinite;
      &:hover {
        animation-play-state: paused;
      }
  1. white-space: nowrap;:这个属性指定了元素内文本的处理方式。nowrap 表示文本不换行,将在一行内显示。这通常用于确保文本不会自动换行,而是水平展示。

  2. transform: translate(0);:这个属性通过 translate 函数对元素进行平移变换。在这个例子中,translate(0) 表示元素不进行任何平移,保持原始位置不变。

  3. animation: myAnimation 50s linear 0s infinite;:这个属性用于创建和控制动画效果。其中的值解释如下:

    • myAnimation 是指定要应用的关键帧动画的名称。
    • 50s 指定动画的持续时间为 50 秒。
    • linear 表示动画的时间函数为线性,即在整个动画过程中速度是恒定的。
    • 0s 表示动画延迟开始的时间为 0 秒。这表示动画将立即开始,没有延迟。
    • infinite 表示动画循环次数为无限。动画将一直循环播放,不会停止
  4. animation-play-state: paused用于控制动画的播放状态。当设置为 paused 时,动画将被暂停,停留在当前的帧上。

效果如下

为了美观,我们在滚动内容 前后 加上一个内容出现和消失过渡渐变,使得显示更加的平滑,这里我们通过css的伪类和background-image: linear-gradient 背景呈现为一个渐变的背景效果

css 复制代码
   &:before {
      content: '';
      position: absolute;
      top: 0;
      left: 0;
      width: 20px;
      height: 100%;
      background-image: linear-gradient(90deg, #212529, rgba(33, 37, 41, 0.15) 70%, transparent);
      z-index: 1;
    }
    &:after {
      content: '';
      position: absolute;
      top: 0;
      right: 0;
      width: 20px;
      height: 100%;
      background-image: linear-gradient(-90deg, #212529, rgba(33, 37, 41, 0.15) 70%, transparent);
      z-index: 1;
    }

实现可以参考代码src\renderer\src\components\Layout\foot.vue

四、系统实现新手引导功能

系统实现新手引导功能的意义在于提供用户友好的指引和引导,帮助新用户熟悉和金融行业系统的功能和界面。

以下是一些通用的新手引导功能主要的意义和好处:

  1. 提高用户体验(UX)和用户满意度: 新手引导功能可以帮助用户快速上手和熟悉应用程序,减少用户的困惑和迷失感。通过向用户提供明确的指引和说明,用户可以更轻松地完成任务,并更好地理解应用程序的功能和价值。
  2. 降低用户学习成本: 对于新用户来说,了解一个全新的应用程序可能需要一定的学习曲线。通过引导功能,用户可以在最初的使用阶段得到指导,从而减少学习成本和学习时间。这可以提高用户的学习效率和使用效果。
  3. 减少用户错误和操作失误: 新手引导功能可以帮助用户避免常见的错误和操作失误。通过引导用户正确地进行操作和输入,可以减少用户因不熟悉应用程序而导致的错误,从而提高用户的准确性和效率。
  4. 推广核心功能和价值: 引导功能可以突出和介绍应用程序的核心功能和价值,引导用户关注和了解最重要的功能。这有助于传达应用程序的独特卖点和价值主张,提高用户对应用程序的认知和理解。
  5. 增加用户参与度和留存率: 通过帮助用户快速熟悉应用程序并获得成功体验,新手引导功能可以增加用户的参与度和留存率。用户在初期获得积极的体验和成就感,更有可能继续使用应用程序并成为忠实用户。

新手引导功能实现思考

  1. 目前市面上有一些轮子可以用,比如driver.js 但业务千般万难,一些定制化的情况通用的轮子,无法满足自身的业务需求(样式、配置项多而杂、未知BUG维护),所以自行实现一个新手引导功能很有必要
  2. 新手引导功能核心点是,配置项的设计,遮罩层的设计,功能的定义(上一步、下一步、窗口变化监听)

新手引导实现具体步骤

配置项设计

配置项这里我们简单设计了支持基本的,新手引导需要的元素为"上一步 "、"下一步 "、"完成 "、"跳过 "、"每一步信息配置"等功能。

js 复制代码
config = {
  prevLabel: '上一步',
  nextLabel: '下一步',
  skipLabel: '跳过',
  doneLabel: '完成',
  steps: [
    {
      domId: 'logoid',
      title: 'logo区域',
      content: '这里是展示的系统logo,点击可以回到首页内容',
      width: 270, //(可选)框选区域自定义宽度,当不指定时,组件自动取目标元素的宽度
      height: 120 //(可选)框选区域自定义高度,当不指定时,组件自动取目标元素的高度
    }
    ]
   }

遮罩层的设计和实现

如何添加遮罩层? 目前行业上比较多的方案是(1) 通过CSS属性实现 用dom拼成中间留白的阴影(2)也有背景图+DOM的组合等等

我们这里采用 canvas 绘制遮罩层,任意一个dom,通过id,查找到这个dom 的宽高,并插入一个遮罩层canvas,这个dom的区域留白不遮罩,其他地方有遮罩

  1. 在 Vue 组件中,使用 ref 属性给目标 DOM 元素添加一个引用。例如,给目标 DOM 元素添加 ref="targetElement"
  2. 在需要获取宽高并插入遮罩层的逻辑中,可以使用 getBoundingClientRect() 方法来获取目标 DOM 元素的宽高和位置信息。
  3. 创建一个遮罩层的 Canvas 元素,并设置其样式和大小,使其覆盖整个页面。
  4. 使用 ctx.clearRect() 方法清除遮罩层 Canvas 上的区域,以实现目标 DOM 元素的区域留白。
  5. 使用 ctx.fillRect() 方法在遮罩层 Canvas 上绘制需要遮罩的区域
js 复制代码
const addMask = (domId) => {
  const targetElement = document.getElementById(domId)
  const maskCanvas = maskCanvasRef.value
  console.log('maskCanvas', maskCanvas)
  const ctx = maskCanvas.getContext('2d')

  // 获取目标 DOM 元素的宽高和位置信息
  const { width, height, top, left } = targetElement.getBoundingClientRect()

  // 设置遮罩层 Canvas 的样式和大小
  maskCanvas.style.position = 'fixed'
  maskCanvas.style.top = '0'
  maskCanvas.style.left = '0'
  maskCanvas.style.width = '100%'
  maskCanvas.style.height = '100%'
  maskCanvas.width = window.innerWidth
  maskCanvas.height = window.innerHeight

  // 清除遮罩层 Canvas 上的区域
  ctx.clearRect(0, 0, maskCanvas.width, maskCanvas.height)

  // 绘制遮罩层 Canvas 上的遮罩区域
  ctx.fillStyle = 'rgba(0, 0, 0, 0.6)'
  ctx.fillRect(0, 0, maskCanvas.width, maskCanvas.height)
  ctx.clearRect(left, top, width, height)
}

说明模块设计和实现

制定宽高的 div 作为说明模块,这个div,根据浏览器大小自适应与之前的targetElement的边上 ,并不遮住targetElement,说明模块位置,优先级:右>左>下>上

js 复制代码
// 控制 右侧优先 再左侧
const handleLeftOrRight = (infoModule, targetRect, infoModuleRect, innerWidth, innerHeight) => {
  // 默认右侧
  if (targetRect.right + infoModuleRect.width <= innerWidth) {
    infoModule.style.left = targetRect.right + 'px'
  } else if (targetRect.left - infoModuleRect.width >= 0) {
    // 左侧
    infoModule.style.left = targetRect.left - infoModuleRect.width + 'px'
  }
}

// 控制上下
const handleTopOrBottom = (infoModule, targetRect, infoModuleRect, innerHeight) => {
  let top = 0
  if (targetRect.bottom + infoModuleRect.height <= innerHeight) {
    top = targetRect.bottom - targetRect.height
  } else if (targetRect.top - infoModuleRect.height >= 0) {
    // 上方
    top = targetRect.top + targetRect.height - infoModuleRect.height
  }

  infoModule.style.top = top + 'px'
}

说明模块的 <div> 添加了 z-index: 1 的样式属性,以确保说明模块位于遮罩层之上。同时,遮罩层的 <canvas> 元素添加了 z-index: 0 的样式属性,使其位于说明模块之下。

监听窗口变化

因为遮罩层和说明模块的位置都是依赖于浏览器的窗口大小变化,定位的,所以窗口变化的时候,遮罩层和说明模块也要同步的更改相对位置。

js 复制代码
onMounted(() => {
  nextTick(() => {
    handleIntro()
    window.addEventListener('resize', handleIntro)
  })
})

这样一个简易的新手引导功能就完成了,当然其中可以自行进行拓展,比如支持图片设置,支持鼠标上下左右键盘联动等功能。

最后

本文从前文回顾之登录到系统框架、到系统框架导航和菜单、底部内容轮播功能实现、系统实现新手引导功能带大家一一实现了对应的功能。这样一个大概的金融系统的框架已经基本成型。

本项目完整代码地址:electron-vite-vue-ft(持续更新代码)

下一篇: 《金融行业前端探索》(3)玩转可视化图表:Vue3+Echarts绘制k线行情图

ps: 暂未编写,更新速度 1-2周一篇

相关推荐
崔庆才丨静觅14 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby606115 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了15 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅15 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅16 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅16 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment16 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅16 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊16 小时前
jwt介绍
前端
爱敲代码的小鱼16 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax