225 lines
9.2 KiB
HTML
225 lines
9.2 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<title>Git Sync 控制台</title>
|
||
<link rel="stylesheet" href="/style.css">
|
||
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/chart.umd.min.js"></script>
|
||
</head>
|
||
<body>
|
||
<header>
|
||
<div class="brand"><span class="brand-dot"></span>Git Sync 控制台</div>
|
||
<div class="header-actions">
|
||
<span id="conn" class="conn">连接中…</span>
|
||
<button class="btn btn-icon" id="btn-theme" title="切换深色 / 浅色模式">🌙</button>
|
||
<button class="btn" id="btn-sync-all">全部同步</button>
|
||
<button class="btn btn-primary" id="btn-new">+ 新建配置</button>
|
||
</div>
|
||
</header>
|
||
|
||
<main class="layout">
|
||
<section class="main-col">
|
||
<div id="grid" class="grid"></div>
|
||
<div id="empty" class="empty" hidden>
|
||
<p>还没有任何仓库配置。</p>
|
||
<button class="btn btn-primary" id="btn-empty-new">创建第一个配置</button>
|
||
</div>
|
||
</section>
|
||
<aside id="live" class="live">
|
||
<div class="live-head">
|
||
<h2>实时活动</h2>
|
||
<span id="live-conn" class="conn">连接中…</span>
|
||
<button class="btn btn-sm" id="btn-live-clear" title="清空本面板">清空</button>
|
||
</div>
|
||
<div class="live-hint">所有仓库的同步(手动与自动)实时显示在此,无需点进详情</div>
|
||
<div id="live-log" class="live-log"></div>
|
||
</aside>
|
||
</main>
|
||
|
||
<div id="modal" class="modal" hidden>
|
||
<div class="modal-box">
|
||
<div class="modal-head">
|
||
<h2 id="m-title">详情</h2>
|
||
<button class="btn-icon" id="m-close" title="关闭">✕</button>
|
||
</div>
|
||
<div class="tabs" id="m-tabs">
|
||
<button data-tab="log" class="tab active">日志</button>
|
||
<button data-tab="history" class="tab">历史</button>
|
||
<button data-tab="diff" class="tab">差异</button>
|
||
<button data-tab="file" class="tab">文件</button>
|
||
<button data-tab="conflict" class="tab">冲突</button>
|
||
<button data-tab="stats" class="tab">统计</button>
|
||
<button data-tab="config" class="tab">配置</button>
|
||
</div>
|
||
<div class="tab-body">
|
||
<div id="tab-log" class="tab-pane">
|
||
<div class="log-tools">
|
||
<label>级别
|
||
<select id="log-level">
|
||
<option value="all">全部</option>
|
||
<option value="error">仅错误</option>
|
||
<option value="warn">仅警告</option>
|
||
<option value="info">仅信息</option>
|
||
</select>
|
||
</label>
|
||
<input id="log-search" class="log-search" placeholder="搜索日志内容(关键词)">
|
||
<button class="btn btn-sm" id="btn-log-clear" title="清除过滤条件">清除</button>
|
||
</div>
|
||
<pre id="logbox" class="logbox">加载中…</pre>
|
||
</div>
|
||
<div id="tab-history" class="tab-pane" hidden>
|
||
<div id="commit-list" class="commit-list">加载中…</div>
|
||
</div>
|
||
<div id="tab-diff" class="tab-pane" hidden>
|
||
<div class="diff-head">
|
||
<label>范围
|
||
<select id="f-diff-scope">
|
||
<option value="working">工作区(未暂存)</option>
|
||
<option value="staged">暂存区</option>
|
||
<option value="all">全部(含已提交未推送)</option>
|
||
<option value="remote">与远程对比</option>
|
||
</select>
|
||
</label>
|
||
<button class="btn btn-sm" id="btn-diff-refresh">刷新</button>
|
||
<button class="btn btn-sm" id="btn-diff-copy">复制</button>
|
||
<button class="btn btn-sm" id="btn-diff-download">下载 .patch</button>
|
||
<span id="diff-filter" class="diff-filter" hidden></span>
|
||
</div>
|
||
<div id="diff-stat" class="diff-stat"></div>
|
||
<pre id="diffbox" class="diffbox">加载中…</pre>
|
||
</div>
|
||
<div id="tab-file" class="tab-pane" hidden>
|
||
<div class="file-head">
|
||
<button class="btn btn-sm" id="btn-file-refresh">刷新文件列表</button>
|
||
<button class="btn btn-sm" id="btn-file-diff" title="只看当前文件的差异">对比此文件</button>
|
||
<span id="file-current" class="file-current"></span>
|
||
<span id="file-draft" class="file-draft" hidden></span>
|
||
</div>
|
||
<div class="file-body">
|
||
<div id="file-list" class="file-list">加载中…</div>
|
||
<div class="file-edit-col">
|
||
<textarea id="file-editor" class="file-editor" placeholder="选择左侧文件进行编辑(Ctrl/Cmd + S 保存)" spellcheck="false"></textarea>
|
||
<div class="file-actions">
|
||
<input id="file-msg" class="file-msg" placeholder="提交说明(可选)">
|
||
<button class="btn btn-sm" id="btn-file-save">保存</button>
|
||
<button class="btn btn-sm btn-primary" id="btn-file-commit">保存并提交</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="tab-conflict" class="tab-pane" hidden>
|
||
<div class="manual-actions">
|
||
<button class="btn btn-sm" id="btn-fetch">获取</button>
|
||
<button class="btn btn-sm" id="btn-pull">拉取</button>
|
||
<button class="btn btn-sm" id="btn-push">推送</button>
|
||
</div>
|
||
<div class="conflict-actions" id="pull-conflict-actions">
|
||
<button class="btn btn-danger" id="btn-abort">放弃合并</button>
|
||
<button class="btn btn-primary" id="btn-resolved">我已在本地解决,继续</button>
|
||
</div>
|
||
<div class="conflict-actions" id="push-conflict-actions" hidden>
|
||
<span class="hint" id="push-conflict-hint"></span>
|
||
<button class="btn btn-danger" id="btn-force-push">强制推送(--force-with-lease)</button>
|
||
<button class="btn" id="btn-abort-push">放弃强制推送</button>
|
||
</div>
|
||
<div id="conflict-list"></div>
|
||
</div>
|
||
<div id="tab-stats" class="tab-pane" hidden>
|
||
<div id="stat-summary" class="stat-summary"></div>
|
||
<canvas id="stat-chart" height="120"></canvas>
|
||
</div>
|
||
<div id="tab-config" class="tab-pane" hidden>
|
||
<form id="cfg-form" autocomplete="off">
|
||
<div class="form-grid">
|
||
<label>配置名称
|
||
<input name="name" id="f-name" required pattern="[A-Za-z0-9_\-]+" title="仅字母、数字、下划线、连字符">
|
||
</label>
|
||
<label>分支
|
||
<input name="branch" id="f-branch" value="main">
|
||
</label>
|
||
<label class="full">仓库路径
|
||
<input name="repo_path" id="f-path" placeholder="C:\path\to\repo 或 /c/path/to/repo" required>
|
||
</label>
|
||
<label class="full">远程仓库(每行一个,格式 名称=URL)
|
||
<textarea name="remotes" id="f-remotes" rows="3" placeholder="origin=https://github.com/user/repo.git"></textarea>
|
||
</label>
|
||
<label>操作模式
|
||
<select name="mode" id="f-mode">
|
||
<option value="both">both(拉取并推送)</option>
|
||
<option value="push">push(仅推送)</option>
|
||
<option value="pull">pull(仅拉取)</option>
|
||
</select>
|
||
</label>
|
||
<label>检查间隔(秒)
|
||
<input name="interval" id="f-interval" type="number" min="5" value="60">
|
||
</label>
|
||
<label>认证方式
|
||
<select name="auth_method" id="f-auth">
|
||
<option value="ssh">SSH</option>
|
||
<option value="https">HTTPS(支持重试)</option>
|
||
</select>
|
||
</label>
|
||
<label>冲突策略
|
||
<select name="conflict_strategy" id="f-conflict">
|
||
<option value="merge">merge(冲突后等待人工解决)</option>
|
||
<option value="rebase">rebase(变基)</option>
|
||
<option value="abort">abort(冲突后自动放弃)</option>
|
||
</select>
|
||
</label>
|
||
<label>推送策略(non-fast-forward)
|
||
<select name="push_strategy" id="f-push">
|
||
<option value="manual">manual(冲突后等待人工决策)</option>
|
||
<option value="rebase">rebase(变基到远程后重试)</option>
|
||
<option value="force">force(--force-with-lease 强制推送)</option>
|
||
</select>
|
||
</label>
|
||
<label>重试次数(HTTPS)
|
||
<input name="retry_count" id="f-retry" type="number" min="0" value="3">
|
||
</label>
|
||
<label>重试间隔(秒,HTTPS)
|
||
<input name="retry_interval" id="f-retry-interval" type="number" min="0" value="5">
|
||
</label>
|
||
<label class="full check-row">
|
||
<input type="checkbox" id="f-autocommit">
|
||
<span>自动提交模式:检测到未提交改动时自动 commit,并随同步推送到远程</span>
|
||
</label>
|
||
<label class="full">Cron 表达式(可选,5 段:分 时 日 月 周;填写后优先于固定间隔)
|
||
<input name="cron" id="f-cron" placeholder="*/30 * * * * 表示每 30 分钟,留空使用固定间隔">
|
||
<span id="cron-next" class="cron-next"></span>
|
||
</label>
|
||
<label class="full">日志文件路径(留空使用默认 logs/配置名.log)
|
||
<input name="log_file" id="f-log">
|
||
</label>
|
||
</div>
|
||
<div class="form-actions">
|
||
<button type="submit" class="btn btn-primary">保存</button>
|
||
<button type="button" class="btn btn-danger" id="btn-delete" hidden>删除配置</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="login" class="modal" hidden>
|
||
<div class="modal-box login-box">
|
||
<div class="modal-head">
|
||
<h2>Git Sync 控制台</h2>
|
||
</div>
|
||
<div class="login-body">
|
||
<label>访问密码
|
||
<input type="password" id="login-password">
|
||
</label>
|
||
<p id="login-err" class="login-err" hidden></p>
|
||
<div class="form-actions">
|
||
<button class="btn btn-primary" id="btn-login">登录</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script src="/app.js"></script>
|
||
</body>
|
||
</html>
|