fix: 修复 Release 正文为空及检查更新 v0.1.0 404 问题

- CI: /tmp/release-notes.md 改用 $RUNNER_TEMP,修复 Windows 路径不一致导致
  release body 显示为 commit message 而非 CHANGELOG 内容
- 删除远端 v0.1.0 tag(早期测试遗留),修复 electron-updater 从 Atom feed
  读到 v0.1.0 > v0.0.4-beta 后尝试 latest.yml 而 404 的检查更新失败
- 关于页面新增应用文件夹、数据文件夹、日志文件夹展示,带复制和打开按钮
This commit is contained in:
钟明原 committed 2026-03-15 01:09:48 +08:00
1 parent e356cd2dcb
commit cf83ca9db3
5 files changed
+73 -9

No files matched your search

+3 -3
View File
@@ -103,8 +103,8 @@ jobs:
id: release_meta
run: |
VERSION=${GITHUB_REF#refs/tags/v}
node scripts/extract-release-notes.mjs $VERSION > /tmp/release-notes.md
cat /tmp/release-notes.md
node scripts/extract-release-notes.mjs $VERSION > "$RUNNER_TEMP/release-notes.md"
cat "$RUNNER_TEMP/release-notes.md"
# 主版本号为 0 或包含 - 的版本视为测试版
if [[ "$VERSION" =~ ^0\. ]] || [[ "$VERSION" =~ - ]]; then
echo "is_prerelease=true" >> $GITHUB_OUTPUT
@@ -119,7 +119,7 @@ jobs:
files: |
dist/*.dmg
dist/latest-mac.yml
body_path: /tmp/release-notes.md
body_path: ${{ runner.temp }}/release-notes.md
draft: false
prerelease: ${{ steps.release_meta.outputs.is_prerelease }}
env:
+3 -3
View File
@@ -85,8 +85,8 @@ jobs:
shell: bash
run: |
VERSION=${GITHUB_REF#refs/tags/v}
node scripts/extract-release-notes.mjs $VERSION > /tmp/release-notes.md
cat /tmp/release-notes.md
node scripts/extract-release-notes.mjs $VERSION > "$RUNNER_TEMP/release-notes.md"
cat "$RUNNER_TEMP/release-notes.md"
# 主版本号为 0 或包含 - 的版本视为测试版
if [[ "$VERSION" =~ ^0\. ]] || [[ "$VERSION" =~ - ]]; then
echo "is_prerelease=true" >> $GITHUB_OUTPUT
@@ -101,7 +101,7 @@ jobs:
files: |
dist/*.exe
dist/latest.yml
body_path: /tmp/release-notes.md
body_path: ${{ runner.temp }}/release-notes.md
draft: false
prerelease: ${{ steps.release_meta.outputs.is_prerelease }}
env:
+12 -1
View File
@@ -16,7 +16,7 @@
*/
import type { IpcMain, BrowserWindow } from 'electron'
import { app } from 'electron'
import { app, shell } from 'electron'
import { autoUpdater } from 'electron-updater'
import { logger } from './lib/logger'
@@ -122,4 +122,15 @@ export function registerAppUpdaterHandlers(ipcMain: IpcMain): void {
ipcMain.handle('app:install-update', () => {
autoUpdater.quitAndInstall()
})
ipcMain.handle('app:paths', () => ({
appPath: app.isPackaged ? process.resourcesPath : app.getAppPath(),
userData: app.getPath('userData'),
logs: app.getPath('logs'),
}))
ipcMain.handle('app:open-path', async (_event, targetPath: string) => {
const err = await shell.openPath(targetPath)
if (err) logger.warn(`[AppPaths] shell.openPath failed: ${err}`)
})
}
+4
View File
@@ -224,6 +224,10 @@ const ipcApi = {
appUpdateCallbacks.add(callback)
return () => appUpdateCallbacks.delete(callback)
},
appPaths: (): Promise<{ appPath: string; userData: string; logs: string }> =>
ipcRenderer.invoke('app:paths'),
appOpenPath: (targetPath: string): Promise<void> =>
ipcRenderer.invoke('app:open-path', targetPath),
// ── Window controls (frameless) ───────────────────────────────────────────
windowMinimize: () => ipcRenderer.send('window:minimize'),
@@ -1,7 +1,7 @@
import { useState, useEffect } from "react"
import { ArrowLeft, Brain, Check, Languages, Info, RefreshCw, Download, CheckCircle2, Loader2 } from "lucide-react"
import { ArrowLeft, Brain, Check, Languages, Info, RefreshCw, Download, CheckCircle2, Loader2, FolderOpen, Copy, CheckCheck } from "lucide-react"
import {
Dialog,
DialogContent,
@@ -174,11 +174,20 @@ type UpdateState =
function AboutPanel() {
const [updateState, setUpdateState] = useState<UpdateState>({ status: 'idle' })
const [appVersion, setAppVersion] = useState<string>('…')
const [paths, setPaths] = useState<{ appPath: string; userData: string; logs: string } | null>(null)
const [copied, setCopied] = useState<string | null>(null)
useEffect(() => {
window.ipc.appVersion().then(setAppVersion)
window.ipc.appPaths().then(setPaths)
}, [])
const handleCopy = (key: string, value: string) => {
navigator.clipboard.writeText(value)
setCopied(key)
setTimeout(() => setCopied(null), 2000)
}
const handleCheckUpdate = async () => {
setUpdateState({ status: 'checking' })
const unsubscribe = window.ipc.onAppUpdateStatus((s) => {
@@ -211,7 +220,47 @@ function AboutPanel() {
</div>
</div>
{/* Update section */}
{/* File paths */}
<div className="space-y-3">
<h3 className="text-sm font-medium">文件目录</h3>
<div className="space-y-2">
{[
{ key: 'appPath', label: '应用文件夹', value: paths?.appPath },
{ key: 'userData', label: '数据文件夹', value: paths?.userData },
{ key: 'logs', label: '日志文件夹', value: paths?.logs },
].map(({ key, label, value }) => (
<div key={key} className="rounded-lg border bg-muted/20 px-3 py-2.5">
<div className="flex items-center justify-between gap-2 mb-1">
<span className="text-xs text-muted-foreground">{label}</span>
<div className="flex items-center gap-1 shrink-0">
<button
onClick={() => value && handleCopy(key, value)}
disabled={!value}
className="p-1 rounded hover:bg-muted transition-colors text-muted-foreground hover:text-foreground disabled:opacity-40"
title="复制路径"
>
{copied === key
? <CheckCheck className="h-3.5 w-3.5 text-green-500" />
: <Copy className="h-3.5 w-3.5" />
}
</button>
<button
onClick={() => value && window.ipc.appOpenPath(value)}
disabled={!value}
className="p-1 rounded hover:bg-muted transition-colors text-muted-foreground hover:text-foreground disabled:opacity-40"
title="在文件管理器中打开"
>
<FolderOpen className="h-3.5 w-3.5" />
</button>
</div>
</div>
<p className="text-xs font-mono text-foreground/80 break-all leading-relaxed">
{value ?? <span className="text-muted-foreground/50 animate-pulse">加载中…</span>}
</p>
</div>
))}
</div>
</div>
<div className="space-y-3">
<h3 className="text-sm font-medium">软件更新</h3>