Browse Source

Electron外壳执行正常

master
hejl 4 weeks ago
parent
commit
d382dd917c
  1. 1
      .gitignore
  2. 4
      gofaster/.vscode/settings.json
  3. 11728
      gofaster/app/package-lock.json
  4. 30
      gofaster/app/package.json
  5. 11
      gofaster/app/public/index.html
  6. 43
      gofaster/app/src/main/index.js
  7. 7
      gofaster/app/src/preload.js
  8. 23
      gofaster/app/src/renderer/App.vue
  9. 107
      gofaster/app/src/renderer/components/SpeedTest.vue
  10. 13
      gofaster/app/src/renderer/main.js
  11. 23
      gofaster/app/src/renderer/router/index.js
  12. 20
      gofaster/app/src/renderer/services/db.js
  13. 28
      gofaster/app/src/renderer/store/index.js
  14. 99
      gofaster/app/src/renderer/views/History.vue
  15. 21
      gofaster/app/src/renderer/views/Home.vue
  16. 55
      gofaster/app/vue.config.js

1
.gitignore vendored

@ -9,3 +9,4 @@
/cpp_server/swagger /cpp_server/swagger
/uft_dev_server/build /uft_dev_server/build
/uft_dev_server/third_party /uft_dev_server/third_party
/gofaster/app/node_modules

4
gofaster/.vscode/settings.json vendored

@ -1 +1,3 @@
{} {
"git.ignoreLimitWarning": true
}

11728
gofaster/app/package-lock.json generated

File diff suppressed because it is too large Load Diff

30
gofaster/app/package.json

@ -0,0 +1,30 @@
{
"name": "GoFaster",
"version": "1.0.0",
"main": "src/main/index.js",
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build && electron-builder",
"start": "electron .",
"dev": "concurrently \"npm run serve\" \"wait-on http://localhost:8080 && npm run start\"",
"postinstall": "electron-builder install-app-deps"
},
"keywords": [],
"author": "",
"license": "ISC",
"description": "",
"devDependencies": {
"@electron/remote": "^2.1.3",
"@vue/cli-service": "^5.0.8",
"concurrently": "^9.2.0",
"electron": "^37.2.6",
"electron-builder": "^26.0.12",
"vue": "^3.5.18",
"wait-on": "^8.0.4"
},
"dependencies": {
"lowdb": "^7.0.1",
"vue-router": "^4.5.1",
"vuex": "^4.0.2"
}
}

11
gofaster/app/public/index.html

@ -0,0 +1,11 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GoFaster</title>
</head>
<body>
<div id="app"></div>
</body>
</html>

43
gofaster/app/src/main/index.js

@ -0,0 +1,43 @@
const { app, BrowserWindow } = require('electron')
const path = require('path')
let mainWindow
function createWindow() {
mainWindow = new BrowserWindow({
width: 1200,
height: 800,
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
enableRemoteModule: false,
preload: path.join(__dirname, '../preload.js')
}
})
// 开发模式下加载开发服务器
if (process.env.NODE_ENV === 'development') {
mainWindow.loadURL('http://localhost:8080')
mainWindow.webContents.openDevTools()
} else {
mainWindow.loadFile(path.join(__dirname, '../public/index.html'))
}
mainWindow.on('closed', () => {
mainWindow = null
})
}
app.whenReady().then(createWindow)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (mainWindow === null) {
createWindow()
}
})

7
gofaster/app/src/preload.js

@ -0,0 +1,7 @@
const { contextBridge } = require('electron')
// 安全地暴露API给渲染进程
contextBridge.exposeInMainWorld('electron', {
platform: process.platform
// 可以添加更多安全的API
})

23
gofaster/app/src/renderer/App.vue

@ -0,0 +1,23 @@
<template>
<div id="app">
<router-view />
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
<style>
/* 全局样式 */
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #2c3e50;
margin: 0;
padding: 0;
}
</style>

107
gofaster/app/src/renderer/components/SpeedTest.vue

@ -0,0 +1,107 @@
<template>
<div class="speed-test">
<h1>GoFaster Speed Test</h1>
<button @click="startTest" :disabled="testing">
{{ testing ? 'Testing...' : 'Start Test' }}
</button>
<div v-if="result" class="results">
<h3>Test Results:</h3>
<div class="result-item">
<span class="label">Download:</span>
<span class="value">{{ result.download }} Mbps</span>
</div>
<div class="result-item">
<span class="label">Upload:</span>
<span class="value">{{ result.upload }} Mbps</span>
</div>
<div class="result-item">
<span class="label">Ping:</span>
<span class="value">{{ result.ping }} ms</span>
</div>
</div>
</div>
</template>
<script>
import { ref } from 'vue'
import { useStore } from 'vuex'
export default {
name: 'SpeedTest',
setup() {
const store = useStore()
const testing = ref(false)
const result = ref(null)
const startTest = async () => {
testing.value = true
result.value = null
// ()
await new Promise(resolve => setTimeout(resolve, 2000))
const testResult = {
download: (Math.random() * 100).toFixed(2),
upload: (Math.random() * 50).toFixed(2),
ping: (Math.random() * 100).toFixed(2),
timestamp: new Date().toISOString()
}
//
await store.dispatch('saveTestResult', testResult)
result.value = testResult
testing.value = false
}
return { testing, result, startTest }
}
}
</script>
<style scoped>
.speed-test {
padding: 20px;
max-width: 600px;
margin: 0 auto;
text-align: center;
}
button {
padding: 10px 20px;
font-size: 16px;
background-color: #42b983;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
margin: 20px 0;
}
button:disabled {
background-color: #cccccc;
cursor: not-allowed;
}
.results {
margin-top: 20px;
padding: 15px;
background-color: #f5f5f5;
border-radius: 4px;
text-align: left;
}
.result-item {
margin: 10px 0;
display: flex;
justify-content: space-between;
}
.label {
font-weight: bold;
}
.value {
color: #42b983;
}
</style>

