diff --git a/server/api/qrcode.get.ts b/server/api/qrcode.get.ts new file mode 100644 index 0000000..e7cadc7 --- /dev/null +++ b/server/api/qrcode.get.ts @@ -0,0 +1,48 @@ +import QRCode from 'qrcode' + +/** + * 通用二维码生成 + * + * 为什么需要这个接口: + * 微信小程序**没有**任何 API 能直接唤起系统浏览器 / 离开小程序打开一个网址。 + * 官方可行的方式只有两种: + * 1. —— 内嵌打开(不离开小程序),且个人主体不可用 + * 2. 复制链接,让用户自己去浏览器粘贴 + * 还有一种能**真正离开小程序**的官方途径:**长按图片 → 识别图中二维码**。 + * 本接口就是把 URL 渲染成二维码图片,供小程序端 wx.previewImage 展示。 + * + * 用法: + * GET /api/qrcode?text=https%3A%2F%2Fbywmusic.bzw-hheb.top%2Fdashboard + * 返回 { success: true, dataUrl: 'data:image/png;base64,...' } + * + * 安全: + * · 需要登录(避免被当成免费二维码生成服务) + * · 只接受 http/https 链接,且长度受限 + */ +export default defineEventHandler(async (event) => { + const user = event.context.user + if (!user) { + throw createError({ statusCode: 401, message: '未授权访问' }) + } + + const query = getQuery(event) + const text = typeof query.text === 'string' ? query.text.trim() : '' + + if (!text) { + throw createError({ statusCode: 400, message: '缺少 text 参数' }) + } + if (text.length > 512) { + throw createError({ statusCode: 400, message: '内容过长(最多 512 字符)' }) + } + if (!/^https?:\/\//i.test(text)) { + throw createError({ statusCode: 400, message: '只支持 http/https 链接' }) + } + + const dataUrl = await QRCode.toDataURL(text, { + errorCorrectionLevel: 'M', + margin: 1, + width: 480 + }) + + return { success: true, dataUrl } +})