lovart3/lib/utils.ts
Your Name 60082aca6f 修复时间显示和图像拓展功能
- 添加formatBeijingTime函数,将所有时间显示转换为北京时间(UTC+8)
- 更新相册、管理后台、精选页面的时间显示
- 图像拓展功能改为直接发送图片URL而不是base64
- 优化API性能,减少数据传输量
2025-12-30 20:16:47 +08:00

154 lines
4.1 KiB
TypeScript
Raw Permalink 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.

import type {
CoreAssistantMessage,
CoreToolMessage,
UIMessage,
UIMessagePart,
} from 'ai';
import { type ClassValue, clsx } from 'clsx';
import { formatISO } from 'date-fns';
import { twMerge } from 'tailwind-merge';
import type { DBMessage, Document } from '@/lib/db/schema';
import { ChatSDKError, type ErrorCode } from './errors';
import type { ChatMessage, ChatTools, CustomUIDataTypes } from './types';
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
export const fetcher = async (url: string) => {
const response = await fetch(url);
if (!response.ok) {
const { code, cause } = await response.json();
throw new ChatSDKError(code as ErrorCode, cause);
}
return response.json();
};
export async function fetchWithErrorHandlers(
input: RequestInfo | URL,
init?: RequestInit,
) {
try {
const response = await fetch(input, init);
if (!response.ok) {
const { code, cause } = await response.json();
throw new ChatSDKError(code as ErrorCode, cause);
}
return response;
} catch (error: unknown) {
if (typeof navigator !== 'undefined' && !navigator.onLine) {
throw new ChatSDKError('offline:chat');
}
throw error;
}
}
export function getLocalStorage(key: string) {
if (typeof window !== 'undefined') {
return JSON.parse(localStorage.getItem(key) || '[]');
}
return [];
}
export function generateUUID(): string {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
const r = (Math.random() * 16) | 0;
const v = c === 'x' ? r : (r & 0x3) | 0x8;
return v.toString(16);
});
}
type ResponseMessageWithoutId = CoreToolMessage | CoreAssistantMessage;
type ResponseMessage = ResponseMessageWithoutId & { id: string };
export function getMostRecentUserMessage(messages: UIMessage[]) {
const userMessages = messages.filter((message) => message.role === 'user');
return userMessages.at(-1);
}
export function getDocumentTimestampByIndex(
documents: Document[],
index: number,
) {
if (!documents) { return new Date(); }
if (index > documents.length) { return new Date(); }
return documents[index].createdAt;
}
export function getTrailingMessageId({
messages,
}: {
messages: ResponseMessage[];
}): string | null {
const trailingMessage = messages.at(-1);
if (!trailingMessage) { return null; }
return trailingMessage.id;
}
export function sanitizeText(text: string) {
return text.replace('<has_function_call>', '');
}
export function convertToUIMessages(messages: DBMessage[]): ChatMessage[] {
return messages.map((message) => ({
id: message.id,
role: message.role as 'user' | 'assistant' | 'system',
parts: message.parts as UIMessagePart<CustomUIDataTypes, ChatTools>[],
metadata: {
createdAt: formatISO(message.createdAt),
},
}));
}
export function getTextFromMessage(message: ChatMessage | UIMessage): string {
return message.parts
.filter((part) => part.type === 'text')
.map((part) => (part as { type: 'text'; text: string}).text)
.join('');
}
/**
* 将UTC时间转换为北京时间(UTC+8)
* @param date - Date对象或时间字符串
* @returns 北京时间对应的Date对象
*/
export function toBeijingTime(date: Date | string): Date {
const d = typeof date === "string" ? new Date(date) : date;
// 获取UTC时间戳
const utcTime = d.getTime() + (d.getTimezoneOffset() * 60 * 1000);
// 转换为北京时间(UTC+8)
const beijingTime = new Date(utcTime + (8 * 60 * 60 * 1000));
return beijingTime;
}
/**
* 格式化时间为北京时间字符串
* @param date - Date对象或时间字符串
* @param options - Intl.DateTimeFormatOptions 格式化选项
* @returns 格式化后的北京时间字符串
*/
export function formatBeijingTime(
date: Date | string,
options?: Intl.DateTimeFormatOptions
): string {
const beijingTime = toBeijingTime(date);
const defaultOptions: Intl.DateTimeFormatOptions = {
year: "numeric",
month: "numeric",
day: "numeric",
hour: "2-digit",
minute: "2-digit",
timeZone: "Asia/Shanghai",
...options,
};
return beijingTime.toLocaleString("zh-CN", defaultOptions);
}