AIDeveloper-PC/prototype/index-v2.html

3301 lines
126 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!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>