用 WorkBuddy 写了个 ImageKit 上传工具

用 WorkBuddy 写了个 ImageKit 上传工具

我平时用 ImageKit 存图。后台那个上传框一次拖几十张就开始排队,进度条挤成一列,还得一直盯着别断了。忍了几次之后决定写个桌面工具,要求也不高:能批量拖进去、能看见每张的状态、失败了能重试。

问题是我不想再从头配一遍 Electron。之前弄过一次,vite、主进程、预加载脚本、打包配置,光让窗口正常出来就花了一下午,最后还卡在 dmg 上。所以这回换了个法子:用 WorkBuddy,把想要的东西说清楚,让它去搭。

头一个小时我还在写"需求文档"

刚上手时我不太确定该怎么跟它说话。第一段我写得跟 PRD 一样,分了好几条,还特意加了"技术要求"和"验收标准",生怕漏掉什么。它照着搭出来了,但我很快就发现没必要------直接说人话就行,说"这个按钮我用着别扭,改一下"它也跟得上。

真正让我改观的是它不只是给我代码片段。它能自己去读文件、跑命令、翻日志、改配置。前两天 mac 的构建挂了,我习惯性地准备去把报错复制出来,结果试了句"mac 的安装包构建失败了,去看一下",它自己把 CI 的日志拉回来,落到了具体哪一行。这跟我以前用过的补全类工具完全不是一回事。

密钥这块我没敢马虎

第一段里我特地加了一句:ImageKit 的 private key 绝对不能进渲染进程。以前踩过坑,所以这条写得很死。

它把结构做成了这样:所有跟 key 沾边的活------签名、发起上传、测试连通性------全部留在主进程,渲染进程只能通过 preload 里白名单放出去的几个 IPC 调用,碰不到密钥。这个结构我认,后面一直没动过。配置存在 userData 下的 config.json 里,仓库里只留一份带假值的 config.example.json。

改得最久的是云端目录

拖拽区、上传队列、历史记录、设置弹窗基本都是一遍过的,来回改得最多的是云端目录浏览那一块。

一开始做成单击目录就进去。自己用两次就觉得别扭:大多数时候你只是想挑一个目录当上传目标,并不想跳进去。改成"单击选中、双击(或者点那个箭头)进入",才顺手起来。

加英文这件事比我想的折腾

界面起初全是中文。后来想想还是得让英文用户能用,于是加了英文,而且默认英文。代价比预想中要大。

文案原本是硬写在组件里的,翻到一半我就知道要出事------改一个词得满项目去搜。

改成字典之后舒服多了:以英文那份为准,中文声明成 Record<MessageKey, string>,少翻一条 npm run typecheck 直接报错,想漏都漏不掉。渲染层包一层 Provider,组件里用 useT() 取。

主进程那边是后来才想起来补的。报错信息、dialog 的标题、文件过滤器的名字,一开始还是中文。中文界面下看不出问题,一切成英文就露馅了。

还有个坑,现在想起来挺好笑的。验证语言切换到底生效没有,我一开始靠截图。有几次截出来还是英文,我以为切换失败了,来回查了半天。后来才反应过来:capturePage() 在状态刚变化的时候会返回上一帧。改成就直接读 DOM 里的文本,一眼就对了。截图现在只留给"给你看看长什么样"这个用途。

顺手还定了个规矩:不能拿翻译后的文案去做判断。比如判断对话框是不是被用户取消了,不能去比"已取消"这个字符串,得走一个专门的函数。

环境比代码难缠

代码上的问题好歹能想明白,环境上的不行。

npm 的缓存目录属主是 root,装依赖直接报错,后来改成指定项目内的缓存目录才过去。这个环境还预设了 ELECTRON_RUN_AS_NODE=1,直接跑起不来,得先把这个变量摘掉。

最阴的一个是"窗口假死"。新开一个实例,看起来毫无反应。查了很久才发现是上次没清干净的单实例锁文件还躺在那儿,新进程一启动就自己退出了,我盯着的一直是那个旧窗口。

