{"repo": "chengyatsung-art/trade-document-grading-system", "files": {"src/pages/Settings.tsx": {"52ddb8ccb6102b56c878a47285aeb5c059eb5c26": {"t": 1785747369.8127651, "n": 15734, "h": "d8731a0af6489171", "c": "import React, { useState, useEffect } from 'react';\nimport { Save, Key, Sliders, Database, Shield, Globe } from 'lucide-react';\n\nexport function Settings() {\n const [engineType, setEngineType] = useState<'builtin' | 'custom'>('builtin');\n const [builtinModel, setBuiltinModel] = useState('gemini-3.5-flash');\n const [customBaseUrl, setCustomBaseUrl] = useState('https://api.deepseek.com/v1');\n const [customApiKey, setCustomApiKey] = useState('');\n const [customModel, setCustomModel] = useState('deepseek-chat');\n const [customGeminiKey, setCustomGeminiKey] = useState('');\n const [customGeminiProxy, setCustomGeminiProxy] = useState('');\n const [coolingDelay, setCoolingDelay] = useState(5);\n const [saved, setSaved] = useState(false);\n\n useEffect(() => {\n const savedEngine = localStorage.getItem('ai_engine_type') as 'builtin' | 'custom';\n if (savedEngine) setEngineType(savedEngine);\n \n const savedBuiltinModel = localStorage.getItem('ai_builtin_model');\n if (savedBuiltinModel) setBuiltinModel(savedBuiltinModel);\n \n const savedBaseUrl = localStorage.getItem('ai_custom_base_url');\n if (savedBaseUrl) setCustomBaseUrl(savedBaseUrl);\n \n const savedApiKey = localStorage.getItem('ai_custom_api_key');\n if (savedApiKey) setCustomApiKey(savedApiKey);\n \n const savedModel = localStorage.getItem('ai_custom_model');\n if (savedModel) setCustomModel(savedModel);\n\n const savedGeminiKey = localStorage.getItem('ai_custom_gemini_key');\n if (savedGeminiKey) setCustomGeminiKey(savedGeminiKey);\n\n const savedGeminiProxy = localStorage.getItem('ai_custom_gemini_proxy');\n if (savedGeminiProxy) setCustomGeminiProxy(savedGeminiProxy);\n\n const savedDelay = localStorage.getItem('ai_cooling_delay');\n if (savedDelay) setCoolingDelay(parseInt(savedDelay, 10) || 5);\n }, []);\n\n const handleSave = () => {\n localStorage.setItem('ai_engine_type', engineType);\n localStorage.setItem('ai_builtin_model', builtinModel);\n localStorage.setItem('ai_custom_base_url', customBaseUrl);\n localStorage.setItem('ai_custom_api_key', customApiKey);\n localStorage.setItem('ai_custom_model', customModel);\n localStorage.setItem('ai_custom_gemini_key', customGeminiKey);\n localStorage.setItem('ai_custom_gemini_proxy', customGeminiProxy);\n localStorage.setItem('ai_cooling_delay', coolingDelay.toString());\n \n setSaved(true);\n setTimeout(() => setSaved(false), 2000);\n };\n\n return (\n
\n

系统设置

\n\n
\n {/* AI Engine Settings */}\n
\n
\n \n

AI 批改引擎配置

\n
\n
\n
\n \n
\n
setEngineType('builtin')}\n >\n
\n
\n

AI Studio 内置引擎

\n
\n

使用当前环境默认的 Gemini 大模型,无需配置 API Key。

\n
\n \n
setEngineType('custom')}\n >\n
\n
\n

自定义国内模型 (OpenAI 兼容)

\n
\n

支持 DeepSeek、智谱 GLM、通义千问等国内大模型接口。

\n
\n
\n
\n\n {engineType === 'builtin' && (\n
\n
\n \n \n

\n Flash 模型是 Google 最新的 3.5 系列大模型,批改速度极快且额度高(限制 15次/分钟);Lite 模型则是超轻量高速模型,适合大规模批改作业(限制 30次/分钟);Pro 模型推理能力极强但频控最严格(限制 2次/分钟)。\n

\n
\n\n
\n \n setCustomGeminiKey(e.target.value)}\n className=\"w-full border border-slate-300 rounded-lg px-4 py-2 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none\"\n placeholder=\"AIzaSy... (若留空,则默认使用系统的共享免费免费体验额度)\"\n />\n

\n 🌟 提示:如果连续批改多份大文件触发了系统的共享频次限制 (429) 或提示额度超限,强烈建议前往 \n \n Google AI Studio 官网\n \n 免费获取您个人的 API Key 并填入此处。配置后页面将直接通过您的独立账号发起安全连接,彻底告别公共额度排队和限流。\n

\n
\n\n
\n \n setCustomGeminiProxy(e.target.value)}\n className=\"w-full border border-slate-300 rounded-lg px-4 py-2 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none\"\n placeholder=\"例如:https://api.example.com/v1\"\n />\n

\n ⚙️ 若您所在的网络环境无法直接连接 Google 官方服务器,或者使用了第三方反向代理/转发接口,可在此处指定代理 Base URL。留空则直接连接 Google 官方接口。\n

\n
\n\n
\n 💡 常见问题与解答:\n

问:为什么首页的「今日 API 请求额度 (本地预估)」显示为 0 次,依然会报错“user has exceeded quota”?

\n

答:这是一个本地离线计数器,它仅通过您本地浏览器的历史批改记录来估算您发送的文档件数,它并不是去 Google 服务器查询 API 额度。如果其他的教师正在共用内置的系统额度,或者您虽然使用了个人免费 Key,但因为单次上传作业多、文件大而触发了以下限制,也会导致该报错。

\n

问:我已经配置了两个专属的免费 Gemini API Key,为什么还是会经常报 “exceeded quota / 429 频限” 错误?

\n

答:Google 提供的免费 API Key 有非常严格的限制。虽然它的总额度足够大,但在批量使用中:

\n
    \n
  • RPM(每分钟请求数) 限制为 15 次。
  • \n
  • TPM(每分钟 Token 数量限额) 被大文件瞬间充盈(批改作业时,尤其是图片和 PDF 格式大文件,会包含海量的字节并消耗巨量 Token),在一分钟内发送多份会导致 TPM 额度瞬间超支,立即被 Google 服务器暂停数分钟。
  • \n
\n

🚀 极速解决办法:

\n
    \n
  1. 在下方「常规设置」中,将「批量批改间隔冷却时间」从默认的 5 秒调大到 15 秒或 20 秒。这能有效拉开排队间隔,防止短时间内累计的 Token 超过每分钟限制。
  2. \n
  3. 如果您要追求极高的并发或者极速不间断地批改大批量文件,推荐切换至上方的「自定义国内模型」,选用如 DeepSeek、智谱、Kimi 等服务,其每百万 Token 的单价极其低廉且完全不设低规格速率限制!
  4. \n
\n
\n
\n )}\n\n {engineType === 'custom' && (\n
\n
\n \n setCustomBaseUrl(e.target.value)}\n className=\"w-full border border-slate-300 rounded-lg px-4 py-2 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none\"\n placeholder=\"例如:https://api.deepseek.com/v1\"\n />\n

\n 常用地址:DeepSeek (https://api.deepseek.com/v1) | 智谱 (https://open.bigmodel.cn/api/paas/v4)\n

\n
\n\n
\n \n setCustomApiKey(e.target.value)}\n className=\"w-full border border-slate-300 rounded-lg px-4 py-2 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none\"\n placeholder=\"sk-...\"\n />\n
\n\n
\n \n setCustomModel(e.target.value)}\n className=\"w-full border border-slate-300 rounded-lg px-4 py-2 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none\"\n placeholder=\"例如:deepseek-chat\"\n />\n

