feat(dashboard): 在数据看板中的模型消耗分布添加显示Token 功能并支持切换 - #2739
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughAdds a display-mode feature to the Data Dashboard: a QUOTA/TOKENS toggle (UI, settings, i18n), persistence to localStorage and new option key, and mode-aware chart aggregation/tooltip logic including token usage tracking. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant UI as ChartsPanel
participant Parent as Dashboard (state)
participant Storage as localStorage
participant Hooks as useDashboardCharts
participant Charts as Chart
User->>UI: click display-mode toggle
UI->>Parent: onDisplayModeChange(newMode)
Parent->>Parent: setDisplayMode(newMode)
Parent->>Storage: save data_export_default_display_mode
Parent->>Hooks: pass displayMode
Hooks->>Hooks: createTooltipConfig(displayMode)
Hooks->>Hooks: aggregate data (rawTokenUsed/rawQuota, tokenUsed)
Hooks->>Charts: updateChartData(spec, tooltipConfig)
Charts->>UI: render updated charts
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
📝 Coding Plan
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
web/src/pages/Setting/Dashboard/SettingsDataDashboard.jsx (1)
98-105: Bug: localStorage is written with stale state values.The
useEffectwrites to localStorage usinginputs.DataExportDefaultTimeandinputs.DataExportDefaultDisplayMode, but at this pointinputsstill holds the previous state values. The new values fromprops.optionsare set viasetInputs(currentInputs)but React state updates are asynchronous, so the subsequent localStorage writes use stale data.🐛 Proposed fix
useEffect(() => { const currentInputs = {}; for (let key in props.options) { if (Object.keys(inputs).includes(key)) { currentInputs[key] = props.options[key]; } } setInputs(currentInputs); setInputsRow(structuredClone(currentInputs)); refForm.current.setValues(currentInputs); localStorage.setItem( 'data_export_default_time', - String(inputs.DataExportDefaultTime), + String(currentInputs.DataExportDefaultTime || 'hour'), ); localStorage.setItem( 'data_export_default_display_mode', - String(inputs.DataExportDefaultDisplayMode || 'QUOTA'), + String(currentInputs.DataExportDefaultDisplayMode || 'QUOTA'), ); }, [props.options]);
🧹 Nitpick comments (5)
web/src/components/dashboard/ChartsPanel.jsx (1)
50-63: Consider adding accessibility attributes to the toggle.The display mode toggle has a
titlefor hover tooltip but lacks anaria-labelfor screen reader users. Addingrole="button"andaria-labelwould improve accessibility.♿ Suggested improvement
<div className='flex items-center gap-1 bg-[var(--semi-color-fill-0)] rounded px-1.5 py-1 cursor-pointer hover:bg-[var(--semi-color-fill-1)] transition-colors' onClick={() => onDisplayModeChange(displayMode === 'QUOTA' ? 'TOKENS' : 'QUOTA')} title={displayMode === 'QUOTA' ? t('切换为 Token') : t('切换为金额')} + role='button' + aria-label={displayMode === 'QUOTA' ? t('切换为 Token') : t('切换为金额')} + tabIndex={0} + onKeyDown={(e) => { + if (e.key === 'Enter' || e.key === ' ') { + e.preventDefault(); + onDisplayModeChange(displayMode === 'QUOTA' ? 'TOKENS' : 'QUOTA'); + } + }} >web/src/hooks/dashboard/useDashboardCharts.jsx (4)
301-302: Questionable data field assignments for rawQuota and rawTokenUsed.When
displayMode === 'TOKENS', bothrawQuotaandrawTokenUsedare set toaggregated?.tokenUsed || 0. This meansrawQuotaloses the actual quota value, andrawTokenUsedis0when in QUOTA mode. This could cause issues if the display mode is toggled without refetching data, as the underlying raw values would be mode-dependent rather than preserving both values.Consider always storing both raw values:
♻️ Suggested fix
return { Time: time, Model: model, - rawQuota: displayMode === 'TOKENS' ? (aggregated?.tokenUsed || 0) : (aggregated?.quota || 0), - rawTokenUsed: displayMode === 'TOKENS' ? (aggregated?.tokenUsed || 0) : 0, + rawQuota: aggregated?.quota || 0, + rawTokenUsed: aggregated?.tokenUsed || 0, Usage: displayValue, };
307-321: DuplicatevalueFielddeclaration.
valueFieldis declared identically at lines 307 and 321. While valid due to block scoping, this duplicates the mode-switching logic. Consider extracting it to a single declaration at the beginning of the data processing block.♻️ Suggested refactor
+ const valueField = displayMode === 'TOKENS' ? 'rawTokenUsed' : 'rawQuota'; + const renderValue = displayMode === 'TOKENS' ? renderNumber : (v) => renderQuota(v, 4); + chartTimePoints.forEach((time) => { // ... existing code ... }); - const valueField = displayMode === 'TOKENS' ? 'rawTokenUsed' : 'rawQuota'; const timeSum = timeData.reduce((sum, item) => sum + item[valueField], 0); // ... const totalValue = displayMode === 'TOKENS' ? totalTokens : totalQuota; const totalDisplay = displayMode === 'TOKENS' ? renderNumber(totalValue) : renderQuota(totalValue, 2); - // 生成 tooltip 配置 - const renderValue = displayMode === 'TOKENS' ? renderNumber : (v) => renderQuota(v, 4); - const valueField = displayMode === 'TOKENS' ? 'rawTokenUsed' : 'rawQuota'; + // 生成 tooltip 配置 (uses valueField and renderValue from above)
448-500: Duplicated tooltip configuration logic.The tooltip configuration at lines 454-493 is nearly identical to lines 322-361 within
updateChartData. This duplication increases maintenance burden and risk of divergence.Consider extracting the tooltip generation into a shared helper function:
♻️ Suggested refactor
// Extract as a helper function within the hook or in helpers/dashboard.jsx const createTooltipConfig = (displayMode, t) => { const renderValue = displayMode === 'TOKENS' ? renderNumber : (v) => renderQuota(v, 4); const valueField = displayMode === 'TOKENS' ? 'rawTokenUsed' : 'rawQuota'; return { mark: { content: [ { key: (datum) => datum['Model'], value: (datum) => renderValue(datum[valueField] || 0), }, ], }, dimension: { content: [ { key: (datum) => datum['Model'], value: (datum) => datum[valueField] || 0, }, ], updateContent: (array) => { array.sort((a, b) => b.value - a.value); let sum = 0; for (let i = 0; i < array.length; i++) { if (array[i].key == '其他') continue; let value = parseFloat(array[i].value); if (isNaN(value)) value = 0; if (array[i].datum && array[i].datum.TimeSum) { sum = array[i].datum.TimeSum; } array[i].value = renderValue(value); } array.unshift({ key: t('总计'), value: renderValue(sum) }); return array; }, }, }; };
342-344: Use strict equality for string comparison.Line 342 uses
==for comparingarray[i].keywith'其他'. Prefer===for strict equality.- if (array[i].key == '其他') { + if (array[i].key === '其他') {
将散落在多个文件中的预扣费/结算/退款逻辑抽象为统一的 BillingSession 生命周期管理: - 新增 BillingSettler 接口 (relay/common/billing.go) 避免循环引用 - 新增 FundingSource 接口 + WalletFunding / SubscriptionFunding 实现 (service/funding_source.go) - 新增 BillingSession 封装预扣/结算/退款原子操作 (service/billing_session.go) - 新增 SettleBilling 统一结算辅助函数,替换各 handler 中的 quotaDelta 模式 - 重写 PreConsumeBilling 为 BillingSession 工厂入口 - controller/relay.go 退款守卫改用 BillingSession.Refund() 修复的 Bug: - 令牌额度泄漏:PreConsumeTokenQuota 成功但 DecreaseUserQuota 失败时未回滚 - 订阅退款遗漏:FinalPreConsumedQuota=0 但 SubscriptionPreConsumed>0 时跳过退款 - 订阅多扣费:subConsume 强制为 1 但 FinalPreConsumedQuota 不同步 - 退款路径不统一:钱包/订阅退款逻辑现统一由 FundingSource.Refund 分派
- Settle 部分失败保护:新增 fundingSettled 标记,资金来源提交后 令牌调整失败不再导致 Refund 误退已结算的资金 - 订阅多扣费修复:trySubscription 传 subConsume 而非 preConsumedQuota 给 preConsume,保证三者(amount/preConsume/FinalPreConsumedQuota)一致 - 令牌回滚错误记录:preConsume 中 funding 失败时令牌回滚错误不再丢弃 - 移除钱包路径死代码:用户额度不足的 strings.Contains 匹配不可能命中 - WalletFunding.Refund 不重试:IncreaseUserQuota 非幂等,重试会多退
…e recharge card tabs - Defaulting to subscriptions when available and avoiding initial flash when no plans exist. - Adjust the wide-screen layout to place wallet and invite sections side by side, simplify the subscription header and controls, and add padding to prevent card borders from clipping. - Update related i18n strings by adding the new tab label and removing the obsolete subscription blurb.
…iption-card-when-no-plans ✨ refactor(wallet): Top-up layout to embed subscription plans into the recharge card tabs
…-session refactor: 抽象统一计费会话 BillingSession
Add a lightweight active-subscription check to skip subscription pre-consume when none exist, reducing unnecessary transactions and locks. In the subscription UI, disable subscription-first options when no active plan is available, show the effective fallback to wallet with a clear notice, and distinguish “invalidated” from “expired” states. Update i18n strings across supported locales to reflect the new messages and status labels.
Aligns the error variable types in the subscription-first path so that quota fallback checks use the correct NewAPIError. This prevents build failures and preserves the intended wallet fallback when subscription pre-consume returns an insufficient quota error.
Routes quota alerts through a subscription-specific check when billing from subscriptions, preventing wallet-based thresholds from triggering false warnings. Updates the notification settings description and localization keys to clarify that both wallet and subscription balances are monitored.
…n-quota-notify 🔔 feat: Add subscription-aware quota notifications and update UI copy
…-preference-fallback ✨ chore: Improve subscription billing fallback and UI states
…tumNous#2881) 当上游为 AWS Bedrock 时,message_delta 的 usage 可能缺少 input_tokens、 cache_creation_input_tokens、cache_read_input_tokens 等字段,导致与原生 Anthropic 格式不一致。从 message_start 积累的 claudeInfo 中补全这些字段后 重新序列化,确保客户端收到一致的 usage 格式。
Modified the formatUserLogs function to include a startIdx parameter, allowing for more flexible log ID assignment. Updated calls to this function in GetLogByTokenId and GetUserLogs to pass the appropriate starting index.
feat: add Codex channel disclaimer (i18n, OpenAI terms)
feat: Force beta=true parameter for Anthropic channel
feat(oauth): implement custom OAuth provider
fix: Claude stream block index/type transitions
fix: add paragraph breaks between reasoning summary chunks
# Conflicts: # service/openaicompat/chat_to_responses.go
…t-stream feat: channel test with stream=true
…fo-input-token fix: 使用openai兼容接口调用部分渠道在最终端点为claude原生端点下还是走了openai扣减input_token的逻辑
fix: 补全 streaming message_delta 事件缺失的 input_tokens 和 cache 相关字段
…sponses feat: /v1/messages -> /v1/responses
…ion-configurable feat: make 5m cache-creation ratio configurable
…4f8a4248b0ab3b03ba703796ea3 fix: kling risk fail return openAIVideo error
fix: add explicit docker-compose networks
…ride-beta-header-append feat:support $keep_only_declared and deduped $append for header override
chore: update model lists for frequently used channels
…tion links and submission checks
Round remaining balance
enhance channel key viewing
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
web/src/i18n/locales/zh-CN.json (1)
2868-2885: Consider consolidating near-duplicate billing keysThere are many punctuation/format variants for the same billing phrase (with/without
:, spacing differences). This will increase translator workload and long-term drift. Prefer one canonical key per phrase pattern.Also applies to: 2911-2918
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@web/src/i18n/locales/zh-CN.json` around lines 2868 - 2885, Several billing translation keys are duplicated with minor punctuation/spacing differences (e.g., "模型价格 {{symbol}}{{price}} / 次" vs "模型价格:{{symbol}}{{price}} / 次", "缓存读取价格:..." vs "缓存读取价格 ..."); pick a single canonical key format for each phrase group (recommend using the colon variant like "模型价格:{{symbol}}{{price}} / 次", "缓存读取价格:{{symbol}}{{price}} / 1M tokens", etc.), remove the duplicate alternatives, and update all code references to use the chosen keys (search for the exact keys present in the diff such as "模型价格 {{symbol}}{{price}} / 次", "按次 {{symbol}}{{price}} * {{ratioType}} {{ratio}} = {{symbol}}{{total}}", "缓存读取价格 {{symbol}}{{price}} / 1M tokens", etc.); repeat the same consolidation for the other duplicates noted around lines 2911-2918 so translators only maintain one canonical key per phrase.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@web/src/i18n/locales/zh-CN.json`:
- Around line 77-78: Several zh-CN JSON entries are left in English (e.g., the
keys/values "Creem Setting Tips", "Creem 介绍" and other entries like
"Configuration", "Prompt tokens", "Completion tokens", "Total tokens",
"Discovery claims/scopes"); update the values to proper Chinese translations so
the locale file is fully localized. Locate the entries in the zh-CN JSON (search
for the exact string literals "Creem Setting Tips", "Creem 介绍" and the other
listed English phrases) and replace their English values with appropriate
Chinese phrases, ensuring consistency with existing Chinese phrasing and other
translations in the file. Ensure plural/special terms match project terminology
and run a quick pass over the block around the mentioned keys (rows ~2923-2977)
to translate any remaining English strings.
---
Nitpick comments:
In `@web/src/i18n/locales/zh-CN.json`:
- Around line 2868-2885: Several billing translation keys are duplicated with
minor punctuation/spacing differences (e.g., "模型价格 {{symbol}}{{price}} / 次" vs
"模型价格:{{symbol}}{{price}} / 次", "缓存读取价格:..." vs "缓存读取价格 ..."); pick a single
canonical key format for each phrase group (recommend using the colon variant
like "模型价格:{{symbol}}{{price}} / 次", "缓存读取价格:{{symbol}}{{price}} / 1M tokens",
etc.), remove the duplicate alternatives, and update all code references to use
the chosen keys (search for the exact keys present in the diff such as "模型价格
{{symbol}}{{price}} / 次", "按次 {{symbol}}{{price}} * {{ratioType}} {{ratio}} =
{{symbol}}{{total}}", "缓存读取价格 {{symbol}}{{price}} / 1M tokens", etc.); repeat
the same consolidation for the other duplicates noted around lines 2911-2918 so
translators only maintain one canonical key per phrase.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 9cd53cbf-d223-4347-a41a-44607bd4cc7d
📒 Files selected for processing (2)
web/src/i18n/locales/zh-CN.jsonweb/src/i18n/locales/zh.json
81b4473 to
622ba01
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (3)
web/src/hooks/dashboard/useDashboardData.js (1)
177-185: Uset()for the hardcoded Chinese string.The
token_used: 0addition is correct. However,'无数据'on line 180 should use the translation function for i18n compliance, as thetfunction is already available in this hook.🌐 Proposed fix
if (data.length === 0) { data.push({ count: 0, - model_name: '无数据', + model_name: t('无数据'), quota: 0, token_used: 0, created_at: now.getTime() / 1000, }); }As per coding guidelines,
web/src/**/*.{ts,tsx,js,jsx}: "UseuseTranslation()hook and callt('中文key')in components."🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@web/src/hooks/dashboard/useDashboardData.js` around lines 177 - 185, In the useDashboardData hook, replace the hardcoded Chinese literal '无数据' in the data.push object (property model_name) with the translation call using the existing t function (e.g., model_name: t('无数据') or the appropriate i18n key such as t('dashboard.noData')); ensure the replacement occurs inside the same data.length === 0 block so the fallback row is localized.web/src/components/dashboard/index.jsx (1)
153-158: Missing dependency in useEffect, but intentional design.The effect omits
dashboardCharts.updateChartDatafrom the dependency array. SinceupdateChartDatais memoized withdisplayModeas a dependency, adding it would cause double-execution whendisplayModechanges.Consider adding an ESLint disable comment to document this intentional omission:
📝 Suggested documentation
// 切换显示模式时重新计算图表 useEffect(() => { if (dashboardData.quotaData && dashboardData.quotaData.length > 0) { dashboardCharts.updateChartData(dashboardData.quotaData); } + // eslint-disable-next-line react-hooks/exhaustive-deps -- updateChartData intentionally omitted to avoid double-execution when displayMode changes }, [displayMode, dashboardData.quotaData]);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@web/src/components/dashboard/index.jsx` around lines 153 - 158, The useEffect that calls dashboardCharts.updateChartData omits updateChartData from dependencies intentionally to avoid double execution when displayMode changes; add a brief inline ESLint directive and explanatory comment above this effect to document the decision (use the react-hooks/exhaustive-deps disable comment), referencing the useEffect, dashboardCharts.updateChartData, displayMode and dashboardData.quotaData so future readers know the omission is deliberate and that updateChartData is memoized based on displayMode.web/src/hooks/dashboard/useDashboardCharts.jsx (1)
466-476: Consider if this effect is necessary given the data update flow.This effect updates the tooltip when
displayModechanges. However, whendisplayModechanges, the parent component (index.jsxlines 153-158) also triggersupdateChartData, which already applies the new tooltip configuration viaupdateChartSpec.This creates some redundancy, though it's not harmful. If the intent is to provide immediate visual feedback before data reprocessing completes, this is fine. Otherwise, consider removing this effect to simplify the update flow.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@web/src/hooks/dashboard/useDashboardCharts.jsx` around lines 466 - 476, The useEffect that recomputes tooltip on displayMode change is redundant because the parent triggers updateChartData which already calls updateChartSpec to apply the new tooltip; remove the useEffect block (the useEffect that calls createTooltipConfig and setSpecLine) from useDashboardCharts.jsx and rely on updateChartData/updateChartSpec to set the tooltip based on displayMode and t; if immediate visual feedback is required instead of removal, replace the effect with a brief comment explaining the intentional redundancy.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@web/src/i18n/locales/en.json`:
- Line 1521: Remove the duplicate JSON translation entry for the key "金额":
"Amount" in the en.json file; locate the repeated key ("金额": "Amount") shown in
the diff and delete this duplicate occurrence so only the original entry remains
(the other instance already present later in the file), ensuring the JSON stays
valid and no duplicate keys exist.
---
Nitpick comments:
In `@web/src/components/dashboard/index.jsx`:
- Around line 153-158: The useEffect that calls dashboardCharts.updateChartData
omits updateChartData from dependencies intentionally to avoid double execution
when displayMode changes; add a brief inline ESLint directive and explanatory
comment above this effect to document the decision (use the
react-hooks/exhaustive-deps disable comment), referencing the useEffect,
dashboardCharts.updateChartData, displayMode and dashboardData.quotaData so
future readers know the omission is deliberate and that updateChartData is
memoized based on displayMode.
In `@web/src/hooks/dashboard/useDashboardCharts.jsx`:
- Around line 466-476: The useEffect that recomputes tooltip on displayMode
change is redundant because the parent triggers updateChartData which already
calls updateChartSpec to apply the new tooltip; remove the useEffect block (the
useEffect that calls createTooltipConfig and setSpecLine) from
useDashboardCharts.jsx and rely on updateChartData/updateChartSpec to set the
tooltip based on displayMode and t; if immediate visual feedback is required
instead of removal, replace the effect with a brief comment explaining the
intentional redundancy.
In `@web/src/hooks/dashboard/useDashboardData.js`:
- Around line 177-185: In the useDashboardData hook, replace the hardcoded
Chinese literal '无数据' in the data.push object (property model_name) with the
translation call using the existing t function (e.g., model_name: t('无数据') or
the appropriate i18n key such as t('dashboard.noData')); ensure the replacement
occurs inside the same data.length === 0 block so the fallback row is localized.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 640bc80b-a9c8-4449-97e5-0e2998d38420
📒 Files selected for processing (10)
model/option.goweb/src/components/dashboard/ChartsPanel.jsxweb/src/components/dashboard/index.jsxweb/src/components/settings/DashboardSetting.jsxweb/src/helpers/dashboard.jsxweb/src/hooks/dashboard/useDashboardCharts.jsxweb/src/hooks/dashboard/useDashboardData.jsweb/src/i18n/locales/en.jsonweb/src/i18n/locales/zh-CN.jsonweb/src/pages/Setting/Dashboard/SettingsDataDashboard.jsx
🚧 Files skipped from review as they are similar to previous changes (3)
- model/option.go
- web/src/pages/Setting/Dashboard/SettingsDataDashboard.jsx
- web/src/helpers/dashboard.jsx
| "默认显示模式": "Default Display Mode", | ||
| "显示金额": "Show Amount", | ||
| "显示 Token": "Show Tokens", | ||
| "金额": "Amount", |
There was a problem hiding this comment.
Remove duplicate translation key "金额".
The key "金额": "Amount" already exists at line 3100. This duplicate entry should be removed to avoid JSON key conflicts.
🔧 Proposed fix
"显示金额": "Show Amount",
"显示 Token": "Show Tokens",
- "金额": "Amount",
"Token": "Token",📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "金额": "Amount", | |
| "显示金额": "Show Amount", | |
| "显示 Token": "Show Tokens", | |
| "Token": "Token", |
🧰 Tools
🪛 Biome (2.4.6)
[error] 1521-1521: The key 金额 was already declared.
(lint/suspicious/noDuplicateObjectKeys)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@web/src/i18n/locales/en.json` at line 1521, Remove the duplicate JSON
translation entry for the key "金额": "Amount" in the en.json file; locate the
repeated key ("金额": "Amount") shown in the diff and delete this duplicate
occurrence so only the original entry remains (the other instance already
present later in the file), ensuring the JSON stays valid and no duplicate keys
exist.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@web/src/i18n/locales/zh-CN.json`:
- Around line 151-153: The zh-CN locale currently uses placeholder values
identical to the keys for SSRF helper text; replace those placeholder values in
web/src/i18n/locales/zh-CN.json for the keys "SSRF防护开关详细说明", "SSRF防护设置", and
"SSRF防护详细说明" (and the other occurrences noted) with the full translated guidance
text used as the original security helper copy (match the English source helper
strings used by SystemSetting.jsx's extraText), so that SystemSetting.jsx (the
SSRF/network protection extraText) renders the complete, actionable instructions
rather than bare keys.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 3943d7ba-0484-4b58-8d23-38587b65830c
📒 Files selected for processing (1)
web/src/i18n/locales/zh-CN.json
| "SSRF防护开关详细说明": "SSRF防护开关详细说明", | ||
| "SSRF防护设置": "SSRF防护设置", | ||
| "SSRF防护详细说明": "SSRF防护可防止恶意用户利用您的服务器访问内网资源。您可以配置受信任域名/IP的白名单,并限制允许的端口。适用于文件下载、Webhook回调和通知功能。", | ||
| "SSRF防护详细说明": "SSRF防护详细说明", |
There was a problem hiding this comment.
Restore full security helper copy instead of self-label placeholders.
These keys are rendered as form extraText help content in web/src/components/settings/SystemSetting.jsx (Line 787-851). Keeping values equal to keys removes critical SSRF/network security guidance for zh-CN admins.
🌐 Suggested fix
- "SSRF防护开关详细说明": "SSRF防护开关详细说明",
+ "SSRF防护开关详细说明": "总开关用于控制是否启用 SSRF 防护。关闭后将跳过所有 SSRF 检查,允许访问任意 URL。⚠️ 仅在完全可信环境下关闭。",
- "SSRF防护详细说明": "SSRF防护详细说明",
+ "SSRF防护详细说明": "SSRF 防护可防止恶意用户利用服务器访问内网资源。请配置受信任域名/IP 白名单并限制允许端口。适用于文件下载、Webhook 和通知等外部请求。",
- "域名IP过滤详细说明": "域名IP过滤详细说明",
+ "域名IP过滤详细说明": "⚠️ 这是实验性选项。域名可能解析到多个 IPv4/IPv6 地址。启用后请确保 IP 过滤列表覆盖这些地址,否则可能访问失败。",
- "私有IP访问详细说明": "私有IP访问详细说明",
+ "私有IP访问详细说明": "⚠️ 安全警告:开启后可访问内网资源(localhost、私有网段)。仅在确有内网访问需求且理解风险时启用。",
- "端口配置详细说明": "端口配置详细说明",
+ "端口配置详细说明": "限制外部请求可访问的端口。支持单端口(80、443)或范围(8000-8999)。留空表示允许全部端口。默认包含常见 Web 端口。",Also applies to: 734-734, 1783-1783, 1794-1794
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@web/src/i18n/locales/zh-CN.json` around lines 151 - 153, The zh-CN locale
currently uses placeholder values identical to the keys for SSRF helper text;
replace those placeholder values in web/src/i18n/locales/zh-CN.json for the keys
"SSRF防护开关详细说明", "SSRF防护设置", and "SSRF防护详细说明" (and the other occurrences noted)
with the full translated guidance text used as the original security helper copy
(match the English source helper strings used by SystemSetting.jsx's extraText),
so that SystemSetting.jsx (the SSRF/network protection extraText) renders the
complete, actionable instructions rather than bare keys.
be40f3b to
b3a63e9
Compare
- Merge zh.json into zh-CN.json (keep local additions) - Remove zh.json (split to zh-CN/zh-TW in upstream) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary by CodeRabbit
New Features
Documentation