chore: starter
1
.gitignore
vendored
@@ -1,5 +1,6 @@
|
||||
node_modules
|
||||
dist
|
||||
dist-web
|
||||
out
|
||||
.DS_Store
|
||||
.eslintcache
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
out
|
||||
dist
|
||||
pnpm-lock.yaml
|
||||
LICENSE.md
|
||||
tsconfig.json
|
||||
tsconfig.*.json
|
||||
@@ -1,4 +0,0 @@
|
||||
singleQuote: true
|
||||
semi: false
|
||||
printWidth: 100
|
||||
trailingComma: none
|
||||
BIN
build/ico.ico
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
build/icon.ico
|
Before Width: | Height: | Size: 121 KiB |
BIN
build/icon.png
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 49 KiB |
@@ -1,6 +1,10 @@
|
||||
import { resolve } from 'path'
|
||||
import { defineConfig } from 'electron-vite'
|
||||
import { resolve } from 'node:path'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import vueJsx from '@vitejs/plugin-vue-jsx'
|
||||
import { defineConfig } from 'electron-vite'
|
||||
import AutoImport from 'unplugin-auto-import/vite'
|
||||
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
|
||||
import Components from 'unplugin-vue-components/vite'
|
||||
|
||||
export default defineConfig({
|
||||
main: {},
|
||||
@@ -8,9 +12,21 @@ export default defineConfig({
|
||||
renderer: {
|
||||
resolve: {
|
||||
alias: {
|
||||
'@renderer': resolve('src/renderer/src')
|
||||
}
|
||||
'@renderer': resolve('src/renderer/src'),
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
vue(),
|
||||
vueJsx(),
|
||||
// 配置自动导入
|
||||
AutoImport({
|
||||
resolvers: [ElementPlusResolver()],
|
||||
dts: true,
|
||||
}),
|
||||
Components({
|
||||
resolvers: [ElementPlusResolver()],
|
||||
dts: true,
|
||||
}),
|
||||
],
|
||||
},
|
||||
plugins: [vue()]
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1,40 +1,4 @@
|
||||
import { defineConfig } from 'eslint/config'
|
||||
import tseslint from '@electron-toolkit/eslint-config-ts'
|
||||
import eslintConfigPrettier from '@electron-toolkit/eslint-config-prettier'
|
||||
import eslintPluginVue from 'eslint-plugin-vue'
|
||||
import vueParser from 'vue-eslint-parser'
|
||||
// eslint.config.mjs
|
||||
import antfu from '@antfu/eslint-config'
|
||||
|
||||
export default defineConfig(
|
||||
{ ignores: ['**/node_modules', '**/dist', '**/out'] },
|
||||
tseslint.configs.recommended,
|
||||
eslintPluginVue.configs['flat/recommended'],
|
||||
{
|
||||
files: ['**/*.vue'],
|
||||
languageOptions: {
|
||||
parser: vueParser,
|
||||
parserOptions: {
|
||||
ecmaFeatures: {
|
||||
jsx: true
|
||||
},
|
||||
extraFileExtensions: ['.vue'],
|
||||
parser: tseslint.parser
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
files: ['**/*.{ts,mts,tsx,vue}'],
|
||||
rules: {
|
||||
'vue/require-default-prop': 'off',
|
||||
'vue/multi-word-component-names': 'off',
|
||||
'vue/block-lang': [
|
||||
'error',
|
||||
{
|
||||
script: {
|
||||
lang: 'ts'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
eslintConfigPrettier
|
||||
)
|
||||
export default antfu()
|
||||
|
||||
36
package.json
@@ -1,46 +1,48 @@
|
||||
{
|
||||
"name": "cslab-dcs-web",
|
||||
"version": "1.0.0",
|
||||
"description": "An Electron application with Vue and TypeScript",
|
||||
"description": "CSLAB DCS 编辑器",
|
||||
"author": "CSLAB FE",
|
||||
"main": "./out/main/index.js",
|
||||
"author": "example.com",
|
||||
"homepage": "https://electron-vite.org",
|
||||
"scripts": {
|
||||
"format": "prettier --write .",
|
||||
"lint": "eslint --cache .",
|
||||
"typecheck:node": "tsc --noEmit -p tsconfig.node.json --composite false",
|
||||
"typecheck:web": "vue-tsc --noEmit -p tsconfig.web.json --composite false",
|
||||
"typecheck": "npm run typecheck:node && npm run typecheck:web",
|
||||
"start": "electron-vite preview",
|
||||
"dev": "electron-vite dev",
|
||||
"dev:web": "vite --config vite.config.web.ts",
|
||||
"build:web": "vite build --config vite.config.web.ts",
|
||||
"start": "electron-vite preview",
|
||||
"build": "npm run typecheck && electron-vite build",
|
||||
"postinstall": "electron-builder install-app-deps",
|
||||
"build:unpack": "npm run build && electron-builder --dir",
|
||||
"build:win": "npm run build && electron-builder --win",
|
||||
"build:mac": "npm run build && electron-builder --mac",
|
||||
"build:linux": "npm run build && electron-builder --linux"
|
||||
"build:linux": "npm run build && electron-builder --linux",
|
||||
"lint": "eslint --cache .",
|
||||
"format": "eslint --cache . --fix",
|
||||
"typecheck:node": "tsc --noEmit -p tsconfig.node.json --composite false",
|
||||
"typecheck:web": "vue-tsc --noEmit -p tsconfig.web.json --composite false",
|
||||
"typecheck": "npm run typecheck:node && npm run typecheck:web",
|
||||
"postinstall": "electron-builder install-app-deps"
|
||||
},
|
||||
"dependencies": {
|
||||
"@electron-toolkit/preload": "^3.0.2",
|
||||
"@electron-toolkit/utils": "^4.0.0",
|
||||
"electron-updater": "^6.3.9"
|
||||
"electron-updater": "^6.3.9",
|
||||
"element-plus": "^2.13.1",
|
||||
"vue-router": "^4.6.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@electron-toolkit/eslint-config-prettier": "3.0.0",
|
||||
"@electron-toolkit/eslint-config-ts": "^3.1.0",
|
||||
"@antfu/eslint-config": "^7.2.0",
|
||||
"@electron-toolkit/tsconfig": "^2.0.0",
|
||||
"@types/node": "^22.19.1",
|
||||
"@vitejs/plugin-vue": "^6.0.2",
|
||||
"@vitejs/plugin-vue-jsx": "^5.1.3",
|
||||
"electron": "^39.2.6",
|
||||
"electron-builder": "^26.0.12",
|
||||
"electron-vite": "^5.0.0",
|
||||
"eslint": "^9.39.1",
|
||||
"eslint-plugin-vue": "^10.6.2",
|
||||
"prettier": "^3.7.4",
|
||||
"typescript": "^5.9.3",
|
||||
"unplugin-auto-import": "^21.0.0",
|
||||
"unplugin-vue-components": "^31.0.0",
|
||||
"vite": "^7.2.6",
|
||||
"vue": "^3.5.25",
|
||||
"vue-eslint-parser": "^10.2.0",
|
||||
"vue-tsc": "^3.1.6"
|
||||
},
|
||||
"pnpm": {
|
||||
|
||||
2205
pnpm-lock.yaml
generated
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 3.3 KiB |
@@ -1,6 +1,7 @@
|
||||
import { app, shell, BrowserWindow, ipcMain } from 'electron'
|
||||
import { join } from 'path'
|
||||
import { electronApp, optimizer, is } from '@electron-toolkit/utils'
|
||||
import { join } from 'node:path'
|
||||
import process from 'node:process'
|
||||
import { electronApp, is, optimizer } from '@electron-toolkit/utils'
|
||||
import { app, BrowserWindow, ipcMain, shell } from 'electron'
|
||||
import icon from '../../resources/icon.png?asset'
|
||||
|
||||
function createWindow(): void {
|
||||
@@ -13,8 +14,8 @@ function createWindow(): void {
|
||||
...(process.platform === 'linux' ? { icon } : {}),
|
||||
webPreferences: {
|
||||
preload: join(__dirname, '../preload/index.js'),
|
||||
sandbox: false
|
||||
}
|
||||
sandbox: false,
|
||||
},
|
||||
})
|
||||
|
||||
mainWindow.on('ready-to-show', () => {
|
||||
@@ -28,9 +29,10 @@ function createWindow(): void {
|
||||
|
||||
// HMR for renderer base on electron-vite cli.
|
||||
// Load the remote URL for development or the local html file for production.
|
||||
if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
|
||||
mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL'])
|
||||
} else {
|
||||
if (is.dev && process.env.ELECTRON_RENDERER_URL) {
|
||||
mainWindow.loadURL(process.env.ELECTRON_RENDERER_URL)
|
||||
}
|
||||
else {
|
||||
mainWindow.loadFile(join(__dirname, '../renderer/index.html'))
|
||||
}
|
||||
}
|
||||
@@ -50,14 +52,15 @@ app.whenReady().then(() => {
|
||||
})
|
||||
|
||||
// IPC test
|
||||
ipcMain.on('ping', () => console.log('pong'))
|
||||
ipcMain.on('ping', () => console.warn('pong'))
|
||||
|
||||
createWindow()
|
||||
|
||||
app.on('activate', function () {
|
||||
app.on('activate', () => {
|
||||
// On macOS it's common to re-create a window in the app when the
|
||||
// dock icon is clicked and there are no other windows open.
|
||||
if (BrowserWindow.getAllWindows().length === 0) createWindow()
|
||||
if (BrowserWindow.getAllWindows().length === 0)
|
||||
createWindow()
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
2
src/preload/index.d.ts
vendored
@@ -1,4 +1,4 @@
|
||||
import { ElectronAPI } from '@electron-toolkit/preload'
|
||||
import type { ElectronAPI } from '@electron-toolkit/preload'
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { contextBridge } from 'electron'
|
||||
import process from 'node:process'
|
||||
import { electronAPI } from '@electron-toolkit/preload'
|
||||
import { contextBridge } from 'electron'
|
||||
|
||||
// Custom APIs for renderer
|
||||
const api = {}
|
||||
@@ -11,12 +12,14 @@ if (process.contextIsolated) {
|
||||
try {
|
||||
contextBridge.exposeInMainWorld('electron', electronAPI)
|
||||
contextBridge.exposeInMainWorld('api', api)
|
||||
} catch (error) {
|
||||
}
|
||||
catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
} else {
|
||||
// @ts-ignore (define in dts)
|
||||
}
|
||||
else {
|
||||
// @ts-expect-error (define in dts)
|
||||
window.electron = electronAPI
|
||||
// @ts-ignore (define in dts)
|
||||
// @ts-expect-error (define in dts)
|
||||
window.api = api
|
||||
}
|
||||
|
||||
10
src/renderer/auto-imports.d.ts
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
/* eslint-disable */
|
||||
/* prettier-ignore */
|
||||
// @ts-nocheck
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
// Generated by unplugin-auto-import
|
||||
// biome-ignore lint: disable
|
||||
export {}
|
||||
declare global {
|
||||
|
||||
}
|
||||
26
src/renderer/components.d.ts
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
// biome-ignore lint: disable
|
||||
// oxlint-disable
|
||||
// ------
|
||||
// Generated by unplugin-vue-components
|
||||
// Read more: https://github.com/vuejs/core/pull/3399
|
||||
import { GlobalComponents } from 'vue'
|
||||
|
||||
export {}
|
||||
|
||||
/* prettier-ignore */
|
||||
declare module 'vue' {
|
||||
export interface GlobalComponents {
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
Versions: typeof import('./src/components/Versions.vue')['default']
|
||||
}
|
||||
}
|
||||
|
||||
// For TSX support
|
||||
declare global {
|
||||
const RouterLink: typeof import('vue-router')['RouterLink']
|
||||
const RouterView: typeof import('vue-router')['RouterView']
|
||||
const Versions: typeof import('./src/components/Versions.vue')['default']
|
||||
}
|
||||
@@ -1,26 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import Versions from './components/Versions.vue'
|
||||
|
||||
const ipcHandle = (): void => window.electron.ipcRenderer.send('ping')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<img alt="logo" class="logo" src="./assets/electron.svg" />
|
||||
<div class="creator">Powered by electron-vite</div>
|
||||
<div class="text">
|
||||
Build an Electron app with
|
||||
<span class="vue">Vue</span>
|
||||
and
|
||||
<span class="ts">TypeScript</span>
|
||||
</div>
|
||||
<p class="tip">Please try pressing <code>F12</code> to open the devTool</p>
|
||||
<div class="actions">
|
||||
<div class="action">
|
||||
<a href="https://electron-vite.org/" target="_blank" rel="noreferrer">Documentation</a>
|
||||
</div>
|
||||
<div class="action">
|
||||
<a target="_blank" rel="noreferrer" @click="ipcHandle">Send IPC</a>
|
||||
</div>
|
||||
</div>
|
||||
<Versions />
|
||||
<router-view />
|
||||
</template>
|
||||
|
||||
BIN
src/renderer/src/assets/icon.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
@@ -1,13 +1,24 @@
|
||||
<script setup lang="ts">
|
||||
import { isElectron } from '@renderer/utils/env'
|
||||
import { reactive } from 'vue'
|
||||
|
||||
const versions = reactive({ ...window.electron.process.versions })
|
||||
const versions = reactive(
|
||||
isElectron()
|
||||
? { ...window.electron.process.versions }
|
||||
: { electron: 'N/A', chrome: 'N/A', node: 'N/A' },
|
||||
)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ul class="versions">
|
||||
<li class="electron-version">Electron v{{ versions.electron }}</li>
|
||||
<li class="chrome-version">Chromium v{{ versions.chrome }}</li>
|
||||
<li class="node-version">Node v{{ versions.node }}</li>
|
||||
<li class="electron-version">
|
||||
Electron v{{ versions.electron }}
|
||||
</li>
|
||||
<li class="chrome-version">
|
||||
Chromium v{{ versions.chrome }}
|
||||
</li>
|
||||
<li class="node-version">
|
||||
Node v{{ versions.node }}
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import './assets/main.css'
|
||||
|
||||
import { createApp } from 'vue'
|
||||
import App from './App.vue'
|
||||
import router from './router'
|
||||
|
||||
createApp(App).mount('#app')
|
||||
import 'element-plus/dist/index.css'
|
||||
import './assets/main.css'
|
||||
|
||||
createApp(App).use(router).mount('#app')
|
||||
|
||||
20
src/renderer/src/router/index.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { isElectron } from '@renderer/utils/env'
|
||||
import { createRouter, createWebHashHistory, createWebHistory } from 'vue-router'
|
||||
|
||||
const routes = [
|
||||
{
|
||||
path: '/',
|
||||
name: 'home',
|
||||
component: () => import('@renderer/views/Home.vue'),
|
||||
},
|
||||
]
|
||||
|
||||
// Electron 使用 hash 模式,Web 使用 history 模式
|
||||
const router = createRouter({
|
||||
history: isElectron()
|
||||
? createWebHashHistory()
|
||||
: createWebHistory('/dcs-web/'),
|
||||
routes,
|
||||
})
|
||||
|
||||
export default router
|
||||
17
src/renderer/src/utils/env.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* 检测当前是否在 Electron 环境中运行
|
||||
*/
|
||||
export function isElectron(): boolean {
|
||||
return typeof window !== 'undefined' && !!window.electron?.process?.versions
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 Electron 进程版本信息
|
||||
* 在 Web 环境中返回 undefined
|
||||
*/
|
||||
export function getElectronVersions() {
|
||||
if (isElectron()) {
|
||||
return window.electron.process.versions
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
35
src/renderer/src/views/Home.vue
Normal file
@@ -0,0 +1,35 @@
|
||||
<script setup lang="ts">
|
||||
import Versions from '@renderer/components/Versions.vue'
|
||||
import { isElectron } from '@renderer/utils/env'
|
||||
|
||||
function ipcHandle(): void {
|
||||
if (isElectron()) {
|
||||
window.electron.ipcRenderer.send('ping')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<img alt="logo" class="logo" src="@renderer/assets/icon.png">
|
||||
<div class="creator">
|
||||
Powered by electron-vite
|
||||
</div>
|
||||
<div class="text">
|
||||
Build an Electron app with
|
||||
<span class="vue">Vue</span>
|
||||
and
|
||||
<span class="ts">TypeScript</span>
|
||||
</div>
|
||||
<p class="tip">
|
||||
Please try pressing <code>F12</code> to open the devTool
|
||||
</p>
|
||||
<div class="actions">
|
||||
<div class="action">
|
||||
<a href="https://electron-vite.org/" target="_blank" rel="noreferrer">Documentation</a>
|
||||
</div>
|
||||
<div v-if="isElectron()" class="action">
|
||||
<a target="_blank" rel="noreferrer" @click="ipcHandle">Send IPC</a>
|
||||
</div>
|
||||
</div>
|
||||
<Versions />
|
||||
</template>
|
||||
@@ -1,4 +1,4 @@
|
||||
{
|
||||
"files": [],
|
||||
"references": [{ "path": "./tsconfig.node.json" }, { "path": "./tsconfig.web.json" }]
|
||||
"references": [{ "path": "./tsconfig.node.json" }, { "path": "./tsconfig.web.json" }],
|
||||
"files": []
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"extends": "@electron-toolkit/tsconfig/tsconfig.node.json",
|
||||
"include": ["electron.vite.config.*", "src/main/**/*", "src/preload/**/*"],
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"types": ["electron-vite/node"]
|
||||
}
|
||||
},
|
||||
"include": ["electron.vite.config.*", "src/main/**/*", "src/preload/**/*"]
|
||||
}
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
{
|
||||
"extends": "@electron-toolkit/tsconfig/tsconfig.web.json",
|
||||
"include": [
|
||||
"src/renderer/src/env.d.ts",
|
||||
"src/renderer/src/**/*",
|
||||
"src/renderer/src/**/*.vue",
|
||||
"src/preload/*.d.ts"
|
||||
],
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"baseUrl": ".",
|
||||
@@ -14,5 +8,11 @@
|
||||
"src/renderer/src/*"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"include": [
|
||||
"src/renderer/src/env.d.ts",
|
||||
"src/renderer/src/**/*",
|
||||
"src/renderer/src/**/*.vue",
|
||||
"src/preload/*.d.ts"
|
||||
]
|
||||
}
|
||||
|
||||
33
vite.config.web.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import { resolve } from 'node:path'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import vueJsx from '@vitejs/plugin-vue-jsx'
|
||||
import AutoImport from 'unplugin-auto-import/vite'
|
||||
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
|
||||
import Components from 'unplugin-vue-components/vite'
|
||||
import { defineConfig } from 'vite'
|
||||
|
||||
export default defineConfig({
|
||||
root: 'src/renderer',
|
||||
base: '/dcs-web/',
|
||||
resolve: {
|
||||
alias: {
|
||||
'@renderer': resolve(__dirname, 'src/renderer/src'),
|
||||
},
|
||||
},
|
||||
build: {
|
||||
outDir: resolve(__dirname, 'dist-web'),
|
||||
emptyOutDir: true,
|
||||
},
|
||||
plugins: [
|
||||
vue(),
|
||||
vueJsx(),
|
||||
AutoImport({
|
||||
resolvers: [ElementPlusResolver()],
|
||||
dts: true,
|
||||
}),
|
||||
Components({
|
||||
resolvers: [ElementPlusResolver()],
|
||||
dts: true,
|
||||
}),
|
||||
],
|
||||
})
|
||||