feat(web): 新增可视化工作台并支持预置SVN项目

新增 Spring Boot Web 后端与前端页面,打通 SVN 抓取、AI 分析、任务管理、文件下载与系统设置全流程。增加 3 个默认 SVN 预置项目下拉与默认项配置,提升日常使用效率与可维护性。
This commit is contained in:
2026-03-08 23:14:55 +08:00
parent abd375bf64
commit e26fb9cebb
25 changed files with 2458 additions and 2 deletions
+132
View File
@@ -0,0 +1,132 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>SVN 日志工作台</title>
<link rel="stylesheet" href="/styles.css">
</head>
<body>
<div class="app-shell">
<aside class="sidebar" aria-label="主导航">
<h1>SVN 工作台</h1>
<nav>
<button class="nav-item active" data-view="dashboard">工作台</button>
<button class="nav-item" data-view="svn">SVN 日志抓取</button>
<button class="nav-item" data-view="ai">AI 工作量分析</button>
<button class="nav-item" data-view="history">任务历史</button>
<button class="nav-item" data-view="settings">系统设置</button>
</nav>
</aside>
<main class="main" id="main">
<header class="main-header">
<h2 id="view-title">工作台</h2>
<p id="view-desc">查看系统状态与最近产物</p>
</header>
<section class="view active" id="view-dashboard" aria-live="polite">
<div class="grid cols-3" id="stats-cards">
<article class="card stat">
<h3>任务总数</h3>
<p id="stat-total">0</p>
</article>
<article class="card stat">
<h3>执行中</h3>
<p id="stat-running">0</p>
</article>
<article class="card stat">
<h3>失败任务</h3>
<p id="stat-failed">0</p>
</article>
</div>
<div class="grid cols-2">
<article class="card">
<h3>最近任务</h3>
<ul id="recent-tasks" class="list"></ul>
</article>
<article class="card">
<h3>最近文件</h3>
<ul id="recent-files" class="list"></ul>
</article>
</div>
</section>
<section class="view" id="view-svn">
<article class="card form-card">
<h3>SVN 抓取参数</h3>
<form id="svn-form" class="form-grid">
<label>预置项目
<select name="presetId" id="svn-preset-select" aria-label="预置 SVN 项目"></select>
</label>
<label>项目名<input name="projectName" placeholder="如:PRS-7050"></label>
<label>SVN 地址<input required name="url" placeholder="https://..." aria-label="SVN 地址"></label>
<label>账号<input required name="username" placeholder="请输入账号"></label>
<label>密码<input required type="password" name="password" placeholder="请输入密码"></label>
<label>开始版本号<input name="startRevision" inputmode="numeric" placeholder="默认最新"></label>
<label>结束版本号<input name="endRevision" inputmode="numeric" placeholder="默认最新"></label>
<label class="span-2">过滤用户名<input name="filterUser" placeholder="包含匹配,留空不过滤"></label>
<div class="actions span-2">
<button type="button" id="btn-test-connection">测试连接</button>
<button type="submit" id="btn-svn-run" class="primary">开始抓取并导出</button>
</div>
</form>
</article>
</section>
<section class="view" id="view-ai">
<article class="card form-card">
<h3>AI 分析参数</h3>
<form id="ai-form" class="form-grid">
<label class="span-2">选择 Markdown 输入文件</label>
<div class="span-2 file-picker" id="md-file-picker" role="group" aria-label="Markdown 文件选择"></div>
<label>工作周期<input name="period" placeholder="例如 2026年03月"></label>
<label>输出文件名<input name="outputFileName" placeholder="例如 202603工作量统计.xlsx"></label>
<label class="span-2">临时 API Key(可选)<input type="password" name="apiKey" placeholder="优先使用设置页或环境变量"></label>
<div class="actions span-2">
<button type="submit" id="btn-ai-run" class="primary">开始 AI 分析并导出 Excel</button>
</div>
</form>
</article>
</section>
<section class="view" id="view-history">
<article class="card">
<h3>任务列表</h3>
<div id="task-table" class="table-wrap"></div>
</article>
<article class="card">
<h3>输出文件</h3>
<div id="file-table" class="table-wrap"></div>
</article>
</section>
<section class="view" id="view-settings">
<article class="card form-card">
<h3>系统设置</h3>
<form id="settings-form" class="form-grid">
<label class="span-2">DeepSeek API Key
<input type="password" name="apiKey" placeholder="设置后将保存在当前进程内存">
</label>
<label class="span-2">默认 SVN 项目
<select name="defaultSvnPresetId" id="settings-default-preset"></select>
</label>
<label class="span-2">输出目录
<input name="outputDir" placeholder="默认 outputs">
</label>
<div class="actions span-2">
<button type="submit" class="primary">保存设置</button>
</div>
</form>
<p id="settings-state" class="muted"></p>
</article>
</section>
<section class="toast" id="toast" aria-live="assertive"></section>
</main>
</div>
<script src="/app.js" defer></script>
</body>
</html>