当前位置: 首页 > article >正文

electron-vite【实战】登录/注册页

效果预览

在这里插入图片描述

项目搭建

https://blog.csdn.net/weixin_41192489/article/details/144611858

技术要点

路由默认跳转到登录页

src/renderer/src/router/index.ts

  routes: [
    // 默认跳转到登录页
    {
      path: '/',
      redirect: '/login'
    },
    ...routes
  ]

登录窗口的必要配置

src/main/index.ts 中

  const mainWindow = new BrowserWindow({
    // 自定义图标
    icon: icon,
    // 自定义窗口宽度
    width: 360,
    // 自定义窗口高度
    height: 430,
    //默认隐藏窗口
    show: false,
    // 隐藏窗口标题栏
    titleBarStyle: 'hidden',
    // 隐藏默认菜单
    autoHideMenuBar: true,
    // 不可改变窗口大小
    resizable: false,
    // 窗口不可最大化
    maximizable: false,

    webPreferences: {
      preload: join(__dirname, '../preload/index.js'),
      sandbox: false
    }
  })

右上角关闭按钮的实现

src/renderer/src/pages/login.vue

  <div class="text-right">
    <el-icon
      class="el-icon-edit text-20px hover:bg-red hover:text-white cursor-pointer p-2"
      @click="quit"
      ><Close
    /></el-icon>
  </div>

渲染进程向主进程发送信息

function quit() {
  window.electron.ipcRenderer.send('quit')
}

src/main/index.ts 主进程响应信息

ipcMain.on('quit', () => {
  app.quit()
})

代码实现

src/renderer/src/router/index.ts

import { createRouter, createWebHashHistory } from 'vue-router'
import { routes, handleHotUpdate } from 'vue-router/auto-routes'

export const router = createRouter({
  // 此处需用 Hash 模式,否则打包后路由会失效
  history: createWebHashHistory(import.meta.env.BASE_URL),
  routes: [
    // 默认跳转到登录页
    {
      path: '/',
      redirect: '/login'
    },
    ...routes
  ]
})

// 支持热更新
if (import.meta.hot) {
  handleHotUpdate(router)
}

src/main/index.ts

import { app, shell, BrowserWindow, ipcMain, Tray, Menu } from 'electron'
import { join } from 'path'
import { electronApp, optimizer, is } from '@electron-toolkit/utils'
import icon from '../../resources/icon.png?asset'

function createWindow(): void {
  const mainWindow = new BrowserWindow({
    // 自定义图标
    icon: icon,
    // 自定义窗口宽度
    width: 360,
    // 自定义窗口高度
    height: 430,
    //默认隐藏窗口
    show: false,
    // 隐藏窗口标题栏
    titleBarStyle: 'hidden',
    // 隐藏默认菜单
    autoHideMenuBar: true,
    // 不可改变窗口大小
    resizable: false,
    // 不可改变窗口大小
    maximizable: false,

    webPreferences: {
      preload: join(__dirname, '../preload/index.js'),
      sandbox: false
    }
  })

  // 托盘
  const tray = new Tray(icon)

  const contextMenu = [
    {
      label: '退出',
      click: function () {
        app.exit()
      }
    }
  ]

  const menu = Menu.buildFromTemplate(contextMenu)

  tray.setToolTip('EC编程俱乐部')

  tray.setContextMenu(menu)

  tray.on('click', () => {
    // 使窗口显示在任务栏中
    mainWindow.setSkipTaskbar(false)
    mainWindow.show()
  })

  // IPC通信
  ipcMain.on('showPage_home', () => {
    // 窗口可调整大小
    mainWindow.setResizable(true)
    mainWindow.setSize(800, 680)
    // 窗口居中
    mainWindow.center()
    // 窗口可最大化
    mainWindow.setMaximizable(true)
  })

  ipcMain.on('top', () => {
    mainWindow.setAlwaysOnTop(true)
  })

  ipcMain.on('cancle_top', () => {
    mainWindow.setAlwaysOnTop(false)
  })

  ipcMain.on('hide', () => {
    // 使窗口不显示在任务栏中
    mainWindow.setSkipTaskbar(true)
    mainWindow.hide()
  })

  ipcMain.on('min', () => {
    mainWindow.minimize()
  })

  ipcMain.on('max', () => {
    mainWindow.maximize()
  })

  ipcMain.on('cancel_max', () => {
    mainWindow.unmaximize()
  })

  mainWindow.on('ready-to-show', () => {
    // 自定义标题
    mainWindow.setTitle('EC编程俱乐部')
    mainWindow.show()
  })

  // 窗口变为最大化状态
  mainWindow.on('maximize', () => {
    mainWindow.webContents.send('maximize')
  })

  // 窗口从最大化状态退出
  mainWindow.on('unmaximize', () => {
    mainWindow.webContents.send('unmaximize')
  })

  mainWindow.webContents.setWindowOpenHandler((details) => {
    shell.openExternal(details.url)
    return { action: 'deny' }
  })

  if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
    mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL'])
  } else {
    mainWindow.loadFile(join(__dirname, '../renderer/index.html'))
  }
}

