大家好,我是 AI 淇橦学。

上一篇我介绍了墨语(摸鱼)这个手写模拟器。有朋友看完问我,"你说的那些功能都做出来了,应该很顺利吧?"

其实恰恰相反,完全不顺利。

做完第一版那天,我在电脑上打开预览,效果挺满意。字体有变化,纸张有纹理,导出也清晰。

然后我用手机打开了一下。

加载慢。纸张框选不了。预览看不到文字。导出次数重新打开又恢复了。

那天晚上我一个一个修,修到凌晨。有些问题修好了,有些问题 AI 改了三遍还是不对,只能回退到上一版本重来。

这一篇,咱就聊聊开发墨语(摸鱼)时踩的那些坑。

二、手机端六个真实问题

) 做完第一版,我上传到云服务器,用手机浏览器打开测试。

第一个发现的问题是加载速度。第一次打开特别慢,字体要一个一个加载,页面基本是白屏状态。你站在用户角度想,打开一个工具,等了十秒还在加载,你还想继续用吗?我反正是直接关了。

修复方向是让字体走国内资源,把静态资源放到腾讯云 COS,减少跨洋请求。

然后是手机端四个步骤的问题。

问题一,纸张框选不了。

第二步选择纸张的时候,桌面上能用鼠标框选,但手机上用手指怎么划都没反应。就算偶尔能框选,边框颜色太淡,在手机屏幕上根本看不出来选了没选。

后来查到原因,桌面端的鼠标事件在手机上不可靠。手机要用 pointer 事件,还要设置 touch-action,否则手指划动的时候浏览器会当成页面滚动。

我把框选边框加粗,改成了红色。手机屏幕小,反馈必须明显,否则用户以为没选中。

问题二,上传 Word 的入口不好找。

第三步输入文字,用户反馈说找不到上传 Word 的地方。页面往下滑,滑到某个位置就滑不动了,不知道下面还有没有内容。

按钮做了,页面也显示了。问题在于手机端信息层级没设计好。一个步骤塞了太多控制项,用户以为页面到底了。

后来把 Word 上传入口明确放在输入区域旁边,风格预设的高度也控制了,底部按钮固定但不挡住内容。

问题三,预览文字不显示。

第四步手机上预览,看不到文字。但奇怪的是,导入记录显示内容确实存在。

数据没丢,但显示不出来。这种问题排查起来最头疼。可能是字体没加载完,可能是画布尺寸不对,可能是渲染没触发,可能是文字画在了可视区域外面。每个可能性都要单独验证。

用户看到的是"没显示",工程上要查的是一整条链路。

问题四,导出次数重置。

手机导出一次,提示还剩 2 次。关掉浏览器重新打开,又变成 3 次了。

根因是设备身份识别不稳定。纯 localStorage 在某些手机浏览器上不可靠,重新打开可能生成一个新的设备 ID。

修复方式是加了一层 cookie 兜底。就算 localStorage 被清,cookie 还能识别设备。长期方案应该是以服务端记录为准。

问题五,纸张模板选了没用。

选了"拍照白纸""横线笔记本"这些模板,界面上卡片显示的图片也对了,但预览和导出还是旧的线格纸。

查了一下发现,界面显示的是新图片,但渲染引擎还在按旧的 paperMode 程序画线格。UI 状态和渲染输入是断开的。

修法是让预设纸张把 PNG 直接加载成背景图,预览和导出都用同一张图。旧的占位文件也删掉,避免部署时继续被误用。

问题六,加载速度慢。

这个前面提了,但值得单独说。服务器在新加坡,国内手机访问速度很慢。字体文件大,跨洋加载更慢。

这个问题的根源其实是部署决策导致的,下一篇咱专门聊。


三、多区域书写是怎么来的

上面都是手机端的问题。还有一个功能上的需求,也是我自己用的时候发现的。

上传自定义纸张模板后,我发现一个问题。比如会议记录这种模板,上面有"时间、地点、参会人员、会议主题"这些区域,每个区域都要分别填文字。如果你把整张纸当一个大区域,所有文字堆在一起,效果完全不协调。

所以我就加了多区域书写功能。可以在一张纸上框选多个区域,每个区域单独输入文字,单独设置参数。

这个功能市面上的手写模拟器基本都没有。我自己用了才知道需要,用户反馈里没人提到这个。

有些需求得自己踩一遍才知道。


四、架构改了四次

技术层面,这个项目的架构经历了四次升级。

说实话,每次升级都不是计划好的,是被逼的。

第一次,3359 行单 HTML 文件。

最初就是一个文件,双击浏览器就能打开。好处是快,坏处是改一处坏一处。到了 3000 多行的时候,找一个函数要在文件里搜索半天。

第二次,拆成 7 个模块。

核心原则是渲染引擎完全独立,不依赖任何网页元素。它只做计算,输出像素。这样同样的引擎未来可以放到桌面端或手机 App 里复用。

第三次,Vue 3 + TypeScript。

项目需要正式的 UI 框架了。用了 Pinia 做状态管理,Naive UI 做组件库。

第四次,Monorepo。

为了 Web 版、桌面版、手机版共用同一套核心代码,拆成了 npm workspaces 结构。

核心设计决策只有一个,渲染引擎零 DOM 引用。纯函数,可以在任何平台跑。

这一路改下来,有一个体会特别深。每次只做一件事。第一次只管拆模块,第二次只管上框架,第三次只管跨平台。不要试图一步到位。


五、踩坑总结

)

回顾整个过程,几个教训。

第一,本地跑得通不等于手机能用。 桌面端鼠标操作流畅,不代表手机端触摸操作也流畅。必须在真实设备上测试,而且要像真实用户一样走完每一步。

第二,用户说"不满意"的地方,才是真问题。 有些问题我自己觉得"差不多就行了",但用户就是过不去。比如框选边框颜色这种细节,在电脑上无所谓,在手机上就是体验断裂。

第三,AI 写代码很快,但产品判断不能外包。 AI 帮你实现功能,但它不知道用户在手机上看到的是什么。你得自己打开手机,自己点一遍,自己觉得不顺的地方记下来,再让 AI 修。

第四,做工具类产品,最怕"局部正确"。 单独看每个模块都没问题,连起来就坏。预览看着正常,导出不对。界面选了新纸张,渲染还在用旧的。工程上的可靠性,来自把所有链路统一。

第五,先跑起来再说。 别一开始就追求完美架构。我那个 3359 行的单文件,帮我验证了核心假设,手写效果够不够好。够好,才有后面四轮重构的动力。


先跑起来,再一轮一轮地修。每一轮修完,产品就离"能用"近了一步。

做墨语(摸鱼)这一周,每天都在体会这个过程。AI 帮我把问题拆成可执行的修复链路,我负责判断修复方向对不对。

下一篇,咱聊聊部署上线的那些事。从买服务器到手机能打开,中间踩的坑比开发还多。


关注公众号「AI 淇橦学」,和 AI 一起成长。 有问题或建议?后台留言即可。