Skip to content
This repository was archived by the owner on Apr 22, 2026. It is now read-only.

Commit cecd53c

Browse files
committed
feat(release): 新增关于页与Tag自动发布多平台流程
1 parent 2f35151 commit cecd53c

12 files changed

Lines changed: 781 additions & 0 deletions

.github/workflows/release.yml

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
name: Tag Release
2+
3+
on:
4+
push:
5+
tags:
6+
- "v*"
7+
8+
permissions:
9+
contents: write
10+
11+
jobs:
12+
build:
13+
name: Build ${{ matrix.platform }}
14+
runs-on: ${{ matrix.os }}
15+
strategy:
16+
fail-fast: false
17+
matrix:
18+
include:
19+
- os: ubuntu-latest
20+
platform: linux
21+
- os: macos-latest
22+
platform: macos
23+
- os: windows-latest
24+
platform: windows
25+
26+
steps:
27+
- name: Checkout
28+
uses: actions/checkout@v4
29+
with:
30+
fetch-depth: 0
31+
32+
- name: Setup Python
33+
uses: actions/setup-python@v5
34+
with:
35+
python-version: "3.11"
36+
37+
- name: Install build dependencies
38+
shell: bash
39+
run: |
40+
python -m pip install --upgrade pip
41+
pip install pyinstaller requests curl_cffi pywebview
42+
43+
- name: Build release bundle
44+
shell: bash
45+
run: |
46+
python scripts/build_release_bundle.py --tag "${GITHUB_REF_NAME}" --platform "${{ matrix.platform }}"
47+
48+
- name: Upload bundle artifact
49+
uses: actions/upload-artifact@v4
50+
with:
51+
name: bundle-${{ matrix.platform }}
52+
path: release-artifacts/*.zip
53+
54+
release:
55+
name: Create GitHub Release
56+
runs-on: ubuntu-latest
57+
needs: build
58+
59+
steps:
60+
- name: Checkout
61+
uses: actions/checkout@v4
62+
with:
63+
fetch-depth: 0
64+
65+
- name: Setup Python
66+
uses: actions/setup-python@v5
67+
with:
68+
python-version: "3.11"
69+
70+
- name: Download build artifacts
71+
uses: actions/download-artifact@v4
72+
with:
73+
path: release-assets
74+
pattern: bundle-*
75+
merge-multiple: true
76+
77+
- name: Generate release notes
78+
shell: bash
79+
run: |
80+
python scripts/generate_release_notes.py --tag "${GITHUB_REF_NAME}" --out release_notes.md
81+
82+
- name: Generate SHA256 checksums
83+
shell: bash
84+
run: |
85+
python - <<'PY'
86+
import hashlib
87+
from pathlib import Path
88+
89+
root = Path("release-assets")
90+
lines = []
91+
for p in sorted(root.glob("*.zip")):
92+
h = hashlib.sha256(p.read_bytes()).hexdigest()
93+
lines.append(f"{h} {p.name}")
94+
(root / "SHA256SUMS.txt").write_text("\n".join(lines) + "\n", encoding="utf-8")
95+
PY
96+
97+
- name: Publish release
98+
env:
99+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
100+
shell: bash
101+
run: |
102+
TAG="${GITHUB_REF_NAME}"
103+
if gh release view "$TAG" >/dev/null 2>&1; then
104+
gh release upload "$TAG" release-assets/* --clobber
105+
gh release edit "$TAG" --title "$TAG" --notes-file release_notes.md
106+
else
107+
gh release create "$TAG" release-assets/* --title "$TAG" --notes-file release_notes.md
108+
fi

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,7 @@ __pycache__/
77
*.db
88
gui_config.json
99
!gui_config.example.json
10+
build/
11+
dist/
12+
release-artifacts/
13+
*.spec

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ CodeX Register 是一个桌面化的 Web 控制台,用于统一管理注册流
1818
- [Graph 账号文件格式](#graph-账号文件格式)
1919
- [SMS 管理策略](#sms-管理策略)
2020
- [运行产物](#运行产物)
21+
- [自动发布(Tag Release)](#自动发布tag-release)
2122
- [本地 API 简表](#本地-api-简表)
2223
- [常见问题](#常见问题)
2324

@@ -95,6 +96,7 @@ python gui.py --mode browser --no-auto-open
9596
- `SMS管理`:HeroSMS 开关、API Key、服务代码、国家价格下拉、余额刷新。
9697
- `服务设置`:并发、冷却、重试、网络与指纹相关配置。
9798
- `代理服务`:FlClash 配置与节点探测。
99+
- `关于`:查看版本号、作者、项目介绍,支持一键检测 GitHub 最新版本。
98100
- `运行日志`:完整运行日志输出。
99101

100102
## 配置文件与安全
@@ -269,6 +271,13 @@ bob@outlook.com----pass456----yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy----0.AXEA...
269271
- `local_accounts.db`:本地账号 SQLite 存储(唯一真源)。
270272
- `gui_config.json`:本地配置回写。
271273

274+
## 自动发布(Tag Release)
275+
276+
- 仓库内置 `.github/workflows/release.yml`,当推送 `v*` 标签时自动触发。
277+
- 会在 GitHub Actions 中构建 Windows/macOS/Linux 三个平台包,并上传到同一个 Release。
278+
- Release 描述会包含“更新信息”(标签注释/提交摘要)与校验文件 `SHA256SUMS.txt`
279+
- 构建时会写入 `VERSION``REPOSITORY`,供「关于」页展示版本并检测更新。
280+
272281
## 本地 API 简表
273282

274283
部分常用接口:

REPOSITORY

Whitespace-only changes.

VERSION

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
0.0.0-dev

gui_frontend_app_setup.js

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
{ label: "SMS管理", key: "sms" },
88
{ label: "服务设置", key: "settings" },
99
{ label: "代理服务", key: "proxy" },
10+
{ label: "关于", key: "about" },
1011
{ label: "运行日志", key: "logs" }
1112
];
1213

@@ -173,6 +174,7 @@
173174
remote_refresh: false,
174175
remote_revive: false,
175176
remote_delete: false,
177+
update_check: false,
176178
run_stats_clear: false,
177179
logs: false,
178180
mail_overview: false,
@@ -204,6 +206,30 @@
204206
accounts_per_file: 50
205207
});
206208

209+
const aboutInfo = Vue.reactive({
210+
name: "CodeX Register",
211+
version: "0.0.0-dev",
212+
author: "-",
213+
intro: "",
214+
repo_slug: "",
215+
repo_url: "",
216+
platform: "",
217+
python: ""
218+
});
219+
const updateInfo = Vue.reactive({
220+
checked: false,
221+
checked_at: "",
222+
has_update: false,
223+
current_version: "",
224+
latest_tag: "",
225+
latest_name: "",
226+
published_at: "",
227+
release_url: "",
228+
release_notes: "",
229+
assets: [],
230+
error: ""
231+
});
232+
207233
const remoteRows = Vue.ref([]);
208234
const remoteSelection = Vue.ref([]);
209235
const remoteSearch = Vue.ref("");
@@ -1605,6 +1631,58 @@
16051631
remoteMeta.test_fail = Number(data.remote_test_fail || remoteMeta.test_fail || 0);
16061632
}
16071633

1634+
function applyAboutInfo(data) {
1635+
aboutInfo.name = String((data && data.name) || "CodeX Register");
1636+
aboutInfo.version = String((data && data.version) || "0.0.0-dev");
1637+
aboutInfo.author = String((data && data.author) || "-");
1638+
aboutInfo.intro = String((data && data.intro) || "");
1639+
aboutInfo.repo_slug = String((data && data.repo_slug) || "");
1640+
aboutInfo.repo_url = String((data && data.repo_url) || "");
1641+
aboutInfo.platform = String((data && data.platform) || "");
1642+
aboutInfo.python = String((data && data.python) || "");
1643+
}
1644+
1645+
async function refreshAboutInfo(showSuccess = false) {
1646+
try {
1647+
const data = await apiRequest("/api/app/about");
1648+
applyAboutInfo(data);
1649+
if (showSuccess) message.success("关于信息已刷新");
1650+
} catch (e) {
1651+
if (showSuccess) message.error(String(e.message || e));
1652+
}
1653+
}
1654+
1655+
async function checkAppUpdate() {
1656+
loading.update_check = true;
1657+
try {
1658+
const data = await apiRequest("/api/app/check-update");
1659+
updateInfo.checked = true;
1660+
updateInfo.checked_at = String(data.checked_at || "");
1661+
updateInfo.has_update = !!data.has_update;
1662+
updateInfo.current_version = String(data.current_version || "");
1663+
updateInfo.latest_tag = String(data.latest_tag || "");
1664+
updateInfo.latest_name = String(data.latest_name || "");
1665+
updateInfo.published_at = String(data.published_at || "");
1666+
updateInfo.release_url = String(data.release_url || "");
1667+
updateInfo.release_notes = String(data.release_notes || "");
1668+
updateInfo.assets = Array.isArray(data.assets) ? data.assets : [];
1669+
updateInfo.error = "";
1670+
if (updateInfo.has_update) {
1671+
message.success(`发现新版本:${updateInfo.latest_tag || updateInfo.latest_name}`);
1672+
} else {
1673+
message.info("当前已是最新版本");
1674+
}
1675+
} catch (e) {
1676+
const err = String(e.message || e);
1677+
updateInfo.checked = true;
1678+
updateInfo.has_update = false;
1679+
updateInfo.error = err;
1680+
message.error(err);
1681+
} finally {
1682+
loading.update_check = false;
1683+
}
1684+
}
1685+
16081686
async function pullLogs() {
16091687
if (loading.logs) return;
16101688
loading.logs = true;
@@ -2960,6 +3038,7 @@
29603038
loadMailDomainStats(),
29613039
refreshSmsOverview(false, true),
29623040
refreshSmsCountryOptions(false, true),
3041+
refreshAboutInfo(false),
29633042
loadStatus(),
29643043
pullLogs()
29653044
]);
@@ -3037,6 +3116,10 @@
30373116
]);
30383117
return;
30393118
}
3119+
if (tab === "about") {
3120+
await refreshAboutInfo(false);
3121+
return;
3122+
}
30403123
if (tab === "mail") {
30413124
if (normalizeMailProvider(mailProviderTab.value) === "graph") {
30423125
await refreshGraphAccountFiles(false);
@@ -3095,6 +3178,8 @@
30953178
accountManageTab,
30963179
showSub2ApiExportModal,
30973180
sub2apiExportForm,
3181+
aboutInfo,
3182+
updateInfo,
30983183
remoteRows,
30993184
remoteSelection,
31003185
remoteSearch,
@@ -3206,6 +3291,8 @@
32063291
stopRun,
32073292
clearLogs,
32083293
clearRunStats,
3294+
refreshAboutInfo,
3295+
checkAppUpdate,
32093296
onLogUserWheel,
32103297
onLogUserScroll,
32113298
manualPoll

gui_frontend_app_template.html

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -861,6 +861,63 @@ <h1>注册任务面板</h1>
861861
</n-card>
862862
</div>
863863

864+
<div v-else-if="activeTab === 'about'" class="tab-page">
865+
<n-card class="glass-card" title="关于" size="small">
866+
<div class="about-head">
867+
<div class="about-name">{{ aboutInfo.name }}</div>
868+
<n-tag type="info" :bordered="false">v{{ aboutInfo.version }}</n-tag>
869+
</div>
870+
<div class="about-intro">{{ aboutInfo.intro }}</div>
871+
872+
<div class="about-grid">
873+
<div class="about-item"><span class="about-label">作者</span><span class="about-value">{{ aboutInfo.author || '-' }}</span></div>
874+
<div class="about-item"><span class="about-label">仓库</span><a class="about-link" :href="aboutInfo.repo_url || '#'" target="_blank" rel="noreferrer">{{ aboutInfo.repo_slug || '未检测到' }}</a></div>
875+
<div class="about-item"><span class="about-label">平台</span><span class="about-value">{{ aboutInfo.platform || '-' }}</span></div>
876+
<div class="about-item"><span class="about-label">Python</span><span class="about-value">{{ aboutInfo.python || '-' }}</span></div>
877+
</div>
878+
879+
<div class="toolbar" style="margin-top: 10px">
880+
<n-button class="toolbar-btn" :loading="loading.update_check" type="primary" @click="checkAppUpdate">检测更新</n-button>
881+
<n-button class="toolbar-btn" @click="refreshAboutInfo(true)">刷新信息</n-button>
882+
</div>
883+
884+
<div v-if="updateInfo.checked" class="about-update-box">
885+
<div class="about-update-line">
886+
<span class="about-label">检测时间</span>
887+
<span class="about-value">{{ updateInfo.checked_at || '-' }}</span>
888+
</div>
889+
<div class="about-update-line">
890+
<span class="about-label">当前版本</span>
891+
<span class="about-value">{{ updateInfo.current_version || aboutInfo.version }}</span>
892+
</div>
893+
<div class="about-update-line">
894+
<span class="about-label">最新版本</span>
895+
<span class="about-value">{{ updateInfo.latest_tag || '-' }}</span>
896+
</div>
897+
<div class="about-update-line" v-if="updateInfo.published_at">
898+
<span class="about-label">发布时间</span>
899+
<span class="about-value">{{ updateInfo.published_at }}</span>
900+
</div>
901+
<div class="about-update-line" v-if="updateInfo.release_url">
902+
<span class="about-label">发布页</span>
903+
<a class="about-link" :href="updateInfo.release_url" target="_blank" rel="noreferrer">打开 Release</a>
904+
</div>
905+
<div class="about-update-line" v-if="updateInfo.error">
906+
<span class="about-label">结果</span>
907+
<span class="about-value" style="color:#f46b78">{{ updateInfo.error }}</span>
908+
</div>
909+
<div class="about-update-line" v-else>
910+
<span class="about-label">结果</span>
911+
<span class="about-value">{{ updateInfo.has_update ? '发现新版本' : '当前已是最新版本' }}</span>
912+
</div>
913+
<div v-if="updateInfo.release_notes" class="about-release-notes">
914+
<div class="about-label" style="margin-bottom: 4px">更新信息</div>
915+
<pre>{{ updateInfo.release_notes }}</pre>
916+
</div>
917+
</div>
918+
</n-card>
919+
</div>
920+
864921
</n-scrollbar>
865922

866923
<div v-else class="log-page-shell">

0 commit comments

Comments
 (0)