我的猫终于打上冰球了------一个 Vue3 + Coze AI 项目的完整落地手记
"代码跑通那一刻,我家布偶猫正以国漫风格站在冰场中央,身穿10号红衣,左手持杆,眼神坚毅。"
------这不是幻想,这是我亲手写出来的现实。
从"想法"到"生成成功",中间隔着无数个 401 Unauthorized
上周我还在为一句报错抓狂:access token invalid。
明明 .env 里写了 VITE_PAT_TOKEN,控制台也打印出来了,为什么 Coze 就是不认?
后来才发现:Token 被我误删了权限。在 Coze 后台重新生成时,忘了勾选「文件上传」和「工作流执行」------于是前端传什么都石沉大海。
修复后,第一张图成功返回的瞬间,我截图发到群里,朋友回:"你这狗穿护具的样子,比我还认真。"
这段代码,是我和 AI 的"协作协议"
现在的代码,已经能稳定完成三步走:
- 用户上传宠物照 → 前端用
FileReader实时预览,体验丝滑; - 调用 Coze 文件接口 → 把图片上传到云端,拿到
file_id; - 触发工作流 → 把
file_id+ 队服颜色/位置/风格等参数打包,交给 AI 生成最终图像。
关键逻辑藏在这几行里:
yaml
const parameters = {
picture: file_id, // 不再 JSON.stringify!直接传 ID
style: style.value,
uniform_color: uniform_color.value,
position: position.value,
shooting_hand: shooting_hand.value,
}
早期我错误地把 picture 包成 JSON 字符串,结果 Coze 工作流收不到有效文件引用。AI 再聪明,也得喂对格式的数据。
还有那个经典的笔误:
csharp
const ret = await ret.json(); // ❌
改成:
csharp
const ret = await res.json(); // ✅
------少这一行,整个流程卡死在黑屏。
类型陷阱:字符串 vs 数字
Vue 的 <select> 默认把 value="0" 当作字符串,但我初始化的是 ref(0)(数字)。
虽然后端可能宽容处理,但为了严谨,我加上了 .number 修饰符:
ini
<select v-model.number="position">
<option :value="0">守门员</option>
<option :value="1">前锋</option>
</select>
现在 position.value 确实是 0、1、2,而不是 "0"、"1"。
类型一致,是前后端和平共处的第一条公约。
安全红线:PAT Token 不该出现在前端
我知道,把 VITE_PAT_TOKEN 放在前端是个"定时炸弹"。
只要有人打开 DevTools,就能看到我的 Token,进而滥用我的 Coze 配额。
所以这个版本只是 MVP(最小可行产品) 。
下一步,我会用 Vercel Edge Function 或 Cloudflare Worker 写一个轻量代理:
javascript
// /api/generate/route.ts (Next.js App Router 示例)
export async function POST(req) {
const { imageBase64, ...params } = await req.json();
// 1. 用后端 PAT 上传文件
// 2. 触发工作流
// 3. 返回 CDN 图片 URL
return new Response(JSON.stringify({ url }));
}
前端只和自己的 API 对话,Token 永远不出服务器。
好玩的项目,也要有安全的骨架。
最终效果:不只是技术,更是情绪价值
当用户上传一张慵懒的猫咪照片,选择"守门员 + 油画风 + 黑色队服",
十秒后,屏幕上出现一只披着厚重护甲、站在冰面裂缝前的猫------
那一刻,技术完成了它的使命:把日常变成童话。
而我,只是一个搭桥的人:
用 Vue3 收集愿望,用 Coze 实现魔法,
中间那几行代码,就是咒语。
结语
这个项目还没结束。
接下来要加分享海报、失败重试、加载动画......
但今天,它已经能让我家主子在朋友圈 C 位出道。
如果你也在做一个"看似无用但超有趣"的小应用,
别怕它简单,别嫌它幼稚。
世界需要更多会打冰球的猫,也需要更多敢写第一行代码的你。