// server/utils/runtimeState.ts - 服务启动时间内存状态 + 问答记录 DB 读写 import { prisma } from "~~/server/utils/db"; import { serverEnv } from "~~/server/utils/env"; /** 进程启动时间,用于 `/api/stats` 返回 uptime */ const startTime = Date.now(); /** 对外展示的服务版本,和 README/API 文档保持一致 */ export const SERVICE_VERSION = "1.1.0"; /** 格式化成本地 `YYYY-MM-DD HH:mm:ss`,对齐旧 Python 服务记录格式 */ export const formatLocalDateTime = (date: Date) => { const pad = (value: number) => value.toString().padStart(2, "0"); return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad( date.getDate() )} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad( date.getSeconds() )}`; }; /** * 向数据库写入一条问答记录 */ export const addQaRecord = async (record: { userId: string; question: string; type: string; options: string; answer: string; hash: string; }) => { await prisma.qaRecord.create({ data: { userId: record.userId, question: record.question, type: record.type, options: record.options || null, answer: record.answer || null, hash: record.hash } }); }; /** * 按用户 + hash 查找 DB 缓存答案 * * 只返回 cacheClearedAt 之后写入的记录;未存入时间或 hash 为 null 的老记录不会命中 */ export const lookupCachedAnswer = async ( userId: string, hash: string, cacheClearedAt: Date | null ): Promise => { const record = await prisma.qaRecord.findFirst({ where: { userId, hash, ...(cacheClearedAt ? { createdAt: { gt: cacheClearedAt } } : {}) }, orderBy: { createdAt: "desc" }, select: { answer: true } }); return record?.answer ?? null; }; /** * 从数据库分页读取指定用户的问答记录,按创建时间倒序 */ export const getQaRecords = async ( userId: string, options: { page: number; size: number } ) => { const { page, size } = options; const skip = (page - 1) * size; const [total, rows] = await Promise.all([ prisma.qaRecord.count({ where: { userId } }), prisma.qaRecord.findMany({ where: { userId }, orderBy: { createdAt: "desc" }, skip, take: size, select: { question: true, type: true, options: true, answer: true, createdAt: true } }) ]); const records = rows.map((r) => ({ time: formatLocalDateTime(r.createdAt), timestamp: r.createdAt.toISOString(), question: r.question, type: r.type, options: r.options ?? "", answer: r.answer ?? "" })); return { records, total }; }; /** 生成 `/api/stats` 的基础运行时信息,不包含用户相关数据 */ export const getRuntimeStats = () => { return { version: SERVICE_VERSION, uptime: (Date.now() - startTime) / 1000, model: serverEnv.openAiModel }; };