前期背景

项目周期:2020.09.24-2020.09.29

使用的框架:Electron  springboot

最终目的:做一个简易版的qq聊天的桌面软件


准备工作

1、安装node、配置node环境

2、安装vscode

3、安装vue-cli脚手架

以上三个步骤如果不会,可以看这个教程   https://blog.csdn.net/qq_37591637/article/details/89944336

4、安装Electron 

5、初始化一个vue与Electron一身的项目


项目初始化模板成功以后,打开文件夹,进行npm install 安装必须的模块

等待这个项目所需安装模块都安装完毕以后,我们启动项目

npm run dev

但是报错  process is not defined

 解决办法

修改你项目文件下.electron-vue里面的webpack.renderer.config.jswebpack.web.config.js

添加一段这个代码

  //加一些参数配置
      templateParameters(compilation, assets, options) {
        return {
          compilation: compilation,
          webpack: compilation.getStats().toJson(),
          webpackConfig: compilation.options,
          htmlWebpackPlugin: {
            files: assets,
            options: options
          },
          process,
        };
      },
      //加一些参数配置

整体的代码是这样的

 new HtmlWebpackPlugin({
      filename: 'index.html',
      template: path.resolve(__dirname, '../src/index.ejs'),
      //加一些参数配置
      templateParameters(compilation, assets, options) {
        return {
          compilation: compilation,
          webpack: compilation.getStats().toJson(),
          webpackConfig: compilation.options,
          htmlWebpackPlugin: {
            files: assets,
            options: options
          },
          process,
        };
      },
      //加一些参数配置
      minify: {
        collapseWhitespace: true,
        removeAttributeQuotes: true,
        removeComments: true
      },
      nodeModules: false
    }),

记住,两个文件的相同位置都要添加这个代码

然后保存,在控制台输入npm run dev

出现

 


 第二部分、制作一个简约的页面,实现数据的前后交互

1、前端页面精美的库    element-ui库(html的)

cnpm install --save element-ui

2、  安装sass库(css的)

cnpm install --save-dev node-sass
cnpm install --save-dev sass-loader

在main.js里面加入全局变量的引用

//添加element-ui组件
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI)
//添加element-ui组件

3、安装axios,用于调用http请求  一般在开始运行项目的时候npm install 就已经安装过了


这个时候,简单快速的布出精美的页面,就需要element-ui了

打开官网      https://element.eleme.cn/#/zh-CN/component/installation


我们先布局出一个登陆 注册的页面出来

打开element-ui这个组件网,选择我们需要的零件

这里有代码,也可以在线运行,我们把代码改成我们需要的,再复制到我们的项目里面来;

问题、代码灰色,没有高亮

但是我发现我项目里面的代码都是灰色的,没有高亮!

是因为没有安装vetur的缘故

选择vscode左侧的最下面的那个图标,输入Vetur   因为我一打开就有,直接点击install就可以了

安装成功以后,就没有绿色的install的按钮了

 

现在重启这个软件,不重启也可以;

代码已经高亮了!


我们写代码主要是在renderer文件夹的components里面新建vue文件,布局的

所以打开项目中vue文件(出了App.vue外),把原有的代码全部清除,只留下基本的标签

之所以留下一些注释的东西,是因为引导,我们如果需要在一个组件里面引入另一个组件的书写方式 ;

忘了说,一个vue文件就是一个组件


开始布局

 我在element-ui官网找到表单,然后在在线运行里面更改成我需要的代码

 然后拷贝相关的代码在vue组件里面

<template>
<div id="app">
<el-form ref="form" :model="form" label-width="80px">
  <el-form-item label="用户名">
    <el-input v-model="form.name"></el-input>
  </el-form-item>
   <el-form-item label="密码">
    <el-input v-model="form.pass"></el-input>
  </el-form-item>
   <el-form-item>
    <el-button type="primary" @click="onSubmit">立即登陆</el-button>
    <el-button>取消</el-button>
  </el-form-item>
</el-form>

</div>
</template>

<script>
 // import 其他vue组件的名称 from './LandingPage/其他vue组件的名称'
  export default {
    name: 'landing-page',
    data(){
      return{
         form: {
          name: '',
          pass:'',
        }
      }
    },
   //导入其他的组件 components: { SystemInformation },
    methods: {
    onSubmit() {
        console.log('submit!');
      }
    }
  }
