feat: 大量优化和bug修复

This commit is contained in:
2026-05-23 22:23:29 +08:00
parent 92b063c4c4
commit fc71e924e7
39 changed files with 1381 additions and 302 deletions
+70 -2
View File
@@ -1,6 +1,7 @@
// server/utils/sysConfig.ts - 从数据库读取系统配置,带 60 秒 TTL 内存缓存
// server/utils/sysConfig.ts - 从数据库读取系统配置,带 60 秒 TTL 内存缓存;支持按用户自定义配置覆盖
// 替代原 env.ts 中的 OpenAI 配置项,配置以 DB 为准,管理员可通过后台修改
import { prisma } from "~~/server/utils/db";
import { normalizeUserConfigValue } from "~~/server/utils/userConfig";
/** 系统配置字段,对应 system_config 表中的各 key */
export interface SysConfig {
@@ -32,7 +33,7 @@ const CONFIG_KEYS = {
const DEFAULTS: SysConfig = {
openAiApiKey: "",
openAiApiBase: "https://api.openai.com/v1",
openAiModel: "gpt-3.5-turbo",
openAiModel: "gpt-5.2",
maxTokens: 500,
temperature: 0.7,
maxSseLineBytes: 1_048_576
@@ -94,3 +95,70 @@ export const invalidateSysConfigCache = () => {
_cachedConfig = null;
_cacheExpiresAt = 0;
};
/**
* 获取当前用户生效的 API 配置
*
* 安全规则(保证系统 key 不流向用户控制的 endpoint):
* - useCustomConfig=true 且 customApiBase + customApiKey 都非空
* → base 和 key 用用户自定义值;model/max_tokens/temperature 有值则各自覆盖系统值
* - 上述条件任一不满足
* → base 和 key 完全使用系统配置(系统 key 不进用户 base)
* - useCustomConfig=false 或未设置
* → 完全使用系统配置,用户覆盖项全部忽略
*/
export const getUserEffectiveApiConfig = async (
userId: string
): Promise<SysConfig> => {
const sysCfg = await getSysConfig();
const row = await prisma.userConfig.findUnique({
where: { userId },
select: { value: true }
});
const userConfig = normalizeUserConfigValue(row?.value);
const useCustom = userConfig.useCustomConfig;
if (!useCustom) {
return sysCfg;
}
const customBase = userConfig.customApiBase ?? "";
const customKey = userConfig.customApiKey?.trim() ?? "";
// base 和 key 必须同时有值,才允许覆盖;否则继续使用系统的 base+key
// 这样可以保证系统 key 绝不发往用户控制的 endpoint
const useCustomEndpoint = customBase.length > 0 && customKey.length > 0;
const effectiveBase = useCustomEndpoint
? normalizeBaseUrl(customBase)
: sysCfg.openAiApiBase;
const effectiveKey = useCustomEndpoint ? customKey : sysCfg.openAiApiKey;
// model / max_tokens / temperature 在自定义配置开启时可以各自独立覆盖
const customModel = userConfig.customModel ?? "";
return {
openAiApiBase: effectiveBase,
openAiApiKey: effectiveKey,
openAiModel: customModel.length > 0 ? customModel : sysCfg.openAiModel,
maxTokens: userConfig.customMaxTokens ?? sysCfg.maxTokens,
temperature: userConfig.customTemperature ?? sysCfg.temperature,
maxSseLineBytes: sysCfg.maxSseLineBytes
};
};
/**
* 遮蔽 API Key,只留前 4 后 4 位,用于前端展示
*
* 长度 > 8 → 前4 + "..." + 后4(如 `sk-a...xxxx`
* 长度 1~8 → 全部替换为 `****`
* 空 → null
*/
export const maskApiKey = (key: string): string | null => {
if (!key) return null;
if (key.length > 8) {
return `${key.slice(0, 4)}...${key.slice(-4)}`;
}
return "****";
};