landingpage4 / index.html
capta1n's picture
Add 3 files
50a7e4e verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AI SDL Digital Twin Dashboard</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
@keyframes float {
0% { transform: translateY(0px); }
50% { transform: translateY(-10px); }
100% { transform: translateY(0px); }
}
@keyframes pulse {
0% { opacity: 0.7; }
50% { opacity: 1; }
100% { opacity: 0.7; }
}
@keyframes pulse-glow {
0% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.7); }
70% { box-shadow: 0 0 0 10px rgba(239, 68, 68, 0); }
100% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0); }
}
@keyframes data-flow {
0% { stroke-dashoffset: 100; }
100% { stroke-dashoffset: 0; }
}
@keyframes rotate {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
@keyframes scanning {
0% { transform: translateX(-100%) rotate(45deg); }
100% { transform: translateX(100%) rotate(45deg); }
}
@keyframes flicker {
0% { opacity: 0.5; }
50% { opacity: 1; }
100% { opacity: 0.5; }
}
@keyframes bounce {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-5px); }
}
@keyframes flip {
0% { transform: rotateX(0deg); }
50% { transform: rotateX(90deg); }
100% { transform: rotateX(0deg); }
}
@keyframes highlight {
0%, 100% { box-shadow: 0 0 0 0 rgba(16, 185, 129, 0); }
50% { box-shadow: 0 0 0 10px rgba(16, 185, 129, 0.3); }
}
.floating {
animation: float 3s ease-in-out infinite;
}
.pulse {
animation: pulse 2s ease-in-out infinite;
}
.pulse-glow {
animation: pulse-glow 1.5s infinite;
}
.data-flow {
stroke-dasharray: 10;
animation: data-flow 2s linear infinite;
}
.rotate {
animation: rotate 2s linear infinite;
}
.scanning {
position: relative;
overflow: hidden;
}
.scanning::after {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(
to bottom,
rgba(16, 185, 129, 0.1) 0%,
rgba(16, 185, 129, 0.3) 50%,
rgba(16, 185, 129, 0.1) 100%
);
transform: rotate(45deg);
animation: scanning 3s linear infinite;
}
.flicker {
animation: flicker 1.5s ease-in-out infinite alternate;
}
.bounce {
animation: bounce 0.5s ease infinite;
}
.flip {
animation: flip 0.6s ease-out;
}
.highlight {
animation: highlight 1.5s ease-in-out infinite;
}
.code-block {
font-family: 'Courier New', monospace;
background-color: #1e293b;
color: #f8fafc;
padding: 1rem;
border-radius: 0.5rem;
overflow-x: auto;
}
.vulnerability-line {
background-color: #7f1d1d;
padding: 0.2rem;
border-radius: 0.2rem;
}
.threat-model {
background-color: #f8fafc;
border: 1px solid #e2e8f0;
border-radius: 0.5rem;
padding: 1rem;
position: relative;
}
.risk-tag {
display: inline-block;
padding: 0.2rem 0.5rem;
border-radius: 1rem;
font-size: 0.75rem;
margin-right: 0.5rem;
margin-bottom: 0.5rem;
}
.progress-ring__circle {
transition: stroke-dashoffset 0.5s;
transform: rotate(-90deg);
transform-origin: 50% 50%;
}
.highlight-box {
position: relative;
border-left: 4px solid;
padding-left: 1rem;
margin-bottom: 1rem;
}
.highlight-box::before {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(255, 255, 255, 0.1);
border-radius: 0.25rem;
z-index: -1;
}
.circular-node {
position: absolute;
width: 100px;
height: 100px;
border-radius: 50%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
transition: all 0.3s ease;
}
.circular-node:hover {
transform: scale(1.1);
z-index: 10;
}
.stats-card {
transition: all 0.3s ease;
position: relative;
}
.stats-card:hover {
transform: translateY(-5px);
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
}
.stats-card::before {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
height: 3px;
background-color: #10b981;
opacity: 0;
transition: opacity 0.3s ease;
}
.stats-card:hover::before {
opacity: 1;
}
.active-scan {
position: relative;
}
.active-scan::after {
content: "Analyzing...";
position: absolute;
bottom: -20px;
left: 0;
right: 0;
text-align: center;
font-size: 0.75rem;
color: #10b981;
font-weight: 600;
}
.chat-bubble {
position: absolute;
background-color: white;
border-radius: 1rem;
padding: 0.75rem 1rem;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
max-width: 300px;
opacity: 0;
transition: opacity 0.3s ease;
z-index: 20;
}
.chat-bubble::after {
content: "";
position: absolute;
bottom: -10px;
left: 20px;
border-width: 10px 10px 0;
border-style: solid;
border-color: white transparent transparent;
}
.alert-item {
transition: all 0.3s ease;
transform-origin: center bottom;
}
.alert-item.new {
animation: bounce 0.5s ease;
}
.alert-item.focused {
transform: scale(1.05);
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
z-index: 10;
}
.alert-detail {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
z-index: 100;
opacity: 0;
pointer-events: none;
transition: opacity 0.3s ease;
}
.alert-detail.active {
opacity: 1;
pointer-events: all;
}
.alert-detail-content {
background-color: white;
border-radius: 0.5rem;
padding: 1.5rem;
max-width: 500px;
width: 90%;
transform: scale(0.9);
transition: transform 0.3s ease;
}
.alert-detail.active .alert-detail-content {
transform: scale(1);
}
.flip-container {
perspective: 1000px;
}
.flipper {
transition: transform 0.6s;
transform-style: preserve-3d;
position: relative;
}
.flipper.flip {
transform: rotateX(360deg);
}
.front, .back {
backface-visibility: hidden;
position: absolute;
top: 0;
left: 0;
}
.front {
z-index: 2;
transform: rotateX(0deg);
}
.back {
transform: rotateX(180deg);
}
.typing-effect {
overflow: hidden;
white-space: nowrap;
border-right: 2px solid #10b981;
animation: blink-caret 0.75s step-end infinite;
}
@keyframes blink-caret {
from, to { border-color: transparent; }
50% { border-color: #10b981; }
}
</style>
</head>
<body class="bg-gray-50 min-h-screen">
<!-- Navigation -->
<nav class="bg-green-800 text-white shadow-lg">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex justify-between h-16 items-center">
<div class="flex items-center">
<div class="flex-shrink-0 flex items-center">
<i class="fas fa-robot text-2xl mr-2"></i>
<span class="text-xl font-bold">AI SDL Digital Twin</span>
</div>
</div>
<div class="hidden md:block">
<div class="ml-10 flex items-baseline space-x-4">
<a href="#" class="bg-green-700 px-3 py-2 rounded-md text-sm font-medium">Dashboard</a>
<a href="#alerts" class="text-green-200 hover:bg-green-700 hover:text-white px-3 py-2 rounded-md text-sm font-medium">Risk Alerts</a>
<a href="#projects" class="text-green-200 hover:bg-green-700 hover:text-white px-3 py-2 rounded-md text-sm font-medium">Risk Projects</a>
</div>
</div>
</div>
</div>
</nav>
<!-- Main Content -->
<main class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
<!-- Dashboard Section -->
<section id="dashboard">
<div class="mb-8">
<h1 class="text-3xl font-bold text-gray-900">Security Risk Dashboard</h1>
<p class="mt-2 text-gray-600">Comprehensive view of security risks across all projects</p>
</div>
<div class="flex flex-col lg:flex-row gap-8">
<!-- Left Column - Stats and Visualization -->
<div class="lg:w-2/3">
<!-- Real-time Stats Panel -->
<div class="bg-white rounded-xl shadow-md overflow-hidden mb-8 scanning">
<div class="p-6">
<div class="flex justify-between items-center mb-6">
<h2 class="text-xl font-bold text-gray-900">Real-time Analysis Dashboard</h2>
<div class="flex items-center">
<div class="h-3 w-3 rounded-full bg-green-500 mr-2 pulse"></div>
<span class="text-sm font-medium text-green-600">Active Scanning</span>
</div>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-5 gap-4">
<div class="stats-card bg-gray-50 p-4 rounded-lg active-scan">
<div class="flex items-center">
<div class="bg-green-100 rounded-full h-10 w-10 flex items-center justify-center text-green-600 mr-3 flicker">
<i class="fas fa-file-alt"></i>
</div>
<div>
<h4 class="text-sm font-medium text-gray-700">Requirements Analyzed</h4>
<p class="text-xl font-bold text-gray-900 flip-container">
<span class="flipper">
<span class="front">24</span>
<span class="back">24</span>
</span>
</p>
<p class="text-xs text-gray-500">2 threats identified</p>
</div>
</div>
</div>
<div class="stats-card bg-gray-50 p-4 rounded-lg active-scan">
<div class="flex items-center">
<div class="bg-green-100 rounded-full h-10 w-10 flex items-center justify-center text-green-600 mr-3 flicker">
<i class="fas fa-code"></i>
</div>
<div>
<h4 class="text-sm font-medium text-gray-700">Code Scanned</h4>
<p class="text-xl font-bold text-gray-900 flip-container">
<span class="flipper">
<span class="front">120,842</span>
<span class="back">120,842</span>
</span>
<span class="text-sm">lines</span>
</p>
<p class="text-xs text-gray-500">1 critical vulnerability</p>
</div>
</div>
</div>
<div class="stats-card bg-gray-50 p-4 rounded-lg active-scan">
<div class="flex items-center">
<div class="bg-green-100 rounded-full h-10 w-10 flex items-center justify-center text-green-600 mr-3 flicker">
<i class="fas fa-shield-alt"></i>
</div>
<div>
<h4 class="text-sm font-medium text-gray-700">Tests Completed</h4>
<p class="text-xl font-bold text-gray-900 flip-container">
<span class="flipper">
<span class="front">18/42</span>
<span class="back">18/42</span>
</span>
</p>
<p class="text-xs text-gray-500">1 medium risk found</p>
</div>
</div>
</div>
<div class="stats-card bg-gray-50 p-4 rounded-lg active-scan">
<div class="flex items-center">
<div class="bg-green-100 rounded-full h-10 w-10 flex items-center justify-center text-green-600 mr-3 flicker">
<i class="fas fa-rocket"></i>
</div>
<div>
<h4 class="text-sm font-medium text-gray-700">Releases Verified</h4>
<p class="text-xl font-bold text-gray-900 flip-container">
<span class="flipper">
<span class="front">3</span>
<span class="back">3</span>
</span>
</p>
<p class="text-xs text-gray-500">All checks passed</p>
</div>
</div>
</div>
<div class="stats-card bg-gray-50 p-4 rounded-lg active-scan">
<div class="flex items-center">
<div class="bg-green-100 rounded-full h-10 w-10 flex items-center justify-center text-green-600 mr-3 flicker">
<i class="fas fa-server"></i>
</div>
<div>
<h4 class="text-sm font-medium text-gray-700">Production Services</h4>
<p class="text-xl font-bold text-gray-900 flip-container">
<span class="flipper">
<span class="front">5</span>
<span class="back">5</span>
</span>
</p>
<p class="text-xs text-gray-500">No active incidents</p>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Circular SDL Process Visualization -->
<div class="bg-white rounded-xl shadow-md overflow-hidden mb-8 p-6 relative">
<!-- Chat Bubble -->
<div id="chatBubble" class="chat-bubble" style="top: 50px; left: 50px;">
<div id="chatText" class="text-sm text-gray-800"></div>
</div>
<div class="relative h-96">
<div class="absolute inset-0 flex items-center justify-center">
<svg width="100%" height="100%" viewBox="0 0 500 500" class="absolute">
<!-- Data flow arrows -->
<defs>
<marker id="arrowhead" markerWidth="10" markerHeight="7"
refX="0" refY="3.5" orient="auto">
<polygon points="0 0, 10 3.5, 0 7" fill="#10b981" />
</marker>
</defs>
<!-- Circular path for data flow -->
<path id="data-path" d="M250,100 A150,150 0 1,1 250,400 A150,150 0 1,1 250,100"
fill="none" stroke="#10b981" stroke-width="2" stroke-dasharray="10,5"
class="data-flow" />
<!-- Animated arrow along the path -->
<circle cx="250" cy="100" r="5" fill="#10b981">
<animateMotion dur="10s" repeatCount="indefinite">
<mpath xlink:href="#data-path"/>
</animateMotion>
</circle>
</svg>
<!-- Requirement Design Node -->
<div id="requirementNode" class="circular-node bg-green-50 border-2 border-green-200" style="top: 10%; left: 50%; transform: translateX(-50%);">
<div class="relative w-16 h-16 mb-2">
<svg class="w-full h-full" viewBox="0 0 36 36">
<path
d="M18 2.0845
a 15.9155 15.9155 0 0 1 0 31.831
a 15.9155 15.9155 0 0 1 0 -31.831"
fill="none"
stroke="#e2e8f0"
stroke-width="3"
/>
<path
class="progress-ring__circle"
stroke="#10b981"
stroke-width="3"
stroke-dasharray="78, 100"
d="M18 2.0845
a 15.9155 15.9155 0 0 1 0 31.831
a 15.9155 15.9155 0 0 1 0 -31.831"
/>
</svg>
<div class="absolute inset-0 flex items-center justify-center">
<i class="fas fa-lightbulb text-green-600 text-xl"></i>
</div>
</div>
<div class="text-xs font-medium text-gray-700">Requirement Design</div>
<div class="text-xs text-gray-500 mt-1">78% analyzed</div>
<div class="absolute -top-2 -right-2 bg-red-500 text-white rounded-full h-6 w-6 flex items-center justify-center text-xs pulse-glow">2</div>
</div>
<!-- Code Changes Node -->
<div id="codeNode" class="circular-node bg-green-50 border-2 border-green-200" style="top: 30%; right: 10%;">
<div class="relative w-16 h-16 mb-2">
<svg class="w-full h-full" viewBox="0 0 36 36">
<path
d="M18 2.0845
a 15.9155 15.9155 0 0 1 0 31.831
a 15.9155 15.9155 0 0 1 0 -31.831"
fill="none"
stroke="#e2e8f0"
stroke-width="3"
/>
<path
class="progress-ring__circle"
stroke="#10b981"
stroke-width="3"
stroke-dasharray="45, 100"
d="M18 2.0845
a 15.9155 15.9155 0 0 1 0 31.831
a 15.9155 15.9155 0 0 1 0 -31.831"
/>
</svg>
<div class="absolute inset-0 flex items-center justify-center">
<i class="fas fa-code text-green-600 text-xl"></i>
</div>
</div>
<div class="text-xs font-medium text-gray-700">Code Changes</div>
<div class="text-xs text-gray-500 mt-1">45% analyzed</div>
<div class="absolute -top-2 -right-2 bg-red-500 text-white rounded-full h-6 w-6 flex items-center justify-center text-xs pulse-glow">1</div>
</div>
<!-- Security Testing Node -->
<div id="testingNode" class="circular-node bg-green-50 border-2 border-green-200" style="bottom: 20%; right: 20%;">
<div class="relative w-16 h-16 mb-2">
<svg class="w-full h-full" viewBox="0 0 36 36">
<path
d="M18 2.0845
a 15.9155 15.9155 0 0 1 0 31.831
a 15.9155 15.9155 0 0 1 0 -31.831"
fill="none"
stroke="#e2e8f0"
stroke-width="3"
/>
<path
class="progress-ring__circle"
stroke="#10b981"
stroke-width="3"
stroke-dasharray="32, 100"
d="M18 2.0845
a 15.9155 15.9155 0 0 1 0 31.831
a 15.9155 15.9155 0 0 1 0 -31.831"
/>
</svg>
<div class="absolute inset-0 flex items-center justify-center">
<i class="fas fa-shield-alt text-green-600 text-xl"></i>
</div>
</div>
<div class="text-xs font-medium text-gray-700">Security Testing</div>
<div class="text-xs text-gray-500 mt-1">32% analyzed</div>
<div class="absolute -top-2 -right-2 bg-yellow-500 text-white rounded-full h-6 w-6 flex items-center justify-center text-xs">1</div>
</div>
<!-- Release Node -->
<div id="releaseNode" class="circular-node bg-green-50 border-2 border-green-200" style="bottom: 20%; left: 20%;">
<div class="relative w-16 h-16 mb-2">
<svg class="w-full h-full" viewBox="0 0 36 36">
<path
d="M18 2.0845
a 15.9155 15.9155 0 0 1 0 31.831
a 15.9155 15.9155 0 0 1 0 -31.831"
fill="none"
stroke="#e2e8f0"
stroke-width="3"
/>
<path
class="progress-ring__circle"
stroke="#10b981"
stroke-width="3"
stroke-dasharray="90, 100"
d="M18 2.0845
a 15.9155 15.9155 0 0 1 0 31.831
a 15.9155 15.9155 0 0 1 0 -31.831"
/>
</svg>
<div class="absolute inset-0 flex items-center justify-center">
<i class="fas fa-rocket text-green-600 text-xl"></i>
</div>
</div>
<div class="text-xs font-medium text-gray-700">Release</div>
<div class="text-xs text-gray-500 mt-1">90% analyzed</div>
</div>
<!-- Production Node -->
<div id="productionNode" class="circular-node bg-green-50 border-2 border-green-200" style="top: 30%; left: 10%;">
<div class="relative w-16 h-16 mb-2">
<svg class="w-full h-full" viewBox="0 0 36 36">
<path
d="M18 2.0845
a 15.9155 15.9155 0 0 1 0 31.831
a 15.9155 15.9155 0 0 1 0 -31.831"
fill="none"
stroke="#e2e8f0"
stroke-width="3"
/>
<path
class="progress-ring__circle"
stroke="#10b981"
stroke-width="3"
stroke-dasharray="65, 100"
d="M18 2.0845
a 15.9155 15.9155 0 0 1 0 31.831
a 15.9155 15.9155 0 0 1 0 -31.831"
/>
</svg>
<div class="absolute inset-0 flex items-center justify-center">
<i class="fas fa-globe text-green-600 text-xl"></i>
</div>
</div>
<div class="text-xs font-medium text-gray-700">Production</div>
<div class="text-xs text-gray-500 mt-1">65% analyzed</div>
</div>
<!-- Center AI Avatar -->
<div class="absolute inset-0 flex items-center justify-center">
<div class="relative">
<div class="floating">
<img id="aiAvatar" class="h-24 w-24 object-contain" src="https://img.icons8.com/color/480/robot-3.png" alt="AI SDL Digital Twin">
</div>
<div class="absolute bottom-0 right-0 bg-green-500 text-white rounded-full h-8 w-8 flex items-center justify-center">
<i class="fas fa-bolt"></i>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Risk Projects Section -->
<section id="projects" class="mb-8">
<h2 class="text-2xl font-bold text-gray-900 mb-4">Risk Projects List</h2>
<div class="bg-white shadow overflow-hidden rounded-lg">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50">
<tr>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Project</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Status</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Progress</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Risks</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Action</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200">
<!-- Project 1 -->
<tr class="hover:bg-gray-50 cursor-pointer" onclick="showProjectDetail('alipay-subsidy')">
<td class="px-6 py-4 whitespace-nowrap">
<div class="flex items-center">
<div class="flex-shrink-0 h-10 w-10 bg-red-100 rounded-full flex items-center justify-center text-red-600">
<i class="fas fa-exclamation-triangle"></i>
</div>
<div class="ml-4">
<div class="text-sm font-medium text-gray-900">支付宝国补项目</div>
<div class="text-sm text-gray-500">Government subsidy system</div>
</div>
</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-red-100 text-red-800">High Risk</span>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="w-full bg-gray-200 rounded-full h-2">
<div class="bg-red-500 h-2 rounded-full" style="width: 65%"></div>
</div>
<div class="text-xs text-gray-500 mt-1">65% analyzed</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<span class="risk-tag bg-red-100 text-red-800">SQL Injection</span>
<span class="risk-tag bg-red-100 text-red-800">AuthZ Bypass</span>
</td>
<td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
<button class="text-green-600 hover:text-green-900">View Details</button>
</td>
</tr>
<!-- Project 2 -->
<tr class="hover:bg-gray-50 cursor-pointer" onclick="showProjectDetail('merchant-portal')">
<td class="px-6 py-4 whitespace-nowrap">
<div class="flex items-center">
<div class="flex-shrink-0 h-10 w-10 bg-orange-100 rounded-full flex items-center justify-center text-orange-600">
<i class="fas fa-exclamation-circle"></i>
</div>
<div class="ml-4">
<div class="text-sm font-medium text-gray-900">Merchant Portal v2.0</div>
<div class="text-sm text-gray-500">Merchant management dashboard</div>
</div>
</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-orange-100 text-orange-800">Medium Risk</span>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="w-full bg-gray-200 rounded-full h-2">
<div class="bg-orange-500 h-2 rounded-full" style="width: 42%"></div>
</div>
<div class="text-xs text-gray-500 mt-1">42% analyzed</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<span class="risk-tag bg-orange-100 text-orange-800">XSS</span>
<span class="risk-tag bg-yellow-100 text-yellow-800">Input Validation</span>
</td>
<td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
<button class="text-green-600 hover:text-green-900">View Details</button>
</td>
</tr>
<!-- Project 3 -->
<tr class="hover:bg-gray-50 cursor-pointer" onclick="showProjectDetail('payment-gateway')">
<td class="px-6 py-4 whitespace-nowrap">
<div class="flex items-center">
<div class="flex-shrink-0 h-10 w-10 bg-yellow-100 rounded-full flex items-center justify-center text-yellow-600">
<i class="fas fa-info-circle"></i>
</div>
<div class="ml-4">
<div class="text-sm font-medium text-gray-900">Payment Gateway</div>
<div class="text-sm text-gray-500">Microservice for payment processing</div>
</div>
</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-yellow-100 text-yellow-800">Low Risk</span>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="w-full bg-gray-200 rounded-full h-2">
<div class="bg-yellow-500 h-2 rounded-full" style="width: 88%"></div>
</div>
<div class="text-xs text-gray-500 mt-1">88% analyzed</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<span class="risk-tag bg-yellow-100 text-yellow-800">Hardcoded Creds</span>
</td>
<td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
<button class="text-green-600 hover:text-green-900">View Details</button>
</td>
</tr>
</tbody>
</table>
</div>
</section>
</div>
<!-- Right Column - Risk Alerts -->
<div class="lg:w-1/3">
<section id="alerts" class="mb-8">
<div class="flex justify-between items-center mb-4">
<h2 class="text-2xl font-bold text-gray-900">Risk Alerts</h2>
<div class="flex items-center">
<span id="newAlertsCount" class="bg-red-500 text-white text-xs font-bold px-2 py-1 rounded-full mr-2">3 New</span>
<button class="text-sm text-green-600 hover:text-green-800">View All</button>
</div>
</div>
<div class="bg-white shadow overflow-hidden rounded-lg">
<div id="alertStream" class="divide-y divide-gray-200 max-h-[600px] overflow-y-auto">
<!-- Critical Alert -->
<div class="alert-item new" data-project="alipay-subsidy" data-phase="requirements">
<div class="p-4 hover:bg-gray-50 cursor-pointer transition" onclick="focusAlert(this)">
<div class="flex items-start">
<div class="flex-shrink-0 pt-1">
<div class="bg-red-500 rounded-full h-8 w-8 flex items-center justify-center text-white pulse-glow">
<i class="fas fa-exclamation-triangle"></i>
</div>
</div>
<div class="ml-3 flex-1">
<div class="flex items-center justify-between">
<h3 class="text-sm font-medium text-red-700">支付宝国补项目 - 需求设计环节</h3>
<span class="text-xs text-gray-500">刚刚</span>
</div>
<div class="mt-1 text-sm text-gray-700">
<p>检测到需求设计中的权限配置风险</p>
</div>
<div class="mt-2">
<span class="risk-tag bg-red-100 text-red-800">SQL Injection</span>
<span class="risk-tag bg-red-100 text-red-800">Authorization Bypass</span>
</div>
</div>
</div>
</div>
</div>
<!-- High Alert -->
<div class="alert-item new" data-project="merchant-portal" data-phase="code">
<div class="p-4 hover:bg-gray-50 cursor-pointer transition" onclick="focusAlert(this)">
<div class="flex items-start">
<div class="flex-shrink-0 pt-1">
<div class="bg-orange-500 rounded-full h-8 w-8 flex items-center justify-center text-white pulse-glow">
<i class="fas fa-exclamation-circle"></i>
</div>
</div>
<div class="ml-3 flex-1">
<div class="flex items-center justify-between">
<h3 class="text-sm font-medium text-orange-700">Merchant Portal - 代码变更环节</h3>
<span class="text-xs text-gray-500">1分钟前</span>
</div>
<div class="mt-1 text-sm text-gray-700">
<p>检测到3个API端点存在XSS漏洞</p>
</div>
<div class="mt-2">
<span class="risk-tag bg-orange-100 text-orange-800">Cross-Site Scripting</span>
<span class="risk-tag bg-yellow-100 text-yellow-800">Input Validation</span>
</div>
</div>
</div>
</div>
</div>
<!-- Medium Alert -->
<div class="alert-item new" data-project="payment-gateway" data-phase="code">
<div class="p-4 hover:bg-gray-50 cursor-pointer transition" onclick="focusAlert(this)">
<div class="flex items-start">
<div class="flex-shrink-0 pt-1">
<div class="bg-yellow-500 rounded-full h-8 w-8 flex items-center justify-center text-white pulse-glow">
<i class="fas fa-info-circle"></i>
</div>
</div>
<div class="ml-3 flex-1">
<div class="flex items-center justify-between">
<h3 class="text-sm font-medium text-yellow-700">Payment Gateway - 代码变更环节</h3>
<span class="text-xs text-gray-500">5分钟前</span>
</div>
<div class="mt-1 text-sm text-gray-700">
<p>配置文件中发现硬编码凭据</p>
</div>
<div class="mt-2">
<span class="risk-tag bg-yellow-100 text-yellow-800">Sensitive Data Exposure</span>
</div>
</div>
</div>
</div>
</div>
<!-- Older alerts -->
<div class="alert-item" data-project="merchant-portal" data-phase="testing">
<div class="p-4 hover:bg-gray-50 cursor-pointer transition" onclick="focusAlert(this)">
<div class="flex items-start">
<div class="flex-shrink-0 pt-1">
<div class="bg-blue-500 rounded-full h-8 w-8 flex items-center justify-center text-white">
<i class="fas fa-shield-alt"></i>
</div>
</div>
<div class="ml-3 flex-1">
<div class="flex items-center justify-between">
<h3 class="text-sm font-medium text-blue-700">Merchant Portal - 安全测试环节</h3>
<span class="text-xs text-gray-500">15分钟前</span>
</div>
<div class="mt-1 text-sm text-gray-700">
<p>安全测试发现输入验证问题</p>
</div>
<div class="mt-2">
<span class="risk-tag bg-blue-100 text-blue-800">Input Validation</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Analysis Details Panel -->
<div class="bg-gray-50 p-6 rounded-lg">
<h3 class="text-lg font-semibold text-gray-900 mb-4">Analysis Insights</h3>
<div class="space-y-4">
<div class="bg-white p-4 rounded-lg shadow-sm border border-gray-200">
<h4 class="text-sm font-medium text-gray-700 mb-2">Current Focus</h4>
<div class="flex items-center">
<div class="bg-green-100 rounded-full h-8 w-8 flex items-center justify-center text-green-600 mr-3">
<i class="fas fa-code"></i>
</div>
<div>
<p class="text-sm text-gray-900">Code Change Analysis</p>
<p class="text-xs text-gray-500">Scanning payment processing module</p>
</div>
</div>
</div>
<div class="bg-white p-4 rounded-lg shadow-sm border border-gray-200">
<h4 class="text-sm font-medium text-gray-700 mb-2">Recent Findings</h4>
<div class="space-y-3">
<div class="flex items-start">
<div class="bg-red-100 rounded-full h-6 w-6 flex items-center justify-center text-red-600 mr-2 mt-0.5">
<i class="fas fa-exclamation-triangle text-xs"></i>
</div>
<div>
<p class="text-sm text-gray-900">SQL Injection vulnerability</p>
<p class="text-xs text-gray-500">In subsidy payment processing</p>
</div>
</div>
<div class="flex items-start">
<div class="bg-yellow-100 rounded-full h-6 w-6 flex items-center justify-center text-yellow-600 mr-2 mt-0.5">
<i class="fas fa-info-circle text-xs"></i>
</div>
<div>
<p class="text-sm text-gray-900">Hardcoded credentials</p>
<p class="text-xs text-gray-500">In payment gateway config</p>
</div>
</div>
</div>
</div>
<div class="bg-white p-4 rounded-lg shadow-sm border border-gray-200">
<h4 class="text-sm font-medium text-gray-700 mb-2">Next Steps</h4>
<div class="flex items-start">
<div class="bg-blue-100 rounded-full h-6 w-6 flex items-center justify-center text-blue-600 mr-2 mt-0.5">
<i class="fas fa-shield-alt text-xs"></i>
</div>
<div>
<p class="text-sm text-gray-900">Security Testing Phase</p>
<p class="text-xs text-gray-500">Starting in approx. 15 minutes</p>
</div>
</div>
</div>
</div>
<div class="mt-6 pt-4 border-t border-gray-200">
<button class="w-full bg-green-600 hover:bg-green-700 text-white font-medium py-2 px-4 rounded-md flex items-center justify-center transition">
<i class="fas fa-bell mr-2"></i> Get Notifications
</button>
</div>
</div>
</div>
</div>
</section>
</main>
<!-- Project Detail Modal -->
<div id="projectDetailModal" class="fixed inset-0 bg-gray-600 bg-opacity-50 overflow-y-auto h-full w-full hidden z-50">
<div class="relative top-20 mx-auto p-5 border w-11/12 max-w-6xl shadow-lg rounded-md bg-white max-h-screen overflow-y-auto">
<div class="flex justify-between items-center pb-3 border-b">
<h3 id="projectDetailTitle" class="text-2xl font-bold text-gray-900"></h3>
<button onclick="hideProjectDetail()" class="text-gray-400 hover:text-gray-600">
<i class="fas fa-times"></i>
</button>
</div>
<div id="projectDetailContent" class="py-4">
<!-- Content will be loaded dynamically -->
</div>
</div>
</div>
<!-- Alert Detail Modal -->
<div id="alertDetailModal" class="alert-detail">
<div class="alert-detail-content">
<div class="flex justify-between items-center pb-3 border-b">
<h3 id="alertDetailTitle" class="text-xl font-bold text-gray-900"></h3>
<button onclick="hideAlertDetail()" class="text-gray-400 hover:text-gray-600">
<i class="fas fa-times"></i>
</button>
</div>
<div id="alertDetailContent" class="py-4">
<div class="flex items-center mb-4">
<div id="alertDetailIcon" class="rounded-full h-10 w-10 flex items-center justify-center text-white mr-3"></div>
<div>
<p id="alertDetailTime" class="text-sm text-gray-500"></p>
<p id="alertDetailStatus" class="text-xs font-medium"></p>
</div>
</div>
<div id="alertDetailDescription" class="text-sm text-gray-700 mb-4"></div>
<div id="alertDetailTags" class="mb-4"></div>
<div class="bg-gray-50 p-3 rounded">
<h4 class="text-sm font-medium text-gray-700 mb-2">Recommended Actions</h4>
<ul id="alertDetailActions" class="text-sm text-gray-700 list-disc pl-5"></ul>
</div>
</div>
<div class="pt-4 border-t">
<button onclick="hideAlertDetail()" class="w-full bg-green-600 hover:bg-green-700 text-white font-medium py-2 px-4 rounded-md">
Acknowledge
</button>
</div>
</div>
</div>
<script>
// Sample project data
const projects = {
'alipay-subsidy': {
title: '支付宝国补项目 (Alipay Subsidy Project)',
description: 'Government subsidy distribution system for Alipay platform',
status: 'high-risk',
progress: 65,
risks: [
{ type: 'SQL Injection', severity: 'high', phase: 'code' },
{ type: 'Authorization Bypass', severity: 'high', phase: 'requirements' },
{ type: 'Data Validation', severity: 'medium', phase: 'requirements' }
],
requirements: {
content: `The system allows government agencies to distribute subsidies directly to citizens' Alipay accounts. Features include:
- Bulk payment processing
- Recipient verification
- Reporting and analytics
Architecture Diagram:
[Frontend] -> [API Gateway] -> [Subsidy Service] -> [Payment Service] -> [Alipay Integration]`,
analysis: [
{
scenario: 'Bulk payment processing',
riskPoint: 'No rate limiting on bulk operations',
riskType: 'Denial of Service',
recommendation: 'Implement rate limiting and batch size restrictions'
},
{
scenario: 'Recipient verification',
riskPoint: 'Relies solely on mobile number verification',
riskType: 'Authorization Bypass',
recommendation: 'Implement multi-factor verification for high-value transactions'
}
]
},
code: {
content: `// SubsidyService.java - Process subsidy payment
public class SubsidyService {
public void processPayment(String userId, BigDecimal amount) {
// Vulnerable SQL query
String query = "UPDATE accounts SET balance = balance + " + amount +
" WHERE user_id = '" + userId + "'";
// Execute query
database.execute(query);
// Log the transaction
logger.log("Processed payment of " + amount + " to user " + userId);
}
}`,
analysis: [
{
vulnerability: 'SQL Injection',
description: 'Concatenating user input directly into SQL query',
code: 'String query = "UPDATE accounts SET balance = balance + " + amount + " WHERE user_id = \'" + userId + "\'";',
recommendation: 'Use prepared statements with parameterized queries'
}
]
},
securityTesting: {
content: `Tested API Endpoint: POST /api/subsidies
Vulnerable Request:
POST /api/subsidies HTTP/1.1
Content-Type: application/json
{
"recipient": "1234567890",
"amount": "1000.00",
"reference": "&lt;script&gt;alert(1)&lt;/script&gt;"
}`,
analysis: [
{
endpoint: 'POST /api/subsidies',
payload: 'XSS payload in reference field',
description: 'Reference field reflects user input without proper encoding'
}
]
},
release: {
content: 'Release candidate v1.2.5 includes fixes for 3 of 5 identified vulnerabilities',
analysis: [
{
unresolved: 'Authorization bypass in recipient verification',
phase: 'requirements',
risk: 'Medium'
},
{
unresolved: 'SQL Injection in payment processing',
phase: 'code',
risk: 'High'
}
]
},
production: {
content: 'Not yet deployed to production',
analysis: []
}
},
'merchant-portal': {
title: 'Merchant Portal v2.0',
description: 'Dashboard for merchants to manage their Alipay integration',
status: 'medium-risk',
progress: 42,
risks: [
{ type: 'Cross-Site Scripting', severity: 'medium', phase: 'security-testing' },
{ type: 'Input Validation', severity: 'low', phase: 'security-testing' }
],
requirements: {
content: `The Merchant Portal provides:
- Transaction history and reporting
- Payout management
- API key management
- Customer support integration
Architecture:
[React Frontend] -> [Node.js API] -> [Various Microservices]`,
analysis: [
{
scenario: 'API key management',
riskPoint: 'No rate limiting on key generation',
riskType: 'Resource Exhaustion',
recommendation: 'Implement rate limiting and quotas'
}
]
},
code: {
content: `// API Key generation endpoint
app.post('/api/keys', (req, res) => {
const { merchantId } = req.body;
// Generate API key
const apiKey = generateApiKey();
// Store in database
db.query(\`INSERT INTO api_keys (merchant_id, key) VALUES (${merchantId}, '${apiKey}')\`);
// Return to client
res.json({ key: apiKey });
});`,
analysis: [
{
vulnerability: 'SQL Injection',
description: 'Concatenating user input directly into SQL query',
code: 'db.query(`INSERT INTO api_keys (merchant_id, key) VALUES (${merchantId}, \'${apiKey}\')`);',
recommendation: 'Use parameterized queries'
}
]
},
securityTesting: {
content: `Tested API Endpoint: GET /api/transactions
Vulnerable Request:
GET /api/transactions?search=&lt;script&gt;alert('XSS')&lt;/script&gt; HTTP/1.1`,
analysis: [
{
endpoint: 'GET /api/transactions',
payload: 'XSS payload in search parameter',
description: 'Search parameter reflects user input without proper encoding'
}
]
},
release: {
content: 'Release candidate v2.0.0-rc3 includes fixes for XSS vulnerabilities',
analysis: []
},
production: {
content: 'Currently running v1.9.4 in production with no critical issues',
analysis: []
}
},
'payment-gateway': {
title: 'Payment Gateway Microservice',
description: 'Core payment processing service',
status: 'low-risk',
progress: 88,
risks: [
{ type: 'Sensitive Data Exposure', severity: 'medium', phase: 'code' }
],
requirements: {
content: `Payment Gateway handles:
- Credit card processing
- Bank transfers
- Digital wallet payments
- Fraud detection
Architecture:
[Clients] -> [Payment Gateway] -> [Processors] -> [Banks]`,
analysis: [
{
scenario: 'Fraud detection',
riskPoint: 'No logging of fraud detection rules',
riskType: 'Auditability',
recommendation: 'Implement detailed audit logging'
}
]
},
code: {
content: `# config.py - Payment Gateway Configuration
DATABASE = {
'host': 'payment-db.internal',
'user': 'admin',
'password': 'supersecret123', # Hardcoded credentials
'name': 'payment_gateway'
}
API_KEYS = {
'stripe': 'sk_live_abcd1234',
'alipay': 'live_xyz789'
}`,
analysis: [
{
vulnerability: 'Hardcoded Credentials',
description: 'Sensitive credentials stored in source code',
code: '\'password\': \'supersecret123\'',
recommendation: 'Use environment variables or secret management system'
}
]
},
securityTesting: {
content: `Tested API Endpoint: POST /api/payments
No vulnerabilities found in recent tests`,
analysis: []
},
release: {
content: 'Release candidate v3.1.2 includes fix for hardcoded credentials',
analysis: []
},
production: {
content: 'Currently running v3.0.9 in production with no active incidents',
analysis: []
}
}
};
// Alert data
const alertDetails = {
'alipay-subsidy-requirements': {
title: '支付宝国补项目 - 需求设计环节',
description: '在需求设计阶段检测到权限配置风险。批量支付处理功能缺乏速率限制,可能导致拒绝服务攻击。',
actions: [
'为批量操作实施速率限制',
'添加批量大小限制',
'实施多因素验证机制'
],
severity: 'high'
},
'merchant-portal-code': {
title: 'Merchant Portal - 代码变更环节',
description: '在3个API端点检测到XSS漏洞。搜索参数未正确编码用户输入,导致跨站脚本攻击风险。',
actions: [
'对所有用户输入实施输出编码',
'添加内容安全策略(CSP)头',
'更新输入验证规则'
],
severity: 'medium'
},
'payment-gateway-code': {
title: 'Payment Gateway - 代码变更环节',
description: '在配置文件中发现硬编码凭据。数据库密码和API密钥以明文形式存储在源代码中。',
actions: [
'将敏感数据移至环境变量',
'实施密钥管理系统',
'轮换所有暴露的凭据'
],
severity: 'medium'
},
'merchant-portal-testing': {
title: 'Merchant Portal - 安全测试环节',
description: '安全测试发现输入验证问题。某些字段未正确验证用户输入,可能导致业务逻辑绕过。',
actions: [
'实施严格的输入验证规则',
'添加服务器端验证',
'更新API文档以反映验证要求'
],
severity: 'low'
}
};
// Show project detail
function showProjectDetail(projectId) {
const project = projects[projectId];
if (!project) return;
document.getElementById('projectDetailTitle').textContent = project.title;
let content = `
<div class="mb-6">
<p class="text-gray-700 mb-4">${escapeHtml(project.description)}</p>
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-4">
<div class="bg-gray-50 p-4 rounded-lg">
<h4 class="text-sm font-medium text-gray-500 mb-1">Status</h4>
<p class="font-medium ${project.status === 'high-risk' ? 'text-red-600' : project.status === 'medium-risk' ? 'text-orange-600' : 'text-yellow-600'}">
${project.status === 'high-risk' ? 'High Risk' : project.status === 'medium-risk' ? 'Medium Risk' : 'Low Risk'}
</p>
</div>
<div class="bg-gray-50 p-4 rounded-lg">
<h4 class="text-sm font-medium text-gray-500 mb-1">Progress</h4>
<div class="w-full bg-gray-200 rounded-full h-2 mt-2">
<div class="h-2 rounded-full ${project.status === 'high-risk' ? 'bg-red-500' : project.status === 'medium-risk' ? 'bg-orange-500' : 'bg-yellow-500'}" style="width: ${project.progress}%"></div>
</div>
<p class="text-xs text-gray-500 mt-1">${project.progress}% complete</p>
</div>
<div class="bg-gray-50 p-4 rounded-lg">
<h4 class="text-sm font-medium text-gray-500 mb-1">Risks Detected</h4>
<div class="mt-1">
${project.risks.map(risk => `
<span class="risk-tag ${risk.severity === 'high' ? 'bg-red-100 text-red-800' : risk.severity === 'medium' ? 'bg-orange-100 text-orange-800' : 'bg-yellow-100 text-yellow-800'}">
${escapeHtml(risk.type)}
</span>
`).join('')}
</div>
</div>
</div>
</div>
<div class="border-t pt-6">
<h3 class="text-lg font-bold text-gray-900 mb-4">SDL Phase Analysis</h3>
<div class="space-y-8">
<!-- Requirements -->
<div>
<div class="flex items-center mb-3">
<div class="bg-green-600 rounded-full h-6 w-6 flex items-center justify-center text-white mr-3">
<i class="fas fa-lightbulb text-xs"></i>
</div>
<h4 class="font-semibold text-gray-900">Requirement Design</h4>
</div>
<div class="ml-9">
<div class="highlight-box border-green-500 mb-4">
<h5 class="font-medium text-gray-900 mb-2">Content</h5>
<div class="text-sm text-gray-700 whitespace-pre-line">${escapeHtml(project.requirements.content)}</div>
</div>
<div class="highlight-box border-green-500">
<h5 class="font-medium text-gray-900 mb-2">Security Analysis Results</h5>
${project.requirements.analysis.length > 0 ? `
<div class="space-y-4">
${project.requirements.analysis.map(item => `
<div class="bg-white p-3 rounded-lg border border-gray-200">
<div class="font-medium">${escapeHtml(item.scenario)}</div>
<div class="text-sm mt-1"><span class="font-medium">Risk:</span> ${escapeHtml(item.riskPoint)} (${escapeHtml(item.riskType)})</div>
<div class="text-sm mt-1"><span class="font-medium">Recommendation:</span> ${escapeHtml(item.recommendation)}</div>
</div>
`).join('')}
</div>
` : '<p class="text-sm text-gray-500">No risks detected in this phase</p>'}
</div>
</div>
</div>
<!-- Code -->
<div>
<div class="flex items-center mb-3">
<div class="bg-green-600 rounded-full h-6 w-6 flex items-center justify-center text-white mr-3">
<i class="fas fa-code text-xs"></i>
</div>
<h4 class="font-semibold text-gray-900">Code Changes</h4>
</div>
<div class="ml-9">
<div class="highlight-box border-green-500 mb-4">
<h5 class="font-medium text-gray-900 mb-2">Content</h5>
<div class="code-block">${escapeHtml(project.code.content)}</div>
</div>
<div class="highlight-box border-green-500">
<h5 class="font-medium text-gray-900 mb-2">Security Analysis Results</h5>
${project.code.analysis.length > 0 ? `
<div class="space-y-4">
${project.code.analysis.map(item => `
<div class="bg-white p-3 rounded-lg border border-gray-200">
<div class="font-medium">${escapeHtml(item.vulnerability)}</div>
<div class="text-sm mt-1"><span class="font-medium">Description:</span> ${escapeHtml(item.description)}</div>
<div class="text-sm mt-1"><span class="font-medium">Vulnerable Code:</span> <span class="code-block vulnerability-line">${escapeHtml(item.code)}</span></div>
<div class="text-sm mt-1"><span class="font-medium">Recommendation:</span> ${escapeHtml(item.recommendation)}</div>
</div>
`).join('')}
</div>
` : '<p class="text-sm text-gray-500">No risks detected in this phase</p>'}
</div>
</div>
</div>
<!-- Security Testing -->
<div>
<div class="flex items-center mb-3">
<div class="bg-green-600 rounded-full h-6 w-6 flex items-center justify-center text-white mr-3">
<i class="fas fa-shield-alt text-xs"></i>
</div>
<h4 class="font-semibold text-gray-900">Security Testing</h4>
</div>
<div class="ml-9">
<div class="highlight-box border-green-500 mb-4">
<h5 class="font-medium text-gray-900 mb-2">Content</h5>
<div class="code-block">${escapeHtml(project.securityTesting.content)}</div>
</div>
<div class="highlight-box border-green-500">
<h5 class="font-medium text-gray-900 mb-2">Security Analysis Results</h5>
${project.securityTesting.analysis.length > 0 ? `
<div class="space-y-4">
${project.securityTesting.analysis.map(item => `
<div class="bg-white p-3 rounded-lg border border-gray-200">
<div class="font-medium">${escapeHtml(item.endpoint)}</div>
<div class="text-sm mt-1"><span class="font-medium">Payload:</span> <span class="code-block">${escapeHtml(item.payload)}</span></div>
<div class="text-sm mt-1"><span class="font-medium">Description:</span> ${escapeHtml(item.description)}</div>
</div>
`).join('')}
</div>
` : '<p class="text-sm text-gray-500">No risks detected in this phase</p>'}
</div>
</div>
</div>
<!-- Release -->
<div>
<div class="flex items-center mb-3">
<div class="bg-green-600 rounded-full h-6 w-6 flex items-center justify-center text-white mr-3">
<i class="fas fa-rocket text-xs"></i>
</div>
<h4 class="font-semibold text-gray-900">Release</h4>
</div>
<div class="ml-9">
<div class="highlight-box border-green-500 mb-4">
<h5 class="font-medium text-gray-900 mb-2">Content</h5>
<p class="text-sm text-gray-700">${escapeHtml(project.release.content)}</p>
</div>
<div class="highlight-box border-green-500">
<h5 class="font-medium text-gray-900 mb-2">Security Analysis Results</h5>
${project.release.analysis.length > 0 ? `
<div class="space-y-4">
${project.release.analysis.map(item => `
<div class="bg-white p-3 rounded-lg border border-gray-200">
<div class="font-medium">Unresolved ${escapeHtml(item.phase)} risk</div>
<div class="text-sm mt-1"><span class="font-medium">Risk:</span> ${escapeHtml(item.unresolved)}</div>
<div class="text-sm mt-1"><span class="font-medium">Severity:</span> <span class="${item.risk === 'High' ? 'text-red-600' : item.risk === 'Medium' ? 'text-orange-600' : 'text-yellow-600'}">${escapeHtml(item.risk)}</span></div>
</div>
`).join('')}
</div>
` : '<p class="text-sm text-gray-500">All identified risks have been resolved</p>'}
</div>
</div>
</div>
<!-- Production -->
<div>
<div class="flex items-center mb-3">
<div class="bg-green-600 rounded-full h-6 w-6 flex items-center justify-center text-white mr-3">
<i class="fas fa-globe text-xs"></i>
</div>
<h4 class="font-semibold text-gray-900">Production</h4>
</div>
<div class="ml-9">
<div class="highlight-box border-green-500 mb-4">
<h5 class="font-medium text-gray-900 mb-2">Content</h5>
<p class="text-sm text-gray-700">${escapeHtml(project.production.content)}</p>
</div>
<div class="highlight-box border-green-500">
<h5 class="font-medium text-gray-900 mb-2">Security Analysis Results</h5>
${project.production.analysis.length > 0 ? `
<div class="space-y-4">
${project.production.analysis.map(item => `
<div class="bg-white p-3 rounded-lg border border-gray-200">
<div class="font-medium">${escapeHtml(item.vulnerability)}</div>
<div class="text-sm mt-1"><span class="font-medium">Status:</span> ${escapeHtml(item.status)}</div>
<div class="text-sm mt-1"><span class="font-medium">Recommendation:</span> ${escapeHtml(item.recommendation)}</div>
</div>
`).join('')}
</div>
` : '<p class="text-sm text-gray-500">No active threats detected in production</p>'}
</div>
</div>
</div>
</div>
</div>
`;
document.getElementById('projectDetailContent').innerHTML = content;
document.getElementById('projectDetailModal').classList.remove('hidden');
}
// Hide project detail
function hideProjectDetail() {
document.getElementById('projectDetailModal').classList.add('hidden');
}
// Show alert detail
function showAlertDetail(alertId) {
const alert = alertDetails[alertId];
if (!alert) return;
document.getElementById('alertDetailTitle').textContent = alert.title;
document.getElementById('alertDetailDescription').textContent = alert.description;
document.getElementById('alertDetailTime').textContent = '刚刚';
// Set icon based on severity
const icon = document.getElementById('alertDetailIcon');
icon.className = 'rounded-full h-10 w-10 flex items-center justify-center text-white mr-3';
if (alert.severity === 'high') {
icon.classList.add('bg-red-500', 'pulse-glow');
icon.innerHTML = '<i class="fas fa-exclamation-triangle"></i>';
document.getElementById('alertDetailStatus').textContent = 'High Risk';
document.getElementById('alertDetailStatus').className = 'text-xs font-medium text-red-600';
} else if (alert.severity === 'medium') {
icon.classList.add('bg-orange-500', 'pulse-glow');
icon.innerHTML = '<i class="fas fa-exclamation-circle"></i
</html>