import { ref, computed } from 'vue'; /** * 生成随机字符串 * @param length 字符串长度 * @returns 随机字符串 */ function generateRandomString(length: number): string { const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; let result = ''; for (let i = 0; i < length; i++) { result += characters.charAt(Math.floor(Math.random() * characters.length)); } return result; } /** * 为验证码文本生成扭曲的 SVG * @param text 验证码文本 * @returns SVG 字符串 */ function generateCaptchaSvg(text: string): string { const width = 150; const height = 50; const fontSize = 30; const letters = text.split(''); // 应用于整个 SVG 的滤镜,增加噪点和轻微扭曲 const filter = ` `; // 为每个字母生成 元素,并应用随机变换 const textElements = letters.map((char, index) => { const x = (width / text.length) * (index + 0.5); const y = height / 2 + fontSize / 3; // 基线调整 const rotate = Math.random() * 30 - 15; // -15 到 15 度旋转 const skewX = Math.random() * 10 - 5; // 轻微倾斜 const fill = `hsl(${Math.random() * 360}, 70%, 70%)`; // 随机 HSL 颜色 return `${char}`; }).join(''); // 添加几条干扰线 let lines = ''; for (let i = 0; i < 3; i++) { lines += ``; } return ` ${filter} ${textElements} ${lines} `; } export function useCaptcha(length: number = 5) { const captchaText = ref(''); const userInput = ref(''); const captchaSvg = ref(''); const error = ref(''); /** * 生成新的验证码 */ const generateCaptcha = () => { const newText = generateRandomString(length); captchaText.value = newText; captchaSvg.value = generateCaptchaSvg(newText); userInput.value = ''; // 清空用户输入 error.value = ''; // 清除错误 }; /** * 验证用户输入 * @returns 是否验证通过 */ const validateCaptcha = (): boolean => { if (!userInput.value) { error.value = '请输入验证码'; return false; } if (userInput.value.toLowerCase() !== captchaText.value.toLowerCase()) { error.value = '验证码错误'; generateCaptcha(); // 错误后自动刷新 return false; } error.value = ''; return true; }; // 初始化生成第一个验证码 generateCaptcha(); return { userInput, captchaSvg, error, generateCaptcha, validateCaptcha, }; }