摘要:本文记录了一个车间电脑批量管理系统的完整开发过程——从需求分析到离线服务器部署上线,全程通过 AI 对话式开发完成。包含整体架构设计、AI 辅助开发的实际工作流、自动化升级链路的设计取舍,以及一路踩过的坑。


背景

工厂车间里散布着大量产线电脑,长期存在几个痛点:

  • 下班后电脑忘记关机,整夜空转浪费电
  • 批量开关机、重启靠人跑到现场逐台操作
  • 客户端程序更新需要逐台拷贝安装
  • 产线环境完全离线,很多现成的云方案直接出局

于是有了 DimLight 项目:一个部署在客户内网 Windows Server 上的 Web 管理系统,管理员在浏览器里按「客户 / 线体 / 段别」的树形结构批量下发关机、休眠、重启、升级命令,电脑上的 Agent 负责接收执行。从第一行代码到上线,全程用 AI 结对完成。

整体架构

技术选型的第一约束是离线:所有依赖必须在一台联网开发机上装好、打包、拷进内网。因此刻意压低了复杂度:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
┌─────────────────────────────────────────────────┐
│  Windows Server 2022(内网,无互联网)             │
│                                                 │
│  nginx ──► Vue3 + Element Plus(CDN 本地化)      │
│    ▲              │                             │
│    │              ▼                             │
│  浏览器      FastAPI + SQLite                    │
│                 │        │                      │
│                 │   ┌────┴─────┐                │
│                 │   │ 定时任务线程│(定时关机/重启) │
│                 │   └──────────┘                │
│                 ▼                               │
│            HTTP 轮询(10s)                       │
│                 ▲                               │
│  产线电脑 ───────┘  Python Agent(PyInstaller exe)│
│       │                                         │
│       └── NSSM 注册为 Windows 服务                │
│       └── FTP 拉取新版本 → 静默自动升级            │
└─────────────────────────────────────────────────┘

几个关键决策:

1. Agent 用 HTTP 轮询,而不是长连接

产线电脑数量多但网络环境差,WebSocket 断线重连的复杂度不值得。Agent 每 10 秒 GET /api/agent/commands,轮询即心跳——顺带上报版本号、刷新在线状态,一个接口解决三件事。离线判定就是"超过 30 秒没轮询"。

2. 命令管道设计成"先取走、后回报"

命令生命周期是 pending → dispatched → done/failed。轮询时立即标记 dispatched,防止休眠唤醒后重复执行同一条关机命令(这是真实发生过的问题:电脑唤醒 → 又收到休眠命令 → 无限休眠)。

3. 数据库用 SQLite,但计划任务必须落库

SQLite 对这种单服务器小规模场景完全够用。唯一的坑是定时关机功能——如果计划存在内存里,服务器一重启就丢,所以计划配置必须存表,配合 last_run_date 字段做当天防重。

AI 结对开发的实际工作流

这个项目最值得分享的不是最终代码,而是和 AI 协作的过程。它不是"一句话生成整个系统",而是一个持续几周的迭代循环:

第一轮:需求 → 初版骨架

我先写了一份 README,把需求分析、技术栈建议、实施路径都列清楚,然后让 AI 按文档生成三端代码。产出的是能跑的最小系统:登录、树形结构、命令下发。这一轮的意义在于让 AI 和我对齐边界——比如它把 frontend 放进了 backend 目录,我一句"可以放同级目录吗"就纠正了。

中间若干轮:小步快跑 + 报错回贴

之后的每一轮对话基本都是这个模式:

1
2
3
4
我:提一个小需求(例如"最近命令里下发时间和状态对调一下")
AI:改代码,说明改了哪些文件
我:部署到测试环境,贴报错日志
AI:定位修复

印象最深的几个修复都是这么完成的:

  • cp1252 编码崩溃:Agent 以 Windows 服务运行时 stdout 是管道,打印中文直接抛 UnicodeEncodeError,服务反复重启进入 Paused 状态。把日志贴给 AI,加了两行 reconfigure(encoding="utf-8") 解决
  • Vue 自闭合标签:DOM 模板模式下 <el-button /> 会让后面的按钮全部消失,页面上按钮"无故失踪"——这种前端诡异现象靠人肉调试可能要半天,贴现象描述给 AI 一次到位

升级链路:三轮对话磨出来的方案

