New
This commit is contained in:
123
frontend/js/utils/utils.js
Normal file
123
frontend/js/utils/utils.js
Normal file
@@ -0,0 +1,123 @@
|
||||
/**
|
||||
* @file utils/utils.js
|
||||
* @description Provides a collection of common, reusable helper functions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A debounce utility to delay function execution, now with a cancel method.
|
||||
* @param {Function} func The function to debounce.
|
||||
* @param {number} wait The delay in milliseconds.
|
||||
* @returns {Function} The new debounced function with a `.cancel()` method attached.
|
||||
*/
|
||||
export function debounce(func, wait) {
|
||||
let timeout;
|
||||
|
||||
// create a named function expression here instead of returning an anonymous one directly.
|
||||
const debounced = function(...args) {
|
||||
// Store the context of 'this' in case it's needed inside the debounced function.
|
||||
const context = this;
|
||||
|
||||
// The core logic remains the same.
|
||||
const later = () => {
|
||||
clearTimeout(timeout);
|
||||
// Use .apply() to preserve the original 'this' context.
|
||||
func.apply(context, args);
|
||||
};
|
||||
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(later, wait);
|
||||
};
|
||||
|
||||
// Attach a 'cancel' method to the debounced function.
|
||||
// This allows us to abort a pending execution.
|
||||
debounced.cancel = () => {
|
||||
clearTimeout(timeout);
|
||||
};
|
||||
|
||||
return debounced;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Asynchronously copies a given string of text to the user's clipboard.
|
||||
* @param {string} text The text to be copied.
|
||||
* @returns {Promise<void>} A promise that resolves on success, rejects on failure.
|
||||
*/
|
||||
export function copyToClipboard(text) {
|
||||
// Use the modern Clipboard API if available
|
||||
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||||
return navigator.clipboard.writeText(text);
|
||||
}
|
||||
// Fallback for older browsers
|
||||
return new Promise((resolve, reject) => {
|
||||
const textArea = document.createElement("textarea");
|
||||
textArea.value = text;
|
||||
|
||||
// Make the textarea invisible and prevent scrolling
|
||||
textArea.style.position = "fixed";
|
||||
textArea.style.top = "-9999px";
|
||||
textArea.style.left = "-9999px";
|
||||
|
||||
document.body.appendChild(textArea);
|
||||
textArea.focus();
|
||||
textArea.select();
|
||||
|
||||
try {
|
||||
const successful = document.execCommand("copy");
|
||||
if (successful) {
|
||||
resolve();
|
||||
} else {
|
||||
reject(new Error("Fallback: Unable to copy text to clipboard."));
|
||||
}
|
||||
} catch (err) {
|
||||
reject(err);
|
||||
} finally {
|
||||
document.body.removeChild(textArea);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates a single API Key against a list of known formats.
|
||||
* @param {string} key - The API key string to validate.
|
||||
* @returns {boolean} - True if the key matches any of the known formats.
|
||||
*/
|
||||
export function isValidApiKeyFormat(key) {
|
||||
// [核心] 这是一个正则表达式列表。未来支持新的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,}$/
|
||||
];
|
||||
// 使用 .some() 方法,只要key匹配列表中的任意一个模式,就返回true。
|
||||
return patterns.some(pattern => pattern.test(key));
|
||||
}
|
||||
|
||||
/**
|
||||
* [NEW] A simple utility to escape HTML special characters from a string.
|
||||
* This is a critical security function to prevent XSS attacks when using .innerHTML.
|
||||
* @param {any} str The input string to escape. If not a string, it's returned as is.
|
||||
* @returns {string} The escaped, HTML-safe string.
|
||||
*/
|
||||
export function escapeHTML(str) {
|
||||
if (typeof str !== 'string') {
|
||||
return str;
|
||||
}
|
||||
return str.replace(/[&<>"']/g, function(match) {
|
||||
return {
|
||||
'&': '&',
|
||||
'<': '<',
|
||||
'>': '>',
|
||||
'"': '"',
|
||||
"'": '''
|
||||
}[match];
|
||||
});
|
||||
}
|
||||
// ... 其他未来可能添加的工具函数 ...
|
||||
Reference in New Issue
Block a user