514 lines
29 KiB
HTML
514 lines
29 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>容量报表处理程序</title>
|
||
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>📊</text></svg>">
|
||
<!-- 本地字体(可选,没有则使用系统字体) -->
|
||
<link rel="stylesheet" href="/static/css/fonts.css">
|
||
<link rel="stylesheet" href="/static/css/style.css">
|
||
<!-- Monaco Editor(本地)- 必须在 app.js 之前加载 -->
|
||
<script src="/static/lib/monaco/vs/loader.js"></script>
|
||
</head>
|
||
<body>
|
||
<div class="app">
|
||
<!-- 侧边栏导航 -->
|
||
<aside class="sidebar" id="sidebar">
|
||
<div class="logo">
|
||
<div class="logo-icon">📊</div>
|
||
<span class="logo-text">CapacityReport</span>
|
||
</div>
|
||
<nav class="nav">
|
||
<a href="#" class="nav-item active" data-page="upload" title="数据上传">
|
||
<span class="nav-icon">📤</span>
|
||
<span>数据上传</span>
|
||
</a>
|
||
<a href="#" class="nav-item" data-page="history" title="处理历史">
|
||
<span class="nav-icon">📋</span>
|
||
<span>处理历史</span>
|
||
</a>
|
||
<a href="#" class="nav-item" data-page="database" title="数据管理">
|
||
<span class="nav-icon">🗄️</span>
|
||
<span>数据管理</span>
|
||
</a>
|
||
<a href="#" class="nav-item" data-page="script" title="脚本编辑">
|
||
<span class="nav-icon">📝</span>
|
||
<span>脚本编辑</span>
|
||
</a>
|
||
<a href="#" class="nav-item" data-page="settings" title="系统设置">
|
||
<span class="nav-icon">⚙️</span>
|
||
<span>系统设置</span>
|
||
</a>
|
||
</nav>
|
||
<div class="sidebar-footer" data-version="v2.0.0">
|
||
<div class="sidebar-footer-info">
|
||
<span class="version">版本:v2.0.0</span>
|
||
<span class="version">Power by:NIXEVOL</span>
|
||
</div>
|
||
</div>
|
||
</aside>
|
||
|
||
<!-- 主内容区 -->
|
||
<main class="main-content">
|
||
<!-- 上传页面 -->
|
||
<section id="page-upload" class="page active">
|
||
<header class="page-header">
|
||
<button class="sidebar-toggle" id="sidebarToggle" title="展开/收起侧边栏">
|
||
<span id="sidebarToggleIcon">☰</span>
|
||
</button>
|
||
<div class="page-header-content">
|
||
<h1>数据上传与处理</h1>
|
||
</div>
|
||
<div class="page-header-actions">
|
||
<button class="btn btn-sm btn-outline" id="newProcess" style="display: none;" title="新建任务">
|
||
<span>🔄</span> 新建任务
|
||
</button>
|
||
<button class="theme-toggle" id="themeToggle" title="切换主题">
|
||
<span>🌓</span>
|
||
</button>
|
||
<button class="restart-btn" id="restartService" title="重启服务">
|
||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||
<circle cx="8" cy="8" r="4.5" stroke="currentColor" stroke-width="1.5" fill="none"/>
|
||
<line x1="8" y1="4" x2="8" y2="6.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
</header>
|
||
|
||
<div class="page-body">
|
||
<div class="upload-zone" id="uploadZone">
|
||
<div class="upload-icon">📁</div>
|
||
<h3>拖拽文件夹或文件到这里</h3>
|
||
<p>支持 .zip, .xlsx, .xls, .csv 格式</p>
|
||
<p class="upload-hint">或者点击选择文件</p>
|
||
<input type="file" id="fileInput" multiple webkitdirectory directory>
|
||
<input type="file" id="fileInputSingle" multiple accept=".zip,.xlsx,.xls,.csv" style="display:none">
|
||
</div>
|
||
|
||
<div class="file-list" id="fileList" style="display: none;">
|
||
<div class="file-list-header">
|
||
<h4>已选择文件</h4>
|
||
<button class="btn btn-sm btn-text" id="clearFiles">清空</button>
|
||
</div>
|
||
|
||
<div class="file-list-footer">
|
||
<span id="fileCount">0 个文件</span>
|
||
<button class="btn btn-primary" id="startUpload">
|
||
<span>🚀</span> 上传并处理
|
||
</button>
|
||
</div>
|
||
|
||
<!-- 总进度 -->
|
||
<div class="total-progress" id="totalProgress" style="display: none; padding: 16px;">
|
||
<div class="total-progress-header">
|
||
<span class="label">上传进度</span>
|
||
<span class="percent" id="totalPercent">0%</span>
|
||
</div>
|
||
<div class="total-progress-bar">
|
||
<div class="total-progress-bar-inner" id="totalProgressBar"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 上传统计 -->
|
||
<div class="upload-stats" id="uploadStats" style="display: none; margin: 0 16px;">
|
||
<div class="upload-stats-item">
|
||
<span>总计:</span>
|
||
<span class="count" id="statsTotal">0</span>
|
||
</div>
|
||
<div class="upload-stats-item uploading">
|
||
<span>上传中:</span>
|
||
<span class="count" id="statsUploading">0</span>
|
||
</div>
|
||
<div class="upload-stats-item success">
|
||
<span>已完成:</span>
|
||
<span class="count" id="statsSuccess">0</span>
|
||
</div>
|
||
<div class="upload-stats-item error">
|
||
<span>失败:</span>
|
||
<span class="count" id="statsError">0</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="file-items" id="fileItems"></div>
|
||
</div>
|
||
|
||
<!-- 处理状态 -->
|
||
<div class="process-section" id="processSection" style="display: none;">
|
||
<div class="card">
|
||
<div class="card-header">
|
||
<div class="card-header-left">
|
||
<span class="card-title">处理进度</span>
|
||
<span class="process-status processing" id="processStatus">处理中...</span>
|
||
</div>
|
||
<div class="card-header-right">
|
||
<label class="auto-refresh-toggle">
|
||
<input type="checkbox" id="autoRefreshLog" checked>
|
||
<span>自动刷新</span>
|
||
</label>
|
||
<button class="btn btn-sm btn-outline" id="manualRefreshLog" title="手动刷新日志">
|
||
<span>🔄</span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<div class="card-body">
|
||
<div class="log-container" id="logContainer">
|
||
<div class="log-content" id="logContent"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 历史记录页面 -->
|
||
<section id="page-history" class="page">
|
||
<header class="page-header">
|
||
<button class="sidebar-toggle" id="sidebarToggle" title="展开/收起侧边栏">
|
||
<span id="sidebarToggleIcon">☰</span>
|
||
</button>
|
||
<div class="page-header-content">
|
||
<h1>处理历史</h1>
|
||
</div>
|
||
<div class="page-header-actions">
|
||
<button class="btn btn-sm btn-outline" id="refreshHistory">
|
||
<span>🔄</span> 刷新
|
||
</button>
|
||
<button class="btn btn-sm btn-danger" id="clearHistory">
|
||
<span>🗑️</span> 清空历史
|
||
</button>
|
||
<span class="total-size" style="margin: 0 8px; font-size: 13px; color: var(--td-text-color-secondary);">总占用: <span id="totalHistorySize">计算中...</span></span>
|
||
<button class="theme-toggle" id="themeToggle" title="切换主题">
|
||
<span>🌓</span>
|
||
</button>
|
||
<button class="restart-btn" id="restartService" title="重启服务">
|
||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||
<circle cx="8" cy="8" r="4.5" stroke="currentColor" stroke-width="1.5" fill="none"/>
|
||
<line x1="8" y1="4" x2="8" y2="6.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
</header>
|
||
<div class="page-body">
|
||
<div class="history-list" id="historyList">
|
||
<div class="empty-state">
|
||
<span class="empty-icon">📭</span>
|
||
<p>暂无处理记录</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 数据库管理页面 -->
|
||
<section id="page-database" class="page">
|
||
<header class="page-header">
|
||
<button class="sidebar-toggle" id="sidebarToggle" title="展开/收起侧边栏">
|
||
<span id="sidebarToggleIcon">☰</span>
|
||
</button>
|
||
<div class="page-header-content">
|
||
<h1>数据管理</h1>
|
||
</div>
|
||
<div class="page-header-actions">
|
||
<button class="btn btn-sm btn-danger" id="dropAllTables" title="删除所有表">
|
||
🗑️ 删除全部表
|
||
</button>
|
||
<button class="theme-toggle" id="themeToggle" title="切换主题">
|
||
<span>🌓</span>
|
||
</button>
|
||
<button class="restart-btn" id="restartService" title="重启服务">
|
||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||
<circle cx="8" cy="8" r="4.5" stroke="currentColor" stroke-width="1.5" fill="none"/>
|
||
<line x1="8" y1="4" x2="8" y2="6.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
</header>
|
||
<div class="page-body" style="display: flex; flex-direction: column; height: calc(100% - 64px);">
|
||
<div class="database-layout" style="flex: 1; overflow: hidden;">
|
||
<div class="db-sidebar">
|
||
<div class="table-list" id="tableList">
|
||
<div class="loading">加载中...</div>
|
||
</div>
|
||
<div class="db-server-info" id="dbServerInfo">
|
||
<div class="server-info-item" id="dbVersion">
|
||
<span class="info-label">版本:</span>
|
||
<span class="info-value">
|
||
<span class="version-badge unknown">检测中</span>
|
||
</span>
|
||
</div>
|
||
<div class="server-info-item" id="loadDataSupport">
|
||
<span class="info-label">快速导入:</span>
|
||
<span class="info-value">
|
||
<span class="support-badge unknown">检测中</span>
|
||
</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="db-content">
|
||
<div class="db-toolbar" id="dbToolbar" style="display: none;">
|
||
<div class="toolbar-left">
|
||
<span class="current-table" id="currentTable"></span>
|
||
<span class="row-count" id="rowCount"></span>
|
||
</div>
|
||
<div class="toolbar-right">
|
||
<button class="btn btn-sm btn-primary" id="downloadTable">📥 导出</button>
|
||
<button class="btn btn-sm btn-warning" id="truncateTable">清空</button>
|
||
<button class="btn btn-sm btn-danger" id="dropTable">删除</button>
|
||
</div>
|
||
</div>
|
||
<div class="data-table-container" id="dataTableContainer">
|
||
<div class="empty-state">
|
||
<span class="empty-icon">👈</span>
|
||
<p>请选择左侧的数据表</p>
|
||
</div>
|
||
</div>
|
||
<div class="pagination" id="pagination" style="display: none;">
|
||
<div class="pagination-left">
|
||
<span class="pagination-total">共 <span id="totalRecords">0</span> 条</span>
|
||
<select class="pagination-size-select" id="pageSizeSelect">
|
||
<option value="50">50 条/页</option>
|
||
<option value="100">100 条/页</option>
|
||
<option value="200">200 条/页</option>
|
||
<option value="500">500 条/页</option>
|
||
</select>
|
||
</div>
|
||
<div class="pagination-center">
|
||
<button class="pagination-btn" id="firstPage" title="首页">«</button>
|
||
<button class="pagination-btn" id="prevPage" title="上一页">‹</button>
|
||
<div class="pagination-jump">
|
||
<span>第</span>
|
||
<input type="number" class="pagination-input" id="pageJumpInput" min="1" value="1">
|
||
<span>页</span>
|
||
<span class="pagination-total-pages">/ <span id="totalPagesDisplay">1</span></span>
|
||
</div>
|
||
<button class="pagination-btn" id="nextPage" title="下一页">›</button>
|
||
<button class="pagination-btn" id="lastPage" title="末页">»</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 脚本编辑页面 -->
|
||
<section id="page-script" class="page">
|
||
<header class="page-header">
|
||
<button class="sidebar-toggle" id="sidebarToggle" title="展开/收起侧边栏">
|
||
<span id="sidebarToggleIcon">☰</span>
|
||
</button>
|
||
<div class="page-header-content">
|
||
<h1>脚本编辑</h1>
|
||
<span class="script-path" id="scriptPath" title="脚本路径"></span>
|
||
</div>
|
||
<div class="page-header-actions">
|
||
<span class="script-modified" id="scriptModified"></span>
|
||
<button class="btn btn-sm btn-primary" id="saveScript" title="保存脚本 (Ctrl+S)">
|
||
💾 保存
|
||
</button>
|
||
<button class="btn btn-sm btn-outline" id="formatScript" title="格式化 SQL">
|
||
✨ 格式化
|
||
</button>
|
||
<button class="btn btn-sm btn-success" id="runScript" title="运行脚本">
|
||
▶️ 运行脚本
|
||
</button>
|
||
<button class="theme-toggle" id="themeToggle" title="切换主题">
|
||
<span>🌓</span>
|
||
</button>
|
||
<button class="restart-btn" id="restartService" title="重启服务">
|
||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||
<circle cx="8" cy="8" r="4.5" stroke="currentColor" stroke-width="1.5" fill="none"/>
|
||
<line x1="8" y1="4" x2="8" y2="6.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
</header>
|
||
<div class="page-body script-page-body">
|
||
<div class="script-editor-container">
|
||
<div id="scriptEditor" class="script-editor"></div>
|
||
</div>
|
||
<div class="script-status-bar">
|
||
<span id="editorCursor">行 1, 列 1</span>
|
||
<span id="editorStatus">就绪</span>
|
||
</div>
|
||
|
||
<!-- 脚本执行状态 -->
|
||
<div class="process-section" id="scriptProcessSection" style="display: none; margin-top: 20px;">
|
||
<div class="card">
|
||
<div class="card-header">
|
||
<div class="card-header-left">
|
||
<span class="card-title">脚本执行进度</span>
|
||
<span class="process-status processing" id="scriptProcessStatus">执行中...</span>
|
||
</div>
|
||
<div class="card-header-right">
|
||
<label class="auto-refresh-toggle">
|
||
<input type="checkbox" id="scriptAutoRefreshLog" checked>
|
||
<span>自动刷新</span>
|
||
</label>
|
||
<button class="btn btn-sm btn-outline" id="scriptManualRefreshLog" title="手动刷新日志">
|
||
<span>🔄</span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<div class="card-body">
|
||
<div class="log-container" id="scriptLogContainer">
|
||
<div class="log-content" id="scriptLogContent"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 设置页面 -->
|
||
<section id="page-settings" class="page">
|
||
<header class="page-header">
|
||
<button class="sidebar-toggle" id="sidebarToggle" title="展开/收起侧边栏">
|
||
<span id="sidebarToggleIcon">☰</span>
|
||
</button>
|
||
<div class="page-header-content">
|
||
<h1>系统设置</h1>
|
||
</div>
|
||
<div class="page-header-actions">
|
||
<button class="btn btn-sm btn-outline" id="downloadConfig" title="下载配置文件">
|
||
📥 下载配置
|
||
</button>
|
||
<label class="btn btn-sm btn-outline" for="uploadConfig" title="上传配置文件" style="cursor: pointer; margin: 0;">
|
||
📤 上传配置
|
||
<input type="file" id="uploadConfig" accept=".json" style="display: none;">
|
||
</label>
|
||
<button class="theme-toggle" id="themeToggle" title="切换主题">
|
||
<span>🌓</span>
|
||
</button>
|
||
<button class="restart-btn" id="restartService" title="重启服务">
|
||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||
<circle cx="8" cy="8" r="4.5" stroke="currentColor" stroke-width="1.5" fill="none"/>
|
||
<line x1="8" y1="4" x2="8" y2="6.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
</header>
|
||
<div class="page-body settings-page-body">
|
||
<!-- 左侧列 -->
|
||
<div class="settings-column">
|
||
<!-- 数据库配置 -->
|
||
<div class="card settings-card">
|
||
<div class="card-header">
|
||
<span class="card-title">数据库配置</span>
|
||
<span class="config-update-time" id="configUpdate">-</span>
|
||
</div>
|
||
<div class="card-body">
|
||
<div class="form-row">
|
||
<div class="form-group">
|
||
<label>主机地址</label>
|
||
<input type="text" id="configHost" class="form-input" placeholder="localhost">
|
||
</div>
|
||
<div class="form-group form-group-sm">
|
||
<label>端口</label>
|
||
<input type="number" id="configPort" class="form-input" placeholder="3306">
|
||
</div>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>数据库名</label>
|
||
<input type="text" id="configDbname" class="form-input" placeholder="CapacityReport">
|
||
</div>
|
||
<div class="form-row">
|
||
<div class="form-group">
|
||
<label>用户名</label>
|
||
<input type="text" id="configUser" class="form-input" placeholder="root">
|
||
</div>
|
||
<div class="form-group">
|
||
<label>密码</label>
|
||
<div class="password-input-wrapper">
|
||
<input type="password" id="configPasswd" class="form-input" placeholder="输入密码">
|
||
<button type="button" class="password-toggle" id="togglePassword" title="显示/隐藏密码">
|
||
<span class="eye-icon">👁</span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="card-footer">
|
||
<button class="btn btn-primary" id="saveMysqlConfig">保存配置</button>
|
||
<button class="btn btn-outline" id="testDbConnection">测试连接</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Sheet 过滤规则 -->
|
||
<div class="card settings-card">
|
||
<div class="card-header">
|
||
<span class="card-title">Sheet 过滤规则</span>
|
||
</div>
|
||
<div class="card-body">
|
||
<p class="form-hint">匹配这些关键词的 Sheet 将被跳过处理</p>
|
||
<div class="filter-list" id="sheetFilterList">
|
||
<!-- 动态生成 -->
|
||
</div>
|
||
<div class="add-filter-row">
|
||
<input type="text" id="newSheetFilter" class="form-input" placeholder="输入过滤关键词">
|
||
<button class="btn btn-outline btn-sm" id="addSheetFilter">添加</button>
|
||
</div>
|
||
</div>
|
||
<div class="card-footer">
|
||
<button class="btn btn-primary" id="saveSheetFilter">保存规则</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 右侧列 - 字段映射 -->
|
||
<div class="settings-column settings-column-wide">
|
||
<div class="card settings-card field-mapping-card">
|
||
<div class="card-header">
|
||
<div class="card-header-top">
|
||
<div class="card-header-left">
|
||
<span class="card-title">字段映射配置</span>
|
||
<span class="field-count" id="fieldCount">0 个字段</span>
|
||
</div>
|
||
<input type="text" class="field-search-input" id="fieldSearchInput" placeholder="搜索字段...">
|
||
</div>
|
||
<p class="form-hint">定义 Excel 列名到数据库字段的映射规则,提取来源匹配任意一个即可</p>
|
||
</div>
|
||
<div class="card-body">
|
||
<div class="field-mapping-list" id="fieldMappingList">
|
||
<!-- 动态生成 -->
|
||
</div>
|
||
</div>
|
||
<div class="card-footer">
|
||
<button class="btn btn-outline" id="addFieldMapping">添加字段</button>
|
||
<button class="btn btn-primary" id="saveFieldMapping">保存映射</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
</main>
|
||
</div>
|
||
|
||
<!-- Toast 通知 -->
|
||
<div class="toast-container" id="toastContainer"></div>
|
||
|
||
<!-- 重启服务加载遮罩 -->
|
||
<div class="restart-overlay" id="restartOverlay">
|
||
<div class="restart-overlay-content">
|
||
<div class="restart-overlay-spinner"></div>
|
||
<div class="restart-overlay-text">正在重启服务...</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 确认对话框 -->
|
||
<div class="modal" id="confirmModal">
|
||
<div class="modal-backdrop"></div>
|
||
<div class="modal-content">
|
||
<h3 id="confirmTitle">确认操作</h3>
|
||
<p id="confirmMessage">确定要执行此操作吗?</p>
|
||
<div class="modal-actions">
|
||
<button class="btn btn-outline" id="confirmCancel">取消</button>
|
||
<button class="btn btn-danger" id="confirmOk">确定</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
<script src="/static/js/app.js"></script>
|
||
</body>
|
||
</html>
|