{% extends 'base.html' %} {% block title %}ZFSAFE{% endblock %} <!-- 在此处可添加样式文件 --> {% block style_link %} <link href="{{ url_for('main.static', filename='css/node_tree.css') }}" rel="stylesheet"> {% endblock %} <!-- 页面样式块 --> {% block style %} /* 搜索条件区域居中 */ .search-area { text-align: center; margin-bottom: 15px; } /* 表格样式 */ .table thead th { text-align: center; /* 表头居中 */ vertical-align: middle; } .table tbody td { vertical-align: middle; padding: 0.3rem 0.5rem; /* 缩小单元格上下内边距 */ line-height: 1.5; } /* 序号列宽度较小 */ .table thead th.seq-col, .table tbody td.seq-col { width: 50px; text-align: center; } /* 分页控件右对齐 */ .pagination { justify-content: end; } /* 左侧任务列表整体样式 */ .task-list { height: calc(100vh - 210px); overflow-y: auto; background-color: #fff; padding: 5px; border-right: 1px solid #ddd; } /* 每个任务项样式 */ .task-item { padding: 5px; margin-bottom: 5px; background-color: #f9f9f9; border: 1px solid #eee; border-radius: 4px; cursor: pointer; transition: background-color 0.3s ease, box-shadow 0.3s ease; } .task-item.running { /*border: 2px solid #52c41a;*/ border: 2px solid #1890ff; /* 蓝色边框 */ } /* 任务项选中状态样式 */ .task-item.selected { background-color: #e6f7ff; border: 1px solid #1890ff; box-shadow: 2px 2px 6px rgba(0, 0, 0, 0.2); } .task-item:hover { background-color: #e6f7ff; } .task-item.selected { border-color: #1890ff; background-color: #bae7ff; } /* 任务目标样式,第一行 */ .task-target { font-weight: bold; white-space: nowrap; /* 不换行 */ overflow: hidden; /* 超出隐藏 */ text-overflow: ellipsis; /* 超出显示... */ } /* 任务状态,第二行,有缩进 */ .task-status { margin-left: 10px; color: #666; font-size: 0.8rem; } /* 定义一个全高容器,与左侧任务列表高度保持一致 */ .full-height { height: calc(100vh - 210px); } /* 右侧区域采用 flex 布局,垂直排列 */ .right-container { display: flex; flex-direction: column; } /* 基本信息区域,保持固定高度 */ .basic-info { /* 根据需要设定高度,或保持内容自适应 */ flex: 0 0 auto; } /* Tab 内容区域占满剩余空间 */ .tab-wrapper { flex: 1 1 auto; display: flex; flex-direction: column; overflow: hidden; /* 防止内部溢出 */ } /* 导航部分根据内容高度 */ #myTab { flex: 0 0 auto; } .tab-content{ flex: 1 1 auto; overflow-y: auto; } .modal-dialog { max-width: calc(100vw - 10rem); margin: 1rem auto; } .table { width: 100%; table-layout: fixed; } .table th, .table td { word-wrap: break-word; white-space: normal; } .disabled-btn { /* 禁用状态样式 */ background-color: #cccccc; /* 灰色背景 */ color: #666666; /* 文字颜色变浅 */ cursor: not-allowed; /* 鼠标显示禁用图标 */ opacity: 0.7; /* 可选:降低透明度 */ /* 禁用点击事件(通过 disabled 属性已实现,此样式仅增强视觉效果) */ pointer-events: none; /* 可选:彻底阻止鼠标事件 */ } {% endblock %} {% block modal %} {% include 'task_manager_modal.html' %} {% endblock %} <!-- 页面内容块 --> {% block content %} <div class="container-xxl mt-4"> <div class="container-fluid"> <div class="row"> <!-- 左侧:任务列表 --> <div class="col-2 task-list" id="taskList"> <!-- 动态生成的任务项将插入此处 --> <p>加载中...</p> </div> <!-- 右侧:任务详情 --> <div class="col-10 full-height right-container"> <!-- 上方:基本信息 --> <div class="row basic-info"> <div class="col-8"> <div class="mb-2"> <label class="fw-bold">测试目标: </label> <span id="detailTestTarget">192.168.1.110</span> </div> <div class="row"> <div class="col-3"> <label class="fw-bold">工作状态: </label> <span id="detailTestStatus">执行中</span> </div> <div class="col-3"> <label class="fw-bold">安全情况: </label> <span id="detailSafeStatus">安全</span> </div> <div class="col-6"> <label class="fw-bold">测试模式: </label> <div class="form-check form-check-inline"> <input class="form-check-input" type="radio" name="testMode" id="autoMode" value="auto" checked /> <label class="form-check-label" for="autoMode" >自动执行</label > </div> <div class="form-check form-check-inline"> <input class="form-check-input" type="radio" name="testMode" id="manualMode" value="manual" /> <label class="form-check-label" for="manualMode" >人工确认</label > </div> </div> </div> </div> <!-- <div class="col-2" style="display: flex; justify-content: center; align-items: center"> --> <div class="col-4 d-flex justify-content-center align-items-center"> <!-- 按钮 (联动测试状态示例: 执行中->暂停, 暂停中->启动,) --> <button class="btn btn-primary btn-block m-2" id="actionButton">启动</button> <div class="m-2" style="margin-bottom: 5px"> <label class="fw-bold" style="font-size:0.9rem">单步步次:</label> <select class="form-select" id="stepNumSelect" style="font-size:0.9rem"> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</option> <option value="5">5</option> <option value="6">6</option> <option value="7">7</option> </select> </div> <button class="btn btn-primary btn-block m-2" id="one_step">单步</button> <button class="btn btn-danger btn-block m-2" id="btnTaskOver">结束</button> </div> </div> <!-- 下方:Tab 页 --> <div class="tab-wrapper"> <ul class="nav nav-tabs" id="myTab" role="tablist"> <li class="nav-item" role="presentation"> <button class="nav-link active" id="nodeTreeTab" data-bs-toggle="tab" data-bs-target="#nodeTree" type="button" role="tab" aria-controls="nodeTree" aria-selected="true" > 节点树 </button> </li> <li class="nav-item" role="presentation"> <button class="nav-link" id="testInstructionsTab" data-bs-toggle="tab" data-bs-target="#testInstructions" type="button" role="tab" aria-controls="testInstructions" aria-selected="false" > 测试指令 </button> </li> <li class="nav-item" role="presentation"> <button class="nav-link" id="vulnerabilitiesTab" data-bs-toggle="tab" data-bs-target="#vulnerabilities" type="button" role="tab" aria-controls="vulnerabilities" aria-selected="false" > 漏洞数据 </button> </li> </ul> <div class="tab-content " id="myTabContent"> <!-- 节点树 --> <div class="tab-pane fade show active p-3 h-100" id="nodeTree" role="tabpanel" aria-labelledby="nodeTreeTab"> <div class="row h-100"> <!-- 左侧:节点树区域 --> <div class="col-8 h-100"> <div class="node-tree-area" id="nodeTreeContainer"> <!-- 顶部刷新按钮 --> <div class="refresh-container"> <button class="tree-refresh" id="btnRefresh" title="刷新节点树"> ↻ </button> </div> <!-- 节点树内容区域 --> <div id="treeContent" class="tree-content"> <p id="treeLoadingMsg" style="text-align:center;">加载中...</p> </div> </div> </div> <!-- 右侧:节点信息与操作 --> <div class="col-4 h-100"> <div class="node-info-area mb-2"> <!-- <h5>节点信息</h5>--> <p><strong>节点名称:</strong> <span id="nodeName">-</span></p> <p><strong>测试状态:</strong> <span id="testStatus">-</span></p> <p><strong>漏洞类型:</strong> <span id="node_vulType">-</span></p> <p><strong>漏洞级别:</strong> <span id="node_vulLevel">-</span></p> <p><strong>漏洞说明:</strong> <span id="node_vulInfo">-</span></p> <p><strong>工作状态:</strong> <span id="node_bwork">-</span></p> <p><strong>执行状态:</strong> <span id="node_workstatus">-</span></p> </div> <div class="node-actions"> <div class="row"> <div class="col-6"><button class="btn btn-primary w-100" id="btnToggleStatus">暂停</button></div> <div class="col-6"><button class="btn btn-primary w-100" id="btnNodeStep">单步</button></div> </div> <div class="row"> <div class="col-6"><button class="btn btn-primary w-100" id="btnViewInstr">查看指令</button></div> <div class="col-6"><button class="btn btn-primary w-100" id="btnViewMsg">查看MSG</button></div> </div> <div class="row"> <div class="col-6"><button class="btn btn-primary w-100" id="btnAddInfo">添加信息</button></div> <div class="col-6"><button class="btn btn-primary w-100" id="btnAddChild">添加子节点</button></div> </div> </div> </div> </div> </div> <!-- 测试指令 --> <div class="tab-pane fade p-3" id="testInstructions" role="tabpanel" aria-labelledby="testInstructionsTab" > <!-- 搜索区域 --> <div class="row search-area"> <div class="col-4"> <input type="text" class="form-control" id="instrNodeName" placeholder="节点名称" /> </div> <div class="col-2"> <button class="btn btn-primary" id="instrSearchBtn"> 查询 </button> <button class="btn btn-primary" id="instrExportBtn"> 导出 </button> </div> </div> <table class="table table-bordered table-hover" id="instrTable" style="width: 100%; table-layout: fixed;"> <colgroup> <!-- 第一列:序号,固定宽度或百分比 --> <col style="width: 5%;"> <!-- 第二列:节点路径,例如 25% --> <col style="width: 15%;"> <!-- 第三列:指令序号,固定宽度 --> <col style="width: 5%;"> <!-- 第四列:执行指令,设置为固定宽度或者百分比 --> <col style="width: 30%;" class="wrap-cell"> <!-- 第五列:执行结果,占用剩余所有宽度 --> <col style="width: auto;"> </colgroup> <thead> <tr> <th>序号</th> <th>节点路径</th> <th>指序</th> <th>执行指令</th> <th>执行结果</th> </tr> </thead> <tbody> <!-- 默认显示 10 行(后续用 JS 渲染数据,补空行) --> </tbody> </table> <!-- 分页控件 --> <nav> <ul class="pagination" id="instrPagination"> <li class="page-item"> <a class="page-link" href="#" id="instrPrev">上一页</a> </li> <li class="page-item"> <a class="page-link" href="#" id="instrNext">下一页</a> </li> </ul> </nav> </div> <!-- 漏洞数据 --> <div class="tab-pane fade p-3" id="vulnerabilities" role="tabpanel" aria-labelledby="vulnerabilitiesTab" > <!-- 搜索区域 --> <div class="row search-area"> <div class="col-3"> <input type="text" class="form-control" id="vulNodeName" placeholder="节点名称" /> </div> <div class="col-3"> <input type="text" class="form-control" id="vulType" placeholder="漏洞类型" /> </div> <div class="col-3"> <select class="form-select" id="vulLevel"> <option value="">漏洞级别</option> <option value="低危">低</option> <option value="中危">中</option> <option value="高危">高</option> </select> </div> <div class="col-2"> <button class="btn btn-primary" id="vulSearchBtn"> 查询 </button> <button class="btn btn-primary" id="vulExportBtn"> 导出 </button> </div> </div> <table class="table table-bordered table-hover" id="vulTable"> <colgroup> <col style="width: 5%;"> <col style="width: 35%;"> <col style="width: 15%;"> <col style="width: 10%;" class="wrap-cell"> <col style="width: auto;"> </colgroup> <thead> <tr> <th>序号</th> <th>节点路径</th> <th>漏洞类型</th> <th>漏洞级别</th> <th>漏洞说明</th> </tr> </thead> <tbody> <!-- 默认显示 10 行 --> </tbody> </table> <!-- 分页控件 --> <nav> <ul class="pagination" id="vulPagination"> <li class="page-item"> <a class="page-link" href="#" id="vulPrev">上一页</a> </li> <li class="page-item"> <a class="page-link" href="#" id="vulNext">下一页</a> </li> </ul> </nav> </div> </div> </div> </div> </div> </div> </div> {% endblock %} <!-- 页面脚本块 --> {% block script %} <!-- 在此处可添加与后端交互的脚本 --> <script src="{{ url_for('main.static', filename='scripts/my_web_socket.js') }}"></script> <script src="{{ url_for('main.static', filename='scripts/task_manager.js') }}"></script> <script src="{{ url_for('main.static', filename='scripts/node_tree.js') }}"></script> <script src="{{ url_for('main.static', filename='scripts/jquery-3.2.1.slim.min.js') }}"></script> {% endblock %}