brand: 品牌统一为 TSP — 应用名/图标(浅色圆角卡, Windows/macOS 双平台)对齐 brand 资产, README 新增官网入口与标题行内嵌 logo

This commit is contained in:
shy3130
2026-10-05 18:45:09 +08:00
parent af63614610
commit b23db4ecd7
11 changed files with 92 additions and 208 deletions
+18 -29
View File
@@ -46,7 +46,7 @@ jobs:
# 2) 项目依赖 polars, 而 polars 自 1.33 起移除了 macOS x86_64 原生 wheel
# (改 py3-none-any), 在 arm64 runner 上经 Rosetta 无法产出可运行的 x64 包。
# runner 用 macos-26 (2026-02 GA, 免费, arm64 原生, SDK 更新)。
ALL='[{"os":"windows-latest","artifact":"TickFlowStockPanel-Setup-x64.exe","platform":"windows"},{"os":"macos-26","artifact":"TickFlowStockPanel-macos-arm64.dmg","platform":"macos","arch":"arm64"},{"os":"ubuntu-latest","artifact":"TickFlowStockPanel-linux-x64.tar.gz","platform":"linux"}]'
ALL='[{"os":"windows-latest","artifact":"TSP-Setup-x64.exe","platform":"windows"},{"os":"macos-26","artifact":"TSP-macos-arm64.dmg","platform":"macos","arch":"arm64"},{"os":"ubuntu-latest","artifact":"TSP-linux-x64.tar.gz","platform":"linux"}]'
# 按 input 过滤平台 (macos → arm64 单项)
python3 -c "
import json, sys
@@ -115,21 +115,10 @@ jobs:
working-directory: backend
run: uv pip install pyinstaller
- name: 生成 macOS 图标 (仅 macOS)
if: matrix.platform == 'macos'
# icon.ico 已入库 (Windows 直接用), 但 icon.icns 未入库 (macOS 专用产物)。
# 用 generate_icon.py 现场生成, 否则 spec 第 37 行 BUNDLE 会因找不到图标而崩。
# 注意: Pillow 不是 backend 的运行时依赖 (它属于 backtest 的 matplotlib 链),
# --no-dev --extra desktop 不装它, 故需在此显式安装 (仅图标生成需要)。
working-directory: backend
run: |
uv pip install pillow
uv run python ../packaging/generate_icon.py
- name: 打包 (PyInstaller)
# 在 backend 目录跑 (用该目录的 venv: pywebview/polars 等依赖)。
# 产物输出到 backend/dist/ (PyInstaller 默认路径), 与 packaging/tickflow.iss
# 第 78 行的 Source 路径 (..\backend\dist\TickFlowStockPanel\*) 保持一致。
# 第 78 行的 Source 路径 (..\backend\dist\TSP\*) 保持一致。
# SPECPATH 由 spec 文件位置决定 (packaging/tickflow.spec → 项目根),
# 与 cwd 无关, 故 frontend/dist、tiers.yaml 等相对路径仍正确。
working-directory: backend
@@ -139,7 +128,7 @@ jobs:
if: matrix.platform == 'windows'
shell: pwsh
run: |
$runtimeRoot = 'backend/dist/TickFlowStockPanel/_internal'
$runtimeRoot = 'backend/dist/TSP/_internal'
$required = @(
'_polars_runtime_32/_polars_runtime.pyd',
'_polars_runtime_compat/_polars_runtime.pyd'
@@ -164,7 +153,7 @@ jobs:
echo "版本号: $ver"
ISCC.exe "/DMyAppVersion=$ver" packaging/tickflow.iss
# 把生成的 Setup.exe 移到工作区根 (Release 上传用)
Move-Item packaging/Output/TickFlowStockPanel-Setup-$ver.exe ${{ matrix.artifact }} -Force
Move-Item packaging/Output/TSP-Setup-$ver.exe ${{ matrix.artifact }} -Force
shell: pwsh
- name: 生成 DMG (macOS)
@@ -183,19 +172,19 @@ jobs:
--window-pos 200 120 \
--window-size 600 400 \
--icon-size 100 \
--icon "TickFlowStockPanel.app" 175 190 \
--icon "TSP.app" 175 190 \
--app-drop-link 425 190 \
--hide-extension "TickFlowStockPanel.app" \
--hide-extension "TSP.app" \
--skip-jenkins \
--no-internet-enable \
"${{ matrix.artifact }}" \
backend/dist/TickFlowStockPanel.app
backend/dist/TSP.app
- name: 压缩产物 (Linux)
if: matrix.platform == 'linux'
run: |
cd backend/dist
tar -czf ../../${{ matrix.artifact }} TickFlowStockPanel
tar -czf ../../${{ matrix.artifact }} TSP
- name: 上传产物为构建产物 (备查)
uses: actions/upload-artifact@v4
@@ -218,16 +207,16 @@ jobs:
| 平台 | 文件 | 下载 |
| :--- | :--- | :--- |
| **Windows x64** | `TickFlowStockPanel-Setup-x64.exe` | [⬇️ 立即下载](https://github.com/${{ github.repository }}/releases/download/${{ github.event.inputs.version }}/TickFlowStockPanel-Setup-x64.exe) |
| **macOS (Apple Silicon / M 系列芯片)** | `TickFlowStockPanel-macos-arm64.dmg` | [⬇️ 立即下载](https://github.com/${{ github.repository }}/releases/download/${{ github.event.inputs.version }}/TickFlowStockPanel-macos-arm64.dmg) |
| **Linux** | `TickFlowStockPanel-linux-x64.tar.gz` | [⬇️ 立即下载](https://github.com/${{ github.repository }}/releases/download/${{ github.event.inputs.version }}/TickFlowStockPanel-linux-x64.tar.gz) |
| **Windows x64** | `TSP-Setup-x64.exe` | [⬇️ 立即下载](https://github.com/${{ github.repository }}/releases/download/${{ github.event.inputs.version }}/TSP-Setup-x64.exe) |
| **macOS (Apple Silicon / M 系列芯片)** | `TSP-macos-arm64.dmg` | [⬇️ 立即下载](https://github.com/${{ github.repository }}/releases/download/${{ github.event.inputs.version }}/TSP-macos-arm64.dmg) |
| **Linux** | `TSP-linux-x64.tar.gz` | [⬇️ 立即下载](https://github.com/${{ github.repository }}/releases/download/${{ github.event.inputs.version }}/TSP-linux-x64.tar.gz) |
> 💡 点击「立即下载」直接获取, 无需滚动到底部附件区。
> 🍎 **macOS 仅提供 Apple Silicon (M 系列芯片) 版本**: 点左上角 → "关于本机", 看"芯片"一项是否为 Apple; Intel 芯片 Mac 暂不支持 (上游 polars 已停止发布 Intel wheel)。
### 📋 使用说明
- **Windows**: 下载后双击运行, 按安装向导操作(无需管理员权限), 自动创建桌面/开始菜单快捷方式
- **macOS**: 双击 dmg 打开, 将 TickFlowStockPanel 拖入 Applications 文件夹; 首次启动需右键→打开(绕过 Gatekeeper)
- **macOS**: 双击 dmg 打开, 将 TSP 拖入 Applications 文件夹; 首次启动需右键→打开(绕过 Gatekeeper)
- **Linux**: 解压后运行可执行文件
- 数据存储在安装目录下的 `data/` 子文件夹, 卸载重装不丢数据
- 内置 Polars 兼容内核, 新老 CPU (无 AVX2) 均可运行
@@ -253,9 +242,9 @@ jobs:
mkdir -p assets && cd assets
# 只拉已知的三个安装包 (latest.json 自身等其他资产不进清单)
gh release download "$TAG" --repo "$GITHUB_REPOSITORY" \
--pattern 'TickFlowStockPanel-Setup-x64.exe' \
--pattern 'TickFlowStockPanel-macos-arm64.dmg' \
--pattern 'TickFlowStockPanel-linux-x64.tar.gz' \
--pattern 'TSP-Setup-x64.exe' \
--pattern 'TSP-macos-arm64.dmg' \
--pattern 'TSP-linux-x64.tar.gz' \
--clobber || true
cd ..
RELEASE_JSON=$(gh api "repos/$GITHUB_REPOSITORY/releases/tags/$TAG")
@@ -269,9 +258,9 @@ jobs:
# 资产文件名 → 渠道名 (客户端按渠道取下载地址)
channels_cfg = {
"TickFlowStockPanel-Setup-x64.exe": "windows",
"TickFlowStockPanel-macos-arm64.dmg": "macos-arm64",
"TickFlowStockPanel-linux-x64.tar.gz": "linux-x64",
"TSP-Setup-x64.exe": "windows",
"TSP-macos-arm64.dmg": "macos-arm64",
"TSP-linux-x64.tar.gz": "linux-x64",
}
by_name = {a["name"]: a for a in rel.get("assets", [])}
+8 -1
View File
@@ -1,6 +1,8 @@
<div align="center">
# 📈 TSP · A股智能量化工作台
# <picture><source media="(prefers-color-scheme: dark)" srcset="brand/logo-dark-title.svg"><img src="brand/logo-title.svg" width="30" alt="TSP Logo"></picture> TSP · A股智能量化工作台
[![官网](https://img.shields.io/badge/%E5%AE%98%E7%BD%91-tsp.shy313.com-2563eb?style=for-the-badge&logo=googlechrome&logoColor=white&labelColor=1d4ed8)](https://tsp.shy313.com/)
<br/>
@@ -406,6 +408,9 @@ flowchart TB
面板的核心能力不只长在页面上 —— **全部开放成受控接口**,外部程序与 AI 客户端平等消费:
> 🌐 **开放平台门户已上线 → [tsp.shy313.com](https://tsp.shy313.com/)**
> 浏览 TSP 全部功能 · 注册账户 · 邀请好友 · 创建 API Key · 在线调用开放接口,一个入口直达。
<table>
<tr>
<td width="50%" align="center"><b>设置 → 开放接口 · Token 管理</b><br/><sub>明文只显示一次,六档 scope 按需授予</sub></td>
@@ -492,6 +497,8 @@ docker run -d --name tsp -p 3018:3018 -v ${PWD}/data:/app/data ghcr.io/shy3130/t
**打开 <http://localhost:3018> 即可使用** · 多架构镜像(linux/amd64 · arm64)由 CI 自动发布,本地无需 Python / Node
**还没决定要不要部署?** 先逛逛 **[官网 tsp.shy313.com](https://tsp.shy313.com/)** —— 功能总览 · 账户注册 · API Key 管理
</div>
<br/>
+2 -2
View File
@@ -25,7 +25,7 @@ from pathlib import Path
logger = logging.getLogger(__name__)
_APP_NAME = "TickFlow 股票面板"
_APP_NAME = "TSP 股票面板"
_BASE_PORT = 3018
_PORT_PROBE_RANGE = 50 # 从 3018 起最多试 50 个端口
@@ -339,7 +339,7 @@ def main() -> int:
# 写完整 traceback 到 data/desktop.log, 并弹原生 MessageBox 让用户截图反馈。
# 必须排在 KeyboardInterrupt 之后 —— Exception 是基类, 在前会遮蔽它。
logger.exception("桌面客户端启动失败")
_show_crash("TickFlow 启动失败", traceback.format_exc())
_show_crash("TSP 启动失败", traceback.format_exc())
return 1
finally:
_release_single_instance()
+3 -1
View File
@@ -13,6 +13,7 @@
| `logo-badge.svg` | 徽章 · 方底白标 `#8B5CF6 → #6D28D9` | App 图标 / 头像(平台圆角由宿主裁切) |
| `logo-tile-light.svg` | 场景底卡 · 浅色圆角卡 `#F6F6F8` 底 | 文档配图 / 社交卡片(浅色) |
| `logo-tile-dark.svg` | 场景底卡 · 深色圆角卡 `#191C25` 底 + `#232838` 描边 | 文档配图 / 社交卡片(深色) |
| `logo-title.svg` / `logo-dark-title.svg` | 裁剪版 · viewBox 裁至墨迹底边 (`0 0 64 57.6`) | **README 标题行内嵌** — 墨迹贴基线, 与文字垂直居中 |
## PNG(全部透明底)
@@ -25,7 +26,8 @@
## 其他
- `icon.ico` — Windows 应用图标(内嵌 16 / 24 / 32 / 48 / 64 / 128 / 256 七档)
- `icon.ico` — Windows 应用图标(内嵌 16 / 24 / 32 / 48 / 64 / 128 / 256 七档;浅色圆角卡版,由 `png/logo-tile-light-512.png` 派生 —— 透明底渐变 logo 在桌面快捷方式上显得过空,圆角浅卡在深/浅壁纸均成立)
- `icon.icns` — macOS 应用图标(16–1024 八档,含 @2x;与 `icon.ico` 同源同版)
## 接入指引
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

+15
View File
@@ -0,0 +1,15 @@
<!-- Tick Stock Panel · 方案 0 正式主标 — 亮紫渐变 · 透明底 · 全直角
变体: 渐变·深底 (终端 / 暗色 UI)
与 logo.svg 同几何, 仅渐变换为深底优化亮度 -->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 57.6" fill="none" role="img" aria-label="Tick Stock Panel">
<defs>
<linearGradient id="tsp-grad-dark" x1="8" y1="6" x2="56" y2="58" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#C4B5FD"/>
<stop offset="1" stop-color="#8B5CF6"/>
</linearGradient>
</defs>
<path d="M20 9 H11 V55 H20" stroke="url(#tsp-grad-dark)" stroke-width="5" stroke-linejoin="miter" stroke-linecap="butt"/>
<path d="M44 9 H53 V55 H44" stroke="url(#tsp-grad-dark)" stroke-width="5" stroke-linejoin="miter" stroke-linecap="butt"/>
<line x1="32" y1="15" x2="32" y2="49" stroke="url(#tsp-grad-dark)" stroke-width="3.5" stroke-linecap="butt" stroke-opacity="0.55"/>
<rect x="26.5" y="19.5" width="11" height="17" fill="url(#tsp-grad-dark)"/>
</svg>

After

Width:  |  Height:  |  Size: 1023 B

+22
View File
@@ -0,0 +1,22 @@
<!-- Tick Stock Panel 品牌主 logo — 透明底, 品牌紫渐变, 全直角 (无圆角/圆笔帽)
概念: 方括号 [ ] = 终端/代码/量化边界; 中央 K 线 = 行情本体
bullish 姿态: 上影短/下影长, 站稳向上
用法: 浅色背景; 深色背景请用 logo-white.svg -->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 57.6" fill="none" role="img" aria-label="Tick Stock Panel">
<defs>
<linearGradient id="tsp-brand" x1="8" y1="6" x2="56" y2="58" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#A78BFA"/>
<stop offset="1" stop-color="#7C3AED"/>
</linearGradient>
</defs>
<!-- 左方括号 (直角折线) -->
<path d="M20 9 H11 V55 H20"
stroke="url(#tsp-brand)" stroke-width="5" stroke-linejoin="miter" stroke-linecap="butt"/>
<!-- 右方括号 (直角折线) -->
<path d="M44 9 H53 V55 H44"
stroke="url(#tsp-brand)" stroke-width="5" stroke-linejoin="miter" stroke-linecap="butt"/>
<!-- K 线 wick (上影短/下影长, 平头端点) -->
<line x1="32" y1="15" x2="32" y2="49" stroke="url(#tsp-brand)" stroke-width="3.5" stroke-linecap="butt" stroke-opacity="0.55"/>
<!-- K 线 body (直角矩形) -->
<rect x="26.5" y="19.5" width="11" height="17" fill="url(#tsp-brand)"/>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

-156
View File
@@ -1,156 +0,0 @@
"""生成应用图标 — 白色 squircle 背景 + 品牌 gradient Logo。
设计 (与 frontend favicon.svg / brand/logo.svg 一致):
背景: 白色 squircle (macOS Big Sur+ 要求不透明 squircle 背景, 用白色填充)
内容: 品牌渐变 (#A78BFA→#7C3AED, 亮端朝上) 方括号 + K线 (上影短/下影长, bullish 站稳)
蜡烛几何 (32x32 viewBox):
wick: y=7 ~ y=25
body: y=9 ~ y=19 (偏上)
→ 上影 = 2 (短), 下影 = 6 (长)
每尺寸独立绘制: 线条占比全尺寸统一 (~9.4%), 小尺寸微调补偿, 不随尺寸递减。
运行: python packaging/generate_icon.py
产物:
packaging/icon.ico — Windows (16/32/48/64/128/256)
packaging/icon.icns — macOS (16/32/64/128/256/512, 含 @2x)
"""
from __future__ import annotations
from pathlib import Path
from PIL import Image, ImageChops, ImageDraw
OUT_ICO = Path(__file__).parent / "icon.ico"
OUT_ICNS = Path(__file__).parent / "icon.icns"
# 背景: 白色 squircle (不透明, macOS 规范)
BG = (255, 255, 255, 255)
# logo 线条色: 品牌渐变 #A78BFA(亮端,左上) → #7C3AED(品牌紫,右下), 与 favicon.svg/brand/logo.svg 一致
GRAD_A = (167, 139, 250) # #A78BFA
GRAD_B = (124, 58, 237) # #7C3AED
# wick 影线: 70% 不透明 (与 favicon.svg 一致; 16px 最小档经超采样仍可读)
WICK_ALPHA = 0.7
def _grad_image(size_px: int) -> Image.Image:
"""32-viewBox 对角渐变 (4,3)→(28,29), 64px 生成后放大 (线性渐变缩放无损)。"""
small = 64
ax, ay, bx, by = 4 / 32, 3 / 32, 28 / 32, 29 / 32
dx, dy = bx - ax, by - ay
len2 = dx * dx + dy * dy
img = Image.new("RGB", (small, small))
px = img.load()
for y in range(small):
vy = (y + 0.5) / small
for x in range(small):
vx = (x + 0.5) / small
t = max(0.0, min(1.0, ((vx - ax) * dx + (vy - ay) * dy) / len2))
px[x, y] = tuple(round(a + (b - a) * t) for a, b in zip(GRAD_A, GRAD_B))
return img.resize((size_px, size_px), Image.BILINEAR)
def _draw(size: int, sw_b: float, sw_w: float, body_w: float) -> Image.Image:
"""绘制单尺寸图标 (像素直接映射 32-viewBox)。"""
factor = max(8, 2048 // size)
s = size * factor
img = Image.new("RGBA", (s, s), (0, 0, 0, 0))
d = ImageDraw.Draw(img)
# 品牌色 squircle 背景 (圆角方块, macOS Big Sur+ 规范形状, 不透明)
# 纯色填充, 不用渐变 — 渐变在 16px 小尺寸下看不出, 反而易引入 alpha 合成 bug
d.rounded_rectangle([0, 0, s - 1, s - 1], radius=int(s * 0.22), fill=BG)
def p(v):
return v * s / 32
swb = max(1, int(round(sw_b * factor)))
sww = max(1, int(round(sw_w * factor)))
# 标记掩膜: 渐变经 alpha 通道贴入, 线条几何与旧版完全一致
mark = Image.new("L", (s, s), 0)
dm = ImageDraw.Draw(mark)
# 方括号 [ ]
for pts in [[(10, 4), (4, 4), (4, 28), (10, 28)], [(22, 4), (28, 4), (28, 28), (22, 28)]]:
scaled = [(p(x), p(y)) for x, y in pts]
for i in range(len(scaled) - 1):
dm.line([scaled[i], scaled[i + 1]], fill=255, width=swb, joint="curve")
# body 实体 (偏上 → 上影短下影长)
dm.rounded_rectangle(
[p(16 - body_w / 2), p(9), p(16 + body_w / 2), p(19)],
radius=p(0.5), fill=255,
)
# wick 影线 (上短下长, 70% 不透明)
wick = Image.new("L", (s, s), 0)
dw = ImageDraw.Draw(wick)
dw.line([(p(16), p(7)), (p(16), p(25))], fill=255, width=sww)
wcap = sww // 2 + 1
for cy in [7, 25]:
dw.ellipse([p(16) - wcap, p(cy) - wcap, p(16) + wcap, p(cy) + wcap], fill=255)
# 渐变层: alpha = mark + WICK_ALPHA * wick
alpha = ImageChops.add(mark, wick.point(lambda v: round(v * WICK_ALPHA)))
layer = _grad_image(s).convert("RGBA")
layer.putalpha(alpha)
img.alpha_composite(layer)
return img.resize((size, size), Image.LANCZOS)
def draw_logo(size: int) -> Image.Image:
"""按尺寸选参数, 保证各尺寸视觉粗细一致。
核心原则: 所有尺寸线条占图标的视觉比例统一, 不能出现"大尺寸反而显细"。
基准定为 sw=4.0/32 (12.5%) — 经多轮对比选定, Dock 放大时线条仍清晰有力。
小尺寸在基准上略加粗, 抵消像素化糊掉; 大尺寸统一用基准, 不递减。
"""
if size <= 16:
return _draw(size, sw_b=4.5, sw_w=3.8, body_w=9)
elif size <= 32:
return _draw(size, sw_b=4.2, sw_w=3.6, body_w=8)
else:
# ≥48px 统一用基准 4.0, 不随尺寸递减
return _draw(size, sw_b=4.0, sw_w=3.4, body_w=8)
def _save_ico(images_by_size: dict[int, Image.Image]) -> None:
"""Windows .ico (16/32/48/64/128/256)。主图 256 优先, 资源管理器大图清晰。"""
sizes = [16, 32, 48, 64, 128, 256]
images = [images_by_size[s] for s in sizes]
images[-1].save(
OUT_ICO, format="ICO",
sizes=[(s, s) for s in sizes],
append_images=images[:-1],
)
print(f"生成: {OUT_ICO} (尺寸 {sizes})")
def _save_icns(images_by_size: dict[int, Image.Image]) -> None:
"""macOS .icns (16/32/64/128/256/512)。
Apple 要求 .icns 至少含一张大图 (512 或 1024) 才合法, 否则 Finder/Dock
不显示。这里用 512 作主图 (Pillow 12 写 1024 需额外编码, 512 已覆盖
Retina @2x)。@2x 高清由系统从大图自动缩放, 无需单独提供。
"""
sizes = [16, 32, 64, 128, 256, 512]
images = [images_by_size[s] for s in sizes]
images[-1].save(
OUT_ICNS, format="ICNS",
append_images=images[:-1],
)
print(f"生成: {OUT_ICNS} (尺寸 {sizes})")
def main() -> None:
# 一次绘制所有用到的尺寸 (ico 和 icns 取并集), 避免重复绘制
all_sizes = {16, 32, 48, 64, 128, 256, 512}
images_by_size = {sz: draw_logo(sz) for sz in all_sizes}
_save_ico(images_by_size)
_save_icns(images_by_size)
if __name__ == "__main__":
main()
+15 -10
View File
@@ -1,13 +1,13 @@
; ===========================================================================
; Tick Stock Panel — Inno Setup 安装包脚本
; ===========================================================================
; 用途: 把 PyInstaller 产出的 dist/TickFlowStockPanel/ 文件夹封装成
; 用途: 把 PyInstaller 产出的 dist/TSP/ 文件夹封装成
; 单个 Setup.exe 安装程序 (双击→安装向导→快捷方式→可卸载)。
;
; 构建 (本地):
; 1. 先跑 PyInstaller: cd backend && uv run pyinstaller ../packaging/tickflow.spec
; 2. 再跑 Inno Setup: ISCC.exe packaging\tickflow.iss
; 3. 产物: packaging\Output\TickFlowStockPanel-Setup-x.x.x.exe
; 3. 产物: packaging\Output\TSP-Setup-x.x.x.exe
;
; 设计决策:
; - 装到用户目录 {localappdata}\Programs\ (不弹 UAC, 不需管理员)
@@ -18,10 +18,10 @@
; - 卸载入口 (控制面板可见)
; ===========================================================================
#define MyAppName "TickFlow 股票面板"
#define MyAppName "TSP 股票面板"
#define MyAppNameEN "Tick Stock Panel"
#define MyAppExeName "TickFlowStockPanel.exe"
#define MyAppPublisher "TickFlow"
#define MyAppExeName "TSP.exe"
#define MyAppPublisher "TSP"
; 版本号: 从 frontend/package.json 读取, 与 Release tag 保持一致
; 手动指定更可靠 (CI 传入 /DMyAppVersion)
@@ -31,17 +31,20 @@
[Setup]
; 基本信息
; AppId 固定 GUID: Inno 默认从 AppName 派生, 一旦改名旧安装会变成重复程序;
; 固定后应用名再调整也保持同一卸载/升级身份
AppId={{B7F4C9E2-3A51-4D8E-9C60-5E8A2F1D7B43}
AppName={#MyAppName}
AppVerName={#MyAppName} {#MyAppVersion}
AppVersion={#MyAppVersion}
AppPublisher={#MyAppPublisher}
; 默认装到 D 盘 (非系统盘), 用户可在向导中改任意位置
; 若 D 盘不存在, [Code] 段 InitializeWizard 会自动回退到用户目录
DefaultDirName=D:\TickFlowStockPanel
DefaultDirName=D:\TSP
DefaultGroupName={#MyAppName}
DisableProgramGroupPage=yes
OutputDir=Output
OutputBaseFilename=TickFlowStockPanel-Setup-{#MyAppVersion}
OutputBaseFilename=TSP-Setup-{#MyAppVersion}
; 关键: 不需要管理员权限, 永不弹 UAC
; 装到 D 盘普通目录 (非 Program Files) 不需要管理员权限
@@ -58,7 +61,9 @@ LZMAUseSeparateProcess=yes
WizardStyle=modern
DisableWelcomePage=no
DisableReadyPage=no
SetupIconFile=icon.ico
; 安装向导/卸载图标: 直接引用品牌资产唯一来源 (brand/README 接入指引),
; 不再使用 packaging/icon.ico 的旧手绘版本, 避免两处漂移
SetupIconFile=..\brand\icon.ico
UninstallDisplayIcon={app}\{#MyAppExeName}
; 卸载相关
@@ -77,7 +82,7 @@ Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{
[Files]
; 把 PyInstaller 产出的整个文件夹搬进安装目录
; Source 路径相对于 .iss 文件所在目录
Source: "..\backend\dist\TickFlowStockPanel\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "..\backend\dist\TSP\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
[Icons]
; 开始菜单
@@ -139,7 +144,7 @@ begin
// D 盘存在 → 用 D 盘; 否则回退用户目录 (无需管理员权限)
if not DirExists('D:\') then
begin
DefaultDir := ExpandConstant('{localappdata}\Programs\TickFlowStockPanel');
DefaultDir := ExpandConstant('{localappdata}\Programs\TSP');
WizardForm.DirEdit.Text := DefaultDir;
end;
end;
+9 -9
View File
@@ -10,7 +10,7 @@
构建 (在项目根目录):
cd frontend && pnpm build # 先构建前端到 frontend/dist
pyinstaller packaging/tickflow.spec # 产物在 dist/TickFlowStockPanel/
pyinstaller packaging/tickflow.spec # 产物在 dist/TSP/
"""
import sys
from importlib.util import find_spec
@@ -32,10 +32,10 @@ ROOT = Path(SPECPATH).parent
FRONTEND_DIST = str(ROOT / "frontend" / "dist")
TIERS_YAML = str(ROOT / "tiers.yaml")
BUILTIN_STRATEGIES = str(ROOT / "backend" / "app" / "strategy" / "builtin")
# 图标按平台选: Windows 用 .ico, macOS 用 .icns (PyInstaller 对 .ico 在
# mac 上静默忽略, 不换格式 Dock/Finder 会显示通用图标)。两者都由
# packaging/generate_icon.py 一并生成。
APP_ICON = str(ROOT / "packaging" / ("icon.icns" if _IS_MACOS else "icon.ico"))
# 图标按平台选: Windows 用 brand/icon.ico, macOS 用 brand/icon.icns —
# 两者均由 brand/png/logo-tile-light-512.png 派生 (浅色圆角卡版, 品牌资产唯一来源,
# 见 brand/README 接入指引), 无需 CI 现场生成。
APP_ICON = str((ROOT / "brand" / "icon.icns") if _IS_MACOS else (ROOT / "brand" / "icon.ico"))
# ── 收集带原生库的依赖 (.libs/ 目录必须完整, 否则启动崩) ─────────────
# polars / pyarrow / duckdb / fastexcel 都自带共享库子目录
@@ -157,7 +157,7 @@ exe = EXE(
a.scripts,
[],
exclude_binaries=True,
name="TickFlowStockPanel",
name="TSP",
debug=False,
bootloader_ignore_signals=False,
strip=False,
@@ -179,7 +179,7 @@ coll = COLLECT(
strip=False,
upx=False,
upx_exclude=[],
name="TickFlowStockPanel",
name="TSP",
)
# ── macOS: 封装成 .app 包 ────────────────────────────────────────────
@@ -200,13 +200,13 @@ if _IS_MACOS:
app = BUNDLE(
coll,
name="TickFlowStockPanel.app",
name="TSP.app",
icon=APP_ICON,
bundle_identifier="com.tickflow.stockpanel",
version=APP_VERSION, # → CFBundleShortVersionString / CFBundleVersion
info_plist={
"CFBundleName": "Tick Stock Panel",
"CFBundleDisplayName": "TickFlow 股票面板",
"CFBundleDisplayName": "TSP 股票面板",
"CFBundleVersion": APP_VERSION,
"NSHighResolutionCapable": True,
"LSMinimumSystemVersion": "10.13",