| | |
| | | <meta name="renderer" content="webkit"> |
| | | <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> |
| | | <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> |
| | | <link rel="stylesheet" href="../../static/layui/css/layui.css" media="all"> |
| | | <link rel="stylesheet" href="../../static/css/admin.css?v=318" media="all"> |
| | | <link rel="stylesheet" href="../../static/css/cool.css" media="all"> |
| | | <!-- CSS --> |
| | | <link rel="stylesheet" href="../../static/vue/element/element.css"> |
| | | <link rel="stylesheet" href="../../static/css/common.css"> |
| | | <style> |
| | | body { margin: 0; padding: 0; background-color: #f0f2f5; height: 100vh; overflow: hidden; } |
| | | #app { height: 100%; padding: 10px; box-sizing: border-box; display: flex; flex-direction: column; } |
| | | .main-container { flex: 1; display: flex; overflow: hidden; } |
| | | .sidebar { width: 260px; margin-right: 10px; display: flex; flex-direction: column; } |
| | | .content { flex: 1; display: flex; flex-direction: column; overflow: hidden; } |
| | | |
| | | .box-card { height: 100%; display: flex; flex-direction: column; border: none; box-shadow: 0 1px 4px rgba(0,21,41,.08); } |
| | | .box-card .el-card__header { padding: 10px 15px; border-bottom: 1px solid #ebeef5; background: #fff; font-weight: bold; font-size: 15px; } |
| | | .box-card .el-card__body { flex: 1; overflow: auto; padding: 15px; } |
| | | |
| | | .device-item { margin-bottom: 10px; } |
| | | .device-card { background-color: #fff; border: 1px solid #e6ebf5; border-radius: 4px; transition: all .3s; } |
| | | .device-card:hover { box-shadow: 0 2px 12px 0 rgba(0,0,0,.1); } |
| | | .device-info { display: flex; justify-content: space-between; align-items: center; padding: 15px; } |
| | | .device-info .info-text { font-size: 14px; color: #606266; } |
| | | .device-info .info-text b { color: #303133; margin-right: 5px; } |
| | | .device-info .tag-group { margin-left: 15px; } |
| | | |
| | | .control-bar { margin-bottom: 15px; padding: 15px; background: #fff; border-radius: 4px; box-shadow: 0 1px 4px rgba(0,21,41,.08); } |
| | | |
| | | /* Visualization styles */ |
| | | .vis-control-panel { margin-bottom: 10px; display: flex; align-items: center; background: #f5f7fa; padding: 10px; border-radius: 4px; } |
| | | .vis-container { border: 1px solid #ebeef5; padding: 10px; border-radius: 4px; min-height: 400px; height: calc(80vh - 100px); overflow-y: auto; } |
| | | </style> |
| | | </head> |
| | | <body> |
| | | |
| | | <div class="layui-fluid"> |
| | | <div class="layui-row"> |
| | | <div class="layui-col-md3"> |
| | | <div class="layui-card"> |
| | | <div class="layui-card-header">日期</div> |
| | | <div class="layui-card-body"> |
| | | <div id="date-tree"></div> |
| | | </div> |
| | | </div> |
| | | <div id="app" v-cloak> |
| | | <div class="main-container"> |
| | | <!-- Sidebar: Date Tree --> |
| | | <div class="sidebar"> |
| | | <el-card class="box-card" :body-style="{padding: '10px'}"> |
| | | <div slot="header">日期选择</div> |
| | | <el-tree |
| | | ref="dateTree" |
| | | :data="dateTreeData" |
| | | :props="defaultProps" |
| | | node-key="id" |
| | | :default-expanded-keys="defaultExpandedKeys" |
| | | @node-click="handleNodeClick" |
| | | highlight-current |
| | | accordion> |
| | | <span class="custom-tree-node" slot-scope="{ node, data }"> |
| | | <i v-if="data.children" class="el-icon-folder"></i> |
| | | <i v-else class="el-icon-document"></i> |
| | | <span style="margin-left: 5px;">{{ node.label }}</span> |
| | | </span> |
| | | </el-tree> |
| | | </el-card> |
| | | </div> |
| | | <div class="layui-col-md9"> |
| | | <div class="layui-card"> |
| | | <div class="layui-card-header">日志下载</div> |
| | | <div class="layui-card-body"> |
| | | <form class="layui-form toolbar" id="search-box"> |
| | | <div class="layui-form-item"> |
| | | <div class="layui-inline"> |
| | | <label class="layui-form-label">选中日期:</label> |
| | | <div class="layui-input-inline"> |
| | | <input id="selected-day" class="layui-input" type="text" placeholder="yyyyMMdd" readonly> |
| | | </div> |
| | | </div> |
| | | <div class="layui-inline"> |
| | | <label class="layui-form-label">设备类型:</label> |
| | | <div class="layui-input-inline"> |
| | | <select id="device-type-input" class="layui-input"> |
| | | <option value="">请选择</option> |
| | | <option value="Crn">Crn</option> |
| | | <option value="Devp">Devp</option> |
| | | <option value="Rgv">Rgv</option> |
| | | </select> |
| | | </div> |
| | | </div> |
| | | <div class="layui-inline"> |
| | | <label class="layui-form-label">设备编号:</label> |
| | | <div class="layui-input-inline"> |
| | | <input id="device-no-input" class="layui-input" type="text" placeholder="请输入设备编号"> |
| | | </div> |
| | | </div> |
| | | <div class="layui-inline"> |
| | | <label class="layui-form-label">起始序号:</label> |
| | | <div class="layui-input-inline"> |
| | | <input id="file-offset" class="layui-input" type="text" placeholder="默认0"> |
| | | </div> |
| | | </div> |
| | | <div class="layui-inline"> |
| | | <label class="layui-form-label">最大文件数:</label> |
| | | <div class="layui-input-inline"> |
| | | <input id="file-limit" class="layui-input" type="text" placeholder="默认200"> |
| | | </div> |
| | | </div> |
| | | <div class="layui-inline"> |
| | | <button id="download-btn" type="button" class="layui-btn layui-btn-normal">下载</button> |
| | | </div> |
| | | </div> |
| | | </form> |
| | | |
| | | <hr class="layui-bg-gray"> |
| | | <!-- Main Content --> |
| | | <div class="content"> |
| | | <!-- Search Bar --> |
| | | <div class="control-bar"> |
| | | <el-form :inline="true" :model="searchForm" size="small" style="margin-bottom: -18px;"> |
| | | <el-form-item label="选中日期"> |
| | | <el-input v-model="searchForm.day" placeholder="yyyyMMdd" readonly style="width: 120px;" disabled></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="设备类型"> |
| | | <el-select v-model="searchForm.type" placeholder="全部" clearable style="width: 100px;"> |
| | | <el-option label="Crn" value="Crn"></el-option> |
| | | <el-option label="Devp" value="Devp"></el-option> |
| | | <el-option label="Rgv" value="Rgv"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="设备编号"> |
| | | <el-input v-model="searchForm.deviceNo" placeholder="请输入编号" style="width: 120px;" clearable></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="起始序号"> |
| | | <el-input-number v-model="searchForm.offset" :min="0" controls-position="right" style="width: 100px;"></el-input-number> |
| | | </el-form-item> |
| | | <el-form-item label="最大文件"> |
| | | <el-input-number v-model="searchForm.limit" :min="1" :max="1000" controls-position="right" style="width: 100px;"></el-input-number> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" icon="el-icon-download" @click="handleBatchDownload" :disabled="!canDownload">下载</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | |
| | | <div class="layui-row"> |
| | | <div class="layui-col-xs12"> |
| | | <div class="layui-card"> |
| | | <div class="layui-card-header">该日设备列表</div> |
| | | <div class="layui-card-body"> |
| | | <div id="device-list" class="layui-row"></div> |
| | | <!-- Device List --> |
| | | <el-card class="box-card"> |
| | | <div slot="header" class="clearfix"> |
| | | <span>设备列表</span> |
| | | <span style="float: right; color: #909399; font-size: 12px;">共 {{ filteredDeviceList.length }} 个设备</span> |
| | | </div> |
| | | |
| | | <div v-if="loading" style="text-align: center; padding: 20px;"> |
| | | <i class="el-icon-loading" style="font-size: 24px;"></i> |
| | | </div> |
| | | <div v-else-if="filteredDeviceList.length === 0" style="text-align: center; color: #909399; padding: 50px;"> |
| | | <i class="el-icon-info" style="margin-right: 5px;"></i>暂无数据,请先选择日期 |
| | | </div> |
| | | <div v-else> |
| | | <div v-for="(item, index) in filteredDeviceList" :key="index" class="device-item"> |
| | | <div class="device-card"> |
| | | <div class="device-info"> |
| | | <div> |
| | | <span class="info-text"><b>设备编号:</b> {{ item.deviceNo }}</span> |
| | | <span class="info-text tag-group"><b>类型:</b> {{ item.types.join(', ') }}</span> |
| | | <span class="info-text tag-group"><b>文件数:</b> {{ item.fileCount }}</span> |
| | | </div> |
| | | <div> |
| | | <template v-for="t in item.types"> |
| | | <el-button size="mini" icon="el-icon-download" @click="downloadLog(item.deviceNo, t)">下载({{t}})</el-button> |
| | | <el-button size="mini" type="success" icon="el-icon-view" @click="visualizeLog(item.deviceNo, t)">可视化({{t}})</el-button> |
| | | </template> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </el-card> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- Visualization Dialog --> |
| | | <el-dialog |
| | | :title="visualizationTitle" |
| | | :visible.sync="visualizationVisible" |
| | | width="90%" |
| | | top="5vh" |
| | | :close-on-click-modal="false" |
| | | @close="handleVisualizationClose"> |
| | | |
| | | <div class="vis-control-panel"> |
| | | <el-button-group> |
| | | <el-button type="primary" icon="el-icon-video-play" @click="play" v-if="!isPlaying" size="small">播放</el-button> |
| | | <el-button type="primary" icon="el-icon-video-pause" @click="pause" v-else size="small">暂停</el-button> |
| | | <el-button type="warning" icon="el-icon-refresh-left" @click="reset" size="small">重置</el-button> |
| | | </el-button-group> |
| | | <div style="margin-left: 20px; flex: 1; padding-right: 20px;"> |
| | | <el-slider v-model="sliderValue" :max="maxSliderValue" @change="sliderChange" @input="sliderInput" :format-tooltip="formatTooltip"></el-slider> |
| | | </div> |
| | | <div style="width: 210px; font-size: 14px; font-weight: bold; font-family: monospace; display: flex; align-items: center;"> |
| | | {{ currentTimeStr }} |
| | | <el-popover |
| | | placement="bottom" |
| | | width="200" |
| | | trigger="click" |
| | | v-model="jumpVisible" |
| | | @show="initJumpTime"> |
| | | <div style="text-align: center;"> |
| | | <el-time-picker |
| | | v-model="jumpTime" |
| | | size="small" |
| | | placeholder="选择时间" |
| | | style="width: 100%; margin-bottom: 10px;" |
| | | :picker-options="{ selectableRange: '00:00:00 - 23:59:59' }"> |
| | | </el-time-picker> |
| | | <el-button type="primary" size="mini" @click="confirmJump" style="width: 100%;">跳转</el-button> |
| | | </div> |
| | | <el-button type="text" slot="reference" icon="el-icon-edit" style="margin-left: 5px; padding: 0;" title="跳转时间"></el-button> |
| | | </el-popover> |
| | | </div> |
| | | <div style="margin-left: 10px;"> |
| | | <el-select v-model="playbackSpeed" style="width: 100px;" size="small" placeholder="倍速"> |
| | | <el-option :value="1" label="1x"></el-option> |
| | | <el-option :value="5" label="5x"></el-option> |
| | | <el-option :value="10" label="10x"></el-option> |
| | | <el-option :value="50" label="50x"></el-option> |
| | | <el-option :value="100" label="100x"></el-option> |
| | | <el-option :value="200" label="200x"></el-option> |
| | | <el-option :value="500" label="500x"></el-option> |
| | | <el-option :value="1000" label="1000x"></el-option> |
| | | </el-select> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="vis-container"> |
| | | <watch-crn-card v-if="visDeviceType === 'Crn'" ref="card" :auto-refresh="false" :read-only="true"></watch-crn-card> |
| | | <watch-rgv-card v-else-if="visDeviceType === 'Rgv'" ref="card" :auto-refresh="false" :read-only="true"></watch-rgv-card> |
| | | <watch-dual-crn-card v-else-if="visDeviceType === 'DualCrn'" ref="card" :auto-refresh="false" :read-only="true"></watch-dual-crn-card> |
| | | <devp-card v-else-if="visDeviceType === 'Devp'" ref="card" :auto-refresh="false" :read-only="true"></devp-card> |
| | | <div v-else style="text-align: center; padding: 50px; color: #909399;"> |
| | | 未知设备类型: {{ visDeviceType }} |
| | | </div> |
| | | </div> |
| | | </el-dialog> |
| | | |
| | | <!-- Download Progress Dialog --> |
| | | <el-dialog title="文件下载中" :visible.sync="downloadDialogVisible" width="400px" :close-on-click-modal="false" :show-close="false"> |
| | | <div style="padding: 10px;"> |
| | | <div style="margin-bottom: 5px; font-size: 14px;">压缩生成进度</div> |
| | | <el-progress :percentage="buildProgress" :text-inside="true" :stroke-width="18"></el-progress> |
| | | <div style="margin: 20px 0 5px; font-size: 14px;">下载接收进度</div> |
| | | <el-progress :percentage="receiveProgress" :text-inside="true" :stroke-width="18" status="success"></el-progress> |
| | | </div> |
| | | </el-dialog> |
| | | </div> |
| | | |
| | | <script type="text/javascript" src="../../static/js/jquery/jquery-3.3.1.min.js"></script> |
| | | <script type="text/javascript" src="../../static/layui/layui.js" charset="utf-8"></script> |
| | | <script type="text/javascript" src="../../static/js/common.js" charset="utf-8"></script> |
| | | <script type="text/javascript" src="../../static/js/cool.js" charset="utf-8"></script> |
| | | <script src="../../static/vue/js/vue.min.js"></script> |
| | | <script src="../../static/vue/element/element.js"></script> |
| | | <script src="../../components/WatchCrnCard.js"></script> |
| | | <script src="../../components/WatchRgvCard.js"></script> |
| | | <script src="../../components/WatchDualCrnCard.js"></script> |
| | | <script src="../../components/DevpCard.js"></script> |
| | | <script type="text/javascript" src="../../static/js/deviceLogs/deviceLogs.js" charset="utf-8"></script> |
| | | </body> |
| | | </html> |
| | | </html> |