- 版本升级 0.1.0 -> 0.2.0(package.json 单一来源,标题栏/设置/关于同步)
- 新增交互发布:指定大屏为主屏,其余屏自行加载本屏页面,主屏可轮流投屏各屏内容
- 单屏发布支持自动轮播(intervalSec)与停止轮播(保留窗体可手动切换)
- 多屏发布支持 alsoMain 主屏同时参与;新增屏幕检测弹窗
- 页面列表缩略图 key 重建避免浏览器复用旧图;「打开」按钮防抖(opening 状态)
- URL 粘贴自动提取网页标题/描述(主进程 fetchMeta)
- 项目组新增「新建」:默认创建 1 个空白页面,保存时选择位置
- 发布组 4 按钮(预览/单屏/多屏/交互)统一为线性 SVG 显示器族图标
- 属性面板 URL 输入框加高 1 行、页面参数加高 2 行并去掉水印
- 编辑预览 WebFrame key={src} 重建,修复切页内容错位
37 KiB
2026-08-23
SmartAgriCenter:用 Electron + React + TypeScript 重写「智慧农业大数据可视化控制中心」
用户对之前 WinForm + WebView2 版(SmartAgriDataCenter)效果不满意,改用 Electron 技术栈重写,新项目位于 c:/Users/范先生/CodeBuddy/DataViewCenter/SmartAgriCenter。
技术栈:Electron + React 19 + TypeScript + Vite 7 + electron-vite@5 + zustand。依赖固定为 electron-vite@5 vite@7 @vitejs/plugin-react@5(避免最新版 vite8 与 electron-vite peer 冲突)。
架构:
- 主进程
src/main/:index.ts(无边框主窗口 + 单实例锁)、ipc.ts(全部 IPC + 未保存关闭守卫)、screens.ts(屏幕窗口管理器,每个显示器一个全屏 BrowserWindow,before-input-event支持数字键 1-9 切页、Esc 退出全屏)。 - 预加载
src/preload/:contextBridge 暴露window.api(win/screens/project/key/syncProject/setDirty/beep/createShortcut/confirm)。 - 渲染层
src/renderer/:zustand store 管理 pages/屏幕/视图;三视图(编辑/发布/配置);Webview 用document.createElement('webview')封装(webviewTag: true),编辑画布与发布预览共用;示例大屏public/sample-screen.html按no/title参数显示 4 种主题动态图表。
关键经验:
- 本机 PowerShell 传参含中文路径(
c:/Users/范先生/...)会乱码导致 cd 失败;命令一律用相对路径。npm 安装时node_modules/electron二进制可能因网络下载失败缺失(表现为 cli.js 报 "Electron failed to install correctly"),需node node_modules/electron/install.js手动下载;网络受限时先$env:ELECTRON_MIRROR="https://npmmirror.com/mirrors/electron/"。 - TypeScript 新版移除了
baseUrl,paths 需写相对形式"./src/..."。 - electron-vite 默认输出 CJS,主进程可用
__dirname。 - 验证渲染层是否正常:
Start-Process electron.cmd -ArgumentList ".", "--remote-debugging-port=9223"后用 CDP 的Runtime.evaluate检查#rootchildren /window.api。
运行:cd SmartAgriCenter && npm run dev(开发)或 npm run build && npm start(生产)。已通过 typecheck + build + 启动验证(React 挂载、4 页面、画布 webview 正常)。
2026-08-23 下午:UI/发布功能增强(需求 2/3/4 全部落地)
针对新需求完成以下改造(均通过 typecheck + build + dev 启动验证):
- 编辑界面:Ribbon 中「项目」菜单组移到「页面」组之前(
Ribbon.tsx调序)。左侧页面列表改为预览图卡片(PageList.tsx重写):新增pc-thumb预览区(无预览显示占位)、hover 出现「前插 ⏫ / 截图 📷」按钮、卡片底部「+ 插入新页」按钮。 - 预览图机制:页面 JSON 新增
PagePreview字段(Base64 图片),utils.ts的pagesToJson/jsonToPages已读写;types.ts的Page增加preview。主进程新增page:snapshotIPC(ipc.ts):隐藏 BrowserWindow 加载 URL → 等 1.6s →capturePage()→toDataURL()。store 的capturePreview(index?)/insertBefore(index?)支持指定索引。 - 发布逻辑:
- 多屏发布:沿用
screens.ts的publishScreen(全屏 BrowserWindow),支持数字键 1-9 切页、Esc 关闭、F5 刷新(新增before-input-event快捷键处理)。 - 单屏轮播(
screens.tsstartCarousel/stopCarousel):在目标屏幕为每页创建一个全屏窗口叠放(show: false),键盘 ↑/↓ 循环切换、数字键直达、Esc 停止并销毁、F5 刷新当前页;轮播状态存carouselsMap,listScreens中显示「单屏轮播(N 页 · 第 M 页)」。 publishActions.ts新增startCarouselOnScreen(取display=true页面轮播)/stopCarouselOnScreen;PublishView.tsx增加「🎠 单屏轮播」/「⏹ 停止轮播」按钮。- preload
index.ts/index.d.ts新增carousel.start/stop与page.snapshotAPI;PageFile增加PagePreview。
- 多屏发布:沿用
- 临时文件:验证时生成的
dev.log/dev-err.log受环境 SafeDelete 保护未能删除(无害,位于 SmartAgriCenter 根目录)。 - 环境注意:后台启动 dev 用
Start-Process npm.cmd -ArgumentList 'run','dev'(npm 直接 Start-Process 会报 "not a valid Win32 application");PowerShell 中文路径需用$env:USERPROFILE拼接。
2026-08-23 修复:编辑页 webview 预览未撑满容器
- 问题:
WebFrame.tsx动态创建的<webview>元素未设置任何 class,而 CSS 已有.webframe-webview { width:100%; height:100%; display:block; border:none }但从未被使用,导致预览画面尺寸异常、不填满画布。 - 修复:创建 webview 时加
wv.setAttribute('class', 'webframe-webview')。 - 注意:
WebFrame的useEffect空依赖创建 webview,HMR 不会重建已存在的 webview,改完需重启 dev 生效。
2026-08-23 编辑页 UI 功能调整(需求一批)
- 页面属性:PageUrl 改为 textarea(
.url-area,rows=2 多行);PageParams textarea 加maxLength={255}并显示计数 "已输入 N / 255"。 - 页面列表卡片:新增底部操作按钮组
.pc-actions(上移⬆/下移⬇/复制📑/删除🗑/截图📷),样式参考半透明深色截图按钮,仅.page-card.active时显示(CSSdisplay:none→flex);缩略图右上角 hover 只保留"前插⏫";底部按钮文案改为"+ 新建页面"。 - 按钮调整:Ribbon「项目」组去掉"重置项目",新增"🔀 页面重置"→
store.resetOrder():按列表顺序重排id='P-001'…'P-NNN'、screen=i+1、ctrl=i+1。"空白页"按钮与store.initBlank一并删除。 - 页面按钮组排序:新建页面 → 插入页面(原"前插页面")→ 复制页面 → 删除页面 → 上移 → 下移 → 缩略图(原"截图预览")。
- store 接口移除
resetProject/initBlank(defaultPages仍作初始数据保留)。
2026-08-23 图标扁平化 + 按钮布局调整
- 新建
src/renderer/src/components/icons.tsx:Feather 风格 SVG 扁平图标组件(IconInsert/IconUp/IconDown/IconCopy/IconTrash/IconCamera),stroke=currentColor,size 默认 13。 - 页面列表卡片:缩略图右上角 hover「前插⏫」按钮移除,全部操作按钮(前插、上移、下移、复制、删除、截图共 6 个)统一放底部
.pc-actions,图标改用 SVG 扁平图标;.pc-thumb-actions相关 CSS 已删除。 - Ribbon 顶部紧凑:
.ribbon-body高度 84→68px、padding 8/14→5/10px、gap 6→4px;.ribbon-groupgap 4→2px、padding 0 10→0 6px;.ribbon-btnmin-width 64→52、高 64→50、gap 4→2、font-size 11→10.5px;.rb-icon30→22px、font 17→13px。
2026-08-23 去掉「发布」Tab,发布功能移植编辑 Tab
- 删除
views/PublishView.tsx及 global.css 中发布视图样式块(.publish-view/.pub-*/.screen-grid/.scard/.publish-right/.preview-*`)。 types.tsViewMode由'edit' | 'publish' | 'config'→'edit' | 'config';App.tsx移除 PublishView 分支与 import;StatusBar.tsx视图名简化。Ribbon.tsx重构:TAB_ICON/TAB_NAME仅 edit/config;编辑 Tab 新增「发布」组(在项目/页面组之后),共 5 个按钮:- 🖥️ 多屏发布
publishAll - 📤 发布当前页
publishCurrentToScreen(curPage.screen)(disabled=无当前页) - 🎠 单屏轮播
startCarouselOnScreen(curPage.screen)(基于当前页所属屏幕轮播所有 display 页面) - ⏹️ 停止轮播
stopCarouselOnScreen(curPage.screen)(disabled=该屏未轮播,依据 screens 状态 /轮播/ 匹配) - 🚪 关闭全部
closeAllScreenOutput RibbonItem增加可选title字段(提示当前屏号/快捷键说明)。
- 🖥️ 多屏发布
- 移除发布 Tab 后快捷键逻辑不受影响(主窗口数字键切页仍走 App.tsx)。
2026-08-23 二次修复:仅设 class 仍只占顶部 100px
- 现象:加上 class 后,webview 仍只占画布顶部约 100px(看起来是内容 intrinsic 高度),下方 620px 空白。
- 根因:Electron
<webview>是 inline-flex 替换元素,普通height: 100%在某些情况下会被内容撑开。需配合父级 flex 拉伸 + inline style 兜底。 - 修复(三重保险):
WebFrame.tsx创建 webview 时加style.display='flex'; style.width='100%'; style.height='100%'。.canvas-stage加display: flex。.webframe加flex: 1 1 auto; min-width: 0; min-height: 0(用 flex 拉伸代替纯 height: 100%)。
2026-08-23 配置页面重构为左右结构 + 7 大菜单(项目信息/遥控设置/快捷方式/发布设置/设备测试/关于)
布局:ConfigView.tsx 改为 .config-shell 左右结构(左侧 .config-menu 菜单栏 6 项 + 右侧 .config-area),面板组件在 src/renderer/src/components/config/ 下。
新增主进程模块:
settings.ts:配置持久化到 userData/settings.json(projectName/projectVersion/jsonPassword/keyThreshold/keyLockKey/publish{mode,screenIndex,alsoMain,intervalSec}),IPCsettings:get/set。crypto.ts:AES-256-GCM(key=SHA256(pwd) + 随机 IV),密文前缀enc:v1:,只加密页面PageUrl/PageParams;密码错误 decrypt 返回 null。project.ts:readProjectFile/writeProjectFile(带密码解密/加密,错误码 '密码错误')、pagesToSync、setUrlBase/buildPageUrl。shortcuts.ts:createDesktopShortcut(kind:'app'|'edit'|'publish', path)+parseArgv(--project/--mode)+chooseProjectFile。快捷方式参数"appDir" --project "path" --mode edit|publish。loader.ts:setPendingLoad/consumePendingLoad/pushLoad,渲染层未就绪时暂存,app:consumeLoadinvoke 兜底 +app:loadProject实时事件(second-instance 也走 handleLaunch)。main/index.ts:handleLaunch读取项目(settings.jsonPassword 解密)→ 推给渲染层;session.setPermissionRequestHandler放行 media(麦克风测试)。- 工程 IPC 带密码:
project:saveAs/save({data,password})、project:open(password?)、project:openAt({path,password})。
快捷键阈值/锁定(screens.ts):setKeyLock/isKeyLocked 全局锁定;makeKeyHandler 统一处理 屏幕窗口/轮播/publishMain:Esc 立即退出、F5 刷新、锁定键(默认 F9)切换识别、数字/方向键需长按超过 keyThreshold 才触发(auto-repeat 不刷新时间戳,避免网页快速输入数字误触切屏)。轮播新增 intervalSec 自动切换定时器。
renderer:
store.ts:新增settings状态 +loadSettings/updateSettings/loadProject;save/saveAs/open 全部带密码(open 密码错误时passwordState.askPassword()弹输入框重试,成功后记忆到设置);新增passwordState.ts+components/PasswordModal.tsx(App.tsx 挂载)。publishActions.ts:新增applyPublishDefaults()(按发布设置 multi/single/main 发布,single 支持 intervalSec)。App.tsx:启动 loadSettings +app:consumeLoad/onLoadProject加载快捷方式项目,mode==='publish' 自动 applyPublishDefaults。- 面板:ProjectInfo(名称/版本/密码+显示切换)、RemoteControl(遥控器模拟器 rc-remote 数字键/↑↓/Esc/F5/🔒、阈值滑杆、锁定键下拉、测试区 rc-test、快捷键速查表)、ShortcutPanel(3 卡片)、PublishSettings(radio+屏幕+间隔+alsoMain)、DeviceTest(键盘回显/WebAudio 提示音+音阶+音量/麦克风电平条 getMediaStream/屏幕列表+probe)、AboutPanel(hero+运行环境+编辑帮助+发布帮助,AppInfo 走
app:info)。 - types.ts 增加 AppSettings/PublishDefaults/LoadPayload/AppInfo;preload d.ts 同步。
踩坑:主窗口数字键切页仍在 App.tsx(renderer keydown);大屏窗口数字键切页走主进程 keyHandler(长按阈值)。密码输入必须用自定义 Modal(Electron sandbox 下 window.prompt 不可用)。
2026-08-23 编辑界面 4 项改动
- 打开/另存为记住最后文件夹:AppSettings 新增
lastDir,ipc.ts的project:open(defaultPath=lastDir)与project:saveAs(join(lastDir, projectName+'.json'))选择后通过rememberDir写回 settings.json。 - 发布按钮组顺序:预览本页 → 单屏发布 → 多屏发布 → 停止轮播 → 关闭所有 → 检测屏幕(Ribbon.tsx pubItems 调整)。
- 单屏发布弹窗新增轮播选项:ScreenSelectModal 增加
showCarouselprop,勾选「自动轮播」显示间隔输入(默认取 settings.publish.intervalSec),onConfirm 签名改为(index, {carousel, intervalSec});Ribbon 单屏发布传startCarouselOnScreen(i, carousel ? intervalSec : 0),不勾选则固定第一页(intervalSec=0 手动切换)。 - 页面重置按钮改名「页面重排」(Ribbon resetorder label)。
新增样式:.m-carousel/.m-interval(弹窗内轮播选项,global.css modal 区)。
2026-08-23 发布按钮组大改造(弹窗选屏 + 检测屏幕 + 编辑器屏幕全屏)
发布组 6 按钮:多屏发布🖥️ / 预览本页👁️ / 单屏发布🎠 / 停止轮播⏹️ / 关闭所有🏁 / 检测屏幕📡。全部通过弹窗交互:
- 预览本页:弹窗选屏 →
publishCurrentToScreen(selected)全屏播放当前页(Esc/F5/数字键)。 - 单屏发布:弹窗选屏 →
startCarouselOnScreen(selected)轮播所有 display 页(↑/↓/数字键/Esc)。 - 多屏发布:
MultiPublishModal预览各屏布局卡片(编号/分辨率/主显示器 + 分配到该屏的页面 chip)+ CheckBox「同时在本机编辑器屏幕上全屏显示页面(屏 X)」,确定后publishAll(alsoMain)。 - 关闭所有:
closeAllScreenOutput(closeAll 已含 restoreMain + closeProbe)。 - 检测屏幕:
DetectModal显示屏幕列表,同时probeScreens()在每块屏显示黑底白字「屏幕 N + 分辨率 + 主显示器」标签 6 秒。
主进程 screens.ts 新增:
setMainWindow/mainScreenIndex/isMainPlaying/publishMain/restoreMain:编辑器主窗口用 WebContentsView 覆盖实现全屏播放(不破坏编辑器 store 状态,退出即移除 view),before-input-event支持 Esc 退出/F5 刷新/数字键 1-9 按 ctrl 切页。probeScreens/closeProbe:data URL 黑底白字标签窗口,6 秒自动销毁。closeAllScreens增加restoreMain()与closeProbe()。- IPC 新增
screens:mainIndex、screen:publishMain、screen:restoreMain、screens:probe;main/index.ts窗口创建后setMainWindow(mainWindow)、closed 置 null。 - preload
index.ts/index.d.ts:screens增加mainIndex/publishMain/restoreMain/probe。
renderer:
publishActions.ts:publishAll(alsoMain)、detectScreens();publishCurrentToScreen/startCarouselOnScreen保留为弹窗确认回调。- 新组件
components/Modal.tsx(通用弹窗)+components/PublishModals.tsx(ScreenSelectModal/MultiPublishModal/DetectModal)。 Ribbon.tsx:pubModaluseState 控制四类弹窗;按钮 action 打开弹窗。- global.css 追加
.modal-overlay/.modal/.modal-head/.modal-body/.modal-foot/.m-screen-row/.m-scard/.m-check等弹窗样式。
2026-08-23 系统崩溃重启 + 存档快照
- 上午系统崩溃,重启后重新拉起客户端:
cd SmartAgriCenter && Start-Process npm.cmd -ArgumentList 'run','dev' -RedirectStandardOutput 'dev.log' -RedirectStandardError 'dev-err.log' -WindowStyle Hidden(仍必须用 npm.cmd,npm 直接 Start-Process 报 "not a valid Win32 application")。 - 验证:vite dev server 5173 HTTP 200;Electron 主窗口标题「智慧农业大数据可视化控制中心」,4 个 electron 进程。
- 当前完成度:项目需求 1-4 及指令清单 1-5 条已全部落地并通过 typecheck + build + dev 启动验证。核心模块:编辑界面(预览图卡片页面列表 + Ribbon + 画布 webview)、发布(预览本页/单屏发布轮播/多屏发布/关闭所有/检测屏幕,全弹窗交互,WebContentsView 主屏全屏)、配置页 6 菜单(项目信息/遥控设置/快捷方式/发布设置/设备测试/关于)、AES 密码加密 JSON、快捷方式三件套、发布默认值。
- 后续候选开发点(未做,供下次继续):(1) 页面列表预览图实际截图流程实测(page:snapshot 依赖 URL 可加载);(2) 遥控器模拟界面视觉美化;(3) 打包分发(electron-builder 等);(4) 项目 JSON 的导入/导出(项目需求编辑 Tab 提到)。
2026-08-23 版本管理 + 标题栏版本号 + 绿色版打包准备
- 版本管理:版本号单一来源 =
package.json的version(当前 0.1.0),主进程用app.getVersion()读取,渲染层经window.api.app.info().appVersion获取。 - 标题栏显示版本号:
TitleBar.tsx:useEffect 拉app.info(),标题右侧新增<span className="tb-ver">系统版本号 v{appVersion}</span>;global.css 加.titlebar .tb-ver样式。main/index.ts:窗口title改为智慧农业大数据可视化控制中心 v${app.getVersion()};因页面<title>会覆盖构造标题,加webContents.on('did-finish-load')里setTitle兜底(任务栏/Alt+Tab 显示 v0.1.0)。
- 绿色版打包配置(已就绪,未执行):新建
electron-builder.yml(appId com.bbit.smartagri,productName 智慧农业大数据可视化控制中心,files: [out/**, package.json],asar:true,win targetzip(x64,解压即用绿色版),electronDownload mirror npmmirror);package.json新增 scripts:pack(electron-builder --dir 出 win-unpacked 目录)、dist(打 zip 包,输出 release/)。注意:electron-builder 尚未安装,需npm i -D electron-builder后才能执行打包;用户明确说「打包」才执行。 - 踩坑实测:
electron-vite dev修改src/main后不会自动重建/重启 electron(renderer 走 HMR 正常,main 不行)——需手动杀 dev 进程组(npm-cli→electron-vite→electron)后重启;仅改 renderer 无需重启。 - 验证:重启后窗口标题「智慧农业大数据可视化控制中心 v0.1.0」,typecheck 通过、无 lint/运行错误。
2026-08-23 绿色版打包完成(用户明确指示后执行)
- 安装
electron-builder@26.15.3(npm i -D electron-builder --registry=https://registry.npmmirror.com,270 包 12s)。 - 执行
npm run dist(electron-vite build + electron-builder)成功:- 产物:
release\智慧农业大数据可视化控制中心-0.1.0-win.zip(139.7MB,绿色免安装压缩包)+release\win-unpacked\(绿色目录,exe 224.6MB)。 - 打包参数:win32 x64 / electron 43.4.1 / asar / 默认 Electron 图标(未配置应用图标,如需要后续加 build/icon.ico)。
- 二进制镜像:打包前设
$env:ELECTRON_BUILDER_BINARIES_MIRROR="https://npmmirror.com/mirrors/electron-builder-binaries/",electron 本体走 yml 里 electronDownload.mirror=npmmirror。
- 产物:
- 验证:win-unpacked 的 exe 独立启动成功,窗口标题「智慧农业大数据可视化控制中心 v0.1.0」;zip 解压测试通过(含 exe)。验证后已关闭。
- 经验:
- PowerShell 传参含中文路径会乱码(再现)——用
Get-ChildItem 'release\*.zip' | Select -First 1通配符定位再操作,避免直接写中文文件名。 - 包名「智慧农业大数据可视化控制中心」的进程名即 exe 名(非 electron),验证用
Get-Process | Where MainWindowTitle -like '*智慧农业*'或 tasklist 匹配。 electron-vite dev启动 electron 偶尔延迟(日志已 "starting electron app" 但进程 10 秒后才出现),查询需多等并重试;tasklist | Select-String electron比 Get-Process 更稳。- SafeDelete 会拦截 release 目录下的批量
Remove-Item -Recurse,临时目录用cmd /c "rd /s /q <dir>"清理。
- PowerShell 传参含中文路径会乱码(再现)——用
- dev 开发环境已恢复运行(主窗口 v0.1.0,vite 5173 HTTP 200)。
2026-08-23 更换应用图标(用户提供的 ico)
- 源图标:
C:\Program Files\Honor\PCManager\qspublic\Documents\LocalAppCenter\Icons\localc04dba21984d49682a967afd00ed0152.ico(仅 64x64 单帧/32bpp)。 - 坑:electron-builder 要求
win.icon≥ 256x256,64x64 直接报Icon must be at least 256x256 pixels。 - 解决:PowerShell + System.Drawing 把 64x64 按 HighQualityBicubic 放大生成 16/24/32/48/64/128/256 共 7 帧的
build/icon.ico(PNG 帧编码 + 手写 ICONDIR 头)。脚本已用完删除(用cmd /c del,SafeDelete 会拦 Remove-Item)。 - 改动:
electron-builder.yml加win.icon: build/icon.ico,files 加build/icon.ico(打进 asar);main/index.tsBrowserWindow 加icon: join(app.getAppPath(), 'build/icon.ico')(dev 与打包后任务栏一致)。 - 重新
npm run dist成功,zip 已更新(10:52);[System.Drawing.Icon]::ExtractAssociatedIcon(exe)验证 exe 图标 32x32 正常提取;打包日志不再有 "default Electron icon is used"。 - dev 已重启,主窗口 v0.1.0 无错误。图标源文件保留在 Program Files(勿删);如需换图,提供 ≥256x256 的 ico 直接替换
build/icon.ico再打包。
2026-08-23 重写「项目需求」文档
- 根目录
项目需求(无扩展名,原 WinForm 版 v1.0 需求)重写为 v2.0,反映 Electron 重写版当前实现阶段。 - 结构:概述/技术架构/界面布局/功能需求(编辑·发布·配置)/业务流程/数据与安全/版本与分发/非功能需求/待办规划/需求来源对照。已实现 ✅、规划 ⏳ 标注。
- 核对确认:配置菜单 6 项(info/remote/shortcut/publish/device/about,
configMenus.ts)、发布 6 按钮顺序与指令清单一致、快捷键体系(1-9 长按阈值/↑↓/Esc/F5/锁定键)、AES-256-GCM 加密、settings.json 字段(lastDir 等)、Page 字段 9 项(含 PagePreview)。 - 未实现(写入文档规划):项目导入/导出、代码视图/页面视图切换、遥控器硬件对接、帮助文档入口。
- 交付:根目录
项目需求文件已整体覆盖为新版;指令清单未改动(其需求已全部实现,作为历史保留)。
2026-08-23 首次 commit + push
- 根目录创建
.gitignore(忽略 node_modules / SmartAgriCenter 的 out、dist、release / IDE / 日志);SmartAgriCenter/.gitignore已存在并正确忽略构建产物。 - 首次提交
68810be(main,61 files,14564 insertions):Electron 重写版全部源码、构建配置、图标、示例工程 json、prototype 原型、项目需求(v2.0)、指令清单、.codebuddy/memory/(记忆一并入仓备份)。 - 推送远程:
DataViewCenter= https://github.bbitcn.net/fanhongcai/DataViewCenter.git(注意远程名是DataViewCenter,不是 origin;git push -u DataViewCenter main)。上游已跟踪DataViewCenter/main。 - 环境备注:PowerShell 终端,
git -C参数含中文路径会乱码,需先在项目根目录再执行 git 命令;credential-manager-core不是有效 git 命令(无害告警,凭据已缓存)。
2026-08-23 打包瘦身
- 问题:用户反馈 zip 139.7MB 太大。构成:exe(Electron 内核)224.6MB、dxcompiler.dll 24.4MB、LICENSES.chromium.html 19.4MB(合规文件勿删)、locales ~55 个语言包 ~55MB。
- 改动:
electron-builder.yml加compression: maximum+afterPack: ./scripts/afterPack.js(新增脚本,裁剪 locales 只留 zh-CN/zh-TW/zh-HK/en-US;可选删除 dxcompiler/dxil 的开关默认关闭)。 - 结果:zip 139.7 → 128.9MB;win-unpacked 364.9 → 319.8MB;locales 55 → 3 个。dxcompiler 保留(用户选择保守)。若删 dxcompiler+dxil 可再省 ~22MB zip。
- ⚠️ 打包环境大坑(重要):CodeBuddy CN 注入的
node-safe-delete-shim把 Node 的fs.rm/PowerShellRemove-Item劫持为"回收站批量删除守卫",删除大量文件时报错(中文用户名范先生路径乱码致守卫脚本 MODULE_NOT_FOUND)。electron-builder 解压前必须删旧 win-unpacked → 必触发 → 打包失败。而且失败后npm run dist的 node/electron-builder 进程会挂死不退出、占用 release 文件。- 解法:① 打包前用
[System.IO.Directory]::Delete(...,$true)删掉整个release目录(.NET API 绕过钩子);② 若报"文件被占用",先Get-CimInstance Win32_Process | Where CommandLine -like '*SmartAgriCenter*'找到挂死的 npm/electron-builder 进程Stop-Process -Force;③ 再删 release 重跑npm run dist。 - 首次打包成功是因为 release 当时不存在;此后只要 release 存在就会触发删除陷阱。记住:每次打包前先 .NET 删 release。
- 解法:① 打包前用
2026-08-23 文档三件套 + 开发进度存档(跨会话恢复入口)
- 「项目需求」升级 v3.0:§5 补充绿色版打包✅/图标✅/瘦身方案(zip 139.7→128.9MB);§7 待办更新(打包分发标✅,新增截图实测/遥控美化候选);§8 补打包阶段对照。
- 新增根目录
开发进度存档(无扩展名):作为跨会话上下文恢复入口,含目录结构/快速启动/打包手册(含所有坑)/代码结构地图/功能清单/待办/Git 信息/踩坑实录表。 - MEMORY.md 更新:顶部加「换环境先读
开发进度存档」指引;文档三件套说明;打包章节更新(128.9MB、build/icon.ico、SafeDelete 坑)。 - 目的:用户重装 CodeBuddy/换文件夹路径后,新会话读
开发进度存档即可省积分快速恢复上下文。
2026-08-23 修复中文 commit message 双编码乱码
- 现象:
git log提交信息显示乱码(如椤圭洰闇€姹傚崌绾?),经字节级验证(cmd 重定向 + node 读 hex)确认为存储层乱码:PowerShell/cmd 把中文-m参数按 GBK 编码传给 git,git 按 UTF-8 存储 → 双编码。 - 修复:Node 脚本(
fix-msgs.js,用完已删)用git cat-file commit读原对象 → 保留 header(tree/parent/author/committer/时间戳)→ 仅替换 message →git hash-object -t commit -w --stdin重建 →git update-ref。新 hash:2c90205(init)/4b3ea03(build)/b11bea1(docs)。已git push --force-with-lease强推(用户授权),69d592b...b11bea1 (forced update),远程一致、工作区干净。 - 以后约定:提交信息用
git commit -F <utf8消息文件>(write_to_file 生成的 UTF-8 文件),禁用git commit -m "中文"。 - 执行环境备注:execute_command 实际走 cmd,
2>$null会被当作重定向生成$null文件(需手动删);;不分割 cmd 命令;[Console]::OutputEncoding=UTF8对 git 输出无效,验证用git log > file后 read_file 工具读。
2026-08-23 发布/轮播测试问题修复(3 项,typecheck 通过)
用户测试反馈 3 个问题,全部修复:
- 单屏发布勾选轮播无效(根因实锤):
ipc.tscarousel:starthandler 漏传payload.intervalSec,自动轮播定时器从不启动。已修:startCarousel(payload.index, payload.pages, payload.intervalSec ?? 0)。 - 上下键/数字键无效(疑似焦点丢失):
screens.ts增强焦点——轮播首窗ready-to-show加win.show();startCarousel结尾 400ms 延迟再次 show+focus 首窗;switchCarousel切页后 120ms 延迟再 focus。注:编辑器主窗口聚焦时大屏窗口收不到按键属 Electron 正常行为,需点击大屏窗口。 - Esc 快捷键 =「关闭所有」:
ensureWindow(单屏预览/多屏发布)、startCarousel(轮播)、publishMain(主屏 WebContentsView)的onEscape全部改为closeAllScreens()(原为 closeScreen/stopCarousel/restoreMain)。所有提示文案同步改「Esc 关闭所有」。 - 多屏发布仅保留 Esc/F5:
makeKeyHandler新增navDisabled(跳过数字/方向/锁定键);navDisabledWinsSet 标记窗口;publishScreen/ensureWindow/IPC/preload 透传navDisabled;publishAll传navDisabled:true(ensureWindow复用窗口时也会刷新标记)。 - 「停止轮播」= 结束窗体:确认
stopCarousel本就 destroy 全部轮播窗口;Ribbon.tsx改进carouselRunning(任一屏轮播即可用,不再要求当前页 screen 匹配)+ 停止目标优先当前屏、否则第一个轮播屏;toast 改「轮播已结束(窗体已关闭)」。
改动文件:src/main/ipc.ts、src/main/screens.ts、src/preload/index.ts+index.d.ts、src/renderer/src/publishActions.ts、components/Ribbon.tsx、components/PublishModals.tsx。typecheck 通过;主进程改动需重启 dev 才生效。
- 已重启 dev 并验证:主窗口标题「智慧农业大数据可视化控制中心 v0.1.0」,dev-err.log 无错误,vite 5173 就绪,5 个 electron 进程。
- 新增页面删除确认弹窗:
views/PageList.tsx删除按钮改为setDelIdx(i)弹出 Modal 确认(标题=删除页面,内容含页面标题+id,footer=取消/删除),确认回调先selectPage(delIdx)再delPage()防弹窗期间切换选中页误删;复用Modal.tsx+.btn.danger样式,纯 renderer 改动走 HMR。 - 排查"重新截图缩略图不刷新":用 CDP 实测(dev 以
npm run dev -- -- --remote-debugging-port=9223启动,Node 24 全局 WebSocket 直连)证明截图后 img.src 每次都变化(1390514→1403322→1397278)、toast 链路正常,UI 刷新其实一直正常,用户"没看到刷新"是因为静态页面像素几乎不变。改进:①PageList.tsx的<img>加key={p.preview}强制重建(杜绝浏览器复用旧图);②store.tscapturePreview 区分反馈——数据变化 toast「✅页面截图已更新」/数据相同 toast「💡页面内容无变化,缩略图已是最新」;toast 类名是.toast(不是 .toast-item)。CDP 临时脚本已删。 - 新增"粘贴 URL 自动提取网页标题/描述":主进程
ipc.ts新增page:fetchMetahandler(隐藏 BrowserWindow 加载 URL,Promise.race12s 超时,轮询最长 2s 等 JS 动态 title,提取document.title+meta[name=description]/og:description,仅接受 http/https);preloadpage.fetchMeta暴露 +index.d.ts类型;PropertyPanel.tsxURL textareaonPaste时用e.clipboardData.getData('text')判断 http(s) 即调用fillMetaFromUrl(useRef去重),提取成功覆盖填入 title/desc,toast 区分「已自动填入网页标题与描述」/「已自动填入网页标题」。CDP 实测fetchMeta('http://localhost:5173/sample-screen.html')→{"title":"农业数据总览","desc":""}。注意LoadURLOptions无timeout字段,超时须用Promise.race。已重启 dev 生效。 - 「打开」按钮防抖:
store.tsAppState 新增opening: boolean(create 初值 false),open()开头if (get().opening) return+set({opening:true}),finally set({opening:false})(防重入锁,覆盖取消/失败/密码错误全流程);Ribbon.tsx打开按钮订阅opening→ disabled + 图标⏳/文案「打开中…」;ProjectInfo.tsx配置页「打开工程」按钮同样 disabled+「⏳ 打开中…」。.ribbon-btn:disabled/.btn:disabled样式已存在。纯 renderer 改动 HMR 生效。 - 单屏发布三项修复:①键盘控制:
screens.ts的makeKeyHandler(b, quick=false)新增 quick 参数,quick 时 threshold 强制 0(原默认 keyThreshold=350ms 导致快速按键被吞);ensureWindow/startCarousel/publishMain三处调用均传true。②停止轮播:CarouselState加auto字段(=intervalSec>0 && pages.length>1);ScreenInfo加carouselAuto?(main screens.ts + renderer types.ts);listScreens返回carouselAuto: car.auto、轮播标题含「· 自动」;新增主进程stopCarouselAuto(index)(清 timer、auto=false、保留窗体)+ IPCcarousel:stopAuto+ preloadcarousel.stopAuto;publishActions.stopCarouselOnScreen改名stopCarouselAutoOnScreen(toast 提示可 ↑/↓ 手动切换);Ribbon的「停止轮播」carouseling过滤条件改为s.carouselAuto && /轮播/(仅自动模式可用)。③PublishModals.tsxScreenSelectModal 默认不勾选自动轮播:useState(false)(原来props.showCarousel ?? false导致 single 模式默认勾选)。注:多屏发布窗口 navDisabled 仍禁用数字/方向键,quick 不影响。改主进程+preload,已杀旧实例重启 dev 至 5173。typecheck(node+web)通过。 - 新增「交互发布」:演示场景(1 大屏 + 多小屏轮流投屏讲解)。
screens.ts新增startInteractive({mainIndex, pagesByScreen}):主屏轮播内容=所有屏页面按屏号排序拼接(label='交互发布'),其余屏轮播本屏页面(label='单屏轮播'),复用 startCarousel;CarouselState加label字段、startCarousel加第 4 参label='单屏轮播'、listScreens标题用car.label。IPCcarousel:startInteractive+ preloadcarousel.startInteractive。渲染层:publishActions.startInteractiveOnScreen(mainIndex)(按 page.screen 分组收集 display 页面);PublishModals.InteractiveModal(卡片点击选主屏,默认主显示器,显示各屏页面分布,m-scard.clickable/.sel新样式);Ribbon发布组 multi 后加「交互发布🔁」按钮(pubModal 类型加 'interactive')。主屏上 ↑/↓/数字键即轮流把各屏页面切到大屏。dev 5173 运行中,preload 产物含 startInteractive,typecheck 通过。坑:同文件多 replace 并行会写锁超时,须每批每文件只改一处。 - 版本升级 0.1.0 → 0.2.0 + 两个用户问题修复:
- 问题1(属性面板所属屏幕最多屏4):
PropertyPanel.tsxscreenCount = Math.max(screens.length, 4, pages.length, ...pages.map(p=>p.screen))。CDP 实测 6 页项目下拉显示 1-6。 - 问题2(编辑 P-005 预览显示 P-006):
Canvas.tsx的 WebFrame 加key={src}强制重建 webview(切页销毁重建,杜绝 webview 复用残留/远端 hash 被改写导致内容错位)。实测:本地模拟(同 URL 不同 hash+query)切换 attr/url 均正确;远端实测 P-005(#/zhihuiyq)→「智慧蚕桑·园区数据可视化平台」、P-006(#/paihangbang)→「排行榜·蚕茧交易音视频督导中心」,内容一一对应。注:WebFrame src 更新逻辑(setAttribute)本身正确,但复用 webview 在远端加载时序/导航残留下可能显示旧页,key 重建为根治。main.tsx加window.__store = useStore调试接口(保留无碍)。 - 版本号改动:
package.json(主来源)→0.2.0、main/settings.ts默认 projectVersion、renderer/utils.ts兜底 version、AboutPanel.tsx/ProjectInfo.tsxfallback+placeholder。项目 JSON 文件内 version 字段是用户数据不动。标题栏版本 = app.getVersion() 读 package.json,重启后显示 v0.2.0。 - 调试技巧沉淀:CDP 动态
import('/src/store.ts')不稳定(偶发 "Promise was collected",因 context 销毁),改走window.__store全局或纯 DOM(点击 .page-card)最稳;npx tsc --noEmit -p tsconfig.web.json单独验渲染层。临时测试脚本/本地模拟页已删,dev 已重启。
- 问题1(属性面板所属屏幕最多屏4):
- 新增「新建」+ 发布图标统一 + 属性面板高度(v0.2.0 并入,未发布):
- 「新建」按钮(项目组第一个 🆕):
store.tsAppState 加newProject——重置为单个空白页{id:'P-001',title:'空白页面',desc:'',screen:1,ctrl:0,display:true,url:'about:blank',params:''},filePath:null, dirty:true(保存走另存为);syncProject 由 App.tsx pages effect 自动处理,无需手动调。CDP 实测(build 产物 + electron.exe--remote-debugging-port=9223):点击后 pages=[P-001:空白页面:about:blank]、预览显示空白页。 - 发布组 4 按钮图标统一:预览本页/单屏发布/多屏发布/交互发布 由 emoji 换成统一样式线性 SVG(显示器族:24 viewBox、stroke currentColor 1.8、15px、在
.rb-iconflex 容器内自动居中着色):预览=显示器+播放三角、单屏=显示器+轮播旋转箭头、多屏=前后双显示器、交互=显示器+双向箭头。Ribbon.tsx顶部定义svgIconProps+ 4 个图标组件,RibbonItem.icon类型改为string | React.JSX.Element(emoji 字符串兼容)。CDP 实测发布组svgs=4。 - 属性面板:URL 输入框
rows 2→3;页面参数 textarearows=4(默认 2 加 2 行)并删除 placeholder 水印(URL 的 placeholder 保留)。.prop-item textarea仅min-height:46px+resize:vertical,无固定高度,rows 生效。 - CDP 验证 build 产物注意:
npm run build后必须用node_modules\electron\dist\electron.exe . --remote-debugging-port=9223(electron.cmd不在 PATH 会报 file not found),页面 URL 是file://...out/renderer/index.html,脚本匹配 page 类型须排除 chrome:// 与 devtools。验证完已杀实例重启 dev 至 5173。
- 「新建」按钮(项目组第一个 🆕):