</script>

<style>
  
</style>

运行项目 npm run dev

 是不是出来了呢?

而且,最方便的是,如果你代码有问题,不用终止项目,直接搞好保存就可以了,界面自动刷新!


 我们现在要做的是

1、再美化页面 添加一个注册的页面

2、与后端以及数据库进行交互 实现登陆的功能(我用的语言是java  采用的是springboot框架)

3、打包前后端项目为桌面程序,安装看看(不需要jdk安装环境的exe程序)


美化页面  添加注册页面

这里涉及到多个路由文件的配置。index.js是主路由,但是随着项目的增大,以及方便管理,需要子路由文件;

 

路由之间的跳转

注册页面有一个登陆的按钮,点击登陆按钮就会跳转到login.vue文件里面

 用   <router-link :to="{path:'这里是路由文件里面的路径'}"> </router-link>

 现在要解决跨域问题

点击注册,登陆按钮,然后把值通过axios给后端,由于端口不同,项目名称不同,存在着跨域

我的后端是idea软件springboot项目


electron-vue项目跨域设置

在dev-runner.js里面添加跨域设置

  /*
         这里是跨域设置
        */
       proxy: {
        '/api': {
          // 请求的目标服务器地址
          target: 'http://localhost:8080/',
          // 如果是https接口,需要配置这个参数
          secure: false,
          // 设置允许跨域
          changeOrigin: true,
          // 重写路径
          pathRewrite: {
            '^/api': ''
          },
          headers: {
            referer: ''
          }
        }
      },
       //这里是跨域设置

 是http不是https

我就是因为这里写错了,所以一直报错  HTTP method names must be tokens

 

在main.js里面全局设置axios

注意如果这里是axios,在其他的vue文件里面使用就是axios;如果是$axios的话,其他文件里面就是$axios;

 进行跨域请求

 onSubmit() {
       //跨平台交互
       // 发送一个 POST 请求
     this.$axios({
   method: 'post',
   url: '/api/user/insert/',
   header:{
        'Content-Type':'application/json'  //如果写成contentType会报错
    },
    data: {
    username: 'Fred',
    password: 'Flintstone',
    tell:'17356286023'
  },
  }).then((res) => {
  console.log(res)
});
       //跨平台交互
      }
    }

后端是springboot 

    @RequestMapping("/insert")
    public String adduser(@RequestBody String juser) throws JSONException {
        //把字符串变成Json对象
        System.out.println("接受到的数据是:"+juser);
        JSONObject jo=new JSONObject(juser);
        user u=new user();
        u.setPassword(jo.getString("password"));
        u.setTell(jo.getString("tell"));
        u.setUsername(jo.getString("username"));
        int i=us.insert(u);
        return "index";
    }

 

我们现在运行项目,看一下,是否能注册成功

 哈哈哈,现在整个流程都跑通了.....


现在普及一个关于jsonobject jsonarray  以及表单数据 前后端如何发送与接受

上面我axios发送的是json数据,准确来说是jsonobject数据,后端用(@RequestBody String juser)接受的

1、axios发送一个json数组,后端的接受

 this.$axios({
   method: 'post',
   url: '/api/user/insert/',
   header:{
        'Content-Type':'application/json'  //如果写成contentType会报错
    },
    data:[{username:'简雍',password:'111',tell:'110'},{username:'糜竺',password:'123',tell:'119'},"true","蜀国初期人员"],
  }).then((res) => {
  console.log(res)
});
       //跨平台交互
  @RequestMapping("/insert")
    public String adduser(@RequestBody String juser) throws JSONException {
        JSONArray ja=new JSONArray(juser);
        JSONObject JO=ja.getJSONObject(0);
        System.out.println(JO.get("username")+"-"+JO.get("password")+"-"+JO.get("tell"));
        JSONObject JO1=ja.getJSONObject(1);
        System.out.println(JO1.get("username")+"-"+JO1.get("password")+"-"+JO1.get("tell"));
        System.out.println(ja.get(2));
        System.out.println(ja.get(3));
}

 

