feat: 完成 Issue #14-15 主题商店与跨平台打包

## Phase 4 - 性能与生态 (续)

### Issue #14: 个性化主题商店 
- ThemeManager 主题管理器
- 4 种内置主题 (深色/浅色/护眼/高对比度)
- 主题安装/卸载功能
- 自定义主题配置
- CSS 变量系统

### Issue #15: 跨平台打包发布 
- build-release.sh 打包脚本
- 支持 macOS (DMG + App Bundle)
- 支持 Linux (AppImage + tar.gz)
- 支持 Windows (NSIS + ZIP)
- Cargo 发布配置优化 (LTO, strip)
- 自动生成 RELEASE.md

## 完成状态
 Phase 2: 4/4 Issues
 Phase 3: 4/4 Issues
 Phase 4: 3/3 Issues

🎉 ReadFlow MVP 全部完成!
This commit is contained in:
大麦
2026-03-10 14:33:36 +08:00
parent 600f205c87
commit 93f2f02d46
4 changed files with 832 additions and 2 deletions

377
scripts/build-release.sh Executable file
View File

@@ -0,0 +1,377 @@
#!/bin/bash
# ReadFlow 跨平台打包发布脚本
# 支持macOS (Intel/Apple Silicon), Windows, Linux
set -e
echo "🚀 ReadFlow 打包发布脚本"
echo "========================"
# 配置
APP_NAME="readflow"
VERSION="0.1.0"
AUTHOR="damai <damai@foshanhuiya.com>"
DESCRIPTION="ReadFlow - 面向开发者和知识工作者的阅读工具"
# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
log_info() {
echo -e "${GREEN}[INFO]${NC} $1"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# 检测操作系统
detect_os() {
case "$(uname -s)" in
Darwin)
echo "macos"
;;
Linux)
echo "linux"
;;
MINGW*|MSYS*|CYGWIN*)
echo "windows"
;;
*)
echo "unknown"
;;
esac
}
# 检测 CPU 架构
detect_arch() {
case "$(uname -m)" in
x86_64)
echo "x86_64"
;;
arm64|aarch64)
echo "aarch64"
;;
*)
echo "unknown"
;;
esac
}
# 构建 Release 版本
build_release() {
log_info "构建 Release 版本..."
# 清理之前的构建
cargo clean
# 构建
cargo build --release
log_info "构建完成!"
}
# macOS 打包
package_macos() {
log_info "打包 macOS 应用..."
local arch=$(detect_arch)
local target_dir="target/release"
local package_dir="dist/${APP_NAME}-${VERSION}-macos-${arch}"
local app_bundle="${package_dir}/${APP_NAME}.app"
# 创建目录结构
mkdir -p "${app_bundle}/Contents/MacOS"
mkdir -p "${app_bundle}/Contents/Resources"
# 复制二进制文件
cp "${target_dir}/${APP_NAME}" "${app_bundle}/Contents/MacOS/"
# 创建 Info.plist
cat > "${app_bundle}/Contents/Info.plist" << EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>${APP_NAME}</string>
<key>CFBundleIdentifier</key>
<string>com.readflow.${APP_NAME}</string>
<key>CFBundleName</key>
<string>ReadFlow</string>
<key>CFBundleDisplayName</key>
<string>ReadFlow</string>
<key>CFBundleVersion</key>
<string>${VERSION}</string>
<key>CFBundleShortVersionString</key>
<string>${VERSION}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>NSHighResolutionCapable</key>
<true/>
</dict>
</plist>
EOF
# 创建 PkgInfo
echo "APPL????" > "${app_bundle}/Contents/PkgInfo"
# 复制资源文件
if [ -d "assets" ]; then
cp -r assets "${app_bundle}/Contents/Resources/"
fi
# 创建 DMG (需要 create-dmg)
if command -v create-dmg &> /dev/null; then
log_info "创建 DMG 文件..."
create-dmg \
--volname "ReadFlow" \
--window-pos 200 120 \
--window-size 600 400 \
--icon-size 100 \
--app-drop-link 450 200 \
"dist/${APP_NAME}-${VERSION}-macos-${arch}.dmg" \
"${app_bundle}"
else
log_warn "create-dmg 未安装,跳过 DMG 创建"
log_info "安装包位于:${package_dir}"
fi
log_info "macOS 打包完成!"
}
# Linux 打包
package_linux() {
log_info "打包 Linux 应用..."
local arch=$(detect_arch)
local target_dir="target/release"
local package_dir="dist/${APP_NAME}-${VERSION}-linux-${arch}"
mkdir -p "${package_dir}"
# 复制二进制文件
cp "${target_dir}/${APP_NAME}" "${package_dir}/"
# 创建 .desktop 文件
cat > "${package_dir}/${APP_NAME}.desktop" << EOF
[Desktop Entry]
Name=ReadFlow
Comment=${DESCRIPTION}
Exec=${APP_NAME}
Icon=${APP_NAME}
Terminal=false
Type=Application
Categories=Utility;Reading;
EOF
# 创建 AppImage (需要 appimagetool)
if command -v appimagetool &> /dev/null; then
log_info "创建 AppImage..."
# AppDir 结构
local appdir="${package_dir}/AppDir"
mkdir -p "${appdir}/usr/bin"
mkdir -p "${appdir}/usr/share/applications"
cp "${target_dir}/${APP_NAME}" "${appdir}/usr/bin/"
cp "${package_dir}/${APP_NAME}.desktop" "${appdir}/usr/share/applications/"
# 创建 AppRun
cat > "${appdir}/AppRun" << EOF
#!/bin/bash
exec "\$(dirname "\$0")/usr/bin/${APP_NAME}" "\$@"
EOF
chmod +x "${appdir}/AppRun"
appimagetool "${appdir}" "dist/${APP_NAME}-${VERSION}-linux-${arch}.AppImage"
else
log_warn "appimagetool 未安装,跳过 AppImage 创建"
fi
# 创建 tar.gz
cd dist
tar -czf "${APP_NAME}-${VERSION}-linux-${arch}.tar.gz" "${APP_NAME}-${VERSION}-linux-${arch}"
cd ..
log_info "Linux 打包完成!"
}
# Windows 打包
package_windows() {
log_info "打包 Windows 应用..."
local target_dir="target/release"
local package_dir="dist/${APP_NAME}-${VERSION}-windows-x86_64"
mkdir -p "${package_dir}"
# 复制二进制文件
cp "${target_dir}/${APP_NAME}.exe" "${package_dir}/"
# 复制依赖 DLL (如果需要)
# cp "${target_dir}"/*.dll "${package_dir}/" 2>/dev/null || true
# 创建 NSIS 安装脚本 (需要 nsis)
if command -v makensis &> /dev/null; then
log_info "创建 NSIS 安装程序..."
cat > "installer.nsi" << EOF
!include "MUI2.nsh"
Name "ReadFlow"
OutFile "dist/${APP_NAME}-${VERSION}-windows-x86_64-installer.exe"
InstallDir "\$PROGRAMFILES\\ReadFlow"
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_LANGUAGE "English"
Section "Install"
SetOutPath "\$INSTDIR"
File "${package_dir}\\${APP_NAME}.exe"
WriteUninstaller "\$INSTDIR\\uninstall.exe"
CreateDirectory "\$SMPROGRAMS\\ReadFlow"
CreateShortCut "\$SMPROGRAMS\\ReadFlow\\ReadFlow.lnk" "\$INSTDIR\\${APP_NAME}.exe"
CreateShortCut "\$DESKTOP\\ReadFlow.lnk" "\$INSTDIR\\${APP_NAME}.exe"
SectionEnd
Section "Uninstall"
Delete "\$INSTDIR\\${APP_NAME}.exe"
Delete "\$INSTDIR\\uninstall.exe"
RMDir "\$INSTDIR"
Delete "\$SMPROGRAMS\\ReadFlow\\ReadFlow.lnk"
RMDir "\$SMPROGRAMS\\ReadFlow"
Delete "\$DESKTOP\\ReadFlow.lnk"
SectionEnd
EOF
makensis installer.nsi
rm installer.nsi
else
log_warn "nsis 未安装,跳过安装程序创建"
fi
# 创建 ZIP
cd dist
zip -r "${APP_NAME}-${VERSION}-windows-x86_64.zip" "${APP_NAME}-${VERSION}-windows-x86_64"
cd ..
log_info "Windows 打包完成!"
}
# 创建发布说明
create_release_notes() {
log_info "创建发布说明..."
cat > "dist/RELEASE.md" << EOF
# ReadFlow v${VERSION} 发布说明
## 下载
### macOS
- [Intel](${APP_NAME}-${VERSION}-macos-x86_64.dmg)
- [Apple Silicon](${APP_NAME}-${VERSION}-macos-aarch64.dmg)
### Linux
- [AppImage](${APP_NAME}-${VERSION}-linux-x86_64.AppImage)
- [tar.gz](${APP_NAME}-${VERSION}-linux-x86_64.tar.gz)
### Windows
- [Installer](${APP_NAME}-${VERSION}-windows-x86_64-installer.exe)
- [Portable](${APP_NAME}-${VERSION}-windows-x86_64.zip)
## 新功能
### Phase 2 - 核心功能
- ✅ EPUB/MOBI/AZW3 格式支持
- ✅ Markdown 阅读模式
- ✅ 双语翻译功能
- ✅ 笔记与书签系统
### Phase 3 - 高级功能
- ✅ 代码阅读器 (20+ 语言支持)
- ✅ 全文双语对照模式
- ✅ 阅读进度同步
- ✅ 插件系统
### Phase 4 - 性能与生态
- ✅ 性能优化与分析
- ✅ 个性化主题商店
- ✅ 跨平台打包发布
## 技术栈
- 语言Rust
- GUI: Dioxus
- 存储sled
- 翻译:阿里百炼/DeepL/Ollama
## 系统要求
- macOS 10.15+
- Windows 10+
- Linux (glibc 2.31+)
## 反馈与支持
- GitHub: https://github.com/damai/readflow
- Email: damai@foshanhuiya.com
---
发布日期:$(date +%Y-%m-%d)
EOF
log_info "发布说明已创建dist/RELEASE.md"
}
# 主函数
main() {
local os=$(detect_os)
log_info "检测到操作系统:${os}"
# 构建
build_release
# 根据操作系统打包
case "${os}" in
macos)
package_macos
;;
linux)
package_linux
;;
windows)
package_windows
;;
*)
log_error "不支持的操作系统:${os}"
exit 1
;;
esac
# 创建发布说明
create_release_notes
log_info "🎉 打包完成!"
log_info "发布文件位于dist/"
# 列出生成的文件
echo ""
echo "生成的文件:"
ls -lh dist/
}
# 运行主函数
main "$@"