客户端自动升级是这个项目里最"工程"的部分,前后迭代了三轮:

  1. 第一版:后端 HTTP 下载 + version.txt 版本标记。能跑,但 exe 要在 FTP 和后端各放一份,维护别扭
  2. 第二版:改走 FTP 单一来源——服务器上本来就有 FTP 服务,新 exe 只上传一个地方。version.txt 也被质疑"我就升级个 exe 还要维护 txt?",于是改成版本号在打包时由脚本自动写入 exe 的版本资源,Agent 用 FTP 的 SIZE 命令比对文件大小判断新版本,连版本文件都不用下载
  3. 第三版:静默自动升级落地。Agent 每 5 分钟检查一次,发现新版本就触发升级脚本:FTP 下载 → 计划任务脱离进程树 → 停服务 → 备份 .bak → 替换 → 重启 → 失败回滚

这轮迭代里 AI 的价值在排障。比如升级时计划任务创建一直报:

1
ERROR: No mapping between account names and security IDs was done.

这类 Windows 冷知识(服务会话里 schtasks 必须显式 /ru SYSTEM),靠搜索引擎要翻很久,AI 直接给出了标准解法。同样解决的还有 ftp.exe 脚本模式不认裸用户名密码行、bat 文件含 UTF-8 中文注释导致 cmd 解析碎裂、NSSM 重定向日志后 Python 块缓冲造成日志乱序延迟(每行强制 flush)等等。

定时关机:一次说清需求的示范

功能成熟后的需求提法已经非常结构化了:

  1. 对应客户的账号可以执行对应客户的定时关机,不限于管理员
  2. 命令除了关机/重启,还要加上休眠
  3. 指定线体里需要定义到段别,不选段别则针对整条线
  4. 对应账号不可以定时操作其他客户的电脑

四条需求一轮对话完成实现 + 测试 + 部署说明。而且第 4 条权限约束 AI 直接做在了后端(403 拦截),而不是只在前端隐藏按钮——这种安全意识如果没有提前对齐,是容易被忽略的。

部署方案

最终交付形态是三个 NSSM 注册的 Windows 服务:

服务 内容
DimLightBackend uvicorn 跑 FastAPI
DimLightNginx nginx 托管前端静态文件并反代 API
DimLightAgent 各产线电脑上的 exe,开机自启

升级流程简化到极致:新 exe 打包后扔进 FTP 的 agent 目录,所有电脑 5 分钟内自动升级,Web 端树形结构里直接显示每台电脑的版本号和"升级OK"状态。

踩坑清单

按"每条一句话"列出来,都是真金白银换来的:

  1. Windows 服务重定向 stdout 后默认 cp1252 编码,打印中文必崩,sys.stdout.reconfigure(encoding="utf-8") 是保命符
  2. Vue3 DOM 模板模式不支持自闭合组件标签,<el-button /> 会吞掉后面的兄弟节点
  3. cmd 执行含 UTF-8 中文注释的 bat 会解析碎裂,部署用脚本一律纯 ASCII
  4. 服务会话里 schtasks /create 必须显式 /ru SYSTEM,否则报"account names and security IDs"错误
  5. NSSM 停服务会杀整个进程树,升级脚本必须通过计划任务脱离进程树执行
  6. Python 日志写入文件默认块缓冲,重定向场景必须逐行 flush,否则日志乱序延迟
  7. 计划任务的同一天防重用日期字段判断而不是时间比较,否则修改执行时间会导致当天重复触发
  8. 升级只替换 exe 不动 config.ini,用户配置天然跨版本保留

后记

回头看,这个项目如果是传统开发方式,前后端加客户端三端 + 离线部署 + 自动升级链路,至少是一个小团队几周的活。AI 结对模式下,一个人通过二十来轮对话完成了全部工作——但前提是每一步都有明确的需求描述和验证反馈。

AI 没有替代掉的东西:对产线现场的理解(为什么离线电脑不能补发关机命令、为什么休眠唤醒不能重复执行)、对方案的取舍判断(FTP 还是 HTTP、轮询还是长连接、手动还是静默升级)。AI 负责实现和排障,人负责定义"什么是对的"。

下一步计划

  • 集成 TightVNC 实现 Web 端一键远程协助(走现有 FTP 升级渠道静默部署)
  • PostgreSQL 迁移(数据量上来之后)
  • 命令执行结果的统计报表