Compare commits
4
Commits
v1.0.21
...
Dev_20261001
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
309de439e8 | ||
|
|
a381d7be03 | ||
|
|
14f5963706 | ||
|
|
40336d014d |
No files matched your search
@@ -10,9 +10,12 @@ Electron + electron-vite + React 终端工具(本地终端 / SSH / SFTP)。
|
||||
- 测试:`npm test`(**npm 生命周期先自动跑 `pretest` 做类型检查**,再 `node tests/build-bundles.cjs` 重建 esbuild bundle,然后依次跑可离线运行的 18 个测试:ssh-loopback、commands-store、connections-store、settings-store、local-path-grants、lock-store、lock-controller、lock-shortcuts、hl-split-smoke、hl-rules、reserved-accelerators、ipc-guard、updater-fallback、log-sanitizer、sftp-timeout、terminal-title、zmodem-e2e、ssh-session-e2e、sysinfo-e2e;真实服务器测试需 JD_* 凭据,不在此列)
|
||||
- 依赖分类规则:**只有 `src/main/`/`src/preload/` 实际 import 的包才能进 `dependencies`**(node-pty/ssh2/zmodem.js/font-list/electron-updater);纯渲染层依赖一律 devDependencies(Vite 全量打包进 out/renderer,`externalizeDepsPlugin` 不作用渲染层)——这条让 asar 从 98MB 瘦到 8.1MB,加新依赖时别放错边
|
||||
- 下载量统计:`node scripts/download-stats.cjs`(Gitea + GitHub release 资产的 download_count 汇总;GitHub 优先直连、失败自动回退 `HTTPS_PROXY`/本地 7897;更新通道无计数接口不计入)
|
||||
- 打包:`npm run dist`(**生命周期先自动跑 `predist` → `npm test`,即类型检查 + 18 个离线测试全部通过后才 build/package**,typecheck 全程只跑一次;predist 末尾的 `npm install --package-lock-only` 会把 `package-lock.json` 根版本号对齐 `package.json`,**发布提交必须带上 package-lock.json**),产物在 `release/`(msi + exe + latest.yml + blockmap)
|
||||
- 打包:`npm run dist`(**生命周期先自动跑 `predist` → `npm test`,即类型检查 + 18 个离线测试全部通过后才 build/package**,typecheck 全程只跑一次;predist 末尾的 `npm install --package-lock-only` 会把 `package-lock.json` 根版本号对齐 `package.json`,**发布提交必须带上 package-lock.json**),产物在 `release/`(exe + latest.yml + blockmap)
|
||||
- GitHub Actions:`.github/workflows/ci.yml` 在 windows-latest + Node 22 上跑 `npm ci` / `npm test`(含 pretest typecheck)/ `npm run build`,只做验证,不打包安装器、不发布
|
||||
- 国内网络需镜像:`ELECTRON_MIRROR=https://npmmirror.com/mirrors/electron/ ELECTRON_BUILDER_BINARIES_MIRROR=https://npmmirror.com/mirrors/electron-builder-binaries/ npm run dist`
|
||||
- 依赖一致性闸门:`predist` 开头跑 `node scripts/verify-deps.cjs`(逐条比对 `node_modules` 与 `package-lock.json` 的版本,跨平台 optional 依赖缺失跳过;不一致就 exit 1)——`npm install --package-lock-only` **只重算 lockfile、不碰 node_modules**(本版 npm 还会把 `node_modules/.package-lock.json` 一并重写成理想树,制造「已经装好了」的假象),所以**改动依赖版本后必须真实 `npm install` 或 `npm ci` 再构建**,别指望 lockfile 对齐就等于树里换了包;v1.0.21 的中文输入法回归正是这个坑(`@xterm/xterm` 锁 6.1.0-beta.304,树里还是 6.0.0,打进去的是旧代码)
|
||||
- **换机/重装环境后第一次打包前必须先跑 `npm ci`**(verify-deps 会兜底拦截,但别浪费一次构建);在任何机器上都先 `node scripts/verify-deps.cjs` 确认再 `npm run dist`
|
||||
- electron-builder `rename win-unpacked.tmp` 撞 EPERM = 安全软件实时扫描新解压文件短暂持锁(实测约 4s,进程退出后数秒即可手动重命名)。应对:`NODE_OPTIONS="--require $(pwd -W)/scripts/rename-retry-shim.cjs" npm run dist`(注入重试垫片,stderr 会打印每次重试);根治是把仓库目录加进安全软件信任区
|
||||
|
||||
## 仓库与远程
|
||||
|
||||
@@ -31,20 +34,20 @@ Electron + electron-vite + React 终端工具(本地终端 / SSH / SFTP)。
|
||||
2. `node scripts/sync-changelog.cjs` 把发布说明并入 `CHANGELOG*.md` —— **必须在 `npm run dist` 之前**:更新日志以 `?raw` 打进安装包(「关于」页离线读),`release.cjs` 也校验 `CHANGELOG.md` 已含该版本号
|
||||
3. `npm run dist` 构建
|
||||
4. `node scripts/release.cjs <版本号>`,例如 `node scripts/release.cjs 1.0.14`(**不带 skip 参数**,Gitea 与 GitHub 一起发)
|
||||
- Gitea:release(msi + exe 资产)→ Gitea 更新通道(`api/packages/admin/generic/openterminal-update/stable`:exe.blockmap → exe → release-notes.md → **latest.yml 最后**)
|
||||
- Gitea:release(exe 资产)→ Gitea 更新通道(`api/packages/admin/generic/openterminal-update/stable`:exe.blockmap → exe → release-notes.md → **latest.yml 最后**)
|
||||
- GitHub:release 资产再次随版本同步发布(exe + exe.blockmap + latest.yml),electron-updater 标准 GitHub provider 直接吃 release 资产
|
||||
- 通道不再先删旧版:新版本文件全部传完、latest.yml 生效后才清掉上一版 exe/blockmap,中途失败不会把通道打空;同一版本可重复运行(release 复用、已传资产跳过)
|
||||
- 上传前先比通道版本:`assertNoDowngrade()` 读通道 latest.yml,若线上版本**高于**待发布版本就直接拒绝——三条本地护栏只比本地产物,旧分支发旧版本号会一路通过,覆盖 latest.yml 之后 `pruneChannel` 会把线上新版本的 exe/blockmap 删掉
|
||||
- 只补通道:`node scripts/release.cjs <版本号> --channel-only`(不建 release、不发 GitHub)
|
||||
- 国内通道全程直连,**不需要设代理**;GitHub 请求走 `HTTPS_PROXY=http://127.0.0.1:7897`(脚本只把它用于 GitHub 请求)
|
||||
5. 验证更新通道:`curl https://git.codingplan.site/api/packages/admin/generic/openterminal-update/stable/latest.yml` 应返回新版本号
|
||||
6. `git tag v<版本号>` 并推送两个远程(代码/tag 与 release 资产的镜像保持同步)
|
||||
6. `git tag v<版本号>` 并推送两个远程(代码/tag 与 release 资产的镜像保持同步)。注意顺序坑:release.cjs 创建 release 时若远端尚无该 tag,Gitea/GitHub 会在**默认分支 HEAD** 自动建一个指向错误 commit 的 tag,第 6 步推送会被拒——要么先建 tag 推上去再跑 release.cjs,要么事后 `git push -f <远端> v<版本号>` 强制修正到 release commit(v1.0.22 即踩过)
|
||||
|
||||
## 更新机制
|
||||
|
||||
- 检查更新:**GitHub 优先**(走系统代理;前置 20 秒连通性探测 `probeGithub`——探测失败/超时直接兜底 Gitea,不给 electron-updater 挂起的机会),失败回退国内 Gitea 通用包通道(强制直连,不走系统代理)。 electron-updater 用独立 session(partition `electron-updater`),代理模式在 `useFeed` 里按源切换
|
||||
- 更新日志:Gitea 仓库是私有的(匿名 API 404),改为从更新通道的 `release-notes.md` 读取(直连 session `openterminal-update-direct`),再回退 Gitea/GitHub releases API
|
||||
- electron-updater 不支持 MSI 自动更新,自动更新只走 NSIS exe
|
||||
- 自动更新只走 NSIS exe;自 v1.0.22 起不再构建 MSI 安装包(electron-updater 本就不支持 MSI 自动更新)
|
||||
- 每次 checkForUpdates 都被 **30s 整体超时**包住(`withTimeout`):electron-updater 自带的 60s 只是 socket 空闲超时,慢滴流响应能一直占住它。超时按普通失败走 GitHub→Gitea 回退,但**被放弃的检查取消不掉**,而 electron-updater 对并发检查去重(返回同一个 in-flight promise),所以兜底那次共用被放弃的 promise——它同样被超时兜住,最终落到错误态,不会永远停在「检查中」
|
||||
- 更新日志 / releases API 的 fetch 都带 `AbortSignal.timeout(15s)`(`directFetch` 与 `fetchChangelog` 里的 `net.fetch`):卡住的通道必须让位给下一个来源,不能把「关于」页吊住
|
||||
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
# OpenTerminal Changelog
|
||||
|
||||
## v1.0.22 - 2026-10-08
|
||||
|
||||
### IME
|
||||
- **Fixed: Chinese IME candidate window not following the caret** (regression in v1.0.21): the v1.0.21 build environment had a terminal component dependency that did not match the locked version, so the installer shipped an older build without the upstream IME fix; this release restores the terminal component version used by v1.0.20, and the candidate window follows the caret again.
|
||||
|
||||
### Installer
|
||||
- The MSI installer is discontinued (electron-updater never supported MSI auto-updates); the NSIS exe is now the only installer format.
|
||||
|
||||
### Internal
|
||||
- The packaging pipeline now verifies dependency consistency before building: installed dependencies are compared against the lockfile and the build aborts on any mismatch, preventing this class of issue from recurring.
|
||||
|
||||
## v1.0.21 - 2026-10-07
|
||||
|
||||
### Background image experience
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
# OpenTerminal 更新履歴
|
||||
|
||||
## v1.0.22 - 2026-10-08
|
||||
|
||||
### IME
|
||||
- **中国語 IME の候補ウィンドウがキャレットに追従しない問題を修正**(v1.0.21 でのリグレッション):v1.0.21 のビルド環境では端末コンポーネントの依存がロックされたバージョンと一致しておらず、インストーラーには上流の IME 修正を含まない古いビルドが同梱されていました。本バージョンでは v1.0.20 と同じ端末コンポーネントに戻し、候補ウィンドウが再びキャレットに追従します。
|
||||
|
||||
### インストーラー
|
||||
- MSI インストーラーの提供を終了しました(electron-updater は MSI の自動更新に非対応のため)。今後は NSIS exe インストーラーに統一されます。
|
||||
|
||||
### 内部
|
||||
- パッケージング前に依存関係の整合性チェックを追加:インストール済み依存とロックファイルを照合し、不一致があればビルドを中止します。同種の問題の再発を防ぎます。
|
||||
|
||||
## v1.0.21 - 2026-10-07
|
||||
|
||||
### 背景画像の体験
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
# OpenTerminal 更新日志
|
||||
|
||||
## v1.0.22 - 2026-10-08
|
||||
|
||||
### 输入法
|
||||
- **修复中文输入法候选窗不跟随光标**(v1.0.21 回归):v1.0.21 的构建环境中终端组件依赖未按锁定版本安装,安装包实际打进的是不含上游输入法修复的旧版本;本版本恢复 v1.0.20 所用的终端组件版本,候选窗重新紧贴光标。
|
||||
|
||||
### 安装包
|
||||
- 不再提供 MSI 安装包(electron-updater 本就不支持 MSI 自动更新),统一使用 NSIS exe 安装包。
|
||||
|
||||
### 内部
|
||||
- 打包流程新增依赖一致性校验:构建前自动比对实际安装的依赖与锁定清单,不一致即中止,防止同类问题再次发生。
|
||||
|
||||
## v1.0.21 - 2026-10-07
|
||||
|
||||
### 背景图体验
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
# OpenTerminal 更新日誌
|
||||
|
||||
## v1.0.22 - 2026-10-08
|
||||
|
||||
### 輸入法
|
||||
- **修復中文輸入法候選視窗不跟隨游標**(v1.0.21 回歸):v1.0.21 的建置環境中終端機元件相依未按鎖定版本安裝,安裝包實際打包的是不含上游輸入法修復的舊版本;本版本恢復 v1.0.20 所用的終端機元件版本,候選視窗重新緊貼游標。
|
||||
|
||||
### 安裝包
|
||||
- 不再提供 MSI 安裝包(electron-updater 本就不支援 MSI 自動更新),統一使用 NSIS exe 安裝包。
|
||||
|
||||
### 內部
|
||||
- 打包流程新增相依一致性校驗:建置前自動比對實際安裝的相依與鎖定清單,不一致即中止,防止同類問題再次發生。
|
||||
|
||||
## v1.0.21 - 2026-10-07
|
||||
|
||||
### 背景圖體驗
|
||||
|
||||
+2
-13
@@ -16,23 +16,12 @@ asarUnpack:
|
||||
# @lydell/node-pty ships prebuilt binaries; do not trigger a rebuild.
|
||||
npmRebuild: false
|
||||
|
||||
# Electron-updater only supports NSIS auto-updates (MSI has no update channel).
|
||||
# The NSIS .exe + latest.yml get uploaded together; MSI is manual/enterprise only.
|
||||
# NSIS exe is the only installer: electron-updater only supports NSIS
|
||||
# auto-updates, so the MSI (no update channel) was dropped in v1.0.22.
|
||||
win:
|
||||
target:
|
||||
- target: msi
|
||||
- target: nsis
|
||||
|
||||
msi:
|
||||
oneClick: false
|
||||
# Fixed upgrade code keeps the upgrade chain consistent across releases.
|
||||
upgradeCode: "{5ab9f79e-e4eb-4052-9df6-3af3a301ab0a}"
|
||||
artifactName: ${productName}-${version}-setup.${ext}
|
||||
# Shortcuts need an <Icon>; build/icon.png (auto-converted to .ico) provides it.
|
||||
# Without an icon the WiX shortcut Icon reference fails to link (LGHT0094).
|
||||
createDesktopShortcut: true
|
||||
createStartMenuShortcut: true
|
||||
|
||||
nsis:
|
||||
oneClick: false
|
||||
allowToChangeInstallationDirectory: true
|
||||
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "open-terminal",
|
||||
"version": "1.0.21",
|
||||
"version": "1.0.22",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "open-terminal",
|
||||
"version": "1.0.21",
|
||||
"version": "1.0.22",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lydell/node-pty": "^1.2.0-beta.15",
|
||||
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "open-terminal",
|
||||
"productName": "OpenTerminal",
|
||||
"version": "1.0.21",
|
||||
"version": "1.0.22",
|
||||
"description": "Open-source terminal with SSH, split panes, themes and fonts",
|
||||
"main": "out/main/index.js",
|
||||
"author": "CodingPlan.Site",
|
||||
@@ -14,8 +14,8 @@
|
||||
"typecheck": "tsc --noEmit -p tsconfig.node.json && tsc --noEmit -p tsconfig.web.json",
|
||||
"pretest": "npm run typecheck",
|
||||
"test": "node tests/build-bundles.cjs && node tests/ssh-loopback.mjs && node tests/commands-store.mjs && node tests/connections-store.mjs && node tests/settings-store.mjs && node tests/local-path-grants.mjs && node tests/lock-store.mjs && node tests/lock-controller.mjs && node tests/lock-shortcuts.mjs && node tests/reserved-accelerators.mjs && node tests/.terminal-title.cjs && node tests/ipc-guard.mjs && node tests/updater-fallback.mjs && node tests/log-sanitizer.mjs && node tests/sftp-timeout.mjs && node tests/.hl-split-smoke.cjs && node tests/.hl-rules.cjs && node tests/zmodem-e2e.mjs && node tests/ssh-session-e2e.mjs && node tests/sysinfo-e2e.mjs",
|
||||
"predist": "npm test && npm install --package-lock-only",
|
||||
"dist": "electron-vite build && electron-builder --win msi nsis",
|
||||
"predist": "node scripts/verify-deps.cjs && npm test && npm install --package-lock-only",
|
||||
"dist": "electron-vite build && electron-builder --win nsis",
|
||||
"dist:dir": "electron-vite build && electron-builder --win --dir"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
+5
-7
@@ -42,14 +42,12 @@ const env = Object.fromEntries(
|
||||
)
|
||||
const notes = fs.readFileSync(path.join(ROOT, 'RELEASE_NOTES.md'), 'utf8')
|
||||
const R = path.join(ROOT, 'release')
|
||||
const msi = path.join(R, `OpenTerminal-${V}-setup.msi`)
|
||||
const exe = path.join(R, `OpenTerminal-${V}-setup.exe`)
|
||||
const files = [msi, exe]
|
||||
// --channel-only republishes the update channel, which carries the NSIS exe and
|
||||
// its blockmap (electron-updater cannot consume an MSI) — the msi is a release
|
||||
// asset only, so demanding it here would block the repair path this mode exists
|
||||
// for. The channel's own file list is validated in giteaChannel().
|
||||
for (const f of CHANNEL_ONLY ? [exe] : files) {
|
||||
const files = [exe]
|
||||
// Only the NSIS exe is built (the MSI was dropped in v1.0.22 — electron-updater
|
||||
// never supported it). The channel's own file list is validated in
|
||||
// giteaChannel().
|
||||
for (const f of files) {
|
||||
if (!fs.existsSync(f)) { console.error('missing build artifact:', f); process.exit(1) }
|
||||
}
|
||||
// Guard rails: the artifacts must belong to the version being published —
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
// 构建垫片:Windows 上安全软件实时扫描新解压的文件时会短暂持有目录句柄(实测 ~4s),
|
||||
// electron-builder 解包后立即 rename 会撞 EPERM。对 fs.promises 的 rename/rm/unlink/copyFile
|
||||
// 加 EPERM/EBUSY/ENOTEMPTY 重试(30 次 × 1s),stderr 会打印每次重试。
|
||||
// 用法(命中 EPERM 时):NODE_OPTIONS="--require $(pwd -W)/scripts/rename-retry-shim.cjs" npm run dist
|
||||
const fs = require('node:fs');
|
||||
|
||||
const RETRY_CODES = new Set(['EPERM', 'EBUSY', 'ENOTEMPTY']);
|
||||
const MAX_TRIES = 30;
|
||||
const DELAY_MS = 1000;
|
||||
|
||||
function wrap(name) {
|
||||
const orig = fs.promises[name];
|
||||
if (typeof orig !== 'function') return;
|
||||
fs.promises[name] = async function (...args) {
|
||||
for (let i = 0; ; i++) {
|
||||
try {
|
||||
return await orig.apply(fs.promises, args);
|
||||
} catch (err) {
|
||||
if (!RETRY_CODES.has(err && err.code) || i >= MAX_TRIES - 1) throw err;
|
||||
process.stderr.write(`[rename-retry-shim] ${name} ${args[0]} -> ${err.code}, retry ${i + 1}/${MAX_TRIES}\n`);
|
||||
await new Promise(r => setTimeout(r, DELAY_MS));
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
wrap('rename');
|
||||
wrap('rm');
|
||||
wrap('unlink');
|
||||
wrap('copyFile');
|
||||
@@ -0,0 +1,59 @@
|
||||
/* Dependency consistency gate: node_modules must match package-lock.json.
|
||||
|
||||
Usage: node scripts/verify-deps.cjs (runs first in `predist`)
|
||||
|
||||
Why it exists: v1.0.21 shipped an input-method fix that never reached the
|
||||
build. @xterm/xterm had been pinned to 6.1.0-beta.304 in package.json, but
|
||||
node_modules still held 6.0.0 from an older install — `npm install
|
||||
--package-lock-only` (the last step of predist) rewrites only the lockfile,
|
||||
so the lockfile agreed with package.json while the tree on disk stayed
|
||||
stale, and the bundler took the stale tree. An install that never happened
|
||||
is invisible to every other check, so it gets its own gate here.
|
||||
|
||||
Scope: version equality only, for every entry the lockfile lists under
|
||||
node_modules. The root entry ("") is deliberately excluded — bumping
|
||||
package.json makes the lockfile root version lag by design until the
|
||||
`npm install --package-lock-only` at the end of predist rewrites it. */
|
||||
const fs = require('node:fs')
|
||||
const path = require('node:path')
|
||||
|
||||
const ROOT = path.join(__dirname, '..')
|
||||
const lock = JSON.parse(fs.readFileSync(path.join(ROOT, 'package-lock.json'), 'utf8'))
|
||||
const packages = lock.packages ?? {}
|
||||
|
||||
const mismatched = []
|
||||
let checked = 0
|
||||
// Optional entries are the cross-platform variants (darwin/linux/arm64 …) that
|
||||
// npm records in the lockfile but never installs on this machine. Their absence
|
||||
// is expected, not drift.
|
||||
let skippedOptional = 0
|
||||
|
||||
for (const [key, entry] of Object.entries(packages)) {
|
||||
if (key === '' || !key.startsWith('node_modules/')) continue
|
||||
// The key is the path under node_modules, so it also resolves nested
|
||||
// ("node_modules/a/node_modules/b") and scoped ("node_modules/@scope/pkg")
|
||||
// entries without any name reconstruction.
|
||||
let installed
|
||||
try {
|
||||
installed = JSON.parse(fs.readFileSync(path.join(ROOT, key, 'package.json'), 'utf8')).version
|
||||
} catch {
|
||||
installed = undefined
|
||||
}
|
||||
if (installed === undefined) {
|
||||
if (entry.optional) skippedOptional++
|
||||
else mismatched.push([key, entry.version, 'MISSING'])
|
||||
continue
|
||||
}
|
||||
checked++
|
||||
if (installed !== entry.version) mismatched.push([key, entry.version, installed])
|
||||
}
|
||||
|
||||
if (mismatched.length) {
|
||||
console.error('node_modules does not match package-lock.json:')
|
||||
for (const [name, expected, actual] of mismatched) {
|
||||
console.error(` ${name}: lockfile expects ${expected}, installed ${actual}`)
|
||||
}
|
||||
console.error('\nnode_modules 与 package-lock.json 不一致,请运行 npm ci 重装依赖')
|
||||
process.exit(1)
|
||||
}
|
||||
console.log(`dependencies ok: ${checked} packages verified, ${skippedOptional} optional entries skipped`)
|
||||
+6
-5
@@ -15,19 +15,20 @@ website/
|
||||
├── .nojekyll # 让 GitHub Pages 原样托管(跳过 Jekyll 处理)
|
||||
└── assets/
|
||||
├── style.css # 全部样式(企业风浅色主题,单一强调色)
|
||||
├── shot-terminal.png # 主界面截图(四路分屏)
|
||||
├── shot-themes.png # 主题设置页截图
|
||||
├── shot-terminal.jpg # 主界面截图(三路分屏并行 AI 编程 Agent,含背景图个性化)
|
||||
├── shot-agents.png # 多路 AI Agent 分屏截图(无背景图版)
|
||||
├── shot-themes.jpg # 主题设置页截图(背景图/不透明度/压暗层)
|
||||
├── shot-lock.png # 锁屏界面截图
|
||||
└── icon.png # 应用图标(来自仓库 build/icon.png)
|
||||
```
|
||||
|
||||
## 发新版本时需要更新的地方
|
||||
|
||||
`index.html` 中搜索 `1.0.15`,共 3 处下载链接(hero 主按钮、下载表格 exe、msi)。
|
||||
下载链接使用 GitHub Releases 原生地址:
|
||||
`index.html` 中搜索当前版本号,共 2 处下载链接(hero 主按钮、下载表格 exe)。
|
||||
自 v1.0.22 起不再提供 MSI,只有 NSIS exe 一条直链:
|
||||
|
||||
```
|
||||
https://github.com/billowliu2/OpenTerminal/releases/download/v<版本>/OpenTerminal-<版本>-setup.exe
|
||||
https://github.com/billowliu2/OpenTerminal/releases/download/v<版本>/OpenTerminal-<版本>-setup.msi
|
||||
```
|
||||
|
||||
注意:发布新版本时需同时把安装包资产上传到 GitHub release
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 96 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 29 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 315 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 83 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 201 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 101 KiB |
+57
-34
@@ -37,22 +37,22 @@
|
||||
内置 SFTP 文件管理与广播输入。安装即用,支持自动更新。
|
||||
</p>
|
||||
<div class="hero-actions">
|
||||
<a class="btn btn-primary" id="dl-exe" href="https://github.com/billowliu2/OpenTerminal/releases/download/v1.0.15/OpenTerminal-1.0.15-setup.exe">
|
||||
<a class="btn btn-primary" id="dl-exe" href="https://github.com/billowliu2/OpenTerminal/releases/download/v1.0.22/OpenTerminal-1.0.22-setup.exe">
|
||||
下载 Windows 安装包
|
||||
</a>
|
||||
<a class="btn btn-ghost" href="https://github.com/billowliu2/OpenTerminal" target="_blank" rel="noopener">
|
||||
查看源码
|
||||
</a>
|
||||
</div>
|
||||
<p class="hero-note">当前版本 v1.0.15 · 提供 exe 与 msi 安装包。</p>
|
||||
<p class="hero-note">当前版本 v1.0.22 · NSIS exe 安装包,支持应用内自动更新。</p>
|
||||
</div>
|
||||
<figure class="hero-shot">
|
||||
<img src="assets/shot-terminal.png" alt="OpenTerminal 主界面:四个分屏终端会话" width="1282" height="801" />
|
||||
<figcaption>四路分屏会话,每路独立连接本地或远程主机</figcaption>
|
||||
<img src="assets/shot-terminal.jpg" alt="OpenTerminal 主界面:三路分屏并行运行 Kimi Code、Claude Code 与 Codex" width="1739" height="870" />
|
||||
<figcaption>三路分屏并行运行 AI 编程 Agent,背景图与压暗层可自定义</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
<div class="container spec-strip">
|
||||
<span>当前版本 <strong class="mono">1.0.15</strong></span>
|
||||
<span>当前版本 <strong class="mono">1.0.22</strong></span>
|
||||
<span>Windows 10 / 11 · x64</span>
|
||||
<span>MIT 开源协议</span>
|
||||
<span>exe 支持应用内自动更新</span>
|
||||
@@ -71,7 +71,7 @@
|
||||
<li>node-pty 本地会话,自动探测 PowerShell / zsh / bash</li>
|
||||
<li>xterm.js WebGL 渲染,声明 256 色与真彩能力,异常时自动降级</li>
|
||||
<li>内嵌搜索(Ctrl+F)、命令历史、粘贴风险确认</li>
|
||||
<li>关键词高亮:内置 11 条规则(错误状态、路径、IP、URL 等),支持自定义正则</li>
|
||||
<li>关键词高亮:22 条内置规则(错误状态、路径、IP、URL 等),支持自定义正则与三档强度</li>
|
||||
<li>字体、字重、字距、行高、光标样式实时生效</li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -89,19 +89,49 @@
|
||||
|
||||
<div class="feature-row media-row">
|
||||
<figure class="feature-shot">
|
||||
<img src="assets/shot-themes.png" alt="OpenTerminal 主题设置:主题画廊与背景图片配置" width="1282" height="801" />
|
||||
<img src="assets/shot-agents.png" alt="OpenTerminal 多路分屏运行 Kimi Code、Claude Code、Codex 等 AI 编程 Agent" width="1296" height="870" />
|
||||
</figure>
|
||||
<div class="feature-copy">
|
||||
<h3>AI Agent 工作台</h3>
|
||||
<ul>
|
||||
<li>多路分屏并行运行 Kimi Code、Claude Code、Codex 等 AI 编程工具</li>
|
||||
<li>为高频刷新的 TUI 界面优化:终端尺寸去抖同步,避免反复重绘</li>
|
||||
<li>中文输入法候选窗紧贴光标,TUI 内输入中文不再漂移</li>
|
||||
<li>关键词高亮自动标出错误、警告、HTTP 状态码与百分比</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="feature-row media-row">
|
||||
<figure class="feature-shot">
|
||||
<img src="assets/shot-themes.jpg" alt="OpenTerminal 主题设置:背景图片、不透明度、压暗层与主题画廊" width="1739" height="870" />
|
||||
</figure>
|
||||
<div class="feature-copy">
|
||||
<h3>定制与效率</h3>
|
||||
<ul>
|
||||
<li>主题编辑器:22 个颜色位逐项调整,实时预览;支持自定义背景图片与不透明度</li>
|
||||
<li>内置 13 套主题,跟随系统明暗自动切换</li>
|
||||
<li>主题编辑器:22 个颜色位逐项调整,实时预览;支持自定义背景图片、不透明度与压暗层</li>
|
||||
<li>内置 11 套主题,跟随系统明暗自动切换</li>
|
||||
<li>命令库:保存常用命令片段,跨会话发送到指定终端</li>
|
||||
<li>启动恢复上次会话布局;界面缩放 50% 至 150%</li>
|
||||
<li>四语言界面:简体中文、繁体中文、English、日本語</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="feature-row media-row">
|
||||
<figure class="feature-shot">
|
||||
<img src="assets/shot-lock.png" alt="OpenTerminal 锁屏界面:不透明遮罩与密码解锁" width="1739" height="870" />
|
||||
</figure>
|
||||
<div class="feature-copy">
|
||||
<h3>锁屏与安全</h3>
|
||||
<ul>
|
||||
<li>Ctrl+L 一键锁屏,支持闲置自动锁定与启动即锁</li>
|
||||
<li>锁定期间禁用应用菜单、页面刷新与开发者工具快捷键</li>
|
||||
<li>密码经 scrypt 加盐哈希存储,不落盘明文;输错触发递增冷却</li>
|
||||
<li>锁屏只是遮罩:背后的终端会话与文件传输保持运行不中断</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -110,7 +140,7 @@
|
||||
<h2>下载</h2>
|
||||
<p class="section-sub">
|
||||
从 GitHub Releases 下载;全部历史版本在同一页面。
|
||||
<!-- 发新版本时更新下方两条直链与 hero 的 id=dl-exe 链接 -->
|
||||
<!-- 发新版本时更新下方 exe 直链与 hero 的 id=dl-exe 链接 -->
|
||||
</p>
|
||||
<table class="dl-table">
|
||||
<thead>
|
||||
@@ -118,19 +148,11 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="mono">OpenTerminal-1.0.15-setup.exe</td>
|
||||
<td>常规安装,支持应用内自动更新(推荐)</td>
|
||||
<td class="mono">122 MB</td>
|
||||
<td class="mono">OpenTerminal-1.0.22-setup.exe</td>
|
||||
<td>NSIS 安装包,支持应用内自动更新(推荐)</td>
|
||||
<td class="mono">109 MB</td>
|
||||
<td>
|
||||
<a href="https://github.com/billowliu2/OpenTerminal/releases/download/v1.0.15/OpenTerminal-1.0.15-setup.exe">下载</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="mono">OpenTerminal-1.0.15-setup.msi</td>
|
||||
<td>企业批量部署(MSI 无自动更新,需手动升级)</td>
|
||||
<td class="mono">135 MB</td>
|
||||
<td>
|
||||
<a href="https://github.com/billowliu2/OpenTerminal/releases/download/v1.0.15/OpenTerminal-1.0.15-setup.msi">下载</a>
|
||||
<a href="https://github.com/billowliu2/OpenTerminal/releases/download/v1.0.22/OpenTerminal-1.0.22-setup.exe">下载</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -147,8 +169,9 @@
|
||||
<div class="update-note">
|
||||
<h3>自动更新说明</h3>
|
||||
<p>
|
||||
应用内检查更新优先访问 git.codingplan.site 更新通道,失败时回退 GitHub Releases。
|
||||
应用内检查更新优先访问 GitHub Releases(跟随系统代理),失败时自动回退国内 git.codingplan.site 更新通道(直连)。
|
||||
更新包经 SHA-512 校验后安装。更新说明文字从发布通道的 release-notes.md 读取,与每次发布同步更新。
|
||||
自 v1.0.22 起不再提供 MSI 安装包,统一使用 NSIS exe。
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -159,26 +182,26 @@
|
||||
<h2>近期更新</h2>
|
||||
<div class="changelog-list">
|
||||
<article>
|
||||
<h3><span class="mono">1.0.15</span> 2026-09-20</h3>
|
||||
<h3><span class="mono">1.0.22</span> 2026-10-08</h3>
|
||||
<ul>
|
||||
<li>新增自定义终端背景图片与图片不透明度设置</li>
|
||||
<li>主题编辑器重名提醒与颜色值校验</li>
|
||||
<li>设置导航选中项文字对比度修复</li>
|
||||
<li>修复中文输入法候选窗不跟随光标(v1.0.21 回归)</li>
|
||||
<li>不再提供 MSI 安装包,统一使用 NSIS exe</li>
|
||||
<li>打包流程新增依赖一致性校验,防止旧依赖混入安装包</li>
|
||||
</ul>
|
||||
</article>
|
||||
<article>
|
||||
<h3><span class="mono">1.0.14</span> 2026-09-20</h3>
|
||||
<h3><span class="mono">1.0.21</span> 2026-10-07</h3>
|
||||
<ul>
|
||||
<li>修复大文件(约 250KB 以上)上传损坏与 SFTP 句柄泄漏</li>
|
||||
<li>SSH 中文乱码、命令历史错乱等终端修复</li>
|
||||
<li>权限编辑、连接错误提示等 20 余项修复</li>
|
||||
<li>背景图体验:任意主题下调透明度均为压暗、文字自动提亮到 WCAG AA、新增背景压暗滑杆</li>
|
||||
<li>性能:设置热更不再触发全窗格重排,SFTP 大目录虚拟滚动,面板独立错误边界</li>
|
||||
<li>安装包精简约 90MB;SFTP/ZMODEM 本地路径准入与多处安全加固</li>
|
||||
</ul>
|
||||
</article>
|
||||
<article>
|
||||
<h3><span class="mono">1.0.13</span> 2026-09-20</h3>
|
||||
<h3><span class="mono">1.0.20</span> 2026-10-01</h3>
|
||||
<ul>
|
||||
<li>命令片段库与广播输入改进</li>
|
||||
<li>监控面板历史曲线实时重绘</li>
|
||||
<li>修复中文输入法候选窗不跟随光标</li>
|
||||
<li>锁屏加固:锁定期间移除应用菜单,Ctrl+L 按键判定重构并补测试</li>
|
||||
</ul>
|
||||
</article>
|
||||
</div>
|
||||
|
||||
Reference in new issue
Block a user