├── .browserslistrc
├── .eslintrc.js
├── .gitignore
├── README.md
├── babel.config.js
├── package-lock.json
├── package.json
├── public
├── favicon.ico
├── icon
│ ├── icon.icns
│ └── icon.ico
└── index.html
├── screen
└── demo.png
├── src
├── App.vue
├── assets
│ ├── electron.png
│ ├── logo.png
│ └── style
│ │ └── public.css
├── background.ts
├── components
│ └── public
│ │ └── SystemInformation.vue
├── main.ts
├── router
│ └── index.ts
├── shims-tsx.d.ts
├── shims-vue.d.ts
├── store
│ └── index.ts
├── utils
│ ├── cookie.ts
│ ├── index.ts
│ └── main
│ │ ├── checkUpdate.ts
│ │ └── windowControl.ts
└── views
│ └── home.vue
├── tsconfig.json
└── vue.config.js
/.browserslistrc:
--------------------------------------------------------------------------------
1 | > 1%
2 | last 2 versions
3 | not dead
4 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: {
4 | node: true,
5 | },
6 | extends: ['plugin:vue/essential', '@vue/typescript'],
7 | rules: {
8 | 'no-console': 'off',
9 | 'no-debugger': 'off',
10 | 'no-duplicate-case': 2,
11 | eqeqeq: [2, 'allow-null'],
12 | 'eol-last': ['error', 'always'],
13 | '@typescript-eslint/no-var-requires': 0,
14 | },
15 | parserOptions: {
16 | parser: '@typescript-eslint/parser',
17 | },
18 | };
19 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 | /dist_electron
5 | /build
6 |
7 |
8 | # local env files
9 | .env.local
10 | .env.*.local
11 |
12 | # Log files
13 | npm-debug.log*
14 | yarn-debug.log*
15 | yarn-error.log*
16 | pnpm-debug.log*
17 |
18 | # Editor directories and files
19 | .idea
20 | .vscode
21 | *.suo
22 | *.ntvs*
23 | *.njsproj
24 | *.sln
25 | *.sw?
26 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # electron-vue-cli3(electron和vue cli3的基础开发示例)
2 |
3 | > electron+cli3+ts
4 |
5 | ## 个人博客
6 | - [Blog](https://blog.zjinh.cn/)
7 | ## 🖥 运行效果
8 | 
9 |
10 | ### 克隆代码
11 | ```bash
12 | git clone https://github.com/zjinh/electron-vue-cli3.git
13 | ```
14 |
15 | ### 安装依赖
16 | ```bash
17 | cd electron-vue-cli3
18 | npm i
19 | ```
20 | ### 淘宝的npm源
21 | ```bash
22 | npm config set registry 'https://registry.npm.taobao.org'
23 | npm config set ELECTRON_MIRROR='https://npm.taobao.org/mirrors/electron/'
24 | ```
25 | 或者使用[Yarn](https://yarnpkg.com/)安装依赖
26 |
27 | ### 运行项目
28 | ```bash
29 | npm run dev
30 | npm run dev:web
31 | ```
32 | ### 打包项目
33 | ```bash
34 | npm run build
35 | npm run build:web
36 | ```
37 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ['@vue/cli-plugin-babel/preset'],
3 | };
4 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "electron-vue-cli3",
3 | "author": "ZJINH",
4 | "version": "2.0.0",
5 | "private": true,
6 | "appId": "com.zjinh.app.test",
7 | "main": "background.js",
8 | "scripts": {
9 | "lint": "vue-cli-service lint",
10 | "dev": "vue-cli-service lint && vue-cli-service electron:serve",
11 | "build": "vue-cli-service lint && vue-cli-service electron:build",
12 | "dev:web": "vue-cli-service serve",
13 | "build:web": "vue-cli-service build",
14 | "postinstall": "electron-builder install-app-deps",
15 | "postuninstall": "electron-builder install-app-deps",
16 | "electron:generate-icons": "electron-icon-builder --input=./public/icon.png --output=build --flatten"
17 | },
18 | "dependencies": {
19 | "@types/lodash": "^4.14.173",
20 | "axios": "^0.21.1",
21 | "core-js": "^3.18.0",
22 | "electron-updater": "^4.3.9",
23 | "vue": "^2.6.11",
24 | "vue-router": "^3.2.0",
25 | "vuex": "^3.4.0"
26 | },
27 | "devDependencies": {
28 | "@typescript-eslint/eslint-plugin": "^4.31.1",
29 | "@typescript-eslint/parser": "^4.31.1",
30 | "@vue/cli-plugin-babel": "~4.5.0",
31 | "@vue/cli-plugin-eslint": "~4.5.0",
32 | "@vue/cli-plugin-router": "~4.5.0",
33 | "@vue/cli-plugin-typescript": "^4.5.13",
34 | "@vue/cli-plugin-vuex": "~4.5.0",
35 | "@vue/cli-service": "~4.5.0",
36 | "@vue/eslint-config-typescript": "^7.0.0",
37 | "electron": "^14.0.1",
38 | "electron-icon-builder": "^2.0.1",
39 | "eslint": "^7.32.0",
40 | "eslint-plugin-vue": "^7.18.0",
41 | "node-sass": "^4.12.0",
42 | "sass-loader": "^8.0.2",
43 | "typescript": "~4.1.5",
44 | "vue-cli-plugin-electron-builder": "^1.4.6",
45 | "vue-template-compiler": "^2.6.11"
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zjinh/electron-vue-cli3/299146715aa6434dd24abe08b0cd81c6e7f0aee8/public/favicon.ico
--------------------------------------------------------------------------------
/public/icon/icon.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zjinh/electron-vue-cli3/299146715aa6434dd24abe08b0cd81c6e7f0aee8/public/icon/icon.icns
--------------------------------------------------------------------------------
/public/icon/icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zjinh/electron-vue-cli3/299146715aa6434dd24abe08b0cd81c6e7f0aee8/public/icon/icon.ico
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | <%= htmlWebpackPlugin.options.title %>
9 |
10 |
11 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/screen/demo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zjinh/electron-vue-cli3/299146715aa6434dd24abe08b0cd81c6e7f0aee8/screen/demo.png
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
10 |
--------------------------------------------------------------------------------
/src/assets/electron.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zjinh/electron-vue-cli3/299146715aa6434dd24abe08b0cd81c6e7f0aee8/src/assets/electron.png
--------------------------------------------------------------------------------
/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zjinh/electron-vue-cli3/299146715aa6434dd24abe08b0cd81c6e7f0aee8/src/assets/logo.png
--------------------------------------------------------------------------------
/src/assets/style/public.css:
--------------------------------------------------------------------------------
1 | *{
2 | margin: 0;
3 | padding: 0;
4 | box-sizing: border-box;
5 | font-family: '微软雅黑';
6 | }
7 | ul,li{
8 | list-style: none;
9 | margin: 0;
10 | padding: 0;
11 | }
12 | :focus,:active{
13 | outline:0;
14 | }
15 | a:hover,a:link,a:visited {
16 | text-decoration:none;
17 | }
18 | input:-webkit-autofill{
19 | -webkit-box-shadow: 0 0 0 400px #fff inset!important;
20 | -webkit-text-fill-color: #666666!important;
21 | }
22 | button,input,select,textarea {
23 | border: none;
24 | -webkit-transition:all .35s;
25 | -moz-transition:all .35s;
26 | -o-transition:all .35s;
27 | resize: none!important;
28 | }
29 | button{
30 | cursor: pointer;
31 | }
32 | button[disabled]{
33 | cursor: not-allowed;
34 | opacity: .5;
35 | }
36 | #app,body,html{
37 | width: 100%;
38 | height: 100%;
39 | overflow: hidden;
40 | user-select: none;
41 | background: transparent none !important;
42 | }
43 |
--------------------------------------------------------------------------------
/src/background.ts:
--------------------------------------------------------------------------------
1 | import packageInfo from '../package.json';
2 | import { app, protocol, ipcMain, BrowserWindow } from 'electron';
3 | import { createProtocol } from 'vue-cli-plugin-electron-builder/lib';
4 | import { WindowControl } from './utils/main/windowControl';
5 | import CheckUpdate from './utils/main/CheckUpdate';
6 | protocol.registerSchemesAsPrivileged([{ scheme: 'app', privileges: { secure: true, standard: true } }]);
7 | const windowControl = new WindowControl();
8 | const checkUpdate = new CheckUpdate();
9 | let win: BrowserWindow | null = null;
10 | /*初始化ipc*/
11 | function bindIpc() {
12 | /*系统操作事件*/
13 | ipcMain.on('system', (event, type, data) => {
14 | switch (type) {
15 | case 'check-for-update' /*检查更新*/:
16 | checkUpdate.check(event, data);
17 | break;
18 | case 'update' /*安装更新*/:
19 | checkUpdate.update();
20 | break;
21 | case 'exit':
22 | app.quit();
23 | break;
24 | }
25 | });
26 | }
27 | /*创建窗口*/
28 | function createWindow() {
29 | win = windowControl.create({
30 | frame: true,
31 | name: 'home',
32 | url: '',
33 | });
34 | }
35 | const gotTheLock = app.requestSingleInstanceLock();
36 | if (!gotTheLock) {
37 | app.quit();
38 | } else {
39 | app.on('second-instance', () => {
40 | //这里是单例模式,当已经存在窗口仍然打开的处理
41 | if (win) {
42 | win.show();
43 | }
44 | });
45 | app.on('ready', function () {
46 | bindIpc(); //初始化ipc
47 | createProtocol('app');
48 | app.setAppUserModelId(packageInfo.appId);
49 | app.commandLine.appendSwitch('autoplay-policy', 'no-user-gesture-required');
50 | createWindow();
51 | });
52 | }
53 | app.on('window-all-closed', () => {
54 | if (process.platform !== 'darwin') {
55 | app.quit();
56 | }
57 | });
58 | app.on('activate', () => {
59 | if (win === null) {
60 | createWindow();
61 | }
62 | });
63 |
--------------------------------------------------------------------------------
/src/components/public/SystemInformation.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 | 路由地址:
5 | {{ path }}
6 |
7 | -
8 | 路由名称:
9 | {{ name }}
10 |
11 | -
12 | Vue.js:
13 | {{ vue }}
14 |
15 | -
16 | Electron:
17 | {{ electron }}
18 |
19 | -
20 | Node:
21 | {{ node }}
22 |
23 | -
24 | 系统类型:
25 | {{ platform }}
26 |
27 |
28 |
29 |
30 |
45 |
46 |
79 |
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import App from './App.vue';
3 | import router from './router';
4 | import store from './store';
5 | require('./utils/index');
6 | declare module 'vue/types/vue' {
7 | interface Vue {
8 | $ipc: any;
9 | $cookie: any;
10 | $notify: Function;
11 | $electron: any;
12 | }
13 | }
14 | Vue.config.productionTip = false;
15 | new Vue({
16 | router,
17 | store,
18 | render: (h) => h(App),
19 | }).$mount('#app');
20 |
--------------------------------------------------------------------------------
/src/router/index.ts:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import VueRouter, { RouteConfig } from 'vue-router';
3 |
4 | Vue.use(VueRouter);
5 |
6 | const routes: Array = [
7 | {
8 | path: '/',
9 | name: 'Home',
10 | component: () => import('../views/home.vue'),
11 | },
12 | ];
13 |
14 | const router = new VueRouter({
15 | routes,
16 | });
17 |
18 | export default router;
19 |
--------------------------------------------------------------------------------
/src/shims-tsx.d.ts:
--------------------------------------------------------------------------------
1 | import Vue, { VNode } from 'vue';
2 |
3 | declare global {
4 | namespace JSX {
5 | // tslint:disable no-empty-interface
6 | interface Element extends VNode {}
7 | // tslint:disable no-empty-interface
8 | interface ElementClass extends Vue {}
9 | interface IntrinsicElements {
10 | [elem: string]: any;
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/shims-vue.d.ts:
--------------------------------------------------------------------------------
1 | declare module '*.vue' {
2 | import Vue from 'vue';
3 | export default Vue;
4 | }
5 | declare module '*.json' {
6 | const value: any;
7 | export default value;
8 | }
9 |
--------------------------------------------------------------------------------
/src/store/index.ts:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import Vuex from 'vuex';
3 |
4 | Vue.use(Vuex);
5 |
6 | export default new Vuex.Store({
7 | state: {},
8 | mutations: {},
9 | actions: {},
10 | modules: {},
11 | });
12 |
--------------------------------------------------------------------------------
/src/utils/cookie.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | get: function (name: string) {
3 | let arr;
4 | const reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)');
5 | if ((arr = document.cookie.match(reg))) return decodeURIComponent(arr[2]);
6 | else return null;
7 | },
8 | set: function (name: string, value: any, time: number) {
9 | const exp = new Date();
10 | exp.setTime(exp.getTime() + time * 1000);
11 | document.cookie = name + '=' + encodeURI(value) + ';expires=' + exp.toUTCString() + ';path=/';
12 | },
13 | remove: function (name: string) {
14 | const exp = new Date();
15 | exp.setTime(exp.getTime() - 1);
16 | if (this.get(name) != null) document.cookie = name + '=' + this.get(name) + ';expires=' + exp.toUTCString();
17 | },
18 | };
19 |
--------------------------------------------------------------------------------
/src/utils/index.ts:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | const path = require('path');
3 | /*开始自动化引入公用组件*/
4 | const requireComponent = require.context('../components/public', true, /\.vue$/);
5 | requireComponent.keys().forEach((fileName) => {
6 | // 获取组件配置
7 | const componentConfig = requireComponent(fileName);
8 | // 剥去文件名开头的 `./` 和`.vue`结尾的扩展名
9 | const componentName = path.basename(fileName).replace(/\.vue$/, '');
10 | // 全局注册组件
11 | Vue.component(componentName.replace(/\//, '-'), componentConfig.default || componentConfig);
12 | });
13 | //cookie模块
14 | Vue.prototype.$cookie = require('./cookie');
15 | //ipc模块
16 | if (!!process.versions) {
17 | const electron = require('electron');
18 | const ipcRenderer = electron.ipcRenderer;
19 | //引入electron接口
20 | Vue.prototype.$electron = electron; //electron
21 | Vue.prototype.$ipc = ipcRenderer; //ipc接口
22 | }
23 | //系统通知
24 | Vue.prototype.$notify = function (msg: string, title: string) {
25 | const notification = {
26 | title: title,
27 | body: msg,
28 | icon: require('../assets/logo.png'),
29 | };
30 | return new window.Notification(notification.title, notification);
31 | };
32 |
--------------------------------------------------------------------------------
/src/utils/main/checkUpdate.ts:
--------------------------------------------------------------------------------
1 | import { autoUpdater } from 'electron-updater';
2 | import { EventEmitter } from 'events';
3 |
4 | class CheckUpdate extends EventEmitter {
5 | constructor() {
6 | super();
7 | }
8 | init(event) {
9 | const message = {
10 | appName: 'CloudDisk',
11 | error: '检查更新出错, 请联系开发人员',
12 | checking: '正在检查更新……',
13 | updateAva: '检测到新版本,正在下载……',
14 | updateNotAva: '现在使用的就是最新版本,不用更新',
15 | downloaded: '最新版本已下载,点击安装进行更新',
16 | };
17 | //当开始检查更新的时候触发
18 | autoUpdater.on('checking-for-update', function () {
19 | event.sender.send('check-for-update', message.checking); //返回一条信息
20 | });
21 | //当发现一个可用更新的时候触发,更新包下载会自动开始
22 | autoUpdater.on('update-available', function (info) {
23 | event.sender.send('update-down-success', info);
24 | event.sender.send('check-for-update', message.updateAva); //返回一条信息
25 | });
26 | //当没有可用更新的时候触发
27 | autoUpdater.on('update-not-available', function () {
28 | event.sender.send('check-for-update', message.updateNotAva); //返回一条信息
29 | });
30 | autoUpdater.on('error', function () {
31 | event.sender.send('check-for-update', message.error); //返回一条信息
32 | });
33 | // 更新下载进度事件
34 | autoUpdater.on('download-progress', (progressObj) => {
35 | event.sender.send('download-progress', progressObj);
36 | });
37 | autoUpdater.on('update-downloaded', function () {
38 | event.sender.send('check-for-update', message.downloaded); //返回一条信息
39 | //通过main进程发送事件给renderer进程,提示更新信息
40 | });
41 | }
42 | check(event, data: string) {
43 | autoUpdater.setFeedURL(data);
44 | this.init(event);
45 | autoUpdater.checkForUpdates();
46 | }
47 | update() {
48 | //安装更新
49 | autoUpdater.quitAndInstall();
50 | }
51 | }
52 | export default CheckUpdate;
53 |
--------------------------------------------------------------------------------
/src/utils/main/windowControl.ts:
--------------------------------------------------------------------------------
1 | import { BrowserWindow, Menu } from 'electron';
2 | const { projectName } = require('../../../package.json');
3 | const isDevelopment = process.env.NODE_ENV !== 'production';
4 | import { EventEmitter } from 'events';
5 | interface WindowControlType {
6 | getWindow: Function;
7 | create: Function;
8 | active: Function;
9 | closeAll: Function;
10 | }
11 | const port = 9020;
12 | class WindowControl extends EventEmitter {
13 | constructor() {
14 | super();
15 | }
16 | isMacOs = process.platform === 'darwin';
17 | winList: any = {};
18 | create(options: any) {
19 | const name: string = options.name;
20 | const data: any = options.data;
21 | if (!name) {
22 | return;
23 | }
24 | //存在就激活窗口
25 | if (this.getWindow(name)) {
26 | this.active(name, data);
27 | return;
28 | }
29 | Menu.setApplicationMenu(null);
30 | const defaultOptions = {
31 | width: 800,
32 | height: 600,
33 | title: projectName,
34 | frame: this.isMacOs,
35 | useContentSize: false,
36 | transparent: false,
37 | minimizable: true,
38 | maximizable: true,
39 | resizable: true,
40 | alwaysOnTop: false,
41 | show: false,
42 | titleBarStyle: 'hiddenInset',
43 | webPreferences: {
44 | devTools: isDevelopment,
45 | nodeIntegration: true,
46 | webSecurity: false,
47 | scrollBounce: true,
48 | contextIsolation: false,
49 | enableRemoteModule: true,
50 | plugins: true,
51 | webviewTag: true,
52 | },
53 | };
54 | options = Object.assign(defaultOptions, options);
55 | this.winList[name] = new BrowserWindow(options);
56 | this.winList[name] = this.winList[name];
57 | if (options.backgroundColor) {
58 | this.winList[name].setBackgroundColor(options.backgroundColor);
59 | }
60 | //自定义回调
61 | this.winList[name].callback = (data: any) => {
62 | this.winList[name].webContents.send('win-data', data);
63 | typeof options.callback === 'function' ? options.callback() : '';
64 | };
65 | //加载url
66 | this.winList[name].loadURL(this.createUrl(options.url)).then(() => {
67 | this.winList[name].setTitle(options.title);
68 | this.winList[name].callback(data);
69 | });
70 | isDevelopment && this.winList[name].webContents.openDevTools();
71 | //处理显示
72 | this.winList[name].on('ready-to-show', (event: Event) => {
73 | this.winList[name].show();
74 | this.winList[name].focus();
75 | typeof options.ready === 'function' ? options.ready(event) : '';
76 | });
77 | //处理关闭
78 | this.winList[name].on('closed', (event: Event) => {
79 | delete this.winList[name];
80 | typeof options.onclose === 'function' ? options.onclose(event) : '';
81 | });
82 | return this.winList[name];
83 | }
84 | getWindow(windowName: string) {
85 | return this.winList[windowName];
86 | }
87 | active(windowName: string, data: any) {
88 | const currentWin = this.getWindow(windowName);
89 | if (currentWin) {
90 | currentWin.show();
91 | currentWin.focus();
92 | data && currentWin.callback(data);
93 | }
94 | }
95 | createUrl(router: string) {
96 | if (router.includes('file://') || router.includes('http')) {
97 | return router;
98 | }
99 | if (isDevelopment) {
100 | return `http://localhost:${port}/#/` + router;
101 | }
102 | return 'app://./index.html#/' + router;
103 | }
104 | closeAll(filterNotClose: Array = []) {
105 | for (const name in this.winList) {
106 | const win = this.winList[name];
107 | if (!filterNotClose.includes(name)) {
108 | win.close();
109 | }
110 | }
111 | }
112 | cloudWindow(options: any, callback: Function, onClose: Function) {
113 | return this.create({
114 | ...options,
115 | onclose: () => {
116 | onClose && onClose();
117 | },
118 | callback: () => {
119 | callback && callback();
120 | },
121 | });
122 | }
123 | }
124 |
125 | export { WindowControl, WindowControlType };
126 |
--------------------------------------------------------------------------------
/src/views/home.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |

5 |
+
6 |

7 |
8 |
9 |
10 |
项目说明
11 |
12 | - 包含了检查升级模块
13 | - 包含了窗口管理模块
14 | - 默认为单例模式
15 | - 使用了scss
16 | - 封装了cookiethis.$cookie方法
17 | - 封装了系统通知this.$notify方法
18 | - 封装了ipc通信方法this.$ipc
19 | - electron方法this.$electron
20 | - 集成了electron-updater
21 | - 自引入components/public下的组件将自动注册
22 |
23 |
24 |
25 |
基本信息
26 |
27 |
28 |
29 |
简单示例
30 |
31 |
35 | {{ message }}
36 |
37 |
38 |
相关文档
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
111 |
112 |
178 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "esnext",
4 | "module": "esnext",
5 | "strict": true,
6 | "jsx": "preserve",
7 | "importHelpers": true,
8 | "moduleResolution": "node",
9 | "experimentalDecorators": true,
10 | "esModuleInterop": true,
11 | "allowSyntheticDefaultImports": true,
12 | "sourceMap": false,
13 | "baseUrl": ".",
14 | "noImplicitAny": false,
15 | "types": [
16 | "webpack-env",
17 | "jest"
18 | ],
19 | "paths": {
20 | "@/*": [
21 | "src/*"
22 | ]
23 | },
24 | "lib": [
25 | "esnext",
26 | "dom",
27 | "dom.iterable",
28 | "scripthost"
29 | ]
30 | },
31 | "include": [
32 | "src/**/*.ts",
33 | "src/**/*.tsx",
34 | "src/**/*.vue",
35 | "tests/**/*.ts",
36 | "tests/**/*.tsx"
37 | ],
38 | "exclude": [
39 | "node_modules"
40 | ]
41 | }
42 |
--------------------------------------------------------------------------------
/vue.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | function resolve(dir) {
3 | return path.join(__dirname, dir);
4 | }
5 | const productName = 'test';
6 | const appId = 'com.zjinh.app.' + productName;
7 | const menuCategory = 'electron-cli3';
8 | const shortcutName = 'cli3-测试';
9 | const port = 9020;
10 | module.exports = {
11 | /*publicPath: '/',
12 | outputDir: 'dist',
13 | assetsDir: 'static',
14 | lintOnSave: process.env.NODE_ENV === 'development',
15 | productionSourceMap: false,*/
16 | devServer: {
17 | port: port,
18 | /* open: true,
19 | overlay: {
20 | warnings: false,
21 | errors: true
22 | }*/
23 | },
24 | chainWebpack(config) {
25 | // alias
26 | config.resolve.alias.set('@', resolve('src'));
27 | },
28 | pluginOptions: {
29 | electronBuilder: {
30 | builderOptions: {
31 | productName: productName,
32 | appId: appId,
33 | directories: {
34 | output: 'build',
35 | },
36 | win: {
37 | icon: 'public/icon/icon.ico',
38 | artifactName: '${productName}_setup_${version}.${ext}',
39 | target: ['nsis'],
40 | },
41 | nsis: {
42 | oneClick: false,
43 | menuCategory: menuCategory,
44 | shortcutName: shortcutName,
45 | allowToChangeInstallationDirectory: true,
46 | perMachine: true,
47 | runAfterFinish: true,
48 | },
49 | dmg: {
50 | contents: [
51 | {
52 | x: 410,
53 | y: 150,
54 | type: 'link',
55 | path: '/Applications',
56 | },
57 | {
58 | x: 130,
59 | y: 150,
60 | type: 'file',
61 | },
62 | ],
63 | },
64 | mac: {
65 | icon: 'public/icon/icon.icns',
66 | },
67 | linux: {
68 | icon: 'public/icon/icon.ico',
69 | },
70 | },
71 | },
72 | },
73 | };
74 |
--------------------------------------------------------------------------------