2026.07.22 (三)

✨ GPT-5.6 Sol 的总结

记录我把既有的年假使用促进功能和数据迁入新的NAS环境,并在接通外部HTTPS后,修复真机移动端暴露出的UI缺陷。

我把旧版年假自动化的功能和数据迁入新的NAS环境,并打通了外部HTTPS请求抵达NAS内部应用的路径。这不只是启动一个container,而是把既有业务流程搬进新的运行环境。

然而,新画面能打开并不代表迁移已经完成。员工与年假数据必须正常显示,年假促进对象和短信文案也必须与旧系统一致。一天超过130条的短信必须顺延到第二天,发送queue和历史记录也要延续。任何一项缺失,都会变成一个只有名字相同的新服务。

此前在重新拆分销售自动化与员工行政时,我决定先复现既有的年假促进功能,再进行迁移。真正开始后,我才发现这个顺序比预想的更加重要。NAS部署暂时被我往后放了。

在本地复现功能并恢复数据

我先在隔离的本地Compose环境中运行FastAPI、Next.js和MariaDB。为了不与既有服务冲突,port、network、volume和credential也分别设置。以管理员身份登录并打开员工、年假数据后,我把促进对象、生成的文案、超过130条限制的预约记录、queue与历史记录逐一对照既有流程。

我不想直接操作生产DB。于是先把原有SQL backup恢复到单独的MariaDB,再比较schema与关键table的记录数。我还重启backend,确认数据仍然存在。做到这里,我才建立起一套本地运行基准。之后如果NAS上出现问题,就能区分是代码发生了变化,还是image或network配置有误。

但backup恢复成功,并不意味着生产切换已经结束。管理员账号、工作手机和真实短信都还没有经过这条新路径。

真实SMS发送路径上的双重限制

接下来卡住的是实际SMS。若不发送短信,就无法把通往Android工作手机的路径看到最后;但也不能为了测试而一直开放production发送。

因此,我先把server发送mode分成三种。

NO_SEND
ALLOWLIST_SEND
PRODUCTION

平时保持NO_SEND。只有测试时,我才把一名获准收信的人加入ALLOWLIST_SEND。系统不用电话号码明文,而是通过SHA-256 hash匹配对象,并把server可取得的消息限制为1条。Android应用内部也另外设置了1条的budget。这样即使server或应用中的一边操作失误,也不会发出第二条短信。

我没有只看代码就认为这个状态没问题。我用Computer Use打开真实管理界面,查看NO_SEND、当前可claim数量、queue和历史记录。还在同一个画面中对照了Codex的工作结果与实现代码。

使用Computer Use查看应用了NO_SEND的短信queue与历史界面,同时对照Codex工作结果和实现代码。已对真实服务地址、非公开人员标识和可识别公司的标记做马赛克处理。

为避免直接改动生产应用,我还另外制作了测试package。通过USB连接Android设备后,我用adb reverse接入本地endpoint。最终,一条真实短信以SUCCESS结束,我也在接收设备上看到了收到的短信。

这里还出现了一个模糊的结果。用户收到了短信,但Android delivery callback没有被捕获。SUCCESS只表示运营商接受了发送请求,并不代表delivery callback已经完成。如果把实际收到短信与callback状态归为同一种成功,之后面对UNKNOWN记录时会更难判断该怎么处理。

确认一条短信后,我立即切回NO_SEND。Android readiness为0,server claim返回204 No Content。最终状态是,即使再次误触测试,也不会有下一条短信被发送。

将linux/amd64 Docker image迁移至NAS

我没有把整个自动化platform搬上NAS,只单独部署了年假自动化服务。NAS上不重新build source,而是在Mac上制作linux/amd64 image,核对hash后再传过去。Compose project也与既有stack分开。这样替换一个backend时,就不会连MariaDB与Frontend也一起重建。

接通外部HTTPS与Reverse Proxy

新地址已经能打开登录界面,既有的员工与年假数据也正常显示。但仅靠文字,很难一眼看清外部浏览器的请求如何一路抵达MariaDB。特别是在解释3101究竟是向Internet开放的port,还是只在NAS内部使用的port时,边界总是混在一起。我把请求路径画成了图。

