/** * 分享链接与二维码纯逻辑(P4a Task 9,依赖注入 qrcode 实现供 vitest 覆盖) * * - viewer URL:VITE_VIEWER_BASE + /a/{publicToken}(viewer 路由 * /a/:token;base 缺省兜底本机 dev 5175,尾斜杠容忍) * - 二维码:node-qrcode canvas 渲染;实现经参数注入(单测不拉真库), * 组件侧默认传 QRCode.toCanvas */ /** viewer 部署基址(缺省兜底本机 dev) */ export const VIEWER_BASE_FALLBACK = 'http://127.0.0.1:5175' /** 部署基址 + 公开令牌 → viewer 相册页 URL(尾斜杠容忍) */ export function buildViewerAlbumUrl(base: string, publicToken: string): string { return `${base.replace(/\/+$/, '')}/a/${publicToken}` } /** 环境基址(VITE_VIEWER_BASE 缺省兜底;Vite 注入 import.meta.env) */ export function viewerBaseFromEnv(env: { VITE_VIEWER_BASE?: string }): string { const base = env.VITE_VIEWER_BASE?.trim() return base && base !== '' ? base : VIEWER_BASE_FALLBACK } /** 二维码单点绘制函数(注入边界:组件包 QRCode.toCanvas,单测传假实现—— @types/qrcode 的 callback 重载使整模块注入不可赋值,收窄到本签名) */ export type QrDraw = ( canvas: HTMLCanvasElement, text: string, options: { width: number; margin: number } ) => Promise | void /** URL → 二维码 canvas(组件 watch 相册变化时调用) */ export async function renderShareQr( canvas: HTMLCanvasElement, url: string, draw: QrDraw ): Promise { await draw(canvas, url, { width: 200, margin: 2 }) }