feat: — 数据目录/实时监控/定时复盘/老CPU兼容

1. 桌面客户端体验优化,Polars 兼容内核 (老 CPU 兼容)
2. 自选页实时监控优化
3. 个股监控逻辑优化
4. 新增定时复盘
6. 其他: 修复 settings.py 中 HTTPException 未 import 的既有 bug
This commit is contained in:
shy3130
2026-06-28 18:08:52 +08:00
parent b79fe60a56
commit 8a8cd746dc
14 changed files with 512 additions and 27 deletions
+43 -10
View File
@@ -11,7 +11,9 @@
;
; 设计决策:
; - 装到用户目录 {localappdata}\Programs\ (不弹 UAC, 不需管理员)
; - 卸载时询问是否删除用户数据 (%LOCALAPPDATA%\TickFlowStockPanel\)
; - 用户数据存在 {app}\data\ (与程序同处一个总目录, 视觉直观)
; - 卸载时询问是否删除用户数据 ({app}\data\)
; - 覆盖安装(升级)不动 data\: Inno Setup 只写程序文件, data 不在安装清单
; - 桌面 + 开始菜单快捷方式
; - 卸载入口 (控制面板可见)
; ===========================================================================
@@ -93,11 +95,36 @@ Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#MyAppName}}
; 卸载前先关闭正在运行的应用 (否则 exe 被占用删不掉)
Filename: "{cmd}"; Parameters: "/C taskkill /F /IM {#MyAppExeName}"; Flags: runhidden; RunOnceId: "KillApp"
[UninstallDelete]
; 清理安装目录下的残留 (日志等)
Type: filesandordirs; Name: "{app}"
; [UninstallDelete] 故意不删 {app}:
; 用户数据在 {app}\data\, 若这里写 Type: filesandordirs; Name: "{app}" 会连数据一起删。
; 卸载默认行为已足够 —— Inno Setup 会删除它安装清单内的所有程序文件, 只留下运行时
; 生成的 data\ 目录。是否清理 data\ 由下方 [Code] 的卸载询问逻辑决定。
[Code]
// ── 辅助函数: 判断目录是否为空 ─────────────────────────────────
// Inno Setup 内置无 IsDirEmpty, 用 FindFirst/FindNext 自行实现。
// 用于卸载后清理空的 {app} 壳目录。
function IsDirEmpty(const Dir: String): Boolean;
var
FindRec: TFindRec;
begin
Result := True;
if FindFirst(AddBackslash(Dir) + '*', FindRec) then
begin
try
repeat
if (FindRec.Name <> '.') and (FindRec.Name <> '..') then
begin
Result := False;
Break;
end;
until not FindNext(FindRec);
finally
FindClose(FindRec);
end;
end;
end;
// ── 启动时: 若 D 盘不存在, 回退默认路径到用户目录 ───────────────
// 避免默认 D:\... 但系统没 D 盘时向导显示无效路径
function InitializeSetup(): Boolean;
@@ -118,17 +145,17 @@ begin
end;
// ── 卸载时询问是否删除用户数据 ─────────────────────────────────
// 用户数据在 {app} 同级的 TickFlowStockPanel_Data\ (策略/选股/回测/监控/行情)
// 注意: 该目录在 {app} 外, 覆盖安装常规卸载都不会动它, 重装后数据自动恢复
// 这里仅在用户明确「彻底卸载」时才清理
// 用户数据在 {app}\data\ (策略/选股/回测/监控/行情), 与程序同处 {app} 总目录。
// Inno Setup 卸载默认只删它装过的程序文件, data\ 会被保留 (覆盖安装/常规卸载都不丢)
// 这里仅在用户明确「彻底卸载」时, 才询问是否清理 data\ + {app} 空壳
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
var
DataDir: String;
DataDir, AppDir: String;
begin
if CurUninstallStep = usPostUninstall then
begin
// {app}\..\TickFlowStockPanel_Data = 与安装目录同级的独立数据目录
DataDir := ExpandConstant('{app}\..\TickFlowStockPanel_Data');
// {app}\data = 用户数据目录 (与程序同总目录, 子文件夹)
DataDir := ExpandConstant('{app}\data');
if DirExists(DataDir) then
begin
if SuppressibleMsgBox(
@@ -141,5 +168,11 @@ begin
DelTree(DataDir, True, True, True);
end;
end;
// 清理可能残留的空 {app} 壳目录 (程序文件已被 Inno Setup 删除)
AppDir := ExpandConstant('{app}');
if DirExists(AppDir) and IsDirEmpty(AppDir) then
begin
DelTree(AppDir, True, True, True);
end;
end;
end;
+13
View File
@@ -48,6 +48,19 @@ for pkg in ("polars", "pyarrow", "duckdb", "fastexcel"):
binaries += b
hiddenimports += h
# polars-runtime-32 (rtcompat 兼容内核): release.yml 用 --extra legacy-cpu 安装。
# 它是独立的伴侣二进制包 (含 .pyd/.so), 与 polars 主包分开发布,
# collect_all("polars") 抓不到它的目录 —— 必须显式收集, 否则老 CPU 用户
# 运行时 rtcompat 加载器找不到兼容库仍会崩 (Illegal instruction)。
# 不存在时 (未装 legacy-cpu) collect_all 返回空, 不影响普通构建。
try:
rt_d, rt_b, rt_h = collect_all("polars_runtime_32")
datas += rt_d
binaries += rt_b
hiddenimports += rt_h
except Exception:
pass
# polars 新 ABI 运行时目录 (_polars_runtime_32) 需显式收集子模块
hiddenimports += collect_submodules("polars")