Files
CapacityReport/static/index.html
T
2026-01-15 15:59:38 +08:00

514 lines
29 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>
<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>