\n 常用模型:deepseek-chat, glm-4-flash, qwen-plus\n

\n
\n
\n )}\n\n {/* Shared Frequency/Throttle Settings */}\n
\n \n
\n setCoolingDelay(Math.max(0, parseInt(e.target.value, 10) || 0))}\n className=\"w-32 border border-slate-300 rounded-lg px-4 py-2 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none\"\n />\n 秒\n
\n

\n * 默认值为 5 秒。如果在连续批改多份作业时遭遇 429 报错,建议调大该值(如 10 秒或 15 秒)以降低请求频率。\n

\n
\n
\n
\n\n {/* Local Storage Settings */}\n
\n
\n \n

本地数据与隐私

\n
\n
\n
\n
\n \n
\n

纯前端模式 (Serverless)

\n

\n 当前系统运行在纯前端模式,所有学生文件均在本地浏览器解析,不会上传到任何第三方服务器(除了将文本发送给 Google Gemini API 进行批改)。\n

\n
\n
\n
\n\n
\n
\n

保留历史记录

\n

在浏览器本地存储 (LocalStorage) 中保留最近的批改任务记录

\n
\n \n
\n
\n
\n\n
\n \n
\n
\n
\n );\n}\n"}, "3166386d2ba3e674950c50758658818eee773134": {"t": 1785772863.552391, "n": 15734, "h": "d8731a0af6489171", "c": "import React, { useState, useEffect } from 'react';\nimport { Save, Key, Sliders, Database, Shield, Globe } from 'lucide-react';\n\nexport function Settings() {\n const [engineType, setEngineType] = useState<'builtin' | 'custom'>('builtin');\n const [builtinModel, setBuiltinModel] = useState('gemini-3.5-flash');\n const [customBaseUrl, setCustomBaseUrl] = useState('https://api.deepseek.com/v1');\n const [customApiKey, setCustomApiKey] = useState('');\n const [customModel, setCustomModel] = useState('deepseek-chat');\n const [customGeminiKey, setCustomGeminiKey] = useState('');\n const [customGeminiProxy, setCustomGeminiProxy] = useState('');\n const [coolingDelay, setCoolingDelay] = useState(5);\n const [saved, setSaved] = useState(false);\n\n useEffect(() => {\n const savedEngine = localStorage.getItem('ai_engine_type') as 'builtin' | 'custom';\n if (savedEngine) setEngineType(savedEngine);\n \n const savedBuiltinModel = localStorage.getItem('ai_builtin_model');\n if (savedBuiltinModel) setBuiltinModel(savedBuiltinModel);\n \n const savedBaseUrl = localStorage.getItem('ai_custom_base_url');\n if (savedBaseUrl) setCustomBaseUrl(savedBaseUrl);\n \n const savedApiKey = localStorage.getItem('ai_custom_api_key');\n if (savedApiKey) setCustomApiKey(savedApiKey);\n \n const savedModel = localStorage.getItem('ai_custom_model');\n if (savedModel) setCustomModel(savedModel);\n\n const savedGeminiKey = localStorage.getItem('ai_custom_gemini_key');\n if (savedGeminiKey) setCustomGeminiKey(savedGeminiKey);\n\n const savedGeminiProxy = localStorage.getItem('ai_custom_gemini_proxy');\n if (savedGeminiProxy) setCustomGeminiProxy(savedGeminiProxy);\n\n const savedDelay = localStorage.getItem('ai_cooling_delay');\n if (savedDelay) setCoolingDelay(parseInt(savedDelay, 10) || 5);\n }, []);\n\n const handleSave = () => {\n localStorage.setItem('ai_engine_type', engineType);\n localStorage.setItem('ai_builtin_model', builtinModel);\n localStorage.setItem('ai_custom_base_url', customBaseUrl);\n localStorage.setItem('ai_custom_api_key', customApiKey);\n localStorage.setItem('ai_custom_model', customModel);\n localStorage.setItem('ai_custom_gemini_key', customGeminiKey);\n localStorage.setItem('ai_custom_gemini_proxy', customGeminiProxy);\n localStorage.setItem('ai_cooling_delay', coolingDelay.toString());\n \n setSaved(true);\n setTimeout(() => setSaved(false), 2000);\n };\n\n return (\n
\n

系统设置

\n\n
\n {/* AI Engine Settings */}\n
\n
\n \n

AI 批改引擎配置

\n
\n
\n
\n \n
\n
setEngineType('builtin')}\n >\n
\n
\n

AI Studio 内置引擎

\n
\n

使用当前环境默认的 Gemini 大模型,无需配置 API Key。

\n
\n \n
setEngineType('custom')}\n >\n
\n
\n