app.whenReady().then(() => {
  // Set app user model id for windows
  electronApp.setAppUserModelId('com.electron')

  app.on('browser-window-created', (_, window) => {
    optimizer.watchWindowShortcuts(window)
  })

  createWindow()

  app.on('activate', function () {
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
})

ipcMain.on('quit', () => {
  app.quit()
})

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

src/renderer/src/pages/login.vue

仅前端页面渲染,省略了表单校验和后端交互。

<script setup lang="ts">
const form = reactive({ account: '', password: '', remember: false, passwordConfirm: '' })

const loginWay_list = [
  { icon: 'mdi:wechat', color: '#07cd66' },
  { icon: 'flat-color-icons:phone-android' },
  { icon: 'icon-park:tencent-qq' }
]

const PageType = ref('login')

function goToRegister() {
  PageType.value = 'register'
}

function goToLogin() {
  PageType.value = 'login'
}

const router = useRouter()

function submit_login() {
  window.electron.ipcRenderer.send('showPage_home')

  router.push('/home')
}
function quit() {
  window.electron.ipcRenderer.send('quit')
}
</script>

<template>
  <div class="text-right">
    <el-icon
      class="el-icon-edit text-20px hover:bg-red hover:text-white cursor-pointer p-2"
      @click="quit"
      ><Close
    /></el-icon>
  </div>
  <div class="w-360px bg-white p-8 pt-2 box-border overflow-hidden">
    <div class="text-28px font-bold text-center p-6">
      {{ PageType === 'login' ? 'EC 编程俱乐部' : '注册 EC' }}
    </div>
    <!-- 表单 -->
    <el-form :model="form">
      <el-form-item>
        <el-input v-model="form.account" placeholder="请输入账号">
          <template #prefix>
            <Icon icon="mdi:account" />
          </template>
        </el-input>
      </el-form-item>
      <el-form-item>
        <el-input v-model="form.password" placeholder="请输入密码">
          <template #prefix>
            <Icon icon="wpf:password1" />
          </template>
        </el-input>
      </el-form-item>
      <el-form-item v-if="PageType === 'register'">
        <el-input v-model="form.passwordConfirm" placeholder="请再次输入密码">
          <template #prefix>
            <Icon icon="mdi:password-check-outline" />
          </template>
        </el-input>
      </el-form-item>
      <div v-if="PageType === 'login'" class="flex justify-between items-center">
        <div>
          <el-checkbox v-model="form.remember" label="自动登录" size="large" />
        </div>
        <div>
          <el-link type="primary" :underline="false">忘记密码</el-link>
          <el-text type="primary"> / </el-text>
          <el-link type="primary" :underline="false" @click="goToRegister">注册</el-link>
        </div>
      </div>
      <el-form-item>
        <el-button v-if="PageType === 'login'" type="primary" class="w-full" @click="submit_login"
          >登录</el-button
        >
        <el-button v-if="PageType === 'register'" type="primary" class="w-full">注册</el-button>
      </el-form-item>
      <div v-if="PageType === 'register'" class="text-right">
        <el-link type="primary" :underline="false" @click="goToLogin">已有账号</el-link>
      </div>
    </el-form>
    <div v-if="PageType === 'login'">
      <el-divider>
        <span class="text-10px">其他登录方式</span>
      </el-divider>

      <div class="flex justify-around">
        <Icon
          v-for="(item, index) in loginWay_list"
          :key="index"
          :icon="item.icon"
          :style="{
            color: item.color
          }"
          class="inline-block text-24px cursor-pointer"
        />
      </div>
    </div>
  </div>
</template>

http://www.kler.cn/a/448797.html

相关文章:

  • MFC/C++学习系列之简单记录9——简单加法
  • ctfshow web入门文件上传总结
  • 【工具】通过js获取chrome浏览器扩展程序列表id及名称等
  • GTID详解
  • 【JAVA】JAVA接口公共返回体ResponseData封装
  • OpenTK 中帧缓存的深度解析与应用实践
  • 实践:从一次故障聊聊前端 UI 自动化测试
  • ROS2 python编写 intel realsense D405相机节点通过launch.py启动多个相机并发送图像话题,基于pyrealsense2库
  • 网络编程 03:端口的定义、分类,端口映射,通过 Java 实现了 IP 和端口的信息获取
  • jvm字节码中方法的结构
  • 在Excel中如果制作可以自动填充的序号,删除或者合并单元也可用
  • 游戏世界是什么
  • MySQL专题:日志及MVCC
  • CSS系列(22)-- 容器查询详解
  • 【译】仅有 Text2SQL 是不够的: 用 TAG 统一人工智能和数据库
  • 前端算法小白日刷三题17
  • 最全解决方案:org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.
  • 基于微信平台的文玩销售小程序ssm+论文源码调试讲解
  • Restaurants WebAPI(四)——Identity
  • 241221面经
  • powershell使用积累
  • 一起学Git【第一节:Git的安装】
  • Llama 3 模型系列解析(一)
  • 王佩丰24节Excel学习笔记——第十七讲:数据函数
  • HTML中的Vue3解析!
  • Ubuntu 安装实时内核指南