feat: 添加跨平台打包支持(Linux .deb)、Docker 构建脚本及项目官网
- electron/builder.js: 修复 Linux 平台 npm 命令、增加 .deb 安装包支持 - electron/main.js: 按平台动态设置保存对话框默认扩展名 - package.json: 添加 Linux deb 打包目标 - 新增 Dockerfile 用于 Linux 交叉构建 - 新增 build-linux-docker.ps1 / build-linux.sh 构建脚本 - 新增 site/ 项目官网页面 - .gitignore: 全面忽略二进制文件 - 新增 GitHub Actions CI 工作流
This commit is contained in:
58
.github/workflows/build.yml
vendored
Normal file
58
.github/workflows/build.yml
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
name: Build Web2App
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build-windows:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
- run: npm ci
|
||||
- run: npm run build
|
||||
- run: npx electron-builder --config --win
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Web2App-Windows
|
||||
path: release/*.exe
|
||||
|
||||
build-macos:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
- run: npm ci
|
||||
- run: npm run build
|
||||
- run: npx electron-builder --config --mac
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Web2App-macOS
|
||||
path: release/*.dmg
|
||||
|
||||
build-linux:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
- run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y rpm libx11-dev libxkbfile-dev libsecret-1-dev
|
||||
- run: npm ci
|
||||
- run: npm run build
|
||||
- run: npx electron-builder --config --linux
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Web2App-Linux
|
||||
path: |
|
||||
release/*.AppImage
|
||||
release/*.deb
|
||||
81
.gitignore
vendored
81
.gitignore
vendored
@@ -1,6 +1,87 @@
|
||||
node_modules/
|
||||
dist/
|
||||
.web2app/
|
||||
release/
|
||||
|
||||
# Binaries & executables
|
||||
*.exe
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
*.bin
|
||||
*.pak
|
||||
*.dat
|
||||
|
||||
# Disk images & installers
|
||||
*.dmg
|
||||
*.iso
|
||||
*.img
|
||||
*.AppImage
|
||||
*.deb
|
||||
*.rpm
|
||||
|
||||
# Archives
|
||||
*.zip
|
||||
*.7z
|
||||
*.tar
|
||||
*.gz
|
||||
*.rar
|
||||
|
||||
# Images (binary formats)
|
||||
*.ico
|
||||
*.icns
|
||||
*.png
|
||||
*.jpg
|
||||
*.jpeg
|
||||
*.gif
|
||||
*.bmp
|
||||
*.webp
|
||||
|
||||
# Documents
|
||||
*.pdf
|
||||
*.doc
|
||||
*.docx
|
||||
*.xls
|
||||
*.xlsx
|
||||
*.ppt
|
||||
*.pptx
|
||||
|
||||
# Audio & Video
|
||||
*.mp3
|
||||
*.mp4
|
||||
*.avi
|
||||
*.mov
|
||||
*.wav
|
||||
*.flac
|
||||
*.mkv
|
||||
|
||||
# Fonts
|
||||
*.ttf
|
||||
*.otf
|
||||
*.woff
|
||||
*.woff2
|
||||
|
||||
# Database
|
||||
*.db
|
||||
*.sqlite
|
||||
*.sqlite3
|
||||
|
||||
# Object & build artifacts
|
||||
*.o
|
||||
*.obj
|
||||
*.class
|
||||
*.lib
|
||||
*.a
|
||||
*.pdb
|
||||
*.idb
|
||||
|
||||
# Other binary
|
||||
*.snap
|
||||
*.crx
|
||||
|
||||
# Logs
|
||||
*.log
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
23
Dockerfile
Normal file
23
Dockerfile
Normal file
@@ -0,0 +1,23 @@
|
||||
FROM node:20-bullseye
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
RUN apt-get update && apt-get install -y \
|
||||
rpm \
|
||||
libx11-dev \
|
||||
libxkbfile-dev \
|
||||
libsecret-1-dev \
|
||||
fakeroot \
|
||||
dpkg-dev \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY package.json package-lock.json ./
|
||||
RUN npm install
|
||||
|
||||
COPY . .
|
||||
|
||||
RUN npm run build
|
||||
|
||||
RUN npx electron-builder --config --linux
|
||||
|
||||
CMD ["cp", "-r", "release/*", "/output/"]
|
||||
19
build-linux-docker.ps1
Normal file
19
build-linux-docker.ps1
Normal file
@@ -0,0 +1,19 @@
|
||||
Write-Host "===== Web2App Linux Docker Build ====="
|
||||
Write-Host ""
|
||||
Write-Host "This script builds the Linux version using Docker."
|
||||
Write-Host "Prerequisites: Docker Desktop with Linux container support"
|
||||
Write-Host ""
|
||||
|
||||
$imageName = "web2app-linux-builder"
|
||||
|
||||
Write-Host "1. Building Docker image..."
|
||||
docker build -t $imageName .
|
||||
|
||||
Write-Host "2. Running build..."
|
||||
$outputDir = Join-Path (Get-Location) "release-linux"
|
||||
New-Item -ItemType Directory -Force -Path $outputDir
|
||||
docker run --rm -v "${outputDir}:/output" $imageName
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "===== Build Complete ====="
|
||||
Write-Host "Output: $outputDir"
|
||||
17
build-linux.sh
Normal file
17
build-linux.sh
Normal file
@@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
echo "===== Web2App Linux Build Script ====="
|
||||
|
||||
echo "1. Installing dependencies..."
|
||||
npm install
|
||||
|
||||
echo "2. Building frontend..."
|
||||
npm run build
|
||||
|
||||
echo "3. Building Linux package (AppImage + deb)..."
|
||||
npx electron-builder --config --linux
|
||||
|
||||
echo "===== Build Complete ====="
|
||||
echo "Output: release/"
|
||||
ls -lh release/
|
||||
@@ -94,7 +94,8 @@ async function startPack(projectPath, outputPath, onProgress) {
|
||||
onProgress({ stage: 'install', message: '安装依赖 (首次较慢)...', percent: 50 })
|
||||
|
||||
try {
|
||||
execSync('npm.cmd install --production', {
|
||||
const npmCmd = process.platform === 'win32' ? 'npm.cmd' : 'npm'
|
||||
execSync(`${npmCmd} install --production`, {
|
||||
cwd: tempDir,
|
||||
stdio: 'pipe',
|
||||
timeout: 300000
|
||||
@@ -155,7 +156,7 @@ async function startPack(projectPath, outputPath, onProgress) {
|
||||
let installerPath = null
|
||||
if (fs.existsSync(distDir)) {
|
||||
const files = fs.readdirSync(distDir)
|
||||
.filter(f => f.endsWith('.exe') || f.endsWith('.dmg') || f.endsWith('.AppImage'))
|
||||
.filter(f => f.endsWith('.exe') || f.endsWith('.dmg') || f.endsWith('.AppImage') || f.endsWith('.deb'))
|
||||
.sort((a, b) => fs.statSync(path.join(distDir, b)).mtimeMs - fs.statSync(path.join(distDir, a)).mtimeMs)
|
||||
if (files.length > 0) {
|
||||
installerPath = path.join(distDir, files[0])
|
||||
|
||||
@@ -70,9 +70,14 @@ ipcMain.handle('dialog:selectIcon', async () => {
|
||||
})
|
||||
|
||||
ipcMain.handle('dialog:saveFile', async (_event, options) => {
|
||||
const defaultFilters = process.platform === 'win32'
|
||||
? [{ name: '安装包', extensions: ['exe'] }]
|
||||
: process.platform === 'darwin'
|
||||
? [{ name: '安装包', extensions: ['dmg'] }]
|
||||
: [{ name: '安装包', extensions: ['AppImage', 'deb'] }]
|
||||
const result = await dialog.showSaveDialog(mainWindow, {
|
||||
defaultPath: options?.defaultPath,
|
||||
filters: options?.filters || [{ name: '安装包', extensions: ['exe', 'dmg', 'AppImage'] }]
|
||||
filters: options?.filters || defaultFilters
|
||||
})
|
||||
if (!result.canceled && result.filePath) {
|
||||
return result.filePath
|
||||
|
||||
14
package.json
14
package.json
@@ -44,8 +44,18 @@
|
||||
"icon": null
|
||||
},
|
||||
"linux": {
|
||||
"target": ["AppImage"],
|
||||
"icon": null
|
||||
"target": [
|
||||
{
|
||||
"target": "AppImage",
|
||||
"arch": ["x64"]
|
||||
},
|
||||
{
|
||||
"target": "deb",
|
||||
"arch": ["x64"]
|
||||
}
|
||||
],
|
||||
"icon": null,
|
||||
"category": "Utility"
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
417
site/index.html
Normal file
417
site/index.html
Normal file
@@ -0,0 +1,417 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Web2App - 将网站转化为独立的桌面应用</title>
|
||||
<style>
|
||||
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
:root {
|
||||
--primary: #4f46e5;
|
||||
--primary-hover: #4338ca;
|
||||
--primary-light: #eef2ff;
|
||||
--primary-glow: rgba(79,70,229,0.15);
|
||||
--bg: #f8fafc;
|
||||
--surface: #ffffff;
|
||||
--border: #e2e8f0;
|
||||
--text: #1e293b;
|
||||
--text-secondary: #64748b;
|
||||
--text-muted: #94a3b8;
|
||||
--radius: 12px;
|
||||
--shadow: 0 1px 3px rgba(0,0,0,0.08);
|
||||
--shadow-md: 0 4px 20px rgba(0,0,0,0.08);
|
||||
--shadow-lg: 0 10px 40px rgba(0,0,0,0.1);
|
||||
--max-width: 1100px;
|
||||
}
|
||||
html { scroll-behavior: smooth; }
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Noto Sans SC', sans-serif;
|
||||
background: var(--bg);
|
||||
color: var(--text);
|
||||
line-height: 1.6;
|
||||
font-size: 16px;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
a { color: var(--primary); text-decoration: none; }
|
||||
a:hover { text-decoration: underline; }
|
||||
img { max-width: 100%; }
|
||||
|
||||
.container { max-width: var(--max-width); margin: 0 auto; padding: 0 24px; }
|
||||
|
||||
/* Nav */
|
||||
nav {
|
||||
position: fixed; top: 0; left: 0; right: 0; z-index: 100;
|
||||
background: rgba(255,255,255,0.85); backdrop-filter: blur(12px);
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
nav .container {
|
||||
display: flex; align-items: center; justify-content: space-between;
|
||||
height: 64px;
|
||||
}
|
||||
nav .logo { font-size: 20px; font-weight: 700; color: var(--primary); display: flex; align-items: center; gap: 8px; }
|
||||
nav .logo svg { width: 28px; height: 28px; }
|
||||
nav .nav-links { display: flex; gap: 32px; align-items: center; }
|
||||
nav .nav-links a { color: var(--text-secondary); font-weight: 500; font-size: 15px; transition: color 0.2s; }
|
||||
nav .nav-links a:hover { color: var(--primary); text-decoration: none; }
|
||||
.nav-cta {
|
||||
background: var(--primary); color: #fff !important; padding: 8px 20px;
|
||||
border-radius: 8px; font-weight: 600;
|
||||
}
|
||||
.nav-cta:hover { background: var(--primary-hover) !important; }
|
||||
|
||||
/* Hero */
|
||||
.hero {
|
||||
padding: 140px 0 80px; text-align: center;
|
||||
background: linear-gradient(180deg, var(--primary-light) 0%, var(--bg) 100%);
|
||||
}
|
||||
.hero-badge {
|
||||
display: inline-flex; align-items: center; gap: 6px;
|
||||
background: rgba(79,70,229,0.1); color: var(--primary);
|
||||
padding: 6px 16px; border-radius: 20px; font-size: 14px; font-weight: 600;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
.hero h1 {
|
||||
font-size: 56px; font-weight: 800; line-height: 1.15; letter-spacing: -1px;
|
||||
background: linear-gradient(135deg, var(--primary) 0%, #7c3aed 100%);
|
||||
-webkit-background-clip: text; -webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
.hero p {
|
||||
font-size: 20px; color: var(--text-secondary); max-width: 640px;
|
||||
margin: 20px auto 36px;
|
||||
}
|
||||
.hero-buttons { display: flex; gap: 16px; justify-content: center; flex-wrap: wrap; }
|
||||
.btn {
|
||||
display: inline-flex; align-items: center; gap: 8px;
|
||||
padding: 14px 32px; border-radius: 10px; font-size: 16px;
|
||||
font-weight: 600; border: none; cursor: pointer;
|
||||
transition: all 0.2s ease; text-decoration: none;
|
||||
}
|
||||
.btn-primary {
|
||||
background: var(--primary); color: #fff; box-shadow: 0 4px 14px var(--primary-glow);
|
||||
}
|
||||
.btn-primary:hover { background: var(--primary-hover); transform: translateY(-1px); text-decoration: none; }
|
||||
.btn-secondary {
|
||||
background: var(--surface); color: var(--text); border: 1px solid var(--border);
|
||||
}
|
||||
.btn-secondary:hover { border-color: var(--primary); color: var(--primary); text-decoration: none; }
|
||||
|
||||
/* Sections */
|
||||
section { padding: 80px 0; }
|
||||
.section-label {
|
||||
display: inline-block; font-size: 13px; font-weight: 700; text-transform: uppercase;
|
||||
letter-spacing: 1px; color: var(--primary); margin-bottom: 8px;
|
||||
}
|
||||
.section-title {
|
||||
font-size: 36px; font-weight: 700; margin-bottom: 16px;
|
||||
}
|
||||
.section-sub {
|
||||
font-size: 18px; color: var(--text-secondary); max-width: 600px;
|
||||
}
|
||||
|
||||
/* Features */
|
||||
#features { text-align: center; }
|
||||
#features .section-sub { margin: 0 auto 48px; }
|
||||
.features-grid {
|
||||
display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||
gap: 24px; text-align: left;
|
||||
}
|
||||
.feature-card {
|
||||
background: var(--surface); border: 1px solid var(--border);
|
||||
border-radius: var(--radius); padding: 32px;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
.feature-card:hover {
|
||||
border-color: var(--primary); box-shadow: var(--shadow-md); transform: translateY(-2px);
|
||||
}
|
||||
.feature-icon {
|
||||
width: 48px; height: 48px; border-radius: 12px;
|
||||
background: var(--primary-light); color: var(--primary);
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
font-size: 24px; margin-bottom: 16px;
|
||||
}
|
||||
.feature-card h3 { font-size: 18px; font-weight: 600; margin-bottom: 8px; }
|
||||
.feature-card p { font-size: 14px; color: var(--text-secondary); line-height: 1.7; }
|
||||
|
||||
/* Workflow */
|
||||
#workflow { background: var(--surface); border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); }
|
||||
#workflow .container { text-align: center; }
|
||||
#workflow .section-sub { margin: 0 auto 48px; }
|
||||
.steps { display: flex; gap: 0; justify-content: center; align-items: flex-start; flex-wrap: wrap; }
|
||||
.step {
|
||||
flex: 1; min-width: 180px; max-width: 220px; padding: 0 16px;
|
||||
position: relative;
|
||||
}
|
||||
.step-num {
|
||||
width: 48px; height: 48px; border-radius: 50%;
|
||||
background: var(--primary); color: #fff;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
font-size: 20px; font-weight: 700; margin: 0 auto 16px;
|
||||
}
|
||||
.step h4 { font-size: 16px; font-weight: 600; margin-bottom: 6px; }
|
||||
.step p { font-size: 14px; color: var(--text-secondary); }
|
||||
.step-arrow {
|
||||
font-size: 24px; color: var(--text-muted);
|
||||
position: absolute; right: -12px; top: 12px;
|
||||
}
|
||||
.steps .step:last-child .step-arrow { display: none; }
|
||||
|
||||
/* Install */
|
||||
#download { text-align: center; }
|
||||
#download .section-sub { margin: 0 auto 48px; }
|
||||
.platforms { display: flex; gap: 20px; justify-content: center; flex-wrap: wrap; }
|
||||
.platform-card {
|
||||
background: var(--surface); border: 1px solid var(--border);
|
||||
border-radius: var(--radius); padding: 36px 40px; min-width: 200px;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
.platform-card:hover { border-color: var(--primary); box-shadow: var(--shadow-md); transform: translateY(-2px); }
|
||||
.platform-icon { font-size: 40px; margin-bottom: 12px; }
|
||||
.platform-card h4 { font-size: 18px; font-weight: 600; margin-bottom: 4px; }
|
||||
.platform-card .version { font-size: 13px; color: var(--text-muted); margin-bottom: 16px; }
|
||||
.platform-card .btn { width: 100%; justify-content: center; }
|
||||
.platform-card .coming-soon {
|
||||
display: inline-flex; align-items: center; gap: 6px;
|
||||
padding: 14px 32px; border-radius: 10px; font-size: 16px; font-weight: 600;
|
||||
background: #f1f5f9; color: var(--text-muted); cursor: not-allowed; width: 100%; justify-content: center;
|
||||
}
|
||||
|
||||
/* Architecture */
|
||||
#architecture { background: var(--surface); border-top: 1px solid var(--border); }
|
||||
#architecture .container { text-align: center; }
|
||||
#architecture .section-sub { margin: 0 auto 48px; }
|
||||
.arch-diagram {
|
||||
display: flex; flex-direction: column; align-items: center; gap: 12px;
|
||||
max-width: 700px; margin: 0 auto;
|
||||
}
|
||||
.arch-box {
|
||||
background: var(--bg); border: 1px solid var(--border);
|
||||
border-radius: var(--radius); padding: 20px 32px; width: 100%;
|
||||
font-weight: 600; font-size: 15px;
|
||||
}
|
||||
.arch-box.primary { background: var(--primary-light); border-color: var(--primary); color: var(--primary); }
|
||||
.arch-box .arch-sub {
|
||||
display: flex; gap: 16px; justify-content: center; margin-top: 12px; flex-wrap: wrap;
|
||||
}
|
||||
.arch-box .arch-sub span {
|
||||
background: var(--surface); border: 1px solid var(--border);
|
||||
padding: 6px 16px; border-radius: 6px; font-weight: 400; font-size: 13px;
|
||||
}
|
||||
.arch-arrow { color: var(--text-muted); font-size: 20px; }
|
||||
|
||||
/* Footer */
|
||||
footer {
|
||||
padding: 40px 0; border-top: 1px solid var(--border);
|
||||
text-align: center; color: var(--text-muted); font-size: 14px;
|
||||
}
|
||||
footer .container { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 12px; }
|
||||
footer a { color: var(--text-secondary); }
|
||||
|
||||
/* Responsive */
|
||||
@media (max-width: 768px) {
|
||||
.hero h1 { font-size: 36px; }
|
||||
.hero p { font-size: 17px; }
|
||||
section { padding: 60px 0; }
|
||||
.section-title { font-size: 28px; }
|
||||
.features-grid { grid-template-columns: 1fr; }
|
||||
.steps { flex-direction: column; align-items: center; gap: 24px; }
|
||||
.step-arrow { display: none !important; }
|
||||
nav .nav-links a:not(.nav-cta) { display: none; }
|
||||
footer .container { flex-direction: column; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<nav>
|
||||
<div class="container">
|
||||
<a href="#" class="logo">
|
||||
<svg viewBox="0 0 28 28" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<rect x="2" y="4" width="24" height="16" rx="3" />
|
||||
<path d="M8 2v4M20 2v4M2 12h24M10 20v4M18 20v4" />
|
||||
</svg>
|
||||
Web2App
|
||||
</a>
|
||||
<div class="nav-links">
|
||||
<a href="#features">功能特性</a>
|
||||
<a href="#workflow">工作流程</a>
|
||||
<a href="#download" class="nav-cta">立即下载</a>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<!-- Hero -->
|
||||
<section class="hero">
|
||||
<div class="container">
|
||||
<div class="hero-badge">
|
||||
<span>v1.0.0</span>
|
||||
</div>
|
||||
<h1>将任意网站<br>转化为独立的桌面应用</h1>
|
||||
<p>导入网站资源,配置应用信息,一键打包为跨平台安装包 —— 无需编写代码,无需配置运行环境。</p>
|
||||
<div class="hero-buttons">
|
||||
<a href="#download" class="btn btn-primary">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4M7 10l5 5 5-5M12 15V3"/></svg>
|
||||
下载安装包
|
||||
</a>
|
||||
<a href="#features" class="btn btn-secondary">了解更多</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Features -->
|
||||
<section id="features">
|
||||
<div class="container">
|
||||
<span class="section-label">功能特性</span>
|
||||
<h2 class="section-title">强大而简洁</h2>
|
||||
<p class="section-sub">从资源导入到打包发布,Web2App 提供一站式的网站转桌面应用解决方案。</p>
|
||||
<div class="features-grid">
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">📦</div>
|
||||
<h3>一键打包</h3>
|
||||
<p>将完整的网站资源(HTML、JS、CSS、图片等)打包为独立的安装包,内置 Electron 运行时,目标机无需任何预装环境。</p>
|
||||
</div>
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">🖥️</div>
|
||||
<h3>跨平台支持</h3>
|
||||
<p>一次打包,多平台分发。支持 Windows(.exe)、macOS(.dmg)、Linux(.AppImage)三大桌面平台。</p>
|
||||
</div>
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">⚙️</div>
|
||||
<h3>灵活配置</h3>
|
||||
<p>自定义应用名称、图标、版本号、窗口尺寸、作者版权信息,支持指定入口文件和后端服务入口。</p>
|
||||
</div>
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">🌐</div>
|
||||
<h3>内嵌后端服务</h3>
|
||||
<p>应用内嵌 HTTP 服务器与 SQLite 数据库,支持运行 Node.js 后端脚本,自动检测端口占用,无需外部 Web 服务器。</p>
|
||||
</div>
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">📂</div>
|
||||
<h3>资源管理</h3>
|
||||
<p>以目录树形式管理所有导入资源,支持批量导入、文件增删改、保留目录结构,资源状态一目了然。</p>
|
||||
</div>
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">🔒</div>
|
||||
<h3>离线可用 · 安全可靠</h3>
|
||||
<p>打包过程完全离线,不上传任何数据至外网。生成 SHA256 校验值确保安装包完整性,安装过程引导清晰。</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Workflow -->
|
||||
<section id="workflow">
|
||||
<div class="container">
|
||||
<span class="section-label">工作流程</span>
|
||||
<h2 class="section-title">四步完成打包</h2>
|
||||
<p class="section-sub">从网站资源到可分发安装包,只需简单四步。</p>
|
||||
<div class="steps">
|
||||
<div class="step">
|
||||
<div class="step-num">1</div>
|
||||
<h4>导入网站资源</h4>
|
||||
<p>导入 HTML、JS、CSS、图片等文件,自动检测入口文件,保留目录结构。</p>
|
||||
<span class="step-arrow">→</span>
|
||||
</div>
|
||||
<div class="step">
|
||||
<div class="step-num">2</div>
|
||||
<h4>配置应用信息</h4>
|
||||
<p>设置名称、图标、版本、窗口尺寸、后端入口等,一切可视化操作。</p>
|
||||
<span class="step-arrow">→</span>
|
||||
</div>
|
||||
<div class="step">
|
||||
<div class="step-num">3</div>
|
||||
<h4>一键打包</h4>
|
||||
<p>点击打包,实时查看进度与日志,自动嵌入 Electron 运行时生成安装包。</p>
|
||||
<span class="step-arrow">→</span>
|
||||
</div>
|
||||
<div class="step">
|
||||
<div class="step-num">4</div>
|
||||
<h4>分发与运行</h4>
|
||||
<p>将安装包分发给用户,安装后即可独立运行,无需任何环境配置。</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Download -->
|
||||
<section id="download">
|
||||
<div class="container">
|
||||
<span class="section-label">下载安装</span>
|
||||
<h2 class="section-title">选择你的平台</h2>
|
||||
<p class="section-sub">Web2App 支持主流桌面平台,下载对应版本即可开始使用。</p>
|
||||
<div class="platforms">
|
||||
<div class="platform-card">
|
||||
<div class="platform-icon">🪟</div>
|
||||
<h4>Windows</h4>
|
||||
<p class="version">v1.0.0 · x64</p>
|
||||
<a href="../release/win-unpacked/Web2App.exe" class="btn btn-primary" download>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4M7 10l5 5 5-5M12 15V3"/></svg>
|
||||
下载便携版
|
||||
</a>
|
||||
<div style="margin-top:10px;font-size:13px;color:var(--text-muted);">可执行安装包请通过 <code>npm run electron:build</code> 构建</div>
|
||||
</div>
|
||||
<div class="platform-card">
|
||||
<div class="platform-icon">🍎</div>
|
||||
<h4>macOS</h4>
|
||||
<p class="version">v1.0.0 · Intel / Apple Silicon</p>
|
||||
<span class="coming-soon">即将发布</span>
|
||||
</div>
|
||||
<div class="platform-card">
|
||||
<div class="platform-icon">🐧</div>
|
||||
<h4>Linux</h4>
|
||||
<p class="version">v1.0.0 · .AppImage</p>
|
||||
<span class="coming-soon">即将发布</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Architecture -->
|
||||
<section id="architecture">
|
||||
<div class="container">
|
||||
<span class="section-label">技术架构</span>
|
||||
<h2 class="section-title">基于 Electron 构建</h2>
|
||||
<p class="section-sub">Web2App 生成的桌面应用采用分层架构设计,确保性能与可扩展性。</p>
|
||||
<div class="arch-diagram">
|
||||
<div class="arch-box">
|
||||
<div>前端界面(用户网站 HTML / JS / CSS)</div>
|
||||
<div class="arch-sub">
|
||||
<span>Chromium 渲染引擎</span>
|
||||
<span>Vue 3 / React</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="arch-arrow">⬇ HTTP 本地通信 ⬇</div>
|
||||
<div class="arch-box">
|
||||
<div>后端服务</div>
|
||||
<div class="arch-sub">
|
||||
<span>Node.js 运行时</span>
|
||||
<span>Express 路由</span>
|
||||
<span>SQLite 数据库</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="arch-arrow">⬇</div>
|
||||
<div class="arch-box primary">
|
||||
<div>Electron 主进程</div>
|
||||
<div class="arch-sub">
|
||||
<span>窗口管理</span>
|
||||
<span>系统托盘</span>
|
||||
<span>自动启动后端</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="arch-arrow">⬇</div>
|
||||
<div class="arch-box">
|
||||
操作系统 (Windows / macOS / Linux)
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<footer>
|
||||
<div class="container">
|
||||
<span>© 2026 Web2App. MIT License.</span>
|
||||
<a href="https://github.com/anomalyco/WebpageExer" target="_blank">GitHub 仓库</a>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user