diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..cefd3f9 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,7 @@ +version: 2 +updates: + - package-ecosystem: "npm" + directory: "/" + schedule: + interval: "daily" + target-branch: "dev" \ No newline at end of file diff --git a/.github/workflows/dev-daily-fixed.yml b/.github/workflows/dev-daily-fixed.yml new file mode 100644 index 0000000..9039096 --- /dev/null +++ b/.github/workflows/dev-daily-fixed.yml @@ -0,0 +1,228 @@ +name: Dev Daily + +on: + schedule: + # GitHub Actions schedule uses UTC. 16:00 UTC = 北京时间次日 00:00 + - cron: "0 16 * * *" + workflow_dispatch: + +permissions: + contents: write + +env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true" + FIXED_DEV_TAG: nightly-dev + +jobs: + prepare: + runs-on: ubuntu-latest + outputs: + dev_version: ${{ steps.meta.outputs.dev_version }} + steps: + - name: Check out git repository + uses: actions/checkout@v5 + with: + fetch-depth: 0 + + - name: Install Node.js + uses: actions/setup-node@v5 + with: + node-version: 24 + cache: "npm" + + - name: Generate daily dev version + id: meta + shell: bash + run: | + set -euo pipefail + BASE_VERSION="$(node -p "require('./package.json').version.split('-')[0]")" + YEAR_2="$(TZ=Asia/Shanghai date +%y)" + MONTH="$(TZ=Asia/Shanghai date +%-m)" + DAY="$(TZ=Asia/Shanghai date +%-d)" + DEV_VERSION="${BASE_VERSION}-dev.${YEAR_2}.${MONTH}.${DAY}" + echo "dev_version=$DEV_VERSION" >> "$GITHUB_OUTPUT" + echo "Dev version: $DEV_VERSION" + + - name: Ensure fixed prerelease exists + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + shell: bash + run: | + set -euo pipefail + if gh release view "$FIXED_DEV_TAG" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then + gh release edit "$FIXED_DEV_TAG" --repo "$GITHUB_REPOSITORY" --title "Daily Dev Build" --prerelease + else + gh release create "$FIXED_DEV_TAG" --repo "$GITHUB_REPOSITORY" --title "Daily Dev Build" --notes "开发版发布页" --prerelease + fi + + dev-mac-arm64: + needs: prepare + runs-on: macos-14 + steps: + - name: Check out git repository + uses: actions/checkout@v5 + with: + fetch-depth: 0 + + - name: Install Node.js + uses: actions/setup-node@v5 + with: + node-version: 24 + cache: "npm" + + - name: Install Dependencies + run: npm install + + - name: Set dev version + shell: bash + run: npm version "${{ needs.prepare.outputs.dev_version }}" --no-git-tag-version --allow-same-version + + - name: Build Frontend & Type Check + run: | + npx tsc + npx vite build + + - name: Package macOS arm64 dev artifacts + run: | + npx electron-builder --mac dmg --arm64 --publish never '--config.publish.channel=dev' '--config.artifactName=${productName}-dev-arm64.${ext}' + + - name: Upload macOS arm64 assets to fixed release + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + shell: bash + run: | + mapfile -t assets < <(find release -maxdepth 1 -type f | sort) + if [ "${#assets[@]}" -eq 0 ]; then + echo "No release files found in ./release" + exit 1 + fi + gh release upload "$FIXED_DEV_TAG" "${assets[@]}" --repo "$GITHUB_REPOSITORY" --clobber + + dev-linux: + needs: prepare + runs-on: ubuntu-latest + steps: + - name: Check out git repository + uses: actions/checkout@v5 + with: + fetch-depth: 0 + + - name: Install Node.js + uses: actions/setup-node@v5 + with: + node-version: 24 + cache: "npm" + + - name: Install Dependencies + run: npm install + + - name: Set dev version + shell: bash + run: npm version "${{ needs.prepare.outputs.dev_version }}" --no-git-tag-version --allow-same-version + + - name: Build Frontend & Type Check + run: | + npx tsc + npx vite build + + - name: Package Linux dev artifacts + run: | + npx electron-builder --linux --publish never '--config.publish.channel=dev' '--config.artifactName=${productName}-dev-linux.${ext}' + + - name: Upload Linux assets to fixed release + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + shell: bash + run: | + mapfile -t assets < <(find release -maxdepth 1 -type f | sort) + if [ "${#assets[@]}" -eq 0 ]; then + echo "No release files found in ./release" + exit 1 + fi + gh release upload "$FIXED_DEV_TAG" "${assets[@]}" --repo "$GITHUB_REPOSITORY" --clobber + + dev-win-x64: + needs: prepare + runs-on: windows-latest + steps: + - name: Check out git repository + uses: actions/checkout@v5 + with: + fetch-depth: 0 + + - name: Install Node.js + uses: actions/setup-node@v5 + with: + node-version: 24 + cache: "npm" + + - name: Install Dependencies + run: npm install + + - name: Set dev version + shell: bash + run: npm version "${{ needs.prepare.outputs.dev_version }}" --no-git-tag-version --allow-same-version + + - name: Build Frontend & Type Check + run: | + npx tsc + npx vite build + + - name: Package Windows x64 dev artifacts + run: | + npx electron-builder --win nsis --x64 --publish never '--config.publish.channel=dev' '--config.artifactName=${productName}-dev-x64-Setup.${ext}' + + - name: Upload Windows x64 assets to fixed release + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + shell: bash + run: | + mapfile -t assets < <(find release -maxdepth 1 -type f | sort) + if [ "${#assets[@]}" -eq 0 ]; then + echo "No release files found in ./release" + exit 1 + fi + gh release upload "$FIXED_DEV_TAG" "${assets[@]}" --repo "$GITHUB_REPOSITORY" --clobber + + dev-win-arm64: + needs: prepare + runs-on: windows-latest + steps: + - name: Check out git repository + uses: actions/checkout@v5 + with: + fetch-depth: 0 + + - name: Install Node.js + uses: actions/setup-node@v5 + with: + node-version: 24 + cache: "npm" + + - name: Install Dependencies + run: npm install + + - name: Set dev version + shell: bash + run: npm version "${{ needs.prepare.outputs.dev_version }}" --no-git-tag-version --allow-same-version + + - name: Build Frontend & Type Check + run: | + npx tsc + npx vite build + + - name: Package Windows arm64 dev artifacts + run: | + npx electron-builder --win nsis --arm64 --publish never '--config.publish.channel=dev-arm64' '--config.artifactName=${productName}-dev-arm64-Setup.${ext}' + + - name: Upload Windows arm64 assets to fixed release + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + shell: bash + run: | + mapfile -t assets < <(find release -maxdepth 1 -type f | sort) + if [ "${#assets[@]}" -eq 0 ]; then + echo "No release files found in ./release" + exit 1 + fi + gh release upload "$FIXED_DEV_TAG" "${assets[@]}" --repo "$GITHUB_REPOSITORY" --clobber diff --git a/.github/workflows/preview-nightly-main.yml b/.github/workflows/preview-nightly-main.yml new file mode 100644 index 0000000..f774bbd --- /dev/null +++ b/.github/workflows/preview-nightly-main.yml @@ -0,0 +1,197 @@ +name: Preview Nightly + +on: + schedule: + # GitHub Actions schedule uses UTC. 16:00 UTC = 北京时间次日 00:00 + - cron: "0 16 * * *" + workflow_dispatch: + +permissions: + contents: write + +env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true" + +jobs: + prepare: + runs-on: ubuntu-latest + outputs: + should_build: ${{ steps.meta.outputs.should_build }} + preview_version: ${{ steps.meta.outputs.preview_version }} + steps: + - name: Check out git repository + uses: actions/checkout@v5 + with: + fetch-depth: 0 + + - name: Install Node.js + uses: actions/setup-node@v5 + with: + node-version: 24 + cache: "npm" + + - name: Decide whether to build and generate preview version + id: meta + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + shell: bash + run: | + set -euo pipefail + + git fetch origin main --depth=1 + COMMITS_24H="$(git rev-list --count --since='24 hours ago' origin/main)" + + if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then + SHOULD_BUILD=true + elif [ "$COMMITS_24H" -gt 0 ]; then + SHOULD_BUILD=true + else + SHOULD_BUILD=false + fi + + BASE_VERSION="$(node -p "require('./package.json').version.split('-')[0]")" + YEAR_2="$(TZ=Asia/Shanghai date +%y)" + EXISTING_COUNT="$(gh api --paginate "repos/${GITHUB_REPOSITORY}/releases" --jq "[.[].tag_name | select(test(\"^v${BASE_VERSION}-preview[.]${YEAR_2}[.][0-9]+$\"))] | length")" + NEXT_COUNT=$((EXISTING_COUNT + 1)) + PREVIEW_VERSION="${BASE_VERSION}-preview.${YEAR_2}.${NEXT_COUNT}" + + echo "should_build=$SHOULD_BUILD" >> "$GITHUB_OUTPUT" + echo "preview_version=$PREVIEW_VERSION" >> "$GITHUB_OUTPUT" + echo "Preview version: $PREVIEW_VERSION (commits in last 24h on main: $COMMITS_24H)" + + preview-mac-arm64: + needs: prepare + if: needs.prepare.outputs.should_build == 'true' + runs-on: macos-14 + steps: + - name: Check out git repository + uses: actions/checkout@v5 + with: + fetch-depth: 0 + + - name: Install Node.js + uses: actions/setup-node@v5 + with: + node-version: 24 + cache: "npm" + + - name: Install Dependencies + run: npm install + + - name: Set preview version + shell: bash + run: npm version "${{ needs.prepare.outputs.preview_version }}" --no-git-tag-version --allow-same-version + + - name: Build Frontend & Type Check + run: | + npx tsc + npx vite build + + - name: Package and Publish macOS arm64 preview + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + CSC_IDENTITY_AUTO_DISCOVERY: "false" + run: | + npx electron-builder --mac dmg --arm64 --publish always '--config.publish.releaseType=prerelease' '--config.publish.channel=preview' + + preview-linux: + needs: prepare + if: needs.prepare.outputs.should_build == 'true' + runs-on: ubuntu-latest + steps: + - name: Check out git repository + uses: actions/checkout@v5 + with: + fetch-depth: 0 + + - name: Install Node.js + uses: actions/setup-node@v5 + with: + node-version: 24 + cache: "npm" + + - name: Install Dependencies + run: npm install + + - name: Set preview version + shell: bash + run: npm version "${{ needs.prepare.outputs.preview_version }}" --no-git-tag-version --allow-same-version + + - name: Build Frontend & Type Check + run: | + npx tsc + npx vite build + + - name: Package and Publish Linux preview + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + npx electron-builder --linux --publish always '--config.publish.releaseType=prerelease' '--config.publish.channel=preview' + + preview-win-x64: + needs: prepare + if: needs.prepare.outputs.should_build == 'true' + runs-on: windows-latest + steps: + - name: Check out git repository + uses: actions/checkout@v5 + with: + fetch-depth: 0 + + - name: Install Node.js + uses: actions/setup-node@v5 + with: + node-version: 24 + cache: "npm" + + - name: Install Dependencies + run: npm install + + - name: Set preview version + shell: bash + run: npm version "${{ needs.prepare.outputs.preview_version }}" --no-git-tag-version --allow-same-version + + - name: Build Frontend & Type Check + run: | + npx tsc + npx vite build + + - name: Package and Publish Windows x64 preview + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + npx electron-builder --win nsis --x64 --publish always '--config.publish.releaseType=prerelease' '--config.publish.channel=preview' '--config.artifactName=${productName}-${version}-x64-Setup.${ext}' + + preview-win-arm64: + needs: prepare + if: needs.prepare.outputs.should_build == 'true' + runs-on: windows-latest + steps: + - name: Check out git repository + uses: actions/checkout@v5 + with: + fetch-depth: 0 + + - name: Install Node.js + uses: actions/setup-node@v5 + with: + node-version: 24 + cache: "npm" + + - name: Install Dependencies + run: npm install + + - name: Set preview version + shell: bash + run: npm version "${{ needs.prepare.outputs.preview_version }}" --no-git-tag-version --allow-same-version + + - name: Build Frontend & Type Check + run: | + npx tsc + npx vite build + + - name: Package and Publish Windows arm64 preview + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + npx electron-builder --win nsis --arm64 --publish always '--config.publish.releaseType=prerelease' '--config.publish.channel=preview-arm64' '--config.artifactName=${productName}-${version}-arm64-Setup.${ext}' diff --git a/.github/workflows/security-scan.yml b/.github/workflows/security-scan.yml index 82c328c..e598698 100644 --- a/.github/workflows/security-scan.yml +++ b/.github/workflows/security-scan.yml @@ -2,8 +2,10 @@ name: Security Scan on: schedule: - - cron: '0 2 * * *' # 每天 UTC 02:00(北京时间 10:00) - workflow_dispatch: # 支持手动触发 + - cron: '0 2 * * *' # 每天 UTC 02:00 + workflow_dispatch: # 手动触发 + pull_request: # PR 时触发 + branches: [ main, dev ] permissions: contents: read @@ -31,18 +33,14 @@ jobs: uses: actions/setup-node@v4 with: node-version: '20' - - - name: Install pnpm - uses: pnpm/action-setup@v3 - with: - version: 9 + cache: 'npm' # 使用 npm 缓存加速 - name: Install dependencies - run: pnpm install --no-frozen-lockfile + run: npm ci --ignore-scripts # 1. npm audit - 检查依赖漏洞 - name: Dependency vulnerability audit - run: pnpm audit --audit-level=moderate + run: npm audit --audit-level=moderate continue-on-error: true # 2. CodeQL 静态分析 @@ -67,7 +65,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} continue-on-error: true - # 动态获取所有分支并扫描(排除已在 matrix 中的) + # 动态获取所有分支并扫描 scan-all-branches: name: Scan additional branches runs-on: ubuntu-latest @@ -77,19 +75,13 @@ jobs: with: fetch-depth: 0 - - name: List all branches - id: branches - run: | - git branch -r | grep -v HEAD | sed 's|origin/||' | tr -d ' ' | while read branch; do - echo "Branch: $branch" - done - - - name: Run pnpm audit on all branches + - name: Run npm audit on all branches run: | git branch -r | grep -v HEAD | sed 's|origin/||' | tr -d ' ' | while read branch; do echo "===== Auditing branch: $branch =====" git checkout "$branch" 2>/dev/null || continue - pnpm install --frozen-lockfile --silent 2>/dev/null || npm install --silent 2>/dev/null || true - pnpm audit --audit-level=moderate 2>/dev/null || true + # 尝试安装并审计 + npm ci --ignore-scripts --silent 2>/dev/null || npm install --ignore-scripts --silent 2>/dev/null || true + npm audit --audit-level=moderate 2>/dev/null || true done - continue-on-error: true + continue-on-error: true \ No newline at end of file diff --git a/.gitignore b/.gitignore index d026e51..95745fb 100644 --- a/.gitignore +++ b/.gitignore @@ -70,4 +70,5 @@ resources/wx_send 概述.md pnpm-lock.yaml /pnpm-workspace.yaml -wechat-research-site \ No newline at end of file +wechat-research-site +.codex \ No newline at end of file diff --git a/electron/main.ts b/electron/main.ts index e9a353a..11c55f7 100644 --- a/electron/main.ts +++ b/electron/main.ts @@ -36,10 +36,41 @@ import { bizService } from './services/bizService' autoUpdater.autoDownload = false autoUpdater.autoInstallOnAppQuit = true autoUpdater.disableDifferentialDownload = true // 禁用差分更新,强制全量下载 -// Windows x64 与 arm64 使用不同更新通道,避免 latest.yml 互相覆盖导致下错架构安装包。 -if (process.platform === 'win32' && process.arch === 'arm64') { - autoUpdater.channel = 'latest-arm64' +// 更新通道策略: +// - 稳定版(如 4.3.0)默认走 latest +// - 预览版(如 4.3.0-preview.26.1)默认走 preview +// - 开发版(如 4.3.0-dev.26.3.4)默认走 dev +// - 用户可在设置页切换稳定/预览/开发,切换后即时生效 +// 同时区分 Windows x64 / arm64,避免更新清单互相覆盖。 +const appVersion = app.getVersion() +const defaultUpdateTrack: 'stable' | 'preview' | 'dev' = (() => { + if (/-preview\.\d+\.\d+$/i.test(appVersion)) return 'preview' + if (/-dev\.\d+\.\d+\.\d+$/i.test(appVersion)) return 'dev' + if (/(alpha|beta|rc)/i.test(appVersion)) return 'dev' + return 'stable' +})() +const isPrereleaseBuild = defaultUpdateTrack !== 'stable' +let configService: ConfigService | null = null + +const normalizeUpdateTrack = (raw: unknown): 'stable' | 'preview' | 'dev' | null => { + if (raw === 'stable' || raw === 'preview' || raw === 'dev') return raw + return null } + +const applyAutoUpdateChannel = (reason: 'startup' | 'settings' = 'startup') => { + const configuredTrack = normalizeUpdateTrack(configService?.get('updateChannel')) + const track: 'stable' | 'preview' | 'dev' = configuredTrack || defaultUpdateTrack + const baseUpdateChannel = track === 'stable' ? 'latest' : track + autoUpdater.allowPrerelease = track !== 'stable' + autoUpdater.allowDowngrade = isPrereleaseBuild && track === 'stable' + autoUpdater.channel = + process.platform === 'win32' && process.arch === 'arm64' + ? `${baseUpdateChannel}-arm64` + : baseUpdateChannel + console.log(`[Update](${reason}) 当前版本 ${appVersion},渠道偏好: ${track},更新通道: ${autoUpdater.channel}`) +} + +applyAutoUpdateChannel('startup') const AUTO_UPDATE_ENABLED = process.env.AUTO_UPDATE_ENABLED === 'true' || process.env.AUTO_UPDATE_ENABLED === '1' || @@ -87,7 +118,6 @@ function sanitizePathEnv() { sanitizePathEnv() // 单例服务 -let configService: ConfigService | null = null // 协议窗口实例 let agreementWindow: BrowserWindow | null = null @@ -1118,6 +1148,9 @@ function registerIpcHandlers() { ipcMain.handle('config:set', async (_, key: string, value: any) => { const result = configService?.set(key as any, value) + if (key === 'updateChannel') { + applyAutoUpdateChannel('settings') + } void messagePushService.handleConfigChanged(key) return result }) @@ -2742,6 +2775,7 @@ app.whenReady().then(async () => { // 初始化配置服务 updateSplashProgress(5, '正在加载配置...') configService = new ConfigService() + applyAutoUpdateChannel('startup') // 将用户主题配置推送给 Splash 窗口 if (splashWindow && !splashWindow.isDestroyed()) { diff --git a/electron/services/cloudControlService.ts b/electron/services/cloudControlService.ts index c43dcd2..39b3345 100644 --- a/electron/services/cloudControlService.ts +++ b/electron/services/cloudControlService.ts @@ -15,15 +15,31 @@ class CloudControlService { private timer: NodeJS.Timeout | null = null private pages: Set = new Set() private platformVersionCache: string | null = null + private pendingReports: UsageStats[] = [] + private flushInProgress = false + private retryDelayMs = 5_000 + private consecutiveFailures = 0 + private circuitOpenedAt = 0 + private nextDelayOverrideMs: number | null = null + private initialized = false + + private static readonly BASE_FLUSH_MS = 300_000 + private static readonly JITTER_MS = 30_000 + private static readonly MAX_BUFFER_REPORTS = 200 + private static readonly MAX_BATCH_REPORTS = 20 + private static readonly MAX_RETRY_MS = 120_000 + private static readonly CIRCUIT_FAIL_THRESHOLD = 5 + private static readonly CIRCUIT_COOLDOWN_MS = 120_000 async init() { + if (this.initialized) return + this.initialized = true this.deviceId = this.getDeviceId() await wcdbService.cloudInit(300) - await this.reportOnline() - - this.timer = setInterval(() => { - this.reportOnline() - }, 300000) + this.enqueueCurrentReport() + await this.flushQueue(true) + this.scheduleNextFlush(this.nextDelayOverrideMs ?? undefined) + this.nextDelayOverrideMs = null } private getDeviceId(): string { @@ -33,8 +49,8 @@ class CloudControlService { return crypto.createHash('md5').update(machineId).digest('hex') } - private async reportOnline() { - const data: UsageStats = { + private buildCurrentReport(): UsageStats { + return { appVersion: app.getVersion(), platform: this.getPlatformVersion(), deviceId: this.deviceId, @@ -42,11 +58,69 @@ class CloudControlService { online: true, pages: Array.from(this.pages) } + } - await wcdbService.cloudReport(JSON.stringify(data)) + private enqueueCurrentReport() { + const report = this.buildCurrentReport() + this.pendingReports.push(report) + if (this.pendingReports.length > CloudControlService.MAX_BUFFER_REPORTS) { + this.pendingReports.splice(0, this.pendingReports.length - CloudControlService.MAX_BUFFER_REPORTS) + } this.pages.clear() } + private isCircuitOpen(nowMs: number): boolean { + if (this.circuitOpenedAt <= 0) return false + return nowMs-this.circuitOpenedAt < CloudControlService.CIRCUIT_COOLDOWN_MS + } + + private scheduleNextFlush(delayMs?: number) { + if (this.timer) { + clearTimeout(this.timer) + this.timer = null + } + const jitter = Math.floor(Math.random() * CloudControlService.JITTER_MS) + const nextDelay = Math.max(1_000, Number(delayMs) > 0 ? Number(delayMs) : CloudControlService.BASE_FLUSH_MS + jitter) + this.timer = setTimeout(() => { + this.enqueueCurrentReport() + this.flushQueue(false).finally(() => { + this.scheduleNextFlush(this.nextDelayOverrideMs ?? undefined) + this.nextDelayOverrideMs = null + }) + }, nextDelay) + } + + private async flushQueue(force: boolean) { + if (this.flushInProgress) return + if (this.pendingReports.length === 0) return + const now = Date.now() + if (!force && this.isCircuitOpen(now)) { + return + } + this.flushInProgress = true + try { + while (this.pendingReports.length > 0) { + const batch = this.pendingReports.slice(0, CloudControlService.MAX_BATCH_REPORTS) + const result = await wcdbService.cloudReport(JSON.stringify(batch)) + if (!result || result.success !== true) { + this.consecutiveFailures += 1 + this.retryDelayMs = Math.min(CloudControlService.MAX_RETRY_MS, this.retryDelayMs * 2) + if (this.consecutiveFailures >= CloudControlService.CIRCUIT_FAIL_THRESHOLD) { + this.circuitOpenedAt = Date.now() + } + this.nextDelayOverrideMs = this.retryDelayMs + return + } + this.pendingReports.splice(0, batch.length) + this.consecutiveFailures = 0 + this.retryDelayMs = 5_000 + this.circuitOpenedAt = 0 + } + } finally { + this.flushInProgress = false + } + } + private getPlatformVersion(): string { if (this.platformVersionCache) { return this.platformVersionCache @@ -146,9 +220,16 @@ class CloudControlService { stop() { if (this.timer) { - clearInterval(this.timer) + clearTimeout(this.timer) this.timer = null } + this.pendingReports = [] + this.flushInProgress = false + this.retryDelayMs = 5_000 + this.consecutiveFailures = 0 + this.circuitOpenedAt = 0 + this.nextDelayOverrideMs = null + this.initialized = false wcdbService.cloudStop() } @@ -158,4 +239,3 @@ class CloudControlService { } export const cloudControlService = new CloudControlService() - diff --git a/electron/services/config.ts b/electron/services/config.ts index 5fdd609..3269b0b 100644 --- a/electron/services/config.ts +++ b/electron/services/config.ts @@ -45,6 +45,7 @@ interface ConfigSchema { // 更新相关 ignoredUpdateVersion: string + updateChannel: 'auto' | 'stable' | 'preview' | 'dev' // 通知 notificationEnabled: boolean @@ -119,6 +120,7 @@ export class ConfigService { authUseHello: false, authHelloSecret: '', ignoredUpdateVersion: '', + updateChannel: 'auto', notificationEnabled: true, notificationPosition: 'top-right', notificationFilterMode: 'all', diff --git a/electron/services/wcdbCore.ts b/electron/services/wcdbCore.ts index 4f0d97b..b5d039b 100644 --- a/electron/services/wcdbCore.ts +++ b/electron/services/wcdbCore.ts @@ -2681,7 +2681,7 @@ export class WcdbCore { } try { const outCursor = [0] - const result = this.wcdbOpenMessageCursorLite( + let result = this.wcdbOpenMessageCursorLite( this.handle, sessionId, batchSize, @@ -2690,6 +2690,29 @@ export class WcdbCore { endTimestamp, outCursor ) + + // result=-3 表示 WCDB_STATUS_NO_MESSAGE_DB:消息数据库缓存为空 + // 自动强制重连并重试一次 + if (result === -3 && outCursor[0] <= 0) { + this.writeLog('openMessageCursorLite: result=-3 (no message db), attempting forceReopen...', true) + const reopened = await this.forceReopen() + if (reopened && this.handle !== null) { + outCursor[0] = 0 + result = this.wcdbOpenMessageCursorLite( + this.handle, + sessionId, + batchSize, + ascending ? 1 : 0, + beginTimestamp, + endTimestamp, + outCursor + ) + this.writeLog(`openMessageCursorLite retry after forceReopen: result=${result} cursor=${outCursor[0]}`, true) + } else { + this.writeLog('openMessageCursorLite forceReopen failed, giving up', true) + } + } + if (result !== 0 || outCursor[0] <= 0) { await this.printLogs(true) this.writeLog( diff --git a/package-lock.json b/package-lock.json index 95ea5a4..731af00 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "4.3.0", "hasInstallScript": true, "dependencies": { - "echarts": "^5.5.1", + "echarts": "^6.0.0", "echarts-for-react": "^3.0.2", "electron-store": "^10.0.0", "electron-updater": "^6.3.9", @@ -20,7 +20,7 @@ "jieba-wasm": "^2.2.0", "jszip": "^3.10.1", "koffi": "^2.9.0", - "lucide-react": "^0.562.0", + "lucide-react": "^1.7.0", "react": "^19.2.3", "react-dom": "^19.2.3", "react-markdown": "^10.1.0", @@ -40,10 +40,10 @@ "@vitejs/plugin-react": "^4.3.4", "electron": "^39.2.7", "electron-builder": "^26.8.1", - "sass": "^1.83.0", + "sass": "^1.98.0", "sharp": "^0.34.5", - "typescript": "^5.6.3", - "vite": "^6.0.5", + "typescript": "^6.0.2", + "vite": "^7.0.0", "vite-plugin-electron": "^0.28.8", "vite-plugin-electron-renderer": "^0.14.6" } @@ -824,9 +824,9 @@ "optional": true }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", - "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "version": "0.27.5", + "resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.27.5.tgz", + "integrity": "sha512-nGsF/4C7uzUj+Nj/4J+Zt0bYQ6bz33Phz8Lb2N80Mti1HjGclTJdXZ+9APC4kLvONbjxN1zfvYNd8FEcbBK/MQ==", "cpu": [ "ppc64" ], @@ -841,9 +841,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.25.12.tgz", - "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "version": "0.27.5", + "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.27.5.tgz", + "integrity": "sha512-Cv781jd0Rfj/paoNrul1/r4G0HLvuFKYh7C9uHZ2Pl8YXstzvCyyeWENTFR9qFnRzNMCjXmsulZuvosDg10Mog==", "cpu": [ "arm" ], @@ -858,9 +858,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", - "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "version": "0.27.5", + "resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.27.5.tgz", + "integrity": "sha512-Oeghq+XFgh1pUGd1YKs4DDoxzxkoUkvko+T/IVKwlghKLvvjbGFB3ek8VEDBmNvqhwuL0CQS3cExdzpmUyIrgA==", "cpu": [ "arm64" ], @@ -875,9 +875,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.25.12.tgz", - "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "version": "0.27.5", + "resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.27.5.tgz", + "integrity": "sha512-nQD7lspbzerlmtNOxYMFAGmhxgzn8Z7m9jgFkh6kpkjsAhZee1w8tJW3ZlW+N9iRePz0oPUDrYrXidCPSImD0Q==", "cpu": [ "x64" ], @@ -892,9 +892,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", - "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "version": "0.27.5", + "resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.27.5.tgz", + "integrity": "sha512-I+Ya/MgC6rr8oRWGRDF3BXDfP8K1BVUggHqN6VI2lUZLdDi1IM1v2cy0e3lCPbP+pVcK3Tv8cgUhHse1kaNZZw==", "cpu": [ "arm64" ], @@ -909,9 +909,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", - "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "version": "0.27.5", + "resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.27.5.tgz", + "integrity": "sha512-MCjQUtC8wWJn/pIPM7vQaO69BFgwPD1jriEdqwTCKzWjGgkMbcg+M5HzrOhPhuYe1AJjXlHmD142KQf+jnYj8A==", "cpu": [ "x64" ], @@ -926,9 +926,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", - "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "version": "0.27.5", + "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.5.tgz", + "integrity": "sha512-X6xVS+goSH0UelYXnuf4GHLwpOdc8rgK/zai+dKzBMnncw7BTQIwquOodE7EKvY2UVUetSqyAfyZC1D+oqLQtg==", "cpu": [ "arm64" ], @@ -943,9 +943,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", - "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "version": "0.27.5", + "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.27.5.tgz", + "integrity": "sha512-233X1FGo3a8x1ekLB6XT69LfZ83vqz+9z3TSEQCTYfMNY880A97nr81KbPcAMl9rmOFp11wO0dP+eB18KU/Ucg==", "cpu": [ "x64" ], @@ -960,9 +960,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", - "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "version": "0.27.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.27.5.tgz", + "integrity": "sha512-0wkVrYHG4sdCCN/bcwQ7yYMXACkaHc3UFeaEOwSVW6e5RycMageYAFv+JS2bKLwHyeKVUvtoVH+5/RHq0fgeFw==", "cpu": [ "arm" ], @@ -977,9 +977,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", - "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "version": "0.27.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.27.5.tgz", + "integrity": "sha512-euKkilsNOv7x/M1NKsx5znyprbpsRFIzTV6lWziqJch7yWYayfLtZzDxDTl+LSQDJYAjd9TVb/Kt5UKIrj2e4A==", "cpu": [ "arm64" ], @@ -994,9 +994,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", - "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "version": "0.27.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.27.5.tgz", + "integrity": "sha512-hVRQX4+P3MS36NxOy24v/Cdsimy/5HYePw+tmPqnNN1fxV0bPrFWR6TMqwXPwoTM2VzbkA+4lbHWUKDd5ZDA/w==", "cpu": [ "ia32" ], @@ -1011,9 +1011,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", - "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "version": "0.27.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.27.5.tgz", + "integrity": "sha512-mKqqRuOPALI8nDzhOBmIS0INvZOOFGGg5n1osGIXAx8oersceEbKd4t1ACNTHM3sJBXGFAlEgqM+svzjPot+ZQ==", "cpu": [ "loong64" ], @@ -1028,9 +1028,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", - "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "version": "0.27.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.27.5.tgz", + "integrity": "sha512-EE/QXH9IyaAj1qeuIV5+/GZkBTipgGO782Ff7Um3vPS9cvLhJJeATy4Ggxikz2inZ46KByamMn6GqtqyVjhenA==", "cpu": [ "mips64el" ], @@ -1045,9 +1045,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", - "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "version": "0.27.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.27.5.tgz", + "integrity": "sha512-0V2iF1RGxBf1b7/BjurA5jfkl7PtySjom1r6xOK2q9KWw/XCpAdtB6KNMO+9xx69yYfSCRR9FE0TyKfHA2eQMw==", "cpu": [ "ppc64" ], @@ -1062,9 +1062,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", - "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "version": "0.27.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.27.5.tgz", + "integrity": "sha512-rYxThBx6G9HN6tFNuvB/vykeLi4VDsm5hE5pVwzqbAjZEARQrWu3noZSfbEnPZ/CRXP3271GyFk/49up2W190g==", "cpu": [ "riscv64" ], @@ -1079,9 +1079,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", - "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "version": "0.27.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.27.5.tgz", + "integrity": "sha512-uEP2q/4qgd8goEUc4QIdU/1P2NmEtZ/zX5u3OpLlCGhJIuBIv0s0wr7TB2nBrd3/A5XIdEkkS5ZLF0ULuvaaYQ==", "cpu": [ "s390x" ], @@ -1096,9 +1096,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", - "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "version": "0.27.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.27.5.tgz", + "integrity": "sha512-+Gq47Wqq6PLOOZuBzVSII2//9yyHNKZLuwfzCemqexqOQCSz0zy0O26kIzyp9EMNMK+nZ0tFHBZrCeVUuMs/ew==", "cpu": [ "x64" ], @@ -1113,9 +1113,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", - "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "version": "0.27.5", + "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.5.tgz", + "integrity": "sha512-3F/5EG8VHfN/I+W5cO1/SV2H9Q/5r7vcHabMnBqhHK2lTWOh3F8vixNzo8lqxrlmBtZVFpW8pmITHnq54+Tq4g==", "cpu": [ "arm64" ], @@ -1130,9 +1130,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", - "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "version": "0.27.5", + "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.27.5.tgz", + "integrity": "sha512-28t+Sj3CPN8vkMOlZotOmDgilQwVvxWZl7b8rxpn73Tt/gCnvrHxQUMng4uu3itdFvrtba/1nHejvxqz8xgEMA==", "cpu": [ "x64" ], @@ -1147,9 +1147,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", - "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "version": "0.27.5", + "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.5.tgz", + "integrity": "sha512-Doz/hKtiuVAi9hMsBMpwBANhIZc8l238U2Onko3t2xUp8xtM0ZKdDYHMnm/qPFVthY8KtxkXaocwmMh6VolzMA==", "cpu": [ "arm64" ], @@ -1164,9 +1164,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", - "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "version": "0.27.5", + "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.27.5.tgz", + "integrity": "sha512-WfGVaa1oz5A7+ZFPkERIbIhKT4olvGl1tyzTRaB5yoZRLqC0KwaO95FeZtOdQj/oKkjW57KcVF944m62/0GYtA==", "cpu": [ "x64" ], @@ -1181,9 +1181,9 @@ } }, "node_modules/@esbuild/openharmony-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", - "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "version": "0.27.5", + "resolved": "https://registry.npmmirror.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.5.tgz", + "integrity": "sha512-Xh+VRuh6OMh3uJ0JkCjI57l+DVe7VRGBYymen8rFPnTVgATBwA6nmToxM2OwTlSvrnWpPKkrQUj93+K9huYC6A==", "cpu": [ "arm64" ], @@ -1198,9 +1198,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", - "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "version": "0.27.5", + "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.27.5.tgz", + "integrity": "sha512-aC1gpJkkaUADHuAdQfuVTnqVUTLqqUNhAvEwHwVWcnVVZvNlDPGA0UveZsfXJJ9T6k9Po4eHi3c02gbdwO3g6w==", "cpu": [ "x64" ], @@ -1215,9 +1215,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", - "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "version": "0.27.5", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.27.5.tgz", + "integrity": "sha512-0UNx2aavV0fk6UpZcwXFLztA2r/k9jTUa7OW7SAea1VYUhkug99MW1uZeXEnPn5+cHOd0n8myQay6TlFnBR07w==", "cpu": [ "arm64" ], @@ -1232,9 +1232,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", - "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "version": "0.27.5", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.27.5.tgz", + "integrity": "sha512-5nlJ3AeJWCTSzR7AEqVjT/faWyqKU86kCi1lLmxVqmNR+j4HrYdns+eTGjS/vmrzCIe8inGQckUadvS0+JkKdQ==", "cpu": [ "ia32" ], @@ -1249,9 +1249,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", - "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", + "version": "0.27.5", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.27.5.tgz", + "integrity": "sha512-PWypQR+d4FLfkhBIV+/kHsUELAnMpx1bRvvsn3p+/sAERbnCzFrtDRG2Xw5n+2zPxBK2+iaP+vetsRl4Ti7WgA==", "cpu": [ "x64" ], @@ -2428,9 +2428,9 @@ "license": "MIT" }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.60.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.0.tgz", - "integrity": "sha512-WOhNW9K8bR3kf4zLxbfg6Pxu2ybOUbB2AjMDHSQx86LIF4rH4Ft7vmMwNt0loO0eonglSNy4cpD3MKXXKQu0/A==", + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.1.tgz", + "integrity": "sha512-d6FinEBLdIiK+1uACUttJKfgZREXrF0Qc2SmLII7W2AD8FfiZ9Wjd+rD/iRuf5s5dWrr1GgwXCvPqOuDquOowA==", "cpu": [ "arm" ], @@ -2442,9 +2442,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.60.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.0.tgz", - "integrity": "sha512-u6JHLll5QKRvjciE78bQXDmqRqNs5M/3GVqZeMwvmjaNODJih/WIrJlFVEihvV0MiYFmd+ZyPr9wxOVbPAG2Iw==", + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.1.tgz", + "integrity": "sha512-YjG/EwIDvvYI1YvYbHvDz/BYHtkY4ygUIXHnTdLhG+hKIQFBiosfWiACWortsKPKU/+dUwQQCKQM3qrDe8c9BA==", "cpu": [ "arm64" ], @@ -2456,9 +2456,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.60.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.0.tgz", - "integrity": "sha512-qEF7CsKKzSRc20Ciu2Zw1wRrBz4g56F7r/vRwY430UPp/nt1x21Q/fpJ9N5l47WWvJlkNCPJz3QRVw008fi7yA==", + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.1.tgz", + "integrity": "sha512-mjCpF7GmkRtSJwon+Rq1N8+pI+8l7w5g9Z3vWj4T7abguC4Czwi3Yu/pFaLvA3TTeMVjnu3ctigusqWUfjZzvw==", "cpu": [ "arm64" ], @@ -2470,9 +2470,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.60.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.0.tgz", - "integrity": "sha512-WADYozJ4QCnXCH4wPB+3FuGmDPoFseVCUrANmA5LWwGmC6FL14BWC7pcq+FstOZv3baGX65tZ378uT6WG8ynTw==", + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.1.tgz", + "integrity": "sha512-haZ7hJ1JT4e9hqkoT9R/19XW2QKqjfJVv+i5AGg57S+nLk9lQnJ1F/eZloRO3o9Scy9CM3wQ9l+dkXtcBgN5Ew==", "cpu": [ "x64" ], @@ -2484,9 +2484,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.60.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.0.tgz", - "integrity": "sha512-6b8wGHJlDrGeSE3aH5mGNHBjA0TTkxdoNHik5EkvPHCt351XnigA4pS7Wsj/Eo9Y8RBU6f35cjN9SYmCFBtzxw==", + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.1.tgz", + "integrity": "sha512-czw90wpQq3ZsAVBlinZjAYTKduOjTywlG7fEeWKUA7oCmpA8xdTkxZZlwNJKWqILlq0wehoZcJYfBvOyhPTQ6w==", "cpu": [ "arm64" ], @@ -2498,9 +2498,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.60.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.0.tgz", - "integrity": "sha512-h25Ga0t4jaylMB8M/JKAyrvvfxGRjnPQIR8lnCayyzEjEOx2EJIlIiMbhpWxDRKGKF8jbNH01NnN663dH638mA==", + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.1.tgz", + "integrity": "sha512-KVB2rqsxTHuBtfOeySEyzEOB7ltlB/ux38iu2rBQzkjbwRVlkhAGIEDiiYnO2kFOkJp+Z7pUXKyrRRFuFUKt+g==", "cpu": [ "x64" ], @@ -2512,9 +2512,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.60.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.0.tgz", - "integrity": "sha512-RzeBwv0B3qtVBWtcuABtSuCzToo2IEAIQrcyB/b2zMvBWVbjo8bZDjACUpnaafaxhTw2W+imQbP2BD1usasK4g==", + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.1.tgz", + "integrity": "sha512-L+34Qqil+v5uC0zEubW7uByo78WOCIrBvci69E7sFASRl0X7b/MB6Cqd1lky/CtcSVTydWa2WZwFuWexjS5o6g==", "cpu": [ "arm" ], @@ -2526,9 +2526,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.60.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.0.tgz", - "integrity": "sha512-Sf7zusNI2CIU1HLzuu9Tc5YGAHEZs5Lu7N1ssJG4Tkw6e0MEsN7NdjUDDfGNHy2IU+ENyWT+L2obgWiguWibWQ==", + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.1.tgz", + "integrity": "sha512-n83O8rt4v34hgFzlkb1ycniJh7IR5RCIqt6mz1VRJD6pmhRi0CXdmfnLu9dIUS6buzh60IvACM842Ffb3xd6Gg==", "cpu": [ "arm" ], @@ -2540,9 +2540,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.60.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.0.tgz", - "integrity": "sha512-DX2x7CMcrJzsE91q7/O02IJQ5/aLkVtYFryqCjduJhUfGKG6yJV8hxaw8pZa93lLEpPTP/ohdN4wFz7yp/ry9A==", + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.1.tgz", + "integrity": "sha512-Nql7sTeAzhTAja3QXeAI48+/+GjBJ+QmAH13snn0AJSNL50JsDqotyudHyMbO2RbJkskbMbFJfIJKWA6R1LCJQ==", "cpu": [ "arm64" ], @@ -2554,9 +2554,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.60.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.0.tgz", - "integrity": "sha512-09EL+yFVbJZlhcQfShpswwRZ0Rg+z/CsSELFCnPt3iK+iqwGsI4zht3secj5vLEs957QvFFXnzAT0FFPIxSrkQ==", + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.1.tgz", + "integrity": "sha512-+pUymDhd0ys9GcKZPPWlFiZ67sTWV5UU6zOJat02M1+PiuSGDziyRuI/pPue3hoUwm2uGfxdL+trT6Z9rxnlMA==", "cpu": [ "arm64" ], @@ -2568,9 +2568,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.60.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.0.tgz", - "integrity": "sha512-i9IcCMPr3EXm8EQg5jnja0Zyc1iFxJjZWlb4wr7U2Wx/GrddOuEafxRdMPRYVaXjgbhvqalp6np07hN1w9kAKw==", + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.1.tgz", + "integrity": "sha512-VSvgvQeIcsEvY4bKDHEDWcpW4Yw7BtlKG1GUT4FzBUlEKQK0rWHYBqQt6Fm2taXS+1bXvJT6kICu5ZwqKCnvlQ==", "cpu": [ "loong64" ], @@ -2582,9 +2582,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.60.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.0.tgz", - "integrity": "sha512-DGzdJK9kyJ+B78MCkWeGnpXJ91tK/iKA6HwHxF4TAlPIY7GXEvMe8hBFRgdrR9Ly4qebR/7gfUs9y2IoaVEyog==", + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.1.tgz", + "integrity": "sha512-4LqhUomJqwe641gsPp6xLfhqWMbQV04KtPp7/dIp0nzPxAkNY1AbwL5W0MQpcalLYk07vaW9Kp1PBhdpZYYcEw==", "cpu": [ "loong64" ], @@ -2596,9 +2596,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.60.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.0.tgz", - "integrity": "sha512-RwpnLsqC8qbS8z1H1AxBA1H6qknR4YpPR9w2XX0vo2Sz10miu57PkNcnHVaZkbqyw/kUWfKMI73jhmfi9BRMUQ==", + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.1.tgz", + "integrity": "sha512-tLQQ9aPvkBxOc/EUT6j3pyeMD6Hb8QF2BTBnCQWP/uu1lhc9AIrIjKnLYMEroIz/JvtGYgI9dF3AxHZNaEH0rw==", "cpu": [ "ppc64" ], @@ -2610,9 +2610,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.60.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.0.tgz", - "integrity": "sha512-Z8pPf54Ly3aqtdWC3G4rFigZgNvd+qJlOE52fmko3KST9SoGfAdSRCwyoyG05q1HrrAblLbk1/PSIV+80/pxLg==", + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.1.tgz", + "integrity": "sha512-RMxFhJwc9fSXP6PqmAz4cbv3kAyvD1etJFjTx4ONqFP9DkTkXsAMU4v3Vyc5BgzC+anz7nS/9tp4obsKfqkDHg==", "cpu": [ "ppc64" ], @@ -2624,9 +2624,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.60.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.0.tgz", - "integrity": "sha512-3a3qQustp3COCGvnP4SvrMHnPQ9d1vzCakQVRTliaz8cIp/wULGjiGpbcqrkv0WrHTEp8bQD/B3HBjzujVWLOA==", + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.1.tgz", + "integrity": "sha512-QKgFl+Yc1eEk6MmOBfRHYF6lTxiiiV3/z/BRrbSiW2I7AFTXoBFvdMEyglohPj//2mZS4hDOqeB0H1ACh3sBbg==", "cpu": [ "riscv64" ], @@ -2638,9 +2638,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.60.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.0.tgz", - "integrity": "sha512-pjZDsVH/1VsghMJ2/kAaxt6dL0psT6ZexQVrijczOf+PeP2BUqTHYejk3l6TlPRydggINOeNRhvpLa0AYpCWSQ==", + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.1.tgz", + "integrity": "sha512-RAjXjP/8c6ZtzatZcA1RaQr6O1TRhzC+adn8YZDnChliZHviqIjmvFwHcxi4JKPSDAt6Uhf/7vqcBzQJy0PDJg==", "cpu": [ "riscv64" ], @@ -2652,9 +2652,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.60.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.0.tgz", - "integrity": "sha512-3ObQs0BhvPgiUVZrN7gqCSvmFuMWvWvsjG5ayJ3Lraqv+2KhOsp+pUbigqbeWqueGIsnn+09HBw27rJ+gYK4VQ==", + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.1.tgz", + "integrity": "sha512-wcuocpaOlaL1COBYiA89O6yfjlp3RwKDeTIA0hM7OpmhR1Bjo9j31G1uQVpDlTvwxGn2nQs65fBFL5UFd76FcQ==", "cpu": [ "s390x" ], @@ -2666,9 +2666,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.60.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.0.tgz", - "integrity": "sha512-EtylprDtQPdS5rXvAayrNDYoJhIz1/vzN2fEubo3yLE7tfAw+948dO0g4M0vkTVFhKojnF+n6C8bDNe+gDRdTg==", + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.1.tgz", + "integrity": "sha512-77PpsFQUCOiZR9+LQEFg9GClyfkNXj1MP6wRnzYs0EeWbPcHs02AXu4xuUbM1zhwn3wqaizle3AEYg5aeoohhg==", "cpu": [ "x64" ], @@ -2680,9 +2680,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.60.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.0.tgz", - "integrity": "sha512-k09oiRCi/bHU9UVFqD17r3eJR9bn03TyKraCrlz5ULFJGdJGi7VOmm9jl44vOJvRJ6P7WuBi/s2A97LxxHGIdw==", + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.1.tgz", + "integrity": "sha512-5cIATbk5vynAjqqmyBjlciMJl1+R/CwX9oLk/EyiFXDWd95KpHdrOJT//rnUl4cUcskrd0jCCw3wpZnhIHdD9w==", "cpu": [ "x64" ], @@ -2694,9 +2694,9 @@ ] }, "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.60.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.0.tgz", - "integrity": "sha512-1o/0/pIhozoSaDJoDcec+IVLbnRtQmHwPV730+AOD29lHEEo4F5BEUB24H0OBdhbBBDwIOSuf7vgg0Ywxdfiiw==", + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.1.tgz", + "integrity": "sha512-cl0w09WsCi17mcmWqqglez9Gk8isgeWvoUZ3WiJFYSR3zjBQc2J5/ihSjpl+VLjPqjQ/1hJRcqBfLjssREQILw==", "cpu": [ "x64" ], @@ -2708,9 +2708,9 @@ ] }, "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.60.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.0.tgz", - "integrity": "sha512-pESDkos/PDzYwtyzB5p/UoNU/8fJo68vcXM9ZW2V0kjYayj1KaaUfi1NmTUTUpMn4UhU4gTuK8gIaFO4UGuMbA==", + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.1.tgz", + "integrity": "sha512-4Cv23ZrONRbNtbZa37mLSueXUCtN7MXccChtKpUnQNgF010rjrjfHx3QxkS2PI7LqGT5xXyYs1a7LbzAwT0iCA==", "cpu": [ "arm64" ], @@ -2722,9 +2722,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.60.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.0.tgz", - "integrity": "sha512-hj1wFStD7B1YBeYmvY+lWXZ7ey73YGPcViMShYikqKT1GtstIKQAtfUI6yrzPjAy/O7pO0VLXGmUVWXQMaYgTQ==", + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.1.tgz", + "integrity": "sha512-i1okWYkA4FJICtr7KpYzFpRTHgy5jdDbZiWfvny21iIKky5YExiDXP+zbXzm3dUcFpkEeYNHgQ5fuG236JPq0g==", "cpu": [ "arm64" ], @@ -2736,9 +2736,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.60.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.0.tgz", - "integrity": "sha512-SyaIPFoxmUPlNDq5EHkTbiKzmSEmq/gOYFI/3HHJ8iS/v1mbugVa7dXUzcJGQfoytp9DJFLhHH4U3/eTy2Bq4w==", + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.1.tgz", + "integrity": "sha512-u09m3CuwLzShA0EYKMNiFgcjjzwqtUMLmuCJLeZWjjOYA3IT2Di09KaxGBTP9xVztWyIWjVdsB2E9goMjZvTQg==", "cpu": [ "ia32" ], @@ -2750,9 +2750,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.60.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.0.tgz", - "integrity": "sha512-RdcryEfzZr+lAr5kRm2ucN9aVlCCa2QNq4hXelZxb8GG0NJSazq44Z3PCCc8wISRuCVnGs0lQJVX5Vp6fKA+IA==", + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.1.tgz", + "integrity": "sha512-k+600V9Zl1CM7eZxJgMyTUzmrmhB/0XZnF4pRypKAlAgxmedUA+1v9R+XOFv56W4SlHEzfeMtzujLJD22Uz5zg==", "cpu": [ "x64" ], @@ -2764,9 +2764,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.60.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.0.tgz", - "integrity": "sha512-PrsWNQ8BuE00O3Xsx3ALh2Df8fAj9+cvvX9AIA6o4KpATR98c9mud4XtDWVvsEuyia5U4tVSTKygawyJkjm60w==", + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.1.tgz", + "integrity": "sha512-lWMnixq/QzxyhTV6NjQJ4SFo1J6PvOX8vUx5Wb4bBPsEb+8xZ89Bz6kOXpfXj9ak9AHTQVQzlgzBEc1SyM27xQ==", "cpu": [ "x64" ], @@ -3040,9 +3040,9 @@ } }, "node_modules/@xmldom/xmldom": { - "version": "0.8.11", - "resolved": "https://registry.npmmirror.com/@xmldom/xmldom/-/xmldom-0.8.11.tgz", - "integrity": "sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw==", + "version": "0.8.12", + "resolved": "https://registry.npmmirror.com/@xmldom/xmldom/-/xmldom-0.8.12.tgz", + "integrity": "sha512-9k/gHF6n/pAi/9tqr3m3aqkuiNosYTurLLUtc7xQ9sxB/wm7WPygCv8GYa6mS0fLJEHhqMC1ATYhz++U/lRHqg==", "dev": true, "license": "MIT", "engines": { @@ -3077,15 +3077,16 @@ } }, "node_modules/ajv": { - "version": "8.18.0", - "resolved": "https://registry.npmmirror.com/ajv/-/ajv-8.18.0.tgz", - "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", + "version": "6.14.0", + "resolved": "https://registry.npmmirror.com/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", + "dev": true, "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, "funding": { "type": "github", @@ -3109,6 +3110,28 @@ } } }, + "node_modules/ajv-formats/node_modules/ajv": { + "version": "8.18.0", + "resolved": "https://registry.npmmirror.com/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" + }, "node_modules/ajv-keywords": { "version": "3.5.2", "resolved": "https://registry.npmmirror.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz", @@ -4228,6 +4251,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/conf/node_modules/ajv": { + "version": "8.18.0", + "resolved": "https://registry.npmmirror.com/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, "node_modules/conf/node_modules/env-paths": { "version": "3.0.0", "resolved": "https://registry.npmmirror.com/env-paths/-/env-paths-3.0.0.tgz", @@ -4240,6 +4279,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/conf/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" + }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmmirror.com/convert-source-map/-/convert-source-map-2.0.0.tgz", @@ -4638,6 +4683,32 @@ "node": ">=8" } }, + "node_modules/dmg-license/node_modules/ajv": { + "version": "8.18.0", + "resolved": "https://registry.npmmirror.com/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/dmg-license/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT", + "optional": true + }, "node_modules/dot-prop": { "version": "9.0.0", "resolved": "https://registry.npmmirror.com/dot-prop/-/dot-prop-9.0.0.tgz", @@ -4744,13 +4815,13 @@ "license": "MIT" }, "node_modules/echarts": { - "version": "5.6.0", - "resolved": "https://registry.npmmirror.com/echarts/-/echarts-5.6.0.tgz", - "integrity": "sha512-oTbVTsXfKuEhxftHqL5xprgLoc0k7uScAwtryCgWF6hPYFLRwOUHiFmHGCBKP5NPFNkDVopOieyUqYGH8Fa3kA==", + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/echarts/-/echarts-6.0.0.tgz", + "integrity": "sha512-Tte/grDQRiETQP4xz3iZWSvoHrkCQtwqd6hs+mifXcjrCuo2iKWbajFObuLJVBlDIJlOzgQPd1hsaKt/3+OMkQ==", "license": "Apache-2.0", "dependencies": { "tslib": "2.3.0", - "zrender": "5.6.1" + "zrender": "6.0.0" } }, "node_modules/echarts-for-react": { @@ -5164,9 +5235,9 @@ "optional": true }, "node_modules/esbuild": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.25.12.tgz", - "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", + "version": "0.27.5", + "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.27.5.tgz", + "integrity": "sha512-zdQoHBjuDqKsvV5OPaWansOwfSQ0Js+Uj9J85TBvj3bFW1JjWTSULMRwdQAc8qMeIScbClxeMK0jlrtB9linhA==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -5177,32 +5248,32 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.12", - "@esbuild/android-arm": "0.25.12", - "@esbuild/android-arm64": "0.25.12", - "@esbuild/android-x64": "0.25.12", - "@esbuild/darwin-arm64": "0.25.12", - "@esbuild/darwin-x64": "0.25.12", - "@esbuild/freebsd-arm64": "0.25.12", - "@esbuild/freebsd-x64": "0.25.12", - "@esbuild/linux-arm": "0.25.12", - "@esbuild/linux-arm64": "0.25.12", - "@esbuild/linux-ia32": "0.25.12", - "@esbuild/linux-loong64": "0.25.12", - "@esbuild/linux-mips64el": "0.25.12", - "@esbuild/linux-ppc64": "0.25.12", - "@esbuild/linux-riscv64": "0.25.12", - "@esbuild/linux-s390x": "0.25.12", - "@esbuild/linux-x64": "0.25.12", - "@esbuild/netbsd-arm64": "0.25.12", - "@esbuild/netbsd-x64": "0.25.12", - "@esbuild/openbsd-arm64": "0.25.12", - "@esbuild/openbsd-x64": "0.25.12", - "@esbuild/openharmony-arm64": "0.25.12", - "@esbuild/sunos-x64": "0.25.12", - "@esbuild/win32-arm64": "0.25.12", - "@esbuild/win32-ia32": "0.25.12", - "@esbuild/win32-x64": "0.25.12" + "@esbuild/aix-ppc64": "0.27.5", + "@esbuild/android-arm": "0.27.5", + "@esbuild/android-arm64": "0.27.5", + "@esbuild/android-x64": "0.27.5", + "@esbuild/darwin-arm64": "0.27.5", + "@esbuild/darwin-x64": "0.27.5", + "@esbuild/freebsd-arm64": "0.27.5", + "@esbuild/freebsd-x64": "0.27.5", + "@esbuild/linux-arm": "0.27.5", + "@esbuild/linux-arm64": "0.27.5", + "@esbuild/linux-ia32": "0.27.5", + "@esbuild/linux-loong64": "0.27.5", + "@esbuild/linux-mips64el": "0.27.5", + "@esbuild/linux-ppc64": "0.27.5", + "@esbuild/linux-riscv64": "0.27.5", + "@esbuild/linux-s390x": "0.27.5", + "@esbuild/linux-x64": "0.27.5", + "@esbuild/netbsd-arm64": "0.27.5", + "@esbuild/netbsd-x64": "0.27.5", + "@esbuild/openbsd-arm64": "0.27.5", + "@esbuild/openbsd-x64": "0.27.5", + "@esbuild/openharmony-arm64": "0.27.5", + "@esbuild/sunos-x64": "0.27.5", + "@esbuild/win32-arm64": "0.27.5", + "@esbuild/win32-ia32": "0.27.5", + "@esbuild/win32-x64": "0.27.5" } }, "node_modules/escalade": { @@ -5323,6 +5394,13 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "license": "MIT" }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, "node_modules/fast-uri": { "version": "3.1.0", "resolved": "https://registry.npmmirror.com/fast-uri/-/fast-uri-3.1.0.tgz", @@ -5349,6 +5427,24 @@ "pend": "~1.2.0" } }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmmirror.com/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, "node_modules/ffmpeg-static": { "version": "5.3.0", "resolved": "https://registry.npmmirror.com/ffmpeg-static/-/ffmpeg-static-5.3.0.tgz", @@ -6348,9 +6444,10 @@ "license": "MIT" }, "node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "version": "0.4.1", + "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, "license": "MIT" }, "node_modules/json-schema-typed": { @@ -6649,9 +6746,9 @@ } }, "node_modules/lucide-react": { - "version": "0.562.0", - "resolved": "https://registry.npmmirror.com/lucide-react/-/lucide-react-0.562.0.tgz", - "integrity": "sha512-82hOAu7y0dbVuFfmO4bYF1XEwYk/mEbM5E+b1jgci/udUBEE/R7LF5Ip0CCEmXe8AybRM8L+04eP+LGZeDvkiw==", + "version": "1.7.0", + "resolved": "https://registry.npmmirror.com/lucide-react/-/lucide-react-1.7.0.tgz", + "integrity": "sha512-yI7BeItCLZJTXikmK4KNUGCKoGzSvbKlfCvw44bU4fXAL6v3gYS4uHD1jzsLkfwODYwI6Drw5Tu9Z5ulDe0TSg==", "license": "ISC", "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" @@ -8260,9 +8357,9 @@ } }, "node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "version": "8.5.8", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.8.tgz", + "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==", "dev": true, "funding": [ { @@ -8390,6 +8487,16 @@ "once": "^1.3.1" } }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmmirror.com/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/quick-lru": { "version": "5.1.1", "resolved": "https://registry.npmmirror.com/quick-lru/-/quick-lru-5.1.1.tgz", @@ -8762,9 +8869,9 @@ } }, "node_modules/rollup": { - "version": "4.60.0", - "resolved": "https://registry.npmmirror.com/rollup/-/rollup-4.60.0.tgz", - "integrity": "sha512-yqjxruMGBQJ2gG4HtjZtAfXArHomazDHoFwFFmZZl0r7Pdo7qCIXKqKHZc8yeoMgzJJ+pO6pEEHa+V7uzWlrAQ==", + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/rollup/-/rollup-4.60.1.tgz", + "integrity": "sha512-VmtB2rFU/GroZ4oL8+ZqXgSA38O6GR8KSIvWmEFv63pQ0G6KaBH9s07PO8XTXP4vI+3UJUEypOfjkGfmSBBR0w==", "dev": true, "license": "MIT", "dependencies": { @@ -8778,31 +8885,31 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.60.0", - "@rollup/rollup-android-arm64": "4.60.0", - "@rollup/rollup-darwin-arm64": "4.60.0", - "@rollup/rollup-darwin-x64": "4.60.0", - "@rollup/rollup-freebsd-arm64": "4.60.0", - "@rollup/rollup-freebsd-x64": "4.60.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.60.0", - "@rollup/rollup-linux-arm-musleabihf": "4.60.0", - "@rollup/rollup-linux-arm64-gnu": "4.60.0", - "@rollup/rollup-linux-arm64-musl": "4.60.0", - "@rollup/rollup-linux-loong64-gnu": "4.60.0", - "@rollup/rollup-linux-loong64-musl": "4.60.0", - "@rollup/rollup-linux-ppc64-gnu": "4.60.0", - "@rollup/rollup-linux-ppc64-musl": "4.60.0", - "@rollup/rollup-linux-riscv64-gnu": "4.60.0", - "@rollup/rollup-linux-riscv64-musl": "4.60.0", - "@rollup/rollup-linux-s390x-gnu": "4.60.0", - "@rollup/rollup-linux-x64-gnu": "4.60.0", - "@rollup/rollup-linux-x64-musl": "4.60.0", - "@rollup/rollup-openbsd-x64": "4.60.0", - "@rollup/rollup-openharmony-arm64": "4.60.0", - "@rollup/rollup-win32-arm64-msvc": "4.60.0", - "@rollup/rollup-win32-ia32-msvc": "4.60.0", - "@rollup/rollup-win32-x64-gnu": "4.60.0", - "@rollup/rollup-win32-x64-msvc": "4.60.0", + "@rollup/rollup-android-arm-eabi": "4.60.1", + "@rollup/rollup-android-arm64": "4.60.1", + "@rollup/rollup-darwin-arm64": "4.60.1", + "@rollup/rollup-darwin-x64": "4.60.1", + "@rollup/rollup-freebsd-arm64": "4.60.1", + "@rollup/rollup-freebsd-x64": "4.60.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.60.1", + "@rollup/rollup-linux-arm-musleabihf": "4.60.1", + "@rollup/rollup-linux-arm64-gnu": "4.60.1", + "@rollup/rollup-linux-arm64-musl": "4.60.1", + "@rollup/rollup-linux-loong64-gnu": "4.60.1", + "@rollup/rollup-linux-loong64-musl": "4.60.1", + "@rollup/rollup-linux-ppc64-gnu": "4.60.1", + "@rollup/rollup-linux-ppc64-musl": "4.60.1", + "@rollup/rollup-linux-riscv64-gnu": "4.60.1", + "@rollup/rollup-linux-riscv64-musl": "4.60.1", + "@rollup/rollup-linux-s390x-gnu": "4.60.1", + "@rollup/rollup-linux-x64-gnu": "4.60.1", + "@rollup/rollup-linux-x64-musl": "4.60.1", + "@rollup/rollup-openbsd-x64": "4.60.1", + "@rollup/rollup-openharmony-arm64": "4.60.1", + "@rollup/rollup-win32-arm64-msvc": "4.60.1", + "@rollup/rollup-win32-ia32-msvc": "4.60.1", + "@rollup/rollup-win32-x64-gnu": "4.60.1", + "@rollup/rollup-win32-x64-msvc": "4.60.1", "fsevents": "~2.3.2" } }, @@ -8844,14 +8951,14 @@ } }, "node_modules/sass": { - "version": "1.97.2", - "resolved": "https://registry.npmmirror.com/sass/-/sass-1.97.2.tgz", - "integrity": "sha512-y5LWb0IlbO4e97Zr7c3mlpabcbBtS+ieiZ9iwDooShpFKWXf62zz5pEPdwrLYm+Bxn1fnbwFGzHuCLSA9tBmrw==", + "version": "1.98.0", + "resolved": "https://registry.npmmirror.com/sass/-/sass-1.98.0.tgz", + "integrity": "sha512-+4N/u9dZ4PrgzGgPlKnaaRQx64RO0JBKs9sDhQ2pLgN6JQZ25uPQZKQYaBJU48Kd5BxgXoJ4e09Dq7nMcOUW3A==", "dev": true, "license": "MIT", "dependencies": { "chokidar": "^4.0.0", - "immutable": "^5.0.2", + "immutable": "^5.1.5", "source-map-js": ">=0.6.2 <2.0.0" }, "bin": { @@ -9072,6 +9179,9 @@ "sherpa-onnx-win-x64": "^1.12.23" } }, + "node_modules/sherpa-onnx-node/node_modules/sherpa-onnx-darwin-x64": { + "optional": true + }, "node_modules/sherpa-onnx-win-ia32": { "version": "1.12.23", "resolved": "https://registry.npmmirror.com/sherpa-onnx-win-ia32/-/sherpa-onnx-win-ia32-1.12.23.tgz", @@ -9578,24 +9688,6 @@ "url": "https://github.com/sponsors/SuperchupuDev" } }, - "node_modules/tinyglobby/node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmmirror.com/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, "node_modules/tmp": { "version": "0.2.5", "resolved": "https://registry.npmmirror.com/tmp/-/tmp-0.2.5.tgz", @@ -9693,9 +9785,9 @@ "license": "MIT" }, "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmmirror.com/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "version": "6.0.2", + "resolved": "https://registry.npmmirror.com/typescript/-/typescript-6.0.2.tgz", + "integrity": "sha512-bGdAIrZ0wiGDo5l8c++HWtbaNCWTS4UTv7RaTH/ThVIgjkveJt83m74bBHMJkuCbslY8ixgLBVZJIOiQlQTjfQ==", "dev": true, "license": "Apache-2.0", "bin": { @@ -9933,6 +10025,16 @@ "browserslist": ">= 4.21.0" } }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmmirror.com/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, "node_modules/utf8-byte-length": { "version": "1.0.5", "resolved": "https://registry.npmmirror.com/utf8-byte-length/-/utf8-byte-length-1.0.5.tgz", @@ -10009,24 +10111,24 @@ } }, "node_modules/vite": { - "version": "6.4.1", - "resolved": "https://registry.npmmirror.com/vite/-/vite-6.4.1.tgz", - "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", + "version": "7.3.1", + "resolved": "https://registry.npmmirror.com/vite/-/vite-7.3.1.tgz", + "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", "dev": true, "license": "MIT", "dependencies": { - "esbuild": "^0.25.0", - "fdir": "^6.4.4", - "picomatch": "^4.0.2", - "postcss": "^8.5.3", - "rollup": "^4.34.9", - "tinyglobby": "^0.2.13" + "esbuild": "^0.27.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" }, "bin": { "vite": "bin/vite.js" }, "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + "node": "^20.19.0 || >=22.12.0" }, "funding": { "url": "https://github.com/vitejs/vite?sponsor=1" @@ -10035,14 +10137,14 @@ "fsevents": "~2.3.3" }, "peerDependencies": { - "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", - "less": "*", + "less": "^4.0.0", "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" @@ -10105,24 +10207,6 @@ "dev": true, "license": "MIT" }, - "node_modules/vite/node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmmirror.com/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, "node_modules/wcwidth": { "version": "1.0.1", "resolved": "https://registry.npmmirror.com/wcwidth/-/wcwidth-1.0.1.tgz", @@ -10329,9 +10413,9 @@ } }, "node_modules/zrender": { - "version": "5.6.1", - "resolved": "https://registry.npmmirror.com/zrender/-/zrender-5.6.1.tgz", - "integrity": "sha512-OFXkDJKcrlx5su2XbzJvj/34Q3m6PvyCZkVPHGYpcCJ52ek4U/ymZyfuV1nKE23AyBJ51E/6Yr0mhZ7xGTO4ag==", + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/zrender/-/zrender-6.0.0.tgz", + "integrity": "sha512-41dFXEEXuJpNecuUQq6JlbybmnHaqqpGlbH1yxnA5V9MMP4SbohSVZsJIwz+zdjQXSSlR1Vc34EgH1zxyTDvhg==", "license": "BSD-3-Clause", "dependencies": { "tslib": "2.3.0" diff --git a/package.json b/package.json index cd81f75..3980c38 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "electron:build": "npm run build" }, "dependencies": { - "echarts": "^5.5.1", + "echarts": "^6.0.0", "echarts-for-react": "^3.0.2", "electron-store": "^10.0.0", "electron-updater": "^6.3.9", @@ -34,7 +34,7 @@ "jieba-wasm": "^2.2.0", "jszip": "^3.10.1", "koffi": "^2.9.0", - "lucide-react": "^0.562.0", + "lucide-react": "^1.7.0", "react": "^19.2.3", "react-dom": "^19.2.3", "react-markdown": "^10.1.0", @@ -54,10 +54,10 @@ "@vitejs/plugin-react": "^4.3.4", "electron": "^39.2.7", "electron-builder": "^26.8.1", - "sass": "^1.83.0", + "sass": "^1.98.0", "sharp": "^0.34.5", - "typescript": "^5.6.3", - "vite": "^6.0.5", + "typescript": "^6.0.2", + "vite": "^7.0.0", "vite-plugin-electron": "^0.28.8", "vite-plugin-electron-renderer": "^0.14.6" }, @@ -102,7 +102,25 @@ "target": [ "nsis" ], - "icon": "public/icon.ico" + "icon": "public/icon.ico", + "extraFiles": [ + { + "from": "resources/msvcp140.dll", + "to": "." + }, + { + "from": "resources/msvcp140_1.dll", + "to": "." + }, + { + "from": "resources/vcruntime140.dll", + "to": "." + }, + { + "from": "resources/vcruntime140_1.dll", + "to": "." + } + ] }, "linux": { "icon": "public/icon.png", @@ -170,30 +188,16 @@ "node_modules/sherpa-onnx-*/**/*", "node_modules/ffmpeg-static/**/*" ], - "extraFiles": [ - { - "from": "resources/msvcp140.dll", - "to": "." - }, - { - "from": "resources/msvcp140_1.dll", - "to": "." - }, - { - "from": "resources/vcruntime140.dll", - "to": "." - }, - { - "from": "resources/vcruntime140_1.dll", - "to": "." - } - ], "icon": "resources/icon.icns" }, "overrides": { "picomatch": "^4.0.4", "tar": "^7.5.13", "immutable": "^5.1.5", - "ajv": "^6.14.0" + "ajv": "^8.17.1", + "@develar/schema-utils": { + "ajv": "^6.12.6", + "ajv-keywords": "^3.5.2" + } } } diff --git a/resources/arm64/wcdb_api.dll b/resources/arm64/wcdb_api.dll index a622386..de6bce8 100644 Binary files a/resources/arm64/wcdb_api.dll and b/resources/arm64/wcdb_api.dll differ diff --git a/resources/libwcdb_api.dylib b/resources/libwcdb_api.dylib index a9a6ccd..d185cfc 100755 Binary files a/resources/libwcdb_api.dylib and b/resources/libwcdb_api.dylib differ diff --git a/resources/libwcdb_api.so b/resources/libwcdb_api.so index 7aa52f4..d3c686a 100755 Binary files a/resources/libwcdb_api.so and b/resources/libwcdb_api.so differ diff --git a/resources/linux/libwcdb_api.so b/resources/linux/libwcdb_api.so index 7aa52f4..d3c686a 100755 Binary files a/resources/linux/libwcdb_api.so and b/resources/linux/libwcdb_api.so differ diff --git a/resources/macos/libwcdb_api.dylib b/resources/macos/libwcdb_api.dylib index a9a6ccd..d185cfc 100755 Binary files a/resources/macos/libwcdb_api.dylib and b/resources/macos/libwcdb_api.dylib differ diff --git a/resources/wcdb_api.dll b/resources/wcdb_api.dll index f7d7589..c9609ad 100644 Binary files a/resources/wcdb_api.dll and b/resources/wcdb_api.dll differ diff --git a/resources/wcdb_api_arm64.dll b/resources/wcdb_api_arm64.dll index 16416fd..de6bce8 100644 Binary files a/resources/wcdb_api_arm64.dll and b/resources/wcdb_api_arm64.dll differ diff --git a/src/components/JumpToDateDialog.scss b/src/components/JumpToDateDialog.scss index 5e03962..0cdcadb 100644 --- a/src/components/JumpToDateDialog.scss +++ b/src/components/JumpToDateDialog.scss @@ -75,6 +75,8 @@ font-size: 15px; font-weight: 600; color: var(--text-primary); + border: none; + background: transparent; &.clickable { cursor: pointer; @@ -172,6 +174,33 @@ } } } + + .year-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 6px; + + .year-btn { + padding: 10px 0; + border: none; + background: transparent; + border-radius: 8px; + cursor: pointer; + font-size: 13px; + color: var(--text-secondary); + transition: all 0.15s; + + &:hover { + background: var(--bg-hover); + color: var(--text-primary); + } + + &.active { + background: var(--primary); + color: #fff; + } + } + } } } @@ -372,4 +401,4 @@ opacity: 1; transform: translateY(0); } -} \ No newline at end of file +} diff --git a/src/components/JumpToDateDialog.tsx b/src/components/JumpToDateDialog.tsx index 90044b2..47bfb80 100644 --- a/src/components/JumpToDateDialog.tsx +++ b/src/components/JumpToDateDialog.tsx @@ -1,4 +1,4 @@ -import React, { useState, useMemo } from 'react' +import React, { useState } from 'react' import { X, ChevronLeft, ChevronRight, Calendar as CalendarIcon, Loader2 } from 'lucide-react' import './JumpToDateDialog.scss' @@ -21,10 +21,15 @@ const JumpToDateDialog: React.FC = ({ messageDates, loadingDates = false }) => { + type CalendarViewMode = 'day' | 'month' | 'year' + const getYearPageStart = (year: number): number => Math.floor(year / 12) * 12 const isValidDate = (d: any) => d instanceof Date && !isNaN(d.getTime()) const [calendarDate, setCalendarDate] = useState(isValidDate(currentDate) ? new Date(currentDate) : new Date()) const [selectedDate, setSelectedDate] = useState(new Date(currentDate)) - const [showYearMonthPicker, setShowYearMonthPicker] = useState(false) + const [viewMode, setViewMode] = useState('day') + const [yearPageStart, setYearPageStart] = useState( + getYearPageStart((isValidDate(currentDate) ? new Date(currentDate) : new Date()).getFullYear()) + ) if (!isOpen) return null @@ -116,6 +121,57 @@ const JumpToDateDialog: React.FC = ({ const weekdays = ['日', '一', '二', '三', '四', '五', '六'] const days = generateCalendar() + const monthNames = ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'] + + const updateCalendarDate = (nextDate: Date) => { + setCalendarDate(nextDate) + } + + const openMonthView = () => setViewMode('month') + const openYearView = () => { + setYearPageStart(getYearPageStart(calendarDate.getFullYear())) + setViewMode('year') + } + + const handleTitleClick = () => { + if (viewMode === 'day') { + openMonthView() + return + } + if (viewMode === 'month') { + openYearView() + } + } + + const handlePrev = () => { + if (viewMode === 'day') { + updateCalendarDate(new Date(calendarDate.getFullYear(), calendarDate.getMonth() - 1, 1)) + return + } + if (viewMode === 'month') { + updateCalendarDate(new Date(calendarDate.getFullYear() - 1, calendarDate.getMonth(), 1)) + return + } + setYearPageStart((prev) => prev - 12) + } + + const handleNext = () => { + if (viewMode === 'day') { + updateCalendarDate(new Date(calendarDate.getFullYear(), calendarDate.getMonth() + 1, 1)) + return + } + if (viewMode === 'month') { + updateCalendarDate(new Date(calendarDate.getFullYear() + 1, calendarDate.getMonth(), 1)) + return + } + setYearPageStart((prev) => prev + 12) + } + + const navTitle = viewMode === 'day' + ? `${calendarDate.getFullYear()}年${calendarDate.getMonth() + 1}月` + : viewMode === 'month' + ? `${calendarDate.getFullYear()}年` + : `${yearPageStart}年 - ${yearPageStart + 11}年` return (
@@ -134,45 +190,57 @@ const JumpToDateDialog: React.FC = ({
- setShowYearMonthPicker(!showYearMonthPicker)}> - {calendarDate.getFullYear()}年{calendarDate.getMonth() + 1}月 - +
- {showYearMonthPicker ? ( + {viewMode === 'month' ? (
-
- - {calendarDate.getFullYear()}年 - -
- {['一月','二月','三月','四月','五月','六月','七月','八月','九月','十月','十一月','十二月'].map((name, i) => ( + {monthNames.map((name, i) => ( ))}
+ ) : viewMode === 'year' ? ( +
+
+ {Array.from({ length: 12 }, (_, i) => yearPageStart + i).map((year) => ( + + ))} +
+
) : (
{loadingDates && ( @@ -208,18 +276,21 @@ const JumpToDateDialog: React.FC = ({ const d = new Date() setSelectedDate(d) setCalendarDate(new Date(d)) + setViewMode('day') }}>今天
diff --git a/src/components/JumpToDatePopover.scss b/src/components/JumpToDatePopover.scss index f9839a6..eb7d447 100644 --- a/src/components/JumpToDatePopover.scss +++ b/src/components/JumpToDatePopover.scss @@ -28,6 +28,20 @@ font-size: 14px; font-weight: 600; color: var(--text-primary); + border: none; + background: transparent; + border-radius: 8px; + padding: 4px 8px; +} + +.jump-date-popover .current-month.clickable { + cursor: pointer; + transition: all 0.18s ease; +} + +.jump-date-popover .current-month.clickable:hover { + color: var(--primary); + background: var(--bg-hover); } .jump-date-popover .nav-btn { @@ -83,6 +97,37 @@ gap: 4px; } +.jump-date-popover .month-grid, +.jump-date-popover .year-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 6px; + min-height: 256px; +} + +.jump-date-popover .month-cell, +.jump-date-popover .year-cell { + border: none; + border-radius: 8px; + background: transparent; + color: var(--text-secondary); + cursor: pointer; + font-size: 13px; + transition: all 0.18s ease; +} + +.jump-date-popover .month-cell:hover, +.jump-date-popover .year-cell:hover { + background: var(--bg-hover); + color: var(--text-primary); +} + +.jump-date-popover .month-cell.active, +.jump-date-popover .year-cell.active { + background: var(--primary); + color: #fff; +} + .jump-date-popover .day-cell { position: relative; border: 1px solid transparent; diff --git a/src/components/JumpToDatePopover.tsx b/src/components/JumpToDatePopover.tsx index ef3c807..e88b502 100644 --- a/src/components/JumpToDatePopover.tsx +++ b/src/components/JumpToDatePopover.tsx @@ -31,14 +31,20 @@ const JumpToDatePopover: React.FC = ({ loadingDates = false, loadingDateCounts = false }) => { + type CalendarViewMode = 'day' | 'month' | 'year' + const getYearPageStart = (year: number): number => Math.floor(year / 12) * 12 const [calendarDate, setCalendarDate] = useState(new Date(currentDate)) const [selectedDate, setSelectedDate] = useState(new Date(currentDate)) + const [viewMode, setViewMode] = useState('day') + const [yearPageStart, setYearPageStart] = useState(getYearPageStart(new Date(currentDate).getFullYear())) useEffect(() => { if (!isOpen) return const normalized = new Date(currentDate) setCalendarDate(normalized) setSelectedDate(normalized) + setViewMode('day') + setYearPageStart(getYearPageStart(normalized.getFullYear())) }, [isOpen, currentDate]) if (!isOpen) return null @@ -114,25 +120,78 @@ const JumpToDatePopover: React.FC = ({ const weekdays = ['日', '一', '二', '三', '四', '五', '六'] const days = generateCalendar() const mergedClassName = ['jump-date-popover', className || ''].join(' ').trim() + const updateCalendarDate = (nextDate: Date) => { setCalendarDate(nextDate) onMonthChange?.(nextDate) } + const openMonthView = () => setViewMode('month') + const openYearView = () => { + setYearPageStart(getYearPageStart(calendarDate.getFullYear())) + setViewMode('year') + } + + const handleTitleClick = () => { + if (viewMode === 'day') { + openMonthView() + return + } + if (viewMode === 'month') { + openYearView() + } + } + + const handlePrev = () => { + if (viewMode === 'day') { + updateCalendarDate(new Date(calendarDate.getFullYear(), calendarDate.getMonth() - 1, 1)) + return + } + if (viewMode === 'month') { + updateCalendarDate(new Date(calendarDate.getFullYear() - 1, calendarDate.getMonth(), 1)) + return + } + setYearPageStart((prev) => prev - 12) + } + + const handleNext = () => { + if (viewMode === 'day') { + updateCalendarDate(new Date(calendarDate.getFullYear(), calendarDate.getMonth() + 1, 1)) + return + } + if (viewMode === 'month') { + updateCalendarDate(new Date(calendarDate.getFullYear() + 1, calendarDate.getMonth(), 1)) + return + } + setYearPageStart((prev) => prev + 12) + } + + const navTitle = viewMode === 'day' + ? `${calendarDate.getFullYear()}年${calendarDate.getMonth() + 1}月` + : viewMode === 'month' + ? `${calendarDate.getFullYear()}年` + : `${yearPageStart}年 - ${yearPageStart + 11}年` + return (
- {calendarDate.getFullYear()}年{calendarDate.getMonth() + 1}月 +
-
-
- {weekdays.map(day => ( -
{day}
+ {viewMode === 'day' && ( +
+
+ {weekdays.map(day => ( +
{day}
+ ))} +
+
+ {days.map((day, index) => { + if (day === null) return
+ const dateKey = toDateKey(day) + const hasMessageOnDay = hasMessage(day) + const count = Number(messageDateCounts?.[dateKey] || 0) + const showCount = count > 0 + const showCountLoading = hasMessageOnDay && loadingDateCounts && !showCount + return ( + + ) + })} +
+
+ )} + + {viewMode === 'month' && ( +
+ {['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'].map((name, monthIndex) => ( + ))}
-
- {days.map((day, index) => { - if (day === null) return
- const dateKey = toDateKey(day) - const hasMessageOnDay = hasMessage(day) - const count = Number(messageDateCounts?.[dateKey] || 0) - const showCount = count > 0 - const showCountLoading = hasMessageOnDay && loadingDateCounts && !showCount - return ( - - ) - })} + )} + + {viewMode === 'year' && ( +
+ {Array.from({ length: 12 }, (_, i) => yearPageStart + i).map((year) => ( + + ))}
-
+ )}
) } diff --git a/src/pages/SettingsPage.scss b/src/pages/SettingsPage.scss index 5862037..8ebad97 100644 --- a/src/pages/SettingsPage.scss +++ b/src/pages/SettingsPage.scss @@ -1401,6 +1401,220 @@ } } +// 版本更新页面 +.updates-tab { + display: flex; + flex-direction: column; + gap: 16px; +} + +.updates-hero { + display: flex; + align-items: center; + justify-content: space-between; + gap: 16px; + padding: 20px 22px; + border-radius: 18px; + border: 1px solid color-mix(in srgb, var(--primary) 18%, var(--border-color)); + background: + linear-gradient(110deg, color-mix(in srgb, var(--bg-primary) 98%, #ffffff 2%), color-mix(in srgb, var(--bg-primary) 97%, var(--primary) 3%)); + box-shadow: 0 8px 22px color-mix(in srgb, var(--primary) 8%, transparent); +} + +.updates-hero-main { + min-width: 0; + + h2 { + margin: 10px 0 6px; + font-size: 30px; + line-height: 1; + letter-spacing: -0.03em; + color: var(--text-primary); + } + + p { + margin: 0; + font-size: 13px; + color: var(--text-secondary); + } +} + +.updates-chip { + display: inline-flex; + align-items: center; + height: 24px; + padding: 0 10px; + border-radius: 999px; + font-size: 12px; + font-weight: 600; + color: var(--primary); + background: color-mix(in srgb, var(--primary) 12%, transparent); +} + +.updates-hero-action { + display: flex; + flex-direction: column; + gap: 8px; + align-items: flex-end; +} + +.updates-card { + padding: 18px; + border-radius: 16px; + border: 1px solid var(--border-color); + background: color-mix(in srgb, var(--bg-primary) 96%, var(--bg-secondary)); +} + +.updates-progress-card { + padding: 16px 18px; + border-radius: 16px; + border: 1px solid color-mix(in srgb, var(--primary) 34%, var(--border-color)); + background: color-mix(in srgb, var(--bg-primary) 95%, var(--primary) 4%); +} + +.updates-progress-header { + display: flex; + align-items: baseline; + justify-content: space-between; + gap: 10px; + margin-bottom: 10px; + + h3 { + margin: 0; + font-size: 15px; + color: var(--text-primary); + } + + strong { + color: var(--primary); + font-size: 14px; + font-variant-numeric: tabular-nums; + } + + span { + font-size: 12px; + color: var(--text-secondary); + } +} + +.updates-card-header { + margin-bottom: 12px; + + h3 { + margin: 0 0 4px; + font-size: 16px; + color: var(--text-primary); + } + + span { + font-size: 12px; + color: var(--text-tertiary); + } +} + +.update-channel-grid { + display: grid; + gap: 10px; +} + +.update-channel-card { + width: 100%; + text-align: left; + border: 1px solid var(--border-color); + border-radius: 14px; + padding: 12px 14px; + background: var(--bg-primary); + color: var(--text-primary); + transition: border-color 0.2s ease, transform 0.2s ease, box-shadow 0.2s ease; + cursor: pointer; + + &:hover:not(:disabled) { + border-color: color-mix(in srgb, var(--primary) 42%, var(--border-color)); + transform: translateY(-1px); + box-shadow: 0 8px 24px color-mix(in srgb, var(--primary) 12%, transparent); + } + + &:disabled { + cursor: default; + } + + &.active { + border-color: color-mix(in srgb, var(--primary) 60%, var(--border-color)); + background: color-mix(in srgb, var(--primary) 10%, var(--bg-primary)); + } +} + +.update-channel-title-row { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 6px; + + .title { + font-size: 14px; + font-weight: 600; + color: var(--text-primary); + } + + svg { + color: var(--primary); + } +} + +.update-channel-card .desc { + display: block; + font-size: 12px; + color: var(--text-secondary); +} + +.updates-progress-track { + height: 10px; + border-radius: 999px; + background: var(--bg-tertiary); + overflow: hidden; +} + +.updates-progress-fill { + height: 100%; + border-radius: inherit; + background: linear-gradient(90deg, var(--primary), color-mix(in srgb, var(--primary) 72%, #ffffff)); + transition: width 0.3s ease; + position: relative; + + &::after { + content: ''; + position: absolute; + inset: 0; + background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.26), transparent); + animation: updatesShimmer 1.7s linear infinite; + } +} + +.updates-ignore-btn { + margin-top: 12px; +} + +@media (max-width: 920px) { + .updates-hero { + flex-direction: column; + align-items: flex-start; + } + + .updates-hero-action { + align-items: flex-start; + } +} + +@keyframes updatesShimmer { + from { + transform: translateX(-100%); + } + + to { + transform: translateX(100%); + } +} + // 关于页面 .about-tab { diff --git a/src/pages/SettingsPage.tsx b/src/pages/SettingsPage.tsx index 36e1776..55c5779 100644 --- a/src/pages/SettingsPage.tsx +++ b/src/pages/SettingsPage.tsx @@ -15,7 +15,7 @@ import { import { Avatar } from '../components/Avatar' import './SettingsPage.scss' -type SettingsTab = 'appearance' | 'notification' | 'database' | 'models' | 'cache' | 'api' | 'security' | 'about' | 'analytics' +type SettingsTab = 'appearance' | 'notification' | 'database' | 'models' | 'cache' | 'api' | 'updates' | 'security' | 'about' | 'analytics' const tabs: { id: SettingsTab; label: string; icon: React.ElementType }[] = [ { id: 'appearance', label: '外观', icon: Palette }, @@ -24,9 +24,9 @@ const tabs: { id: SettingsTab; label: string; icon: React.ElementType }[] = [ { id: 'models', label: '模型管理', icon: Mic }, { id: 'cache', label: '缓存', icon: HardDrive }, { id: 'api', label: 'API 服务', icon: Globe }, - { id: 'analytics', label: '分析', icon: BarChart2 }, { id: 'security', label: '安全', icon: ShieldCheck }, + { id: 'updates', label: '版本更新', icon: RefreshCw }, { id: 'about', label: '关于', icon: Info } ] @@ -68,7 +68,6 @@ function SettingsPage({ onClose }: SettingsPageProps = {}) { setDownloadProgress, showUpdateDialog, setShowUpdateDialog, - setUpdateError } = useAppStore() const resetChatStore = useChatStore((state) => state.reset) @@ -141,6 +140,7 @@ function SettingsPage({ onClose }: SettingsPageProps = {}) { const [notificationFilterList, setNotificationFilterList] = useState([]) const [windowCloseBehavior, setWindowCloseBehavior] = useState('ask') const [quoteLayout, setQuoteLayout] = useState('quote-top') + const [updateChannel, setUpdateChannel] = useState('stable') const [filterSearchKeyword, setFilterSearchKeyword] = useState('') const [filterModeDropdownOpen, setFilterModeDropdownOpen] = useState(false) const [positionDropdownOpen, setPositionDropdownOpen] = useState(false) @@ -339,6 +339,7 @@ function SettingsPage({ onClose }: SettingsPageProps = {}) { const savedMessagePushEnabled = await configService.getMessagePushEnabled() const savedWindowCloseBehavior = await configService.getWindowCloseBehavior() const savedQuoteLayout = await configService.getQuoteLayout() + const savedUpdateChannel = await configService.getUpdateChannel() const savedAuthEnabled = await window.electronAPI.auth.verifyEnabled() const savedAuthUseHello = await configService.getAuthUseHello() @@ -387,6 +388,18 @@ function SettingsPage({ onClose }: SettingsPageProps = {}) { setMessagePushEnabled(savedMessagePushEnabled) setWindowCloseBehavior(savedWindowCloseBehavior) setQuoteLayout(savedQuoteLayout) + if (savedUpdateChannel) { + setUpdateChannel(savedUpdateChannel) + } else { + const currentVersion = await window.electronAPI.app.getVersion() + if (/-preview\.\d+\.\d+$/i.test(currentVersion)) { + setUpdateChannel('preview') + } else if (/-dev\.\d+\.\d+\.\d+$/i.test(currentVersion) || /(alpha|beta|rc)/i.test(currentVersion)) { + setUpdateChannel('dev') + } else { + setUpdateChannel('stable') + } + } const savedExcludeWords = await configService.getWordCloudExcludeWords() setWordCloudExcludeWords(savedExcludeWords) @@ -512,7 +525,22 @@ function SettingsPage({ onClose }: SettingsPageProps = {}) { } } + const handleUpdateChannelChange = async (channel: configService.UpdateChannel) => { + if (channel === updateChannel) return + try { + setUpdateChannel(channel) + await configService.setUpdateChannel(channel) + await configService.setIgnoredUpdateVersion('') + setUpdateInfo(null) + setShowUpdateDialog(false) + const channelLabel = channel === 'stable' ? '稳定版' : channel === 'preview' ? '预览版' : '开发版' + showMessage(`已切换到${channelLabel}更新渠道,正在检查更新`, true) + await handleCheckUpdate() + } catch (e: any) { + showMessage(`切换更新渠道失败: ${e}`, false) + } + } const showMessage = (text: string, success: boolean) => { setMessage({ text, success }) @@ -1474,6 +1502,16 @@ function SettingsPage({ onClose }: SettingsPageProps = {}) { const renderDatabaseTab = () => (
+
+ + 检测当前数据库配置是否可用 + +
+ +
+
64位十六进制密钥 @@ -2400,35 +2438,7 @@ function SettingsPage({ onClose }: SettingsPageProps = {}) { WeFlow

WeFlow

-

WeFlow

v{appVersion || '...'}

- -
- {updateInfo?.hasUpdate ? ( - <> -

新版 v{updateInfo.version} 可用

- {isDownloading ? ( -
-
-
-
- {(downloadProgress?.percent || 0).toFixed(0)}% -
- ) : ( - - )} - - ) : ( -
- -
- )} -
@@ -2440,7 +2450,7 @@ function SettingsPage({ onClose }: SettingsPageProps = {}) { · { e.preventDefault(); window.electronAPI.window.openAgreementWindow() }}>用户协议
-

© 2025 WeFlow. All rights reserved.

+

© 2026 WeFlow. All rights reserved.

匿名数据收集 @@ -2463,6 +2473,82 @@ function SettingsPage({ onClose }: SettingsPageProps = {}) {
) + const renderUpdatesTab = () => { + const downloadPercent = Math.max(0, Math.min(100, Number(downloadProgress?.percent || 0))) + const channelCards: { id: configService.UpdateChannel; title: string; desc: string }[] = [ + { id: 'stable', title: '稳定版', desc: '正式发布的版本,适合日常使用' }, + { id: 'preview', title: '预览版', desc: '正式发布前的预览体验版本' }, + { id: 'dev', title: '开发版', desc: '即刻体验我们的屎山代码' } + ] + + return ( +
+
+
+ 当前版本 +

{appVersion || '...'}

+

{updateInfo?.hasUpdate ? `发现新版本 v${updateInfo.version}` : '当前已是最新版本,可手动检查更新'}

+
+
+ {updateInfo?.hasUpdate ? ( + + ) : ( + + )} +
+
+ + {(isDownloading || updateInfo?.hasUpdate) && ( +
+
+

{isDownloading ? `正在下载 v${updateInfo?.version || ''}` : `新版本 v${updateInfo?.version} 已就绪`}

+ {isDownloading ? {downloadPercent.toFixed(0)}% : 可立即安装} +
+
+
+
+ {updateInfo?.hasUpdate && !isDownloading && ( + + )} +
+ )} + +
+
+

更新渠道

+ 切换渠道后会自动重新检查 +
+
+ {channelCards.map((channel) => { + const active = updateChannel === channel.id + return ( + + ) + })} +
+
+
+ ) + } + return (
event.stopPropagation()}> @@ -2510,9 +2596,6 @@ function SettingsPage({ onClose }: SettingsPageProps = {}) {

设置

- {onClose && (