自定义国内模型 (OpenAI 兼容)

\n
\n

支持 DeepSeek、智谱 GLM、通义千问等国内大模型接口。

\n
\n
\n
\n\n {engineType === 'builtin' && (\n
\n
\n \n \n

\n Flash 模型是 Google 最新的 3.5 系列大模型,批改速度极快且额度高(限制 15次/分钟);Lite 模型则是超轻量高速模型,适合大规模批改作业(限制 30次/分钟);Pro 模型推理能力极强但频控最严格(限制 2次/分钟)。\n

\n
\n\n
\n \n setCustomGeminiKey(e.target.value)}\n className=\"w-full border border-slate-300 rounded-lg px-4 py-2 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none\"\n placeholder=\"AIzaSy... (若留空,则默认使用系统的共享免费免费体验额度)\"\n />\n

\n 🌟 提示:如果连续批改多份大文件触发了系统的共享频次限制 (429) 或提示额度超限,强烈建议前往 \n \n Google AI Studio 官网\n \n 免费获取您个人的 API Key 并填入此处。配置后页面将直接通过您的独立账号发起安全连接,彻底告别公共额度排队和限流。\n

\n
\n\n
\n \n setCustomGeminiProxy(e.target.value)}\n className=\"w-full border border-slate-300 rounded-lg px-4 py-2 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none\"\n placeholder=\"例如:https://api.example.com/v1\"\n />\n

