mirror of
https://github.com/Ed1s0nZ/CyberStrikeAI.git
synced 2026-03-31 16:20:28 +02:00
474 lines
28 KiB
HTML
474 lines
28 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>CyberStrikeAI - 自主渗透测试平台</title>
|
||
<link rel="icon" type="image/png" href="/static/logo.png">
|
||
<link rel="shortcut icon" type="image/png" href="/static/favicon.ico">
|
||
<link rel="stylesheet" href="/static/css/style.css">
|
||
</head>
|
||
<body>
|
||
<div id="login-overlay" class="login-overlay" style="display: none;">
|
||
<div class="login-card">
|
||
<div class="login-header">
|
||
<h2>登录 CyberStrikeAI</h2>
|
||
<p class="login-subtitle">请输入配置中的访问密码</p>
|
||
</div>
|
||
<form id="login-form" class="login-form">
|
||
<div class="form-group">
|
||
<label for="login-password">密码</label>
|
||
<input type="password" id="login-password" placeholder="输入登录密码" required autocomplete="current-password" />
|
||
</div>
|
||
<div id="login-error" class="login-error" role="alert" style="display: none;"></div>
|
||
<button type="submit" class="btn-primary login-submit">登录</button>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="container">
|
||
<header>
|
||
<div class="header-content">
|
||
<div class="logo">
|
||
<img src="/static/logo.png" alt="CyberStrikeAI Logo" style="width: 32px; height: 32px; margin-right: 8px;">
|
||
<h1>CyberStrikeAI</h1>
|
||
</div>
|
||
<div class="header-right">
|
||
<p class="header-subtitle">AI 驱动的自动化安全测试平台</p>
|
||
<div class="header-actions">
|
||
<button id="attack-chain-btn" class="attack-chain-btn" title="请选择一个对话以查看攻击链" disabled>
|
||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||
<path d="M10.5 13.5l3-3M8 8H5a4 4 0 1 0 0 8h3m8-8h3a4 4 0 0 1 0 8h-3" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||
</svg>
|
||
<span>攻击链</span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</header>
|
||
|
||
<div class="main-layout">
|
||
<!-- 主侧边栏 -->
|
||
<aside class="main-sidebar" id="main-sidebar">
|
||
<div class="sidebar-collapse-btn" onclick="toggleSidebar()" title="折叠/展开侧边栏">
|
||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||
<path d="M15 18l-6-6 6-6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||
</svg>
|
||
</div>
|
||
<nav class="main-sidebar-nav">
|
||
<div class="nav-item" data-page="chat">
|
||
<div class="nav-item-content" data-title="对话" onclick="switchPage('chat')">
|
||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||
<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||
</svg>
|
||
<span>对话</span>
|
||
</div>
|
||
</div>
|
||
<div class="nav-item nav-item-has-submenu" data-page="mcp">
|
||
<div class="nav-item-content" data-title="MCP" onclick="toggleSubmenu('mcp')">
|
||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||
<path d="M3 12h4l3 8 4-16 3 8h4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||
</svg>
|
||
<span>MCP</span>
|
||
<svg class="submenu-arrow" width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||
<path d="M9 18l6-6-6-6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||
</svg>
|
||
</div>
|
||
<div class="nav-submenu">
|
||
<div class="nav-submenu-item" data-page="mcp-monitor" onclick="switchPage('mcp-monitor')">
|
||
<span>MCP状态监控</span>
|
||
</div>
|
||
<div class="nav-submenu-item" data-page="mcp-management" onclick="switchPage('mcp-management')">
|
||
<span>MCP管理</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="nav-item" data-page="settings">
|
||
<div class="nav-item-content" data-title="系统设置" onclick="switchPage('settings')">
|
||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||
<path d="M12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||
<path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||
</svg>
|
||
<span>系统设置</span>
|
||
</div>
|
||
</div>
|
||
</nav>
|
||
</aside>
|
||
|
||
<!-- 内容区域 -->
|
||
<div class="content-area">
|
||
<!-- 对话页面 -->
|
||
<div id="page-chat" class="page active">
|
||
<div class="chat-page-layout">
|
||
<!-- 历史对话侧边栏 -->
|
||
<aside class="conversation-sidebar">
|
||
<div class="sidebar-header">
|
||
<button class="new-chat-btn" onclick="startNewConversation()">
|
||
<span>+</span> 新对话
|
||
</button>
|
||
</div>
|
||
<div class="sidebar-content">
|
||
<div class="sidebar-title">历史对话</div>
|
||
<div id="conversations-list" class="conversations-list"></div>
|
||
</div>
|
||
</aside>
|
||
|
||
<!-- 对话界面 -->
|
||
<div class="chat-container">
|
||
<div id="active-tasks-bar" class="active-tasks-bar"></div>
|
||
<div id="chat-messages" class="chat-messages"></div>
|
||
<div class="chat-input-container">
|
||
<div class="chat-input-field">
|
||
<textarea id="chat-input" placeholder="输入测试目标或命令... (Shift+Enter 换行,Enter 发送)" rows="1"></textarea>
|
||
<div id="mention-suggestions" class="mention-suggestions" role="listbox" aria-label="工具提及候选"></div>
|
||
</div>
|
||
<button onclick="sendMessage()">发送</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- MCP状态监控页面 -->
|
||
<div id="page-mcp-monitor" class="page">
|
||
<div class="page-header">
|
||
<h2>MCP 状态监控</h2>
|
||
<button class="btn-secondary" onclick="refreshMonitorPanel()">刷新</button>
|
||
</div>
|
||
<div class="page-content">
|
||
<div class="monitor-sections">
|
||
<section class="monitor-section monitor-overview">
|
||
<div class="section-header">
|
||
<h3>执行统计</h3>
|
||
</div>
|
||
<div id="monitor-stats" class="monitor-stats-grid">
|
||
<div class="monitor-empty">加载中...</div>
|
||
</div>
|
||
</section>
|
||
<section class="monitor-section monitor-executions">
|
||
<div class="section-header">
|
||
<h3>最新执行记录</h3>
|
||
<div class="section-actions">
|
||
<label>
|
||
状态筛选
|
||
<select id="monitor-status-filter" onchange="applyMonitorFilters()">
|
||
<option value="all">全部</option>
|
||
<option value="completed">已完成</option>
|
||
<option value="running">执行中</option>
|
||
<option value="failed">失败</option>
|
||
</select>
|
||
</label>
|
||
</div>
|
||
</div>
|
||
<div id="monitor-executions" class="monitor-table-container">
|
||
<div class="monitor-empty">加载中...</div>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- MCP管理页面 -->
|
||
<div id="page-mcp-management" class="page">
|
||
<div class="page-header">
|
||
<h2>MCP 管理</h2>
|
||
<div class="page-header-actions">
|
||
<button class="btn-secondary" onclick="loadExternalMCPs()">刷新</button>
|
||
<button class="btn-primary" onclick="showAddExternalMCPModal()">添加外部MCP</button>
|
||
</div>
|
||
</div>
|
||
<div class="page-content">
|
||
<!-- MCP工具配置 -->
|
||
<div class="settings-section" style="margin-bottom: 32px;">
|
||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px;">
|
||
<h3 style="margin: 0;">MCP 工具配置</h3>
|
||
<button class="btn-primary" onclick="saveToolsConfig()">保存工具配置</button>
|
||
</div>
|
||
<div class="tools-controls">
|
||
<div class="tools-actions">
|
||
<button class="btn-secondary" onclick="selectAllTools()">全选</button>
|
||
<button class="btn-secondary" onclick="deselectAllTools()">全不选</button>
|
||
<div class="search-box">
|
||
<input type="text" id="tools-search" placeholder="搜索工具..." onkeypress="handleSearchKeyPress(event)" oninput="if(this.value.trim() === '') clearSearch()" />
|
||
<button class="btn-search" onclick="searchTools()" title="搜索">🔍</button>
|
||
</div>
|
||
<div class="tools-stats" id="tools-stats"></div>
|
||
</div>
|
||
<div id="tools-list" class="tools-list"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 外部MCP配置 -->
|
||
<div class="settings-section">
|
||
<h3>外部 MCP 配置</h3>
|
||
<div class="external-mcp-controls">
|
||
<div class="external-mcp-actions">
|
||
<div class="external-mcp-stats" id="external-mcp-stats"></div>
|
||
</div>
|
||
<div id="external-mcp-list" class="external-mcp-list"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 系统设置页面 -->
|
||
<div id="page-settings" class="page">
|
||
<div class="page-header">
|
||
<h2>系统设置</h2>
|
||
</div>
|
||
<div class="page-content settings-body">
|
||
<!-- OpenAI配置 -->
|
||
<div class="settings-section">
|
||
<h3>OpenAI 配置</h3>
|
||
<div class="settings-form">
|
||
<div class="form-group">
|
||
<label for="openai-base-url">Base URL <span style="color: red;">*</span></label>
|
||
<input type="text" id="openai-base-url" placeholder="https://api.openai.com/v1" required />
|
||
</div>
|
||
<div class="form-group">
|
||
<label for="openai-api-key">API Key <span style="color: red;">*</span></label>
|
||
<input type="password" id="openai-api-key" placeholder="输入OpenAI API Key" required />
|
||
</div>
|
||
<div class="form-group">
|
||
<label for="openai-model">模型 <span style="color: red;">*</span></label>
|
||
<input type="text" id="openai-model" placeholder="gpt-4" required />
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Agent配置 -->
|
||
<div class="settings-section">
|
||
<h3>Agent 配置</h3>
|
||
<div class="settings-form">
|
||
<div class="form-group">
|
||
<label for="agent-max-iterations">最大迭代次数</label>
|
||
<input type="number" id="agent-max-iterations" min="1" max="100" placeholder="30" />
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 安全设置 -->
|
||
<div class="settings-section">
|
||
<h3>安全设置</h3>
|
||
<div class="settings-form">
|
||
<div class="form-group">
|
||
<label for="auth-current-password">当前密码</label>
|
||
<input type="password" id="auth-current-password" placeholder="输入当前登录密码" autocomplete="current-password" />
|
||
</div>
|
||
<div class="form-group">
|
||
<label for="auth-new-password">新密码</label>
|
||
<input type="password" id="auth-new-password" placeholder="设置新密码(至少 8 位)" autocomplete="new-password" />
|
||
</div>
|
||
<div class="form-group">
|
||
<label for="auth-confirm-password">确认新密码</label>
|
||
<input type="password" id="auth-confirm-password" placeholder="再次输入新密码" autocomplete="new-password" />
|
||
</div>
|
||
<div class="form-actions">
|
||
<button class="btn-secondary" type="button" onclick="resetPasswordForm()">清空</button>
|
||
<button class="btn-primary change-password-submit" type="button" onclick="changePassword()">修改密码</button>
|
||
</div>
|
||
<p class="password-hint">修改密码后,需要使用新密码重新登录。</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="settings-actions">
|
||
<button class="btn-primary" onclick="applySettings()">应用配置</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
<!-- MCP调用详情模态框 -->
|
||
<div id="mcp-detail-modal" class="modal">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h2>工具调用详情</h2>
|
||
<span class="modal-close" onclick="closeMCPDetail()">×</span>
|
||
</div>
|
||
<div class="modal-body">
|
||
<div class="detail-section detail-section-overview">
|
||
<div class="detail-section-header">
|
||
<h3>执行信息</h3>
|
||
</div>
|
||
<div class="detail-info-grid">
|
||
<div class="detail-item">
|
||
<strong>工具</strong>
|
||
<span id="detail-tool-name"></span>
|
||
</div>
|
||
<div class="detail-item">
|
||
<strong>状态</strong>
|
||
<span id="detail-status" class="status-chip status-unknown"></span>
|
||
</div>
|
||
<div class="detail-item">
|
||
<strong>时间</strong>
|
||
<span id="detail-time"></span>
|
||
</div>
|
||
<div class="detail-item">
|
||
<strong>执行 ID</strong>
|
||
<span id="detail-execution-id" class="mono-text"></span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<div class="detail-section-header">
|
||
<h3>请求参数</h3>
|
||
<button class="btn-ghost" type="button" onclick="copyDetailBlock('detail-request', this)">复制 JSON</button>
|
||
</div>
|
||
<div class="detail-code-card">
|
||
<pre id="detail-request" class="code-block"></pre>
|
||
</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<div class="detail-section-header">
|
||
<h3>响应结果</h3>
|
||
<button class="btn-ghost" type="button" onclick="copyDetailBlock('detail-response', this)">复制内容</button>
|
||
</div>
|
||
<div class="detail-code-card">
|
||
<pre id="detail-response" class="code-block"></pre>
|
||
</div>
|
||
</div>
|
||
<div class="detail-section detail-success-wrapper" id="detail-success-section" style="display: none;">
|
||
<div class="detail-section-header">
|
||
<h3>正确信息</h3>
|
||
<button class="btn-ghost" type="button" onclick="copyDetailBlock('detail-success', this)">复制内容</button>
|
||
</div>
|
||
<div class="detail-code-card">
|
||
<pre id="detail-success" class="code-block"></pre>
|
||
</div>
|
||
</div>
|
||
<div class="detail-section detail-error-wrapper" id="detail-error-section" style="display: none;">
|
||
<div class="detail-section-header">
|
||
<h3>错误信息</h3>
|
||
<button class="btn-ghost" type="button" onclick="copyDetailBlock('detail-error', this)">复制错误</button>
|
||
</div>
|
||
<div class="detail-code-card">
|
||
<pre id="detail-error" class="code-block error"></pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 外部MCP配置模态框 -->
|
||
<div id="external-mcp-modal" class="modal">
|
||
<div class="modal-content" style="max-width: 900px;">
|
||
<div class="modal-header">
|
||
<h2 id="external-mcp-modal-title">添加外部MCP</h2>
|
||
<span class="modal-close" onclick="closeExternalMCPModal()">×</span>
|
||
</div>
|
||
<div class="modal-body">
|
||
<div class="form-group">
|
||
<label for="external-mcp-json">配置JSON <span style="color: red;">*</span></label>
|
||
<textarea id="external-mcp-json" rows="15" placeholder='{\n "hexstrike-ai": {\n "command": "python3",\n "args": ["/path/to/script.py"],\n "description": "描述",\n "timeout": 300\n }\n}' style="font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace; font-size: 0.875rem; line-height: 1.5;"></textarea>
|
||
<div class="password-hint">
|
||
<strong>配置格式:</strong>JSON对象,key为配置名称,value为配置内容。状态通过"启动/停止"按钮控制,无需在JSON中配置。<br>
|
||
<strong>配置示例:</strong><br>
|
||
<strong>stdio模式:</strong><br>
|
||
<code style="display: block; margin: 8px 0; padding: 8px; background: var(--bg-secondary); border-radius: 4px; white-space: pre-wrap;">{
|
||
"hexstrike-ai": {
|
||
"command": "python3",
|
||
"args": ["/path/to/script.py", "--server", "http://example.com"],
|
||
"description": "描述",
|
||
"timeout": 300
|
||
}
|
||
}</code>
|
||
<strong>HTTP模式:</strong><br>
|
||
<code style="display: block; margin: 8px 0; padding: 8px; background: var(--bg-secondary); border-radius: 4px; white-space: pre-wrap;">{
|
||
"cyberstrike-ai-http": {
|
||
"transport": "http",
|
||
"url": "http://127.0.0.1:8081/mcp"
|
||
}
|
||
}</code>
|
||
</div>
|
||
<div id="external-mcp-json-error" class="error-message" style="display: none; margin-top: 8px; padding: 8px; background: rgba(220, 53, 69, 0.1); border: 1px solid rgba(220, 53, 69, 0.3); border-radius: 4px; color: var(--error-color); font-size: 0.875rem;"></div>
|
||
</div>
|
||
<div class="form-group">
|
||
<button type="button" class="btn-secondary" onclick="formatExternalMCPJSON()" style="margin-top: 8px;">格式化JSON</button>
|
||
<button type="button" class="btn-secondary" onclick="loadExternalMCPExample()" style="margin-top: 8px; margin-left: 8px;">加载示例</button>
|
||
</div>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button class="btn-secondary" onclick="closeExternalMCPModal()">取消</button>
|
||
<button class="btn-primary" onclick="saveExternalMCP()">保存</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 攻击链可视化模态框 -->
|
||
<div id="attack-chain-modal" class="modal">
|
||
<div class="modal-content attack-chain-modal-content">
|
||
<div class="modal-header">
|
||
<h2>攻击链可视化</h2>
|
||
<div class="modal-header-actions">
|
||
<button class="btn-secondary" onclick="regenerateAttackChain()" title="重新生成攻击链(包含最新对话内容)" style="background: #007bff; color: white; border-color: #007bff; margin-right: 8px;">
|
||
🔄 重新生成
|
||
</button>
|
||
<button class="btn-secondary" onclick="exportAttackChain('png')" title="导出为PNG">
|
||
📥 PNG
|
||
</button>
|
||
<button class="btn-secondary" onclick="exportAttackChain('svg')" title="导出为SVG">
|
||
📥 SVG
|
||
</button>
|
||
<button class="btn-secondary" onclick="refreshAttackChain()" title="刷新当前攻击链(不重新生成)">
|
||
↻ 刷新
|
||
</button>
|
||
<span class="modal-close" onclick="closeAttackChainModal()">×</span>
|
||
</div>
|
||
</div>
|
||
<div class="modal-body attack-chain-body">
|
||
<div class="attack-chain-controls">
|
||
<div class="attack-chain-info">
|
||
<span id="attack-chain-stats">节点: 0 | 边: 0</span>
|
||
</div>
|
||
<div class="attack-chain-legend">
|
||
<div class="legend-item">
|
||
<span class="legend-color" style="background: #ff4444;"></span>
|
||
<span>高风险 (80-100)</span>
|
||
</div>
|
||
<div class="legend-item">
|
||
<span class="legend-color" style="background: #ff8800;"></span>
|
||
<span>中高风险 (60-79)</span>
|
||
</div>
|
||
<div class="legend-item">
|
||
<span class="legend-color" style="background: #ffbb00;"></span>
|
||
<span>中风险 (40-59)</span>
|
||
</div>
|
||
<div class="legend-item">
|
||
<span class="legend-color" style="background: #88cc00;"></span>
|
||
<span>低风险 (0-39)</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="attack-chain-container" class="attack-chain-container">
|
||
<div class="loading-spinner">加载中...</div>
|
||
</div>
|
||
<div id="attack-chain-details" class="attack-chain-details" style="display: none;">
|
||
<h3>节点详情</h3>
|
||
<div id="attack-chain-details-content"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Marked.js for Markdown parsing -->
|
||
<script src="https://cdn.jsdelivr.net/npm/marked@11.1.1/marked.min.js"></script>
|
||
<!-- DOMPurify for HTML sanitization to prevent XSS -->
|
||
<script src="https://cdn.jsdelivr.net/npm/dompurify@3.0.8/dist/purify.min.js"></script>
|
||
<!-- Cytoscape.js for attack chain visualization -->
|
||
<script src="https://cdn.jsdelivr.net/npm/cytoscape@3.27.0/dist/cytoscape.min.js"></script>
|
||
<!-- dagre layout dependencies -->
|
||
<script src="https://cdn.jsdelivr.net/npm/graphlib@2.1.8/dist/graphlib.min.js"></script>
|
||
<script src="https://cdn.jsdelivr.net/npm/dagre@0.8.5/dist/dagre.min.js"></script>
|
||
<!-- dagre layout for hierarchical layout -->
|
||
<script src="https://cdn.jsdelivr.net/npm/cytoscape-dagre@2.5.0/cytoscape-dagre.min.js"></script>
|
||
<script src="/static/js/auth.js"></script>
|
||
<script src="/static/js/router.js"></script>
|
||
<script src="/static/js/monitor.js"></script>
|
||
<script src="/static/js/chat.js"></script>
|
||
<script src="/static/js/settings.js"></script>
|
||
</body>
|
||
</html>
|
||
|