13
gofaster/app/src/renderer/main.js

@ -0,0 +1,13 @@
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
// 初始化数据库
import { initDB } from './services/db'
initDB().then(() => {
createApp(App)
.use(store)
.use(router)
.mount('#app')
})

23
gofaster/app/src/renderer/router/index.js

@ -0,0 +1,23 @@
import { createRouter, createWebHashHistory } from 'vue-router'
import Home from '@/views/Home.vue'
import History from '@/views/History.vue'
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/history',
name: 'History',
component: History
}
]
const router = createRouter({
history: createWebHashHistory(),
routes
})
export default router

20
gofaster/app/src/renderer/services/db.js

@ -0,0 +1,20 @@
import { Low, JSONFile } from 'lowdb'
import { join } from 'path'
import { app } from '@electron/remote'
const file = join(app.getPath('userData'), 'gofaster-db.json')
const adapter = new JSONFile(file)
const db = new Low(adapter)
// 初始化数据库
async function initDB() {
await db.read()
db.data ||= {
settings: {},
activities: [],
stats: {}
}
await db.write()
}
export { db, initDB }

28
gofaster/app/src/renderer/store/index.js

@ -0,0 +1,28 @@
import { createStore } from 'vuex'
import { db } from '../services/db'
export default createStore({
state: {
testResults: []
},
mutations: {
setTestResults(state, results) {
state.testResults = results
},
addTestResult(state, result) {
state.testResults.unshift(result)
}
},
actions: {
async loadTestResults({ commit }) {
await db.read()
commit('setTestResults', db.data.activities || [])
},
async saveTestResult({ commit }, result) {
await db.read()
db.data.activities.unshift(result)
await db.write()
commit('addTestResult', result)
}
}
})

99
gofaster/app/src/renderer/views/History.vue

@ -0,0 +1,99 @@
<template>
<div class="history-view">
<h1>Test History</h1>
<div v-if="testResults.length === 0" class="empty-state">
No speed tests recorded yet.
</div>
<div v-else class="history-list">
<div v-for="(result, index) in testResults" :key="index" class="history-item">
<div class="history-date">
{{ formatDate(result.timestamp) }}
</div>
<div class="history-stats">
<span class="stat download"> {{ result.download }} Mbps</span>
<span class="stat upload"> {{ result.upload }} Mbps</span>
<span class="stat ping"> {{ result.ping }} ms</span>
</div>
</div>
</div>
</div>
</template>
<script>
import { computed, onMounted } from 'vue'
import { useStore } from 'vuex'
export default {
name: 'HistoryView',
setup() {
const store = useStore()
onMounted(() => {
store.dispatch('loadTestResults')
})
const testResults = computed(() => store.state.testResults)
const formatDate = (timestamp) => {
return new Date(timestamp).toLocaleString()
}
return { testResults, formatDate }
}
}
</script>
<style scoped>
.history-view {
padding: 20px;
max-width: 800px;
margin: 0 auto;
}
.empty-state {
text-align: center;
padding: 40px;
color: #888;
}
.history-list {
margin-top: 20px;
}
.history-item {
padding: 15px;
margin-bottom: 10px;
background-color: #f9f9f9;
border-radius: 4px;
display: flex;
justify-content: space-between;
align-items: center;
}
.history-date {
color: #666;
}
.history-stats {
display: flex;
gap: 15px;
}
.stat {
font-weight: bold;
}
.download {
color: #42b983;
}
.upload {
color: #3498db;
}
.ping {
color: #e74c3c;
}
</style>

21
gofaster/app/src/renderer/views/Home.vue

@ -0,0 +1,21 @@
<!-- src/renderer/views/Home.vue -->
<template>
<div class="home">
<h1>Welcome to Your Electron App</h1>
<!-- 这里可以放你的首页内容 -->
</div>
</template>
<script>
export default {
name: 'HomeView'
}
</script>
<style scoped>
/* 可以添加一些基础样式 */
.home {
padding: 20px;
text-align: center;
}
</style>

55
gofaster/app/vue.config.js

@ -0,0 +1,55 @@
const path = require('path')
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
outputDir: path.resolve(__dirname, 'dist/renderer'),
publicPath: './',
// 关键修改:配置 Electron 构建目标和排除原生模块
configureWebpack: {
target: 'electron-renderer', // 指定为 Electron 渲染进程
externals: {
electron: 'require("electron")', // 防止 Webpack 处理 electron 模块
fs: 'require("fs")', // 排除 Node.js 原生模块
path: 'require("path")',
},
resolve: {
alias: {
'@': path.resolve(__dirname, 'src/renderer'),
// 确保 Vue 单文件组件引用时自动补全扩展名
'views': path.resolve(__dirname, 'src/renderer/views')
},
// 添加扩展名自动解析
extensions: ['.js', '.vue', '.json']
}
},
// 保留原有页面配置
pages: {
index: {
entry: 'src/renderer/main.js',
template: 'public/index.html',
filename: 'index.html'
}
},
// 保留 Electron Builder 配置
pluginOptions: {
electronBuilder: {
preload: 'src/preload.js',
nodeIntegration: false,
contextIsolation: true,
// 可选:明确指定主进程文件路径
mainProcessFile: 'src/main/index.js'
}
},
// 开发服务器配置(与 Electron 主进程配合)
devServer: {
port: 8080, // 确保与 wait-on 端口一致
hot: true,
headers: {
'Access-Control-Allow-Origin': '*'
}
}
})
Loading…
Cancel
Save