\n ⚙️ 若您所在的网络环境无法直接连接 Google 官方服务器,或者使用了第三方反向代理/转发接口,可在此处指定代理 Base URL。留空则直接连接 Google 官方接口。\n

\n
\n\n
\n 💡 常见问题与解答:\n

问:为什么首页的「今日 API 请求额度 (本地预估)」显示为 0 次,依然会报错“user has exceeded quota”?

\n

答:这是一个本地离线计数器,它仅通过您本地浏览器的历史批改记录来估算您发送的文档件数,它并不是去 Google 服务器查询 API 额度。如果其他的教师正在共用内置的系统额度,或者您虽然使用了个人免费 Key,但因为单次上传作业多、文件大而触发了以下限制,也会导致该报错。

\n

问:我已经配置了两个专属的免费 Gemini API Key,为什么还是会经常报 “exceeded quota / 429 频限” 错误?

\n

答:Google 提供的免费 API Key 有非常严格的限制。虽然它的总额度足够大,但在批量使用中:

\n
    \n
  • RPM(每分钟请求数) 限制为 15 次。
  • \n
  • TPM(每分钟 Token 数量限额) 被大文件瞬间充盈(批改作业时,尤其是图片和 PDF 格式大文件,会包含海量的字节并消耗巨量 Token),在一分钟内发送多份会导致 TPM 额度瞬间超支,立即被 Google 服务器暂停数分钟。
  • \n
\n

🚀 极速解决办法:

\n
    \n
  1. 在下方「常规设置」中,将「批量批改间隔冷却时间」从默认的 5 秒调大到 15 秒或 20 秒。这能有效拉开排队间隔,防止短时间内累计的 Token 超过每分钟限制。
  2. \n
  3. 如果您要追求极高的并发或者极速不间断地批改大批量文件,推荐切换至上方的「自定义国内模型」,选用如 DeepSeek、智谱、Kimi 等服务,其每百万 Token 的单价极其低廉且完全不设低规格速率限制!
  4. \n
\n
\n
\n )}\n\n {engineType === 'custom' && (\n
\n
\n \n setCustomBaseUrl(e.target.value)}\n className=\"w-full border border-slate-300 rounded-lg px-4 py-2 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none\"\n placeholder=\"例如:https://api.deepseek.com/v1\"\n />\n

\n 常用地址:DeepSeek (https://api.deepseek.com/v1) | 智谱 (https://open.bigmodel.cn/api/paas/v4)\n

\n
\n\n
\n \n setCustomApiKey(e.target.value)}\n className=\"w-full border border-slate-300 rounded-lg px-4 py-2 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none\"\n placeholder=\"sk-...\"\n />\n
\n\n
\n \n setCustomModel(e.target.value)}\n className=\"w-full border border-slate-300 rounded-lg px-4 py-2 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none\"\n placeholder=\"例如:deepseek-chat\"\n />\n

\n 常用模型:deepseek-chat, glm-4-flash, qwen-plus\n

\n
\n
\n )}\n\n {/* Shared Frequency/Throttle Settings */}\n
\n \n
\n setCoolingDelay(Math.max(0, parseInt(e.target.value, 10) || 0))}\n className=\"w-32 border border-slate-300 rounded-lg px-4 py-2 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none\"\n />\n 秒\n
\n

\n * 默认值为 5 秒。如果在连续批改多份作业时遭遇 429 报错,建议调大该值(如 10 秒或 15 秒)以降低请求频率。\n

\n
\n
\n
\n\n {/* Local Storage Settings */}\n
\n
\n \n

本地数据与隐私

\n
\n
\n
\n
\n \n
\n

纯前端模式 (Serverless)

\n

