工业仿真(simulation)--前端(七)--消息栏

在这篇文章中,主要讲解仿真软件的消息栏

那在我们的仿真软件中,消息栏是分为三部分的

  • 系统提示消息【包括打开某个窗口,系统出现了某个警告,错误,网络连接等等】
  • 画布操作消息【对画布的一切操作都会记录在上面,类似于一个历史操作步骤】
  • 仿真控制器【控制仿真的组件】

如图一,二,三

图一 提示消息

图二 画布操作

图三 仿真控制器

在这三个组件中,只有图二不需要和主进程进行通信,提示消息需要监听主进程发送的消息,比如说当有其他渲染进程有重要消息时,就需要通过主进程将消息传递给提示组件

其他渲染进程📢 --> 主进程 --> 👂消息组件

首先说一下提示和画布操作,这两个有异曲同工的地方

提示和画布

先看代码 message.ts

ts 复制代码
import { defineStore } from 'pinia'
import { CanvasOperateType, Message } from '@renderer/types/message'
import { generateUUID } from '@renderer/utils/utils'
import dayjs from 'dayjs'
import { nextTick } from 'vue'

export const useMessageStore = defineStore('message', {
  state: () => ({
    activeTab: 'prompt' as 'prompt' | 'canvas' | 'simControler',

    prompt: [] as Message[],
    messageContentRef: null as HTMLElement | null,
    showNewMessage: false as boolean,

    canvasOperate: [] as CanvasOperateType[],
    canvasOperateContentRef: null as HTMLElement | null
  }),
  actions: {
    //切换tab
    changeTab(tab: 'prompt' | 'canvas' | 'simControler') {
      this.activeTab = tab
    },

    //添加信息
    addPrompt(message: Message) {
      const msg = {} as Message
      //设置id
      msg.id = generateUUID()
      //获取当前时间
      msg.time = dayjs().format('HH:mm:ss')

      msg.content = message.content
      msg.source = message.source
      msg.type = message.type

      //判断当前消息内容是否和上一条消息内容一样
      if (this.prompt.length > 0 && this.prompt[this.prompt.length - 1].content === msg.content) {
        //获取上一条消息的次数,如果没有就默认为1
        const count = this.prompt[this.prompt.length - 1].count || 1
        //设置当前消息的次数
        msg.count = count + 1
        //删除上一条消息
        this.prompt.pop()
      }

      //判断消息是否超过了200条
      if (this.prompt.length > 200) {
        //删除前一百条
        this.prompt.splice(0, 100)
      }
      this.prompt.push(msg)

      if (this.activeTab !== 'prompt') {
        this.showNewMessage = true
      }

      nextTick(() => {
        //将messageContentRef滚动条滚动到最后
        if (this.messageContentRef) {
          this.messageContentRef.scrollTop = this.messageContentRef.scrollHeight
        }
      })
    },

    //添加画布操作信息
    addCanvasOperate(message: CanvasOperateType) {
      const msg = {} as CanvasOperateType
      //设置id
      msg.id = generateUUID()
      //获取当前时间
      msg.time = dayjs().format('HH:mm:ss')

      msg.content = message.content
      msg.source = message.source
      msg.otherMsg = message.otherMsg

      this.judgeCanvasOperate(msg)
      nextTick(() => {
        //将canvasOperateContentRef滚动条滚动到最后
        if (this.canvasOperateContentRef) {
          this.canvasOperateContentRef.scrollTop = this.canvasOperateContentRef.scrollHeight
        }
      })
    },

    //对画布操作进行判断
    judgeCanvasOperate(msg: CanvasOperateType) {
      //判断当前消息内容是否和上一条消息内容一样
      if (
        this.canvasOperate.length > 0 &&
        this.canvasOperate[this.canvasOperate.length - 1].content === msg.content
      ) {
        //获取上一条消息的次数,如果没有就默认为1
        const count = this.canvasOperate[this.canvasOperate.length - 1].count || 1
        //设置当前消息的次数
        msg.count = count + 1
        //删除上一条消息
        this.canvasOperate.pop()
      }

      //判断消息是否超过了200条
      if (this.canvasOperate.length > 200) {
        this.canvasOperate.splice(0, 100)
      }

      this.canvasOperate.push(msg)
    },

    //清除消息
    clearMessage() {
      if (this.activeTab === 'prompt') {
        this.prompt = []
      } else {
        this.canvasOperate = []
      }
    }
  }
})

提示的数据格式和画布操作的格式是差不多的

ts 复制代码
export interface Message {
  id?: string
  time?: string
  source?: string
  content: string
  type?: 'info' | 'warning' | 'error' | 'success'
  count?: number
}

export interface CanvasOperateType {
  id?: string
  time?: string
  source: string
  content: string
  otherMsg?: string
  count?: number
}
  • id:位移ID值,可以采用UUID形式
  • time:当前消息的时间
  • source:消息来源于哪个地方
  • content:消息内容
  • type:消息类型
  • count:当消息和上一条消息重复时,此count就会+1

那此时我们就需要考虑一下,怎么去监听主进程的消息,在我的上一篇文章,属性栏里面其实已经讲过,属性栏数据是来源于主进程的,那么同理,我们也需要写一个监听事件

ts 复制代码
  //监听主进程发送的消息数据
  window.electron.ipcRenderer.on('mainProcessMsg', (e, data): void => {
    useMessageStore().addPrompt(data)
  })

然后这个方法需要放到main.ts里面区立即执行

那么在我们的主进程中,也同样需要一个方法,这个方法起到统一接收消息,然后将消息传递给渲染进程,代码如下

ts 复制代码
import { mainWindow } from '../..'

//给渲染进程的消息框发消息
export const sendMsgToRender = (
  source: string,
  content: string,
  type?: 'info' | 'warning' | 'error' | 'success'
): void => {
  const data = {
    source,
    content,
    type
  }
  //判断mainWindow是否存在
  if (mainWindow) {
    mainWindow?.webContents?.send('mainProcessMsg', data)
  }
}

那么至此我们的消息栏已经将核心讲解完毕了,关于仿真控制器的部分,我需要留到后面和仿真引擎一起讲解

相关推荐
鱼樱前端10 分钟前
uni-app快速入门章法(一)
前端·uni-app
zhangxuyu111830 分钟前
flex布局学习记录
前端·css·学习
掘金一周36 分钟前
🍏让前端去做 iPhone 的液态玻璃❓ | 掘金一周 10.2
前端·人工智能·后端
Keepreal49642 分钟前
谈谈对javascript原型链的理解以及原型链的作用
前端·javascript
itslife42 分钟前
vite 源码 - 配置
前端·javascript
Keepreal4961 小时前
Typescript中type和interface的区别
前端·typescript
RJiazhen1 小时前
从迁移至 Rsbuild 说起,前端为什么要工程化
前端·架构·前端工程化
小红1 小时前
网络通信核心协议详解:从ARP到TCP三次握手与四次挥手
前端·神经网络
影子信息2 小时前
uniapp 日历组件 uni-datetime-picker
前端·uni-app