2、axios发送一个表单数据,后端的接受

    // 发送一个 POST 请求
     this.$axios({
   method: 'post',
   url: '/api/user/insert/',
   header:{
        'Content-Type':'application/x-www-form-urlencoded'  //如果写成contentType会报错
    },
    data:this.qs.stringify({username:'刘备',password:'999',tell:'12365897452'}),
  }).then((res) => {
  console.log(res)
});
       //跨平台交互
 @RequestMapping("/insert")
    public String adduser(@RequestParam String username,@RequestParam String password,@RequestParam String tell) throws JSONException {
        //把字符串变成Json对象
        System.out.println("---------"+username+"-----"+password+"-----"+tell);
}

 

总结

   如果是json数据,不管是json数组还是json对象,axios中要设置 'Content-Type':'application/json',并且不需要qs转换;

   后端用@RequestBody String juser 接受,然后转换为原本的类型,如json对象或json数组;

   如果是单纯的键值对   'Content-Type':'application/x-www-form-urlencoded',用qs转换一下,然后在后端用

 @RequestParam  一模一样的属性名称接受

如果json对象与json数组不懂的,可以看这个详细的教程案例

https://blog.csdn.net/qq_37591637/article/details/90319229


实现动态的注册、登陆功能

reg.vue

<template>
<div id="app">
  <el-form  :model="form" label-width="50px" class="mc"> 
  <el-form-item >
    <el-input v-model="form.name" placeholder="用户名/手机号码"></el-input>
  </el-form-item>
   <el-form-item >
    <el-input v-model="form.pass" placeholder="密码"></el-input>
  </el-form-item>
     <el-form-item >
    <el-input v-model="form.tell" placeholder="手机号码"></el-input>
  </el-form-item>
   <el-form-item>
    <el-button type="primary" @click="onSubmit">立即注册</el-button>
    <router-link :to="{path:'/'}"><el-button>登陆</el-button></router-link>
  </el-form-item>
</el-form>
</div>
</template>

<script>
 // import 其他vue组件的名称 from './LandingPage/其他vue组件的名称'
  export default {
    name: 'landing-page',
    data(){
      return{
         form: {
          name: '',
          pass:'',
          tell:''
        }
      }
    },
   //导入其他的组件 components: { SystemInformation },
    methods: {
    onSubmit() {
       //跨平台交互
       // 发送一个 POST 请求
       console.log(this.form.name);
     this.$axios({
   method: 'post',
   url: '/api/user/insert/',
   header:{
        'Content-Type':'application/x-www-form-urlencoded'  //如果写成contentType会报错
    },
    data:this.qs.stringify({username:this.form.name,password:this.form.pass,tell:this.form.tell}),
  }).then((res) => {
  console.log(res)
});
       //跨平台交互
      }
    }
  }
</script>

<style>
 /* #app{
  background-image: url('~@/assets/img/bg1.jpg');
}  */
  .mc{
    padding-top: 110px;
    padding-left: 552px;
    width: 400px;
}
</style>

login.vue

<template>
<div id="app">
  <el-form  :model="form" label-width="50px" class="mc"> 
  <el-form-item >
    <el-input v-model="form.name" placeholder="用户名/手机号码"></el-input>
  </el-form-item>
   <el-form-item >
    <el-input v-model="form.pass" placeholder="密码"></el-input>
  </el-form-item>
   <el-form-item>
    <el-button type="primary" @click="onSubmit">立即登陆</el-button>
    <router-link :to="{path:'/user/reg'}"><el-button>注册</el-button></router-link>
  </el-form-item>
</el-form>
</div>
</template>
<script>
//import router;
 // import 其他vue组件的名称 from './LandingPage/其他vue组件的名称'
  export default {
    name: 'landing-page',
    data(){
      return{
         form: {
          name: '',
          pass:'',
        }
      }
    },
   //导入其他的组件 components: { SystemInformation },
    methods: {
    onSubmit() {
       this.$axios({
       method: 'post',
       url: '/api/user/qby/',
      header:{
        'Content-Type':'application/x-www-form-urlencoded'  //如果写成contentType会报错
    },
    data:this.qs.stringify({name:this.form.name,pass:this.form.pass}),
       }).then((res) => {
  console.log(res);
  if(res.data=="success"){
    //跳转页面
    alert("登陆成功");
  }else{
   // 不跳转
   alert("用户名或密码错误");
  }
});

    },
     
    }
  }
