|
940 | 940 | runtimeTargetLifecycleReasonRuntimeGuard: "运行监测需要复核", |
941 | 941 | runtimeTargetLifecycleReasonHeartbeat: "执行心跳需要复核", |
942 | 942 | runtimeTargetLifecycleReasonUnavailable: "监测数据不可用", |
943 | | - m0ResearchBoard: "市场研究", |
944 | | - m0ResearchLoginNotice: "登录后查看市场研究和观察记录。", |
945 | | - m0ResearchStaleNotice: "研究内容更新延迟,仅供历史参考。", |
946 | | - m0ResearchUnavailableNotice: "暂时没有可用的市场研究。", |
947 | | - m0ResearchUpstreamNotice: "部分研究内容暂不可用,请稍后重试。", |
948 | | - m0ResearchEmpty: "当前没有可展示的市场研究。", |
| 943 | + m0ResearchBoard: "外部研究记录", |
| 944 | + m0ResearchLoginNotice: "登录后查看外部研究记录。", |
| 945 | + m0ResearchStaleNotice: "外部研究更新延迟,仅供历史参考。", |
| 946 | + m0ResearchUnavailableNotice: "暂时没有可用的外部研究记录。", |
| 947 | + m0ResearchUpstreamNotice: "部分外部研究暂不可用,请稍后重试。", |
| 948 | + m0ResearchEmpty: "当前没有可展示的外部研究记录。", |
949 | 949 | m0ResearchMore: "显示前 {count} 条研究观察。", |
950 | 950 | m0ResearchMeta: "{kind} · 查看于:{viewed}", |
951 | 951 | m0ResearchStateFreshness: "状态:{state} · 新鲜度:{freshness}", |
952 | 952 | m0ResearchHorizons: "主要观察期:{primary} · 适用观察期:{suitable}", |
953 | 953 | m0ResearchEvidence: "置信:{confidence} · 风格:{style} · 资料摘要:{digest}", |
954 | 954 | m0ResearchConsistency: "当前周期分歧:{conflict} · 历史失效漂移:{drift}", |
955 | | - m0ResearchNoOrder: "查看当前研究摘要。", |
| 955 | + m0ResearchNoOrder: "外部研究不影响当前策略运行。", |
956 | 956 | adaptiveSelectionBoard: "系统建议", |
957 | 957 | adaptiveSelectionLoginNotice: "登录后查看系统建议。", |
958 | 958 | adaptiveSelectionStaleNotice: "建议更新延迟,仅供历史参考。", |
|
994 | 994 | healthUnavailableNotice: "暂时无法读取策略状态,请稍后刷新。", |
995 | 995 | healthUpstreamNotice: "部分策略状态暂不可用,请稍后重试。", |
996 | 996 | healthNormalNotice: "当前没有需要关注的运行问题。", |
| 997 | + healthAttentionNotice: "有 {critical} 项严重、{review} 项需要复核、{watch} 项观察;系统正在持续监测。", |
997 | 998 | healthEmpty: "当前分类下没有策略。", |
998 | 999 | healthStatusHealthy: "健康", |
999 | 1000 | healthStatusWatch: "观察", |
|
1007 | 1008 | healthRecommendationWatch: "系统正在继续观察。", |
1008 | 1009 | healthRecommendationReview: "请查看诊断详情,等待系统复核完成。", |
1009 | 1010 | healthRecommendationCritical: "请查看诊断详情,并暂缓相关变更。", |
1010 | | - healthDetail: "最近检查:{date}", |
| 1011 | + healthDetail: "数据截至:{date}", |
1011 | 1012 | healthScoreLabel: "健康度", |
1012 | 1013 | diagnosticDetails: "查看诊断详情", |
1013 | 1014 | diagnosticDetailsHint: "仅在排查问题或查看研究记录时使用。", |
|
1331 | 1332 | runtimeTargetLifecycleReasonRuntimeGuard: "runtime guard needs review", |
1332 | 1333 | runtimeTargetLifecycleReasonHeartbeat: "execution heartbeat needs review", |
1333 | 1334 | runtimeTargetLifecycleReasonUnavailable: "monitoring data unavailable", |
1334 | | - m0ResearchBoard: "Market research", |
1335 | | - m0ResearchLoginNotice: "Sign in to see market research and observations.", |
1336 | | - m0ResearchStaleNotice: "Research is delayed and is provided for historical context only.", |
1337 | | - m0ResearchUnavailableNotice: "Market research is temporarily unavailable.", |
1338 | | - m0ResearchUpstreamNotice: "Some research content is unavailable. Please retry later.", |
1339 | | - m0ResearchEmpty: "There is no market research to display.", |
| 1335 | + m0ResearchBoard: "External research records", |
| 1336 | + m0ResearchLoginNotice: "Sign in to see external research records.", |
| 1337 | + m0ResearchStaleNotice: "External research is delayed and is provided for historical context only.", |
| 1338 | + m0ResearchUnavailableNotice: "External research records are temporarily unavailable.", |
| 1339 | + m0ResearchUpstreamNotice: "Some external research records are unavailable. Please retry later.", |
| 1340 | + m0ResearchEmpty: "There are no external research records to display.", |
1340 | 1341 | m0ResearchMore: "Showing the first {count} research observations.", |
1341 | 1342 | m0ResearchMeta: "{kind} · viewed {viewed}", |
1342 | 1343 | m0ResearchStateFreshness: "State: {state} · freshness: {freshness}", |
1343 | 1344 | m0ResearchHorizons: "Primary horizon: {primary} · suitable horizons: {suitable}", |
1344 | 1345 | m0ResearchEvidence: "Confidence: {confidence} · style: {style} · source digest: {digest}", |
1345 | 1346 | m0ResearchConsistency: "Current horizon conflict: {conflict} · historical stale drift: {drift}", |
1346 | | - m0ResearchNoOrder: "View the current research summary.", |
| 1347 | + m0ResearchNoOrder: "External research does not affect current strategy operation.", |
1347 | 1348 | adaptiveSelectionBoard: "System suggestions", |
1348 | 1349 | adaptiveSelectionLoginNotice: "Sign in to see system suggestions.", |
1349 | 1350 | adaptiveSelectionStaleNotice: "Suggestions are delayed and are provided for historical context only.", |
|
1385 | 1386 | healthUnavailableNotice: "Strategy status is temporarily unavailable. Refresh later.", |
1386 | 1387 | healthUpstreamNotice: "Some strategy status is unavailable. Retry later.", |
1387 | 1388 | healthNormalNotice: "There are no runtime issues that need attention.", |
| 1389 | + healthAttentionNotice: "{critical} critical, {review} to review, and {watch} under observation. Monitoring continues.", |
1388 | 1390 | healthEmpty: "There are no strategies in this category.", |
1389 | 1391 | healthStatusHealthy: "Healthy", |
1390 | 1392 | healthStatusWatch: "Watch", |
|
1398 | 1400 | healthRecommendationWatch: "The system is continuing to monitor.", |
1399 | 1401 | healthRecommendationReview: "View diagnostic details while the system completes its review.", |
1400 | 1402 | healthRecommendationCritical: "View diagnostic details and hold related changes for now.", |
1401 | | - healthDetail: "Last checked: {date}", |
| 1403 | + healthDetail: "Data as of: {date}", |
1402 | 1404 | healthScoreLabel: "Health", |
1403 | 1405 | diagnosticDetails: "View diagnostic details", |
1404 | 1406 | diagnosticDetailsHint: "Use this only to investigate an issue or review research records.", |
|
1747 | 1749 | }).format(parsed); |
1748 | 1750 | } |
1749 | 1751 |
|
| 1752 | + function formatAsOfDate(value) { |
| 1753 | + if (typeof value === "string" && /^\d{4}-\d{2}-\d{2}$/.test(value)) { |
| 1754 | + const parsed = new Date(`${value}T00:00:00.000Z`); |
| 1755 | + return new Intl.DateTimeFormat(locale(), { |
| 1756 | + dateStyle: "medium", |
| 1757 | + timeZone: "UTC", |
| 1758 | + }).format(parsed); |
| 1759 | + } |
| 1760 | + return formatDateTime(value); |
| 1761 | + } |
| 1762 | + |
1750 | 1763 | function localizedExternalText(value, fallback) { |
1751 | 1764 | const text = typeof value === "string" ? value.trim() : ""; |
1752 | 1765 | if (!text) return fallback; |
|
4832 | 4845 | function renderHealth() { |
4833 | 4846 | const payload = state.health.payload; |
4834 | 4847 | const summary = payload.summary || {}; |
| 4848 | + const healthCount = (status) => Math.max( |
| 4849 | + Number(summary[status]) || 0, |
| 4850 | + payload.strategies.filter((item) => item.status === status).length, |
| 4851 | + ); |
| 4852 | + const criticalCount = healthCount("critical"); |
| 4853 | + const reviewCount = healthCount("review"); |
| 4854 | + const watchCount = healthCount("watch"); |
| 4855 | + const hasAttention = criticalCount + reviewCount + watchCount > 0; |
4835 | 4856 | const summaryAvailable = state.auth.allowed && payload.data_status !== "unavailable"; |
4836 | 4857 | const summaryCount = (value) => (summaryAvailable ? String(Number(value) || 0) : "—"); |
4837 | 4858 | const statusText = payload.data_status === "ready" |
|
4854 | 4875 | notice.textContent = t("healthStaleNotice"); |
4855 | 4876 | } else if (payload.data_status !== "ready") { |
4856 | 4877 | notice.textContent = t("healthUnavailableNotice"); |
| 4878 | + } else if (hasAttention) { |
| 4879 | + notice.textContent = t("healthAttentionNotice") |
| 4880 | + .replace("{critical}", String(criticalCount)) |
| 4881 | + .replace("{review}", String(reviewCount)) |
| 4882 | + .replace("{watch}", String(watchCount)); |
4857 | 4883 | } else if (payload.errors?.length) { |
4858 | 4884 | notice.textContent = t("healthUpstreamNotice"); |
4859 | 4885 | } else { |
|
4889 | 4915 | const detail = document.createElement("div"); |
4890 | 4916 | detail.className = "health-card__meta"; |
4891 | 4917 | detail.textContent = t("healthDetail") |
4892 | | - .replace("{date}", formatDateTime(item.as_of)); |
| 4918 | + .replace("{date}", formatAsOfDate(item.as_of)); |
4893 | 4919 | main.append(meta, title, reason, detail); |
4894 | 4920 | const scoreBlock = document.createElement("div"); |
4895 | 4921 | scoreBlock.className = "health-card__score"; |
|
0 commit comments