HelloCard 网页贺卡生成器 —— 一个第一次发帖的萌新,用华为云码道(CodeArts)2 小时造了一张能转发的“网页祝福“
HelloCard 网页贺卡生成器 —— 一个第一次发帖的萌新,用华为云码道(CodeArts)2 小时造了一张能转发的"网页祝福"
不是大佬,不是工程师,就是一个周末闲着没事、想做点小东西的普通人。
如果你也是新手,这篇文章可能正好是你需要的"第一份能跟着抄完的实战"。
这次想搞个什么?
事情是这样的:
🌧️ 周六下午,下雨,没事干。
🎁 朋友说:“我下周生日,能不能发我个特别点的祝福?”
🤔 我心想:朋友圈那种"复制粘贴长文"太敷衍了,我得搞点新意。
💡 灵光一现:做一张能用网址转发的"网页贺卡"—— 朋友点开链接就是一张飘彩纸的卡片,上面写着我对 TA 说的话。
但问题是:
- 我会一点 HTML,但没做过完整的"应用"
- 我没钱买云服务器
- 我不会后端、不会数据库
- 我只有 2 个小时,今晚约了饭
抱着试试看的心态,我打开了华为云码道(CodeArts)AI IDE。
📌结论先说:2 小时 7 分钟后,我把链接发给朋友了。
📌朋友的反馈:第一句是"卧槽这是你做的?"
📌总成本:~3 元 Token + 几乎为零的 OBS 存储费
下面是这 2 小时的全程记录,新手向,能跟着复刻。
1. 先聊聊"网页贺卡"是个啥?为什么不需要后端?
这一段对资深的人是常识,但对新人可能是关键认知。
🧠核心思路:把祝福内容塞进 URL(网址)本身。
像这样:
https://xxxxxx.obs.example.com/index.html?to=小明&from=神秘人&msg=生日快乐&theme=🎂朋友点开这个网址,浏览器就能把?后面的内容读出来,拼成一张卡片显示给 TA。
✨这意味着:
- ❌ 不需要后端(没人需要保存数据)
- ❌ 不需要数据库(数据就在网址里)
- ❌ 不需要登录注册(谁拿到链接谁看)
- ✅ 只要 1 个
index.html文件就够了
🎉 那我就有信心了 —— 我会的那点 HTML 知识,刚好够用。
2. 进码道,先和它"约法三章"
打开码道(华为云开发者空间里直接开网页版,免下载)。新建空项目HelloCard。
📍 这一步关键中的关键:先写 AGENTS.md,再开口说话。
这是码道4-5 月新特性「新增 AGENTS.md 文件支持」—— 简单说就是把"我是谁、我喜欢什么、不要给我整啥花活"写进一个文件,AI 就会按这个规矩说话。
我之前没用码道的时候,AI 一上来就推荐我用 React,让我装 Node,结果一晚上没跑起来 😭。这次先写 AGENTS.md,后面就再没翻过车。
我在项目根目录新建AGENTS.md,把"游戏规则"摆出来:
# HelloCard · AGENTS.md ## 一句话规则 只要 1 个 index.html 能搞定的,绝不分文件、绝不引入框架、绝不上 npm。 ## 我是谁 - 编程菜鸟一枚,会基础 HTML/CSS,JS 还在入门 - 最讨厌"装环境装一下午" ## 子代理 @buddy(搭子) 每次回复请: - 用"哥们儿/姐们儿"般的轻松语气 - 关键代码必须给出可直接复制的完整版 - 解释一律用类比 / 大白话 ## 禁止 - ❌ React / Vue / 任何需要 build 的东西 - ❌ Node.js 后端💡 我把 AI 子代理叫做
@buddy(搭子)。一旦我 @ 它,码道就会用我设定的"搭子语气"回话,比官方的"严肃工程师"模式亲切多了。
保存。码道左下角弹了一行字:
✅ 已加载项目规约
AGENTS.md,子代理@buddy已就位。
OK,开整 ✊。
3. 直播实录 · 第 1 小时:从零搭出能用的雏形
接下来全是我和
@buddy的真实对话节选。
〔我〕代表我说的话,〔@buddy〕代表 AI 的回复(精简版)。
3.1 第一句话,不要怂
〔我〕
@buddy 我想做一个网页贺卡。用户在编辑页填"送给谁/我是谁/祝福语/主题",点按钮生成一个带参数的网址,把这个网址发给朋友,朋友打开就能看到一张漂亮的卡片。
一个 index.html 搞定。先给我把骨架搭起来。
〔@buddy〕
行嘞 ✌️。咱要的核心思路是:编辑模式 + 展示模式 共用一个文件,靠 URL 有没有参数来区分。
- 没参数 → 显示编辑表单
- 有参数 → 显示卡片
来,先抄这版骨架(含 HTML+CSS+JS 一体):
(@buddy 给了大约 70 行的初版)
我把代码复制到index.html,双击打开。
🟦 屏幕上出现一个粉色背景,中间一个白色卡片,里面有 4 个输入框和一个"生成专属链接"按钮。
🤩 比我心里想的好看。
3.2 让按钮真的能"生成网址"
〔我〕
我点了按钮没反应啊,应该跳到带 ?to=xxx 那个网址才对吧
〔@buddy〕
对,是我藏了个坑(笑)。我先让你看看 UI,逻辑得自己加。来抄这段:
functionbuildUrl(data){constsp=newURLSearchParams();Object.entries(data).forEach(([k,v])=>v&&sp.set(k,v));returnlocation.origin+location.pathname+'?'+sp.toString();}document.getElementById('gen').addEventListener('click',()=>{constto=document.getElementById('to').value.trim();constfrom=document.getElementById('from').value.trim();constmsg=document.getElementById('msg').value.trim();consttheme=document.getElementById('theme').value;if(!to||!msg){alert('收件人和祝福语不能空哦~');return;}consturl=buildUrl({to,from,theme,msg});location.href=url;// 跳到带参数的自己});解释一下哈:
URLSearchParams是浏览器内置的"网址参数管家",你给它喂键值对,它帮你拼成?to=xxx&from=yyy,自动处理中文转码(不然中文会变乱码)。location.href = url让浏览器跳转,等于跳到带参数的自己,触发咱们下一步要写的"展示模式"。
复制粘贴,刷新。
填了 “to=朋友A” “msg=生日快乐”,点按钮。
📍网址变了:...index.html?to=朋友A&msg=%E7%94%9F%E6%97%A5%E5%BF%AB%E4%B9%90&theme=🎂%7C生日快乐!
但是页面还显示编辑框 —— 因为我还没写"展示模式"。
3.3 让页面"判断"自己该显示啥
〔我〕
现在网址变了,但页面没变。怎么让它看到 ?to=xxx 就切换成卡片?
〔@buddy〕
这就是"启动判断"的活儿,加在
<script>最开头:functionreadParams(){constsp=newURLSearchParams(location.search);return{to:sp.get('to')||'',from:sp.get('from')||'',theme:sp.get('theme')||'',msg:sp.get('msg')||'',};}constparams=readParams();if(params.to&¶ms.msg){showCard(params);// 有完整内容 → 展示卡片}else{bindEditor();// 否则 → 编辑模式}
location.search就是网址里?开头的那一段。咱拿到to和msg,有就切卡片,没有就让用户编辑。逻辑像不像门口的保安?看你有没有票,决定让你进剧场还是去售票处。
我笑出声:这比喻好懂啊。
3.4 卡片渲染 + 撒彩纸彩蛋
〔我〕
卡片要好看一点,最好打开还能撒彩纸 ✨
〔@buddy〕
嘿这才有过节的样子。来看
showCard完整版:functionshowCard(p){document.getElementById('editor').style.display='none';document.getElementById('card').style.display='block';const[emoji,greet]=(p.theme||'🎂|你好').split('|');document.getElementById('cEmoji').textContent=emoji;document.getElementById('cGreet').textContent=`${escapeHtml(p.to)},${escapeHtml(greet)}`;document.getElementById('cMsg').textContent=p.msg;document.getElementById('cFrom').textContent=p.from?`——${p.from}`:'';confetti();// 撒彩纸}撒彩纸用纯 CSS 动画 + JS 生成 40 个小色块就行(完整代码在文末)。
零依赖、纯原生,符合咱 AGENTS.md 的死规矩。
我刷新 —— 朋友 A 的卡片显示出来了,40 片彩纸从屏幕顶部哗啦啦飘下来🎉🎊
🥲 第一次"用代码做出过节感",太爽了。
4. 翻车现场:朋友把我网页"黑"了
得意洋洋发给朋友 B 试试。
朋友 B 是个程序员,10 秒后回我一句:“你这有 XSS 漏洞 😏” + 一个新链接。
我点开 ——页面弹出一个alert("被我黑啦")框。
😱😱😱
〔我〕
@buddy 朋友输入了
<script>alert("被我黑啦")</script>,结果真弹框了,怎么办!
〔@buddy〕
哥们儿别慌,正常的"成长痛" 😂。这玩意儿叫XSS(跨站脚本攻击):
打个比方:你开了家面馆,菜单上写"客人写啥我就照做啥"。客人写了"把店关了",你真去关,店没了 —— 这就是 XSS。
修法:用户输入的字,永远不要直接当 HTML 塞进页面。
我看了下你的代码,大部分地方我用的是
.textContent(自动转义,安全),但cGreet里我用了模板字符串拼接,需要手动 escape 一下。加个工具函数:functionescapeHtml(s){returnString(s).replace(/[&<>"']/g,c=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c]));}然后凡是用户输入的东西在拼 HTML 之前都包一层
escapeHtml(...)。
我修完,让朋友 B 再试 ——这次页面只是显示一行文字<script>alert("被我黑啦")</script>,不再执行了。
🛡️ 朋友 B 回:“行,及格了。”
🎓这一段是我整个 2 小时学到最值钱的东西:
- 之前以为 XSS 是"大网站才有的事"
- 原来个人小项目稍不注意就中招
- AI 不仅修了,还讲清了为啥会犯 + 怎么防范
5. 第 2 小时:用上"记忆模块",让搭子真的"懂我"
🪄 这一段我想专门聊聊码道的**「记忆模块」新特性** —— 第一次用震撼到我了。
事情是这样:
我做完核心功能后,把页面截图发给闺蜜看。她说"颜色再粉一点、再温柔一点"。
〔我〕
@buddy 我闺蜜说颜色不够温柔,再美一下
〔@buddy〕
(自动改了 CSS,给我换成了奶橘 + 粉的渐变)
顺带我把这条记下来了:
✅ 已记入项目记忆:主人偏好柔和渐变(粉/橙/紫系),UI 要"温柔"。
🤯 等等,它把我的偏好记下来了?
下午我又开了新会话,让@buddy加一个"复制链接"按钮。它生成的代码里 ——按钮颜色直接用了我之前的粉色,没问我一个字。
〔我〕
你怎么知道用粉色?
〔@buddy〕
记忆里写着呢哥们儿 😎。你之前说过"温柔粉橙紫",我默认就按这个来。
😭第一次有"AI 真的认识我"的错觉。
📌这就是码道的记忆模块:
- 不是只在这个对话里记住
- 是写到项目里,下次新开对话也认得
- 不用我每次都重复"我喜欢粉色、不要太正经…"
6. Skill 复用:让"复制按钮"功能 30 秒就完成
还有一个新特性叫Skills(技能),我也试了一下,挺神奇。
需求:在卡片下方加一个"📋 复制链接"按钮,点了就把当前网址复制到剪贴板。
正常情况下我得:
- 找剪贴板 API 怎么用
- 处理"复制成功/失败"的反馈
- 处理浏览器兼容性
但码道的Skills 仓库里有现成的clipboard-copy技能。
〔我〕
@buddy 给卡片加个"复制链接"按钮,调用 clipboard 技能就行
〔@buddy〕
(直接套用技能模板,30 秒给出代码)
document.getElementById('copy').addEventListener('click',async()=>{try{awaitnavigator.clipboard.writeText(location.href);alert('已复制到剪贴板~');}catch{alert('请手动选中链接复制');}});这个技能我已经用过 200+ 次了,直接套就行。
try/catch是兜底:用户用老浏览器没这个 API,咱让 ta 手动选 —— 不让任何一个用户卡住。
📌Skill 的价值:把"重复轮子"沉淀下来,新手不用从零学剪贴板 API、CORS、错误兜底,站在前人肩膀上写代码。
7. 部署上线:华为云 OBS,2 块钱不到
🌐 现在网页只在我电脑上能开,朋友怎么访问?
最便宜的方案:华为云 OBS 静态网站托管。
💸 价格扫盲(按官网当前价):
- 标准存储:约0.0099 元 / GB / 月
- 我这个
index.html才 6 KB,可以忽略- 流量按访问量算,朋友圈分享几十次也就几分钱
7 步搞定(小白照搬):
- 登录华为云控制台 → 搜 「对象存储 OBS」
- 创建桶
- 桶名:随便起,但必须全网唯一(比如
hellocard-小写英文-数字) - 区域:选离你近的(北京/上海/广州)
- 存储类别:标准存储
- 桶策略:公共读
- 桶名:随便起,但必须全网唯一(比如
- 进入桶 → 点上传对象→ 把
index.html拖进去 - 左侧菜单 →基础配置 → 静态网站托管 → 启用
- 默认主页填:
index.html
- 默认主页填:
- 在「概览」页找到「访问域名」
- 浏览器打开这个域名,编辑一张贺卡试试
- 把生成的链接发给朋友 ✅
我的真实账单
| 项目 | 数据 |
|---|---|
| 上传对象 | 1 个文件(6 KB) |
| 当月预估存储费 | < 0.01 元 |
| 朋友圈预计访问量 | 30 次左右 |
| 当月预估流量费 | < 0.5 元 |
| 总计 | 不到 1 块钱 |
📌这意味着:你做一个能上线的小项目,月成本可能比一杯奶茶的零头还少。
8. 真实演示:把链接发给朋友是什么体验
朋友 A 的生日卡链接(化名):
https://hellocard-xxxx.obs.cn-xxxx.example.com/index.html?to=朋友A&from=神秘人&theme=🎂%7C生日快乐!&msg=祝你新的一岁,所有好运都不期而至,所有想去的地方都顺利抵达。朋友 A 的真实反馈(已经过她同意分享):
“卧槽这是你做的??我以为你买了什么会员”
“彩纸我看了 3 遍 哈哈哈哈”
“把链接发给我老公他也想要一个”
🥹 那种“代码改善了一段真实关系”的感觉,比写 100 个练习题都爽。
9. 一个新人,从这 2 小时里学到的 8 件事
- AGENTS.md 是新手最大的护身符。把"别给我整 React"写进去,AI 就乖乖给你纯 HTML。
- URL 参数是个很被低估的"伪后端"。不需要数据库,照样能做"分享链接"。
URLSearchParams自动处理中文转码,比手写encodeURIComponent省心。textContent比innerHTML安全。前者自动转义,后者会执行 HTML,是 XSS 元凶。- XSS 不是大公司的事。哪怕个人小玩具,朋友随手就能让你弹框。
- 彩纸动画不需要任何库。CSS
@keyframes+ 40 个<div>,搞定。 navigator.clipboard要包 try/catch。老浏览器没这 API,得给用户手动复制的兜底路径。- OBS 静态托管是新人部署最便宜的方案。花一杯奶茶钱够你的小网页跑半年。
10. 给新人的 4 个建议
- 别等"学完"才动手。我 HTML 才看了几节课,照样做出能转发的小作品。开始本身就是最大的学习。
- 第一句话先写 AGENTS.md。3 分钟的事,能省后面 3 小时。
- 每次让 AI"用人话讲讲为什么"。比代码本身重要 100 倍。
- 做的东西要"有人会用"。朋友收到我贺卡的那一刻,是我学代码以来最有成就感的瞬间。
但我真的想说一句:AI 编程工具的意义,不是让程序员更快,而是让原本不写代码的人,也能创造点什么。
闺蜜不会写代码,但她下个月会用我教的方法,给她爸做一张父亲节贺卡。
朋友 A 已经把链接发给老公了。
朋友 B 让我帮他做"求婚倒计时"页面(我还没接,怕翻车 😂)。
这些用代码改善关系的瞬间,是我学习路上最大的奖励。
如果你也是新手,看到这里 —— 试试吧。
打开华为云码道,写一句@buddy 我想做个 XX,让它带你做。
第一个能跑起来、能分享出去的小东西,会改变你看代码的方式。
🌈 祝你做出第一张属于自己的贺卡。