</script>

<style>
 /*
#app{
 background-image: url('~@/assets/img/bg1.jpg'); 
}
*/
  .img{
    position: absolute;
    width:100%;
    height:40rem;
  }
  .mc{
    padding-top: 110px;
    padding-left: 552px;
    width: 400px;
}
</style>

效果如下

 

给页面添加背景图片

图片放在assets文件夹下面img文件夹下面

写法是 <img src="~@/assets/img/bj1.jpg"  />

用~@/表示

 

部署项目

1、把electron-vue项目进行打包

控制台输出npm run build

但是报错

 

 安装electron-builder

yarn add electron-builder --dev

再次在控制台输入yarn run build

又报错了

解决方案

如果您使用的是 Babel,你将需要添加 syntax-dynamic-import 插件,才能使 Babel 可以正确地解析语法。

yarn add babel-plugin-syntax-dynamic-import

 打开webpack.main.config.js里面修改以下的内容

 

{
        test: /\.js$/,
        loader:'babel-loader',
        options:{
       plugins:['syntax-dynamic-import']
      },
      },

 把子路由的配置改成这样的;

import login  from '@/components/user/login.vue'
import reg  from '@/components/user/reg.vue'
export default[
    {
        path: '/',
        name: 'login',
        component:login,
    },
    {
        path: '/user/reg',
        name:'reg',
        component:reg,
    }
];

 先运行项目,yarn run dev

如果正常就继续,如果不正常的话,报错  vue- Couldn't find preset "es2015" relative to directory

                                                         解决办法  yarn add babel-preset-es2015 --save-dev

 再次运行项目 yarn run dev

失败的原因是下载的时间太长了导致的

electron-vue项目打包成桌面开发程序的流程

1、下载SHASUMS256.txt与electron-v2.0.18-win32-x64.zip

现在打开链接,然后再浏览器上下载,再放到缓存里面

https://npm.taobao.org/mirrors/electron/2.0.18/

记住SHASUMS256.txt 也要下载 可以新建一个txt文件,然后复制内容进去保存

将SHASUMS256.txt改成SHASUMS256.txt-2.0.18

 

2、下载winCodeSign-2.6.0

不同的环境变量的项目所需要的版本不一样,你可以通过yarn run build  ,当程序卡住的时候,仔细看一下提示,需要什么版本的;当然其他版本的不影响,你下载下来,只需要改文件夹的名称就可以了,但是你必须知道你的版本是什么。

 

下载winCodeSign-2.6.0(至于版本,你们可以yarn run build  到某个地方就会卡住,你们看看是提示是什么版本的)

https://github.com/electron-userland/electron-builder-binaries/releases/tag/winCodeSign-2.6.0

如果版本是2.7 就更改网页最后的版本号就可以了

下载结束以后,在Cache里面新建一个winCodeSign的文件夹,记住这个名字不能改

在这个winCodeSign文件夹里面新建一个winCodeSign-你的版本的名称,如果是2.6.0.7就去前面2个点.

拷贝刚才下载的文件里面的这几个东西

然后再yarn run build

如果发现又卡住下载东西,仔细看是什么,如果还是winCodeSign,说明你以上的配置不对!!!

仔细看文件名称以及版本号;

如果你下错了winCodeSign版本没有关系,一样可以用,里面内容一样的,要把文件夹名称改成你需要的就可以了!!


3、下载nsis

不同的环境变量的项目所需要的版本不一样,你可以通过yarn run build  ,当程序卡住的时候,仔细看一下提示,需要什么版本的;当然其他版本的不影响,你下载下来,只需要改文件夹的名称就可以了,但是你必须知道你的版本是什么。

如果是nsis的话,就继续往下看

下载nsis-3.0.3.2

https://github.com/electron-userland/electron-builder-binaries/releases/tag/nsis-3.0.3.2

在Cache文件夹里面新建一个文件夹nsis

在文件夹nsis里面新建一个文件夹nsis-版本号

我需要的是nsis-3.0.4.1  ,但是不影响,因为虽然版本不一样,但是里面内容一样,文件夹名称与需要的一样就可以了

现在运行yarn run build  就没有问题了

在build文件夹里面有生成的.exe程序

