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 `
`;
}
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,
};
}