mirror of
https://github.com/jingyaogong/minimind.git
synced 2026-01-13 19:57:20 +08:00
update web dataset file
This commit is contained in:
parent
a0013eae8f
commit
249d1c08fe
@ -472,6 +472,37 @@ input[type="text"]:focus, input[type="number"]:focus, select:focus, textarea:foc
|
||||
filter: brightness(1.1);
|
||||
}
|
||||
|
||||
/* 模态框底部样式 */
|
||||
.modal-footer {
|
||||
display: flex;
|
||||
gap: 0.75rem;
|
||||
align-items: center;
|
||||
padding-top: 1rem;
|
||||
border-top: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.modal-footer input {
|
||||
flex: 1;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
/* 改进模态框关闭按钮 */
|
||||
.modal-close {
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: 1.5rem;
|
||||
color: var(--text-secondary);
|
||||
cursor: pointer;
|
||||
padding: 0.25rem;
|
||||
border-radius: var(--radius-sm);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.modal-close:hover {
|
||||
color: var(--text);
|
||||
background: rgba(239, 68, 68, 0.1);
|
||||
}
|
||||
|
||||
/* 文件浏览器导航 */
|
||||
.file-browser-nav {
|
||||
display: flex;
|
||||
@ -483,6 +514,11 @@ input[type="text"]:focus, input[type="number"]:focus, select:focus, textarea:foc
|
||||
border-radius: var(--radius-md);
|
||||
}
|
||||
|
||||
.nav-buttons {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.current-path {
|
||||
font-family: 'Courier New', monospace;
|
||||
font-size: 0.85rem;
|
||||
@ -519,6 +555,19 @@ input[type="text"]:focus, input[type="number"]:focus, select:focus, textarea:foc
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.file-browser-help {
|
||||
background: rgba(59, 130, 246, 0.1);
|
||||
border: 1px solid rgba(59, 130, 246, 0.3);
|
||||
border-radius: var(--radius-sm);
|
||||
padding: 0.75rem;
|
||||
margin-bottom: 1rem;
|
||||
font-size: 0.8rem;
|
||||
color: var(--info-grad-start);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.quick-path-btn {
|
||||
background: rgba(139, 92, 246, 0.1);
|
||||
color: var(--accent);
|
||||
@ -542,6 +591,7 @@ input[type="text"]:focus, input[type="number"]:focus, select:focus, textarea:foc
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius-md);
|
||||
background: rgba(22, 22, 32, 0.3);
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.file-item {
|
||||
@ -566,6 +616,15 @@ input[type="text"]:focus, input[type="number"]:focus, select:focus, textarea:foc
|
||||
border-left: 3px solid var(--accent);
|
||||
}
|
||||
|
||||
.file-item.disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.file-item.disabled:hover {
|
||||
background: none;
|
||||
}
|
||||
|
||||
.file-icon {
|
||||
margin-right: 0.75rem;
|
||||
font-size: 1.2rem;
|
||||
|
||||
@ -17,53 +17,50 @@ const hooks = {
|
||||
|
||||
window.openTab = (evt, tabName) => _openTab(evt, tabName, hooks);
|
||||
|
||||
// 文件夹选择器功能 - 支持远程文件浏览
|
||||
window.selectFolder = async (inputId) => {
|
||||
try {
|
||||
// 检测是否为远程连接(通过检查主机名或端口)
|
||||
const isRemote = window.location.hostname !== 'localhost' && window.location.hostname !== '127.0.0.1';
|
||||
|
||||
if (isRemote) {
|
||||
// 远程连接:使用服务器端文件浏览
|
||||
openRemoteFileBrowser(inputId);
|
||||
} else {
|
||||
// 本地连接:尝试本地文件系统访问
|
||||
await openLocalFileBrowser(inputId);
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('文件夹选择失败:', error);
|
||||
if (error.name !== 'AbortError') {
|
||||
// 降级到远程文件浏览
|
||||
openRemoteFileBrowser(inputId);
|
||||
}
|
||||
}
|
||||
// 文件夹选择器功能 - 直接显示服务器端文件浏览器
|
||||
window.selectFolder = (inputId) => {
|
||||
// 直接使用远程文件浏览器,不尝试本地文件系统访问
|
||||
openRemoteFileBrowser(inputId);
|
||||
};
|
||||
|
||||
// 本地文件浏览器(兼容模式)
|
||||
async function openLocalFileBrowser(inputId) {
|
||||
try {
|
||||
// 检查是否支持 File System Access API
|
||||
if ('showDirectoryPicker' in window) {
|
||||
const dirHandle = await window.showDirectoryPicker();
|
||||
const path = dirHandle.name;
|
||||
document.getElementById(inputId).value = `./${path}`;
|
||||
} else {
|
||||
// 降级到远程文件浏览
|
||||
await openRemoteFileBrowser(inputId);
|
||||
}
|
||||
} catch (error) {
|
||||
// 如果本地失败,降级到远程文件浏览
|
||||
await openRemoteFileBrowser(inputId);
|
||||
}
|
||||
}
|
||||
|
||||
// 远程文件浏览器
|
||||
// 远程文件浏览器 - 支持文件和文件夹选择
|
||||
let currentFileBrowserTarget = null;
|
||||
let currentBrowsePath = './';
|
||||
let selectedFilePath = null;
|
||||
let currentSelectionMode = 'auto'; // 'file', 'folder', or 'auto'
|
||||
|
||||
function openRemoteFileBrowser(inputId) {
|
||||
console.log('openRemoteFileBrowser called with:', inputId);
|
||||
currentFileBrowserTarget = inputId;
|
||||
document.getElementById('file-browser-modal').classList.remove('hidden');
|
||||
|
||||
// 根据输入框ID确定选择模式
|
||||
if (inputId === 'data_path') {
|
||||
currentSelectionMode = 'file'; // 数据路径需要文件选择
|
||||
console.log('Mode set to: FILE selection');
|
||||
} else if (inputId === 'save_dir' || inputId.includes('reward_model_path')) {
|
||||
currentSelectionMode = 'folder'; // 保存目录和奖励模型路径需要文件夹选择
|
||||
console.log('Mode set to: FOLDER selection');
|
||||
} else {
|
||||
currentSelectionMode = 'auto'; // 自动模式
|
||||
console.log('Mode set to: AUTO selection');
|
||||
}
|
||||
|
||||
const modal = document.getElementById('file-browser-modal');
|
||||
if (modal) {
|
||||
modal.classList.remove('hidden');
|
||||
console.log('Modal opened successfully');
|
||||
} else {
|
||||
console.error('Modal element not found!');
|
||||
return;
|
||||
}
|
||||
|
||||
// 重置选择状态
|
||||
selectedFilePath = null;
|
||||
const selectedPathInput = document.getElementById('selected-path');
|
||||
if (selectedPathInput) {
|
||||
selectedPathInput.value = '';
|
||||
console.log('Selected path input cleared');
|
||||
}
|
||||
|
||||
// 加载初始路径
|
||||
loadQuickPaths();
|
||||
@ -74,14 +71,31 @@ function closeFileBrowser() {
|
||||
document.getElementById('file-browser-modal').classList.add('hidden');
|
||||
currentFileBrowserTarget = null;
|
||||
currentBrowsePath = './';
|
||||
selectedFilePath = null;
|
||||
currentSelectionMode = 'auto';
|
||||
}
|
||||
|
||||
function confirmFileSelection() {
|
||||
const selectedPath = document.getElementById('selected-path').value;
|
||||
if (selectedPath && currentFileBrowserTarget) {
|
||||
document.getElementById(currentFileBrowserTarget).value = selectedPath;
|
||||
console.log('confirmFileSelection called');
|
||||
console.log('selectedFilePath:', selectedFilePath);
|
||||
console.log('currentFileBrowserTarget:', currentFileBrowserTarget);
|
||||
|
||||
if (selectedFilePath && currentFileBrowserTarget) {
|
||||
const targetElement = document.getElementById(currentFileBrowserTarget);
|
||||
console.log('targetElement:', targetElement);
|
||||
|
||||
if (targetElement) {
|
||||
targetElement.value = selectedFilePath;
|
||||
console.log('Value set successfully');
|
||||
closeFileBrowser();
|
||||
} else {
|
||||
console.error('Target element not found:', currentFileBrowserTarget);
|
||||
alert('错误:无法找到目标输入框');
|
||||
}
|
||||
} else {
|
||||
console.log('Missing selection or target');
|
||||
alert('请先选择文件或文件夹');
|
||||
}
|
||||
closeFileBrowser();
|
||||
}
|
||||
|
||||
function navigateToParent() {
|
||||
@ -92,6 +106,13 @@ function navigateToParent() {
|
||||
}
|
||||
}
|
||||
|
||||
function selectCurrentDirectory() {
|
||||
// 选择当前目录
|
||||
selectedFilePath = currentBrowsePath;
|
||||
document.getElementById('selected-path').value = currentBrowsePath;
|
||||
// 可以关闭模态框或让用户继续浏览
|
||||
}
|
||||
|
||||
async function loadQuickPaths() {
|
||||
try {
|
||||
const response = await fetch('/api/quick-paths');
|
||||
@ -116,9 +137,15 @@ async function loadQuickPaths() {
|
||||
}
|
||||
|
||||
async function browsePath(path) {
|
||||
console.log('browsePath called with:', path);
|
||||
try {
|
||||
currentBrowsePath = path;
|
||||
selectedFilePath = null; // 重置选中的文件路径
|
||||
document.getElementById('current-path').textContent = path;
|
||||
document.getElementById('selected-path').value = ''; // 清空显示
|
||||
|
||||
// 更新帮助文本
|
||||
updateHelpText();
|
||||
|
||||
const response = await fetch(`/api/browse?path=${encodeURIComponent(path)}`);
|
||||
const data = await response.json();
|
||||
@ -129,6 +156,7 @@ async function browsePath(path) {
|
||||
}
|
||||
|
||||
renderFileList(data);
|
||||
console.log('File list rendered successfully');
|
||||
} catch (error) {
|
||||
console.error('浏览路径失败:', error);
|
||||
alert('浏览路径失败,请检查网络连接');
|
||||
@ -154,17 +182,29 @@ function renderFileList(data) {
|
||||
fileList.appendChild(div);
|
||||
});
|
||||
|
||||
// 渲染文件
|
||||
files.forEach(item => {
|
||||
const div = createFileItem(item, '📄');
|
||||
fileList.appendChild(div);
|
||||
});
|
||||
// 渲染文件(仅在文件选择模式或自动模式下显示)
|
||||
if (currentSelectionMode !== 'folder') {
|
||||
files.forEach(item => {
|
||||
const div = createFileItem(item, '📄');
|
||||
fileList.appendChild(div);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function createFileItem(item, icon) {
|
||||
const div = document.createElement('div');
|
||||
div.className = 'file-item';
|
||||
div.onclick = () => selectFileItem(item);
|
||||
|
||||
// 根据选择模式添加适当的CSS类
|
||||
if (currentSelectionMode === 'file' && item.type === 'directory') {
|
||||
// 文件选择模式下,文件夹只用于导航,不能选择
|
||||
div.classList.add('navigable');
|
||||
} else if (currentSelectionMode === 'folder' && item.type === 'file') {
|
||||
// 文件夹选择模式下,文件不能被选择
|
||||
div.classList.add('disabled');
|
||||
}
|
||||
|
||||
div.onclick = (event) => selectFileItem(item, event);
|
||||
|
||||
div.innerHTML = `
|
||||
<span class="file-icon">${icon}</span>
|
||||
@ -175,14 +215,54 @@ function createFileItem(item, icon) {
|
||||
return div;
|
||||
}
|
||||
|
||||
function selectFileItem(item) {
|
||||
function selectFileItem(item, event) {
|
||||
console.log('selectFileItem called with:', item);
|
||||
console.log('currentSelectionMode:', currentSelectionMode);
|
||||
console.log('event:', event);
|
||||
|
||||
// 检查是否点击了被禁用的项目
|
||||
if (event && event.currentTarget && event.currentTarget.classList.contains('disabled')) {
|
||||
console.log('Clicked disabled item, ignoring');
|
||||
return;
|
||||
}
|
||||
|
||||
if (item.type === 'directory') {
|
||||
browsePath(item.path);
|
||||
// 文件夹:根据选择模式决定行为
|
||||
if (currentSelectionMode === 'file') {
|
||||
// 文件选择模式:只能选择文件,点击进入目录
|
||||
console.log('File mode: navigating into directory');
|
||||
browsePath(item.path);
|
||||
} else if (currentSelectionMode === 'folder') {
|
||||
// 文件夹选择模式:可以选择文件夹
|
||||
console.log('Folder mode: selecting directory');
|
||||
selectedFilePath = item.path;
|
||||
document.getElementById('selected-path').value = item.path;
|
||||
// 高亮显示选中的文件夹
|
||||
document.querySelectorAll('.file-item').forEach(el => el.classList.remove('selected'));
|
||||
if (event && event.currentTarget) {
|
||||
event.currentTarget.classList.add('selected');
|
||||
}
|
||||
console.log('Directory selected:', selectedFilePath);
|
||||
} else {
|
||||
// 自动模式:点击进入目录
|
||||
console.log('Auto mode: navigating into directory');
|
||||
browsePath(item.path);
|
||||
}
|
||||
} else {
|
||||
document.getElementById('selected-path').value = item.path;
|
||||
// 文件被选中,可以高亮显示
|
||||
document.querySelectorAll('.file-item').forEach(el => el.classList.remove('selected'));
|
||||
event.currentTarget.classList.add('selected');
|
||||
// 文件:选中文件路径(仅在选择文件或自动模式下)
|
||||
if (currentSelectionMode !== 'folder') {
|
||||
console.log('Selecting file:', item.path);
|
||||
selectedFilePath = item.path;
|
||||
document.getElementById('selected-path').value = item.path;
|
||||
// 高亮显示选中的文件
|
||||
document.querySelectorAll('.file-item').forEach(el => el.classList.remove('selected'));
|
||||
if (event && event.currentTarget) {
|
||||
event.currentTarget.classList.add('selected');
|
||||
}
|
||||
console.log('File selected:', selectedFilePath);
|
||||
} else {
|
||||
console.log('File clicked in folder mode, ignoring');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -194,6 +274,60 @@ function formatFileSize(bytes) {
|
||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i];
|
||||
}
|
||||
|
||||
function updateHelpText() {
|
||||
const helpText = document.querySelector('.file-browser-help');
|
||||
const modalTitle = document.getElementById('modal-title');
|
||||
|
||||
if (!helpText) return;
|
||||
|
||||
let text = '';
|
||||
let title = '';
|
||||
switch (currentSelectionMode) {
|
||||
case 'file':
|
||||
text = '💡 请选择文件:点击文件选择,点击文件夹进入目录,使用📍选择当前目录';
|
||||
title = '选择文件';
|
||||
break;
|
||||
case 'folder':
|
||||
text = '💡 请选择文件夹:点击文件夹选择,点击文件无效,使用📍选择当前目录';
|
||||
title = '选择文件夹';
|
||||
break;
|
||||
default:
|
||||
text = '💡 点击文件夹进入目录,点击文件选择文件,使用📍选择当前目录';
|
||||
title = '选择文件或文件夹';
|
||||
}
|
||||
helpText.textContent = text;
|
||||
if (modalTitle) {
|
||||
modalTitle.textContent = title;
|
||||
}
|
||||
}
|
||||
|
||||
// 添加模态框键盘事件监听
|
||||
document.addEventListener('keydown', function(event) {
|
||||
if (event.key === 'Escape') {
|
||||
closeFileBrowser();
|
||||
}
|
||||
});
|
||||
|
||||
// 添加模态框点击外部关闭功能
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const modal = document.getElementById('file-browser-modal');
|
||||
if (modal) {
|
||||
modal.addEventListener('click', function(event) {
|
||||
if (event.target === modal) {
|
||||
closeFileBrowser();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 将文件浏览器函数暴露到全局作用域
|
||||
window.selectFolder = selectFolder;
|
||||
window.openRemoteFileBrowser = openRemoteFileBrowser;
|
||||
window.closeFileBrowser = closeFileBrowser;
|
||||
window.confirmFileSelection = confirmFileSelection;
|
||||
window.navigateToParent = navigateToParent;
|
||||
window.selectCurrentDirectory = selectCurrentDirectory;
|
||||
|
||||
window.addEventListener('load', () => {
|
||||
initTrainForm();
|
||||
startProcessPolling();
|
||||
|
||||
@ -323,23 +323,29 @@
|
||||
<div id="file-browser-modal" class="modal hidden">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3>选择文件夹</h3>
|
||||
<h3 id="modal-title">选择文件或文件夹</h3>
|
||||
<button class="modal-close" onclick="closeFileBrowser()">×</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="file-browser-nav">
|
||||
<div class="current-path" id="current-path">./</div>
|
||||
<button class="btn-navigate" onclick="navigateToParent()">⬆️ 上级目录</button>
|
||||
<div class="nav-buttons">
|
||||
<button class="btn-navigate" onclick="selectCurrentDirectory()" title="选择当前目录">📍</button>
|
||||
<button class="btn-navigate" onclick="navigateToParent()" title="上级目录">⬆️</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="quick-paths" id="quick-paths">
|
||||
<!-- 快捷路径将在这里显示 -->
|
||||
</div>
|
||||
<div class="file-browser-help">
|
||||
💡 点击文件夹进入目录,点击文件选择文件,使用📍选择当前目录
|
||||
</div>
|
||||
<div class="file-list" id="file-list">
|
||||
<!-- 文件列表将在这里显示 -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<input type="text" id="selected-path" placeholder="选择的文件夹路径" readonly>
|
||||
<input type="text" id="selected-path" placeholder="选择的文件或文件夹路径" readonly>
|
||||
<button class="btn-primary" onclick="confirmFileSelection()">确认选择</button>
|
||||
<button class="btn-secondary" onclick="closeFileBrowser()">取消</button>
|
||||
</div>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user