烧录软件(单个烧录)
commit
7c30acc526
|
@ -0,0 +1,8 @@
|
|||
node_modules
|
||||
.DS_Store
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
.vscode
|
||||
.idea
|
|
@ -0,0 +1,26 @@
|
|||
# Vite Electron Typescript Template
|
||||
|
||||
`vite 2` `vue 3` `electron 12`
|
||||
|
||||
## How to use
|
||||
clone the repo via git and install dependencies:
|
||||
```shell
|
||||
git clone --depth 1 --single-branch https://github.com/hocili/vite-electron-typescript-template.git your-project-name
|
||||
cd your-project-name
|
||||
yarn
|
||||
```
|
||||
|
||||
## Starting Development
|
||||
Start the app in the `dev` environment:
|
||||
```shell
|
||||
yarn dev
|
||||
```
|
||||
|
||||
```shell
|
||||
yarn electron:dev
|
||||
```
|
||||
## Packaging for Production
|
||||
To package apps for the local platform:
|
||||
```shell
|
||||
yarn electron:build
|
||||
```
|
|
@ -0,0 +1,57 @@
|
|||
const fs = require('fs')
|
||||
const archiver = require('archiver')
|
||||
const { Platform } = require("electron-builder")
|
||||
const { name } = require('./package.json')
|
||||
|
||||
exports.default = function (buildResult) {
|
||||
// you can return additional files to publish
|
||||
// return ["/path/to/additional/result/file"]
|
||||
|
||||
const zipFilePath = buildResult.outDir + '/' + name + '.zip'
|
||||
const sourceDirPath = buildResult.outDir + '/' + Platform.current().buildConfigurationKey + '-unpacked/'
|
||||
|
||||
// create a file to stream archive data to.
|
||||
const output = fs.createWriteStream(zipFilePath)
|
||||
const archive = archiver('zip', {
|
||||
zlib: { level: 9 } // Sets the compression level.
|
||||
})
|
||||
|
||||
// listen for all archive data to be written
|
||||
// 'close' event is fired only when a file descriptor is involved
|
||||
output.on('close', function() {
|
||||
console.log(archive.pointer() + ' total bytes');
|
||||
console.log('archiver has been finalized and the output file descriptor has closed.');
|
||||
});
|
||||
|
||||
// This event is fired when the data source is drained no matter what was the data source.
|
||||
// It is not part of this library but rather from the NodeJS Stream API.
|
||||
// @see: https://nodejs.org/api/stream.html#stream_event_end
|
||||
output.on('end', function() {
|
||||
console.log('Data has been drained');
|
||||
});
|
||||
|
||||
// good practice to catch warnings (ie stat failures and other non-blocking errors)
|
||||
archive.on('warning', function(err) {
|
||||
if (err.code === 'ENOENT') {
|
||||
// log warning
|
||||
} else {
|
||||
// throw error
|
||||
throw err;
|
||||
}
|
||||
});
|
||||
|
||||
// good practice to catch this error explicitly
|
||||
archive.on('error', function(err) {
|
||||
throw err;
|
||||
});
|
||||
|
||||
// pipe archive data to the file
|
||||
archive.pipe(output);
|
||||
|
||||
// append files from a sub-directory, putting its contents at the root of archive
|
||||
archive.directory(sourceDirPath, false);
|
||||
|
||||
// finalize the archive (ie we are done appending files but streams have to finish yet)
|
||||
// 'close', 'end' or 'finish' may be fired right after calling this method so register to them beforehand
|
||||
archive.finalize();
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>esp32程序烧录</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/render/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,4 @@
|
|||
require('ts-node').register({
|
||||
project:'./tsconfig.electron.json'
|
||||
});
|
||||
require('./src/main/app.ts')
|
|
@ -0,0 +1,210 @@
|
|||
{
|
||||
root: 'D:\\VS Code\\hwasmart-yanfaleixiangmu-esp32-program-burner-',
|
||||
registry: 'https://registry.npmmirror.com',
|
||||
pkgs: [
|
||||
{
|
||||
name: 'archiver',
|
||||
version: '5.3.1',
|
||||
type: 'version',
|
||||
alias: undefined,
|
||||
arg: [Result]
|
||||
},
|
||||
{
|
||||
name: 'dev',
|
||||
version: 'latest',
|
||||
type: 'tag',
|
||||
alias: undefined,
|
||||
arg: [Result]
|
||||
}
|
||||
],
|
||||
production: false,
|
||||
cacheStrict: false,
|
||||
cacheDir: 'C:\\Users\\OEM\\.npminstall_tarball',
|
||||
env: {
|
||||
npm_config_registry: 'https://registry.npmmirror.com',
|
||||
npm_config_argv: '{"remain":[],"cooked":["--fix-bug-versions","--china","--userconfig=C:\\\\Users\\\\OEM\\\\.cnpmrc","--disturl=https://cdn.npmmirror.com/binaries/node","--registry=https://registry.npmmirror.com","archiver@5.3.1","dev"],"original":["--fix-bug-versions","--china","--userconfig=C:\\\\Users\\\\OEM\\\\.cnpmrc","--disturl=https://cdn.npmmirror.com/binaries/node","--registry=https://registry.npmmirror.com","archiver@5.3.1","dev"]}',
|
||||
npm_config_user_agent: 'npminstall/7.9.0 npm/? node/v16.18.1 win32 x64',
|
||||
npm_config_cache: 'C:\\Users\\OEM\\.npminstall_tarball',
|
||||
NODE: 'C:\\Program Files\\nodejs\\node.exe',
|
||||
npm_node_execpath: 'C:\\Program Files\\nodejs\\node.exe',
|
||||
npm_execpath: 'C:\\Users\\OEM\\AppData\\Roaming\\npm\\node_modules\\cnpm\\node_modules\\npminstall\\bin\\install.js',
|
||||
npm_config_userconfig: 'C:\\Users\\OEM\\.cnpmrc',
|
||||
npm_config_disturl: 'https://cdn.npmmirror.com/binaries/node',
|
||||
npm_config_r: 'https://registry.npmmirror.com',
|
||||
COREPACK_NPM_REGISTRY: 'https://registry.npmmirror.com',
|
||||
NODEJS_ORG_MIRROR: 'https://cdn.npmmirror.com/binaries/node',
|
||||
NVM_NODEJS_ORG_MIRROR: 'https://cdn.npmmirror.com/binaries/node',
|
||||
PHANTOMJS_CDNURL: 'https://cdn.npmmirror.com/binaries/phantomjs',
|
||||
CHROMEDRIVER_CDNURL: 'https://cdn.npmmirror.com/binaries/chromedriver',
|
||||
OPERADRIVER_CDNURL: 'https://cdn.npmmirror.com/binaries/operadriver',
|
||||
CYPRESS_DOWNLOAD_PATH_TEMPLATE: 'https://cdn.npmmirror.com/binaries/cypress/${version}/${platform}-${arch}/cypress.zip',
|
||||
ELECTRON_MIRROR: 'https://cdn.npmmirror.com/binaries/electron/',
|
||||
ELECTRON_BUILDER_BINARIES_MIRROR: 'https://cdn.npmmirror.com/binaries/electron-builder-binaries/',
|
||||
SASS_BINARY_SITE: 'https://cdn.npmmirror.com/binaries/node-sass',
|
||||
SWC_BINARY_SITE: 'https://cdn.npmmirror.com/binaries/node-swc',
|
||||
NWJS_URLBASE: 'https://cdn.npmmirror.com/binaries/nwjs/v',
|
||||
PUPPETEER_DOWNLOAD_HOST: 'https://cdn.npmmirror.com/binaries/chrome-for-testing',
|
||||
PUPPETEER_DOWNLOAD_BASE_URL: 'https://cdn.npmmirror.com/binaries/chrome-for-testing',
|
||||
PLAYWRIGHT_DOWNLOAD_HOST: 'https://cdn.npmmirror.com/binaries/playwright',
|
||||
SENTRYCLI_CDNURL: 'https://cdn.npmmirror.com/binaries/sentry-cli',
|
||||
SAUCECTL_INSTALL_BINARY_MIRROR: 'https://cdn.npmmirror.com/binaries/saucectl',
|
||||
RE2_DOWNLOAD_MIRROR: 'https://cdn.npmmirror.com/binaries/node-re2',
|
||||
RE2_DOWNLOAD_SKIP_PATH: 'true',
|
||||
PRISMA_ENGINES_MIRROR: 'https://cdn.npmmirror.com/binaries/prisma',
|
||||
npm_config_better_sqlite3_binary_host: 'https://cdn.npmmirror.com/binaries/better-sqlite3',
|
||||
npm_config_keytar_binary_host: 'https://cdn.npmmirror.com/binaries/keytar',
|
||||
npm_config_sharp_binary_host: 'https://cdn.npmmirror.com/binaries/sharp',
|
||||
npm_config_sharp_libvips_binary_host: 'https://cdn.npmmirror.com/binaries/sharp-libvips',
|
||||
npm_config_robotjs_binary_host: 'https://cdn.npmmirror.com/binaries/robotjs',
|
||||
npm_rootpath: 'D:\\VS Code\\hwasmart-yanfaleixiangmu-esp32-program-burner-',
|
||||
INIT_CWD: 'D:\\VS Code\\hwasmart-yanfaleixiangmu-esp32-program-burner-'
|
||||
},
|
||||
binaryMirrors: {
|
||||
ENVS: {
|
||||
COREPACK_NPM_REGISTRY: 'https://registry.npmmirror.com',
|
||||
NODEJS_ORG_MIRROR: 'https://cdn.npmmirror.com/binaries/node',
|
||||
NVM_NODEJS_ORG_MIRROR: 'https://cdn.npmmirror.com/binaries/node',
|
||||
PHANTOMJS_CDNURL: 'https://cdn.npmmirror.com/binaries/phantomjs',
|
||||
CHROMEDRIVER_CDNURL: 'https://cdn.npmmirror.com/binaries/chromedriver',
|
||||
OPERADRIVER_CDNURL: 'https://cdn.npmmirror.com/binaries/operadriver',
|
||||
CYPRESS_DOWNLOAD_PATH_TEMPLATE: 'https://cdn.npmmirror.com/binaries/cypress/${version}/${platform}-${arch}/cypress.zip',
|
||||
ELECTRON_MIRROR: 'https://cdn.npmmirror.com/binaries/electron/',
|
||||
ELECTRON_BUILDER_BINARIES_MIRROR: 'https://cdn.npmmirror.com/binaries/electron-builder-binaries/',
|
||||
SASS_BINARY_SITE: 'https://cdn.npmmirror.com/binaries/node-sass',
|
||||
SWC_BINARY_SITE: 'https://cdn.npmmirror.com/binaries/node-swc',
|
||||
NWJS_URLBASE: 'https://cdn.npmmirror.com/binaries/nwjs/v',
|
||||
PUPPETEER_DOWNLOAD_HOST: 'https://cdn.npmmirror.com/binaries/chrome-for-testing',
|
||||
PUPPETEER_DOWNLOAD_BASE_URL: 'https://cdn.npmmirror.com/binaries/chrome-for-testing',
|
||||
PLAYWRIGHT_DOWNLOAD_HOST: 'https://cdn.npmmirror.com/binaries/playwright',
|
||||
SENTRYCLI_CDNURL: 'https://cdn.npmmirror.com/binaries/sentry-cli',
|
||||
SAUCECTL_INSTALL_BINARY_MIRROR: 'https://cdn.npmmirror.com/binaries/saucectl',
|
||||
RE2_DOWNLOAD_MIRROR: 'https://cdn.npmmirror.com/binaries/node-re2',
|
||||
RE2_DOWNLOAD_SKIP_PATH: 'true',
|
||||
PRISMA_ENGINES_MIRROR: 'https://cdn.npmmirror.com/binaries/prisma',
|
||||
npm_config_better_sqlite3_binary_host: 'https://cdn.npmmirror.com/binaries/better-sqlite3',
|
||||
npm_config_keytar_binary_host: 'https://cdn.npmmirror.com/binaries/keytar',
|
||||
npm_config_sharp_binary_host: 'https://cdn.npmmirror.com/binaries/sharp',
|
||||
npm_config_sharp_libvips_binary_host: 'https://cdn.npmmirror.com/binaries/sharp-libvips',
|
||||
npm_config_robotjs_binary_host: 'https://cdn.npmmirror.com/binaries/robotjs'
|
||||
},
|
||||
'@ali/s2': { host: 'https://cdn.npmmirror.com/binaries/looksgood-s2' },
|
||||
sharp: { replaceHostFiles: [Array], replaceHostMap: [Object] },
|
||||
'@tensorflow/tfjs-node': {
|
||||
replaceHostFiles: [Array],
|
||||
replaceHostRegExpMap: [Object],
|
||||
replaceHostMap: [Object]
|
||||
},
|
||||
cypress: {
|
||||
host: 'https://cdn.npmmirror.com/binaries/cypress',
|
||||
newPlatforms: [Object]
|
||||
},
|
||||
'utf-8-validate': {
|
||||
host: 'https://cdn.npmmirror.com/binaries/utf-8-validate/v{version}'
|
||||
},
|
||||
xprofiler: {
|
||||
remote_path: './xprofiler/v{version}/',
|
||||
host: 'https://cdn.npmmirror.com/binaries'
|
||||
},
|
||||
leveldown: { host: 'https://cdn.npmmirror.com/binaries/leveldown/v{version}' },
|
||||
couchbase: { host: 'https://cdn.npmmirror.com/binaries/couchbase/v{version}' },
|
||||
gl: { host: 'https://cdn.npmmirror.com/binaries/gl/v{version}' },
|
||||
sqlite3: {
|
||||
host: 'https://cdn.npmmirror.com/binaries/sqlite3',
|
||||
remote_path: 'v{version}'
|
||||
},
|
||||
'@journeyapps/sqlcipher': { host: 'https://cdn.npmmirror.com/binaries' },
|
||||
grpc: {
|
||||
host: 'https://cdn.npmmirror.com/binaries',
|
||||
remote_path: '{name}/v{version}'
|
||||
},
|
||||
'grpc-tools': { host: 'https://cdn.npmmirror.com/binaries' },
|
||||
wrtc: {
|
||||
host: 'https://cdn.npmmirror.com/binaries',
|
||||
remote_path: '{name}/v{version}'
|
||||
},
|
||||
fsevents: { host: 'https://cdn.npmmirror.com/binaries/fsevents' },
|
||||
nodejieba: { host: 'https://cdn.npmmirror.com/binaries/nodejieba' },
|
||||
canvas: { host: 'https://cdn.npmmirror.com/binaries/canvas' },
|
||||
'skia-canvas': { host: 'https://cdn.npmmirror.com/binaries/skia-canvas' },
|
||||
'flow-bin': {
|
||||
replaceHost: 'https://github.com/facebook/flow/releases/download/v',
|
||||
host: 'https://cdn.npmmirror.com/binaries/flow/v'
|
||||
},
|
||||
'jpegtran-bin': {
|
||||
replaceHost: [Array],
|
||||
host: 'https://cdn.npmmirror.com/binaries/jpegtran-bin'
|
||||
},
|
||||
'cwebp-bin': {
|
||||
replaceHost: [Array],
|
||||
host: 'https://cdn.npmmirror.com/binaries/cwebp-bin'
|
||||
},
|
||||
'zopflipng-bin': {
|
||||
replaceHost: [Array],
|
||||
host: 'https://cdn.npmmirror.com/binaries/zopflipng-bin'
|
||||
},
|
||||
'optipng-bin': {
|
||||
replaceHost: [Array],
|
||||
host: 'https://cdn.npmmirror.com/binaries/optipng-bin'
|
||||
},
|
||||
mozjpeg: {
|
||||
replaceHost: [Array],
|
||||
host: 'https://cdn.npmmirror.com/binaries/mozjpeg-bin'
|
||||
},
|
||||
gifsicle: {
|
||||
replaceHost: [Array],
|
||||
host: 'https://cdn.npmmirror.com/binaries/gifsicle-bin'
|
||||
},
|
||||
'pngquant-bin': {
|
||||
replaceHost: [Array],
|
||||
host: 'https://cdn.npmmirror.com/binaries/pngquant-bin',
|
||||
replaceHostMap: [Object]
|
||||
},
|
||||
'pngcrush-bin': {
|
||||
replaceHost: [Array],
|
||||
host: 'https://cdn.npmmirror.com/binaries/pngcrush-bin'
|
||||
},
|
||||
'jpeg-recompress-bin': {
|
||||
replaceHost: [Array],
|
||||
host: 'https://cdn.npmmirror.com/binaries/jpeg-recompress-bin'
|
||||
},
|
||||
'advpng-bin': {
|
||||
replaceHost: [Array],
|
||||
host: 'https://cdn.npmmirror.com/binaries/advpng-bin'
|
||||
},
|
||||
'pngout-bin': {
|
||||
replaceHost: [Array],
|
||||
host: 'https://cdn.npmmirror.com/binaries/pngout-bin'
|
||||
},
|
||||
'jpegoptim-bin': {
|
||||
replaceHost: [Array],
|
||||
host: 'https://cdn.npmmirror.com/binaries/jpegoptim-bin'
|
||||
},
|
||||
argon2: { host: 'https://cdn.npmmirror.com/binaries/argon2' },
|
||||
'ali-zeromq': { host: 'https://cdn.npmmirror.com/binaries/ali-zeromq' },
|
||||
'ali-usb_ctl': { host: 'https://cdn.npmmirror.com/binaries/ali-usb_ctl' },
|
||||
'gdal-async': { host: 'https://cdn.npmmirror.com/binaries/node-gdal-async' },
|
||||
'libpg-query': { host: 'https://cdn.npmmirror.com/binaries' }
|
||||
},
|
||||
forbiddenLicenses: null,
|
||||
flatten: false,
|
||||
proxy: undefined,
|
||||
prune: false,
|
||||
disableFallbackStore: false,
|
||||
workspacesMap: Map(0) {},
|
||||
enableWorkspace: false,
|
||||
workspaceRoot: 'D:\\VS Code\\hwasmart-yanfaleixiangmu-esp32-program-burner-',
|
||||
isWorkspaceRoot: true,
|
||||
isWorkspacePackage: false,
|
||||
offline: false,
|
||||
strictSSL: true,
|
||||
ignoreScripts: false,
|
||||
foregroundScripts: false,
|
||||
ignoreOptionalDependencies: false,
|
||||
detail: false,
|
||||
forceLinkLatest: false,
|
||||
trace: false,
|
||||
engineStrict: false,
|
||||
registryOnly: false,
|
||||
client: false,
|
||||
autoFixVersion: [Function: autoFixVersion]
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
{
|
||||
"name": "esp32-program-batch-burner",
|
||||
"version": "3.3.3",
|
||||
"description": "esp32程序批量烧录",
|
||||
"main": "dist/main/app.js",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"serve": "vite preview",
|
||||
"electron:dev": "cross-env NODE_ENV=development electron index.js",
|
||||
"electron:copy-esp32-dir": "fse copy ./public/esp32/ ./dist/release/win-unpacked/esp32/",
|
||||
"electron:build": "rimraf dist && vite build && tsc -p tsconfig.electron.json && electron-builder --dir && yarn electron:copy-esp32-dir"
|
||||
},
|
||||
"dependencies": {
|
||||
"archiver": "5.3.1",
|
||||
"serialport": "9.2.4",
|
||||
"vue": "^3.2.26"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@atao60/fse-cli": "^0.1.7",
|
||||
"@vitejs/plugin-vue": "^1.1.5",
|
||||
"@vue/compiler-sfc": "^3.2.26",
|
||||
"archiver": "^5.3.1",
|
||||
"autoprefixer": "^10.4.2",
|
||||
"cross-env": "^7.0.3",
|
||||
"electron": "13.6.6",
|
||||
"electron-builder": "^22.10.5",
|
||||
"electron-rebuild": "2.3.5",
|
||||
"postcss": "^8.4.5",
|
||||
"rimraf": "^3.0.2",
|
||||
"tailwindcss": "^3.0.13",
|
||||
"ts-node": "^9.1.1",
|
||||
"typescript": "^4.2.3",
|
||||
"vite": "^2.0.5"
|
||||
},
|
||||
"build": {
|
||||
"productName": "esp32程序批量烧录",
|
||||
"appId": "your.id",
|
||||
"mac": {
|
||||
"category": "your.app.category.type"
|
||||
},
|
||||
"files": [
|
||||
"dist/main/**/*",
|
||||
"dist/render/**/*"
|
||||
],
|
||||
"win": {
|
||||
"icon": "./public/favicon.ico"
|
||||
},
|
||||
"directories": {
|
||||
"output": "dist/release"
|
||||
},
|
||||
"afterAllArtifactBuild": "afterAllArtifactBuildHook.js"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
module.exports = {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 72 KiB |
|
@ -0,0 +1,58 @@
|
|||
import { app, Menu, BrowserWindow } from 'electron'
|
||||
import { join } from "path"
|
||||
import './fileManager'
|
||||
import './burnManager'
|
||||
import serialPortManager from './serialPortManager'
|
||||
|
||||
Menu.setApplicationMenu(null)
|
||||
|
||||
function createWindow() {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
minWidth: 560,
|
||||
minHeight: 400,
|
||||
title:'esp32程序烧录',
|
||||
icon: join(__dirname, '../../public/favicon.ico'),
|
||||
webPreferences: {
|
||||
nodeIntegration: true,
|
||||
preload: join(__dirname, 'preload.js')
|
||||
}
|
||||
})
|
||||
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
win.loadURL('http://localhost:3000/')
|
||||
win.webContents.openDevTools()
|
||||
} else {
|
||||
win.loadFile('dist/render/index.html')
|
||||
}
|
||||
|
||||
win.webContents.on('did-finish-load', () => {
|
||||
serialPortManager.sendPortList(win.webContents)
|
||||
});
|
||||
|
||||
win.hookWindowMessage(537, (wParam, lParam) => {
|
||||
// WM_DEVICECHANGE = 537; 通知应用程序对设备或计算机的硬件配置的更改
|
||||
// console.log('WM_DEVICECHANGE');
|
||||
if ((wParam[0] == 0 && wParam[1] == 0x80) || (wParam[0] == 0x04 && wParam[1] == 0x80)) {
|
||||
// DBT_DEVICEREMOVECOMPLETE 0x8004 已删除设备或介质
|
||||
// DBT_DEVICEARRIVAL 0x8000 已插入设备或介质,现已推出
|
||||
// console.log(wParam)
|
||||
serialPortManager.sendPortList(win.webContents)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
app.whenReady().then(createWindow)
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
|
@ -0,0 +1,85 @@
|
|||
import { ipcMain } from 'electron'
|
||||
import { execFile } from 'child_process'
|
||||
|
||||
const ESP32_RELATIVE_PATH = process.env.NODE_ENV === 'development' ? './public/esp32/' : './esp32/'
|
||||
|
||||
ipcMain.on('BURN', (event, {selectedPort, selectedFilePath, errsum, sucsum}) => {
|
||||
// event.reply('CLEAN_MSG')
|
||||
execFile(ESP32_RELATIVE_PATH + 'esptool.exe',
|
||||
['--chip', 'esp32', '--port', selectedPort, '--baud', '921600', '--before', 'default_reset', '--after', 'hard_reset', 'write_flash', '-z', '--flash_mode', 'dio', '--flash_freq', '80m', '--flash_size', 'detect',
|
||||
'0xe000', ESP32_RELATIVE_PATH + 'boot_app0.bin',
|
||||
'0x1000', ESP32_RELATIVE_PATH + 'bootloader.bin',
|
||||
'0x10000', selectedFilePath,
|
||||
'0x8000', ESP32_RELATIVE_PATH + 'partitions.bin'], (error, stdout, stderr) => {
|
||||
if (error) {
|
||||
console.log('-----------------------------')
|
||||
console.error(error);
|
||||
console.log('-----------------------------')
|
||||
let errmsg
|
||||
let errget = /A fatal error occurred/
|
||||
let porterr = /Failed to open port/
|
||||
let pererr = /Permission denied/
|
||||
let wrong = /SerialException: Cannot configure port, something went wrong. Original message: OSError/
|
||||
if(errget.test(stdout)){
|
||||
console.log('错误')
|
||||
let timeout = /Timed out waiting for packet header/
|
||||
let nodata = /No serial data received/
|
||||
let noise = /Possible serial noise or corruption/
|
||||
let flash = /Failed to write compressed data to flash/
|
||||
let md5err = /MD5 of file does not match data in flash/
|
||||
let chiperr = /This chip is ESP32-S2 not ESP32. Wrong --chip argument/
|
||||
if(timeout.test(stdout)){
|
||||
console.log('esp32模组未正常进入下载模式或串口被占用')
|
||||
errmsg = '请检查串口调试助手工具查看是否有进入下载模式的打印或关闭串口后重新烧录'
|
||||
}else if(nodata.test(stdout)){
|
||||
console.log('TX、RX引脚未连接或usb转串口工具硬件存在问题')
|
||||
errmsg = '请检查串口引脚连接是否正常或更换usb转串口工具后重新烧录'
|
||||
}else if(noise.test(stdout)){
|
||||
console.log('usb电缆错误或开发板spi flash 引脚短路或电压不稳定')
|
||||
errmsg = '请尝试更换usb电缆、更换模组、更换开发板或更换稳压电源后重新烧录'
|
||||
}else if(flash.test(stdout)){
|
||||
console.log('flah参数问题')
|
||||
errmsg = '请确保电源稳定、以及串口连接无异常,重试下载烧录程序后重新烧录'
|
||||
}else if(md5err.test(stdout)){
|
||||
console.log('flash损坏或引脚焊接问题')
|
||||
errmsg = 'MD5文件与flash中的数据不匹配,请重试烧录'
|
||||
}else if(chiperr.test(stdout)){
|
||||
console.log('串口连接的设备不是烧录设备')
|
||||
errmsg = '请确认串口连接的是烧录设备后重新烧录'
|
||||
}
|
||||
}else if(porterr.test(stdout)){
|
||||
console.log('没有串口权限')
|
||||
errmsg = '请提升用户权限后重新烧录'
|
||||
}else if(pererr.test(stdout)){
|
||||
console.log('串口被占用')
|
||||
errmsg = '请检查串口调试助手工具关闭串口后重新烧录'
|
||||
}else if(wrong.test(error)){
|
||||
console.log('无法配置串口')
|
||||
errmsg = '请确保烧录设备已正确连接到计算机并检查串口配置后重新烧录'
|
||||
}else{
|
||||
console.log('未知错误')
|
||||
errmsg = '未知错误,请重新烧录'
|
||||
}
|
||||
// event.reply('ALERT_MSG', errmsg)
|
||||
event.reply('ERR_SUM', errsum+1)
|
||||
// event.reply('APPEND_MSG', error.stack)
|
||||
console.log('-----------------------------')
|
||||
console.log(stdout);
|
||||
console.log('-----------------------------')
|
||||
// event.reply('APPEND_MSG', stdout)
|
||||
event.reply('APPEND_MSG', selectedPort + '烧录失败' + '\n' + error.stack + stdout)
|
||||
event.reply('FAILED_RESULT', selectedPort)
|
||||
event.reply('BURN_END')
|
||||
}else{
|
||||
console.log('-----------------------------')
|
||||
console.log(stdout);
|
||||
console.log('-----------------------------')
|
||||
// event.reply('ALERT_MSG', '烧录成功!')
|
||||
event.reply('SUC_SUM', sucsum+1)
|
||||
// event.reply('APPEND_MSG', stdout)
|
||||
event.reply('APPEND_MSG', selectedPort + '烧录成功')
|
||||
event.reply('SUC_RESULT', selectedPort)
|
||||
event.reply('BURN_END')
|
||||
}
|
||||
});
|
||||
})
|
|
@ -0,0 +1,6 @@
|
|||
export const filters = [
|
||||
{ usbProductId: 8963 , usbVendorId: 1659 }, // 核心处理模块(micro-usb),蓝色无线通信模块
|
||||
{ usbProductId: 29986, usbVendorId: 6790 }, // 核心处理模块(type-c),红色无线通信模块
|
||||
{ usbProductId: 29987, usbVendorId: 6790 }, // 核心处理模块(type-c)
|
||||
]
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
import { dialog, ipcMain } from 'electron'
|
||||
|
||||
ipcMain.on('SELECT_FILE', (event) => {
|
||||
const filePaths = dialog.showOpenDialogSync({
|
||||
filters: [{name: 'esp32 bin file', extensions: ['bin']}],
|
||||
properties: ['openFile']
|
||||
})
|
||||
|
||||
if (filePaths === undefined) {
|
||||
return
|
||||
}
|
||||
|
||||
event.reply('SELECT_FILE', filePaths[0])
|
||||
})
|
|
@ -0,0 +1,20 @@
|
|||
const {ipcRenderer, contextBridge} = require('electron')
|
||||
|
||||
contextBridge.exposeInMainWorld('ipcRenderer', {
|
||||
send: (channel, data) => {
|
||||
// whitelist channels
|
||||
let validChannels = ['toMain']
|
||||
if (validChannels.includes(channel)) {
|
||||
ipcRenderer.send(channel, data)
|
||||
}
|
||||
ipcRenderer.send(channel, data)
|
||||
},
|
||||
receive: (channel, func) => {
|
||||
let validChannels = ['fromMain']
|
||||
if (validChannels.includes(channel)) {
|
||||
// Deliberately strip event as it includes `sender`
|
||||
ipcRenderer.on(channel, (event, ...args) => func(...args))
|
||||
}
|
||||
ipcRenderer.on(channel, (event, ...args) => func(...args))
|
||||
}
|
||||
})
|
|
@ -0,0 +1,25 @@
|
|||
import SerialPort from 'serialport'
|
||||
import { filters } from './data'
|
||||
|
||||
const serialPortManager = {
|
||||
sendPortList: async (sender) => {
|
||||
if (!sender) return
|
||||
const ports = await serialPortManager.list_ports()
|
||||
let targetArr = []
|
||||
ports.forEach(element => {
|
||||
filters.forEach(item => {
|
||||
//十六进制转十进制
|
||||
if(parseInt(element.vendorId,16)==item.usbVendorId&&parseInt(element.productId,16)==item.usbProductId){
|
||||
targetArr.push(element)
|
||||
}
|
||||
})
|
||||
})
|
||||
sender.send('LIST_PORTS', targetArr)
|
||||
},
|
||||
list_ports: async () => {
|
||||
const ports = await SerialPort.list()
|
||||
return ports
|
||||
}
|
||||
}
|
||||
|
||||
export default serialPortManager
|
|
@ -0,0 +1,12 @@
|
|||
<template>
|
||||
<div class="container mx-auto">
|
||||
<ProgramBurnForm />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { provide } from 'vue'
|
||||
import ProgramBurnForm from './components/ProgramBurnForm.vue'
|
||||
|
||||
provide('IPCRENDERER_API_SUPPORTED', 'ipcRenderer' in window)
|
||||
</script>
|
Binary file not shown.
After Width: | Height: | Size: 6.7 KiB |
|
@ -0,0 +1,444 @@
|
|||
<template>
|
||||
<h1 class="text-center text-3xl title">ESP32程序批量烧录</h1>
|
||||
<div class="home">
|
||||
<div class="operatebox">
|
||||
<div class="flexbox">
|
||||
<div class="p-4 nop">
|
||||
<div class="textport">待烧录串口</div>
|
||||
<textarea disabled class="commsg resize-none border-2" :value="ports">
|
||||
</textarea>
|
||||
</div>
|
||||
<div class="p-4 nop">
|
||||
<div class="textport">文 件 路 径</div>
|
||||
<button
|
||||
class="seleanni px-4 border-2 rounded text-white"
|
||||
:class="loading ? 'bg-gray-500' : 'bg-blue-500'"
|
||||
:disabled="loading"
|
||||
@click="selectFile"
|
||||
>
|
||||
选 择
|
||||
</button>
|
||||
</div>
|
||||
<div class="p-4 truncate nop">
|
||||
<input
|
||||
disabled
|
||||
type="text"
|
||||
class="filebox border-2"
|
||||
:value="selectedFilePath"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-span-2 nopd">
|
||||
<button
|
||||
class="anni px-4 border-2 rounded text-white"
|
||||
:class="loading ? 'bg-gray-500' : 'bg-blue-500'"
|
||||
:disabled="loading"
|
||||
@click="burn_start"
|
||||
>
|
||||
<svg
|
||||
v-if="loadings"
|
||||
class="svgbox animate-spin h-5 w-5"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<circle
|
||||
class="opacity-25"
|
||||
cx="12"
|
||||
cy="12"
|
||||
r="10"
|
||||
stroke="currentColor"
|
||||
stroke-width="4"
|
||||
></circle>
|
||||
<path
|
||||
class="opacity-75"
|
||||
fill="currentColor"
|
||||
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
||||
></path>
|
||||
</svg>
|
||||
<div class="fontset" v-else>烧 录</div>
|
||||
</button>
|
||||
</div>
|
||||
<div class="tips">
|
||||
<h6 class="tipstitle">操 作 方 法</h6>
|
||||
<textarea disabled class="tipsmsg resize-none border-2">
|
||||
1. 待烧录或烧录失败的串口会自动显示。
|
||||
2. 点击按钮选择需要烧录的程序。
|
||||
3. 点击烧录按钮,等待烧录完成。
|
||||
|
||||
**右侧为烧录输出**
|
||||
#若烧录失败可以通过烧录输出判断错误原因#
|
||||
</textarea
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="msgbox">
|
||||
<textarea
|
||||
ref="container"
|
||||
disabled
|
||||
class="textbox resize-none border-2 w-full"
|
||||
:value="msg"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, inject, watch, onMounted } from "vue";
|
||||
|
||||
function alert(data) {
|
||||
loading.value = true;
|
||||
var a = document.createElement("div"),
|
||||
p = document.createElement("p"),
|
||||
btn = document.createElement("div"),
|
||||
textNode = document.createTextNode(data ? data : ""),
|
||||
btnText = document.createTextNode("确定");
|
||||
// 控制样式
|
||||
css(a, {
|
||||
"padding-top": "60px",
|
||||
position: "fixed",
|
||||
left: "0",
|
||||
right: "0",
|
||||
top: "40%",
|
||||
width: "300px",
|
||||
height: "180px",
|
||||
margin: "0 auto",
|
||||
"background-color": "#fff",
|
||||
border: "2px solid #ccc",
|
||||
"font-size": "100%",
|
||||
"text-align": "center",
|
||||
"z-index": "3",
|
||||
});
|
||||
css(btn, {
|
||||
margin: "10%",
|
||||
"margin-bottom": "5%",
|
||||
width: "80%",
|
||||
position: "absolute",
|
||||
bottom: "0",
|
||||
background: "#2222ff",
|
||||
opacity: "0.8",
|
||||
"border-radius": "24px",
|
||||
color: "#fff",
|
||||
});
|
||||
// 内部结构套入
|
||||
p.appendChild(textNode);
|
||||
btn.appendChild(btnText);
|
||||
a.appendChild(p);
|
||||
a.appendChild(btn);
|
||||
// 整体显示到页面内
|
||||
document.getElementsByTagName("body")[0].appendChild(a);
|
||||
|
||||
// 确定绑定点击事件删除标签
|
||||
btn.onclick = function () {
|
||||
a.parentNode?.removeChild(a);
|
||||
loading.value = false;
|
||||
};
|
||||
}
|
||||
function css(targetObj, cssObj) {
|
||||
var str = targetObj.getAttribute("style") ? targetObj.getAttribute("style") : "";
|
||||
for (var i in cssObj) {
|
||||
str += i + ":" + cssObj[i] + ";";
|
||||
}
|
||||
targetObj.style.cssText = str;
|
||||
}
|
||||
window.alert = alert;
|
||||
|
||||
const IPCRENDERER_API_SUPPORTED = inject("IPCRENDERER_API_SUPPORTED", false);
|
||||
|
||||
const loading = ref(false);
|
||||
const loadings = ref(false);
|
||||
const msg = ref("烧录结果输出:\n");
|
||||
const container = ref(null);
|
||||
const selectedPort = ref("");
|
||||
const ports = ref([]);
|
||||
const errsum = ref(0);
|
||||
const sucsum = ref(0);
|
||||
const succom = ref([]);
|
||||
const failedcom = ref([]);
|
||||
const comlength = ref(0);
|
||||
|
||||
const setPorts = (value: Object[]) => {
|
||||
let compath = [];
|
||||
value.forEach((element) => {
|
||||
compath.push(element.path);
|
||||
});
|
||||
|
||||
if (loading.value == false) {
|
||||
ports.value = compath;
|
||||
}
|
||||
comlength.value = ports.value.length;
|
||||
};
|
||||
|
||||
const selectedFilePath = ref("");
|
||||
|
||||
const setSelectedFilePath = (value: string) => (selectedFilePath.value = value);
|
||||
|
||||
const selectFile = () => {
|
||||
if (!IPCRENDERER_API_SUPPORTED) {
|
||||
alert("The ipcRenderer API is not supported.");
|
||||
return;
|
||||
}
|
||||
|
||||
ipcRenderer.send("SELECT_FILE");
|
||||
};
|
||||
|
||||
const alert_msg = (value: string) => {
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
|
||||
alert(value);
|
||||
};
|
||||
|
||||
const errlog = (value: number) => {
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
|
||||
errsum.value = value;
|
||||
};
|
||||
|
||||
const suclog = (value: number) => {
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
|
||||
sucsum.value = value;
|
||||
};
|
||||
|
||||
const append_msg = (value: string) => {
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
|
||||
msg.value += value + "\n";
|
||||
};
|
||||
|
||||
const suc_result = (value: Array<string>) => {
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
|
||||
succom.value.push(value);
|
||||
};
|
||||
|
||||
const failed_result = (value: Array<string>) => {
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
|
||||
failedcom.value.push(value);
|
||||
};
|
||||
|
||||
const scroll = () => {
|
||||
setTimeout(() => (container.value.scrollTop = container.value.scrollHeight), 5);
|
||||
};
|
||||
|
||||
const burn = () => {
|
||||
selectedPort.value = ports.value.shift();
|
||||
const param = {
|
||||
selectedPort: selectedPort.value,
|
||||
selectedFilePath: selectedFilePath.value,
|
||||
errsum: errsum.value,
|
||||
sucsum: sucsum.value,
|
||||
};
|
||||
ipcRenderer.send("BURN", param);
|
||||
loading.value = true;
|
||||
loadings.value = true;
|
||||
};
|
||||
|
||||
const burn_start = () => {
|
||||
if (ports.value.length == 0) {
|
||||
alert("未发现串口");
|
||||
return;
|
||||
}
|
||||
if (!selectedFilePath.value) {
|
||||
alert("请选择程序文件");
|
||||
return;
|
||||
}
|
||||
succom.value = [];
|
||||
failedcom.value = [];
|
||||
errsum.value = 0;
|
||||
sucsum.value = 0;
|
||||
msg.value = "烧录结果输出:\n";
|
||||
burn();
|
||||
};
|
||||
|
||||
watch(msg, () => {
|
||||
scroll();
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
if (!IPCRENDERER_API_SUPPORTED) {
|
||||
alert("The ipcRenderer API is not supported.");
|
||||
return;
|
||||
}
|
||||
|
||||
ipcRenderer.receive("SELECT_FILE", setSelectedFilePath);
|
||||
ipcRenderer.receive("LIST_PORTS", setPorts);
|
||||
ipcRenderer.receive("BURN_END", () => {
|
||||
if (ports.value.length == 0) {
|
||||
loadings.value = false;
|
||||
loading.value = false;
|
||||
if (errsum.value == 0) {
|
||||
alert("串口已全部烧录成功!");
|
||||
return;
|
||||
} else if (sucsum.value == 0) {
|
||||
alert("串口已全部烧录失败!");
|
||||
ports.value = failedcom.value;
|
||||
return;
|
||||
} else {
|
||||
alert(`烧录结束,成功:${sucsum.value}个,失败:${errsum.value}个`);
|
||||
ports.value = failedcom.value;
|
||||
return;
|
||||
}
|
||||
}
|
||||
burn();
|
||||
});
|
||||
ipcRenderer.receive("ALERT_MSG", alert_msg);
|
||||
ipcRenderer.receive("ERR_SUM", errlog);
|
||||
ipcRenderer.receive("SUC_SUM", suclog);
|
||||
ipcRenderer.receive("APPEND_MSG", append_msg);
|
||||
ipcRenderer.receive("FAILED_RESULT", failed_result);
|
||||
ipcRenderer.receive("SUC_RESULT", suc_result);
|
||||
// ipcRenderer.receive('CLEAN_MSG' , () => msg.value = '')
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.title {
|
||||
min-width: 220px;
|
||||
height: 14vh;
|
||||
line-height: 14vh;
|
||||
}
|
||||
.textport {
|
||||
width: 45%;
|
||||
font-size: clamp(0.8rem, 0.5rem + 1vw, 2rem);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.anni {
|
||||
width: 40%;
|
||||
min-width: 60px;
|
||||
height: 80%;
|
||||
margin-top: 1%;
|
||||
border-radius: 48px;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
.fontset {
|
||||
margin: auto;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
font-size: clamp(0.8rem, 0.5rem + 1vw, 2rem);
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
}
|
||||
.seleanni {
|
||||
width: 45%;
|
||||
border-radius: 24px;
|
||||
height: 100%;
|
||||
font-size: clamp(0.8rem, 0.5rem + 1vw, 2rem);
|
||||
}
|
||||
.selebox {
|
||||
width: 45%;
|
||||
border-radius: 24px;
|
||||
height: 100%;
|
||||
box-shadow: inset 4px 4px 4px rgba(0, 0, 0, 0.3),
|
||||
inset -4px -4px 4px rgba(255, 255, 255, 0.7);
|
||||
}
|
||||
.filebox {
|
||||
min-width: 90px;
|
||||
width: 90%;
|
||||
background-color: #fff;
|
||||
height: 100%;
|
||||
border-radius: 24px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
box-shadow: inset 4px 4px 4px rgba(0, 0, 0, 0.3),
|
||||
inset -4px -4px 4px rgba(255, 255, 255, 0.7);
|
||||
}
|
||||
.flexbox {
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
height: 40%;
|
||||
background-color: #eeffff;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-content: space-evenly;
|
||||
flex-wrap: wrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
.svgbox {
|
||||
margin: auto;
|
||||
}
|
||||
.nop {
|
||||
padding: 0;
|
||||
padding-left: 10%;
|
||||
flex: 1;
|
||||
min-width: 100%;
|
||||
max-width: 200%;
|
||||
height: 16%;
|
||||
min-height: 28px;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
justify-content: start;
|
||||
}
|
||||
.nopd {
|
||||
padding: 0;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 10%;
|
||||
justify-content: center;
|
||||
align-content: center;
|
||||
}
|
||||
.msgbox {
|
||||
padding: 0;
|
||||
width: 48%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
.textbox {
|
||||
height: 100%;
|
||||
background-color: #ffe;
|
||||
}
|
||||
.home {
|
||||
height: 80vh;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin: auto;
|
||||
}
|
||||
.operatebox {
|
||||
margin: 0;
|
||||
width: 48%;
|
||||
margin-right: 1%;
|
||||
height: 100%;
|
||||
background-color: #ccffff;
|
||||
}
|
||||
.tips {
|
||||
width: 100%;
|
||||
height: 50%;
|
||||
background-color: #99ffff;
|
||||
padding-left: 9%;
|
||||
}
|
||||
.tipstitle {
|
||||
width: 90%;
|
||||
min-width: 120px;
|
||||
min-height: 10%;
|
||||
text-align: center;
|
||||
padding-top: 1.5%;
|
||||
font-size: clamp(0.6rem, 0.5rem + 1vw, 1.2rem);
|
||||
}
|
||||
.tipsmsg {
|
||||
width: 90%;
|
||||
height: 80%;
|
||||
background-color: #efe;
|
||||
}
|
||||
.commsg {
|
||||
width: 45%;
|
||||
height: 100%;
|
||||
background-color: #efe;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,3 @@
|
|||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
|
@ -0,0 +1,5 @@
|
|||
import { createApp } from 'vue'
|
||||
import App from './App.vue'
|
||||
import './index.css'
|
||||
|
||||
createApp(App).mount('#app')
|
|
@ -0,0 +1,5 @@
|
|||
declare module '*.vue' {
|
||||
import { DefineComponent } from 'vue'
|
||||
const component: DefineComponent<{}, {}, any>
|
||||
export default component
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
module.exports = {
|
||||
content: [
|
||||
"./index.html",
|
||||
"./src/**/*.{vue,js,ts,jsx,tsx}",
|
||||
],
|
||||
theme: {
|
||||
extend: {},
|
||||
},
|
||||
plugins: [],
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "esnext",
|
||||
"module": "CommonJS",
|
||||
"moduleResolution": "node",
|
||||
"strict": true,
|
||||
"resolveJsonModule": true,
|
||||
"esModuleInterop": true,
|
||||
"allowJs": true,
|
||||
"outDir": "dist/main"
|
||||
},
|
||||
"include": [
|
||||
"src/main/app.ts",
|
||||
"src/main/preload.js",
|
||||
]
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "esnext",
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"strict": true,
|
||||
"jsx": "preserve",
|
||||
"sourceMap": true,
|
||||
"resolveJsonModule": true,
|
||||
"esModuleInterop": true,
|
||||
"lib": ["esnext", "dom"],
|
||||
"types": ["vite/client"]
|
||||
},
|
||||
"include": ["src/render/**/*.ts", "src/render/**/*.d.ts", "src/render/**/*.tsx", "src/render/**/*.vue"],
|
||||
"exclude": ["src/app.ts"]
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
import { join } from 'path'
|
||||
import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
|
||||
const outDir = join(__dirname, 'dist/render')
|
||||
const renderDir = join(__dirname, 'src/render')
|
||||
const publicDir = join(__dirname, 'public')
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
publicDir,
|
||||
base: './',
|
||||
plugins: [vue()],
|
||||
build: {
|
||||
outDir,
|
||||
emptyOutDir: true,
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': renderDir,
|
||||
}
|
||||
},
|
||||
})
|
Loading…
Reference in New Issue