时光飞逝,光阴似箭。转眼间,三年初中生涯已落下帷幕。
回望 2026 年春节前夕,在某个心血来潮的瞬间,WenPill 诞生了。
最初的想法是做一个类似于「手帐」的静态纪念册项目,最初的 Demo 也是纯静态的 HTML 页面。但在多次思考后,觉得静态纪念册还是过于简单了,因此最终决定采用 Python Flask 的动态渲染方案。
UI & 前端
最初的 Demo 是纯深绿色作为主色调的圆角矩形+液态玻璃的方案。但在后续的测试中发现性能过于堪忧(毕竟液态玻璃连 Apple 自己还没优化好,还是太吃性能了),以及色调过于阴暗、主色调与现有的项目不统一、浏览器支持等问题,最终决定采用现在这版稍浅色调,圆角+毛玻璃的设计。
UI 的初稿由 Google Stitch 生成,后续手动补充 & 微调。虽说 Gemini 3.1 Pro 的 UI 设计现在已经是第一梯队的了,但一致性还是不太理想,页面的细节样式/排版对齐/动画还须人工完成。

3月份,前端大致功能方向明确:
- 首页
- 相册+
上传(现如今的时光册页面;上传功能则因使用频率不高及安全问题,在最后上线前被砍掉) - 同学信息(同学录)
- 教师数据(群里的问卷调查)
- 3D 高斯泼溅
- 关于
在4月,基本功能完成了开发,但功能仍较为基础,部分功能只有占位符。

后端
原本打算采用 PHP/C++ 来写,但是后来发现 Python 完全够用了(数据和并发量也不高);MySQL 被换成了 JSON(是的,你没看错,相当于把 TXT 当数据库来存了😱)。当然经过这一番降本增笑(效),我们的开发效率也大幅提升。经过一段时间的修修补补,我们的主程序代码量也再创新高,达到了3500+(已经乱到不用 Agent 压根读不懂代码到底写的是什么的地步了)。Route 路由数也是再创新高,环环相套已经成屎山代码了。

因为做了时光册的缘故,为了方便管理,干脆单独做了个管理的 macOS App(管理部分直接套用去年做的 WenBlog App 的 UI,需要二次修改的地方使用 AI 完成)。

安全方面也不能少。后端先使用 CDN 回传的 IP 做区域检测,进行初步判断。再无问题后使用出生日期进行身份校验(包含 QOS 限制)。为防止爆破,异常流量也做了判断和 403 拦截。所有照片/内容均使用 Cookie 鉴权。
首页
这是最开始构想的一个重点页面。需要简洁、轻量、现代化而又不失「毕业纪念册」的风格。要包含 Banner、功能卡片以及寄语等内容,完成时间较早。
该页最后的寄语来自 ChiliChill 的《飞鸟说》。
时光册
这也是一个重点页面,而且是这些页面里体量最大的一个。最初在本地服务器测试时一切正常,好到我不敢相信是我自己做的(因为没有带宽限制/超高延迟的 Debuff),但一上线就开始出现问题了:图片量太大导致加载过多,同时因为没有 ICP 备案, CDN 节点只能在中国大陆以外,最终导致初次测试时的加载时间长达20s。于是便开始着手进行优化:首先是降本增效,压缩图片体积,成功减少了20MB+(原来加载一直用的原图),但仍然很慢。最后使用了预加载(在主页浏览时就会预先缓存时光册的图片资源),才基本解决。
然后是图片查看器,因为现有开源的 LightBox 与现有UI风格不统一,所以决定自己手搓一个,这导致图片查看器这块的 Bug 尤其多,鼠标、触控板、手机、平板端,在每种设备上都有奇奇怪怪的问题,其中有些到最终上线时也没解决(组图放大到一定程度时会自己移动到下一张图片;图片放大后清晰度异常)。

你还可以在纪念册页的最后一张图片「运动会 · 高中部」的右下角看见烂尾的「实况照片」按钮,原本的体验已经与系统内的体验几乎无异,但同样是最后因为 CDN 问题而被迫搁置。
同学录
这是最奇思妙想的,同时也是功能最完整的一个页面。

先来说说个人卡片,包含每个人自己的签名/昵称/座右铭以及别人给 TA 打的 Tag。关于电签,这是我六年级毕业时就有的想法:墨水会褪色,纸张会丢失,要是能数字化多好呢?说到这里,感谢 Affinity,这是我用过最棒的图像编辑 App,其中的批处理功能更是帮我解放了双手,不用再一个一个扣签名了(小学毕业时真这么干过,只不过没做几张就放弃了)。
签名先是用打印好定位格的A4纸在学校收集签名,后期通过扫描、批量裁剪和人工纠正处理,最终提取出透明底的 png 签名。这样既保留纸质签名的书写痕迹与字重,又能将每个人的签名数字化。

Tag 功能是我当时的灵光一现:既然做的是动态渲染的页面,那肯定不能做的跟静态页面一样。又想到可以投票选择自己对某人的“印象”,于是乎 Tag 功能诞生了。
最后的签名墙想法来自于@Ollas,使用已有的签名进行排列+ Canvas,最后并到了同学录页(这何尝不是一种资产复用)。
教师评分 & 留言板
教师评分页展示了从同学群内收集的教师评分问卷结果,也是完成时间较早的页面之一,后于上线前添加感谢计数功能。
留言板页没什么可说的,不过显示问题一直没解决,留言达到一定量后会自己消失(貌似是浏览器支持问题)。
高斯泼溅(3DGS)
先使用五班教室外的楼道作为试验,但效果并不是太好。后来使用 Action 5 Pro 搭配 iPhone 13 mini 的组合进行同步录制,最终渲染出来的效果才勉强能看。由于时间原因,最终精度仍然较低。

然而更重要的是如何将模型嵌入页面。一个走廊场景使用经压缩过的 .ply 仍然有20MB,教室更是高达200MB+,这是完全不能接受的,流量和设备都要完蛋了(就连M系列iPad也才勉强跑到60FPS,更别说绝大多数人的设备了)。最终采用了动态加载+削减面数来解决。
如果想保存完整版的话,可以从 Replay 下载页下载完整的高斯泼溅模型并通过本地查看。
素材
时光册的素材由班主任 & 同学们提供,使用 Google Gemini 进行整理分类和挑选。
图标使用 Icon Composer 制作;其他背景和图像大多使用 NanoBanana Pro 生成。
这个 Icon 风格也将应用到 WenBlog 和未来的项目上。
部署
部署环境为 Linux,Python 3.14.0。采用 Gunicorn 作为 Web 服务器和 OpenResty 反向代理。
WenPill 目前部署在一台位于新加坡的云服务器上,由 Tencent EdgeOne 和 Cloudflare 提供 CDN 支持。部分分发内容存储在 COS 上。
最后
这是我人生中完成的第一个全栈开发项目,从2月开始构思到6月完成。在这四个月里,经历了很多事,也从中学到了很多。
实践。
即使 WenPill 的功能或许还很“简陋”,架构或许也谈不上健壮,但它却是我亲手制作而成的结晶。对我而言,这既是告别初中时代的终章,也是向广袤的开发世界正式递交的第一份答卷。
鸣谢
班主任和三年间的所有老师们;
五班全体同学

REACHED THE FINALS!
