feat(ui): 添加 IDE 组件(文件浏览器 + 代码编辑器)
- 新增 CodeEditor 组件,基于 CodeMirror 实现多标签代码编辑 - 新增 FileExplorer 组件,支持文件树展开/折叠和文件选择 - 新增 IDE 组件,整合文件浏览器和代码编辑器 - 新增 SessionPanel 组件,用于会话管理 - 添加文件写入 API(PUT /api/files/write) - 优化布局:IDE 始终显示,移除文件切换按钮 - 工作目录路径显示在文件浏览器标题栏,支持悬浮显示完整路径
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
import { Hono } from 'hono';
|
||||
import { readdir, stat, readFile } from 'node:fs/promises';
|
||||
import { readdir, stat, readFile, writeFile, mkdir } from 'node:fs/promises';
|
||||
import { join, resolve, basename, extname, dirname } from 'node:path';
|
||||
import { searchFiles as coreSearchFiles, type FileIndexEntry } from '@ai-assistant/core';
|
||||
|
||||
@@ -398,4 +398,50 @@ filesRouter.get('/search', async (c) => {
|
||||
}
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// PUT /api/files/write - 写入文件内容
|
||||
// ============================================================================
|
||||
filesRouter.put('/write', async (c) => {
|
||||
try {
|
||||
const body = await c.req.json();
|
||||
const { path: requestedPath, content } = body;
|
||||
|
||||
if (!requestedPath) {
|
||||
return c.json({ success: false, error: 'Path is required' }, 400);
|
||||
}
|
||||
|
||||
if (typeof content !== 'string') {
|
||||
return c.json({ success: false, error: 'Content must be a string' }, 400);
|
||||
}
|
||||
|
||||
const absolutePath = safePath(requestedPath);
|
||||
if (!absolutePath) {
|
||||
return c.json({ success: false, error: 'Access denied: path outside working directory' }, 403);
|
||||
}
|
||||
|
||||
// 确保父目录存在
|
||||
const parentDir = dirname(absolutePath);
|
||||
await mkdir(parentDir, { recursive: true });
|
||||
|
||||
// 写入文件
|
||||
await writeFile(absolutePath, content, 'utf-8');
|
||||
|
||||
const stats = await stat(absolutePath);
|
||||
const name = basename(absolutePath);
|
||||
|
||||
return c.json({
|
||||
success: true,
|
||||
data: {
|
||||
path: requestedPath,
|
||||
name,
|
||||
size: stats.size,
|
||||
modified: stats.mtime.toISOString(),
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : 'Unknown error';
|
||||
return c.json({ success: false, error: message }, 500);
|
||||
}
|
||||
});
|
||||
|
||||
export { filesRouter };
|
||||
|
||||
Reference in New Issue
Block a user