feat: 人员年龄/号码布、图片上传、多显示器菜单、Console 两栏、exe 改名等一批改动
人员与报名:
- 人员唯一标识改为「证件号 或 号码布」二选一(0013/0014 迁移 + 导入匹配/回填/冲突)
- 人员新增「年龄」(0015 迁移):表单/列表/导入模板表头 11 列;冲突比较只在两边
都有值且不同时才算差异,旧数据不误报
- 冲突决策键改为「证件号优先 → 号码布」(前端原先只用 idCard,号码布行会互相覆盖)
- 报名选择器支持无证件号但有号码布的运动员
大屏与 Console:
- 大屏控制新增「显示器」菜单:可给指定显示器重建全屏窗口;单屏/主显示器强制窗口化,
限制在 Console 侧判定,不信任页面传参
- Console 服务管理窗口改左右两栏,运行日志独占右栏满高;窗口默认尺寸 1280×860
- 大屏右上角时钟精确到秒(同时把刷新间隔 15s 改为 1s)
图片与配置:
- 新增图片上传 POST /api/uploads(recorder+,png/jpg/webp/gif,≤5MiB)与匿名静态
访问 GET /uploads/{name}(防目录穿越);文件落赛事项目目录 uploads/,随赛事包
一起导出/导入
- 「赛事信息」新增赛事会标 / 大屏会标 / 大屏背景图三个上传项
- 参赛单位 logo 输入框右侧加上传按钮
关于页与构建:
- 构建时间打通:version.BuildTime + /api/system/about 返回 + build.bat 注入
(用 PowerShell 取时间戳,避免本地化 %DATE% 的非 ASCII 星期)
安装包:
- 主程序改名 Scoreboard_Console.exe(win.executableName;productName/显示名不变)
- 记住上次安装目录:自定义 NSIS 宏优先沿用自存路径(卸载不清除),并在 customInit
里补写回 electron-builder 的键,避免安装模式页把 $INSTDIR 打回默认
自检:服务端 12 包全绿;前端 vue-tsc + build 通过、node --test 58/58;console 12 文件通过。
This commit is contained in:
1 parent
24fff8dd08
commit
6483acf9ad
50 files changed
+2980
-395
No files matched your search
+10
-2
@@ -36,20 +36,28 @@ REM deploy\signature.build.txt, and for /f reads that file directly (no re-encod
|
||||
node ..\deploy\prepare-signature.mjs || exit /b 1
|
||||
set "INTERNAL_SIGNATURE="
|
||||
if exist "..\deploy\signature.build.txt" for /f "usebackq delims= eol=" %%A in ("..\deploy\signature.build.txt") do if not defined INTERNAL_SIGNATURE set "INTERNAL_SIGNATURE=%%A"
|
||||
REM build time for the About page. Do NOT use %DATE%/%TIME%: a localized Windows
|
||||
REM prints non-ASCII weekday names, which cmd mis-parses (see the header note).
|
||||
set "BUILD_TIME="
|
||||
for /f "usebackq delims=" %%T in (`powershell -NoProfile -Command "(Get-Date).ToString('yyyy-MM-dd HH:mm:ss')"`) do if not defined BUILD_TIME set "BUILD_TIME=%%T"
|
||||
set "BUILD_TIME_LDFLAG=-X 'git.yeij.top/AskaEth/Scoreboard/server/internal/version.BuildTime=%BUILD_TIME%'"
|
||||
if defined INTERNAL_SIGNATURE (
|
||||
REM single quotes keep spaces inside the value intact for go's ldflags parser
|
||||
go build -ldflags "-X 'git.yeij.top/AskaEth/Scoreboard/server/internal/version.InternalSignature=%INTERNAL_SIGNATURE%'" -o ..\dist\scoreboard.exe . || exit /b 1
|
||||
go build -ldflags "-X 'git.yeij.top/AskaEth/Scoreboard/server/internal/version.InternalSignature=%INTERNAL_SIGNATURE%' %BUILD_TIME_LDFLAG%" -o ..\dist\scoreboard.exe . || exit /b 1
|
||||
node ..\deploy\verify-signature.mjs || exit /b 1
|
||||
echo internal signature injected
|
||||
) else (
|
||||
go build -o ..\dist\scoreboard.exe . || exit /b 1
|
||||
go build -ldflags "%BUILD_TIME_LDFLAG%" -o ..\dist\scoreboard.exe . || exit /b 1
|
||||
echo no internal signature
|
||||
)
|
||||
echo build time %BUILD_TIME%
|
||||
cd ..
|
||||
|
||||
echo === [4/4] console package (electron-builder) ===
|
||||
REM win.icon is written into the PE resources by electron-builder (via rcedit);
|
||||
REM it needs winCodeSign / nsis, fetched through the gh proxy above.
|
||||
taskkill /im "Scoreboard_Console.exe" /f >nul 2>&1
|
||||
REM builds from before the exe rename used a space in the file name - kill that too
|
||||
taskkill /im "Scoreboard Console.exe" /f >nul 2>&1
|
||||
taskkill /im scoreboard.exe /f >nul 2>&1
|
||||
if not exist "rules" (
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
// 构建前准备两样东西:
|
||||
// 1) 把 docs/ 下的使用说明暂存到 console/extra/,供 electron-builder 的 extraFiles 平铺到部署包根目录;
|
||||
// 2) 生成安装器许可页顶部文案(console/resources/installer-signature.nsh),署名来自构建机本地文件。
|
||||
// 2) 生成安装器自定义脚本(console/resources/installer-custom.nsh):许可页顶部文案(署名来自构建机本地文件)
|
||||
// + 记住上次安装目录(重装时沿用,而不是退回系统默认路径)。
|
||||
// 用 Node 而不是批处理:中文文件名/中文内容在 .bat 里会被 cmd 解析错乱。
|
||||
import { copyFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
|
||||
import { copyFileSync, existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
|
||||
import { dirname, join } from 'node:path'
|
||||
|
||||
const root = dirname(import.meta.dirname)
|
||||
@@ -20,15 +21,80 @@ if (usageSource) {
|
||||
console.log(' [docs] no usage doc, skip')
|
||||
}
|
||||
|
||||
// ---- 2. installer license page text ----------------------------------------
|
||||
// ---- 2. installer custom script ---------------------------------------------
|
||||
// electron-builder 的 nsis.include 只收一个文件,所以许可页文案与安装目录记忆写在同一个 .nsh 里。
|
||||
const signatureFile = join(root, 'deploy', 'signature.local.txt')
|
||||
const nshFile = join(root, 'console', 'resources', 'installer-signature.nsh')
|
||||
mkdirSync(dirname(nshFile), { recursive: true })
|
||||
const nshDir = join(root, 'console', 'resources')
|
||||
const nshFile = join(nshDir, 'installer-custom.nsh')
|
||||
const legacyNshFile = join(nshDir, 'installer-signature.nsh')
|
||||
mkdirSync(nshDir, { recursive: true })
|
||||
|
||||
let topText = '请阅读并接受许可协议'
|
||||
if (existsSync(signatureFile)) {
|
||||
const signature = readFileSync(signatureFile, 'utf8').trim()
|
||||
if (signature !== '') topText = `内部署名:${signature}`
|
||||
}
|
||||
writeFileSync(nshFile, `!macro customHeader\n !define MUI_LICENSEPAGE_TEXT_TOP "${topText}"\n!macroend\n`, 'utf8')
|
||||
console.log(` installer license text ready (${existsSync(signatureFile) ? 'with' : 'without'} internal signature)`)
|
||||
|
||||
// 换行用 CRLF:.gitattributes 里 *.nsh 就是 CRLF,NSIS 在 Windows 上按CRLF 读最稳。
|
||||
const nsh = [
|
||||
'!include "LogicLib.nsh"',
|
||||
'',
|
||||
'; 安装器自定义脚本:由 deploy/prepare-extra.mjs 生成,不要手改。',
|
||||
'; 内容只有三块:许可页文案、上次安装目录记忆、卸载钩子。',
|
||||
'',
|
||||
'; 自己记的安装目录(per-user 落 HKCU,per-all-users 落 HKLM)。',
|
||||
'; electron-builder 自带的 ${INSTALL_REGISTRY_KEY} 在卸载时会被整键删掉,',
|
||||
'; 「先卸载再装新版」或换过安装模式就会退回系统默认路径,所以另存一份不会被卸载器清理的。',
|
||||
'!define SCOREBOARD_INSTALL_KEY "Software\\Scoreboard Console"',
|
||||
'',
|
||||
'!macro customHeader',
|
||||
` !define MUI_LICENSEPAGE_TEXT_TOP "${topText}"`,
|
||||
'!macroend',
|
||||
'',
|
||||
'!macro customInit',
|
||||
' ; 在 .onInit 里、initMultiUser 之后执行:此时改 $INSTDIR 还来得及影响后面的目录页。',
|
||||
' ReadRegStr $R9 HKCU "${SCOREBOARD_INSTALL_KEY}" "InstallLocation"',
|
||||
' ${If} $R9 != ""',
|
||||
' StrCpy $INSTDIR $R9',
|
||||
' ; 安装模式页(per-user / per-all-users)离开时,electron-builder 会用自己那个键',
|
||||
' ; 重新算一遍 $INSTDIR;卸载后它已经被删了,把记忆值补写回同一个 hive 里。',
|
||||
' ; 不跨 hive 写:否则会把 per-machine 装的机器悄悄带成默认 per-user 模式(反之亦然)。',
|
||||
' WriteRegStr HKCU "${INSTALL_REGISTRY_KEY}" "InstallLocation" "$R9"',
|
||||
' ${Else}',
|
||||
' ReadRegStr $R9 HKLM "${SCOREBOARD_INSTALL_KEY}" "InstallLocation"',
|
||||
' ${If} $R9 != ""',
|
||||
' StrCpy $INSTDIR $R9',
|
||||
' WriteRegStr HKLM "${INSTALL_REGISTRY_KEY}" "InstallLocation" "$R9"',
|
||||
' ${Else}',
|
||||
' ; 没有自己的记忆时,退回 electron-builder 的键(老版本装过、没卸载过的情况)',
|
||||
' ReadRegStr $R9 HKCU "${INSTALL_REGISTRY_KEY}" "InstallLocation"',
|
||||
' ${If} $R9 == ""',
|
||||
' ReadRegStr $R9 HKLM "${INSTALL_REGISTRY_KEY}" "InstallLocation"',
|
||||
' ${EndIf}',
|
||||
' ; 只认非空值;旧目录已经被删掉也照样用(这就是「记住我的路径」的语义)。',
|
||||
' ${If} $R9 != ""',
|
||||
' StrCpy $INSTDIR $R9',
|
||||
' ${EndIf}',
|
||||
' ${EndIf}',
|
||||
' ${EndIf}',
|
||||
' ClearErrors',
|
||||
'!macroend',
|
||||
'',
|
||||
'!macro customInstall',
|
||||
' ; SHELL_CONTEXT 跟随安装模式:per-user → HKCU,per-all-users → HKLM。',
|
||||
' WriteRegStr SHELL_CONTEXT "${SCOREBOARD_INSTALL_KEY}" "InstallLocation" "$INSTDIR"',
|
||||
'!macroend',
|
||||
'',
|
||||
'!macro customUnInstall',
|
||||
' ; 故意什么都不删:需求就是「卸载后重装仍沿用上次的目录」。',
|
||||
' ; 若改成卸载即遗忘,在这里补两行(卸载时 SHELL_CONTEXT 不一定已设定,要写死根键):',
|
||||
' ; DeleteRegValue HKCU "${SCOREBOARD_INSTALL_KEY}" "InstallLocation"',
|
||||
' ; DeleteRegValue HKLM "${SCOREBOARD_INSTALL_KEY}" "InstallLocation"',
|
||||
'!macroend',
|
||||
'',
|
||||
].join('\r\n')
|
||||
|
||||
writeFileSync(nshFile, nsh, 'utf8')
|
||||
// 改名前生成的旧脚本已经没人引用,构建机上顺手清掉,免得看起来还在用。
|
||||
rmSync(legacyNshFile, { force: true })
|
||||
console.log(` installer custom script ready (${existsSync(signatureFile) ? 'with' : 'without'} internal signature)`)
|
||||
Reference in new issue
Block a user