把exe程序放在桌面上,关闭vscode

 

当打包结束以后,运行界面没有问题。但是axios请求报错!!!!

原因:proxy配置的跨域设置只适合开发环境,不适合上线的环境(以及打包的项目)

有两个方法可以解决这个问题

方法一、如果你是electron是v10.*.*版本的话,可以用这个方法

 1.1、删除掉proxy代理,那个只是开发环境下面使用的跨域设置,没有用

1.2、打开main文件夹下面的index.js

找到mainWindow = new BrowserWindow({}) 添加跨域设置 webPreferences:{webSecurity:false}

 mainWindow = new BrowserWindow({

    height: 563,

    useContentSize: true,

    width: 1000,

    //跨域设置

    webPreferences:{webSecurity:false}

    //跨域设置

  })

再在下面添加

//跨域

app.commandLine.appendSwitch('disable-features', 'OutOfBlinkCors');

//跨域

在axios请求的方法里面把url改成绝对路径

 this.$axios({
   method: 'post',
   url: 'http://185.92.156.173:8088/user/insert/',
   header:{
        'Content-Type':'application/x-www-form-urlencoded'  //如果写成contentType会报错
    },
    data:this.qs.stringify({username:this.form.name,password:this.form.pass,tell:this.form.tell}),
  }).then((res) => {
  console.log(res)
});

 然后保存,打包,就可以了

前提是你的electron是v10版本以上的,不然没用。

我亲自测试了,把这个exe程序放在其他没有这些环境变量的电脑上都可以,有效!(前提你的后端是能访问到的,云服务器)


方法二、nginx反向代理(最普遍的方法)

1、安装nginx

官网地址 http://nginx.org/download/nginx-1.0.11.zip
 

2、解压后,把文件放在想要的地方

打开文件夹,双击 nginx.exe,就是启动了;

但是我双击了以后闪退了,原因是80端口被占用了;

修改conf/nginx.conf文件中的 端口

我改成了8090 ,保存然后再双击试试看

是不是一闪而过,都看不到窗口,我就是的。

我改了好几次,但是还是一闪而退,百度了很多,不需要配置环境变量,不需要的

后来,我打开了任务管理器,发现很多的nginx.exe在运行。我没有关闭

全部关闭以后,在双击(即使还是一闪而过,别怕),在页面上输入localhost:8085(你在配置文件里面设置的端口号),我改了很多,最后是8085端口

居然能打开,没问题,我都崩溃了.............我还以为跟tomcat一样呢?

经过几个小时的尝试,告诉大家一个很重要的技巧

1、想要知道nginx服务有没有开启,打开任务管理器

  有两个nginx是对的;想要关闭的话,可以直接点击关闭进程,两个

用谷歌浏览器,我用了火狐浏览器,很快的修改配置参数,火狐浏览器都反应不过来,我都不知道究竟是对是错

打开ngnix的nginx.conf配置文件


#user  nobody;
worker_processes  1;
#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;
#pid        logs/nginx.pid;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
   
    keepalive_timeout  65;

   upstream domi{
    server 182.96.153.143:8088;
                         }
    server {
        listen       8085;
        server_name  localhost;
        location / {
            root   html;
            index  index.html index.htm;
        }
       location /ttt/ {
            proxy_pass http://domi/;
       }

       error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }

}

要点:

1、申明另一个服务器的地址以及端口

upstream domi{

    server 182.92.153.173:8088;

                         }

并且 不能有_  可以是domi 可以是yyy 不能是e_p

2、proxy_pass 里面要与这个申明的服务器名称一致

3、先访问ngnix是否没问题  比如ngnix的地址是http://localhost:8085

那么在后面网址加上ttt就可以了

4、然后再electron-vue项目里面,axios请求的地址设置为http://ngnix的访问地址/ttt

若在本机电脑上:http://localhost:8085/ttt/

若后端服务器与ngnix在阿里云上:http://阿里云地址:8085/ttt/

不管你在哪里,记住,你的(ngnix的地址:端口号)/ttt/

 当然,如果采用ngnix反向代理跨域,就可以注释掉方法一的配置

 然后再进行yarn run build就可以了

我试过了可以注册登录

 


您的支持是我分享经验的动力

 

Logo

前往低代码交流专区

更多推荐