Files
YGChatCS/utils/index.js
2025-08-10 12:07:58 +08:00

430 lines
11 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 工具函数集合
* 包含打字机效果、ID生成、回调安全调用等通用工具函数
*/
/**
* 打字机工具类
* 提供打字机效果相关的工具函数
*/
export class TypewriterUtils {
/**
* 计算动态打字速度
* @param {string} char - 当前字符
* @param {number} baseSpeed - 基础速度(ms)
* @returns {number} 动态调整后的速度
*/
static calculateDynamicSpeed(char, baseSpeed = 100) {
const punctuationMarks = [
"。",
"",
"",
".",
"!",
"?",
"",
",",
"",
";",
"",
":",
];
const isSpace = char === " ";
const hasPunctuation = punctuationMarks.includes(char);
if (hasPunctuation) {
// 标点符号后停顿更久,模拟思考时间
return baseSpeed * 2.5;
} else if (isSpace) {
// 空格稍快一些
return baseSpeed * 0.6;
} else {
// 普通字符添加一些随机性,模拟真实打字的不均匀性
const randomFactor = 0.7 + Math.random() * 0.6; // 0.7-1.3倍速度
return baseSpeed * randomFactor;
}
}
/**
* 检查字符是否为标点符号
* @param {string} char - 要检查的字符
* @returns {boolean} 是否为标点符号
*/
static isPunctuation(char) {
const punctuationMarks = [
"。",
"",
"",
".",
"!",
"?",
"",
",",
"",
";",
"",
":",
];
return punctuationMarks.includes(char);
}
/**
* 检查字符是否为空格
* @param {string} char - 要检查的字符
* @returns {boolean} 是否为空格
*/
static isSpace(char) {
return char === " ";
}
/**
* 生成加载动画文本
* @param {number} dotCount - 点的数量(1-3)
* @param {string} baseText - 基础文本
* @returns {string} 加载动画文本
*/
static generateLoadingText(dotCount = 1, baseText = "加载中") {
const normalizedDotCount = ((dotCount - 1) % 3) + 1;
return baseText + ".".repeat(normalizedDotCount);
}
/**
* 启动加载动画
*/
static startLoadingAnimation(
onProgress,
options = {},
onTimerCreated = null
) {
const { speed = 500, text = "加载中" } = options;
let dotCount = 1;
const timerId = setInterval(() => {
dotCount = (dotCount % 3) + 1;
const loadingText = text + ".".repeat(dotCount);
onProgress(loadingText);
}, speed);
if (onTimerCreated) {
onTimerCreated(timerId);
}
return timerId;
}
/**
* 启动打字机效果
* @param {string} text - 要显示的文本
* @param {Element} targetElement - 目标元素(可选)
* @param {Object} options - 配置选项
* @param {Function} onTimerCreated - 定时器创建回调(可选)
*/
static startTypewriter(
text,
targetElement = null,
options = {},
onTimerCreated = null
) {
const {
speed = 100,
onProgress = () => {},
onComplete = () => {},
} = options;
let index = 0;
const typeNextChar = () => {
if (index < text.length) {
const char = text[index];
const currentText = text.substring(0, index + 1);
// 调用进度回调
onProgress(currentText, index);
// 如果有目标元素,更新其内容
if (targetElement) {
targetElement.textContent = currentText;
}
index++;
// 计算下一个字符的延时
const delay = TypewriterUtils.calculateDynamicSpeed(
char,
speed
);
const timerId = setTimeout(typeNextChar, delay);
if (onTimerCreated && index === 1) {
onTimerCreated(timerId);
}
} else {
// 打字完成
onComplete(text);
}
};
// 开始打字
const initialTimerId = setTimeout(typeNextChar, 0);
if (onTimerCreated) {
onTimerCreated(initialTimerId);
}
return initialTimerId;
}
}
/**
* ID生成工具类
* 提供各种ID生成功能
*/
export class IdUtils {
/**
* 生成消息ID
* @returns {string} 消息ID
*/
static generateMessageId() {
return "mid" + new Date().getTime();
}
}
/**
* 回调函数安全调用工具类
* 提供安全的回调函数调用机制
*/
export class CallbackUtils {
/**
* 安全调用回调函数
* @param {Object} callbacks - 回调函数对象
* @param {string} callbackName - 回调函数名称
* @param {...any} args - 传递给回调函数的参数
*/
static safeCall(callbacks, callbackName, ...args) {
if (callbacks && typeof callbacks[callbackName] === "function") {
try {
callbacks[callbackName](...args);
} catch (error) {
console.error(`回调函数 ${callbackName} 执行出错:`, error);
}
} else {
console.warn(`回调函数 ${callbackName} 不可用`);
}
}
/**
* 批量安全调用回调函数
* @param {Object} callbacks - 回调函数对象
* @param {Array} callbackConfigs - 回调配置数组 [{name, args}, ...]
*/
static safeBatchCall(callbacks, callbackConfigs) {
callbackConfigs.forEach((config) => {
const { name, args = [] } = config;
this.safeCall(callbacks, name, ...args);
});
}
}
/**
* 消息处理工具类
* 提供消息相关的工具函数
*/
export class MessageUtils {
/**
* 验证消息格式
* @param {any} message - 消息对象
* @returns {boolean} 是否为有效消息格式
*/
static validateMessage(message) {
return message && typeof message === "object" && message.type;
}
/**
* 格式化消息
* @param {string} type - 消息类型
* @param {any} content - 消息内容
* @param {Object} options - 额外选项
* @returns {Object} 格式化后的消息对象
*/
static formatMessage(type, content, options = {}) {
return {
type,
content,
timestamp: Date.now(),
...options,
};
}
/**
* 检查是否为完整消息
* @param {any} message - 消息对象
* @returns {boolean} 是否为完整消息
*/
static isCompleteMessage(message) {
return message && message.isComplete === true;
}
/**
* 检查消息是否为心跳响应
* @param {any} messageData - 消息数据
* @returns {boolean} 是否为心跳响应
*/
static isPongMessage(messageData) {
if (typeof messageData === "string") {
return (
messageData === "pong" ||
messageData.toLowerCase().includes("pong")
);
}
if (typeof messageData === "object" && messageData !== null) {
return messageData.type === "pong";
}
return false;
}
/**
* 安全解析JSON消息
* @param {string} messageStr - 消息字符串
* @returns {Object|null} 解析后的对象或null
*/
static safeParseJSON(messageStr) {
try {
return JSON.parse(messageStr);
} catch (error) {
console.warn("JSON解析失败:", messageStr);
return null;
}
}
/**
* 创建打字机消息对象
* @param {string} content - 消息内容
* @param {boolean} isComplete - 是否完成
* @param {string} type - 消息类型
* @returns {Object} 消息对象
*/
static createTypewriterMessage(
content,
isComplete = false,
type = "typewriter"
) {
return {
type,
content,
isComplete,
timestamp: Date.now(),
};
}
/**
* 创建加载消息对象
* @param {string} content - 加载内容
* @returns {Object} 加载消息对象
*/
static createLoadingMessage(content = "加载中...") {
return {
type: "loading",
content,
timestamp: Date.now(),
};
}
/**
* 创建错误消息对象
* @param {string} error - 错误信息
* @returns {Object} 错误消息对象
*/
static createErrorMessage(error) {
return {
type: "error",
content: error.message || error || "未知错误",
timestamp: Date.now(),
};
}
}
/**
* 定时器管理工具类
* 提供定时器的统一管理
*/
export class TimerUtils {
/**
* 安全清除定时器
* @param {number|null} timerId - 定时器ID
* @param {string} type - 定时器类型 'timeout' | 'interval'
* @returns {null} 返回null便于重置变量
*/
static safeClear(timerId, type = "timeout") {
if (timerId) {
if (type === "interval") {
clearInterval(timerId);
} else {
clearTimeout(timerId);
}
}
return null;
}
/**
* 清除定时器(别名方法)
* @param {number|null} timerId - 定时器ID
* @param {string} type - 定时器类型 'timeout' | 'interval'
* @returns {null} 返回null便于重置变量
*/
static clearTimer(timerId, type = "timeout") {
return this.safeClear(timerId, type);
}
/**
* 创建可取消的延时执行
* @param {Function} callback - 回调函数
* @param {number} delay - 延时时间
* @returns {Object} 包含cancel方法的对象
*/
static createCancelableTimeout(callback, delay) {
let timerId = setTimeout(callback, delay);
return {
cancel() {
if (timerId) {
clearTimeout(timerId);
timerId = null;
}
},
isActive() {
return timerId !== null;
},
};
}
/**
* 创建可取消的定时执行
* @param {Function} callback - 回调函数
* @param {number} interval - 间隔时间
* @returns {Object} 包含cancel方法的对象
*/
static createCancelableInterval(callback, interval) {
let timerId = setInterval(callback, interval);
return {
cancel() {
if (timerId) {
clearInterval(timerId);
timerId = null;
}
},
isActive() {
return timerId !== null;
},
};
}
}
// 默认导出所有工具类
export default {
TypewriterUtils,
IdUtils,
CallbackUtils,
MessageUtils,
TimerUtils,
};