Jack Jiang

          我的最新工程MobileIMSDK:http://git.oschina.net/jackjiang/MobileIMSDK
          posts - 506, comments - 13, trackbacks - 0, articles - 1

          本文由環(huán)信技術(shù)黃飛鵬分享,原題“實(shí)戰(zhàn)|如何利用 Electron 快速開(kāi)發(fā)一個(gè)桌面端應(yīng)用”,本文進(jìn)行了排版和內(nèi)容優(yōu)化等。

          1、引言

          早就聽(tīng)說(shuō)利用Electron可以非常便捷的將網(wǎng)頁(yè)端快速打包成桌面應(yīng)用,并且利用 Electron 提供的 API 調(diào)用可以使用原生桌面 API 一些高級(jí)功能。于是這次借著論證 Web IM端 SDK 是否可以在 Electron 生成的桌面端正常穩(wěn)定使用,我決定把官方新推出的 webim-vue3-demo,打包到桌面端,并記錄了這次驗(yàn)證的過(guò)程以及所遇到的問(wèn)題和解決方法。

          2、系列文章

          本文是系列文章中的第11篇,本系列總目錄如下:

          IM跨平臺(tái)技術(shù)學(xué)習(xí)(一):快速了解新一代跨平臺(tái)桌面技術(shù)——Electron

          IM跨平臺(tái)技術(shù)學(xué)習(xí)(二):Electron初體驗(yàn)(快速開(kāi)始、跨進(jìn)程通信、打包、踩坑等)

          IM跨平臺(tái)技術(shù)學(xué)習(xí)(三):vivo的Electron技術(shù)棧選型、全方位實(shí)踐總結(jié)

          IM跨平臺(tái)技術(shù)學(xué)習(xí)(四):蘑菇街基于Electron開(kāi)發(fā)IM客戶端的技術(shù)實(shí)踐

          IM跨平臺(tái)技術(shù)學(xué)習(xí)(五):融云基于Electron的IM跨平臺(tái)SDK改造實(shí)踐總結(jié)

          IM跨平臺(tái)技術(shù)學(xué)習(xí)(六):網(wǎng)易云信基于Electron的IM消息全文檢索技術(shù)實(shí)踐

          IM跨平臺(tái)技術(shù)學(xué)習(xí)(七):得物基于Electron開(kāi)發(fā)客服IM桌面端的技術(shù)實(shí)踐

          IM跨平臺(tái)技術(shù)學(xué)習(xí)(八):新QQ桌面版為何選擇Electron作為跨端框架

          IM跨平臺(tái)技術(shù)學(xué)習(xí)(九):全面解密新QQ桌面版的Electron內(nèi)存占用優(yōu)化

          IM跨平臺(tái)技術(shù)學(xué)習(xí)(十):快速選型跨平臺(tái)框架Electron、Flutter、Tauri、React Native等

          IM跨平臺(tái)技術(shù)學(xué)習(xí)(十一):環(huán)信基于Electron打包WebIM桌面端的技術(shù)實(shí)踐》(* 本文

          3、前置技能

          • 1)擁有良好的情緒自我管理,能夠在遇到棘手問(wèn)題時(shí)不一拳給到鍵盤;
          • 2)擁有較為熟練的水群能力,能夠在遇到問(wèn)題時(shí),主動(dòng)向技術(shù)群內(nèi)參差不齊的群友們拋出自己的問(wèn)題;
          • 3)重要的是,要擁有較為熟練的搜索引擎使用能力;
          • 4)能夠看到這篇文章,那說(shuō)明以上能力你已完全具備。

          PS:不開(kāi)玩笑的說(shuō),開(kāi)始Electron的踩坑之前,肯定還是要對(duì)Electron的方方面面有所了解才能磨刀不誤砍柴工,建議從《快速了解新一代跨平臺(tái)桌面技術(shù)——Electron》、《Electron初體驗(yàn)(快速開(kāi)始、跨進(jìn)程通信、打包、踩坑等)》這兩篇開(kāi)始。

          4、第1步:準(zhǔn)備工作

          • 1)克隆 vue3 Demo 項(xiàng)目到本地(vue3-demo的源碼地址);
          • 2)在編輯器內(nèi)打開(kāi)此項(xiàng)目并執(zhí)行yarn install安裝項(xiàng)目相關(guān) npm 依賴;
          • 3)在此項(xiàng)目目錄下打開(kāi)終端請(qǐng)敲下yarn add electron,從而在該項(xiàng)目中安裝 electron;
          • 4)安裝一些依賴工具wait-on以及cross-env。

          PS:如果訪問(wèn)vue3 Demo的Github倉(cāng)庫(kù)太慢,可以直接下載以下附件:

           webim-vue-demo(demo-vue3).zip (1.05 MB , 下載次數(shù): 0 , 售價(jià): 1 金幣)

          wait-on:它是一個(gè) Node.js 包,它可以用于等待多個(gè)指定的資源(如 HTTP 資源、TCP 端口或文件)變得可用。它通常用于等待應(yīng)用程序的依賴項(xiàng)準(zhǔn)備好后再啟動(dòng)應(yīng)用程序。例如,您可以使用 wait-on 等待數(shù)據(jù)庫(kù)連接、消息隊(duì)列和其他服務(wù)就緒后再啟動(dòng)您的應(yīng)用程序。這樣可以確保您的應(yīng)用程序在嘗試使用這些資源之前不會(huì)崩潰。

          cross-env:是一個(gè) npm 包,它的作用是在不同平臺(tái)上設(shè)置環(huán)境變量。在不同操作系統(tǒng)中,設(shè)置環(huán)境變量的方式是不同的。例如,在 Windows 中使用命令 set NODE_ENV=production 設(shè)置環(huán)境變量,而在 Unix/Linux/Mac 上則需要使用 export NODE_ENV=production 命令。

          此時(shí)可能會(huì)進(jìn)入到漫長(zhǎng)的等待階段(第一、這個(gè)包本身就比較大,第二、相信大家都懂由于網(wǎng)絡(luò)原因?qū)е拢⑶矣锌赡苓M(jìn)行會(huì)經(jīng)歷幾次TIMOUT安裝失敗。此時(shí)就需要心平氣和,且有耐心的進(jìn)行改變鏡像地址、科學(xué)進(jìn)行上網(wǎng),WIFI切換為移動(dòng)流量多去重試幾次,相信道友你總會(huì)成功過(guò)的。

          有如下輸出則應(yīng)該為安裝成功:

          5、第2步:項(xiàng)目目錄增加 Electron 文件

          在項(xiàng)目增加 Electron 文件時(shí)我們需要擴(kuò)展一部分知識(shí)從而了解為什么創(chuàng)建創(chuàng)建這個(gè)目錄,并在該目錄下增加main.js文件的作用。當(dāng)然如果覺(jué)得不需要可以直接略過(guò)。

          5.1主進(jìn)程與渲染進(jìn)程的概念

          在 Electron 中,主進(jìn)程和渲染進(jìn)程是兩個(gè)不同的概念。主進(jìn)程是 Electron 應(yīng)用程序的核心,它運(yùn)行在一個(gè) Node.js 實(shí)例中,并管理應(yīng)用程序的生命周期、窗口創(chuàng)建和銷毀、與底層操作系統(tǒng)進(jìn)行交互等。主進(jìn)程還可以通過(guò) IPC(進(jìn)程間通信)機(jī)制與渲染進(jìn)程進(jìn)行通信。

          渲染進(jìn)程則是應(yīng)用程序的 UI 界面所在的進(jìn)程。每個(gè) Electron 窗口都有其自己的渲染進(jìn)程。渲染進(jìn)程是一個(gè) Chromium 渲染引擎實(shí)例,它運(yùn)行在一個(gè)僅包含 Web API 的環(huán)境中。渲染進(jìn)程負(fù)責(zé)渲染 HTML、CSS 和 JavaScript,并處理來(lái)自用戶的輸入事件,同時(shí)通過(guò) IPC 機(jī)制與主進(jìn)程進(jìn)行通信。

          由于渲染進(jìn)程只能訪問(wèn) Web API 而不能直接訪問(wèn) Node.js API,因此如果需要在渲染進(jìn)程中使用 Node.js API,就需要通過(guò) IPC 機(jī)制向主進(jìn)程發(fā)出請(qǐng)求,由主進(jìn)程代為執(zhí)行并將結(jié)果返回給渲染進(jìn)程。

          PS:關(guān)于Electron的進(jìn)程知識(shí),可以詳讀《Electron初體驗(yàn)(快速開(kāi)始、跨進(jìn)程通信、打包、踩坑等)》一文的“5、進(jìn)程詳解”一節(jié)。

          5.2主進(jìn)程與渲染進(jìn)程分別應(yīng)該寫在哪?

          在 Electron 應(yīng)用程序中,主進(jìn)程通常寫在名為 main.js 或者 index.js 的 JavaScript 文件中,這個(gè)文件是應(yīng)用程序的入口點(diǎn)。

          而渲染進(jìn)程則通常寫在 HTML 文件和其引入的 JavaScript 文件中。在一個(gè) Electron 窗口中,可以通過(guò)調(diào)用 webContents 對(duì)象的 loadURL 方法來(lái)加載一個(gè) HTML 文件,其中包含了渲染進(jìn)程所需的代碼和資源。該 HTML 文件中的 JavaScript 代碼將運(yùn)行在對(duì)應(yīng)的渲染進(jìn)程中,可以通過(guò) Electron 提供的一些 API 和 Web API 來(lái)進(jìn)行與用戶界面相關(guān)的操作。

          需要注意的是,在 Electron 中,由于主進(jìn)程和渲染進(jìn)程是不同的 Node.js 實(shí)例,因此它們之間并不能直接共享變量或者調(diào)用函數(shù)。如果想要實(shí)現(xiàn)主進(jìn)程和渲染進(jìn)程之間的通信,必須使用 Electron 提供的 IPC 機(jī)制,通過(guò)發(fā)送消息的方式來(lái)進(jìn)行進(jìn)程間通信。

          5.3有些 Electron 文件目錄下 preload.js 的作用

          在 Electron 中,preload.js 文件是一個(gè)可選的 JavaScript 文件,用于在渲染進(jìn)程創(chuàng)建之前加載一些額外的腳本或者模塊,從而擴(kuò)展渲染進(jìn)程的能力。preload.js 文件通常存放在與主進(jìn)程代碼相同的目錄下。

          preload.js 的實(shí)際運(yùn)用主要有以下幾個(gè)方面。

          1)托管 Node.js API:preload.js 中可以引入 Node.js 模塊,并將其暴露到 window 對(duì)象中,從而使得在渲染進(jìn)程中也能夠使用 Node.js API,避免了直接在渲染進(jìn)程中調(diào)用 Node.js API 帶來(lái)的安全風(fēng)險(xiǎn);

          2)擴(kuò)展 Web API:preload.js 中還可以定義一些自定義的函數(shù)或者對(duì)象,然后將它們注入到 window 對(duì)象中,這樣在渲染進(jìn)程中就可以直接使用它們了,而無(wú)需再進(jìn)行額外的導(dǎo)入操作;

          3)進(jìn)行一些初始化操作:preload.js 文件中的代碼會(huì)在每個(gè)渲染進(jìn)程的上下文中都運(yùn)行一遍,在這里可以進(jìn)行一些初始化操作,比如為頁(yè)面添加一些必要的 DOM 元素、為頁(yè)面注冊(cè)事件處理程序等。

          需要注意的是:preload.js 文件中的代碼運(yùn)行在渲染進(jìn)程的上下文中,因此如果 preload.js 中包含一些惡意代碼,那么它很可能會(huì)危及整個(gè)渲染進(jìn)程的安全性。因此,在編寫 preload.js 文件時(shí),一定要格外小心,并且僅引入那些你信任的模塊和對(duì)象。

          1) 添加 Electron 文件(此時(shí)項(xiàng)目目錄):

          2) Electron 下新建main.js示例代碼如下:

          const { app, BrowserWindow } = require('electron');

          const path = require('path');

          const NODE_ENV = process.env.NODE_ENV;

          app.commandLine.appendSwitch('allow-file-access-from-files');

          function createWindow() {

            // Create the browser window.

            const mainWindow = new BrowserWindow({

              width: 980,

              height: 680,

              fullscreen: true,

              skipTaskbar: true,

              webPreferences: {

                nodeIntegration: true,

                preload: path.join(__dirname, 'preload.js'),

              },

            });

           

            if (NODE_ENV === 'development') {

              mainWindow.loadURL('http://localhost:9001/');

              mainWindow.webContents.openDevTools();

            } else {

              mainWindow.loadURL(`file://${path.join(__dirname, '../dist/index.html')}`);

            }

          }

           

          // This method will be called when Electron has finished

          // initialization and is ready to create browser windows.

          // Some APIs can only be used after this event occurs.

           

          app.whenReady().then(() => {

            createWindow();

          });

           

          // Quit when all windows are closed, except on macOS. There, it's common

          // for applications and their menu bar to stay active until the user quits

          // explicitly with Cmd + Q.

          app.on('window-all-closed', function () {

            if (process.platform !== 'darwin') app.quit();

          });

          3)Electron 下新建preload.js,示例代碼如下(此文件為可選文件):

          //允許vue項(xiàng)目使用 ipcRenderer 接口, 演示項(xiàng)目中沒(méi)有使用此功能

          const { contextBridge, ipcRenderer } = require('electron');

          contextBridge.exposeInMainWorld('ipcRender', ipcRenderer);

          4)修改package.json:

          當(dāng)前示例代碼如下:

          • 1)修改"main"配置,將其指向?yàn)?main": "electron/main.js";
          • 2)增加一個(gè)針對(duì) electron 啟動(dòng)的"scripts","electron:dev": "wait-on tcp:3000 && cross-env NODE_ENV=development electron ./"。

          當(dāng)前項(xiàng)目配置如下所示:

          {

            "name": "webim-vue3-demo",

            "version": "0.1.0",

            "private": true,

            "main": "electron/main.js",

            "scripts": {

              "dev": "vue-cli-service serve",

              "build": "vue-cli-service build",

              "lint": "vue-cli-service lint",

              "electron:dev": "wait-on tcp:9001 && cross-env NODE_ENV=development  electron ./"

            },

            "dependencies": {

              "@vueuse/core": "^8.4.2",

              "agora-rtc-sdk-ng": "^4.14.0",

              "axios": "^0.27.2",

              "benz-amr-recorder": "^1.1.3",

              "core-js": "^3.8.3",

              "easemob-websdk": "^4.1.6",

              "element-plus": "^2.2.5",

              "nprogress": "^0.2.0",

              "pinyin-pro": "^3.10.2",

              "vue": "^3.2.13",

              "vue-router": "^4.0.3",

              "vuex": "^4.0.0"

            },

            "devDependencies": {

              "@babel/core": "^7.12.16",

              "@babel/eslint-parser": "^7.12.16",

              "@vue/cli-plugin-babel": "~5.0.0",

              "@vue/cli-plugin-eslint": "~5.0.0",

              "@vue/cli-plugin-router": "~5.0.0",

              "@vue/cli-plugin-vuex": "~5.0.0",

              "@vue/cli-service": "~5.0.0",

              "cross-env": "^7.0.3",

              "electron": "^24.3.1",

              "eslint": "^7.32.0",

              "eslint-plugin-vue": "^8.0.3",

              "sass": "^1.51.0",

              "sass-loader": "^12.6.0",

              "wait-on": "^7.0.1"

            }

          }

          6、第3步:本地啟動(dòng)起來(lái)驗(yàn)證一下

          6.1啟動(dòng)運(yùn)行原 vue 項(xiàng)目

          這里啟動(dòng)項(xiàng)目至端口號(hào) 9001,跟上面 electron/main.jsmainWindow.loadURL(' http://localhost:9001/')是可以對(duì)應(yīng)上的,也就是 Electron 運(yùn)行起來(lái)將會(huì)加載此服務(wù)地址。

          yarn run dev

          6.2新開(kāi)終端,啟動(dòng)Electron

          新開(kāi)一個(gè)終端執(zhí)行,輸入下方命令啟動(dòng) Electron。

          執(zhí)行下面命令:

          yarn run electron:dev

           

          并且經(jīng)過(guò)測(cè)試驗(yàn)證登錄沒(méi)有什么問(wèn)題。

          7、第4步:嘗試打包并驗(yàn)證打包出來(lái)的安裝包是否可用

          7.1安裝electron-builder

          該工具為 Electron 打包工具庫(kù),點(diǎn)擊打開(kāi)electron-builder 官方文檔

          終端執(zhí)行下面命令安裝 electron-builder:

          yarn add electron-builder --dev

          7.2配置打包腳本命令及個(gè)性化配置項(xiàng)

          package.json 配置打包腳本命令以及設(shè)置打包個(gè)性化配置項(xiàng)。

          具體配置項(xiàng)作用請(qǐng)參考官網(wǎng)文檔,下面有些配置也是 CV 大發(fā)過(guò)來(lái)的,沒(méi)有具體深入研究。

          {

            "name": "webim-vue3-demo",

            "version": "0.1.0",

            "private": true,

            "main": "electron/main.js",

            "scripts": {

              "dev": "vue-cli-service serve",

              "build": "vue-cli-service build",

              "lint": "vue-cli-service lint",

              "electron:dev": "wait-on tcp:9001 && cross-env NODE_ENV=development  electron ./",

              "electron:build": "rimraf dist &&  vue-cli-service build &&  electron-builder",

              "electron:build2": "electron-builder"

            },

            "dependencies": {

              "@vueuse/core": "^8.4.2",

              "agora-rtc-sdk-ng": "^4.14.0",

              "axios": "^0.27.2",

              "benz-amr-recorder": "^1.1.3",

              "core-js": "^3.8.3",

              "easemob-websdk": "^4.1.6",

              "element-plus": "^2.2.5",

              "nprogress": "^0.2.0",

              "pinyin-pro": "^3.10.2",

              "vue": "^3.2.13",

              "vue-router": "^4.0.3",

              "vuex": "^4.0.0"

            },

            "devDependencies": {

              "@babel/core": "^7.12.16",

              "@babel/eslint-parser": "^7.12.16",

              "@vue/cli-plugin-babel": "~5.0.0",

              "@vue/cli-plugin-eslint": "~5.0.0",

              "@vue/cli-plugin-router": "~5.0.0",

              "@vue/cli-plugin-vuex": "~5.0.0",

              "@vue/cli-service": "~5.0.0",

              "cross-env": "^7.0.3",

              "electron": "^24.3.1",

              "electron-builder": "^23.6.0",

              "eslint": "^7.32.0",

              "eslint-plugin-vue": "^8.0.3",

              "sass": "^1.51.0",

              "sass-loader": "^12.6.0",

              "wait-on": "^7.0.1"

            },

            "build": {

              "productName": "webim-electron",

              "appId": "com.lvais",

              "copyright": "2023@easemob",

              "directories": {

                "output": "output"

              },

              "extraResources": [

                {

                  "from": "./src/assets",

                  "to": "./assets"

                }

              ],

              "files": ["dist/**/*", "electron/**/*"],

              "mac": {

                "artifactName": "${productName}_${version}.${ext}",

                "target": ["dmg"]

              },

              "win": {

                "target": [

                  {

                    "target": "nsis",

                    "arch": ["x64"]

                  }

                ],

                "artifactName": "${productName}_${version}.${ext}"

              },

              "nsis": {

                "oneClick": false,

                "allowElevation": true,

                "allowToChangeInstallationDirectory": true,

                "createDesktopShortcut": true

              },

              "linux": {}

            }

          }

          7.3開(kāi)始 build

          先這樣——build 原始 vue 項(xiàng)目:

          yarn run build

          再那樣——build Electron 項(xiàng)目:

          yarn run electron:build

          可能會(huì)進(jìn)入漫長(zhǎng)的等待,但是不要慌,可能與網(wǎng)絡(luò)關(guān)系比較大,需要耐心等待。

          打包成功之后可以看到有一個(gè) output 文件夾的生成,打開(kāi)之后可以選擇雙擊打開(kāi)軟件驗(yàn)證看下是否可以正常開(kāi)啟應(yīng)用。

          8、 痛苦踩坑1:打包后頁(yè)面空白等

          8.1概述

          打包后頁(yè)面空白并出現(xiàn)類似“Failed to load resource: net::ERR_FILE_NOT_FOUND”的報(bào)錯(cuò)。

          問(wèn)題簡(jiǎn)述:發(fā)現(xiàn)只有在打包之后的 Electron 應(yīng)用,啟動(dòng)后存在頁(yè)面空白,dev 情況下正常。

          8.2解決手段1

          經(jīng)排查,更改vue.config.js中publicPath的配置為‘./’。

          const { defineConfig } = require('@vue/cli-service');

          module.exports = defineConfig({

            transpileDependencies: true,

            lintOnSave: false,

            devServer: {

              host: 'localhost',

              port: 9001,

              // https:true

            },

            publicPath: './',

            chainWebpack: (config) => {

              //最小化代碼

              config.optimization.minimize(true);

              //分割代碼

              config.optimization.splitChunks({

                chunks: 'all',

              });

            },

          });

          原因是:打包后的應(yīng)用 Electron 會(huì)從相對(duì)路徑開(kāi)始找資源,所以經(jīng)過(guò)此配置可以所有資源則開(kāi)始從相對(duì)路徑尋找。

          默認(rèn)情況下:Vue CLI 會(huì)假設(shè)你的應(yīng)用是被部署在一個(gè)域名的根路徑上,例如 https://www.my-app.com/。如果應(yīng)用被部署在一個(gè)子路徑上,你就需要用這個(gè)選項(xiàng)指定這個(gè)子路徑。

          例如:如果你的應(yīng)用被部署在 https://www.my-app.com/my-app/,則設(shè)置 publicPath為 /my-app/。這個(gè)值也可以被設(shè)置為空字符串 ('') 或是相對(duì)路徑 ('./'),這樣所有的資源都會(huì)被鏈接為相對(duì)路

          8.3解決手段2

          經(jīng)過(guò)一頓操作之后發(fā)現(xiàn)仍然還是空白,并且打開(kāi)控制臺(tái)看到頁(yè)面可以正常加載資源文件,但是 index.html 返回此類錯(cuò)誤:“We're sorry but XXX doesn't work properly without JavaScript”,經(jīng)過(guò)查找發(fā)現(xiàn)可以通過(guò)修改路由模式來(lái)解決,經(jīng)過(guò)測(cè)試確實(shí)有效。

          參考文章為:vue3項(xiàng)目打包時(shí)We're sorry but XXX doesn't work properly without JavaScript》。

          修改后的代碼示例:

          const router = createRouter({

            //改為#則可以直接變更路由模式

            history: createWebHistory('#'),

            routes,

          });

          9、痛苦踩坑2:頁(yè)面展示正常后,調(diào)用登錄報(bào)錯(cuò)

          問(wèn)題簡(jiǎn)述:頁(yè)面展示正常后,調(diào)用登錄發(fā)現(xiàn)出現(xiàn)如下圖所示的報(bào)錯(cuò)。

           

          解決方式:經(jīng)發(fā)現(xiàn)原來(lái)是發(fā)起 axios 請(qǐng)求環(huán)信置換連接 token 接口的時(shí)候,協(xié)議的獲取是通過(guò)window.location.protocol來(lái)獲取的,那么打包之后的協(xié)議為file:那么這時(shí)發(fā)起的請(qǐng)求就會(huì)變更為以 file 協(xié)議發(fā)起的請(qǐng)求,那么修改這里的邏輯,判斷如果為 file 協(xié)議則默認(rèn)走 http 協(xié)議發(fā)起請(qǐng)求。

          示例代碼如下:

          import axios from 'axios';

          const defaultBaseUrl = '//a1.easemob.com';

          console.log('window.location.protocol', window.location.protocol);

          // create an axios instance

          const service = axios.create({

            withCredentials: false,

            // baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url

            baseURL: `${

              window.location.protocol === 'file:' ? 'https:' : window.location.protocol

            }${defaultBaseUrl}`,

            // withCredentials: true, // send cookies when cross-domain requests

            timeout: 30000, // request timeout

            headers: { 'Content-Type': 'application/json' },

          });

          // request interceptor

          service.interceptors.request.use(

            (config) => {

              // do something before request is sent

              return config;

            },

            (error) => {

              // do something with request error

              console.log('request error', error); // for debug

              return Promise.reject(error);

            }

          );

           

          // response interceptor

          service.interceptors.response.use(

            /**

             * If you want to get http information such as headers or status

             * Please return  response => response

             */

           

            /**

             * Determine the request status by custom code

             * Here is just an example

             * You can also judge the status by HTTP Status Code

             */

            (response) => {

              const res = response.data;

              const code = response.status;

              // if the custom code is not 20000, it is judged as an error.

              if (code >= 400) {

                return Promise.reject(new Error(res.desc || 'Error'));

              } else {

                return res;

              }

            },

            (error) => {

              if (error.response) {

                const res = error.response.data; // for debug

                if (error.response.status === 401 && res.code !== '001') {

                  console.log('>>>>>無(wú)權(quán)限');

                }

                if (error.response.status === 403) {

                  res.desc = '您沒(méi)有權(quán)限進(jìn)行查詢和操作!';

                }

                return Promise.reject(res.desc || error);

              }

              return Promise.reject(error);

            }

          );

           

          export default service;

          10、參考資料

          [1] Electron官方文檔

          [2] 快速了解新一代跨平臺(tái)桌面技術(shù)——Electron

          [3] Electron初體驗(yàn)(快速開(kāi)始、跨進(jìn)程通信、打包、踩坑等)

          [4] Electron + Vue3 + TS + Vite 桌面應(yīng)用項(xiàng)目搭建教程

          [5] Electron + Vue3 +Ant Design Vue 桌面應(yīng)用從項(xiàng)目搭建到打包發(fā)布

          [6] vivo的Electron技術(shù)棧選型、全方位實(shí)踐總結(jié)

          [7] 一文讀懂前端技術(shù)演進(jìn):盤點(diǎn)Web前端20年的技術(shù)變遷史

          [8] 詳解Web端通信方式的演進(jìn):從Ajax、JSONP 到 SSE、Websocket

          [9] WebSocket從入門到精通,半小時(shí)就夠!

          (本文已同步發(fā)布于:http://www.52im.net/thread-4666-1-1.html



          作者:Jack Jiang (點(diǎn)擊作者姓名進(jìn)入Github)
          出處:http://www.52im.net/space-uid-1.html
          交流:歡迎加入即時(shí)通訊開(kāi)發(fā)交流群 215891622
          討論:http://www.52im.net/
          Jack Jiang同時(shí)是【原創(chuàng)Java Swing外觀工程BeautyEye】【輕量級(jí)移動(dòng)端即時(shí)通訊框架MobileIMSDK】的作者,可前往下載交流。
          本博文 歡迎轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)注明出處(也可前往 我的52im.net 找到我)。


          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          Jack Jiang的 Mail: jb2011@163.com, 聯(lián)系QQ: 413980957, 微信: hellojackjiang
          主站蜘蛛池模板: 乐业县| 富裕县| 屏南县| 孟州市| 鲁甸县| 临清市| 临猗县| 天水市| 永泰县| 新安县| 吴忠市| 开原市| 乌拉特后旗| 芮城县| 宁阳县| 鸡东县| 治县。| 恩施市| 微山县| 开鲁县| 康平县| 西畴县| 吴忠市| 文昌市| 巴林左旗| 喀喇沁旗| 阿克陶县| 刚察县| 东源县| 河津市| 毕节市| 前郭尔| 库车县| 岚皋县| 雷波县| 武川县| 文山县| 临颍县| 和田市| 安庆市| 苗栗市|