merge: 同步 main 最新代码到 dev(依赖更新、版本 4.3.0、资源文件)

This commit is contained in:
hicccc77
2026-03-28 16:54:47 +08:00
16 changed files with 768 additions and 1338 deletions

View File

@@ -12,27 +12,8 @@ env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true" FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
jobs: jobs:
prepare-release:
runs-on: ubuntu-latest
steps:
- name: Mark release as pre-release (building)
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
shell: bash
run: |
set -euo pipefail
TAG="$GITHUB_REF_NAME"
REPO="$GITHUB_REPOSITORY"
# Create or update the release as a pre-release with a placeholder note
if gh release view "$TAG" --repo "$REPO" > /dev/null 2>&1; then
gh release edit "$TAG" --repo "$REPO" --prerelease --notes $'## ⚠️ 正在自动构建中,请勿下载\n\n各平台安装包正在构建完成后将自动更新本页面并正式发布。\n\n**请勿在此期间下载任何文件。**'
else
gh release create "$TAG" --repo "$REPO" --prerelease --title "$TAG" --notes $'## ⚠️ 正在自动构建中,请勿下载\n\n各平台安装包正在构建完成后将自动更新本页面并正式发布。\n\n**请勿在此期间下载任何文件。**'
fi
release-mac-arm64: release-mac-arm64:
runs-on: macos-14 runs-on: macos-14
needs: prepare-release
steps: steps:
- name: Check out git repository - name: Check out git repository
@@ -61,16 +42,31 @@ jobs:
npx tsc npx tsc
npx vite build npx vite build
- name: Package and Publish macOS arm64 (unsigned DMG + ZIP) - name: Package and Publish macOS arm64 (unsigned DMG)
env: env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CSC_IDENTITY_AUTO_DISCOVERY: "false" CSC_IDENTITY_AUTO_DISCOVERY: "false"
run: | run: |
npx electron-builder --mac --arm64 --publish always npx electron-builder --mac dmg --arm64 --publish always
- name: Inject minimumVersion into latest yml
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
shell: bash
run: |
TAG=${GITHUB_REF_NAME}
REPO=${{ github.repository }}
MINIMUM_VERSION="4.1.7"
for YML_FILE in latest-mac.yml latest-arm64-mac.yml; do
gh release download "$TAG" --repo "$REPO" --pattern "$YML_FILE" --output "/tmp/$YML_FILE" 2>/dev/null || continue
if ! grep -q 'minimumVersion' "/tmp/$YML_FILE"; then
echo "minimumVersion: $MINIMUM_VERSION" >> "/tmp/$YML_FILE"
fi
gh release upload "$TAG" --repo "$REPO" "/tmp/$YML_FILE" --clobber
done
release-linux: release-linux:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: prepare-release
steps: steps:
- name: Check out git repository - name: Check out git repository
@@ -105,9 +101,22 @@ jobs:
run: | run: |
npx electron-builder --linux --publish always npx electron-builder --linux --publish always
- name: Inject minimumVersion into latest yml
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
shell: bash
run: |
TAG=${GITHUB_REF_NAME}
REPO=${{ github.repository }}
MINIMUM_VERSION="4.1.7"
gh release download "$TAG" --repo "$REPO" --pattern "latest-linux.yml" --output "/tmp/latest-linux.yml" 2>/dev/null
if [ -f /tmp/latest-linux.yml ] && ! grep -q 'minimumVersion' /tmp/latest-linux.yml; then
echo "minimumVersion: $MINIMUM_VERSION" >> /tmp/latest-linux.yml
gh release upload "$TAG" --repo "$REPO" /tmp/latest-linux.yml --clobber
fi
release: release:
runs-on: windows-latest runs-on: windows-latest
needs: prepare-release
steps: steps:
- name: Check out git repository - name: Check out git repository
@@ -137,15 +146,27 @@ jobs:
npx vite build npx vite build
- name: Package and Publish - name: Package and Publish
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
npx electron-builder --win nsis --x64 --publish always '--config.artifactName=${productName}-${version}-x64-Setup.${ext}'
- name: Inject minimumVersion into latest yml
env: env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
shell: bash shell: bash
run: | run: |
npx electron-builder --win nsis --x64 --publish always "-c.artifactName=\${productName}-\${version}-x64-Setup.\${ext}" TAG=${GITHUB_REF_NAME}
REPO=${{ github.repository }}
MINIMUM_VERSION="4.1.7"
gh release download "$TAG" --repo "$REPO" --pattern "latest.yml" --output "/tmp/latest.yml" 2>/dev/null
if [ -f /tmp/latest.yml ] && ! grep -q 'minimumVersion' /tmp/latest.yml; then
echo "minimumVersion: $MINIMUM_VERSION" >> /tmp/latest.yml
gh release upload "$TAG" --repo "$REPO" /tmp/latest.yml --clobber
fi
release-windows-arm64: release-windows-arm64:
runs-on: windows-latest runs-on: windows-latest
needs: prepare-release
steps: steps:
- name: Check out git repository - name: Check out git repository
@@ -175,11 +196,24 @@ jobs:
npx vite build npx vite build
- name: Package and Publish Windows arm64 - name: Package and Publish Windows arm64
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
npx electron-builder --win nsis --arm64 --publish always '--config.publish.channel=latest-arm64' '--config.artifactName=${productName}-${version}-arm64-Setup.${ext}'
- name: Inject minimumVersion into latest yml
env: env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
shell: bash shell: bash
run: | run: |
npx electron-builder --win nsis --arm64 --publish always -c.publish.channel=latest-arm64 "-c.artifactName=\${productName}-\${version}-arm64-Setup.\${ext}" TAG=${GITHUB_REF_NAME}
REPO=${{ github.repository }}
MINIMUM_VERSION="4.1.7"
gh release download "$TAG" --repo "$REPO" --pattern "latest-arm64.yml" --output "/tmp/latest-arm64.yml" 2>/dev/null
if [ -f /tmp/latest-arm64.yml ] && ! grep -q 'minimumVersion' /tmp/latest-arm64.yml; then
echo "minimumVersion: $MINIMUM_VERSION" >> /tmp/latest-arm64.yml
gh release upload "$TAG" --repo "$REPO" /tmp/latest-arm64.yml --clobber
fi
update-release-notes: update-release-notes:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -190,53 +224,6 @@ jobs:
- release-windows-arm64 - release-windows-arm64
steps: steps:
- name: Fix latest.yml to point to x64 installer
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
shell: bash
run: |
set -euo pipefail
TAG="$GITHUB_REF_NAME"
VERSION="${TAG#v}"
REPO="$GITHUB_REPOSITORY"
# Find the x64 exe asset name
ASSETS_JSON="$(gh release view "$TAG" --repo "$REPO" --json assets)"
X64_ASSET="$(echo "$ASSETS_JSON" | jq -r '[.assets[].name | select(test("x64.*\\.exe$"))][0] // ""')"
if [ -z "$X64_ASSET" ]; then
X64_ASSET="$(echo "$ASSETS_JSON" | jq -r '[.assets[].name | select(test("\\.exe$")) | select(test("arm64") | not)][0] // ""')"
fi
if [ -z "$X64_ASSET" ]; then
echo "ERROR: Could not find x64 exe asset"
exit 1
fi
echo "Downloading x64 installer: $X64_ASSET"
gh release download "$TAG" --repo "$REPO" --pattern "$X64_ASSET" --dir /tmp/weflow-x64
SHA512_B64="$(sha512sum "/tmp/weflow-x64/$X64_ASSET" | awk '{print $1}' | xxd -r -p | base64 -w 0)"
SIZE="$(stat -c%s "/tmp/weflow-x64/$X64_ASSET")"
RELEASE_DATE="$(gh release view "$TAG" --repo "$REPO" --json publishedAt -q .publishedAt)"
cat > /tmp/latest.yml <<YMLEOF
version: $VERSION
files:
- url: $X64_ASSET
sha512: $SHA512_B64
size: $SIZE
path: $X64_ASSET
sha512: $SHA512_B64
releaseDate: '$RELEASE_DATE'
YMLEOF
# Strip leading spaces (heredoc indentation)
sed -i 's/^ //' /tmp/latest.yml
cat /tmp/latest.yml
gh release upload "$TAG" --repo "$REPO" /tmp/latest.yml --clobber
echo "latest.yml updated successfully to point to $X64_ASSET"
- name: Generate release notes with platform download links - name: Generate release notes with platform download links
env: env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -294,18 +281,10 @@ jobs:
## macOS 安装提示(未知来源) ## macOS 安装提示(未知来源)
- 若打开时提示“来自未知开发者”或“无法验证开发者”,请到「系统设置 -> 隐私与安全性」中允许打开该应用。 - 若打开时提示“来自未知开发者”或“无法验证开发者”,请到「系统设置 -> 隐私与安全性」中允许打开该应用。
- 如果仍被系统拦截,请在终端执行以下命令去除隔离标记: - 如果仍被系统拦截,请在终端执行以下命令去除隔离标记:
- xattr -rd com.apple.quarantine /Applications/WeFlow.app - \`xattr -dr com.apple.quarantine "/Applications/WeFlow.app"\`
- 执行后重新打开 WeFlow。 - 执行后重新打开 WeFlow。
> 如果某个平台链接暂时未生成,可进入完整发布页查看全部资源:$RELEASE_PAGE > 如果某个平台链接暂时未生成,可进入完整发布页查看全部资源:$RELEASE_PAGE
EOF EOF
gh release edit "$TAG" --repo "$REPO" --notes-file release_notes.md gh release edit "$TAG" --repo "$REPO" --notes-file release_notes.md
- name: Mark release as published (no longer pre-release)
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
shell: bash
run: |
set -euo pipefail
gh release edit "$GITHUB_REF_NAME" --repo "$GITHUB_REPOSITORY" --latest --draft=false --prerelease=false

23
.gitleaks.toml Normal file
View File

@@ -0,0 +1,23 @@
title = "Gitleaks Config"
[extend]
# 继承默认规则
useDefault = true
# 排除误报路径
[[rules]]
id = "curl-auth-header"
[rules.allowlist]
paths = [
'''docs/HTTP-API\.md'''
]
regexes = [
'''YOUR_TOKEN'''
]
[[rules]]
id = "generic-api-key"
[rules.allowlist]
paths = [
'''src/pages/ChatPage\.tsx'''
]

View File

@@ -1242,7 +1242,8 @@ function registerIpcHandlers() {
return { return {
hasUpdate: true, hasUpdate: true,
version: latestVersion, version: latestVersion,
releaseNotes: normalizeReleaseNotes(result.updateInfo.releaseNotes) releaseNotes: normalizeReleaseNotes(result.updateInfo.releaseNotes),
minimumVersion: (result.updateInfo as any).minimumVersion
} }
} }
} }
@@ -2706,7 +2707,8 @@ function checkForUpdatesOnStartup() {
// 通知渲染进程有新版本 // 通知渲染进程有新版本
mainWindow.webContents.send('app:updateAvailable', { mainWindow.webContents.send('app:updateAvailable', {
version: latestVersion, version: latestVersion,
releaseNotes: normalizeReleaseNotes(result.updateInfo.releaseNotes) releaseNotes: normalizeReleaseNotes(result.updateInfo.releaseNotes),
minimumVersion: (result.updateInfo as any).minimumVersion
}) })
} }
} }

1877
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{ {
"name": "weflow", "name": "weflow",
"version": "4.2.0", "version": "4.3.0",
"description": "WeFlow", "description": "WeFlow",
"main": "dist-electron/main.js", "main": "dist-electron/main.js",
"author": { "author": {
@@ -38,7 +38,7 @@
"react": "^19.2.3", "react": "^19.2.3",
"react-dom": "^19.2.3", "react-dom": "^19.2.3",
"react-markdown": "^10.1.0", "react-markdown": "^10.1.0",
"react-router-dom": "^7.1.1", "react-router-dom": "^7.13.2",
"react-virtuoso": "^4.18.1", "react-virtuoso": "^4.18.1",
"remark-gfm": "^4.0.1", "remark-gfm": "^4.0.1",
"sherpa-onnx-node": "^1.10.38", "sherpa-onnx-node": "^1.10.38",
@@ -53,7 +53,7 @@
"@types/react-dom": "^19.1.0", "@types/react-dom": "^19.1.0",
"@vitejs/plugin-react": "^4.3.4", "@vitejs/plugin-react": "^4.3.4",
"electron": "^39.2.7", "electron": "^39.2.7",
"electron-builder": "^25.1.8", "electron-builder": "^26.8.1",
"sass": "^1.83.0", "sass": "^1.83.0",
"sharp": "^0.34.5", "sharp": "^0.34.5",
"typescript": "^5.6.3", "typescript": "^5.6.3",
@@ -61,6 +61,17 @@
"vite-plugin-electron": "^0.28.8", "vite-plugin-electron": "^0.28.8",
"vite-plugin-electron-renderer": "^0.14.6" "vite-plugin-electron-renderer": "^0.14.6"
}, },
"pnpm": {
"overrides": {
"tar": ">=6.2.1",
"minimatch": ">=3.1.2",
"rollup": ">=4.0.0",
"immutable": ">=4.0.0",
"lodash": ">=4.17.21",
"brace-expansion": ">=1.1.11",
"picomatch": ">=2.3.1"
}
},
"build": { "build": {
"appId": "com.WeFlow.app", "appId": "com.WeFlow.app",
"publish": { "publish": {
@@ -177,5 +188,10 @@
} }
], ],
"icon": "resources/icon.icns" "icon": "resources/icon.icns"
},
"overrides": {
"picomatch": "^4.0.4",
"tar": "^7.5.13",
"immutable": "^5.1.5"
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 212 KiB

After

Width:  |  Height:  |  Size: 364 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 570 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

After

Width:  |  Height:  |  Size: 570 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -312,10 +312,14 @@ function App() {
const removeUpdateListener = window.electronAPI?.app?.onUpdateAvailable?.((info: any) => { const removeUpdateListener = window.electronAPI?.app?.onUpdateAvailable?.((info: any) => {
// 发现新版本时保存更新信息,锁定状态下不弹窗,解锁后再显示 // 发现新版本时保存更新信息,锁定状态下不弹窗,解锁后再显示
if (info) { if (info) {
setUpdateInfo({ ...info, hasUpdate: true }) window.electronAPI.app.getVersion().then((currentVersion: string) => {
if (!useAppStore.getState().isLocked) { const isMandatory = !!(info.minimumVersion && currentVersion &&
setShowUpdateDialog(true) currentVersion.localeCompare(info.minimumVersion, undefined, { numeric: true, sensitivity: 'base' }) <= 0)
} setUpdateInfo({ ...info, hasUpdate: true, isMandatory })
if (!useAppStore.getState().isLocked) {
setShowUpdateDialog(true)
}
})
} }
}) })
const removeProgressListener = window.electronAPI?.app?.onDownloadProgress?.((progress: any) => { const removeProgressListener = window.electronAPI?.app?.onDownloadProgress?.((progress: any) => {
@@ -685,10 +689,11 @@ function App() {
<UpdateDialog <UpdateDialog
open={showUpdateDialog} open={showUpdateDialog}
updateInfo={updateInfo} updateInfo={updateInfo}
onClose={() => setShowUpdateDialog(false)} onClose={() => { if (!(updateInfo as any)?.isMandatory) setShowUpdateDialog(false) }}
onUpdate={handleUpdateNow} onUpdate={handleUpdateNow}
onIgnore={handleIgnoreUpdate} onIgnore={handleIgnoreUpdate}
isDownloading={isDownloading} isDownloading={isDownloading}
isMandatory={!!(updateInfo as any)?.isMandatory}
progress={downloadProgress} progress={downloadProgress}
/> />

View File

@@ -282,4 +282,13 @@
transform: translateY(0); transform: translateY(0);
opacity: 1; opacity: 1;
} }
} }
.mandatory-tip {
color: #e53e3e;
font-size: 13px;
text-align: center;
margin: 0 0 8px;
padding: 6px 12px;
background: rgba(229, 62, 62, 0.08);
border-radius: 6px;
}

View File

@@ -14,6 +14,7 @@ interface UpdateDialogProps {
onUpdate: () => void onUpdate: () => void
onIgnore?: () => void onIgnore?: () => void
isDownloading: boolean isDownloading: boolean
isMandatory?: boolean
progress: number | { progress: number | {
percent: number percent: number
bytesPerSecond?: number bytesPerSecond?: number
@@ -30,6 +31,7 @@ const UpdateDialog: React.FC<UpdateDialogProps> = ({
onUpdate, onUpdate,
onIgnore, onIgnore,
isDownloading, isDownloading,
isMandatory,
progress progress
}) => { }) => {
if (!open || !updateInfo) return null if (!open || !updateInfo) return null
@@ -69,7 +71,7 @@ const UpdateDialog: React.FC<UpdateDialogProps> = ({
return ( return (
<div className="update-dialog-overlay"> <div className="update-dialog-overlay">
<div className="update-dialog"> <div className="update-dialog">
{!isDownloading && ( {!isDownloading && !isMandatory && (
<button className="close-btn" onClick={onClose}> <button className="close-btn" onClick={onClose}>
<X size={20} /> <X size={20} />
</button> </button>
@@ -119,11 +121,14 @@ const UpdateDialog: React.FC<UpdateDialogProps> = ({
</div> </div>
) : ( ) : (
<div className="actions"> <div className="actions">
{onIgnore && ( {onIgnore && !isMandatory && (
<button className="btn-ignore" onClick={onIgnore}> <button className="btn-ignore" onClick={onIgnore}>
</button> </button>
)} )}
{isMandatory && (
<p className="mandatory-tip">使</p>
)}
<button className="btn-update" onClick={onUpdate}> <button className="btn-update" onClick={onUpdate}>
</button> </button>