\n 当前系统运行在纯前端模式,所有学生文件均在本地浏览器解析,不会上传到任何第三方服务器(除了将文本发送给 Google Gemini API 进行批改)。\n

\n
\n
\n
\n\n
\n
\n

保留历史记录

\n

在浏览器本地存储 (LocalStorage) 中保留最近的批改任务记录

\n
\n \n
\n
\n
\n\n
\n \n
\n
\n
\n );\n}\n"}, "2fccec9f54bffe41452e4c7804cdcd4128f77426": {"t": 1785772869.0975354, "n": 15586, "h": "459c321f97d942da", "c": "import React, { useState, useEffect } from 'react';\nimport { Save, Key, Sliders, Database, Shield, Globe } from 'lucide-react';\n\nexport function Settings() {\n const [engineType, setEngineType] = useState<'builtin' | 'custom'>('builtin');\n const [builtinModel, setBuiltinModel] = useState('gemini-3.5-flash');\n const [customBaseUrl, setCustomBaseUrl] = useState('https://api.deepseek.com/v1');\n const [customApiKey, setCustomApiKey] = useState('');\n const [customModel, setCustomModel] = useState('deepseek-chat');\n const [customGeminiKey, setCustomGeminiKey] = useState('');\n const [customGeminiProxy, setCustomGeminiProxy] = useState('');\n const [coolingDelay, setCoolingDelay] = useState(5);\n const [saved, setSaved] = useState(false);\n\n useEffect(() => {\n const savedEngine = localStorage.getItem('ai_engine_type') as 'builtin' | 'custom';\n if (savedEngine) setEngineType(savedEngine);\n \n const savedBuiltinModel = localStorage.getItem('ai_builtin_model');\n if (savedBuiltinModel) setBuiltinModel(savedBuiltinModel);\n \n const savedBaseUrl = localStorage.getItem('ai_custom_base_url');\n if (savedBaseUrl) setCustomBaseUrl(savedBaseUrl);\n \n const savedApiKey = localStorage.getItem('ai_custom_api_key');\n if (savedApiKey) setCustomApiKey(savedApiKey);\n \n const savedModel = localStorage.getItem('ai_custom_model');\n if (savedModel) setCustomModel(savedModel);\n\n const savedGeminiKey = localStorage.getItem('ai_custom_gemini_key');\n if (savedGeminiKey) setCustomGeminiKey(savedGeminiKey);\n\n const savedGeminiProxy = localStorage.getItem('ai_custom_gemini_proxy');\n if (savedGeminiProxy) setCustomGeminiProxy(savedGeminiProxy);\n\n const savedDelay = localStorage.getItem('ai_cooling_delay');\n if (savedDelay) setCoolingDelay(parseInt(savedDelay, 10) || 5);\n }, []);\n\n const handleSave = () => {\n localStorage.setItem('ai_engine_type', engineType);\n localStorage.setItem('ai_builtin_model', builtinModel);\n localStorage.setItem('ai_custom_base_url', customBaseUrl);\n localStorage.setItem('ai_custom_api_key', customApiKey);\n localStorage.setItem('ai_custom_model', customModel);\n localStorage.setItem('ai_custom_gemini_key', customGeminiKey);\n localStorage.setItem('ai_custom_gemini_proxy', customGeminiProxy);\n localStorage.setItem('ai_cooling_delay', coolingDelay.toString());\n \n setSaved(true);\n setTimeout(() => setSaved(false), 2000);\n };\n\n return (\n
\n

系统设置

\n\n
\n {/* AI Engine Settings */}\n
\n
\n \n

AI 批改引擎配置

\n
\n
\n
\n \n
\n
setEngineType('builtin')}\n >\n
\n
\n

AI Studio 内置引擎

\n
\n

使用当前环境默认的 Gemini 大模型,无需配置 API Key。

\n
\n \n
setEngineType('custom')}\n >\n
\n
\n

自定义国内模型 (OpenAI 兼容)

\n
\n

支持 DeepSeek、智谱 GLM、通义千问等国内大模型接口。

