fix(web): S11+S12 載入失敗修復 — Sprint 5R Phase 1A
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled

- S11: Tab 2 approvals API path 修正 (?status=pending → /pending)
- S11: Tab 2 fetch 加 r.ok 檢查避免解析錯誤 JSON
- S12: 安全合規改用 SecurityPanel + CompliancePanel (解決 double AppLayout)
- S12: 知識庫改為 redirect 到 /knowledge-base (避免 lazy import 問題)
- S12: 拓撲圖加入 useDashboardStore.connect() 啟動 SSE

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
OG T
2026-04-09 15:43:06 +08:00
parent c180bdaaac
commit 289dac6bd1
8 changed files with 278 additions and 32 deletions

View File

@@ -215,8 +215,7 @@ export default function KnowledgeBasePage({
const totalCount = categories.reduce((sum, c) => sum + c.count, 0)
return (
<AppLayout locale={params.locale}>
const content = (
<div className="flex h-[calc(100vh-64px)]">
{/* 左側分類導航 */}
@@ -527,6 +526,12 @@ export default function KnowledgeBasePage({
</aside>
)}
</div>
)
return (
<AppLayout locale={params.locale}>
{content}
</AppLayout>
)
}

View File

@@ -2,24 +2,19 @@
/**
* 知識 (/knowledge) — Sprint 5 整合頁面
* 直接載入現有 knowledge-base 內容
* 零假數據: 原封不動使用現有頁面
* 建立時間: 2026-04-08 (台北時區)
* 直接渲染 knowledge-base 內容(不含 AppLayout
* @updated 2026-04-09 Claude Opus 4.6 — 移除 lazy import 避免 double AppLayout
*/
import { lazy, Suspense } from 'react'
import { useTranslations } from 'next-intl'
import { AppLayout } from '@/components/layout'
const KnowledgeBaseContent = lazy(() => import('@/app/[locale]/knowledge-base/page'))
import { useRouter } from 'next/navigation'
import { useEffect } from 'react'
export default function KnowledgePage({ params }: { params: { locale: string } }) {
const t = useTranslations('common')
return (
<AppLayout locale={params.locale}>
<Suspense fallback={<div style={{ padding: 32, textAlign: 'center', color: '#87867f' }}>{t('loading')}</div>}>
<KnowledgeBaseContent params={params} />
</Suspense>
</AppLayout>
)
const router = useRouter()
useEffect(() => {
router.replace(`/${params.locale}/knowledge-base`)
}, [router, params.locale])
return null
}

View File

@@ -44,8 +44,8 @@ function AlertsAndApprovalsTab() {
useEffect(() => {
Promise.all([
fetch(`${API_BASE}/api/v1/incidents`).then(r => r.json()).catch(() => ({ incidents: [] })),
fetch(`${API_BASE}/api/v1/approvals?status=pending`).then(r => r.json()).catch(() => []),
fetch(`${API_BASE}/api/v1/incidents`).then(r => r.ok ? r.json() : { incidents: [] }).catch(() => ({ incidents: [] })),
fetch(`${API_BASE}/api/v1/approvals/pending`).then(r => r.ok ? r.json() : []).catch(() => []),
]).then(([incData, apprData]) => {
setAlerts(incData.incidents ?? incData ?? [])
setApprovals(Array.isArray(apprData) ? apprData : apprData.approvals ?? [])

View File

@@ -3,28 +3,21 @@
/**
* 安全合規 (/security-compliance) — Sprint 5 整合頁面
* 整合: 安全掃描 + 合規報告
* 零假數據: 全部載入現有頁面內容
* 建立時間: 2026-04-08 (台北時區)
* @updated 2026-04-09 Claude Opus 4.6 — 改用 Panel 元件解決 double AppLayout
*/
import { lazy, Suspense } from 'react'
import { useTranslations } from 'next-intl'
import { AppLayout } from '@/components/layout'
import { PageTabs, type TabConfig } from '@/components/layout/page-tabs'
const SecurityContent = lazy(() => import('@/app/[locale]/security/page'))
const ComplianceContent = lazy(() => import('@/app/[locale]/compliance/page'))
function Loading() {
return <div style={{ padding: 32, textAlign: 'center', color: '#87867f' }}>...</div>
}
import { SecurityPanel } from '@/components/panels/SecurityPanel'
import { CompliancePanel } from '@/components/panels/CompliancePanel'
export default function SecurityCompliancePage({ params }: { params: { locale: string } }) {
const t = useTranslations('nav')
const tabs: TabConfig[] = [
{ id: 'security', label: t('security'), content: <Suspense fallback={<Loading />}><SecurityContent params={params} /></Suspense> },
{ id: 'compliance', label: t('compliance'), content: <Suspense fallback={<Loading />}><ComplianceContent params={params} /></Suspense> },
{ id: 'security', label: t('security'), content: <SecurityPanel /> },
{ id: 'compliance', label: t('compliance'), content: <CompliancePanel /> },
]
return (

View File

@@ -11,13 +11,23 @@
* @updated 2026-04-09 Claude Code — Sprint 5 React Flow 完整升級
*/
import { useEffect } from 'react'
import { useTranslations } from 'next-intl'
import { AppLayout } from '@/components/layout'
import { ServiceTopology } from '@/components/topology'
import { useDashboardStore } from '@/stores/dashboard.store'
export default function TopologyPage({ params }: { params: { locale: string } }) {
const t = useTranslations('topology')
// 確保 SSE 連接啟動,拓撲圖才有資料
useEffect(() => {
const apiBase = process.env.NEXT_PUBLIC_API_URL
if (apiBase) {
useDashboardStore.getState().connect(apiBase)
}
}, [])
return (
<AppLayout locale={params.locale}>
<div style={{ display: 'flex', flexDirection: 'column', height: 'calc(100vh - 68px)' }}>