重构项目结构,移除旧Java客户端,添加前后端目录

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
liumangmang
2026-02-09 17:22:26 +08:00
parent ddeb7c65ff
commit 9ee9c96a91
71 changed files with 4893 additions and 2943 deletions

632
ui-preview-idea-style.html Normal file
View File

@@ -0,0 +1,632 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SVN管理器 - IDEA风格界面预览</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&family=IBM+Plex+Sans:wght@300;400;500;600;700&display=swap');
* {
font-family: 'IBM Plex Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}
.font-mono {
font-family: 'JetBrains Mono', monospace;
}
/* 深色主题配色 */
:root {
--bg-primary: #1E293B;
--bg-secondary: #334155;
--bg-tertiary: #0F172A;
--text-primary: #F8FAFC;
--text-secondary: #CBD5E1;
--border-color: #334155;
--accent-green: #22C55E;
--accent-blue: #3B82F6;
--accent-yellow: #F59E0B;
--accent-red: #EF4444;
}
body {
background: var(--bg-tertiary);
color: var(--text-primary);
}
/* 左侧项目列表 */
.project-sidebar {
background: var(--bg-primary);
border-right: 1px solid var(--border-color);
}
.project-item {
transition: all 0.2s ease;
cursor: pointer;
border-left: 3px solid transparent;
}
.project-item:hover {
background: var(--bg-secondary);
}
.project-item.active {
background: var(--bg-secondary);
border-left-color: var(--accent-blue);
}
/* 文件树样式 */
.file-tree {
background: var(--bg-primary);
font-family: 'JetBrains Mono', monospace;
font-size: 13px;
}
.tree-node {
display: flex;
align-items: center;
padding: 2px 4px;
cursor: pointer;
user-select: none;
transition: background-color 0.15s ease;
}
.tree-node:hover {
background: var(--bg-secondary);
}
.tree-node.selected {
background: #3B82F6;
color: white;
}
.tree-indent {
display: inline-block;
width: 16px;
}
.tree-toggle {
width: 16px;
height: 16px;
display: inline-flex;
align-items: center;
justify-content: center;
margin-right: 4px;
color: var(--text-secondary);
font-size: 10px;
}
.tree-icon {
width: 16px;
height: 16px;
margin-right: 6px;
display: inline-flex;
align-items: center;
justify-content: center;
color: var(--text-secondary);
}
.tree-label {
flex: 1;
display: flex;
align-items: center;
gap: 6px;
}
/* SVN状态徽章 */
.svn-badge {
font-size: 10px;
padding: 2px 6px;
border-radius: 3px;
font-weight: 600;
font-family: 'JetBrains Mono', monospace;
}
.svn-badge.modified {
background: rgba(34, 197, 94, 0.2);
color: var(--accent-green);
}
.svn-badge.added {
background: rgba(59, 130, 246, 0.2);
color: var(--accent-blue);
}
.svn-badge.deleted {
background: rgba(239, 68, 68, 0.2);
color: var(--accent-red);
}
.svn-badge.conflicted {
background: rgba(245, 158, 11, 0.2);
color: var(--accent-yellow);
}
.svn-badge.unversioned {
background: rgba(148, 163, 184, 0.2);
color: #94A3B8;
}
/* 工具栏 */
.toolbar {
background: var(--bg-primary);
border-bottom: 1px solid var(--border-color);
}
.toolbar-btn {
padding: 6px 12px;
background: transparent;
border: none;
color: var(--text-secondary);
cursor: pointer;
border-radius: 4px;
transition: all 0.15s ease;
font-size: 13px;
}
.toolbar-btn:hover {
background: var(--bg-secondary);
color: var(--text-primary);
}
.toolbar-btn.active {
background: var(--bg-secondary);
color: var(--accent-blue);
}
/* 滚动条样式 */
::-webkit-scrollbar {
width: 12px;
height: 12px;
}
::-webkit-scrollbar-track {
background: var(--bg-primary);
}
::-webkit-scrollbar-thumb {
background: var(--bg-secondary);
border-radius: 6px;
}
::-webkit-scrollbar-thumb:hover {
background: #475569;
}
/* 右键菜单 */
.context-menu {
position: fixed;
background: var(--bg-primary);
border: 1px solid var(--border-color);
border-radius: 4px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
padding: 4px 0;
min-width: 180px;
z-index: 1000;
display: none;
}
.context-menu-item {
padding: 8px 16px;
cursor: pointer;
color: var(--text-primary);
font-size: 13px;
transition: background-color 0.15s ease;
}
.context-menu-item:hover {
background: var(--bg-secondary);
}
.context-menu-item.disabled {
color: var(--text-secondary);
cursor: not-allowed;
}
.context-menu-item.disabled:hover {
background: transparent;
}
.context-menu-separator {
height: 1px;
background: var(--border-color);
margin: 4px 0;
}
</style>
</head>
<body class="overflow-hidden">
<div class="flex h-screen">
<!-- 左侧:项目列表 -->
<div class="project-sidebar w-64 flex flex-col">
<!-- 头部 -->
<div class="p-4 border-b border-gray-700">
<div class="flex items-center gap-3 mb-4">
<div class="w-8 h-8 bg-gradient-to-br from-blue-500 to-purple-600 rounded flex items-center justify-center">
<i class="fas fa-code-branch text-white text-sm"></i>
</div>
<div>
<h1 class="text-sm font-semibold text-white">SVN管理器</h1>
<p class="text-xs text-gray-400">多项目管理</p>
</div>
</div>
<button class="w-full bg-blue-600 hover:bg-blue-700 text-white text-xs font-medium py-2 px-3 rounded transition-colors duration-200 flex items-center justify-center gap-2">
<i class="fas fa-plus text-xs"></i>
添加项目
</button>
</div>
<!-- 项目列表 -->
<div class="flex-1 overflow-y-auto p-2">
<div class="project-item active px-3 py-2 rounded mb-1" onclick="selectProject('project-a')">
<div class="flex items-center gap-2">
<i class="fas fa-folder text-blue-400 text-sm"></i>
<div class="flex-1 min-w-0">
<div class="text-sm font-medium text-white truncate">项目A - 前端开发</div>
<div class="text-xs text-gray-400 truncate">/workspace/project-a</div>
</div>
</div>
<div class="mt-1 flex items-center gap-2">
<span class="text-xs px-1.5 py-0.5 bg-green-500/20 text-green-400 rounded">已同步</span>
<span class="text-xs text-gray-500">r1234</span>
</div>
</div>
<div class="project-item px-3 py-2 rounded mb-1" onclick="selectProject('project-b')">
<div class="flex items-center gap-2">
<i class="fas fa-folder text-purple-400 text-sm"></i>
<div class="flex-1 min-w-0">
<div class="text-sm font-medium text-white truncate">项目B - 后端服务</div>
<div class="text-xs text-gray-400 truncate">/workspace/project-b</div>
</div>
</div>
<div class="mt-1 flex items-center gap-2">
<span class="text-xs px-1.5 py-0.5 bg-yellow-500/20 text-yellow-400 rounded">有更新</span>
<span class="text-xs text-gray-500">r2456</span>
</div>
</div>
<div class="project-item px-3 py-2 rounded mb-1" onclick="selectProject('project-c')">
<div class="flex items-center gap-2">
<i class="fas fa-folder text-pink-400 text-sm"></i>
<div class="flex-1 min-w-0">
<div class="text-sm font-medium text-white truncate">项目C - 移动端</div>
<div class="text-xs text-gray-400 truncate">/workspace/project-c</div>
</div>
</div>
<div class="mt-1 flex items-center gap-2">
<span class="text-xs px-1.5 py-0.5 bg-gray-500/20 text-gray-400 rounded">未连接</span>
<span class="text-xs text-gray-500">r1890</span>
</div>
</div>
</div>
<!-- 底部信息 -->
<div class="p-3 border-t border-gray-700">
<div class="text-xs text-gray-400 text-center">共 3 个项目</div>
</div>
</div>
<!-- 右侧:文件树和工具栏 -->
<div class="flex-1 flex flex-col overflow-hidden" style="background: var(--bg-tertiary);">
<!-- 工具栏 -->
<div class="toolbar px-4 py-2 flex items-center justify-between">
<div class="flex items-center gap-2">
<h2 class="text-sm font-semibold text-white" id="project-title">项目A - 前端开发</h2>
<span class="text-xs text-gray-400" id="project-path">/workspace/project-a</span>
</div>
<div class="flex items-center gap-1">
<button class="toolbar-btn" title="刷新状态">
<i class="fas fa-sync-alt"></i>
</button>
<button class="toolbar-btn" title="更新">
<i class="fas fa-download"></i>
</button>
<button class="toolbar-btn" title="提交">
<i class="fas fa-upload"></i>
</button>
<button class="toolbar-btn" title="状态">
<i class="fas fa-info-circle"></i>
</button>
<button class="toolbar-btn" title="日志">
<i class="fas fa-history"></i>
</button>
<button class="toolbar-btn" title="差异">
<i class="fas fa-code"></i>
</button>
</div>
</div>
<!-- 文件树 -->
<div class="file-tree flex-1 overflow-y-auto p-2" id="file-tree">
<!-- 项目根目录 -->
<div class="tree-node selected" onclick="selectNode(this)" oncontextmenu="showContextMenu(event, this)">
<span class="tree-indent"></span>
<span class="tree-icon"><i class="fas fa-folder-open text-blue-400"></i></span>
<span class="tree-label">
<span>project-a</span>
<span class="text-xs text-gray-500 ml-2">r1234</span>
</span>
</div>
<!-- src目录 -->
<div class="tree-node" onclick="toggleNode(this)" oncontextmenu="showContextMenu(event, this)">
<span class="tree-indent"></span>
<span class="tree-toggle"><i class="fas fa-chevron-down text-xs"></i></span>
<span class="tree-icon"><i class="fas fa-folder-open text-blue-400"></i></span>
<span class="tree-label">src</span>
</div>
<!-- src/main目录 -->
<div class="tree-node" onclick="toggleNode(this)" oncontextmenu="showContextMenu(event, this)">
<span class="tree-indent"></span>
<span class="tree-indent"></span>
<span class="tree-toggle"><i class="fas fa-chevron-down text-xs"></i></span>
<span class="tree-icon"><i class="fas fa-folder-open text-blue-400"></i></span>
<span class="tree-label">main</span>
</div>
<!-- src/main/java目录 -->
<div class="tree-node" onclick="toggleNode(this)" oncontextmenu="showContextMenu(event, this)">
<span class="tree-indent"></span>
<span class="tree-indent"></span>
<span class="tree-indent"></span>
<span class="tree-toggle"><i class="fas fa-chevron-down text-xs"></i></span>
<span class="tree-icon"><i class="fas fa-folder-open text-blue-400"></i></span>
<span class="tree-label">java</span>
</div>
<!-- MainController.java - 已修改 -->
<div class="tree-node" onclick="selectNode(this); openFile('MainController.java')" oncontextmenu="showContextMenu(event, this)">
<span class="tree-indent"></span>
<span class="tree-indent"></span>
<span class="tree-indent"></span>
<span class="tree-indent"></span>
<span class="tree-icon"><i class="fab fa-java text-orange-400"></i></span>
<span class="tree-label">
<span>MainController.java</span>
<span class="svn-badge modified ml-2">M</span>
</span>
</div>
<!-- StatusService.java - 正常 -->
<div class="tree-node" onclick="selectNode(this); openFile('StatusService.java')" oncontextmenu="showContextMenu(event, this)">
<span class="tree-indent"></span>
<span class="tree-indent"></span>
<span class="tree-indent"></span>
<span class="tree-indent"></span>
<span class="tree-icon"><i class="fab fa-java text-orange-400"></i></span>
<span class="tree-label">StatusService.java</span>
</div>
<!-- src/main/resources目录 -->
<div class="tree-node" onclick="toggleNode(this)" oncontextmenu="showContextMenu(event, this)">
<span class="tree-indent"></span>
<span class="tree-indent"></span>
<span class="tree-indent"></span>
<span class="tree-toggle"><i class="fas fa-chevron-right text-xs"></i></span>
<span class="tree-icon"><i class="fas fa-folder text-gray-500"></i></span>
<span class="tree-label">resources</span>
</div>
<!-- src/test目录 -->
<div class="tree-node" onclick="toggleNode(this)" oncontextmenu="showContextMenu(event, this)">
<span class="tree-indent"></span>
<span class="tree-indent"></span>
<span class="tree-toggle"><i class="fas fa-chevron-right text-xs"></i></span>
<span class="tree-icon"><i class="fas fa-folder text-gray-500"></i></span>
<span class="tree-label">test</span>
</div>
<!-- pom.xml - 已修改 -->
<div class="tree-node" onclick="selectNode(this); openFile('pom.xml')" oncontextmenu="showContextMenu(event, this)">
<span class="tree-indent"></span>
<span class="tree-icon"><i class="fas fa-file-code text-yellow-400"></i></span>
<span class="tree-label">
<span>pom.xml</span>
<span class="svn-badge modified ml-2">M</span>
</span>
</div>
<!-- README.md - 正常 -->
<div class="tree-node" onclick="selectNode(this); openFile('README.md')" oncontextmenu="showContextMenu(event, this)">
<span class="tree-indent"></span>
<span class="tree-icon"><i class="fab fa-markdown text-blue-400"></i></span>
<span class="tree-label">README.md</span>
</div>
<!-- .gitignore - 新增 -->
<div class="tree-node" onclick="selectNode(this); openFile('.gitignore')" oncontextmenu="showContextMenu(event, this)">
<span class="tree-indent"></span>
<span class="tree-icon"><i class="fas fa-file text-gray-400"></i></span>
<span class="tree-label">
<span>.gitignore</span>
<span class="svn-badge added ml-2">A</span>
</span>
</div>
<!-- config.properties - 冲突 -->
<div class="tree-node" onclick="selectNode(this); openFile('config.properties')" oncontextmenu="showContextMenu(event, this)">
<span class="tree-indent"></span>
<span class="tree-icon"><i class="fas fa-file text-gray-400"></i></span>
<span class="tree-label">
<span>config.properties</span>
<span class="svn-badge conflicted ml-2">C</span>
</span>
</div>
<!-- temp.log - 未版本控制 -->
<div class="tree-node" onclick="selectNode(this); openFile('temp.log')" oncontextmenu="showContextMenu(event, this)">
<span class="tree-indent"></span>
<span class="tree-icon"><i class="fas fa-file text-gray-500"></i></span>
<span class="tree-label">
<span>temp.log</span>
<span class="svn-badge unversioned ml-2">?</span>
</span>
</div>
</div>
</div>
</div>
<!-- 右键菜单 -->
<div class="context-menu" id="context-menu">
<div class="context-menu-item" onclick="openFileFromMenu()">
<i class="fas fa-eye mr-2"></i>查看文件
</div>
<div class="context-menu-item" onclick="showDiff()">
<i class="fas fa-code mr-2"></i>查看差异
</div>
<div class="context-menu-item" onclick="showHistory()">
<i class="fas fa-history mr-2"></i>查看历史
</div>
<div class="context-menu-separator"></div>
<div class="context-menu-item" onclick="addToSvn()">
<i class="fas fa-plus mr-2"></i>添加到SVN
</div>
<div class="context-menu-item" onclick="revertFile()">
<i class="fas fa-undo mr-2"></i>还原
</div>
<div class="context-menu-item" onclick="deleteFile()">
<i class="fas fa-trash mr-2"></i>删除
</div>
<div class="context-menu-separator"></div>
<div class="context-menu-item" onclick="copyPath()">
<i class="fas fa-copy mr-2"></i>复制路径
</div>
<div class="context-menu-item" onclick="showInExplorer()">
<i class="fas fa-folder-open mr-2"></i>在资源管理器中显示
</div>
</div>
<script>
// 项目数据
const projects = {
'project-a': {
title: '项目A - 前端开发',
path: '/workspace/project-a'
},
'project-b': {
title: '项目B - 后端服务',
path: '/workspace/project-b'
},
'project-c': {
title: '项目C - 移动端',
path: '/workspace/project-c'
}
};
// 选择项目
function selectProject(projectId) {
// 更新项目列表选中状态
document.querySelectorAll('.project-item').forEach(item => {
item.classList.remove('active');
});
event.currentTarget.classList.add('active');
// 更新标题
const project = projects[projectId];
if (project) {
document.getElementById('project-title').textContent = project.title;
document.getElementById('project-path').textContent = project.path;
}
}
// 切换树节点展开/折叠
function toggleNode(node) {
event.stopPropagation();
const toggle = node.querySelector('.tree-toggle i');
const icon = node.querySelector('.tree-icon i');
if (toggle.classList.contains('fa-chevron-right')) {
toggle.classList.remove('fa-chevron-right');
toggle.classList.add('fa-chevron-down');
icon.classList.remove('fa-folder');
icon.classList.add('fa-folder-open');
icon.classList.add('text-blue-400');
icon.classList.remove('text-gray-500');
} else {
toggle.classList.remove('fa-chevron-down');
toggle.classList.add('fa-chevron-right');
icon.classList.remove('fa-folder-open');
icon.classList.add('fa-folder');
icon.classList.remove('text-blue-400');
icon.classList.add('text-gray-500');
}
}
// 选择树节点
function selectNode(node) {
document.querySelectorAll('.tree-node').forEach(n => {
n.classList.remove('selected');
});
node.classList.add('selected');
}
// 打开文件
function openFile(filename) {
alert(`打开文件: ${filename}\n\n这里会显示文件内容查看器`);
}
// 显示右键菜单
function showContextMenu(event, node) {
event.preventDefault();
const menu = document.getElementById('context-menu');
menu.style.display = 'block';
menu.style.left = event.pageX + 'px';
menu.style.top = event.pageY + 'px';
// 选中节点
selectNode(node);
// 点击其他地方关闭菜单
setTimeout(() => {
document.addEventListener('click', function closeMenu() {
menu.style.display = 'none';
document.removeEventListener('click', closeMenu);
});
}, 0);
}
// 右键菜单操作
function openFileFromMenu() {
alert('查看文件');
}
function showDiff() {
alert('查看差异');
}
function showHistory() {
alert('查看历史');
}
function addToSvn() {
alert('添加到SVN');
}
function revertFile() {
alert('还原文件');
}
function deleteFile() {
alert('删除文件');
}
function copyPath() {
alert('复制路径');
}
function showInExplorer() {
alert('在资源管理器中显示');
}
// 点击空白处关闭右键菜单
document.addEventListener('contextmenu', function(e) {
if (!e.target.closest('.tree-node')) {
document.getElementById('context-menu').style.display = 'none';
}
});
</script>
</body>
</html>