\n
\n
\n
\n\n {engineType === 'builtin' && (\n
\n
\n \n \n

\n Flash 模型是 Google 最新的 3.5 系列轻量化大模型,批改速度极快且额度高(限制 15次/分钟),Pro 模型推理能力极强但限制较严格(限制 2次/分钟)。\n

\n
\n\n
\n \n setCustomGeminiKey(e.target.value)}\n className=\"w-full border border-slate-300 rounded-lg px-4 py-2 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none\"\n placeholder=\"AIzaSy... (若留空,则默认使用系统的共享免费免费体验额度)\"\n />\n

\n 🌟 提示:如果连续批改多份大文件触发了系统的共享频次限制 (429) 或提示额度超限,强烈建议前往 \n \n Google AI Studio 官网\n \n 免费获取您个人的 API Key 并填入此处。配置后页面将直接通过您的独立账号发起安全连接,彻底告别公共额度排队和限流。\n

\n
\n\n
\n \n setCustomGeminiProxy(e.target.value)}\n className=\"w-full border border-slate-300 rounded-lg px-4 py-2 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none\"\n placeholder=\"例如:https://api.example.com/v1\"\n />\n

\n ⚙️ 若您所在的网络环境无法直接连接 Google 官方服务器,或者使用了第三方反向代理/转发接口,可在此处指定代理 Base URL。留空则直接连接 Google 官方接口。\n

\n
\n\n
\n 💡 常见问题与解答:\n

问:为什么首页的「今日 API 请求额度 (本地预估)」显示为 0 次,依然会报错“user has exceeded quota”?

\n

答:这是一个本地离线计数器,它仅通过您本地浏览器的历史批改记录来估算您发送的文档件数,它并不是去 Google 服务器查询 API 额度。如果其他的教师正在共用内置的系统额度,或者您虽然使用了个人免费 Key,但因为单次上传作业多、文件大而触发了以下限制,也会导致该报错。

\n

问:我已经配置了两个专属的免费 Gemini API Key,为什么还是会经常报 “exceeded quota / 429 频限” 错误?

\n

答:Google 提供的免费 API Key 有非常严格的限制。虽然它的总额度足够大,但在批量使用中:

\n
    \n
  • RPM(每分钟请求数) 限制为 15 次。
  • \n
  • TPM(每分钟 Token 数量限额) 被大文件瞬间充盈(批改作业时,尤其是图片和 PDF 格式大文件,会包含海量的字节并消耗巨量 Token),在一分钟内发送多份会导致 TPM 额度瞬间超支,立即被 Google 服务器暂停数分钟。
  • \n
\n

🚀 极速解决办法:

\n
    \n
  1. 在下方「常规设置」中,将「批量批改间隔冷却时间」从默认的 5 秒调大到 15 秒或 20 秒。这能有效拉开排队间隔,防止短时间内累计的 Token 超过每分钟限制。
  2. \n
  3. 如果您要追求极高的并发或者极速不间断地批改大批量文件,推荐切换至上方的「自定义国内模型」,选用如 DeepSeek、智谱、Kimi 等服务,其每百万 Token 的单价极其低廉且完全不设低规格速率限制!
  4. \n
\n
\n
\n )}\n\n {engineType === 'custom' && (\n
\n
\n \n setCustomBaseUrl(e.target.value)}\n className=\"w-full border border-slate-300 rounded-lg px-4 py-2 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none\"\n placeholder=\"例如:https://api.deepseek.com/v1\"\n />\n

\n 常用地址:DeepSeek (https://api.deepseek.com/v1) | 智谱 (https://open.bigmodel.cn/api/paas/v4)\n

\n
\n\n
\n \n setCustomApiKey(e.target.value)}\n className=\"w-full border border-slate-300 rounded-lg px-4 py-2 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none\"\n placeholder=\"sk-...\"\n />\n
\n\n
\n \n setCustomModel(e.target.value)}\n className=\"w-full border border-slate-300 rounded-lg px-4 py-2 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none\"\n placeholder=\"例如:deepseek-chat\"\n />\n

\n 常用模型:deepseek-chat, glm-4-flash, qwen-plus\n

\n
\n
\n )}\n\n {/* Shared Frequency/Throttle Settings */}\n
\n \n
\n setCoolingDelay(Math.max(0, parseInt(e.target.value, 10) || 0))}\n className=\"w-32 border border-slate-300 rounded-lg px-4 py-2 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none\"\n />\n 秒\n
\n

\n * 默认值为 5 秒。如果在连续批改多份作业时遭遇 429 报错,建议调大该值(如 10 秒或 15 秒)以降低请求频率。\n

\n
\n
\n
\n\n {/* Local Storage Settings */}\n
\n
\n \n

本地数据与隐私

\n
\n
\n
\n
\n \n
\n

纯前端模式 (Serverless)