ps 和 pkill 在这个环境里也用不了,列不出进程,只能拿已知的 pid 一个个 kill -0 去试。那两天我的排查方式基本是"猜一个 pid,试一下"。

打 tag 那天晚上,mac 挂了

CI 分了三条线:平时 push 和提 PR 只跑类型检查加构建;打 v* 的 tag 才出安装包,dmg 和 exe,然后自动建 Release。

前两天打了个 v1.0.0。Windows 那边一百秒出头就完事了,mac 这边 85 秒退出,倒在打包 dmg 上。日志最后是这样:

复制代码
⨯ unable to execute hdiutil args=["detach","-quiet","/Volumes/ImageKit Uploader"]
    error=Exit code: 16.  Above command failed, retrying 5 more times

卸载挂载卷失败,重试 6 次全挂,然后整个 job 断掉。

我一开始怀疑是 runner 环境的问题,macos-14 是 arm64 机器,Spotlight 又爱去啃刚挂上来的卷。后来把日志往前翻才看到关键的地方:arm64 和 x64 两个 dmg 是同时开始打的,而它们的挂载卷名一模一样,都叫 ImageKit Uploader------卷名取自 dmg.title,也就是 productName。两个同名卷撞在一起,谁先卸载谁失败。

修的时候还多踩了一脚。我以为在命令后面加 --arm64 / --x64 就能把两个架构拆开,试了才发现没用:electron-builder.yml 里 mac.target 下面写死的 arch 列表会盖掉命令行的参数。得先把那段删掉,架构全部交给命令行指定,再拆成两次串行调用。

现在 CI 里是这么写的:

yaml 复制代码
- name: 关闭 Spotlight 索引
  run: sudo mdutil -a -i off || true

- name: 打包 dmg(arm64 + x64)
  run: |
    build_dmg() {
      npx electron-builder --mac --arm64 --publish never &&
      npx electron-builder --mac --x64 --publish never
    }
    build_dmg || {
      hdiutil detach -force "/Volumes/ImageKit Uploader" || true
      sleep 10
      build_dmg
    }

到底是同名卷的锅还是 Spotlight 的锅,说实话我没百分之百确定,干脆两边一起堵,外面再套一次重试。能稳定跑就行。

现在的状态

Release 里躺着两个 dmg(Apple Silicon 和 Intel)加一个 exe,都没签名。mac 上第一次打开要右键,Windows 会弹 SmartScreen 提示。

还欠着两件:图标到现在还是 Electron 默认那个原子球,被朋友吐槽过一次;自动更新也没接,每次发版都得到处去下载手动装。

先这样,功能上是能用了,剩下的慢慢补。

仓库地址

github地址

相关推荐
凤城老人12 小时前
从PyQt6到Electron:一款英语字帖生成器的跨平台重构实战与踩坑全记录
javascript·重构·electron
不可能片场2 天前
Electron 发布标题的冒号 击穿命令行解析
前端·electron
500842 天前
React Native for OpenHarmony 实战:三方库 react-native-crypto-js 的鸿蒙化适配指南
javascript·react native·性能优化·electron·harmonyos
星辰徐哥3 天前
鸿蒙平台 KDevelop 集成开发环境适配实战:基于 Electron 壳方案的跨平台多语言代码编辑器开发
electron·编辑器·harmonyos
fellow993 天前
鸿蒙真机调试三板斧:Playwright 为什么驱动不了 Electron-on-鸿蒙
华为·electron·harmonyos
web打印社区4 天前
远程打印:WebSocket 与 HTTP 轮询怎么选
前端·vue.js·websocket·网络协议·http·electron·pdf
去伪存真6 天前
Electron 自动化发布指南:GitHub Actions 跨平台打包全纪录
前端·electron
不可能片场6 天前
Windows 中文传参坑 命令行乱码变量来救场
前端·electron
某亿6 天前
为什么我放弃了 esbuild,改用 typescript 包做运行时编译
前端·electron