AIDeveloper-PC/prototype/index-v2.html

3301 lines
126 KiB
HTML
Raw Normal View History

2026-01-31 09:32:00 +00:00
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>智能低代码开发平台</title>
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<!-- Bootstrap Icons -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.0/font/bootstrap-icons.css">
<style>
:root {
--bg-primary: #0a0e27;
--bg-secondary: #1a1f3a;
--bg-panel: rgba(30, 41, 59, 0.6);
--bg-card: rgba(51, 65, 85, 0.4);
--border-color: rgba(59, 130, 246, 0.2);
--border-hover: rgba(59, 130, 246, 0.4);
--border-active: rgba(59, 130, 246, 0.6);
--accent-blue: #3b82f6;
--accent-cyan: #06b6d4;
--text-primary: #e0e6ed;
--text-secondary: #94a3b8;
--text-highlight: #60a5fa;
--success: #10b981;
--warning: #f59e0b;
--error: #ef4444;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Microsoft YaHei', Arial, sans-serif;
background: linear-gradient(135deg, var(--bg-primary) 0%, var(--bg-secondary) 100%);
color: var(--text-primary);
overflow-x: hidden;
min-height: 100vh;
}
/* 顶部导航栏 */
.top-navbar {
background: rgba(15, 23, 42, 0.8);
backdrop-filter: blur(10px);
border-bottom: 2px solid var(--border-color);
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5), 0 0 20px rgba(59, 130, 246, 0.3);
padding: 15px 0;
position: sticky;
top: 0;
z-index: 1000;
}
.logo {
font-size: 24px;
font-weight: bold;
background: linear-gradient(135deg, var(--accent-blue) 0%, var(--accent-cyan) 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 0 0 30px rgba(59, 130, 246, 0.5);
}
.top-navbar .btn {
color: var(--text-secondary);
border: 1px solid var(--border-color);
background: rgba(51, 65, 85, 0.5);
transition: all 0.3s;
}
.top-navbar .btn:hover {
color: var(--text-primary);
background: rgba(51, 65, 85, 0.8);
border-color: var(--border-hover);
}
.notification-badge {
position: absolute;
top: -5px;
right: -5px;
background: var(--error);
color: white;
border-radius: 50%;
width: 18px;
height: 18px;
font-size: 10px;
display: flex;
align-items: center;
justify-content: center;
}
/* 面板样式 */
.panel {
background: var(--bg-panel);
backdrop-filter: blur(15px);
border: 1px solid var(--border-color);
border-radius: 12px;
padding: 20px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.05);
height: 100%;
position: relative;
transition: all 0.3s;
}
.panel::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 1px;
background: linear-gradient(90deg, transparent, rgba(59, 130, 246, 0.5), transparent);
}
.panel-header {
font-size: 16px;
font-weight: bold;
margin-bottom: 15px;
padding-bottom: 10px;
border-bottom: 1px solid var(--border-color);
display: flex;
align-items: center;
gap: 10px;
}
.panel-header::before {
content: '';
width: 4px;
height: 18px;
background: linear-gradient(180deg, var(--accent-blue), var(--accent-cyan));
border-radius: 2px;
box-shadow: 0 0 10px rgba(59, 130, 246, 0.5);
}
/* 按钮样式 */
.btn-primary {
background: linear-gradient(135deg, var(--accent-blue) 0%, #2563eb 100%);
border: none;
box-shadow: 0 4px 15px rgba(59, 130, 246, 0.4);
transition: all 0.3s;
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(59, 130, 246, 0.6);
}
.btn-primary:active {
transform: scale(0.95);
}
.btn-secondary {
background: rgba(51, 65, 85, 0.5);
color: var(--text-secondary);
border: 1px solid var(--border-color);
}
.btn-secondary:hover {
background: rgba(51, 65, 85, 0.8);
color: var(--text-primary);
border-color: var(--border-hover);
}
.btn-success {
background: linear-gradient(135deg, var(--success) 0%, #059669 100%);
border: none;
box-shadow: 0 4px 15px rgba(16, 185, 129, 0.4);
}
.btn-success:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(16, 185, 129, 0.6);
}
/* 项目列表 */
.project-search {
margin-bottom: 15px;
}
.project-search input {
background: rgba(51, 65, 85, 0.5);
border: 1px solid var(--border-color);
color: var(--text-primary);
padding: 8px 12px;
border-radius: 6px;
width: 100%;
}
.project-search input:focus {
outline: none;
border-color: var(--accent-blue);
box-shadow: 0 0 10px rgba(59, 130, 246, 0.3);
}
.project-item {
padding: 12px;
margin-bottom: 8px;
background: var(--bg-card);
border: 1px solid var(--border-color);
border-radius: 8px;
cursor: pointer;
transition: all 0.3s;
position: relative;
}
.project-item::before {
content: '';
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 3px;
background: transparent;
border-radius: 8px 0 0 8px;
transition: all 0.3s;
}
.project-item:hover {
background: rgba(59, 130, 246, 0.15);
border-color: var(--border-hover);
transform: translateX(5px);
}
.project-item.active {
background: rgba(59, 130, 246, 0.2);
border-color: var(--border-active);
box-shadow: 0 0 20px rgba(59, 130, 246, 0.3);
}
.project-item.active::before {
background: linear-gradient(180deg, var(--accent-blue), var(--accent-cyan));
box-shadow: 0 0 10px rgba(59, 130, 246, 0.5);
}
.project-name {
font-weight: bold;
color: var(--text-highlight);
margin-bottom: 5px;
}
.project-desc {
font-size: 12px;
color: var(--text-secondary);
margin-bottom: 5px;
}
.project-meta {
font-size: 11px;
color: var(--text-secondary);
display: flex;
justify-content: space-between;
align-items: center;
}
.project-status {
padding: 2px 8px;
border-radius: 4px;
font-size: 10px;
}
.status-active {
background: rgba(16, 185, 129, 0.2);
color: var(--success);
border: 1px solid var(--success);
}
.status-completed {
background: rgba(59, 130, 246, 0.2);
color: var(--accent-blue);
border: 1px solid var(--accent-blue);
}
.status-paused {
background: rgba(245, 158, 11, 0.2);
color: var(--warning);
border: 1px solid var(--warning);
}
/* 标签页 */
.nav-tabs {
border-bottom: 1px solid var(--border-color);
}
.nav-tabs .nav-link {
color: var(--text-secondary);
background: var(--bg-card);
border: 1px solid var(--border-color);
border-radius: 6px 6px 0 0;
margin-right: 5px;
transition: all 0.3s;
}
.nav-tabs .nav-link:hover {
background: rgba(59, 130, 246, 0.15);
color: var(--text-primary);
}
.nav-tabs .nav-link.active {
background: linear-gradient(135deg, var(--accent-blue) 0%, #2563eb 100%);
color: white;
border-color: var(--accent-blue);
box-shadow: 0 0 15px rgba(59, 130, 246, 0.5);
}
/* 卡片 */
.item-card {
padding: 15px;
margin-bottom: 10px;
background: var(--bg-card);
border: 1px solid var(--border-color);
border-radius: 8px;
transition: all 0.3s;
}
.item-card:hover {
border-color: var(--border-hover);
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
transform: scale(1.02);
}
.item-title {
font-weight: bold;
color: var(--text-highlight);
margin-bottom: 8px;
}
.item-desc {
font-size: 13px;
color: var(--text-secondary);
line-height: 1.5;
}
/* 文档列表 */
.doc-item {
padding: 12px;
margin-bottom: 8px;
background: var(--bg-card);
border-left: 3px solid var(--accent-blue);
border-radius: 4px;
cursor: pointer;
transition: all 0.3s;
display: flex;
justify-content: space-between;
align-items: center;
}
.doc-item:hover {
background: rgba(59, 130, 246, 0.15);
transform: translateX(5px);
}
.doc-name {
display: flex;
align-items: center;
gap: 10px;
flex: 1;
}
.doc-meta {
font-size: 11px;
color: var(--text-secondary);
margin-top: 5px;
}
.doc-actions {
display: flex;
gap: 5px;
}
.doc-actions .btn {
padding: 4px 8px;
font-size: 12px;
}
/* 代码树 */
.code-tree {
font-family: 'Consolas', 'Monaco', monospace;
font-size: 13px;
}
.tree-node {
padding: 5px 10px;
cursor: pointer;
transition: all 0.2s;
border-radius: 4px;
display: flex;
align-items: center;
gap: 8px;
}
.tree-node:hover {
background: rgba(59, 130, 246, 0.1);
}
.tree-folder {
color: #fbbf24;
}
.tree-file {
color: var(--text-highlight);
}
.tree-toggle {
cursor: pointer;
width: 16px;
text-align: center;
}
/* 流水线 */
.pipeline {
display: flex;
gap: 10px;
align-items: center;
position: relative;
}
.pipeline-step {
flex: 1;
text-align: center;
padding: 20px 15px;
background: var(--bg-card);
border: 1px solid var(--border-color);
border-radius: 8px;
position: relative;
transition: all 0.3s;
cursor: pointer;
}
.pipeline-step:hover {
background: rgba(59, 130, 246, 0.15);
transform: translateY(-3px);
}
.pipeline-step.active {
background: linear-gradient(135deg, rgba(59, 130, 246, 0.3) 0%, rgba(37, 99, 235, 0.3) 100%);
border-color: var(--accent-blue);
box-shadow: 0 0 20px rgba(59, 130, 246, 0.4);
}
.pipeline-step.success {
border-color: var(--success);
background: rgba(16, 185, 129, 0.1);
}
.pipeline-step.error {
border-color: var(--error);
background: rgba(239, 68, 68, 0.1);
}
.pipeline-step::after {
content: '→';
position: absolute;
right: -15px;
top: 50%;
transform: translateY(-50%);
color: var(--accent-blue);
font-size: 20px;
z-index: 1;
}
.pipeline-step:last-child::after {
content: '';
}
.step-icon {
font-size: 28px;
margin-bottom: 10px;
}
.step-name {
font-size: 14px;
font-weight: bold;
margin-bottom: 5px;
}
.step-status {
font-size: 12px;
color: var(--text-secondary);
}
/* 滚动条 */
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-track {
background: rgba(30, 41, 59, 0.5);
border-radius: 4px;
}
::-webkit-scrollbar-thumb {
background: rgba(59, 130, 246, 0.4);
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: rgba(59, 130, 246, 0.6);
}
/* 模态框 */
.modal-content {
background: rgba(30, 41, 59, 0.95);
border: 1px solid var(--border-color);
color: var(--text-primary);
backdrop-filter: blur(15px);
}
.modal-header {
border-bottom: 1px solid var(--border-color);
}
.modal-footer {
border-top: 1px solid var(--border-color);
}
.form-control, .form-select {
background: rgba(51, 65, 85, 0.5);
border: 1px solid var(--border-color);
color: var(--text-primary);
}
.form-control:focus, .form-select:focus {
background: rgba(51, 65, 85, 0.7);
border-color: var(--accent-blue);
color: var(--text-primary);
box-shadow: 0 0 10px rgba(59, 130, 246, 0.3);
}
.form-control::placeholder {
color: var(--text-secondary);
}
.form-label {
color: var(--text-secondary);
margin-bottom: 8px;
}
/* 向导步骤 */
.wizard-steps {
display: flex;
justify-content: space-between;
margin-bottom: 30px;
position: relative;
}
.wizard-steps::before {
content: '';
position: absolute;
top: 20px;
left: 0;
right: 0;
height: 2px;
background: var(--border-color);
z-index: 0;
}
.wizard-step {
flex: 1;
text-align: center;
position: relative;
z-index: 1;
}
.wizard-step-number {
width: 40px;
height: 40px;
border-radius: 50%;
background: rgba(51, 65, 85, 0.5);
border: 2px solid var(--border-color);
display: inline-flex;
align-items: center;
justify-content: center;
margin-bottom: 8px;
font-weight: bold;
transition: all 0.3s;
}
.wizard-step.active .wizard-step-number {
background: linear-gradient(135deg, var(--accent-blue), #2563eb);
border-color: var(--accent-blue);
box-shadow: 0 0 20px rgba(59, 130, 246, 0.5);
}
.wizard-step.completed .wizard-step-number {
background: rgba(16, 185, 129, 0.3);
border-color: var(--success);
}
.wizard-step-label {
font-size: 12px;
color: var(--text-secondary);
}
/* 进度条 */
.progress {
background: rgba(51, 65, 85, 0.5);
border-radius: 4px;
height: 8px;
}
.progress-bar {
background: linear-gradient(90deg, var(--accent-blue), var(--accent-cyan));
box-shadow: 0 0 10px rgba(59, 130, 246, 0.5);
}
.progress-bar-animated {
animation: progress-stripes 1s linear infinite;
}
@keyframes progress-stripes {
0% { background-position: 0 0; }
100% { background-position: 40px 0; }
}
/* 高度控制 */
.scrollable-panel {
max-height: calc(100vh - 250px);
overflow-y: auto;
}
.main-content {
padding: 20px;
min-height: calc(100vh - 80px);
}
/* 徽章 */
.badge {
padding: 4px 8px;
border-radius: 4px;
font-size: 11px;
font-weight: normal;
}
/* 需求录入方式选择卡片 */
.input-method-card {
padding: 20px;
border: 2px solid var(--border-color);
border-radius: 8px;
cursor: pointer;
transition: all 0.3s;
text-align: center;
background: var(--bg-card);
}
.input-method-card:hover {
border-color: var(--border-hover);
background: rgba(59, 130, 246, 0.1);
}
.input-method-card.selected {
border-color: var(--accent-blue);
background: rgba(59, 130, 246, 0.2);
box-shadow: 0 0 20px rgba(59, 130, 246, 0.3);
}
.input-method-icon {
font-size: 48px;
margin-bottom: 15px;
}
.input-method-title {
font-size: 16px;
font-weight: bold;
margin-bottom: 8px;
}
.input-method-desc {
font-size: 13px;
color: var(--text-secondary);
}
/* 语音录制界面 */
.voice-recorder {
text-align: center;
padding: 40px;
}
.mic-button {
width: 120px;
height: 120px;
border-radius: 50%;
border: none;
background: linear-gradient(135deg, var(--accent-blue), #2563eb);
color: white;
font-size: 48px;
cursor: pointer;
transition: all 0.3s;
box-shadow: 0 8px 32px rgba(59, 130, 246, 0.4);
}
.mic-button:hover {
transform: scale(1.05);
box-shadow: 0 12px 40px rgba(59, 130, 246, 0.6);
}
.mic-button.recording {
background: linear-gradient(135deg, var(--error), #dc2626);
animation: pulse 1.5s ease-in-out infinite;
}
@keyframes pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.1); }
}
.recording-time {
font-size: 24px;
margin-top: 20px;
color: var(--text-highlight);
}
.waveform {
height: 60px;
margin: 20px 0;
display: flex;
align-items: center;
justify-content: center;
gap: 3px;
}
.waveform-bar {
width: 4px;
background: var(--accent-blue);
border-radius: 2px;
animation: wave 1s ease-in-out infinite;
}
@keyframes wave {
0%, 100% { height: 10px; }
50% { height: 40px; }
}
.waveform-bar:nth-child(2) { animation-delay: 0.1s; }
.waveform-bar:nth-child(3) { animation-delay: 0.2s; }
.waveform-bar:nth-child(4) { animation-delay: 0.3s; }
.waveform-bar:nth-child(5) { animation-delay: 0.4s; }
/* 工程类型卡片 */
.project-type-card {
padding: 20px;
border: 2px solid var(--border-color);
border-radius: 8px;
cursor: pointer;
transition: all 0.3s;
background: var(--bg-card);
height: 100%;
}
.project-type-card:hover {
border-color: var(--border-hover);
transform: translateY(-5px);
}
.project-type-card.selected {
border-color: var(--accent-blue);
background: rgba(59, 130, 246, 0.2);
box-shadow: 0 0 20px rgba(59, 130, 246, 0.3);
}
.project-type-icon {
font-size: 48px;
margin-bottom: 15px;
}
/* Toast 通知 */
.toast-container {
position: fixed;
top: 80px;
right: 20px;
z-index: 9999;
}
.toast {
background: rgba(30, 41, 59, 0.95);
border: 1px solid var(--border-color);
color: var(--text-primary);
backdrop-filter: blur(15px);
min-width: 300px;
}
.toast.success {
border-color: var(--success);
}
.toast.error {
border-color: var(--error);
}
.toast.warning {
border-color: var(--warning);
}
/* 功能模块卡片 */
.module-card {
padding: 20px;
background: var(--bg-card);
border: 1px solid var(--border-color);
border-radius: 8px;
transition: all 0.3s;
height: 100%;
}
.module-card:hover {
border-color: var(--border-hover);
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
transform: translateY(-5px);
}
.module-icon {
font-size: 36px;
margin-bottom: 10px;
}
.complexity-stars {
color: var(--warning);
}
/* 下拉菜单 */
.dropdown-menu {
background: rgba(30, 41, 59, 0.95);
border: 1px solid var(--border-color);
backdrop-filter: blur(15px);
}
.dropdown-item {
color: var(--text-primary);
}
.dropdown-item:hover {
background: rgba(59, 130, 246, 0.2);
color: var(--text-primary);
}
/* 右键菜单 */
.context-menu {
position: fixed;
background: rgba(30, 41, 59, 0.95);
border: 1px solid var(--border-color);
border-radius: 8px;
padding: 8px 0;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
backdrop-filter: blur(15px);
z-index: 9999;
display: none;
}
.context-menu-item {
padding: 8px 20px;
cursor: pointer;
transition: all 0.2s;
display: flex;
align-items: center;
gap: 10px;
}
.context-menu-item:hover {
background: rgba(59, 130, 246, 0.2);
}
/* 文件上传区域 */
.upload-area {
border: 2px dashed var(--border-color);
border-radius: 8px;
padding: 40px;
text-align: center;
cursor: pointer;
transition: all 0.3s;
background: var(--bg-card);
}
.upload-area:hover {
border-color: var(--accent-blue);
background: rgba(59, 130, 246, 0.1);
}
.upload-area.dragover {
border-color: var(--accent-blue);
background: rgba(59, 130, 246, 0.2);
}
/* 标签输入 */
.tag-input-container {
display: flex;
flex-wrap: wrap;
gap: 8px;
padding: 8px;
background: rgba(51, 65, 85, 0.5);
border: 1px solid var(--border-color);
border-radius: 6px;
min-height: 42px;
}
.tag-item {
background: rgba(59, 130, 246, 0.2);
border: 1px solid var(--accent-blue);
padding: 4px 10px;
border-radius: 4px;
display: flex;
align-items: center;
gap: 5px;
font-size: 13px;
}
.tag-remove {
cursor: pointer;
color: var(--error);
}
/* 响应式调整 */
@media (max-width: 1200px) {
.main-content {
padding: 15px;
}
}
@media (max-width: 768px) {
.logo {
font-size: 18px;
}
.pipeline {
flex-direction: column;
}
.pipeline-step::after {
content: '↓';
right: 50%;
top: auto;
bottom: -20px;
transform: translateX(50%);
}
}
</style>
</head>
<body>
<!-- 顶部导航栏 -->
<nav class="top-navbar">
<div class="container-fluid">
<div class="d-flex justify-content-between align-items-center">
<div class="logo">
<i class="bi bi-lightning-charge-fill"></i> 智能低代码开发平台
</div>
<div class="d-flex gap-2 align-items-center">
<button class="btn btn-sm">
<i class="bi bi-search"></i>
</button>
<button class="btn btn-sm">
<i class="bi bi-gear"></i>
</button>
<button class="btn btn-sm">
<i class="bi bi-question-circle"></i>
</button>
<button class="btn btn-sm position-relative">
<i class="bi bi-bell"></i>
<span class="notification-badge">3</span>
</button>
<div class="d-flex align-items-center gap-2 ms-2">
<img src="https://via.placeholder.com/32" class="rounded-circle" alt="用户头像">
<span style="color: var(--text-primary);">管理员</span>
</div>
</div>
</div>
</div>
</nav>
<!-- 主内容区 -->
<div class="main-content">
<div class="row g-3">
<!-- 左侧:项目列表 -->
<div class="col-lg-3">
<div class="panel">
<div class="panel-header">项目列表</div>
<button class="btn btn-primary w-100 mb-3" data-bs-toggle="modal" data-bs-target="#newProjectModal">
<i class="bi bi-plus-circle"></i> 新建项目
</button>
<div class="project-search">
<input type="text" placeholder="搜索项目..." class="form-control form-control-sm">
</div>
<div class="scrollable-panel">
<div class="project-item active" onclick="selectProject(this, 0)">
<div class="project-name">智能监控系统</div>
<div class="project-desc">基于AI的实时监控平台</div>
<div class="project-meta">
<span>2024-01-15</span>
<span class="project-status status-active">进行中</span>
</div>
</div>
<div class="project-item" onclick="selectProject(this, 1)">
<div class="project-name">数据分析平台</div>
<div class="project-desc">大数据可视化分析工具</div>
<div class="project-meta">
<span>2024-01-10</span>
<span class="project-status status-completed">已完成</span>
</div>
</div>
<div class="project-item" onclick="selectProject(this, 2)">
<div class="project-name">物联网管理系统</div>
<div class="project-desc">设备管理与数据采集</div>
<div class="project-meta">
<span>2024-01-05</span>
<span class="project-status status-active">进行中</span>
</div>
</div>
<div class="project-item" onclick="selectProject(this, 3)">
<div class="project-name">电商管理系统</div>
<div class="project-desc">订单、库存、用户管理</div>
<div class="project-meta">
<span>2023-12-28</span>
<span class="project-status status-paused">已暂停</span>
</div>
</div>
</div>
</div>
</div>
<!-- 中间:需求与功能 -->
<div class="col-lg-6">
<div class="row g-3">
<!-- 需求板块 -->
<div class="col-12">
<div class="panel">
<div class="panel-header">需求管理</div>
<ul class="nav nav-tabs mb-3" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active" data-bs-toggle="tab" data-bs-target="#originalReq" type="button">
原始需求
</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#reqList" type="button">
需求列表
</button>
</li>
</ul>
<div class="tab-content scrollable-panel" style="max-height: 300px;">
<div class="tab-pane fade show active" id="originalReq">
<div class="alert" style="background: rgba(59, 130, 246, 0.1); border-color: var(--border-color); color: var(--text-primary);">
<div class="d-flex justify-content-between align-items-start mb-2">
<div>
<i class="bi bi-info-circle text-primary"></i>
<strong class="ms-2">录入方式:</strong>
<span class="badge bg-primary ms-2">文本输入</span>
</div>
<small class="text-secondary">2024-01-15 10:30</small>
</div>
<hr style="border-color: var(--border-color);">
<p class="mb-0">
需要开发一个智能监控系统,该系统应具备以下核心功能:<br><br>
1. 用户登录认证:支持用户通过用户名和密码进行登录,并集成多因素认证机制,确保账户安全性。<br>
2. 实时数据监控:平台需要实时采集设备数据,并通过可视化图表展示关键指标,支持异常告警。<br>
3. 数据导出功能支持将监控数据导出为Excel、CSV等格式便于后续分析和报告生成。<br>
4. 系统日志管理:记录所有系统操作日志,支持日志查询和审计。
</p>
</div>
</div>
<div class="tab-pane fade" id="reqList">
<div class="d-flex justify-content-between align-items-center mb-3">
<div>
<input type="checkbox" class="form-check-input me-2" id="selectAll">
<label for="selectAll">全选</label>
</div>
<div class="btn-group btn-group-sm">
<button class="btn btn-outline-primary">
<i class="bi bi-pencil"></i> 批量编辑
</button>
<button class="btn btn-outline-danger">
<i class="bi bi-trash"></i> 批量删除
</button>
<button class="btn btn-outline-success">
<i class="bi bi-plus"></i> 添加需求
</button>
</div>
</div>
<div class="item-card">
<div class="d-flex align-items-start gap-2">
<input class="form-check-input mt-1" type="checkbox" checked>
<div class="flex-grow-1">
<div class="d-flex justify-content-between align-items-start mb-2">
<div class="item-title">REQ-001 用户登录认证</div>
<div>
<span class="badge bg-success">高 95%</span>
<span class="badge bg-warning text-dark ms-1">高优先级</span>
</div>
</div>
<div class="item-desc">系统需要支持用户通过用户名和密码进行登录,并集成多因素认证机制,确保账户安全性。</div>
<div class="mt-2">
<button class="btn btn-sm btn-outline-primary">
<i class="bi bi-pencil"></i>
</button>
<button class="btn btn-sm btn-outline-danger ms-1">
<i class="bi bi-trash"></i>
</button>
</div>
</div>
</div>
</div>
<div class="item-card">
<div class="d-flex align-items-start gap-2">
<input class="form-check-input mt-1" type="checkbox" checked>
<div class="flex-grow-1">
<div class="d-flex justify-content-between align-items-start mb-2">
<div class="item-title">REQ-002 实时数据监控</div>
<div>
<span class="badge bg-success">高 92%</span>
<span class="badge bg-warning text-dark ms-1">高优先级</span>
</div>
</div>
<div class="item-desc">平台需要实时采集设备数据,并通过可视化图表展示关键指标,支持异常告警。</div>
<div class="mt-2">
<button class="btn btn-sm btn-outline-primary">
<i class="bi bi-pencil"></i>
</button>
<button class="btn btn-sm btn-outline-danger ms-1">
<i class="bi bi-trash"></i>
</button>
</div>
</div>
</div>
</div>
<div class="item-card">
<div class="d-flex align-items-start gap-2">
<input class="form-check-input mt-1" type="checkbox">
<div class="flex-grow-1">
<div class="d-flex justify-content-between align-items-start mb-2">
<div class="item-title">REQ-003 数据导出功能</div>
<div>
<span class="badge bg-warning text-dark">中 78%</span>
<span class="badge bg-info ms-1">中优先级</span>
</div>
</div>
<div class="item-desc">支持将监控数据导出为Excel、CSV等格式便于后续分析和报告生成。</div>
<div class="mt-2">
<button class="btn btn-sm btn-outline-primary">
<i class="bi bi-pencil"></i>
</button>
<button class="btn btn-sm btn-outline-danger ms-1">
<i class="bi bi-trash"></i>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 功能板块 -->
<div class="col-12">
<div class="panel">
<div class="d-flex justify-content-between align-items-center mb-3">
<div class="panel-header mb-0">功能模块</div>
<div class="btn-group btn-group-sm">
<button class="btn btn-outline-primary active">
<i class="bi bi-grid-3x3-gap"></i>
</button>
<button class="btn btn-outline-primary">
<i class="bi bi-list-ul"></i>
</button>
</div>
</div>
<div class="scrollable-panel" style="max-height: 300px;">
<div class="row g-2">
<div class="col-md-6">
<div class="module-card">
<div class="module-icon text-warning">
<i class="bi bi-shield-lock"></i>
</div>
<div class="item-title">用户认证模块</div>
<div class="mb-2">
<span class="badge bg-primary">REQ-001</span>
</div>
<div class="item-desc mb-2">实现登录、注册、密码重置、多因素认证等功能</div>
<div class="mb-2">
<span class="badge bg-secondary">Spring Boot</span>
<span class="badge bg-secondary ms-1">JWT</span>
</div>
<div class="progress mb-2" style="height: 6px;">
<div class="progress-bar" style="width: 85%"></div>
</div>
<div class="d-flex gap-1">
<button class="btn btn-sm btn-outline-primary flex-grow-1">
<i class="bi bi-gear"></i> 配置
</button>
<button class="btn btn-sm btn-outline-info">
<i class="bi bi-code"></i>
</button>
</div>
</div>
</div>
<div class="col-md-6">
<div class="module-card">
<div class="module-icon text-success">
<i class="bi bi-graph-up"></i>
</div>
<div class="item-title">数据监控模块</div>
<div class="mb-2">
<span class="badge bg-primary">REQ-002</span>
</div>
<div class="item-desc mb-2">实时数据采集、可视化展示、告警管理</div>
<div class="mb-2">
<span class="badge bg-secondary">ECharts</span>
<span class="badge bg-secondary ms-1">WebSocket</span>
</div>
<div class="progress mb-2" style="height: 6px;">
<div class="progress-bar" style="width: 60%"></div>
</div>
<div class="d-flex gap-1">
<button class="btn btn-sm btn-outline-primary flex-grow-1">
<i class="bi bi-gear"></i> 配置
</button>
<button class="btn btn-sm btn-outline-info">
<i class="bi bi-code"></i>
</button>
</div>
</div>
</div>
<div class="col-md-6">
<div class="module-card">
<div class="module-icon text-info">
<i class="bi bi-folder"></i>
</div>
<div class="item-title">数据管理模块</div>
<div class="mb-2">
<span class="badge bg-primary">REQ-003</span>
</div>
<div class="item-desc mb-2">数据查询、导出、备份与恢复</div>
<div class="mb-2">
<span class="badge bg-secondary">POI</span>
<span class="badge bg-secondary ms-1">MySQL</span>
</div>
<div class="progress mb-2" style="height: 6px;">
<div class="progress-bar" style="width: 40%"></div>
</div>
<div class="d-flex gap-1">
<button class="btn btn-sm btn-outline-primary flex-grow-1">
<i class="bi bi-gear"></i> 配置
</button>
<button class="btn btn-sm btn-outline-info">
<i class="bi bi-code"></i>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 右侧:文档与代码 -->
<div class="col-lg-3">
<div class="row g-3">
<!-- 文档板块 -->
<div class="col-12">
<div class="panel">
<div class="panel-header">项目文档</div>
<div class="scrollable-panel" style="max-height: 300px;">
<div class="doc-item">
<div class="doc-name">
<i class="bi bi-file-earmark-text fs-5"></i>
<div>
<div>需求规格说明书</div>
<div class="doc-meta">2.3 MB · 2024-01-15</div>
</div>
</div>
<div class="doc-actions">
<button class="btn btn-sm btn-outline-primary" onclick="viewDocument('需求规格说明书')">
<i class="bi bi-eye"></i>
</button>
<div class="btn-group">
<button class="btn btn-sm btn-outline-success dropdown-toggle" data-bs-toggle="dropdown">
<i class="bi bi-download"></i>
</button>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#" onclick="downloadDocument('需求规格说明书.docx')">Word (.docx)</a></li>
<li><a class="dropdown-item" href="#" onclick="downloadDocument('需求规格说明书.pdf')">PDF (.pdf)</a></li>
<li><a class="dropdown-item" href="#" onclick="downloadDocument('需求规格说明书.md')">Markdown (.md)</a></li>
</ul>
</div>
</div>
</div>
<div class="doc-item">
<div class="doc-name">
<i class="bi bi-file-earmark-code fs-5"></i>
<div>
<div>功能设计文档</div>
<div class="doc-meta">1.8 MB · 2024-01-15</div>
</div>
</div>
<div class="doc-actions">
<button class="btn btn-sm btn-outline-primary" onclick="viewDocument('功能设计文档')">
<i class="bi bi-eye"></i>
</button>
<div class="btn-group">
<button class="btn btn-sm btn-outline-success dropdown-toggle" data-bs-toggle="dropdown">
<i class="bi bi-download"></i>
</button>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#" onclick="downloadDocument('功能设计文档.docx')">Word (.docx)</a></li>
<li><a class="dropdown-item" href="#" onclick="downloadDocument('功能设计文档.pdf')">PDF (.pdf)</a></li>
<li><a class="dropdown-item" href="#" onclick="downloadDocument('功能设计文档.md')">Markdown (.md)</a></li>
</ul>
</div>
</div>
</div>
<div class="doc-item">
<div class="doc-name">
<i class="bi bi-diagram-3 fs-5"></i>
<div>
<div>软件概要设计文档</div>
<div class="doc-meta">3.1 MB · 2024-01-15</div>
</div>
</div>
<div class="doc-actions">
<button class="btn btn-sm btn-outline-primary" onclick="viewDocument('软件概要设计文档')">
<i class="bi bi-eye"></i>
</button>
<div class="btn-group">
<button class="btn btn-sm btn-outline-success dropdown-toggle" data-bs-toggle="dropdown">
<i class="bi bi-download"></i>
</button>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#" onclick="downloadDocument('软件概要设计文档.docx')">Word (.docx)</a></li>
<li><a class="dropdown-item" href="#" onclick="downloadDocument('软件概要设计文档.pdf')">PDF (.pdf)</a></li>
<li><a class="dropdown-item" href="#" onclick="downloadDocument('软件概要设计文档.md')">Markdown (.md)</a></li>
</ul>
</div>
</div>
</div>
<div class="doc-item">
<div class="doc-name">
<i class="bi bi-file-earmark-ruled fs-5"></i>
<div>
<div>软件详细设计文档</div>
<div class="doc-meta">4.5 MB · 2024-01-15</div>
</div>
</div>
<div class="doc-actions">
<button class="btn btn-sm btn-outline-primary" onclick="viewDocument('软件详细设计文档')">
<i class="bi bi-eye"></i>
</button>
<div class="btn-group">
<button class="btn btn-sm btn-outline-success dropdown-toggle" data-bs-toggle="dropdown">
<i class="bi bi-download"></i>
</button>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#" onclick="downloadDocument('软件详细设计文档.docx')">Word (.docx)</a></li>
<li><a class="dropdown-item" href="#" onclick="downloadDocument('软件详细设计文档.pdf')">PDF (.pdf)</a></li>
<li><a class="dropdown-item" href="#" onclick="downloadDocument('软件详细设计文档.md')">Markdown (.md)</a></li>
</ul>
</div>
</div>
</div>
<div class="doc-item">
<div class="doc-name">
<i class="bi bi-book fs-5"></i>
<div>
<div>接口文档</div>
<div class="doc-meta">1.2 MB · 2024-01-15</div>
</div>
</div>
<div class="doc-actions">
<button class="btn btn-sm btn-outline-primary" onclick="viewDocument('接口文档')">
<i class="bi bi-eye"></i>
</button>
<div class="btn-group">
<button class="btn btn-sm btn-outline-success dropdown-toggle" data-bs-toggle="dropdown">
<i class="bi bi-download"></i>
</button>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#" onclick="downloadDocument('接口文档.html')">HTML (.html)</a></li>
<li><a class="dropdown-item" href="#" onclick="downloadDocument('接口文档.pdf')">PDF (.pdf)</a></li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 代码板块 -->
<div class="col-12">
<div class="panel">
<div class="d-flex justify-content-between align-items-center mb-3">
<div class="panel-header mb-0">代码结构</div>
<div class="btn-group btn-group-sm">
<button class="btn btn-outline-success" onclick="downloadCode('all')">
<i class="bi bi-download"></i> 全部
</button>
</div>
</div>
<div class="scrollable-panel code-tree" style="max-height: 300px;">
<div class="tree-node tree-folder" onclick="toggleFolder(this)">
<span class="tree-toggle"></span>
<i class="bi bi-folder-fill"></i>
<span>智能监控系统</span>
</div>
<div class="tree-children">
<div class="tree-node tree-folder" onclick="toggleFolder(this)" style="padding-left: 30px;">
<span class="tree-toggle"></span>
<i class="bi bi-folder-fill"></i>
<span>src</span>
</div>
<div class="tree-children">
<div class="tree-node tree-file" style="padding-left: 50px;">
<span class="tree-toggle"></span>
<i class="bi bi-file-earmark-code"></i>
<span>Application.java</span>
<button class="btn btn-sm btn-outline-success ms-auto" onclick="downloadCode('Application.java')">
<i class="bi bi-download"></i>
</button>
</div>
<div class="tree-node tree-folder" onclick="toggleFolder(this)" style="padding-left: 50px;">
<span class="tree-toggle"></span>
<i class="bi bi-folder-fill"></i>
<span>modules</span>
</div>
<div class="tree-children">
<div class="tree-node tree-folder" onclick="toggleFolder(this)" style="padding-left: 70px;">
<span class="tree-toggle"></span>
<i class="bi bi-folder-fill"></i>
<span>auth</span>
</div>
<div class="tree-children">
<div class="tree-node tree-file" style="padding-left: 90px;">
<span class="tree-toggle"></span>
<i class="bi bi-file-earmark-code"></i>
<span>AuthController.java</span>
<button class="btn btn-sm btn-outline-success ms-auto" onclick="downloadCode('AuthController.java')">
<i class="bi bi-download"></i>
</button>
</div>
<div class="tree-node tree-file" style="padding-left: 90px;">
<span class="tree-toggle"></span>
<i class="bi bi-file-earmark-code"></i>
<span>AuthService.java</span>
<button class="btn btn-sm btn-outline-success ms-auto" onclick="downloadCode('AuthService.java')">
<i class="bi bi-download"></i>
</button>
</div>
</div>
<div class="tree-node tree-folder" onclick="toggleFolder(this)" style="padding-left: 70px;">
<span class="tree-toggle"></span>
<i class="bi bi-folder-fill"></i>
<span>monitor</span>
</div>
</div>
<div class="tree-node tree-folder" onclick="toggleFolder(this)" style="padding-left: 50px;">
<span class="tree-toggle"></span>
<i class="bi bi-folder-fill"></i>
<span>utils</span>
</div>
<div class="tree-node tree-folder" onclick="toggleFolder(this)" style="padding-left: 50px;">
<span class="tree-toggle"></span>
<i class="bi bi-folder-fill"></i>
<span>config</span>
</div>
</div>
<div class="tree-node tree-file" style="padding-left: 30px;">
<span class="tree-toggle"></span>
<i class="bi bi-file-earmark-text"></i>
<span>pom.xml</span>
<button class="btn btn-sm btn-outline-success ms-auto" onclick="downloadCode('pom.xml')">
<i class="bi bi-download"></i>
</button>
</div>
<div class="tree-node tree-file" style="padding-left: 30px;">
<span class="tree-toggle"></span>
<i class="bi bi-file-earmark-text"></i>
<span>README.md</span>
<button class="btn btn-sm btn-outline-success ms-auto" onclick="downloadCode('README.md')">
<i class="bi bi-download"></i>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 底部:操作流水线 -->
<div class="col-12">
<div class="panel">
<div class="d-flex justify-content-between align-items-center mb-3">
<div class="panel-header mb-0">流水线操作 </div>
<div class="btn-group btn-group-sm">
<button class="btn btn-success" onclick="startPipeline()">
<i class="bi bi-play-fill"></i> 启动
</button>
<button class="btn btn-warning" onclick="stopPipeline()">
<i class="bi bi-stop-fill"></i> 停止
</button>
<button class="btn btn-info" onclick="restartPipeline()">
<i class="bi bi-arrow-clockwise"></i> 重新运行
</button>
</div>
</div>
<div class="pipeline">
<div class="pipeline-step success" onclick="showPipelineDetail('scan')">
<div class="step-icon"><i class="bi bi-search"></i></div>
<div class="step-name">静态扫描</div>
<div class="step-status">已完成 · 2分15秒</div>
<small class="text-success">SonarQube</small>
</div>
<div class="pipeline-step active" onclick="showPipelineDetail('build')">
<div class="step-icon"><i class="bi bi-hammer"></i></div>
<div class="step-name">编译构建</div>
<div class="step-status">进行中 · 65%</div>
<div class="progress mt-2" style="height: 4px;">
<div class="progress-bar progress-bar-striped progress-bar-animated" style="width: 65%"></div>
</div>
</div>
<div class="pipeline-step" onclick="showPipelineDetail('package')">
<div class="step-icon"><i class="bi bi-box-seam"></i></div>
<div class="step-name">打包</div>
<div class="step-status">等待中</div>
<small class="text-secondary">JAR</small>
</div>
<div class="pipeline-step" onclick="showPipelineDetail('deploy')">
<div class="step-icon"><i class="bi bi-rocket-takeoff"></i></div>
<div class="step-name">部署</div>
<div class="step-status">等待中</div>
<small class="text-secondary">测试环境</small>
</div>
<div class="pipeline-step" onclick="showPipelineDetail('verify')">
<div class="step-icon"><i class="bi bi-check-circle"></i></div>
<div class="step-name">验证测试</div>
<div class="step-status">等待中</div>
<small class="text-secondary">0/25 通过</small>
</div>
</div>
<div class="mt-3 text-center">
<small class="text-secondary">总耗时: 3分42秒 · 预计剩余: 2分18秒</small>
</div>
</div>
</div>
</div>
</div>
<!-- 新建项目模态框 -->
<div class="modal fade" id="newProjectModal" tabindex="-1" data-bs-backdrop="static">
<div class="modal-dialog modal-xl modal-dialog-centered modal-dialog-scrollable">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">
<i class="bi bi-plus-circle"></i> 新建项目
</h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<!-- 步骤导航 -->
<div class="wizard-steps">
<div class="wizard-step active" id="wizardStep1">
<div class="wizard-step-number">1</div>
<div class="wizard-step-label">基本信息</div>
</div>
<div class="wizard-step" id="wizardStep2">
<div class="wizard-step-number">2</div>
<div class="wizard-step-label">需求分析</div>
</div>
<div class="wizard-step" id="wizardStep3">
<div class="wizard-step-number">3</div>
<div class="wizard-step-label">功能生成</div>
</div>
<div class="wizard-step" id="wizardStep4">
<div class="wizard-step-number">4</div>
<div class="wizard-step-label">工程生成</div>
</div>
</div>
<!-- 步骤1: 基本信息 -->
<div id="step1Content" class="wizard-content">
<div class="mb-3">
<label class="form-label">项目名称 <span class="text-danger">*</span></label>
<input type="text" class="form-control" id="projectName" placeholder="请输入项目名称" maxlength="50">
<small class="text-secondary">已输入 <span id="nameCount">0</span>/50 字符</small>
</div>
<div class="mb-3">
<label class="form-label">项目描述</label>
<textarea class="form-control" rows="3" placeholder="请输入项目描述"></textarea>
</div>
<div class="mb-3">
<label class="form-label">项目标签</label>
<div class="tag-input-container" id="tagContainer">
<input type="text" class="border-0 bg-transparent text-white flex-grow-1" placeholder="输入标签后按回车" id="tagInput" style="outline: none;">
</div>
<small class="text-secondary">预设标签:</small>
<div class="mt-2">
<button class="btn btn-sm btn-outline-primary me-1" onclick="addTag('Web应用')">Web应用</button>
<button class="btn btn-sm btn-outline-primary me-1" onclick="addTag('移动应用')">移动应用</button>
<button class="btn btn-sm btn-outline-primary me-1" onclick="addTag('后台服务')">后台服务</button>
<button class="btn btn-sm btn-outline-primary me-1" onclick="addTag('数据分析')">数据分析</button>
</div>
</div>
<div class="mb-3">
<label class="form-label">需求录入方式 <span class="text-danger">*</span></label>
<div class="row g-3">
<div class="col-md-4">
<div class="input-method-card" onclick="selectInputMethod('text')">
<div class="input-method-icon">📝</div>
<div class="input-method-title">文本输入</div>
<div class="input-method-desc">直接输入或粘贴需求文本</div>
</div>
</div>
<div class="col-md-4">
<div class="input-method-card" onclick="selectInputMethod('file')">
<div class="input-method-icon">📁</div>
<div class="input-method-title">文件导入</div>
<div class="input-method-desc">上传需求文档文件</div>
</div>
</div>
<div class="col-md-4">
<div class="input-method-card" onclick="selectInputMethod('voice')">
<div class="input-method-icon">🎤</div>
<div class="input-method-title">语音输入</div>
<div class="input-method-desc">通过语音描述需求</div>
</div>
</div>
</div>
</div>
<!-- 文本输入区域 -->
<div id="textInputArea" class="mb-3" style="display: none;">
<label class="form-label">需求内容 <span class="text-danger">*</span></label>
<div class="d-flex justify-content-between mb-2">
<small class="text-secondary">建议 500-5000 字</small>
<button class="btn btn-sm btn-outline-info" onclick="insertTemplate()">
<i class="bi bi-file-text"></i> 插入模板
</button>
</div>
<textarea class="form-control" rows="10" id="requirementText" placeholder="请输入需求描述..."></textarea>
<small class="text-secondary">已输入 <span id="textCount">0</span> 字符</small>
</div>
<!-- 文件上传区域 -->
<div id="fileInputArea" class="mb-3" style="display: none;">
<label class="form-label">上传需求文档 <span class="text-danger">*</span></label>
<div class="upload-area" id="uploadArea">
<i class="bi bi-cloud-upload fs-1 text-primary mb-3"></i>
<p>拖拽文件到此处或点击选择文件</p>
<small class="text-secondary">支持 .txt, .doc, .docx, .pdf, .md 格式,最大 10MB</small>
<input type="file" id="fileInput" class="d-none" accept=".txt,.doc,.docx,.pdf,.md">
</div>
<div id="filePreview" style="display: none;" class="mt-3">
<div class="alert alert-info d-flex justify-content-between align-items-center">
<div>
<i class="bi bi-file-earmark-text fs-4 me-2"></i>
<span id="fileName"></span>
<small class="text-secondary ms-2" id="fileSize"></small>
</div>
<div>
<button class="btn btn-sm btn-outline-danger" onclick="removeFile()">
<i class="bi bi-trash"></i> 删除
</button>
</div>
</div>
</div>
</div>
<!-- 语音输入区域 -->
<div id="voiceInputArea" class="mb-3" style="display: none;">
<label class="form-label">语音录制 <span class="text-danger">*</span></label>
<div class="voice-recorder">
<button class="mic-button" id="micButton" onclick="toggleRecording()">
<i class="bi bi-mic-fill"></i>
</button>
<div class="recording-time" id="recordingTime">00:00</div>
<div class="text-secondary mb-3">点击麦克风开始录入</div>
<div class="waveform" id="waveform" style="display: none;">
<div class="waveform-bar"></div>
<div class="waveform-bar"></div>
<div class="waveform-bar"></div>
<div class="waveform-bar"></div>
<div class="waveform-bar"></div>
</div>
<div class="mt-3">
<button class="btn btn-warning me-2" id="pauseBtn" style="display: none;" onclick="pauseRecording()">
<i class="bi bi-pause-fill"></i> 暂停
</button>
<button class="btn btn-danger me-2" id="stopBtn" style="display: none;" onclick="stopRecording()">
<i class="bi bi-stop-fill"></i> 停止录入
</button>
<button class="btn btn-info" id="resetBtn" style="display: none;" onclick="resetRecording()">
<i class="bi bi-arrow-clockwise"></i> 重新录制
</button>
</div>
<div class="mt-4">
<label class="form-label">实时转写文本</label>
<textarea class="form-control" rows="6" id="transcriptText" placeholder="语音识别结果将显示在这里..."></textarea>
<small class="text-secondary">识别置信度: <span id="confidence">--</span>%</small>
</div>
</div>
</div>
</div>
<!-- 步骤2: 需求分析 -->
<div id="step2Content" class="wizard-content" style="display: none;">
<div class="text-center mb-4" id="analysisProgress">
<div class="mb-3">
<i class="bi bi-robot fs-1 text-primary"></i>
</div>
<h5 class="mb-3">AI 正在分析需求...</h5>
<div class="progress mb-2" style="height: 12px;">
<div class="progress-bar progress-bar-striped progress-bar-animated" id="analysisProgressBar" style="width: 0%"></div>
</div>
<div class="d-flex justify-content-between">
<small class="text-secondary" id="analysisStage">正在解析需求文本...</small>
<small class="text-primary" id="analysisPercent">0%</small>
</div>
<div class="mt-2">
<small class="text-secondary">已识别需求: <span class="text-primary" id="identifiedCount">0</span></small>
</div>
</div>
<div id="requirementsList" style="display: none;">
<div class="d-flex justify-content-between align-items-center mb-3">
<h6>AI 已识别 <span class="text-primary" id="totalReqCount">0</span> 个需求条目</h6>
<div class="btn-group btn-group-sm">
<button class="btn btn-outline-primary" onclick="selectAllRequirements()">
<i class="bi bi-check-all"></i> 全选
</button>
<button class="btn btn-outline-secondary" onclick="deselectAllRequirements()">
<i class="bi bi-x"></i> 全不选
</button>
<button class="btn btn-outline-success" onclick="addManualRequirement()">
<i class="bi bi-plus"></i> 添加需求
</button>
</div>
</div>
<div id="requirementsContainer">
<!-- 需求卡片将动态生成 -->
</div>
</div>
</div>
<!-- 步骤3: 功能生成 -->
<div id="step3Content" class="wizard-content" style="display: none;">
<div class="text-center mb-4" id="moduleProgress">
<div class="mb-3">
<i class="bi bi-gear-fill fs-1 text-primary"></i>
</div>
<h5 class="mb-3">AI 正在生成功能模块...</h5>
<div class="progress mb-2" style="height: 12px;">
<div class="progress-bar progress-bar-striped progress-bar-animated" id="moduleProgressBar" style="width: 0%"></div>
</div>
<div class="d-flex justify-content-between">
<small class="text-secondary" id="moduleStage">正在分析需求关联...</small>
<small class="text-primary" id="modulePercent">0%</small>
</div>
<div class="mt-2">
<small class="text-secondary">已生成模块: <span class="text-primary" id="generatedModuleCount">0</span></small>
</div>
</div>
<div id="modulesList" style="display: none;">
<div class="d-flex justify-content-between align-items-center mb-3">
<h6>AI 已生成 <span class="text-primary" id="totalModuleCount">0</span> 个功能模块</h6>
<div class="btn-group btn-group-sm">
<button class="btn btn-outline-primary active">
<i class="bi bi-grid-3x3-gap"></i> 网格
</button>
<button class="btn btn-outline-primary">
<i class="bi bi-list-ul"></i> 列表
</button>
<button class="btn btn-outline-success">
<i class="bi bi-plus"></i> 添加模块
</button>
</div>
</div>
<div class="row g-3" id="modulesContainer">
<!-- 功能模块卡片将动态生成 -->
</div>
</div>
</div>
<!-- 步骤4: 工程生成 -->
<div id="step4Content" class="wizard-content" style="display: none;">
<div class="mb-4">
<label class="form-label">选择工程类型 <span class="text-danger">*</span></label>
<div class="row g-3">
<div class="col-md-4">
<div class="project-type-card" onclick="selectProjectType('java')">
<div class="project-type-icon"></div>
<h6>Java Spring Boot</h6>
<p class="text-secondary small mb-2">企业级 Java Web 应用</p>
<small class="text-secondary">Spring Boot + Maven</small>
</div>
</div>
<div class="col-md-4">
<div class="project-type-card" onclick="selectProjectType('qt')">
<div class="project-type-icon">🖥️</div>
<h6>Qt C++ 工程</h6>
<p class="text-secondary small mb-2">跨平台桌面应用</p>
<small class="text-secondary">Qt 5/6 + CMake</small>
</div>
</div>
<div class="col-md-4">
<div class="project-type-card" onclick="selectProjectType('makefile')">
<div class="project-type-icon">⚙️</div>
<h6>Makefile C/C++</h6>
<p class="text-secondary small mb-2">传统 C/C++ 项目</p>
<small class="text-secondary">GCC + Makefile</small>
</div>
</div>
<div class="col-md-4">
<div class="project-type-card" onclick="selectProjectType('python')">
<div class="project-type-icon">🐍</div>
<h6>Python Flask</h6>
<p class="text-secondary small mb-2">轻量级 Web 框架</p>
<small class="text-secondary">Flask + pip</small>
</div>
</div>
<div class="col-md-4">
<div class="project-type-card" onclick="selectProjectType('nodejs')">
<div class="project-type-icon">🟢</div>
<h6>Node.js Express</h6>
<p class="text-secondary small mb-2">JavaScript 后端框架</p>
<small class="text-secondary">Express + npm</small>
</div>
</div>
<div class="col-md-4">
<div class="project-type-card" onclick="selectProjectType('vue')">
<div class="project-type-icon">💚</div>
<h6>Vue.js 前端</h6>
<p class="text-secondary small mb-2">渐进式前端框架</p>
<small class="text-secondary">Vue 3 + Vite</small>
</div>
</div>
</div>
</div>
<div class="mb-3" id="projectConfig" style="display: none;">
<h6 class="mb-3">工程配置</h6>
<div class="row g-3">
<div class="col-md-6">
<label class="form-label">项目根目录名称</label>
<input type="text" class="form-control" placeholder="my-project">
</div>
<div class="col-md-6">
<label class="form-label">版本号</label>
<input type="text" class="form-control" value="1.0.0">
</div>
<div class="col-md-6">
<label class="form-label">包名/命名空间</label>
<input type="text" class="form-control" placeholder="com.example.project">
</div>
<div class="col-md-6">
<label class="form-label">作者信息</label>
<input type="text" class="form-control" placeholder="Your Name">
</div>
</div>
</div>
<div class="mb-3">
<h6 class="mb-3">文档生成选项</h6>
<div class="row g-2">
<div class="col-md-6">
<div class="form-check">
<input class="form-check-input" type="checkbox" checked id="doc1">
<label class="form-check-label" for="doc1">需求规格说明书 (SRS)</label>
</div>
</div>
<div class="col-md-6">
<div class="form-check">
<input class="form-check-input" type="checkbox" checked id="doc2">
<label class="form-check-label" for="doc2">功能设计文档</label>
</div>
</div>
<div class="col-md-6">
<div class="form-check">
<input class="form-check-input" type="checkbox" checked id="doc3">
<label class="form-check-label" for="doc3">软件概要设计文档 (HLD)</label>
</div>
</div>
<div class="col-md-6">
<div class="form-check">
<input class="form-check-input" type="checkbox" checked id="doc4">
<label class="form-check-label" for="doc4">软件详细设计文档 (LLD)</label>
</div>
</div>
<div class="col-md-6">
<div class="form-check">
<input class="form-check-input" type="checkbox" checked id="doc5">
<label class="form-check-label" for="doc5">接口文档 (API Docs)</label>
</div>
</div>
<div class="col-md-6">
<div class="form-check">
<input class="form-check-input" type="checkbox" checked id="doc6">
<label class="form-check-label" for="doc6">数据库设计文档</label>
</div>
</div>
<div class="col-md-6">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="doc7">
<label class="form-check-label" for="doc7">部署文档</label>
</div>
</div>
<div class="col-md-6">
<div class="form-check">
<input class="form-check-input" type="checkbox" checked id="doc8">
<label class="form-check-label" for="doc8">README.md</label>
</div>
</div>
</div>
<div class="mt-2">
<label class="form-label">文档格式</label>
<div class="d-flex gap-3">
<div class="form-check">
<input class="form-check-input" type="checkbox" checked id="format1">
<label class="form-check-label" for="format1">Word (.docx)</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" checked id="format2">
<label class="form-check-label" for="format2">PDF (.pdf)</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="format3">
<label class="form-check-label" for="format3">Markdown (.md)</label>
</div>
</div>
</div>
</div>
<div class="mb-3">
<h6 class="mb-3">代码生成选项</h6>
<div class="row g-2">
<div class="col-md-6">
<div class="form-check">
<input class="form-check-input" type="checkbox" checked id="code1">
<label class="form-check-label" for="code1">生成单元测试代码</label>
</div>
</div>
<div class="col-md-6">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="code2">
<label class="form-check-label" for="code2">生成 Docker 配置</label>
</div>
</div>
<div class="col-md-6">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="code3">
<label class="form-check-label" for="code3">生成 CI/CD 配置</label>
</div>
</div>
<div class="col-md-6">
<label class="form-label">代码注释语言</label>
<select class="form-select form-select-sm">
<option selected>中文</option>
<option>英文</option>
</select>
</div>
</div>
</div>
<div id="generationProgress" style="display: none;">
<hr>
<div class="text-center mb-4">
<div class="mb-3">
<div class="spinner-border text-primary" style="width: 4rem; height: 4rem;"></div>
</div>
<h5 class="mb-3">正在生成项目工程...</h5>
<div class="progress mb-2" style="height: 12px;">
<div class="progress-bar progress-bar-striped progress-bar-animated" id="genProgressBar" style="width: 0%"></div>
</div>
<div class="d-flex justify-content-between mb-3">
<small class="text-secondary" id="genStage">创建项目结构...</small>
<small class="text-primary" id="genPercent">0%</small>
</div>
<div class="row g-2 text-start">
<div class="col-md-6">
<small class="text-success">✅ 创建项目结构</small>
</div>
<div class="col-md-6">
<small class="text-primary">🔄 生成代码文件...</small>
</div>
<div class="col-md-6">
<small class="text-secondary">⏳ 生成文档...</small>
</div>
<div class="col-md-6">
<small class="text-secondary">⏳ 配置构建脚本...</small>
</div>
</div>
<div class="mt-3">
<small class="text-secondary">
已生成文件: <span class="text-primary">45</span> 个 ·
代码行数: <span class="text-primary">3,250</span> 行 ·
预计剩余: <span class="text-primary">1分30秒</span>
</small>
</div>
</div>
</div>
<div id="generationSuccess" style="display: none;">
<hr>
<div class="text-center">
<div class="mb-3">
<i class="bi bi-check-circle-fill text-success" style="font-size: 4rem;"></i>
</div>
<h4 class="text-success mb-3">项目生成成功!</h4>
<div class="row g-2 mb-4">
<div class="col-3">
<div class="card bg-transparent border-success">
<div class="card-body">
<h3 class="text-success">156</h3>
<small class="text-secondary">总文件数</small>
</div>
</div>
</div>
<div class="col-3">
<div class="card bg-transparent border-info">
<div class="card-body">
<h3 class="text-info">8,450</h3>
<small class="text-secondary">代码行数</small>
</div>
</div>
</div>
<div class="col-3">
<div class="card bg-transparent border-warning">
<div class="card-body">
<h3 class="text-warning">8</h3>
<small class="text-secondary">文档数量</small>
</div>
</div>
</div>
<div class="col-3">
<div class="card bg-transparent border-primary">
<div class="card-body">
<h3 class="text-primary">3:42</h3>
<small class="text-secondary">总耗时</small>
</div>
</div>
</div>
</div>
<div class="d-flex gap-2 justify-content-center">
<button class="btn btn-primary" onclick="viewGeneratedProject()">
<i class="bi bi-eye"></i> 查看项目
</button>
<button class="btn btn-success" onclick="downloadProject()">
<i class="bi bi-download"></i> 下载项目
</button>
<button class="btn btn-info" onclick="openInIDE()">
<i class="bi bi-code-square"></i> 在 IDE 中打开
</button>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" id="prevBtn" style="display: none;" onclick="previousStep()">
<i class="bi bi-arrow-left"></i> 上一步
</button>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
<button type="button" class="btn btn-primary" id="nextBtn" onclick="nextStep()">
下一步 <i class="bi bi-arrow-right"></i>
</button>
</div>
</div>
</div>
</div>
<!-- Toast 容器 -->
<div class="toast-container"></div>
<!-- 右键菜单 -->
<div class="context-menu" id="contextMenu">
<div class="context-menu-item" onclick="handleContextMenu('rename')">
<i class="bi bi-pencil"></i> 重命名
</div>
<div class="context-menu-item" onclick="handleContextMenu('delete')">
<i class="bi bi-trash text-danger"></i> 删除
</div>
<div class="context-menu-item" onclick="handleContextMenu('export')">
<i class="bi bi-box-arrow-up"></i> 导出
</div>
<div class="context-menu-item" onclick="handleContextMenu('copy')">
<i class="bi bi-files"></i> 复制
</div>
</div>
<!-- Bootstrap JS -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script>
let currentStep = 1;
let selectedInputMethod = '';
let isRecording = false;
let recordingInterval = null;
let recordingSeconds = 0;
let selectedProjectType = '';
// 项目选择
function selectProject(element, index) {
document.querySelectorAll('.project-item').forEach(item => {
item.classList.remove('active');
});
element.classList.add('active');
}
// 项目右键菜单
document.querySelectorAll('.project-item').forEach(item => {
item.addEventListener('contextmenu', function(e) {
e.preventDefault();
const menu = document.getElementById('contextMenu');
menu.style.display = 'block';
menu.style.left = e.pageX + 'px';
menu.style.top = e.pageY + 'px';
});
});
document.addEventListener('click', function() {
document.getElementById('contextMenu').style.display = 'none';
});
function handleContextMenu(action) {
showToast('info', `执行操作: ${action}`);
}
// 文档查看
function viewDocument(docName) {
showToast('info', `正在打开文档: ${docName}`);
}
// 文档下载
function downloadDocument(fileName) {
const content = `这是 ${fileName} 的内容\n\n生成时间: ${new Date().toLocaleString()}\n\n这是一个示例文档。`;
const blob = new Blob([content], { type: 'text/plain' });
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = fileName;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
showToast('success', `正在下载: ${fileName}`);
}
// 代码下载
function downloadCode(fileName) {
showToast('success', `正在下载: ${fileName}`);
}
// 树形结构折叠
function toggleFolder(element) {
const toggle = element.querySelector('.tree-toggle');
const children = element.nextElementSibling;
if (children && children.classList.contains('tree-children')) {
if (toggle.textContent === '▼') {
toggle.textContent = '▶';
children.style.display = 'none';
} else {
toggle.textContent = '▼';
children.style.display = 'block';
}
}
}
// 流水线操作
function startPipeline() {
showToast('success', '流水线已启动');
}
function stopPipeline() {
showToast('warning', '流水线已停止');
}
function restartPipeline() {
showToast('info', '流水线重新运行中...');
}
function showPipelineDetail(stage) {
showToast('info', `查看 ${stage} 详情`);
}
// Toast 通知
function showToast(type, message) {
const container = document.querySelector('.toast-container');
const iconMap = {
success: 'check-circle-fill',
error: 'exclamation-triangle-fill',
info: 'info-circle-fill',
warning: 'exclamation-circle-fill'
};
const colorMap = {
success: 'success',
error: 'danger',
info: 'primary',
warning: 'warning'
};
const toastEl = document.createElement('div');
toastEl.className = `toast ${type}`;
toastEl.setAttribute('role', 'alert');
toastEl.innerHTML = `
<div class="toast-body d-flex align-items-center">
<i class="bi bi-${iconMap[type]} text-${colorMap[type]} me-2 fs-5"></i>
<span class="flex-grow-1">${message}</span>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="toast"></button>
</div>
`;
container.appendChild(toastEl);
const toast = new bootstrap.Toast(toastEl, { delay: 3000 });
toast.show();
toastEl.addEventListener('hidden.bs.toast', function() {
toastEl.remove();
});
}
// 向导步骤控制
function nextStep() {
if (currentStep === 1) {
// 验证步骤1
const projectName = document.getElementById('projectName').value.trim();
if (!projectName) {
showToast('error', '请输入项目名称');
return;
}
if (!selectedInputMethod) {
showToast('error', '请选择需求录入方式');
return;
}
// 进入步骤2开始AI分析
document.getElementById('step1Content').style.display = 'none';
document.getElementById('wizardStep1').classList.remove('active');
document.getElementById('wizardStep1').classList.add('completed');
currentStep = 2;
document.getElementById('step2Content').style.display = 'block';
document.getElementById('wizardStep2').classList.add('active');
document.getElementById('prevBtn').style.display = 'inline-block';
// 模拟AI分析
simulateAnalysis();
} else if (currentStep === 2) {
// 验证至少选中一个需求
const checkedReqs = document.querySelectorAll('#requirementsContainer input[type="checkbox"]:checked');
if (checkedReqs.length === 0) {
showToast('error', '请至少选中一个需求');
return;
}
document.getElementById('step2Content').style.display = 'none';
document.getElementById('wizardStep2').classList.remove('active');
document.getElementById('wizardStep2').classList.add('completed');
currentStep = 3;
document.getElementById('step3Content').style.display = 'block';
document.getElementById('wizardStep3').classList.add('active');
// 模拟功能生成
simulateModuleGeneration();
} else if (currentStep === 3) {
document.getElementById('step3Content').style.display = 'none';
document.getElementById('wizardStep3').classList.remove('active');
document.getElementById('wizardStep3').classList.add('completed');
currentStep = 4;
document.getElementById('step4Content').style.display = 'block';
document.getElementById('wizardStep4').classList.add('active');
document.getElementById('nextBtn').innerHTML = '<i class="bi bi-check-circle"></i> 开始生成';
} else if (currentStep === 4) {
if (!selectedProjectType) {
showToast('error', '请选择工程类型');
return;
}
// 开始生成
document.getElementById('generationProgress').style.display = 'block';
document.getElementById('nextBtn').style.display = 'none';
document.getElementById('prevBtn').style.display = 'none';
simulateProjectGeneration();
}
}
function previousStep() {
if (currentStep > 1) {
document.getElementById(`step${currentStep}Content`).style.display = 'none';
document.getElementById(`wizardStep${currentStep}`).classList.remove('active');
currentStep--;
document.getElementById(`step${currentStep}Content`).style.display = 'block';
document.getElementById(`wizardStep${currentStep}`).classList.remove('completed');
document.getElementById(`wizardStep${currentStep}`).classList.add('active');
if (currentStep === 1) {
document.getElementById('prevBtn').style.display = 'none';
}
document.getElementById('nextBtn').innerHTML = '下一步 <i class="bi bi-arrow-right"></i>';
document.getElementById('nextBtn').style.display = 'inline-block';
}
}
// 需求录入方式选择
function selectInputMethod(method) {
selectedInputMethod = method;
document.querySelectorAll('.input-method-card').forEach(card => {
card.classList.remove('selected');
});
event.currentTarget.classList.add('selected');
// 隐藏所有输入区域
document.getElementById('textInputArea').style.display = 'none';
document.getElementById('fileInputArea').style.display = 'none';
document.getElementById('voiceInputArea').style.display = 'none';
// 显示对应区域
if (method === 'text') {
document.getElementById('textInputArea').style.display = 'block';
} else if (method === 'file') {
document.getElementById('fileInputArea').style.display = 'block';
} else if (method === 'voice') {
document.getElementById('voiceInputArea').style.display = 'block';
}
}
// 标签管理
const tags = [];
document.getElementById('tagInput').addEventListener('keypress', function(e) {
if (e.key === 'Enter' && this.value.trim()) {
addTag(this.value.trim());
this.value = '';
}
});
function addTag(tagText) {
if (!tags.includes(tagText)) {
tags.push(tagText);
const tagEl = document.createElement('div');
tagEl.className = 'tag-item';
tagEl.innerHTML = `
<span>${tagText}</span>
<i class="bi bi-x tag-remove" onclick="removeTag('${tagText}')"></i>
`;
document.getElementById('tagContainer').insertBefore(tagEl, document.getElementById('tagInput'));
}
}
function removeTag(tagText) {
const index = tags.indexOf(tagText);
if (index > -1) {
tags.splice(index, 1);
}
event.target.parentElement.remove();
}
// 项目名称字符计数
document.getElementById('projectName').addEventListener('input', function() {
document.getElementById('nameCount').textContent = this.value.length;
});
// 文本输入字符计数
document.getElementById('requirementText')?.addEventListener('input', function() {
document.getElementById('textCount').textContent = this.value.length;
});
// 插入模板
function insertTemplate() {
const template = `项目背景:
请描述项目的背景和目标
核心功能:
1. 功能一
2. 功能二
3. 功能三
用户角色:
- 管理员
- 普通用户
性能要求:
- 响应时间
- 并发用户数
安全要求:
- 数据加密
- 权限控制`;
document.getElementById('requirementText').value = template;
document.getElementById('textCount').textContent = template.length;
}
// 文件上传
const uploadArea = document.getElementById('uploadArea');
const fileInput = document.getElementById('fileInput');
uploadArea.addEventListener('click', () => fileInput.click());
uploadArea.addEventListener('dragover', (e) => {
e.preventDefault();
uploadArea.classList.add('dragover');
});
uploadArea.addEventListener('dragleave', () => {
uploadArea.classList.remove('dragover');
});
uploadArea.addEventListener('drop', (e) => {
e.preventDefault();
uploadArea.classList.remove('dragover');
if (e.dataTransfer.files.length) {
handleFileUpload(e.dataTransfer.files[0]);
}
});
fileInput.addEventListener('change', (e) => {
if (e.target.files.length) {
handleFileUpload(e.target.files[0]);
}
});
function handleFileUpload(file) {
const maxSize = 10 * 1024 * 1024; // 10MB
if (file.size > maxSize) {
showToast('error', '文件大小超过 10MB 限制');
return;
}
document.getElementById('fileName').textContent = file.name;
document.getElementById('fileSize').textContent = (file.size / 1024).toFixed(2) + ' KB';
document.getElementById('filePreview').style.display = 'block';
uploadArea.style.display = 'none';
}
function removeFile() {
document.getElementById('filePreview').style.display = 'none';
uploadArea.style.display = 'block';
fileInput.value = '';
}
// 语音录制
function toggleRecording() {
if (!isRecording) {
startRecording();
} else {
stopRecording();
}
}
function startRecording() {
isRecording = true;
recordingSeconds = 0;
document.getElementById('micButton').classList.add('recording');
document.getElementById('waveform').style.display = 'flex';
document.getElementById('pauseBtn').style.display = 'inline-block';
document.getElementById('stopBtn').style.display = 'inline-block';
recordingInterval = setInterval(() => {
recordingSeconds++;
const minutes = Math.floor(recordingSeconds / 60).toString().padStart(2, '0');
const seconds = (recordingSeconds % 60).toString().padStart(2, '0');
document.getElementById('recordingTime').textContent = `${minutes}:${seconds}`;
// 模拟实时转写
if (recordingSeconds % 3 === 0) {
const mockText = ['我想开发一个', '智能监控系统', '支持实时数据采集', '和可视化展示'];
const currentText = document.getElementById('transcriptText').value;
document.getElementById('transcriptText').value = currentText + ' ' + mockText[Math.floor(Math.random() * mockText.length)];
document.getElementById('confidence').textContent = (85 + Math.random() * 10).toFixed(1);
}
}, 1000);
}
function pauseRecording() {
if (recordingInterval) {
clearInterval(recordingInterval);
recordingInterval = null;
}
document.getElementById('micButton').classList.remove('recording');
document.getElementById('waveform').style.display = 'none';
showToast('info', '录制已暂停');
}
function stopRecording() {
isRecording = false;
if (recordingInterval) {
clearInterval(recordingInterval);
recordingInterval = null;
}
document.getElementById('micButton').classList.remove('recording');
document.getElementById('waveform').style.display = 'none';
document.getElementById('pauseBtn').style.display = 'none';
document.getElementById('stopBtn').style.display = 'none';
document.getElementById('resetBtn').style.display = 'inline-block';
showToast('success', '录制已完成');
}
function resetRecording() {
recordingSeconds = 0;
document.getElementById('recordingTime').textContent = '00:00';
document.getElementById('transcriptText').value = '';
document.getElementById('confidence').textContent = '--';
document.getElementById('resetBtn').style.display = 'none';
}
// 模拟AI需求分析
function simulateAnalysis() {
let progress = 0;
const stages = [
'正在解析需求文本...',
'正在识别功能点...',
'正在提取需求条目...',
'正在分类整理...'
];
let stageIndex = 0;
const interval = setInterval(() => {
progress += 5;
document.getElementById('analysisProgressBar').style.width = progress + '%';
document.getElementById('analysisPercent').textContent = progress + '%';
if (progress % 25 === 0 && stageIndex < stages.length) {
document.getElementById('analysisStage').textContent = stages[stageIndex];
stageIndex++;
}
document.getElementById('identifiedCount').textContent = Math.floor(progress / 25);
if (progress >= 100) {
clearInterval(interval);
setTimeout(() => {
document.getElementById('analysisProgress').style.display = 'none';
document.getElementById('requirementsList').style.display = 'block';
generateRequirementsList();
}, 500);
}
}, 100);
}
// 生成需求列表
function generateRequirementsList() {
const requirements = [
{ id: 'REQ-001', title: '用户登录认证', desc: '系统需要支持用户通过用户名和密码进行登录,并集成多因素认证机制', confidence: 95, priority: '高', type: '功能性' },
{ id: 'REQ-002', title: '实时数据监控', desc: '平台需要实时采集设备数据,并通过可视化图表展示关键指标', confidence: 92, priority: '高', type: '功能性' },
{ id: 'REQ-003', title: '数据导出功能', desc: '支持将监控数据导出为Excel、CSV等格式', confidence: 88, priority: '中', type: '功能性' },
{ id: 'REQ-004', title: '系统日志管理', desc: '记录所有系统操作日志,支持日志查询和审计', confidence: 85, priority: '中', type: '非功能性' }
];
document.getElementById('totalReqCount').textContent = requirements.length;
const container = document.getElementById('requirementsContainer');
container.innerHTML = '';
requirements.forEach(req => {
const confidenceClass = req.confidence >= 90 ? 'success' : req.confidence >= 70 ? 'warning' : 'danger';
const confidenceText = req.confidence >= 90 ? '高' : req.confidence >= 70 ? '中' : '低';
const card = document.createElement('div');
card.className = 'item-card';
card.innerHTML = `
<div class="d-flex align-items-start gap-2">
<input class="form-check-input mt-1" type="checkbox" checked>
<div class="flex-grow-1">
<div class="d-flex justify-content-between align-items-start mb-2">
<div class="item-title">${req.id} ${req.title}</div>
<div>
<span class="badge bg-${confidenceClass}">${confidenceText} ${req.confidence}%</span>
<span class="badge bg-${req.priority === '高' ? 'warning' : 'info'} text-dark ms-1">${req.priority}优先级</span>
</div>
</div>
<div class="item-desc mb-2">${req.desc}</div>
<div class="mb-2">
<span class="badge bg-secondary">${req.type}</span>
</div>
<input type="text" class="form-control form-control-sm" placeholder="添加需求描述...">
<div class="mt-2">
<button class="btn btn-sm btn-outline-primary">
<i class="bi bi-pencil"></i> 编辑
</button>
<button class="btn btn-sm btn-outline-danger ms-1">
<i class="bi bi-trash"></i> 删除
</button>
</div>
</div>
</div>
`;
container.appendChild(card);
});
}
// 需求全选/全不选
function selectAllRequirements() {
document.querySelectorAll('#requirementsContainer input[type="checkbox"]').forEach(cb => {
cb.checked = true;
});
}
function deselectAllRequirements() {
document.querySelectorAll('#requirementsContainer input[type="checkbox"]').forEach(cb => {
cb.checked = false;
});
}
function addManualRequirement() {
showToast('info', '添加手动需求功能');
}
// 模拟功能模块生成
function simulateModuleGeneration() {
let progress = 0;
const stages = [
'正在分析需求关联...',
'正在设计功能模块...',
'正在规划模块架构...',
'正在生成功能清单...'
];
let stageIndex = 0;
const interval = setInterval(() => {
progress += 5;
document.getElementById('moduleProgressBar').style.width = progress + '%';
document.getElementById('modulePercent').textContent = progress + '%';
if (progress % 25 === 0 && stageIndex < stages.length) {
document.getElementById('moduleStage').textContent = stages[stageIndex];
stageIndex++;
}
document.getElementById('generatedModuleCount').textContent = Math.floor(progress / 33);
if (progress >= 100) {
clearInterval(interval);
setTimeout(() => {
document.getElementById('moduleProgress').style.display = 'none';
document.getElementById('modulesList').style.display = 'block';
generateModulesList();
}, 500);
}
}, 100);
}
// 生成功能模块列表
function generateModulesList() {
const modules = [
{ name: '用户认证模块', icon: '🔐', reqs: ['REQ-001'], tech: ['Spring Boot', 'JWT'], progress: 0 },
{ name: '数据监控模块', icon: '📊', reqs: ['REQ-002'], tech: ['ECharts', 'WebSocket'], progress: 0 },
{ name: '数据管理模块', icon: '📁', reqs: ['REQ-003'], tech: ['POI', 'MySQL'], progress: 0 }
];
document.getElementById('totalModuleCount').textContent = modules.length;
const container = document.getElementById('modulesContainer');
container.innerHTML = '';
modules.forEach(module => {
const col = document.createElement('div');
col.className = 'col-md-6';
col.innerHTML = `
<div class="module-card">
<div class="module-icon">${module.icon}</div>
<div class="item-title">${module.name}</div>
<div class="mb-2">
${module.reqs.map(req => `<span class="badge bg-primary">${req}</span>`).join(' ')}
</div>
<div class="item-desc mb-2">功能模块描述...</div>
<div class="mb-2">
${module.tech.map(tech => `<span class="badge bg-secondary">${tech}</span>`).join(' ')}
</div>
<div class="progress mb-2" style="height: 6px;">
<div class="progress-bar" style="width: ${module.progress}%"></div>
</div>
<div class="d-flex gap-1">
<button class="btn btn-sm btn-outline-primary flex-grow-1">
<i class="bi bi-gear"></i> 配置
</button>
<button class="btn btn-sm btn-outline-danger">
<i class="bi bi-trash"></i>
</button>
</div>
</div>
`;
container.appendChild(col);
});
}
// 工程类型选择
function selectProjectType(type) {
selectedProjectType = type;
document.querySelectorAll('.project-type-card').forEach(card => {
card.classList.remove('selected');
});
event.currentTarget.classList.add('selected');
document.getElementById('projectConfig').style.display = 'block';
}
// 模拟项目生成
function simulateProjectGeneration() {
let progress = 0;
const stages = [
'创建项目结构...',
'生成代码文件...',
'生成文档...',
'配置构建脚本...',
'初始化版本控制...'
];
let stageIndex = 0;
const interval = setInterval(() => {
progress += 2;
document.getElementById('genProgressBar').style.width = progress + '%';
document.getElementById('genPercent').textContent = progress + '%';
if (progress % 20 === 0 && stageIndex < stages.length) {
document.getElementById('genStage').textContent = stages[stageIndex];
stageIndex++;
}
if (progress >= 100) {
clearInterval(interval);
setTimeout(() => {
document.getElementById('generationProgress').style.display = 'none';
document.getElementById('generationSuccess').style.display = 'block';
}, 500);
}
}, 100);
}
// 生成完成后的操作
function viewGeneratedProject() {
bootstrap.Modal.getInstance(document.getElementById('newProjectModal')).hide();
showToast('success', '项目已添加到列表');
resetWizard();
}
function downloadProject() {
showToast('success', '正在打包下载项目...');
}
function openInIDE() {
showToast('info', '正在打开 IDE...');
}
// 重置向导
function resetWizard() {
currentStep = 1;
selectedInputMethod = '';
selectedProjectType = '';
for (let i = 1; i <= 4; i++) {
document.getElementById(`step${i}Content`).style.display = i === 1 ? 'block' : 'none';
document.getElementById(`wizardStep${i}`).classList.remove('active', 'completed');
}
document.getElementById('wizardStep1').classList.add('active');
document.getElementById('prevBtn').style.display = 'none';
document.getElementById('nextBtn').innerHTML = '下一步 <i class="bi bi-arrow-right"></i>';
document.getElementById('nextBtn').style.display = 'inline-block';
// 重置表单
document.getElementById('projectName').value = '';
document.getElementById('nameCount').textContent = '0';
// 重置进度显示
document.getElementById('analysisProgress').style.display = 'block';
document.getElementById('requirementsList').style.display = 'none';
document.getElementById('moduleProgress').style.display = 'block';
document.getElementById('modulesList').style.display = 'none';
document.getElementById('generationProgress').style.display = 'none';
document.getElementById('generationSuccess').style.display = 'none';
}
// 模态框关闭时重置
document.getElementById('newProjectModal').addEventListener
('hidden.bs.modal', function () {
resetWizard();
});
// 快捷键支持
document.addEventListener('keydown', function(e) {
// Ctrl/Cmd + N: 新建项目
if ((e.ctrlKey || e.metaKey) && e.key === 'n') {
e.preventDefault();
const modal = new bootstrap.Modal(document.getElementById('newProjectModal'));
modal.show();
}
// Ctrl/Cmd + K: 全局搜索
if ((e.ctrlKey || e.metaKey) && e.key === 'k') {
e.preventDefault();
showToast('info', '全局搜索功能');
}
// Esc: 关闭模态框
if (e.key === 'Escape') {
const modals = document.querySelectorAll('.modal.show');
modals.forEach(modal => {
bootstrap.Modal.getInstance(modal)?.hide();
});
}
});
// 页面加载动画
window.addEventListener('load', function() {
document.querySelectorAll('.panel').forEach((panel, index) => {
panel.style.opacity = '0';
panel.style.transform = 'translateY(20px)';
setTimeout(() => {
panel.style.transition = 'all 0.5s ease';
panel.style.opacity = '1';
panel.style.transform = 'translateY(0)';
}, index * 100);
});
});
// 搜索功能
document.querySelector('.project-search input')?.addEventListener('input', function(e) {
const searchTerm = e.target.value.toLowerCase();
document.querySelectorAll('.project-item').forEach(item => {
const name = item.querySelector('.project-name').textContent.toLowerCase();
const desc = item.querySelector('.project-desc').textContent.toLowerCase();
if (name.includes(searchTerm) || desc.includes(searchTerm)) {
item.style.display = 'block';
} else {
item.style.display = 'none';
}
});
});
// 模块配置弹窗
function showModuleConfig(moduleName) {
const modalHtml = `
<div class="modal fade" id="moduleConfigModal" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">配置模块: ${moduleName}</h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<ul class="nav nav-tabs mb-3" role="tablist">
<li class="nav-item">
<button class="nav-link active" data-bs-toggle="tab" data-bs-target="#basicInfo">基本信息</button>
</li>
<li class="nav-item">
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#techStack">技术选型</button>
</li>
<li class="nav-item">
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#apiDesign">接口设计</button>
</li>
<li class="nav-item">
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#dataModel">数据模型</button>
</li>
</ul>
<div class="tab-content">
<div class="tab-pane fade show active" id="basicInfo">
<div class="mb-3">
<label class="form-label">模块名称</label>
<input type="text" class="form-control" value="${moduleName}">
</div>
<div class="mb-3">
<label class="form-label">模块描述</label>
<textarea class="form-control" rows="3"></textarea>
</div>
<div class="mb-3">
<label class="form-label">模块类型</label>
<select class="form-select">
<option>前端模块</option>
<option selected>后端模块</option>
<option>服务模块</option>
<option>工具模块</option>
</select>
</div>
</div>
<div class="tab-pane fade" id="techStack">
<div class="mb-3">
<label class="form-label">编程语言</label>
<select class="form-select">
<option selected>Java</option>
<option>Python</option>
<option>JavaScript</option>
<option>C++</option>
</select>
</div>
<div class="mb-3">
<label class="form-label">框架选择</label>
<select class="form-select">
<option selected>Spring Boot</option>
<option>Spring MVC</option>
<option>Micronaut</option>
</select>
</div>
<div class="mb-3">
<label class="form-label">数据库</label>
<select class="form-select">
<option selected>MySQL</option>
<option>PostgreSQL</option>
<option>MongoDB</option>
<option>Oracle</option>
</select>
</div>
</div>
<div class="tab-pane fade" id="apiDesign">
<button class="btn btn-sm btn-primary mb-3">
<i class="bi bi-plus"></i> 添加接口
</button>
<div class="table-responsive">
<table class="table table-dark table-hover">
<thead>
<tr>
<th>接口路径</th>
<th>方法</th>
<th>描述</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr>
<td>/api/auth/login</td>
<td><span class="badge bg-success">POST</span></td>
<td>用户登录</td>
<td>
<button class="btn btn-sm btn-outline-primary"><i class="bi bi-pencil"></i></button>
<button class="btn btn-sm btn-outline-danger"><i class="bi bi-trash"></i></button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="tab-pane fade" id="dataModel">
<button class="btn btn-sm btn-primary mb-3">
<i class="bi bi-plus"></i> 添加数据表
</button>
<div class="accordion" id="tableAccordion">
<div class="accordion-item bg-transparent border-secondary">
<h2 class="accordion-header">
<button class="accordion-button bg-transparent text-white" type="button" data-bs-toggle="collapse" data-bs-target="#table1">
用户表 (user)
</button>
</h2>
<div id="table1" class="accordion-collapse collapse show">
<div class="accordion-body">
<table class="table table-sm table-dark">
<thead>
<tr>
<th>字段名</th>
<th>类型</th>
<th>约束</th>
</tr>
</thead>
<tbody>
<tr>
<td>id</td>
<td>BIGINT</td>
<td>PRIMARY KEY</td>
</tr>
<tr>
<td>username</td>
<td>VARCHAR(50)</td>
<td>NOT NULL, UNIQUE</td>
</tr>
<tr>
<td>password</td>
<td>VARCHAR(255)</td>
<td>NOT NULL</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
<button type="button" class="btn btn-primary" onclick="saveModuleConfig()">保存配置</button>
</div>
</div>
</div>
</div>
`;
// 移除旧的模态框
const oldModal = document.getElementById('moduleConfigModal');
if (oldModal) {
oldModal.remove();
}
// 添加新模态框
document.body.insertAdjacentHTML('beforeend', modalHtml);
const modal = new bootstrap.Modal(document.getElementById('moduleConfigModal'));
modal.show();
}
function saveModuleConfig() {
showToast('success', '模块配置已保存');
bootstrap.Modal.getInstance(document.getElementById('moduleConfigModal')).hide();
}
// 代码预览弹窗
function showCodePreview(fileName, code) {
const modalHtml = `
<div class="modal fade" id="codePreviewModal" tabindex="-1">
<div class="modal-dialog modal-xl">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">
<i class="bi bi-file-earmark-code"></i> ${fileName}
</h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<div class="d-flex justify-content-between mb-2">
<div>
<span class="badge bg-success">代码质量: A</span>
<span class="badge bg-info ms-1">156 行</span>
</div>
<button class="btn btn-sm btn-outline-primary" onclick="copyCode()">
<i class="bi bi-clipboard"></i> 复制代码
</button>
</div>
<pre class="bg-dark p-3 rounded" style="max-height: 500px; overflow-y: auto;"><code class="language-java" id="codeContent">${code || `package com.example.auth;
import org.springframework.web.bind.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 用户认证控制器
* @author AI Generator
* @date 2024-01-15
*/
@RestController
@RequestMapping("/api/auth")
public class AuthController {
@Autowired
private AuthService authService;
/**
* 用户登录
* @param loginRequest 登录请求
* @return 登录响应
*/
@PostMapping("/login")
public ResponseEntity<LoginResponse> login(@RequestBody LoginRequest loginRequest) {
// 验证用户名和密码
User user = authService.authenticate(
loginRequest.getUsername(),
loginRequest.getPassword()
);
if (user != null) {
// 生成 JWT Token
String token = jwtUtil.generateToken(user);
return ResponseEntity.ok(new LoginResponse(token, user));
} else {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
.body(new LoginResponse("认证失败"));
}
}
/**
* 用户注册
* @param registerRequest 注册请求
* @return 注册响应
*/
@PostMapping("/register")
public ResponseEntity<RegisterResponse> register(@RequestBody RegisterRequest registerRequest) {
// 检查用户名是否已存在
if (authService.userExists(registerRequest.getUsername())) {
return ResponseEntity.status(HttpStatus.CONFLICT)
.body(new RegisterResponse("用户名已存在"));
}
// 创建新用户
User newUser = authService.createUser(registerRequest);
return ResponseEntity.ok(new RegisterResponse("注册成功", newUser));
}
}`}</code></pre>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>
<button type="button" class="btn btn-success" onclick="downloadCode('${fileName}')">
<i class="bi bi-download"></i> 下载
</button>
</div>
</div>
</div>
</div>
`;
const oldModal = document.getElementById('codePreviewModal');
if (oldModal) {
oldModal.remove();
}
document.body.insertAdjacentHTML('beforeend', modalHtml);
const modal = new bootstrap.Modal(document.getElementById('codePreviewModal'));
modal.show();
}
function copyCode() {
const code = document.getElementById('codeContent').textContent;
navigator.clipboard.writeText(code).then(() => {
showToast('success', '代码已复制到剪贴板');
});
}
// 流水线日志查看
function showPipelineLog(stage) {
const logs = {
scan: `[INFO] 开始静态代码扫描...
[INFO] 扫描工具: SonarQube 9.9
[INFO] 扫描文件: 156 个
[INFO] 发现问题: 3 个
[WARN] 代码复杂度较高: AuthService.java:45
[WARN] 未使用的导入: UserController.java:12
[INFO] 代码覆盖率: 85%
[INFO] 扫描完成,耗时: 2分15秒`,
build: `[INFO] 开始编译构建...
[INFO] 构建工具: Maven 3.8.6
[INFO] JDK 版本: 17.0.5
[INFO] 下载依赖...
[INFO] 编译源代码...
[INFO] 编译测试代码...
[INFO] 运行单元测试...
[INFO] 测试通过: 45/48
[WARN] 测试失败: 3 个
[INFO] 构建进度: 65%`,
package: `[INFO] 开始打包...
[INFO] 打包格式: JAR
[INFO] 包含资源文件...
[INFO] 生成 MANIFEST.MF
[INFO] 打包完成
[INFO] 输出文件: target/smart-monitor-1.0.0.jar
[INFO] 文件大小: 45.6 MB`,
deploy: `[INFO] 准备部署...
[INFO] 目标环境: 测试环境
[INFO] 服务器: 192.168.1.100:8080
[INFO] 上传部署包...
[INFO] 停止旧服务...
[INFO] 启动新服务...
[INFO] 健康检查...
[INFO] 部署成功`,
verify: `[INFO] 开始验证测试...
[INFO] 测试用例总数: 25
[INFO] 运行接口测试...
[INFO] 运行性能测试...
[INFO] 运行安全测试...
[INFO] 测试通过: 22/25
[WARN] 测试失败: 3 个
[INFO] 测试通过率: 88%`
};
const modalHtml = `
<div class="modal fade" id="logModal" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">
<i class="bi bi-terminal"></i> ${stage} 日志
</h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<div class="d-flex justify-content-between mb-2">
<div class="btn-group btn-group-sm">
<button class="btn btn-outline-primary active">全部</button>
<button class="btn btn-outline-info">INFO</button>
<button class="btn btn-outline-warning">WARN</button>
<button class="btn btn-outline-danger">ERROR</button>
</div>
<button class="btn btn-sm btn-outline-success" onclick="exportLog()">
<i class="bi bi-download"></i> 导出日志
</button>
</div>
<pre class="bg-dark p-3 rounded" style="max-height: 400px; overflow-y: auto; font-family: 'Consolas', monospace; font-size: 13px;">${logs[stage] || '暂无日志'}</pre>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>
</div>
</div>
</div>
</div>
`;
const oldModal = document.getElementById('logModal');
if (oldModal) {
oldModal.remove();
}
document.body.insertAdjacentHTML('beforeend', modalHtml);
const modal = new bootstrap.Modal(document.getElementById('logModal'));
modal.show();
}
function exportLog() {
showToast('success', '日志已导出');
}
// 添加代码树点击事件
document.querySelectorAll('.tree-file').forEach(node => {
node.addEventListener('dblclick', function() {
const fileName = this.querySelector('span').textContent;
showCodePreview(fileName);
});
});
// 添加流水线步骤点击事件
document.querySelectorAll('.pipeline-step').forEach(step => {
const originalOnclick = step.getAttribute('onclick');
step.setAttribute('onclick', originalOnclick + '; event.stopPropagation();');
step.addEventListener('dblclick', function() {
const stageName = this.querySelector('.step-name').textContent;
const stageMap = {
'静态扫描': 'scan',
'编译构建': 'build',
'打包': 'package',
'部署': 'deploy',
'验证测试': 'verify'
};
showPipelineLog(stageMap[stageName]);
});
});
// 初始化提示
setTimeout(() => {
showToast('info', '欢迎使用智能低代码开发平台!按 Ctrl+N 创建新项目');
}, 1000);
// 自动保存功能
let autoSaveTimer = null;
function enableAutoSave() {
const inputs = document.querySelectorAll('input[type="text"], textarea');
inputs.forEach(input => {
input.addEventListener('input', function() {
clearTimeout(autoSaveTimer);
autoSaveTimer = setTimeout(() => {
console.log('自动保存...');
// 这里可以添加实际的保存逻辑
}, 30000); // 30秒后自动保存
});
});
}
enableAutoSave();
// 网络状态监听
window.addEventListener('online', function() {
showToast('success', '网络已连接');
});
window.addEventListener('offline', function() {
showToast('warning', '网络已断开,数据将保存在本地');
});
// 页面可见性变化
document.addEventListener('visibilitychange', function() {
if (document.hidden) {
console.log('页面已隐藏');
} else {
console.log('页面已显示');
// 可以在这里刷新数据
}
});
// 防止意外关闭
window.addEventListener('beforeunload', function(e) {
if (currentStep > 1 && currentStep < 4) {
e.preventDefault();
e.returnValue = '您有未完成的项目创建,确定要离开吗?';
return e.returnValue;
}
});
// 性能监控
if ('PerformanceObserver' in window) {
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.duration > 1000) {
console.warn(`性能警告: ${entry.name} 耗时 ${entry.duration}ms`);
}
}
});
observer.observe({ entryTypes: ['measure', 'navigation'] });
}
console.log('%c智能低代码开发平台', 'color: #3b82f6; font-size: 24px; font-weight: bold;');
console.log('%c版本: 1.0.0', 'color: #94a3b8; font-size: 14px;');
console.log('%c基于 Bootstrap 5 + 原生 JavaScript 构建', 'color: #94a3b8; font-size: 12px;');
</script>
</body>
</html>