外部只使用HTTPS 443,NAS内部则依次连接Frontend 3101、Backend 8000与MariaDB 3306的年假自动化请求流程

画成图后就清楚了:外部只需要HTTPS 443。Router把443转发给NAS,NAS reverse proxy根据hostname,把请求发送到127.0.0.1:3101的Frontend。Backend 8000与MariaDB 3306只在Docker network内部连接。3101也只绑定NAS loopback,因此无法从Internet直接访问。

没有把Cloudflare加入默认路径也是出于同样原因。我已有authoritative DNS、固定公网IP,也能直接控制Router。只添加服务用A record,再由NAS管理证书,就能少一个中间组件。代价是证书续期与port forwarding都要自行维护。除了签发、更新证书所需的80端口,实际服务请求只通过443接收。

在真实移动设备上验证并修复响应式UI

外部HTTPS地址能打开,并不代表迁移已经结束。我通过USB连接真实Android设备,使用移动网络访问新地址,并亲自走完登录、dashboard、员工列表、SMS历史和年假管理。页面能开,但还没到可以直接使用的状态。

在PC浏览器里仅仅缩窄宽度时遗漏的问题,在真机上一次性暴露了出来。dashboard里的桌面sidebar占据了大部分屏幕,card和文字都被挤成长条。

下面所有对比图中,左侧是修改前,右侧是修改后。

在真实移动设备上发现的dashboard布局缺陷及修复结果

员工列表中的标题和button逐字断行,宽table则被强行压进狭窄屏幕。我让标题与操作区保持横向排列,并让table按需横向scroll,而不是继续压扁内容。

适配移动端宽度后的员工列表标题、操作区与table前后对比

SMS历史与年假管理的filter也有同样的问题。多个输入框与日期范围被硬塞在一行。小屏幕上改成以两列为主,日期范围则另起一行,让每个项目都能看清并点击。

让SMS发送历史filter在移动端可读、可操作的前后对比

按移动端宽度重新排列年假管理filter的前后对比

修复后,我重新部署新的Docker image,并在同一部手机上再次登录。我打开菜单、滚动画面,直接查看每个filter和table,确认最初发现的缺陷是否消失。原本只是检查外部network能否抵达NAS container,最后却一路延伸到了修复真实使用界面。

分阶段迁移状态与管理员UI/E2E验证

把NAS迁移、外部访问和一条内部短信串起来后,我再次展开完整roadmap,发现第1到第3阶段已经越过。当前所在的位置是第4阶段:把改进后的管理员UI作为新image部署,再通过ADB和真实设备重新检查所有page。

Operations Automation阶段图:规划、旧版迁移和NAS连接已完成,正在进行管理员UI/UX部署与真机E2E

放上这张图后,这次工作的下一个边界也清楚了。外部访问本身已经通过,但在管理员界面的真机复验结束前,还不能进入总部dogfooding。因此下一步不是继续添加新功能,而是把修正后的UI检查到底,确认桌面端和移动端都维持同一业务流程。

生产切换前的安全状态与rollback

目前,新stack被刻意设置为不会自动执行任何操作。

ENABLE_SCHEDULER=False
SMS_SEND_MODE=NO_SEND
SMS_ALLOWLIST_MAX_CLAIMS=0

管理员credential没有写入Compose或image。NAS上通过权限为0600的secret file提供,Mac上则保存在Keychain中。

现在可以在新地址登录并读取数据,在受限条件下也确实收到了一条短信。使用外部移动网络时,我也确认了从登录、数据查询到界面操作的整个过程。即便如此,在删除既有年假短信服务前,仍需确定无delivery callback记录的恢复方式,并取得真实发送条件的批准。

所以,我只停止了既有container和volume,仍将它们完整保留。接下来需要的不是增加更多配置,而是决定如何恢复没有callback的发送记录,并在获准的条件下从少量真实发送开始开放。

除了技术迁移,我还把让AI一同查看真实手机以及Router、NAS管理界面后,自己感受到的变化写在了当你会主动运用AI时,能做的事仿佛一下变得无穷无尽中。

留下评论