fix: bundle AkShare calendar data in desktop builds (#1990)

This commit is contained in:
zhulinsen
2026-07-12 14:38:49 +08:00
committed by GitHub
parent 85c02edca9
commit 6fda28b4be
5 changed files with 56 additions and 3 deletions

View File

@@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
## [Unreleased]
- [修复] 市场结构概念排行为空或超时时复用本轮负结果,避免批量个股分析重复请求同一概念排行数据源。
- [修复] Windows/macOS 桌面后端打包显式收集并校验 AkShare `file_fold/calendar.json`,避免发行包因缺少交易日历 package data 导致热点题材和选股日线增强降级。
- [改进] 为 multi-agent DecisionAgent 增加内部低敏分歧摘要输入管线,作为 #1904 P1 解释输出的前置 plumbing不改变 public API、dashboard schema 或最终解释字段。
- [修复] 推送报告、Jinja 报告与历史 Markdown 导出复用 Web/API 的评分-action 口径:高分但旧 `operation_advice` 仍为持有且无降级原因时,建议文案与三类统计展示为买入;有明确 guardrail reason 时继续保留持有/观望。
- [改进] GitHub Actions 每日分析工作流补齐 TickFlow 数据源环境变量映射,并收敛 README 数据源稳定性说明到完整指南。

View File

@@ -190,7 +190,7 @@ npm install
npm run build
```
2) 按现有脚本打包 Python 后端(脚本已内置 AlphaSift 依赖收集)
2) 按现有脚本打包 Python 后端(脚本已内置 AlphaSift 与 AkShare 数据文件收集)
- Windows
@@ -204,7 +204,7 @@ powershell -ExecutionPolicy Bypass -File scripts\build-backend.ps1
bash scripts/build-backend-macos.sh
```
该脚本会在安装依赖后执行 `--collect-all alphasift`,并校验打包产物中可导入 `alphasift.dsa_adapter`,避免分步命令遗漏内置 AlphaSift 模块
该脚本会在安装依赖后执行 `--collect-all alphasift``--collect-data akshare`。构建完成后会校验 `alphasift.dsa_adapter` 可导入,并确认 AkShare 的 `file_fold/calendar.json` 已进入冻结产物,避免发行包在热点题材或日线增强路径中因缺少 package data 降级
3) 打包 Electron 桌面应用
@@ -297,6 +297,8 @@ win-unpacked/
PyInstaller 打包时缺少模块,需要在 `scripts/build-backend.ps1` 中增加 `--hidden-import`
如果日志提示缺少 `akshare/file_fold/calendar.json`,说明后端冻结产物没有完整收集 AkShare package data。请使用仓库当前的 `scripts/build-backend.ps1``scripts/build-backend-macos.sh` 重新构建;脚本会在生成桌面包前检查该文件,缺失时直接终止构建。
### UI 加载空白
确认 `static/index.html` 存在,如不存在需重新构建 React UI。

View File

@@ -110,7 +110,7 @@ for module in "${hidden_imports[@]}"; do
done
pushd "${ROOT_DIR}" >/dev/null
cmd=("${PYTHON_BIN}" -m PyInstaller --name stock_analysis --onedir --noconfirm --noconsole --add-data "static:static" --add-data "strategies:strategies" --collect-data litellm --collect-data tiktoken)
cmd=("${PYTHON_BIN}" -m PyInstaller --name stock_analysis --onedir --noconfirm --noconsole --add-data "static:static" --add-data "strategies:strategies" --collect-data litellm --collect-data tiktoken --collect-data akshare)
cmd+=("--collect-all" "alphasift")
cmd+=("${hidden_import_args[@]}" "main.py")
@@ -144,6 +144,16 @@ else
exit 1
fi
log "Verifying packaged AkShare calendar data..."
packaged_akshare_calendar="${packaged_root}/_internal/akshare/file_fold/calendar.json"
if [[ ! -f "${packaged_akshare_calendar}" ]]; then
packaged_akshare_calendar="${packaged_root}/akshare/file_fold/calendar.json"
fi
if [[ ! -f "${packaged_akshare_calendar}" ]]; then
echo "ERROR: packaged AkShare calendar data not found under ${packaged_root}."
exit 1
fi
log "Verifying static asset references (packaged)..."
packaged_static="${ROOT_DIR}/dist/backend/stock_analysis/_internal/static"
if [[ ! -d "${packaged_static}" ]]; then

View File

@@ -124,6 +124,7 @@ $pyInstallerArgs = @(
'--add-data', 'strategies;strategies',
'--collect-data', 'litellm',
'--collect-data', 'tiktoken',
'--collect-data', 'akshare',
'--collect-all', 'alphasift'
)
$pyInstallerArgs += $hiddenImportArgs
@@ -161,6 +162,15 @@ try {
}
}
Write-Host 'Verifying packaged AkShare calendar data...'
$packagedAkshareCalendar = Join-Path 'dist\backend\stock_analysis' '_internal\akshare\file_fold\calendar.json'
if (-not (Test-Path $packagedAkshareCalendar)) {
$packagedAkshareCalendar = Join-Path 'dist\backend\stock_analysis' 'akshare\file_fold\calendar.json'
}
if (-not (Test-Path $packagedAkshareCalendar)) {
throw 'Packaged AkShare calendar data not found under dist\backend\stock_analysis.'
}
Write-Host 'Verifying static asset references (packaged)...'
$packagedStatic = Join-Path 'dist\backend\stock_analysis' '_internal\static'
if (-not (Test-Path $packagedStatic)) {

View File

@@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-
"""Static contracts for third-party data bundled in desktop backends."""
from __future__ import annotations
import unittest
from pathlib import Path
class DesktopPackagingAssetsTestCase(unittest.TestCase):
"""Keep Windows and macOS PyInstaller package-data rules aligned."""
repo_root = Path(__file__).resolve().parent.parent
def test_scripts_collect_and_verify_akshare_calendar_data(self) -> None:
macos_script = (self.repo_root / "scripts" / "build-backend-macos.sh").read_text(
encoding="utf-8"
)
windows_script = (self.repo_root / "scripts" / "build-backend.ps1").read_text(
encoding="utf-8"
)
self.assertIn("--collect-data akshare", macos_script)
self.assertIn("'--collect-data', 'akshare'", windows_script)
self.assertIn("_internal/akshare/file_fold/calendar.json", macos_script)
self.assertIn("_internal\\akshare\\file_fold\\calendar.json", windows_script)
if __name__ == "__main__":
unittest.main()