@
chore: delete old layout/common/tabs components before redesign @
This commit is contained in:
636
docs/superpowers/plans/2026-05-21-system-status-optimizations.md
Normal file
636
docs/superpowers/plans/2026-05-21-system-status-optimizations.md
Normal file
@@ -0,0 +1,636 @@
|
||||
# System Status Module Optimization Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Upgrade the 系统状态 page from a static one-shot snapshot into a reliable observability dashboard with loading states, service health checks, auto-refresh, BM25/Reranker visibility, and config display fixes.
|
||||
|
||||
**Architecture:** Backend adds a unified `/status/health` aggregate endpoint (Milvus + MinIO + BM25 + Reranker + Sessions) and a TTL cache on `/status/stats`. Frontend adds loading/error states, a refresh button, auto-polling while documents are processing, a health services panel, and config value truncation fixes.
|
||||
|
||||
**Tech Stack:** FastAPI, Python 3.11, React 18, TypeScript, CSS-in-JS (inline styles with theme context)
|
||||
|
||||
---
|
||||
|
||||
## File Map
|
||||
|
||||
| File | Action | Purpose |
|
||||
|------|--------|---------|
|
||||
| `backend/app/api/routes/status.py` | Modify | Add `/health` endpoint, TTL cache on `/stats`, import session store |
|
||||
| `frontend/src/api/status.ts` | Modify | Add `SystemHealth` type + `getSystemHealth()` |
|
||||
| `frontend/src/api/index.ts` | Modify | Export `SystemHealth` interface |
|
||||
| `frontend/src/pages/Status/StatusPage.tsx` | Modify | Loading/error states, refresh, auto-poll, health panel, config fix |
|
||||
|
||||
---
|
||||
|
||||
## Task 1: Backend — Add `/status/health` Endpoint + TTL Cache on `/status/stats`
|
||||
|
||||
**Files:**
|
||||
- Modify: `backend/app/api/routes/status.py`
|
||||
|
||||
- [ ] **Step 1: Read the current `status.py`**
|
||||
|
||||
```
|
||||
File: backend/app/api/routes/status.py
|
||||
```
|
||||
|
||||
Note existing imports and route signatures before editing.
|
||||
|
||||
- [ ] **Step 2: Replace `status.py` with the new version**
|
||||
|
||||
Replace the entire content of `backend/app/api/routes/status.py` with:
|
||||
|
||||
```python
|
||||
"""Define API routes for status."""
|
||||
|
||||
import time
|
||||
from typing import Any
|
||||
|
||||
from fastapi import APIRouter
|
||||
|
||||
from app.config.settings import settings
|
||||
from app.shared.bootstrap import (
|
||||
get_bm25_retriever,
|
||||
get_binary_store,
|
||||
get_conversation_store,
|
||||
get_document_query_service,
|
||||
get_vector_index,
|
||||
)
|
||||
|
||||
router = APIRouter(prefix="/status", tags=["系统状态"])
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Simple TTL cache for /stats (avoids O(N) doc scan on every request)
|
||||
# ---------------------------------------------------------------------------
|
||||
_stats_cache: dict[str, Any] = {}
|
||||
_stats_cache_time: float = 0.0
|
||||
_STATS_TTL_SECONDS: float = 10.0
|
||||
|
||||
|
||||
def _invalidate_stats_cache() -> None:
|
||||
global _stats_cache_time
|
||||
_stats_cache_time = 0.0
|
||||
|
||||
|
||||
@router.get("/stats")
|
||||
async def get_stats():
|
||||
"""Return document statistics (cached for 10 s)."""
|
||||
global _stats_cache, _stats_cache_time
|
||||
now = time.time()
|
||||
if _stats_cache and (now - _stats_cache_time) < _STATS_TTL_SECONDS:
|
||||
return _stats_cache
|
||||
|
||||
documents = get_document_query_service().list_documents()
|
||||
indexed = sum(1 for d in documents if d.status.value == "indexed")
|
||||
failed = sum(1 for d in documents if d.status.value == "failed")
|
||||
_stats_cache = {
|
||||
"documents_total": len(documents),
|
||||
"documents_indexed": indexed,
|
||||
"documents_failed": failed,
|
||||
"chunks_total": sum(d.chunk_count for d in documents),
|
||||
}
|
||||
_stats_cache_time = now
|
||||
return _stats_cache
|
||||
|
||||
|
||||
@router.get("/config")
|
||||
async def get_config():
|
||||
"""Return system configuration."""
|
||||
return {
|
||||
"embedding_model": settings.embedding_model,
|
||||
"embedding_dim": settings.embedding_dim,
|
||||
"embedding_base_url": settings.embedding_base_url,
|
||||
"milvus_collection": settings.milvus_collection,
|
||||
"parser_backend": settings.parser_backend,
|
||||
"chunk_backend": settings.chunk_backend,
|
||||
"artifact_prefix": settings.document_parse_artifact_prefix,
|
||||
"parser_failure_mode": settings.parser_failure_mode,
|
||||
"llm_provider": settings.llm_provider,
|
||||
"llm_model": settings.llm_model,
|
||||
"document_metadata_path": settings.document_metadata_path,
|
||||
}
|
||||
|
||||
|
||||
@router.get("/milvus/health")
|
||||
async def milvus_health():
|
||||
"""Return Milvus health (kept for backwards compat)."""
|
||||
return get_vector_index().health()
|
||||
|
||||
|
||||
@router.get("/health")
|
||||
async def get_health():
|
||||
"""Return aggregate health of all backend services."""
|
||||
# --- Milvus ---
|
||||
try:
|
||||
milvus_info = get_vector_index().health()
|
||||
milvus_status = "ok" if milvus_info.get("connected") else "error"
|
||||
except Exception as exc: # noqa: BLE001
|
||||
milvus_info = {}
|
||||
milvus_status = "error"
|
||||
milvus_info["error"] = str(exc)
|
||||
|
||||
# --- MinIO ---
|
||||
try:
|
||||
minio_connected = get_binary_store().client.connected
|
||||
minio_status = "ok" if minio_connected else "error"
|
||||
except Exception as exc: # noqa: BLE001
|
||||
minio_status = "error"
|
||||
minio_connected = False
|
||||
|
||||
# --- BM25 ---
|
||||
bm25 = get_bm25_retriever()
|
||||
|
||||
# --- Sessions ---
|
||||
try:
|
||||
session_count = len(get_conversation_store().list_sessions())
|
||||
except Exception: # noqa: BLE001
|
||||
session_count = 0
|
||||
|
||||
return {
|
||||
"milvus": {"status": milvus_status, **milvus_info},
|
||||
"minio": {"status": minio_status, "connected": minio_connected},
|
||||
"bm25": {"available": bm25 is not None},
|
||||
"reranker": {
|
||||
"enabled": settings.reranker_enabled,
|
||||
"model": settings.reranker_model if settings.reranker_enabled else None,
|
||||
},
|
||||
"sessions": {
|
||||
"active": session_count,
|
||||
"max": settings.session_max_sessions,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 3: Verify Python syntax**
|
||||
|
||||
```bash
|
||||
cd backend && python -c "from app.api.routes.status import router; print('OK')"
|
||||
```
|
||||
|
||||
Expected output: `OK`
|
||||
|
||||
- [ ] **Step 4: Commit**
|
||||
|
||||
```bash
|
||||
git add backend/app/api/routes/status.py
|
||||
git commit -m "feat(status): add /health aggregate endpoint and 10s TTL cache on /stats"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 2: Frontend API — Add `SystemHealth` Type + `getSystemHealth()`
|
||||
|
||||
**Files:**
|
||||
- Modify: `frontend/src/api/index.ts`
|
||||
- Modify: `frontend/src/api/status.ts`
|
||||
|
||||
- [ ] **Step 1: Add `SystemHealth` interface to `frontend/src/api/index.ts`**
|
||||
|
||||
Open `frontend/src/api/index.ts`. After the `SystemConfig` interface (around line 240), add:
|
||||
|
||||
```typescript
|
||||
export interface ServiceHealth {
|
||||
status: 'ok' | 'error' | 'unknown';
|
||||
error?: string;
|
||||
}
|
||||
|
||||
export interface SystemHealth {
|
||||
milvus: ServiceHealth & {
|
||||
connected?: boolean;
|
||||
collection_name?: string;
|
||||
num_entities?: number;
|
||||
};
|
||||
minio: ServiceHealth & { connected?: boolean };
|
||||
bm25: { available: boolean };
|
||||
reranker: { enabled: boolean; model?: string | null };
|
||||
sessions: { active: number; max: number };
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Add `getSystemHealth()` to `frontend/src/api/status.ts`**
|
||||
|
||||
Open `frontend/src/api/status.ts`. The current content is:
|
||||
|
||||
```typescript
|
||||
import { fetchAPI, type SystemConfig, type SystemStats } from './index';
|
||||
|
||||
export async function getSystemStats(): Promise<SystemStats> {
|
||||
return fetchAPI<SystemStats>('/status/stats');
|
||||
}
|
||||
|
||||
export async function getSystemConfig(): Promise<SystemConfig> {
|
||||
return fetchAPI<SystemConfig>('/status/config');
|
||||
}
|
||||
|
||||
export async function getMilvusHealth(): Promise<{ connected: boolean; collections: string[] }> {
|
||||
return fetchAPI('/status/milvus/health');
|
||||
}
|
||||
|
||||
export type { SystemConfig, SystemStats };
|
||||
```
|
||||
|
||||
Replace with:
|
||||
|
||||
```typescript
|
||||
import { fetchAPI, type SystemConfig, type SystemHealth, type SystemStats } from './index';
|
||||
|
||||
export async function getSystemStats(): Promise<SystemStats> {
|
||||
return fetchAPI<SystemStats>('/status/stats');
|
||||
}
|
||||
|
||||
export async function getSystemConfig(): Promise<SystemConfig> {
|
||||
return fetchAPI<SystemConfig>('/status/config');
|
||||
}
|
||||
|
||||
export async function getSystemHealth(): Promise<SystemHealth> {
|
||||
return fetchAPI<SystemHealth>('/status/health');
|
||||
}
|
||||
|
||||
export type { SystemConfig, SystemHealth, SystemStats };
|
||||
```
|
||||
|
||||
- [ ] **Step 3: Commit**
|
||||
|
||||
```bash
|
||||
git add frontend/src/api/index.ts frontend/src/api/status.ts
|
||||
git commit -m "feat(status): add SystemHealth type and getSystemHealth() API function"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 3: Frontend — Loading/Error States + Refresh Button + Auto-Poll
|
||||
|
||||
**Files:**
|
||||
- Modify: `frontend/src/pages/Status/StatusPage.tsx`
|
||||
|
||||
This task replaces the `useEffect` + `loadData` pattern and the top of the component with loading/error/refresh support. Auto-poll fires every 5 s while any document is `parsing` or `pending`.
|
||||
|
||||
- [ ] **Step 1: Read current `StatusPage.tsx`**
|
||||
|
||||
```
|
||||
File: frontend/src/pages/Status/StatusPage.tsx
|
||||
```
|
||||
|
||||
Identify: the `useState` block, `loadData` function, and the single `useEffect`.
|
||||
|
||||
- [ ] **Step 2: Replace the import block and state/effect section**
|
||||
|
||||
Find and replace the imports at the top of the file:
|
||||
|
||||
**Old:**
|
||||
```typescript
|
||||
import React, { useEffect, useState } from 'react';
|
||||
```
|
||||
|
||||
**New:**
|
||||
```typescript
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
```
|
||||
|
||||
- [ ] **Step 3: Add `SystemHealth` to the API import**
|
||||
|
||||
**Old:**
|
||||
```typescript
|
||||
import { getSystemStats, getSystemConfig, type SystemStats, type SystemConfig } from '../../api/status';
|
||||
```
|
||||
|
||||
**New:**
|
||||
```typescript
|
||||
import { getSystemStats, getSystemConfig, getSystemHealth, type SystemStats, type SystemConfig, type SystemHealth } from '../../api/status';
|
||||
```
|
||||
|
||||
- [ ] **Step 4: Replace the state declarations and loadData + useEffect block inside the component**
|
||||
|
||||
Find the block starting with `const [stats, setStats]` and ending after the closing `}, []);` of the first `useEffect`. Replace it entirely with:
|
||||
|
||||
```typescript
|
||||
const [stats, setStats] = useState<SystemStats>({
|
||||
documents_total: 0,
|
||||
documents_indexed: 0,
|
||||
documents_failed: 0,
|
||||
chunks_total: 0,
|
||||
});
|
||||
const [config, setConfig] = useState<SystemConfig | null>(null);
|
||||
const [docs, setDocs] = useState<DocInfo[]>([]);
|
||||
const [health, setHealth] = useState<SystemHealth | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const loadData = useCallback(async () => {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
try {
|
||||
const [statsRes, configRes, docsRes, healthRes] = await Promise.all([
|
||||
getSystemStats(),
|
||||
getSystemConfig(),
|
||||
getDocumentList(),
|
||||
getSystemHealth(),
|
||||
]);
|
||||
setStats(statsRes);
|
||||
setConfig(configRes);
|
||||
setDocs(docsRes.docs);
|
||||
setHealth(healthRes);
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : 'Failed to load status data');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, []);
|
||||
|
||||
// Initial load
|
||||
useEffect(() => {
|
||||
void loadData();
|
||||
}, [loadData]);
|
||||
|
||||
// Auto-poll every 5 s while any document is still processing
|
||||
useEffect(() => {
|
||||
const hasProcessing = docs.some(d => d.status === 'parsing' || d.status === 'pending');
|
||||
if (!hasProcessing) return;
|
||||
const id = window.setInterval(() => void loadData(), 5000);
|
||||
return () => window.clearInterval(id);
|
||||
}, [docs, loadData]);
|
||||
```
|
||||
|
||||
- [ ] **Step 5: Add loading banner and error banner at the top of the returned JSX**
|
||||
|
||||
Find the `return (` statement in the component. Inside `<Content>`, right after `<TPattern />`, add:
|
||||
|
||||
```typescript
|
||||
{/* Loading overlay */}
|
||||
{loading && (
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 16, color: theme.text3, fontSize: 13 }}>
|
||||
<span style={{ display: 'inline-block', width: 12, height: 12, borderRadius: '50%', border: `2px solid ${theme.accent}`, borderTopColor: 'transparent', animation: 'spin 0.8s linear infinite' }} />
|
||||
<span className="mono">LOADING...</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Error banner */}
|
||||
{error && (
|
||||
<div style={{
|
||||
marginBottom: 16,
|
||||
padding: '12px 16px',
|
||||
background: '#d6454520',
|
||||
border: '1px solid #d64545',
|
||||
borderRadius: 8,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
}}>
|
||||
<span style={{ fontSize: 13, color: '#d64545' }}>{error}</span>
|
||||
<button
|
||||
onClick={() => void loadData()}
|
||||
style={{ background: 'none', border: '1px solid #d64545', borderRadius: 6, color: '#d64545', cursor: 'pointer', padding: '4px 10px', fontSize: 12 }}
|
||||
>
|
||||
重试
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
```
|
||||
|
||||
- [ ] **Step 6: Add a refresh button to the stats section header**
|
||||
|
||||
Find the `<section style={{ marginBottom: 48 }}>` that wraps the 4 stats cards. Add a header row with a refresh button just before the grid `<div>`:
|
||||
|
||||
```typescript
|
||||
<section style={{ marginBottom: 48 }}>
|
||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 16 }}>
|
||||
<h2 style={{ fontSize: 14, fontWeight: 600, color: theme.accent, letterSpacing: '1px', margin: 0 }}>
|
||||
DOCUMENT STATISTICS
|
||||
</h2>
|
||||
<button
|
||||
onClick={() => void loadData()}
|
||||
disabled={loading}
|
||||
style={{
|
||||
background: 'none',
|
||||
border: `1px solid ${theme.border}`,
|
||||
borderRadius: 6,
|
||||
color: theme.text3,
|
||||
cursor: loading ? 'not-allowed' : 'pointer',
|
||||
padding: '4px 12px',
|
||||
fontSize: 11,
|
||||
opacity: loading ? 0.5 : 1,
|
||||
}}
|
||||
>
|
||||
↻ 刷新
|
||||
</button>
|
||||
</div>
|
||||
{/* existing 4-card grid stays here unchanged */}
|
||||
```
|
||||
|
||||
- [ ] **Step 7: Add CSS keyframe for the spinner**
|
||||
|
||||
Find the `<Content>` wrapping element. Add a `<style>` tag as the very first child inside `<Content>`:
|
||||
|
||||
```typescript
|
||||
<style>{`@keyframes spin { to { transform: rotate(360deg); } }`}</style>
|
||||
```
|
||||
|
||||
- [ ] **Step 8: Commit**
|
||||
|
||||
```bash
|
||||
git add frontend/src/pages/Status/StatusPage.tsx
|
||||
git commit -m "feat(status): add loading/error states, refresh button, auto-poll for processing docs"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 4: Frontend — Service Health Panel
|
||||
|
||||
**Files:**
|
||||
- Modify: `frontend/src/pages/Status/StatusPage.tsx`
|
||||
|
||||
Adds a new section after the stats cards that shows a colored status badge for each service (Milvus, MinIO, BM25, Reranker) plus the active session count.
|
||||
|
||||
- [ ] **Step 1: Add the `ServiceBadge` helper component** (add just before `StatsCard`)
|
||||
|
||||
```typescript
|
||||
const ServiceBadge = ({
|
||||
label,
|
||||
status,
|
||||
detail,
|
||||
}: {
|
||||
label: string;
|
||||
status: 'ok' | 'error' | 'unknown' | boolean;
|
||||
detail?: string;
|
||||
}) => {
|
||||
const { theme } = useTheme();
|
||||
const isOk = status === 'ok' || status === true;
|
||||
const color = isOk ? theme.green : '#d64545';
|
||||
const dot = isOk ? '●' : '●';
|
||||
return (
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
padding: '12px 16px',
|
||||
background: theme.bgCard,
|
||||
borderRadius: 10,
|
||||
border: `1px solid ${theme.border}`,
|
||||
}}>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
|
||||
<span style={{ color, fontSize: 10 }}>{dot}</span>
|
||||
<span className="mono" style={{ fontSize: 12, color: theme.text2 }}>{label}</span>
|
||||
</div>
|
||||
<span style={{ fontSize: 12, color, fontWeight: 600 }}>
|
||||
{detail ?? (isOk ? 'OK' : 'ERROR')}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Insert the health section between the stats section and the SYSTEM CONFIGURATION section**
|
||||
|
||||
Find `<section style={{ marginBottom: 48 }}>` for SYSTEM CONFIGURATION. Just before it, insert:
|
||||
|
||||
```typescript
|
||||
<section style={{ marginBottom: 48 }}>
|
||||
<h2 style={{ fontSize: 14, fontWeight: 600, color: theme.accent, marginBottom: 20, letterSpacing: '1px' }}>
|
||||
SERVICE HEALTH
|
||||
</h2>
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 12, marginBottom: 12 }}>
|
||||
<ServiceBadge
|
||||
label="MILVUS"
|
||||
status={health?.milvus.status ?? 'unknown'}
|
||||
detail={health ? (health.milvus.status === 'ok' ? `${health.milvus.num_entities ?? 0} entities` : 'disconnected') : '—'}
|
||||
/>
|
||||
<ServiceBadge
|
||||
label="MINIO"
|
||||
status={health?.minio.status ?? 'unknown'}
|
||||
detail={health ? (health.minio.status === 'ok' ? 'connected' : 'disconnected') : '—'}
|
||||
/>
|
||||
<ServiceBadge
|
||||
label="BM25 HYBRID"
|
||||
status={health?.bm25.available ?? false}
|
||||
detail={health ? (health.bm25.available ? 'enabled' : 'unavailable') : '—'}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 12 }}>
|
||||
<ServiceBadge
|
||||
label="RERANKER"
|
||||
status={health?.reranker.enabled ?? false}
|
||||
detail={health ? (health.reranker.enabled ? health.reranker.model ?? 'enabled' : 'disabled') : '—'}
|
||||
/>
|
||||
<ServiceBadge
|
||||
label="SESSIONS"
|
||||
status="ok"
|
||||
detail={health ? `${health.sessions.active} / ${health.sessions.max}` : '—'}
|
||||
/>
|
||||
<ServiceBadge
|
||||
label="LLM"
|
||||
status="ok"
|
||||
detail={config ? `${config.llm_provider} · ${config.llm_model}` : '—'}
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
```
|
||||
|
||||
- [ ] **Step 3: Commit**
|
||||
|
||||
```bash
|
||||
git add frontend/src/pages/Status/StatusPage.tsx
|
||||
git commit -m "feat(status): add SERVICE HEALTH panel with Milvus/MinIO/BM25/Reranker/Session badges"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 5: Frontend — Config Value Truncation Fix + Failed Docs Highlight
|
||||
|
||||
**Files:**
|
||||
- Modify: `frontend/src/pages/Status/StatusPage.tsx`
|
||||
|
||||
- [ ] **Step 1: Fix config value truncation**
|
||||
|
||||
In the SYSTEM CONFIGURATION section, find the `<span>` that renders the config value `v` — it currently renders as:
|
||||
|
||||
```typescript
|
||||
<span style={{ fontSize: 14, fontWeight: 500 }}>{v}</span>
|
||||
```
|
||||
|
||||
Replace it with:
|
||||
|
||||
```typescript
|
||||
<span
|
||||
title={v}
|
||||
style={{
|
||||
fontSize: 13,
|
||||
fontWeight: 500,
|
||||
maxWidth: 240,
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
whiteSpace: 'nowrap',
|
||||
cursor: 'help',
|
||||
}}
|
||||
>
|
||||
{v}
|
||||
</span>
|
||||
```
|
||||
|
||||
This applies to both the MODELS and STORAGE AND PATHS sub-sections since they share the same `.map(([k, v]) => ...)` render pattern.
|
||||
|
||||
- [ ] **Step 2: Highlight failed documents in the document list**
|
||||
|
||||
In the DOCUMENT INDEX section, find the `docs.map(d => ...)` container `<div>`. Change the border to highlight failed docs:
|
||||
|
||||
**Old:**
|
||||
```typescript
|
||||
border: `1px solid ${theme.border}`,
|
||||
```
|
||||
|
||||
**New:**
|
||||
```typescript
|
||||
border: `1px solid ${d.status === 'failed' ? '#d64545' : d.status === 'parsing' || d.status === 'pending' ? theme.accent + '80' : theme.border}`,
|
||||
```
|
||||
|
||||
- [ ] **Step 3: Add pulsing indicator for in-progress documents**
|
||||
|
||||
In the same `docs.map` block, the status badge currently always shows a static green background. Update it to show different colors per status:
|
||||
|
||||
**Old:**
|
||||
```typescript
|
||||
<div style={{
|
||||
padding: '4px 12px',
|
||||
background: d.status === 'failed' ? '#d64545' : theme.green,
|
||||
borderRadius: 6,
|
||||
}}>
|
||||
<span className="mono" style={{ fontSize: 10, fontWeight: 600, color: '#fff' }}>
|
||||
{d.status.toUpperCase()}
|
||||
</span>
|
||||
</div>
|
||||
```
|
||||
|
||||
**New:**
|
||||
```typescript
|
||||
<div style={{
|
||||
padding: '4px 12px',
|
||||
background:
|
||||
d.status === 'failed' ? '#d64545' :
|
||||
d.status === 'parsing' || d.status === 'pending' ? theme.accent :
|
||||
theme.green,
|
||||
borderRadius: 6,
|
||||
opacity: d.status === 'parsing' || d.status === 'pending' ? 0.85 : 1,
|
||||
}}>
|
||||
<span className="mono" style={{ fontSize: 10, fontWeight: 600, color: '#fff' }}>
|
||||
{d.status === 'parsing' ? '⟳ ' : ''}{d.status.toUpperCase()}
|
||||
</span>
|
||||
</div>
|
||||
```
|
||||
|
||||
- [ ] **Step 4: Commit**
|
||||
|
||||
```bash
|
||||
git add frontend/src/pages/Status/StatusPage.tsx
|
||||
git commit -m "fix(status): config value ellipsis truncation, failed doc highlight, parsing doc pulse"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Self-Review Checklist
|
||||
|
||||
- [x] Task 1 covers P2 (TTL cache) + P1 (service health backend)
|
||||
- [x] Task 2 adds the `SystemHealth` type that Tasks 3–4 depend on
|
||||
- [x] Task 3 covers P0 (loading/error/refresh/auto-poll)
|
||||
- [x] Task 4 covers P1 (BM25/reranker/sessions visibility)
|
||||
- [x] Task 5 covers P1 (config truncation) + P1 (failed doc visual)
|
||||
- [x] All `getSystemHealth` references match the function name defined in Task 2
|
||||
- [x] `health?.milvus.status` type matches `ServiceHealth.status: 'ok' | 'error' | 'unknown'`
|
||||
- [x] Backend `/health` endpoint uses only already-imported bootstrap functions
|
||||
- [x] No TBD or TODO left in plan
|
||||
944
docs/superpowers/plans/2026-05-27-boss-report-html.md
Normal file
944
docs/superpowers/plans/2026-05-27-boss-report-html.md
Normal file
@@ -0,0 +1,944 @@
|
||||
# Boss Progress Report HTML Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Build a single self-contained HTML file (`boss-report.html`) that serves as a phase-1 progress report for the AI+合规智能中枢 project — usable both for in-person projection and async reading by the boss.
|
||||
|
||||
**Architecture:** Single HTML file, zero external dependencies except Google Fonts CDN. All styles inline via `<style>` tag, all interactivity via vanilla JS `<script>` tag. 8 vertical sections with a fixed top nav that highlights the active section on scroll. IntersectionObserver triggers fade-in animations as sections enter the viewport.
|
||||
|
||||
**Tech Stack:** HTML5, CSS3 (custom properties, grid, flexbox), vanilla JS (IntersectionObserver, scroll spy), Google Fonts (Noto Sans SC + JetBrains Mono)
|
||||
|
||||
---
|
||||
|
||||
## File Map
|
||||
|
||||
| File | Action | Purpose |
|
||||
|------|--------|---------|
|
||||
| `boss-report.html` | **CREATE** (project root) | The single deliverable — complete self-contained report |
|
||||
|
||||
---
|
||||
|
||||
### Task 1: HTML skeleton + visual system + fixed nav
|
||||
|
||||
**Files:**
|
||||
- Create: `boss-report.html`
|
||||
|
||||
- [ ] **Step 1: Create the HTML file with the base skeleton**
|
||||
|
||||
Create `C:\Projects\AIProjects\AIRegulations\AIRegulation-DocAnalysis-Demo\boss-report.html` with the following content:
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>AI+合规智能中枢 — 阶段汇报 2026.05</title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@400;500;700;900&family=JetBrains+Mono:wght@400;600&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
/* ── Reset & base ── */
|
||||
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
|
||||
:root {
|
||||
--bg: #0a0a12;
|
||||
--bg-card: #12121f;
|
||||
--bg-hover: #1a1a2e;
|
||||
--border: #2a2a40;
|
||||
--text: #ffffff;
|
||||
--text2: #c0c0d0;
|
||||
--text3: #9a9aaa;
|
||||
--accent: #e20074;
|
||||
--accent-dk: #be0060;
|
||||
--green: #00d4aa;
|
||||
--orange: #ff8800;
|
||||
--blue: #4a90d9;
|
||||
--radius: 12px;
|
||||
}
|
||||
|
||||
html { scroll-behavior: smooth; }
|
||||
|
||||
body {
|
||||
font-family: 'Noto Sans SC', 'Microsoft YaHei', sans-serif;
|
||||
background: var(--bg);
|
||||
color: var(--text);
|
||||
line-height: 1.6;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.mono { font-family: 'JetBrains Mono', monospace; }
|
||||
|
||||
/* ── Fixed nav ── */
|
||||
#nav {
|
||||
position: fixed; top: 0; left: 0; right: 0; z-index: 100;
|
||||
background: rgba(10,10,18,0.92);
|
||||
backdrop-filter: blur(12px);
|
||||
border-bottom: 1px solid var(--border);
|
||||
display: flex; align-items: center; justify-content: space-between;
|
||||
padding: 0 40px; height: 52px;
|
||||
}
|
||||
#nav .brand {
|
||||
font-size: 13px; font-weight: 700; color: var(--accent);
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
#nav ul {
|
||||
display: flex; gap: 4px; list-style: none;
|
||||
}
|
||||
#nav ul li a {
|
||||
display: block; padding: 6px 12px; border-radius: 6px;
|
||||
font-size: 12px; color: var(--text3); text-decoration: none;
|
||||
transition: background 0.2s, color 0.2s;
|
||||
}
|
||||
#nav ul li a:hover,
|
||||
#nav ul li a.active {
|
||||
background: var(--accent); color: #fff;
|
||||
}
|
||||
|
||||
/* ── Section wrapper ── */
|
||||
.section {
|
||||
padding: 100px 40px 80px;
|
||||
max-width: 1200px; margin: 0 auto;
|
||||
}
|
||||
|
||||
/* ── Fade-in animation ── */
|
||||
.fade-in {
|
||||
opacity: 0; transform: translateY(24px);
|
||||
transition: opacity 0.6s ease, transform 0.6s ease;
|
||||
}
|
||||
.fade-in.visible {
|
||||
opacity: 1; transform: translateY(0);
|
||||
}
|
||||
|
||||
/* ── Section label ── */
|
||||
.section-label {
|
||||
font-size: 11px; font-weight: 700; letter-spacing: 2px;
|
||||
color: var(--accent); text-transform: uppercase;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
/* ── Section title ── */
|
||||
.section-title {
|
||||
font-size: 32px; font-weight: 900; color: var(--text);
|
||||
margin-bottom: 8px; line-height: 1.2;
|
||||
}
|
||||
|
||||
.section-sub {
|
||||
font-size: 15px; color: var(--text3); margin-bottom: 48px;
|
||||
}
|
||||
|
||||
/* ── Divider line ── */
|
||||
.divider {
|
||||
height: 1px; background: var(--border);
|
||||
max-width: 1200px; margin: 0 auto;
|
||||
}
|
||||
|
||||
/* ── Scrollbar ── */
|
||||
::-webkit-scrollbar { width: 6px; }
|
||||
::-webkit-scrollbar-track { background: transparent; }
|
||||
::-webkit-scrollbar-thumb { background: var(--accent); border-radius: 3px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- ── Fixed Nav ── -->
|
||||
<nav id="nav">
|
||||
<div class="brand">AI+合规智能中枢</div>
|
||||
<ul>
|
||||
<li><a href="#hero">概览</a></li>
|
||||
<li><a href="#background">背景</a></li>
|
||||
<li><a href="#progress">进展</a></li>
|
||||
<li><a href="#architecture">架构</a></li>
|
||||
<li><a href="#demo">功能</a></li>
|
||||
<li><a href="#value">价值</a></li>
|
||||
<li><a href="#roadmap">路线图</a></li>
|
||||
<li><a href="#next">下一步</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<!-- Sections will be added in subsequent tasks -->
|
||||
|
||||
<script>
|
||||
// Scroll spy
|
||||
const sections = document.querySelectorAll('section[id]');
|
||||
const navLinks = document.querySelectorAll('#nav ul li a');
|
||||
|
||||
const observer = new IntersectionObserver((entries) => {
|
||||
entries.forEach(entry => {
|
||||
if (entry.isIntersecting) {
|
||||
navLinks.forEach(a => a.classList.remove('active'));
|
||||
const active = document.querySelector(`#nav a[href="#${entry.target.id}"]`);
|
||||
if (active) active.classList.add('active');
|
||||
}
|
||||
});
|
||||
}, { threshold: 0.3 });
|
||||
|
||||
sections.forEach(s => observer.observe(s));
|
||||
|
||||
// Fade-in
|
||||
const fadeObserver = new IntersectionObserver((entries) => {
|
||||
entries.forEach(entry => {
|
||||
if (entry.isIntersecting) {
|
||||
entry.target.classList.add('visible');
|
||||
fadeObserver.unobserve(entry.target);
|
||||
}
|
||||
});
|
||||
}, { threshold: 0.1 });
|
||||
|
||||
document.querySelectorAll('.fade-in').forEach(el => fadeObserver.observe(el));
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Open in browser to verify nav renders**
|
||||
|
||||
Open `boss-report.html` in a browser. Expected: dark background page with a fixed top nav bar showing "AI+合规智能中枢" on the left and 8 nav links on the right. Page body should be empty below the nav.
|
||||
|
||||
---
|
||||
|
||||
### Task 2: Section 1 — Hero 封面
|
||||
|
||||
**Files:**
|
||||
- Modify: `boss-report.html` — add hero section before `<script>` tag
|
||||
|
||||
- [ ] **Step 1: Add Hero section HTML**
|
||||
|
||||
Insert the following after the `<!-- Sections will be added in subsequent tasks -->` comment:
|
||||
|
||||
```html
|
||||
<!-- ── S1: Hero ── -->
|
||||
<section id="hero" style="min-height:100vh; display:flex; align-items:center; position:relative; overflow:hidden;">
|
||||
<!-- Background glow -->
|
||||
<div style="position:absolute; top:50%; left:50%; transform:translate(-50%,-50%); width:600px; height:600px; background:radial-gradient(circle, rgba(226,0,116,0.12) 0%, transparent 70%); pointer-events:none;"></div>
|
||||
<!-- Grid pattern -->
|
||||
<div style="position:absolute; inset:0; background-image:linear-gradient(var(--border) 1px, transparent 1px), linear-gradient(90deg, var(--border) 1px, transparent 1px); background-size:60px 60px; opacity:0.3; pointer-events:none;"></div>
|
||||
|
||||
<div class="section fade-in" style="width:100%; padding-top:52px;">
|
||||
<!-- Tag -->
|
||||
<div style="display:inline-flex; align-items:center; gap:8px; background:rgba(226,0,116,0.12); border:1px solid rgba(226,0,116,0.3); border-radius:20px; padding:6px 16px; margin-bottom:32px;">
|
||||
<span style="width:6px;height:6px;border-radius:50%;background:var(--accent);display:inline-block;animation:pulse 2s infinite;"></span>
|
||||
<span class="mono" style="font-size:11px; color:var(--accent); letter-spacing:1px;">INTERNAL · AI 合规项目组 · 2026.05</span>
|
||||
</div>
|
||||
|
||||
<!-- Title -->
|
||||
<h1 style="font-size:clamp(36px,5vw,64px); font-weight:900; line-height:1.1; margin-bottom:16px;">
|
||||
AI + 合规智能中枢<br>
|
||||
<span style="color:var(--accent);">阶段性进展汇报</span>
|
||||
</h1>
|
||||
<p style="font-size:18px; color:var(--text2); max-width:640px; margin-bottom:60px;">
|
||||
基于 RAG 的多模块法规合规智能平台 — EMS/EHS 合规响应效率提升,降低人工成本
|
||||
</p>
|
||||
|
||||
<!-- KPI cards -->
|
||||
<div style="display:grid; grid-template-columns:repeat(3,1fr); gap:20px; max-width:720px;">
|
||||
<div class="fade-in" style="background:var(--bg-card); border:1px solid var(--border); border-top:3px solid var(--accent); border-radius:var(--radius); padding:24px 28px;">
|
||||
<div class="mono" style="font-size:48px; font-weight:700; color:var(--accent); line-height:1;">5</div>
|
||||
<div style="font-size:13px; color:var(--text3); margin-top:6px;">功能模块<br>已完成/开发中</div>
|
||||
</div>
|
||||
<div class="fade-in" style="background:var(--bg-card); border:1px solid var(--border); border-top:3px solid var(--green); border-radius:var(--radius); padding:24px 28px;">
|
||||
<div class="mono" style="font-size:48px; font-weight:700; color:var(--green); line-height:1;">17+</div>
|
||||
<div style="font-size:13px; color:var(--text3); margin-top:6px;">API 接口<br>已设计并文档化</div>
|
||||
</div>
|
||||
<div class="fade-in" style="background:var(--bg-card); border:1px solid var(--border); border-top:3px solid var(--orange); border-radius:var(--radius); padding:24px 28px;">
|
||||
<div class="mono" style="font-size:48px; font-weight:700; color:var(--orange); line-height:1;">6+</div>
|
||||
<div style="font-size:13px; color:var(--text3); margin-top:6px;">法规来源<br>接入覆盖</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Scroll hint -->
|
||||
<div style="margin-top:60px; display:flex; align-items:center; gap:10px; color:var(--text3); font-size:13px;">
|
||||
<div style="width:1px; height:40px; background:linear-gradient(to bottom, transparent, var(--accent));"></div>
|
||||
向下滚动查看详情
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="divider"></div>
|
||||
```
|
||||
|
||||
Add this keyframe to the `<style>` block (before the closing `</style>`):
|
||||
|
||||
```css
|
||||
@keyframes pulse {
|
||||
0%, 100% { opacity: 1; }
|
||||
50% { opacity: 0.4; }
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Verify in browser**
|
||||
|
||||
Refresh `boss-report.html`. Expected: Full-height dark hero section with grid background, pink glow, large title with magenta accent, 3 KPI cards (5 / 17+ / 6+), and a scroll hint at the bottom.
|
||||
|
||||
---
|
||||
|
||||
### Task 3: Section 2 — 项目背景与痛点
|
||||
|
||||
**Files:**
|
||||
- Modify: `boss-report.html` — add background section after the hero divider
|
||||
|
||||
- [ ] **Step 1: Add background section HTML**
|
||||
|
||||
Insert the following after the hero `<div class="divider"></div>`:
|
||||
|
||||
```html
|
||||
<!-- ── S2: Background ── -->
|
||||
<section id="background">
|
||||
<div class="section fade-in">
|
||||
<div class="section-label">项目背景</div>
|
||||
<h2 class="section-title">为什么要做这个系统?</h2>
|
||||
<p class="section-sub">当前汽车行业合规管理面临三大核心痛点,传统人工方式已无法满足需求</p>
|
||||
|
||||
<div style="display:grid; grid-template-columns:repeat(3,1fr); gap:20px;">
|
||||
|
||||
<div class="fade-in" style="background:var(--bg-card); border:1px solid var(--border); border-radius:var(--radius); padding:28px; position:relative; overflow:hidden;">
|
||||
<div style="position:absolute; top:0; left:0; right:0; height:3px; background:linear-gradient(90deg,var(--accent),var(--accent-dk));"></div>
|
||||
<div style="font-size:36px; margin-bottom:16px;">📋</div>
|
||||
<h3 style="font-size:18px; font-weight:700; color:var(--text); margin-bottom:10px;">法规碎片化</h3>
|
||||
<p style="font-size:14px; color:var(--text2); line-height:1.7;">
|
||||
GB、MIIT、UN-ECE、IATF 16949、ISO 45001、EUR-Lex 等多源法规并存,更新频繁,人工跟踪极易遗漏,合规窗口期短。
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="fade-in" style="background:var(--bg-card); border:1px solid var(--border); border-radius:var(--radius); padding:28px; position:relative; overflow:hidden;">
|
||||
<div style="position:absolute; top:0; left:0; right:0; height:3px; background:linear-gradient(90deg,var(--orange),#ff5500);"></div>
|
||||
<div style="font-size:36px; margin-bottom:16px;">⏱️</div>
|
||||
<h3 style="font-size:18px; font-weight:700; color:var(--text); margin-bottom:10px;">响应周期长</h3>
|
||||
<p style="font-size:14px; color:var(--text2); line-height:1.7;">
|
||||
从法规发布到内部解读、影响评估、整改计划,人工流程往往需要数周,无法满足快速迭代的合规要求。
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="fade-in" style="background:var(--bg-card); border:1px solid var(--border); border-radius:var(--radius); padding:28px; position:relative; overflow:hidden;">
|
||||
<div style="position:absolute; top:0; left:0; right:0; height:3px; background:linear-gradient(90deg,var(--green),#00a080);"></div>
|
||||
<div style="font-size:36px; margin-bottom:16px;">💼</div>
|
||||
<h3 style="font-size:18px; font-weight:700; color:var(--text); margin-bottom:10px;">人工成本高</h3>
|
||||
<p style="font-size:14px; color:var(--text2); line-height:1.7;">
|
||||
合规专家大量时间消耗在文档检索、条款比对、报告撰写等重复性工作上,高价值判断时间被严重压缩。
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="divider"></div>
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Verify in browser**
|
||||
|
||||
Refresh. Expected: Three cards with colored top borders (magenta / orange / green), emoji icons, Chinese titles and descriptions. Each card should animate in on scroll.
|
||||
|
||||
---
|
||||
|
||||
### Task 4: Section 3 — 已完成进展
|
||||
|
||||
**Files:**
|
||||
- Modify: `boss-report.html` — add progress section
|
||||
|
||||
- [ ] **Step 1: Add progress section HTML**
|
||||
|
||||
Insert after the background `<div class="divider"></div>`:
|
||||
|
||||
```html
|
||||
<!-- ── S3: Progress ── -->
|
||||
<section id="progress">
|
||||
<div class="section fade-in">
|
||||
<div class="section-label">阶段成果</div>
|
||||
<h2 class="section-title">已完成的工作</h2>
|
||||
<p class="section-sub">5 个核心功能模块,覆盖从法规感知到报告输出的完整合规链路</p>
|
||||
|
||||
<div style="display:grid; grid-template-columns:repeat(1,1fr); gap:16px;">
|
||||
|
||||
<!-- Module 1 -->
|
||||
<div class="fade-in" style="background:var(--bg-card); border:1px solid var(--border); border-radius:var(--radius); padding:24px 28px; display:grid; grid-template-columns:auto 1fr auto; gap:20px; align-items:start;">
|
||||
<div style="width:48px; height:48px; border-radius:10px; background:rgba(226,0,116,0.15); border:1px solid rgba(226,0,116,0.3); display:flex; align-items:center; justify-content:center; font-size:22px;">📡</div>
|
||||
<div>
|
||||
<div style="display:flex; align-items:center; gap:10px; margin-bottom:8px;">
|
||||
<h3 style="font-size:16px; font-weight:700;">法规感知模块</h3>
|
||||
<span class="mono" style="font-size:10px; background:rgba(0,212,170,0.15); color:var(--green); border:1px solid rgba(0,212,170,0.3); padding:2px 8px; border-radius:4px;">✓ 已完成</span>
|
||||
</div>
|
||||
<ul style="font-size:13px; color:var(--text2); line-height:2; list-style:none;">
|
||||
<li>▸ 接入 MIIT、UN-ECE、ISO、国标委、EUR-Lex、IATF 六大法规来源,实时抓取动态</li>
|
||||
<li>▸ 支持按来源/影响等级(高/中/低)过滤,KPI 统计卡(总计/高影响/近90天)</li>
|
||||
<li>▸ 法规详情侧边面板,关联 AI 影响分析与条款摘要</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="mono" style="font-size:11px; color:var(--text3); white-space:nowrap;">模块 01/05</div>
|
||||
</div>
|
||||
|
||||
<!-- Module 2 -->
|
||||
<div class="fade-in" style="background:var(--bg-card); border:1px solid var(--border); border-radius:var(--radius); padding:24px 28px; display:grid; grid-template-columns:auto 1fr auto; gap:20px; align-items:start;">
|
||||
<div style="width:48px; height:48px; border-radius:10px; background:rgba(74,144,217,0.15); border:1px solid rgba(74,144,217,0.3); display:flex; align-items:center; justify-content:center; font-size:22px;">📄</div>
|
||||
<div>
|
||||
<div style="display:flex; align-items:center; gap:10px; margin-bottom:8px;">
|
||||
<h3 style="font-size:16px; font-weight:700;">文档分析模块</h3>
|
||||
<span class="mono" style="font-size:10px; background:rgba(0,212,170,0.15); color:var(--green); border:1px solid rgba(0,212,170,0.3); padding:2px 8px; border-radius:4px;">✓ 已完成</span>
|
||||
</div>
|
||||
<ul style="font-size:13px; color:var(--text2); line-height:2; list-style:none;">
|
||||
<li>▸ PDF/Word 文档上传解析,支持阿里云 DocMind OCR + MinerU 双引擎</li>
|
||||
<li>▸ RAG 检索增强问答:BM25 稀疏 + 向量混合检索,Cross-Encoder 精排</li>
|
||||
<li>▸ 文档知识库管理,Workspace 隔离,支持多文档联合问答</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="mono" style="font-size:11px; color:var(--text3); white-space:nowrap;">模块 02/05</div>
|
||||
</div>
|
||||
|
||||
<!-- Module 3 -->
|
||||
<div class="fade-in" style="background:var(--bg-card); border:1px solid var(--border); border-radius:var(--radius); padding:24px 28px; display:grid; grid-template-columns:auto 1fr auto; gap:20px; align-items:start;">
|
||||
<div style="width:48px; height:48px; border-radius:10px; background:rgba(255,136,0,0.15); border:1px solid rgba(255,136,0,0.3); display:flex; align-items:center; justify-content:center; font-size:22px;">🏭</div>
|
||||
<div>
|
||||
<div style="display:flex; align-items:center; gap:10px; margin-bottom:8px;">
|
||||
<h3 style="font-size:16px; font-weight:700;">EHS 合规模块</h3>
|
||||
<span class="mono" style="font-size:10px; background:rgba(255,136,0,0.15); color:var(--orange); border:1px solid rgba(255,136,0,0.3); padding:2px 8px; border-radius:4px;">⟳ 进行中</span>
|
||||
</div>
|
||||
<ul style="font-size:13px; color:var(--text2); line-height:2; list-style:none;">
|
||||
<li>▸ EHS 风险评估引擎,对接 ISO 45001 PDCA 体系,SIF 重伤风险识别</li>
|
||||
<li>▸ 环境/职业健康/安全三维度合规检查,结构化整改建议生成</li>
|
||||
<li>▸ 合规状态仪表盘,风险等级可视化,历史趋势追踪</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="mono" style="font-size:11px; color:var(--text3); white-space:nowrap;">模块 03/05</div>
|
||||
</div>
|
||||
|
||||
<!-- Module 4 -->
|
||||
<div class="fade-in" style="background:var(--bg-card); border:1px solid var(--border); border-radius:var(--radius); padding:24px 28px; display:grid; grid-template-columns:auto 1fr auto; gap:20px; align-items:start;">
|
||||
<div style="width:48px; height:48px; border-radius:10px; background:rgba(0,212,170,0.15); border:1px solid rgba(0,212,170,0.3); display:flex; align-items:center; justify-content:center; font-size:22px;">🔌</div>
|
||||
<div>
|
||||
<div style="display:flex; align-items:center; gap:10px; margin-bottom:8px;">
|
||||
<h3 style="font-size:16px; font-weight:700;">API 集成模块</h3>
|
||||
<span class="mono" style="font-size:10px; background:rgba(0,212,170,0.15); color:var(--green); border:1px solid rgba(0,212,170,0.3); padding:2px 8px; border-radius:4px;">✓ 已完成</span>
|
||||
</div>
|
||||
<ul style="font-size:13px; color:var(--text2); line-height:2; list-style:none;">
|
||||
<li>▸ 17+ REST API 接口完整设计,涵盖知识库、合规检查、订阅推送全链路</li>
|
||||
<li>▸ RBAC 权限模型,5 角色分级管控(管理员/合规专员/EHS专员/审核员/查看员)</li>
|
||||
<li>▸ 预留 PLM、ERP、OA、MES 系统集成接口,支持企业现有系统接入</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="mono" style="font-size:11px; color:var(--text3); white-space:nowrap;">模块 04/05</div>
|
||||
</div>
|
||||
|
||||
<!-- Module 5 -->
|
||||
<div class="fade-in" style="background:var(--bg-card); border:1px solid var(--border); border-radius:var(--radius); padding:24px 28px; display:grid; grid-template-columns:auto 1fr auto; gap:20px; align-items:start;">
|
||||
<div style="width:48px; height:48px; border-radius:10px; background:rgba(123,104,238,0.15); border:1px solid rgba(123,104,238,0.3); display:flex; align-items:center; justify-content:center; font-size:22px;">📊</div>
|
||||
<div>
|
||||
<div style="display:flex; align-items:center; gap:10px; margin-bottom:8px;">
|
||||
<h3 style="font-size:16px; font-weight:700;">报告生成模块</h3>
|
||||
<span class="mono" style="font-size:10px; background:rgba(255,136,0,0.15); color:var(--orange); border:1px solid rgba(255,136,0,0.3); padding:2px 8px; border-radius:4px;">⟳ 进行中</span>
|
||||
</div>
|
||||
<ul style="font-size:13px; color:var(--text2); line-height:2; list-style:none;">
|
||||
<li>▸ AI 自动生成合规分析报告,支持 PDF/Word/Excel 多格式导出</li>
|
||||
<li>▸ 报告模板引擎,适配不同法规体系(车辆安全/数据合规/EHS/碳排放)</li>
|
||||
<li>▸ 报告版本管理与审批流,支持与 SharePoint/Confluence 协同</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="mono" style="font-size:11px; color:var(--text3); white-space:nowrap;">模块 05/05</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="divider"></div>
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Verify in browser**
|
||||
|
||||
Refresh. Expected: 5 module rows, each with colored icon box, title with status badge (绿色"✓ 已完成" or 橙色"⟳ 进行中"), and 3 bullet points of detail.
|
||||
|
||||
---
|
||||
|
||||
### Task 5: Section 4 — 技术架构概览
|
||||
|
||||
**Files:**
|
||||
- Modify: `boss-report.html` — add architecture section
|
||||
|
||||
- [ ] **Step 1: Add architecture section HTML**
|
||||
|
||||
Insert after the progress `<div class="divider"></div>`:
|
||||
|
||||
```html
|
||||
<!-- ── S4: Architecture ── -->
|
||||
<section id="architecture">
|
||||
<div class="section fade-in">
|
||||
<div class="section-label">技术架构</div>
|
||||
<h2 class="section-title">系统分层架构</h2>
|
||||
<p class="section-sub">清洁架构 + Ports & Adapters,5 层分离,高内聚低耦合,可独立替换各层实现</p>
|
||||
|
||||
<div style="display:flex; flex-direction:column; gap:10px; max-width:960px; margin:0 auto;">
|
||||
|
||||
<!-- Layer 1: User -->
|
||||
<div class="fade-in" style="border-radius:10px; border:1px solid rgba(226,0,116,0.4); background:rgba(226,0,116,0.06); overflow:hidden;">
|
||||
<div style="padding:12px 20px; background:linear-gradient(135deg,#b0005a,#e20074); display:flex; align-items:center; gap:12px;">
|
||||
<span style="font-size:18px;">👥</span>
|
||||
<span style="font-weight:700; font-size:15px;">用户层</span>
|
||||
<span style="font-size:11px; opacity:0.75;">合规专员 / EHS专员 / 审核员 / 管理员 / 查看员</span>
|
||||
</div>
|
||||
<div style="padding:14px 20px; display:flex; gap:10px; flex-wrap:wrap;">
|
||||
<span style="background:rgba(226,0,116,0.12); border:1px solid rgba(226,0,116,0.25); border-radius:6px; padding:4px 12px; font-size:12px; color:#f04090;">法规感知</span>
|
||||
<span style="background:rgba(226,0,116,0.12); border:1px solid rgba(226,0,116,0.25); border-radius:6px; padding:4px 12px; font-size:12px; color:#f04090;">文档分析</span>
|
||||
<span style="background:rgba(226,0,116,0.12); border:1px solid rgba(226,0,116,0.25); border-radius:6px; padding:4px 12px; font-size:12px; color:#f04090;">EHS合规</span>
|
||||
<span style="background:rgba(226,0,116,0.12); border:1px solid rgba(226,0,116,0.25); border-radius:6px; padding:4px 12px; font-size:12px; color:#f04090;">API集成</span>
|
||||
<span style="background:rgba(226,0,116,0.12); border:1px solid rgba(226,0,116,0.25); border-radius:6px; padding:4px 12px; font-size:12px; color:#f04090;">报告生成</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="text-align:center; color:var(--accent); font-size:18px;">↕</div>
|
||||
|
||||
<!-- Layer 2: Frontend -->
|
||||
<div class="fade-in" style="border-radius:10px; border:1px solid rgba(0,212,170,0.4); background:rgba(0,212,170,0.06); overflow:hidden;">
|
||||
<div style="padding:12px 20px; background:linear-gradient(135deg,#00a080,#00d4aa); display:flex; align-items:center; gap:12px;">
|
||||
<span style="font-size:18px;">🖥️</span>
|
||||
<span style="font-weight:700; font-size:15px;">前端层</span>
|
||||
<span style="font-size:11px; opacity:0.75;">React 19 · TypeScript · Vite · React Router v7</span>
|
||||
</div>
|
||||
<div style="padding:14px 20px; display:flex; gap:10px; flex-wrap:wrap;">
|
||||
<span style="background:rgba(0,212,170,0.1); border:1px solid rgba(0,212,170,0.25); border-radius:6px; padding:4px 12px; font-size:12px; color:var(--green);">KeepAlive 路由</span>
|
||||
<span style="background:rgba(0,212,170,0.1); border:1px solid rgba(0,212,170,0.25); border-radius:6px; padding:4px 12px; font-size:12px; color:var(--green);">三主题系统 (Dark/Dim/Light)</span>
|
||||
<span style="background:rgba(0,212,170,0.1); border:1px solid rgba(0,212,170,0.25); border-radius:6px; padding:4px 12px; font-size:12px; color:var(--green);">shadcn/ui 组件库</span>
|
||||
<span style="background:rgba(0,212,170,0.1); border:1px solid rgba(0,212,170,0.25); border-radius:6px; padding:4px 12px; font-size:12px; color:var(--green);">Tailwind v4</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="text-align:center; color:var(--accent); font-size:18px;">↕</div>
|
||||
|
||||
<!-- Layer 3: API -->
|
||||
<div class="fade-in" style="border-radius:10px; border:1px solid rgba(74,144,217,0.4); background:rgba(74,144,217,0.06); overflow:hidden;">
|
||||
<div style="padding:12px 20px; background:linear-gradient(135deg,#2060a0,#4a90d9); display:flex; align-items:center; gap:12px;">
|
||||
<span style="font-size:18px;">⚡</span>
|
||||
<span style="font-weight:700; font-size:15px;">API 层</span>
|
||||
<span style="font-size:11px; opacity:0.75;">FastAPI · kbmp-service · mcp-server · Worker</span>
|
||||
</div>
|
||||
<div style="padding:14px 20px; display:flex; gap:10px; flex-wrap:wrap;">
|
||||
<span style="background:rgba(74,144,217,0.1); border:1px solid rgba(74,144,217,0.25); border-radius:6px; padding:4px 12px; font-size:12px; color:var(--blue);">知识库管理 API</span>
|
||||
<span style="background:rgba(74,144,217,0.1); border:1px solid rgba(74,144,217,0.25); border-radius:6px; padding:4px 12px; font-size:12px; color:var(--blue);">合规检查 API</span>
|
||||
<span style="background:rgba(74,144,217,0.1); border:1px solid rgba(74,144,217,0.25); border-radius:6px; padding:4px 12px; font-size:12px; color:var(--blue);">文档解析 API</span>
|
||||
<span style="background:rgba(74,144,217,0.1); border:1px solid rgba(74,144,217,0.25); border-radius:6px; padding:4px 12px; font-size:12px; color:var(--blue);">检索问答 API</span>
|
||||
<span style="background:rgba(74,144,217,0.1); border:1px solid rgba(74,144,217,0.25); border-radius:6px; padding:4px 12px; font-size:12px; color:var(--blue);">订阅推送 API</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="text-align:center; color:var(--accent); font-size:18px;">↕</div>
|
||||
|
||||
<!-- Layer 4: AI Engine -->
|
||||
<div class="fade-in" style="border-radius:10px; border:1px solid rgba(255,136,0,0.4); background:rgba(255,136,0,0.06); overflow:hidden;">
|
||||
<div style="padding:12px 20px; background:linear-gradient(135deg,#c05000,#ff8800); display:flex; align-items:center; gap:12px;">
|
||||
<span style="font-size:18px;">🧠</span>
|
||||
<span style="font-weight:700; font-size:15px;">AI 引擎层</span>
|
||||
<span style="font-size:11px; opacity:0.75;">RAG Pipeline · LLM · Embedding · Reranker</span>
|
||||
</div>
|
||||
<div style="padding:14px 20px; display:flex; gap:10px; flex-wrap:wrap;">
|
||||
<span style="background:rgba(255,136,0,0.1); border:1px solid rgba(255,136,0,0.25); border-radius:6px; padding:4px 12px; font-size:12px; color:var(--orange);">Qwen / DeepSeek LLM</span>
|
||||
<span style="background:rgba(255,136,0,0.1); border:1px solid rgba(255,136,0,0.25); border-radius:6px; padding:4px 12px; font-size:12px; color:var(--orange);">BM25 稀疏检索</span>
|
||||
<span style="background:rgba(255,136,0,0.1); border:1px solid rgba(255,136,0,0.25); border-radius:6px; padding:4px 12px; font-size:12px; color:var(--orange);">向量语义检索</span>
|
||||
<span style="background:rgba(255,136,0,0.1); border:1px solid rgba(255,136,0,0.25); border-radius:6px; padding:4px 12px; font-size:12px; color:var(--orange);">Cross-Encoder 精排</span>
|
||||
<span style="background:rgba(255,136,0,0.1); border:1px solid rgba(255,136,0,0.25); border-radius:6px; padding:4px 12px; font-size:12px; color:var(--orange);">阿里云 DocMind OCR</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="text-align:center; color:var(--accent); font-size:18px;">↕</div>
|
||||
|
||||
<!-- Layer 5: Infrastructure -->
|
||||
<div class="fade-in" style="border-radius:10px; border:1px solid rgba(123,104,238,0.4); background:rgba(123,104,238,0.06); overflow:hidden;">
|
||||
<div style="padding:12px 20px; background:linear-gradient(135deg,#5040b0,#7b68ee); display:flex; align-items:center; gap:12px;">
|
||||
<span style="font-size:18px;">🗄️</span>
|
||||
<span style="font-weight:700; font-size:15px;">基础设施层</span>
|
||||
<span style="font-size:11px; opacity:0.75;">Milvus · MySQL · S3/OSS · Prometheus · Grafana</span>
|
||||
</div>
|
||||
<div style="padding:14px 20px; display:flex; gap:10px; flex-wrap:wrap;">
|
||||
<span style="background:rgba(123,104,238,0.1); border:1px solid rgba(123,104,238,0.25); border-radius:6px; padding:4px 12px; font-size:12px; color:#9b8cf0;">Milvus 向量数据库</span>
|
||||
<span style="background:rgba(123,104,238,0.1); border:1px solid rgba(123,104,238,0.25); border-radius:6px; padding:4px 12px; font-size:12px; color:#9b8cf0;">MySQL 结构化存储</span>
|
||||
<span style="background:rgba(123,104,238,0.1); border:1px solid rgba(123,104,238,0.25); border-radius:6px; padding:4px 12px; font-size:12px; color:#9b8cf0;">对象存储 (文档/Markdown)</span>
|
||||
<span style="background:rgba(123,104,238,0.1); border:1px solid rgba(123,104,238,0.25); border-radius:6px; padding:4px 12px; font-size:12px; color:#9b8cf0;">Prometheus + Grafana</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="divider"></div>
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Verify in browser**
|
||||
|
||||
Refresh. Expected: 5 colored layered boxes with arrows between them, each showing layer name, tech stack, and module tags.
|
||||
|
||||
---
|
||||
|
||||
### Task 6: Section 5 — Demo 核心功能
|
||||
|
||||
**Files:**
|
||||
- Modify: `boss-report.html` — add demo section
|
||||
|
||||
- [ ] **Step 1: Add demo section HTML**
|
||||
|
||||
Insert after the architecture `<div class="divider"></div>`:
|
||||
|
||||
```html
|
||||
<!-- ── S5: Demo ── -->
|
||||
<section id="demo">
|
||||
<div class="section fade-in">
|
||||
<div class="section-label">产品演示</div>
|
||||
<h2 class="section-title">核心功能一览</h2>
|
||||
<p class="section-sub">Demo 已部署,以下为五大核心功能模块的界面与能力说明</p>
|
||||
|
||||
<div style="display:grid; grid-template-columns:repeat(3,1fr); gap:20px;">
|
||||
|
||||
<div class="fade-in" style="background:var(--bg-card); border:1px solid var(--border); border-radius:var(--radius); overflow:hidden;">
|
||||
<div style="height:140px; background:linear-gradient(135deg,#1a0a20,#2a1035); display:flex; align-items:center; justify-content:center; position:relative; border-bottom:1px solid var(--border);">
|
||||
<div style="position:absolute; inset:0; display:flex; align-items:center; justify-content:center; flex-direction:column; gap:8px;">
|
||||
<div style="font-size:40px;">📡</div>
|
||||
<div style="display:flex; gap:6px;">
|
||||
<span style="width:8px;height:8px;border-radius:50%;background:#d64545;"></span>
|
||||
<span style="width:8px;height:8px;border-radius:50%;background:#ff8800;"></span>
|
||||
<span style="width:8px;height:8px;border-radius:50%;background:#00d4aa;"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div style="position:absolute; top:10px; right:10px; background:rgba(0,212,170,0.2); color:var(--green); font-size:10px; padding:2px 8px; border-radius:4px; font-weight:700;">LIVE</div>
|
||||
</div>
|
||||
<div style="padding:18px 20px;">
|
||||
<h3 style="font-size:15px; font-weight:700; margin-bottom:8px;">法规感知</h3>
|
||||
<p style="font-size:13px; color:var(--text2); line-height:1.6;">实时监控六大法规源,高/中/低影响分级,支持过滤筛选,点击查看 AI 解读</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="fade-in" style="background:var(--bg-card); border:1px solid var(--border); border-radius:var(--radius); overflow:hidden;">
|
||||
<div style="height:140px; background:linear-gradient(135deg,#0a1020,#101a35); display:flex; align-items:center; justify-content:center; position:relative; border-bottom:1px solid var(--border);">
|
||||
<div style="font-size:40px;">💬</div>
|
||||
<div style="position:absolute; bottom:12px; left:12px; right:12px; background:rgba(74,144,217,0.15); border:1px solid rgba(74,144,217,0.3); border-radius:6px; padding:6px 10px; font-size:11px; color:var(--blue);">"GB 18384 对我们的 BMS 设计有什么影响?"</div>
|
||||
</div>
|
||||
<div style="padding:18px 20px;">
|
||||
<h3 style="font-size:15px; font-weight:700; margin-bottom:8px;">文档分析 Q&A</h3>
|
||||
<p style="font-size:13px; color:var(--text2); line-height:1.6;">上传法规/技术文档,AI 即可回答专业问题,引用原文段落,支持追问</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="fade-in" style="background:var(--bg-card); border:1px solid var(--border); border-radius:var(--radius); overflow:hidden;">
|
||||
<div style="height:140px; background:linear-gradient(135deg,#0a1808,#101f0f); display:flex; align-items:center; justify-content:center; position:relative; border-bottom:1px solid var(--border);">
|
||||
<div style="font-size:40px;">🏭</div>
|
||||
<div style="position:absolute; top:10px; left:10px; background:rgba(255,68,68,0.2); color:#ff6b6b; font-size:10px; padding:2px 8px; border-radius:4px; font-weight:700;">⚠ 高风险</div>
|
||||
</div>
|
||||
<div style="padding:18px 20px;">
|
||||
<h3 style="font-size:15px; font-weight:700; margin-bottom:8px;">EHS 合规检查</h3>
|
||||
<p style="font-size:13px; color:var(--text2); line-height:1.6;">上传 EHS 文档,自动识别风险条款,生成整改建议,对标 ISO 45001</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="fade-in" style="background:var(--bg-card); border:1px solid var(--border); border-radius:var(--radius); overflow:hidden;">
|
||||
<div style="height:140px; background:linear-gradient(135deg,#081510,#0f1f18); display:flex; align-items:center; justify-content:center; position:relative; border-bottom:1px solid var(--border);">
|
||||
<div style="font-size:40px;">🔌</div>
|
||||
<div style="position:absolute; bottom:12px; left:12px; right:12px; display:flex; gap:6px;">
|
||||
<span style="background:rgba(0,212,170,0.15); color:var(--green); font-size:10px; padding:2px 8px; border-radius:4px;">PLM</span>
|
||||
<span style="background:rgba(0,212,170,0.15); color:var(--green); font-size:10px; padding:2px 8px; border-radius:4px;">ERP</span>
|
||||
<span style="background:rgba(0,212,170,0.15); color:var(--green); font-size:10px; padding:2px 8px; border-radius:4px;">OA</span>
|
||||
<span style="background:rgba(0,212,170,0.15); color:var(--green); font-size:10px; padding:2px 8px; border-radius:4px;">MES</span>
|
||||
</div>
|
||||
</div>
|
||||
<div style="padding:18px 20px;">
|
||||
<h3 style="font-size:15px; font-weight:700; margin-bottom:8px;">系统集成</h3>
|
||||
<p style="font-size:13px; color:var(--text2); line-height:1.6;">RBAC 权限管控,REST API 开放,预留企业系统对接接口,支持 Webhook 订阅</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="fade-in" style="background:var(--bg-card); border:1px solid var(--border); border-radius:var(--radius); overflow:hidden; grid-column:span 2;">
|
||||
<div style="height:140px; background:linear-gradient(135deg,#101018,#181830); display:flex; align-items:center; justify-content:center; position:relative; border-bottom:1px solid var(--border);">
|
||||
<div style="font-size:40px;">📊</div>
|
||||
<div style="position:absolute; bottom:12px; right:12px; display:flex; gap:8px;">
|
||||
<span style="background:rgba(226,0,116,0.15); color:var(--accent); font-size:10px; padding:2px 8px; border-radius:4px;">PDF</span>
|
||||
<span style="background:rgba(226,0,116,0.15); color:var(--accent); font-size:10px; padding:2px 8px; border-radius:4px;">Word</span>
|
||||
<span style="background:rgba(226,0,116,0.15); color:var(--accent); font-size:10px; padding:2px 8px; border-radius:4px;">Excel</span>
|
||||
</div>
|
||||
</div>
|
||||
<div style="padding:18px 20px;">
|
||||
<h3 style="font-size:15px; font-weight:700; margin-bottom:8px;">合规报告生成</h3>
|
||||
<p style="font-size:13px; color:var(--text2); line-height:1.6;">AI 自动生成合规分析报告,多格式导出,支持模板定制,含版本管理与审批流</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="divider"></div>
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Verify in browser**
|
||||
|
||||
Refresh. Expected: 5 feature cards in a 3-column grid (last card spanning 2 columns), each with a dark-tinted preview area and description below.
|
||||
|
||||
---
|
||||
|
||||
### Task 7: Section 6 — 业务价值对比
|
||||
|
||||
**Files:**
|
||||
- Modify: `boss-report.html` — add value comparison section
|
||||
|
||||
- [ ] **Step 1: Add value section HTML**
|
||||
|
||||
Insert after the demo `<div class="divider"></div>`:
|
||||
|
||||
```html
|
||||
<!-- ── S6: Value ── -->
|
||||
<section id="value">
|
||||
<div class="section fade-in">
|
||||
<div class="section-label">业务价值</div>
|
||||
<h2 class="section-title">有与没有的差距</h2>
|
||||
<p class="section-sub">量化对比:AI 智能中枢 vs 传统人工合规方式</p>
|
||||
|
||||
<div style="display:grid; grid-template-columns:1fr auto 1fr; gap:0; align-items:stretch; max-width:960px; margin:0 auto 48px;">
|
||||
|
||||
<!-- Without -->
|
||||
<div class="fade-in" style="background:rgba(255,68,68,0.06); border:1px solid rgba(255,68,68,0.2); border-radius:12px 0 0 12px; padding:28px;">
|
||||
<div style="font-size:13px; font-weight:700; color:#ff6b6b; margin-bottom:20px; letter-spacing:1px;">❌ 传统人工方式</div>
|
||||
<ul style="list-style:none; display:flex; flex-direction:column; gap:16px;">
|
||||
<li style="font-size:14px; color:var(--text2);"><span style="color:#ff6b6b; font-weight:700;">数周</span> — 法规解读 + 影响评估周期</li>
|
||||
<li style="font-size:14px; color:var(--text2);"><span style="color:#ff6b6b; font-weight:700;">人工检索</span> — 依赖专家经验,易遗漏</li>
|
||||
<li style="font-size:14px; color:var(--text2);"><span style="color:#ff6b6b; font-weight:700;">碎片化</span> — 各系统数据孤岛,无法联动</li>
|
||||
<li style="font-size:14px; color:var(--text2);"><span style="color:#ff6b6b; font-weight:700;">高成本</span> — 合规专家时间大量消耗在重复工作</li>
|
||||
<li style="font-size:14px; color:var(--text2);"><span style="color:#ff6b6b; font-weight:700;">被动响应</span> — 法规变化后才开始评估</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Arrow -->
|
||||
<div style="display:flex; align-items:center; justify-content:center; padding:0 20px; background:var(--bg-card); border-top:1px solid var(--border); border-bottom:1px solid var(--border);">
|
||||
<div style="font-size:28px; color:var(--accent);">→</div>
|
||||
</div>
|
||||
|
||||
<!-- With -->
|
||||
<div class="fade-in" style="background:rgba(0,212,170,0.06); border:1px solid rgba(0,212,170,0.2); border-radius:0 12px 12px 0; padding:28px;">
|
||||
<div style="font-size:13px; font-weight:700; color:var(--green); margin-bottom:20px; letter-spacing:1px;">✅ AI+合规智能中枢</div>
|
||||
<ul style="list-style:none; display:flex; flex-direction:column; gap:16px;">
|
||||
<li style="font-size:14px; color:var(--text2);"><span style="color:var(--green); font-weight:700;">分钟级</span> — 法规发布即自动解读,影响秒级评估</li>
|
||||
<li style="font-size:14px; color:var(--text2);"><span style="color:var(--green); font-weight:700;">RAG 智能检索</span> — 语义理解,精准定位条款</li>
|
||||
<li style="font-size:14px; color:var(--text2);"><span style="color:var(--green); font-weight:700;">统一平台</span> — 多源法规、多系统数据融合</li>
|
||||
<li style="font-size:14px; color:var(--text2);"><span style="color:var(--green); font-weight:700;">降低重复劳动 70%+</span> — 专家聚焦高价值判断</li>
|
||||
<li style="font-size:14px; color:var(--text2);"><span style="color:var(--green); font-weight:700;">主动预警</span> — 订阅推送,法规变化即刻触达</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Metric highlights -->
|
||||
<div style="display:grid; grid-template-columns:repeat(4,1fr); gap:16px; max-width:960px; margin:0 auto;">
|
||||
<div class="fade-in" style="text-align:center; padding:24px; background:var(--bg-card); border:1px solid var(--border); border-radius:var(--radius);">
|
||||
<div class="mono" style="font-size:36px; font-weight:700; color:var(--accent);">70%+</div>
|
||||
<div style="font-size:12px; color:var(--text3); margin-top:6px;">重复性工作减少</div>
|
||||
</div>
|
||||
<div class="fade-in" style="text-align:center; padding:24px; background:var(--bg-card); border:1px solid var(--border); border-radius:var(--radius);">
|
||||
<div class="mono" style="font-size:36px; font-weight:700; color:var(--green);">分钟级</div>
|
||||
<div style="font-size:12px; color:var(--text3); margin-top:6px;">法规响应时间</div>
|
||||
</div>
|
||||
<div class="fade-in" style="text-align:center; padding:24px; background:var(--bg-card); border:1px solid var(--border); border-radius:var(--radius);">
|
||||
<div class="mono" style="font-size:36px; font-weight:700; color:var(--orange);">6+</div>
|
||||
<div style="font-size:12px; color:var(--text3); margin-top:6px;">法规源统一管理</div>
|
||||
</div>
|
||||
<div class="fade-in" style="text-align:center; padding:24px; background:var(--bg-card); border:1px solid var(--border); border-radius:var(--radius);">
|
||||
<div class="mono" style="font-size:36px; font-weight:700; color:var(--blue);">5</div>
|
||||
<div style="font-size:12px; color:var(--text3); margin-top:6px;">业务场景覆盖</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="divider"></div>
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Verify in browser**
|
||||
|
||||
Refresh. Expected: Side-by-side red/green comparison panel, then 4 metric highlight cards below with large colored numbers.
|
||||
|
||||
---
|
||||
|
||||
### Task 8: Section 7 — 路线图 & Section 8 — 下一步 + 页脚
|
||||
|
||||
**Files:**
|
||||
- Modify: `boss-report.html` — add roadmap, next steps, and footer
|
||||
|
||||
- [ ] **Step 1: Add roadmap + next steps + footer HTML**
|
||||
|
||||
Insert after the value `<div class="divider"></div>`:
|
||||
|
||||
```html
|
||||
<!-- ── S7: Roadmap ── -->
|
||||
<section id="roadmap">
|
||||
<div class="section fade-in">
|
||||
<div class="section-label">发展路线</div>
|
||||
<h2 class="section-title">四阶段推进计划</h2>
|
||||
<p class="section-sub">当前处于第二阶段"能力建设",核心模块已完成,正在推进全量接入</p>
|
||||
|
||||
<div style="position:relative; padding:40px 0;">
|
||||
<!-- Timeline line -->
|
||||
<div style="position:absolute; top:60px; left:12.5%; right:12.5%; height:3px; background:linear-gradient(90deg, var(--green) 50%, var(--border) 50%);"></div>
|
||||
|
||||
<div style="display:grid; grid-template-columns:repeat(4,1fr); gap:20px; position:relative;">
|
||||
|
||||
<!-- Phase 1: DONE -->
|
||||
<div class="fade-in" style="text-align:center;">
|
||||
<div style="width:48px; height:48px; border-radius:50%; background:var(--green); border:3px solid var(--green); display:flex; align-items:center; justify-content:center; margin:0 auto 16px; font-size:18px; position:relative; z-index:1;">✓</div>
|
||||
<div style="background:rgba(0,212,170,0.1); border:1px solid rgba(0,212,170,0.3); border-radius:10px; padding:18px 14px;">
|
||||
<div class="mono" style="font-size:10px; color:var(--green); margin-bottom:6px;">阶段 01 · 已完成</div>
|
||||
<h4 style="font-size:14px; font-weight:700; margin-bottom:10px;">POC 验证</h4>
|
||||
<ul style="font-size:12px; color:var(--text2); list-style:none; text-align:left; line-height:1.9;">
|
||||
<li>▸ 架构设计完成</li>
|
||||
<li>▸ 技术栈验证</li>
|
||||
<li>▸ 核心 RAG 流程打通</li>
|
||||
<li>▸ 前端原型搭建</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Phase 2: ACTIVE -->
|
||||
<div class="fade-in" style="text-align:center;">
|
||||
<div style="width:48px; height:48px; border-radius:50%; background:var(--accent); border:3px solid var(--accent); display:flex; align-items:center; justify-content:center; margin:0 auto 16px; font-size:18px; position:relative; z-index:1; animation:pulse 2s infinite; box-shadow:0 0 20px rgba(226,0,116,0.4);">⟳</div>
|
||||
<div style="background:rgba(226,0,116,0.1); border:2px solid var(--accent); border-radius:10px; padding:18px 14px; box-shadow:0 0 24px rgba(226,0,116,0.12);">
|
||||
<div class="mono" style="font-size:10px; color:var(--accent); margin-bottom:6px;">阶段 02 · 进行中 ◀ 当前</div>
|
||||
<h4 style="font-size:14px; font-weight:700; margin-bottom:10px;">能力建设</h4>
|
||||
<ul style="font-size:12px; color:var(--text2); list-style:none; text-align:left; line-height:1.9;">
|
||||
<li>▸ 5 大模块开发</li>
|
||||
<li>▸ API 接口完整设计</li>
|
||||
<li>▸ RBAC 权限系统</li>
|
||||
<li>▸ Demo 可演示</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Phase 3 -->
|
||||
<div class="fade-in" style="text-align:center;">
|
||||
<div style="width:48px; height:48px; border-radius:50%; background:var(--bg-card); border:3px solid var(--border); display:flex; align-items:center; justify-content:center; margin:0 auto 16px; font-size:18px; position:relative; z-index:1; color:var(--text3);">3</div>
|
||||
<div style="background:var(--bg-card); border:1px solid var(--border); border-radius:10px; padding:18px 14px;">
|
||||
<div class="mono" style="font-size:10px; color:var(--text3); margin-bottom:6px;">阶段 03 · 规划中</div>
|
||||
<h4 style="font-size:14px; font-weight:700; color:var(--text2); margin-bottom:10px;">全量接入</h4>
|
||||
<ul style="font-size:12px; color:var(--text3); list-style:none; text-align:left; line-height:1.9;">
|
||||
<li>▸ IT 系统对接</li>
|
||||
<li>▸ 2-3 个试点部门</li>
|
||||
<li>▸ 用户培训</li>
|
||||
<li>▸ 数据迁移</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Phase 4 -->
|
||||
<div class="fade-in" style="text-align:center;">
|
||||
<div style="width:48px; height:48px; border-radius:50%; background:var(--bg-card); border:3px solid var(--border); display:flex; align-items:center; justify-content:center; margin:0 auto 16px; font-size:18px; position:relative; z-index:1; color:var(--text3);">4</div>
|
||||
<div style="background:var(--bg-card); border:1px solid var(--border); border-radius:10px; padding:18px 14px;">
|
||||
<div class="mono" style="font-size:10px; color:var(--text3); margin-bottom:6px;">阶段 04 · 规划中</div>
|
||||
<h4 style="font-size:14px; font-weight:700; color:var(--text2); margin-bottom:10px;">规模运营</h4>
|
||||
<ul style="font-size:12px; color:var(--text3); list-style:none; text-align:left; line-height:1.9;">
|
||||
<li>▸ API 平台开放</li>
|
||||
<li>▸ PLM/ERP/MES 集成</li>
|
||||
<li>▸ 全公司推广</li>
|
||||
<li>▸ 持续优化迭代</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="divider"></div>
|
||||
|
||||
<!-- ── S8: Next Steps ── -->
|
||||
<section id="next">
|
||||
<div class="section fade-in">
|
||||
<div class="section-label">下一步</div>
|
||||
<h2 class="section-title">近期行动项</h2>
|
||||
<p class="section-sub">阶段二收尾,推进阶段三启动所需的关键决策与资源</p>
|
||||
|
||||
<div style="display:grid; grid-template-columns:repeat(2,1fr); gap:20px; max-width:800px;">
|
||||
|
||||
<div class="fade-in" style="background:var(--bg-card); border:1px solid var(--border); border-left:4px solid var(--accent); border-radius:var(--radius); padding:24px;">
|
||||
<div style="font-size:12px; font-weight:700; color:var(--accent); margin-bottom:12px; letter-spacing:1px;">🎯 技术</div>
|
||||
<ul style="font-size:14px; color:var(--text2); list-style:none; line-height:2;">
|
||||
<li>□ 完成 EHS 模块与报告模块开发</li>
|
||||
<li>□ 后端 kbmp-service 生产环境部署</li>
|
||||
<li>□ 端到端集成测试</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="fade-in" style="background:var(--bg-card); border:1px solid var(--border); border-left:4px solid var(--green); border-radius:var(--radius); padding:24px;">
|
||||
<div style="font-size:12px; font-weight:700; color:var(--green); margin-bottom:12px; letter-spacing:1px;">📋 业务</div>
|
||||
<ul style="font-size:14px; color:var(--text2); list-style:none; line-height:2;">
|
||||
<li>□ 确定试点部门(EHS/合规/法务)</li>
|
||||
<li>□ 收集 2-3 个真实合规场景需求</li>
|
||||
<li>□ IT 系统对接方案评估</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="fade-in" style="background:var(--bg-card); border:1px solid var(--border); border-left:4px solid var(--orange); border-radius:var(--radius); padding:24px;">
|
||||
<div style="font-size:12px; font-weight:700; color:var(--orange); margin-bottom:12px; letter-spacing:1px;">🔐 安全合规</div>
|
||||
<ul style="font-size:14px; color:var(--text2); list-style:none; line-height:2;">
|
||||
<li>□ PIPL/DSL 数据合规评审</li>
|
||||
<li>□ 内部安全审计配合</li>
|
||||
<li>□ 数据脱敏与权限细化</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="fade-in" style="background:var(--bg-card); border:1px solid var(--border); border-left:4px solid var(--blue); border-radius:var(--radius); padding:24px;">
|
||||
<div style="font-size:12px; font-weight:700; color:var(--blue); margin-bottom:12px; letter-spacing:1px;">💰 资源申请</div>
|
||||
<ul style="font-size:14px; color:var(--text2); list-style:none; line-height:2;">
|
||||
<li>□ GPU/云资源扩容评估</li>
|
||||
<li>□ 阿里云 DocMind 商业授权</li>
|
||||
<li>□ 阶段三人力资源确认</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ── Footer ── -->
|
||||
<footer style="border-top:1px solid var(--border); padding:40px; text-align:center; background:var(--bg-card);">
|
||||
<div style="max-width:1200px; margin:0 auto; display:flex; align-items:center; justify-content:space-between; flex-wrap:wrap; gap:16px;">
|
||||
<div>
|
||||
<div style="font-size:16px; font-weight:700; color:var(--text); margin-bottom:4px;">AI+合规智能中枢</div>
|
||||
<div style="font-size:12px; color:var(--text3);">EMS & EHS Compliance Intelligence Hub · Internal · Confidential</div>
|
||||
</div>
|
||||
<div style="text-align:right;">
|
||||
<div class="mono" style="font-size:13px; color:var(--accent); font-weight:600;">2026.05</div>
|
||||
<div style="font-size:12px; color:var(--text3); margin-top:4px;">AI 合规项目组 · T-Systems</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Finalize JS — move `querySelectorAll` after all sections are added**
|
||||
|
||||
In the `<script>` block, ensure the JS runs after all sections are in the DOM. The script block is already at the bottom of `<body>`, so this is already correct. No changes needed.
|
||||
|
||||
- [ ] **Step 3: Full page verification**
|
||||
|
||||
Open `boss-report.html` in browser and scroll through all 8 sections. Expected:
|
||||
1. ✅ Hero — dark full-viewport with KPI cards
|
||||
2. ✅ Background — 3 pain point cards
|
||||
3. ✅ Progress — 5 module rows with status badges
|
||||
4. ✅ Architecture — 5 colored layer boxes
|
||||
5. ✅ Demo — 5 feature cards in grid
|
||||
6. ✅ Value — left/right comparison + 4 metric cards
|
||||
7. ✅ Roadmap — 4-phase timeline, phase 2 highlighted in magenta
|
||||
8. ✅ Next Steps — 4 action cards + footer
|
||||
9. ✅ Fixed nav highlights active section on scroll
|
||||
10. ✅ All `.fade-in` elements animate on scroll into view
|
||||
|
||||
---
|
||||
|
||||
## Self-Review
|
||||
|
||||
**Spec coverage check:**
|
||||
- ✅ Hero + KPI → Task 2
|
||||
- ✅ Background / pain points → Task 3
|
||||
- ✅ 5 module progress → Task 4
|
||||
- ✅ Architecture diagram → Task 5
|
||||
- ✅ Demo features → Task 6
|
||||
- ✅ Business value comparison → Task 7
|
||||
- ✅ Roadmap (4-phase) → Task 8
|
||||
- ✅ Next steps + footer → Task 8
|
||||
- ✅ Fixed nav with scroll spy → Task 1
|
||||
- ✅ Fade-in animations → Task 1
|
||||
- ✅ Dark theme, T-Systems magenta → Task 1
|
||||
|
||||
**Placeholder scan:** None found. All code is complete and explicit.
|
||||
|
||||
**Type consistency:** No typed interfaces — pure HTML/CSS. All color variables defined in `:root` in Task 1 and used consistently throughout.
|
||||
|
||||
**Scope check:** Single file deliverable, well within one implementation plan.
|
||||
2015
docs/superpowers/plans/2026-06-03-frontend-redesign.md
Normal file
2015
docs/superpowers/plans/2026-06-03-frontend-redesign.md
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user