53 lines
1.3 KiB
JavaScript
53 lines
1.3 KiB
JavaScript
// frontend/js/utils/utils.js
|
|
function debounce(func, wait) {
|
|
let timeout;
|
|
const debounced = function(...args) {
|
|
const context = this;
|
|
const later = () => {
|
|
clearTimeout(timeout);
|
|
func.apply(context, args);
|
|
};
|
|
clearTimeout(timeout);
|
|
timeout = setTimeout(later, wait);
|
|
};
|
|
debounced.cancel = () => {
|
|
clearTimeout(timeout);
|
|
};
|
|
return debounced;
|
|
}
|
|
function isValidApiKeyFormat(key) {
|
|
const patterns = [
|
|
// Google Gemini API Key: AIzaSy + 33 characters (alphanumeric, _, -)
|
|
/^AIzaSy[\w-]{33}$/,
|
|
// OpenAI API Key (新格式): sk- + 48 alphanumeric characters
|
|
/^sk-[\w]{48}$/,
|
|
// Google AI Studio Key: gsk_ + alphanumeric & hyphens
|
|
/^gsk_[\w-]{40,}$/,
|
|
// Anthropic API Key (示例): sk-ant-api03- + long string
|
|
/^sk-ant-api\d{2}-[\w-]{80,}$/,
|
|
// Fallback for other potential "sk-" keys with a reasonable length
|
|
/^sk-[\w-]{20,}$/
|
|
];
|
|
return patterns.some((pattern) => pattern.test(key));
|
|
}
|
|
function escapeHTML(str) {
|
|
if (typeof str !== "string") {
|
|
return str;
|
|
}
|
|
return str.replace(/[&<>"']/g, function(match) {
|
|
return {
|
|
"&": "&",
|
|
"<": "<",
|
|
">": ">",
|
|
'"': """,
|
|
"'": "'"
|
|
}[match];
|
|
});
|
|
}
|
|
|
|
export {
|
|
debounce,
|
|
isValidApiKeyFormat,
|
|
escapeHTML
|
|
};
|