\n

\n 当前系统运行在纯前端模式,所有学生文件均在本地浏览器解析,不会上传到任何第三方服务器(除了将文本发送给 Google Gemini API 进行批改)。\n

\n
\n
\n
\n\n
\n
\n

保留历史记录

\n

在浏览器本地存储 (LocalStorage) 中保留最近的批改任务记录

\n
\n \n
\n
\n
\n\n
\n \n
\n
\n
\n );\n}\n"}, "95a38db93dbad7fdb3003c78c429fde809dc9d93": {"t": 1785772870.408774, "n": 8485, "h": "ba3bff5c4a50cd1e", "c": "import React, { useState, useEffect } from 'react';\nimport { Save, Key, Sliders, Database, Shield, Globe } from 'lucide-react';\n\nexport function Settings() {\n const [engineType, setEngineType] = useState<'builtin' | 'custom'>('builtin');\n const [customBaseUrl, setCustomBaseUrl] = useState('https://api.deepseek.com/v1');\n const [customApiKey, setCustomApiKey] = useState('');\n const [customModel, setCustomModel] = useState('deepseek-chat');\n const [saved, setSaved] = useState(false);\n\n useEffect(() => {\n const savedEngine = localStorage.getItem('ai_engine_type') as 'builtin' | 'custom';\n if (savedEngine) setEngineType(savedEngine);\n \n const savedBaseUrl = localStorage.getItem('ai_custom_base_url');\n if (savedBaseUrl) setCustomBaseUrl(savedBaseUrl);\n \n const savedApiKey = localStorage.getItem('ai_custom_api_key');\n if (savedApiKey) setCustomApiKey(savedApiKey);\n \n const savedModel = localStorage.getItem('ai_custom_model');\n if (savedModel) setCustomModel(savedModel);\n }, []);\n\n const handleSave = () => {\n localStorage.setItem('ai_engine_type', engineType);\n localStorage.setItem('ai_custom_base_url', customBaseUrl);\n localStorage.setItem('ai_custom_api_key', customApiKey);\n localStorage.setItem('ai_custom_model', customModel);\n \n setSaved(true);\n setTimeout(() => setSaved(false), 2000);\n };\n\n return (\n
\n

系统设置

\n\n
\n {/* AI Engine Settings */}\n
\n
\n \n

AI 批改引擎配置

\n
\n
\n
\n \n
\n
setEngineType('builtin')}\n >\n
\n
\n

AI Studio 内置引擎

\n
\n

使用当前环境默认的 Gemini 大模型,无需配置 API Key。

\n
\n \n
setEngineType('custom')}\n >\n
\n
\n

自定义国内模型 (OpenAI 兼容)

\n
\n

支持 DeepSeek、智谱 GLM、通义千问等国内大模型接口。

\n
\n
\n
\n\n {engineType === 'custom' && (\n
\n
\n \n setCustomBaseUrl(e.target.value)}\n className=\"w-full border border-slate-300 rounded-lg px-4 py-2 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none\"\n placeholder=\"例如:https://api.deepseek.com/v1\"\n />\n

\n 常用地址:DeepSeek (https://api.deepseek.com/v1) | 智谱 (https://open.bigmodel.cn/api/paas/v4)\n

\n
\n\n
\n \n setCustomApiKey(e.target.value)}\n className=\"w-full border border-slate-300 rounded-lg px-4 py-2 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none\"\n placeholder=\"sk-...\"\n />\n
\n\n
\n \n setCustomModel(e.target.value)}\n className=\"w-full border border-slate-300 rounded-lg px-4 py-2 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none\"\n placeholder=\"例如:deepseek-chat\"\n />\n

\n 常用模型:deepseek-chat, glm-4-flash, qwen-plus\n

\n
\n
\n )}\n
\n
\n\n {/* Local Storage Settings */}\n
\n
\n \n

本地数据与隐私

\n
\n
\n
\n
\n \n
\n

纯前端模式 (Serverless)

\n

\n 当前系统运行在纯前端模式,所有学生文件均在本地浏览器解析,不会上传到任何第三方服务器(除了将文本发送给 Google Gemini API 进行批改)。\n

\n
\n
\n
\n\n
\n
\n

保留历史记录

\n

在浏览器本地存储 (LocalStorage) 中保留最近的批改任务记录

\n
\n \n
\n
\n
\n\n
\n \n
\n
\n
\n );\n}\n"}}}}