《金融行业前端探索》(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周一篇

相关推荐
鑫~阳6 分钟前
html + css 淘宝网实战
前端·css·html
Catherinemin10 分钟前
CSS|14 z-index
前端·css
漫天转悠11 分钟前
Vue3项目中引入TailwindCSS(图文详情)
vue.js
qq_589568101 小时前
Echarts+vue电商平台数据可视化——后台实现笔记
vue.js·信息可视化·echarts
2401_882727572 小时前
低代码配置式组态软件-BY组态
前端·后端·物联网·低代码·前端框架
NoneCoder2 小时前
CSS系列(36)-- Containment详解
前端·css
anyup_前端梦工厂2 小时前
初始 ShellJS:一个 Node.js 命令行工具集合
前端·javascript·node.js
5hand2 小时前
Element-ui的使用教程 基于HBuilder X
前端·javascript·vue.js·elementui
GDAL2 小时前
vue3入门教程:ref能否完全替代reactive?
前端·javascript·vue.js
六卿2 小时前
react防止页面崩溃
前端·react.js·前端框架