fix(web): S11+S12 載入失敗修復 — Sprint 5R Phase 1A
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
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:
@@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 ?? [])
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -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)' }}>
|
||||
|
||||
Reference in New Issue
Block a user