@@ -5,7 +5,7 @@ import MarkdownPreview from './components/MarkdownPreview.vue';
55import FileTree from ' ./components/FileTree.vue' ;
66import ConfigPanel from ' ./components/ConfigPanel.vue' ;
77import Toolbar from ' ./components/Toolbar.vue' ;
8- import { generatePrompt , copyToClipboard , filesToTree , fileToNode , type FileNode } from ' ./utils/promptGenerator' ;
8+ import { generatePrompt , copyToClipboard , filesToTree , fileToNode , nodeToFile , type FileNode } from ' ./utils/promptGenerator' ;
99import { generateCursorRules } from ' ./utils/cursorRulesGenerator' ;
1010
1111// 状态
@@ -17,6 +17,7 @@ const projectFiles = ref<FileNode[]>([]);
1717const selectedFile = ref <FileNode | null >(null );
1818const showConfigModal = ref (false );
1919const showSidebar = ref (true ); // 控制侧边栏显示状态
20+ const uploadedFiles = ref <File []>([]);
2021
2122// 计算属性
2223const canConvert = computed (() => sourceCode .value .trim ().length > 0 );
@@ -83,6 +84,9 @@ const handleConvert = async () => {
8384const handleFileUpload = (files : File []) => {
8485 if (files .length === 0 ) return ;
8586
87+ // 保存上传的文件,以便后续访问
88+ uploadedFiles .value = files ;
89+
8690 if (files .length === 1 && ! files [0 ].webkitRelativePath ) {
8791 // 单个文件上传
8892 const file = files [0 ];
@@ -133,17 +137,77 @@ const handleFileSelect = (file: FileNode) => {
133137 setLanguageFromExtension (extension );
134138 } else {
135139 // 否则尝试从上传的文件中加载内容
136- const uploadedFiles = document .querySelector (' input[type="file"]' ) as HTMLInputElement ;
137- if (uploadedFiles && uploadedFiles .files ) {
138- const files = Array .from (uploadedFiles .files );
139- loadFileContent (file , files );
140- }
140+ loadFileContent (file , projectFiles .value );
141141 }
142142 }
143143};
144144
145- const loadFileContent = (file : FileNode , files : File []) => {
146- const uploadedFile = files .find (f => f .webkitRelativePath === file .path || f .name === file .name );
145+ const loadFileContent = (file : FileNode , files : FileNode [] | File []) => {
146+ // 辅助函数: 将文件树展平
147+ const flattenFiles = (nodes : FileNode []): FileNode [] => {
148+ let result: FileNode [] = [];
149+ for (const node of nodes ) {
150+ if (! node .isDirectory ) {
151+ result .push (node );
152+ }
153+ if (node .children ) {
154+ result = result .concat (flattenFiles (node .children ));
155+ }
156+ }
157+ return result ;
158+ };
159+
160+ // 如果传入的是FileNode数组,从中查找所有实际文件
161+ if (files .length > 0 && ' isDirectory' in files [0 ]) {
162+
163+ const allFileNodes = flattenFiles (files as FileNode []);
164+ const targetNode = allFileNodes .find (node => node .path === file .path );
165+
166+ if (targetNode ) {
167+ if (targetNode .content ) {
168+ file .content = targetNode .content ;
169+ sourceCode .value = targetNode .content ;
170+ } else {
171+ // 使用缓存的上传文件列表而不是DOM查询
172+ let foundFile = null ;
173+ if (uploadedFiles .value .length > 0 ) {
174+ console .log (" 从缓存的上传文件中查找:" , uploadedFiles .value .length , " 个文件" );
175+ foundFile = uploadedFiles .value .find (f => {
176+ console .log (" 比较:" , f .webkitRelativePath , targetNode .path , f .name , targetNode .name );
177+ return f .webkitRelativePath === targetNode .path || f .name === targetNode .name ;
178+ });
179+ }
180+
181+ if (foundFile ) {
182+ console .log (" 找到匹配文件:" , foundFile .name );
183+ const reader = new FileReader ();
184+ reader .onload = (e ) => {
185+ if (e .target ?.result ) {
186+ const content = e .target .result as string ;
187+ file .content = content ;
188+ targetNode .content = content ;
189+ sourceCode .value = content ;
190+ } else {
191+ console .error (' 文件内容读取失败' , e );
192+ }
193+ };
194+ reader .onerror = (e ) => {
195+ console .error (' 文件读取错误' , e );
196+ };
197+ reader .readAsText (foundFile );
198+ } else {
199+ console .warn (` 找不到匹配的文件: ${targetNode .path || targetNode .name } ` );
200+ }
201+ }
202+ // 根据文件扩展名设置语言
203+ const extension = file .name .split (' .' ).pop ()?.toLowerCase () || ' ' ;
204+ setLanguageFromExtension (extension );
205+ return ;
206+ }
207+ }
208+
209+ // 如果是File数组,按原方式处理
210+ const uploadedFile = (files as File []).find (f => f .webkitRelativePath === file .path || f .name === file .name );
147211 if (uploadedFile ) {
148212 const reader = new FileReader ();
149213 reader .onload = (e ) => {
@@ -224,6 +288,40 @@ const handleConfigChange = (newConfig: any) => {
224288const closeConfigModal = () => {
225289 showConfigModal .value = false ;
226290};
291+
292+ const handleFileRemove = (file : FileNode ) => {
293+ // 从文件树中移除文件
294+ const removeFile = (files : FileNode []): FileNode [] => {
295+ return files .filter (f => {
296+ if (f .path === file .path ) {
297+ return false ;
298+ }
299+ if (f .children ) {
300+ f .children = removeFile (f .children );
301+ }
302+ return true ;
303+ });
304+ };
305+
306+ projectFiles .value = removeFile (projectFiles .value );
307+
308+ // 如果移除的是当前选中的文件,清空编辑器
309+ if (selectedFile .value ?.path === file .path ) {
310+ selectedFile .value = null ;
311+ sourceCode .value = ' ' ;
312+ }
313+ };
314+
315+ const handleFileEdit = (file : FileNode ) => {
316+ if (! file .isDirectory ) {
317+ selectedFile .value = file ;
318+ sourceCode .value = file .content || ' ' ;
319+
320+ // 根据文件扩展名设置语言
321+ const extension = file .name .split (' .' ).pop ()?.toLowerCase () || ' ' ;
322+ setLanguageFromExtension (extension );
323+ }
324+ };
227325 </script >
228326
229327<template >
@@ -239,14 +337,16 @@ const closeConfigModal = () => {
239337 <div v-if =" hasSidebar" class =" sidebar" >
240338 <div class =" sidebar-header" >
241339 <h3 >项目文件</h3 >
242- <button class =" sidebar-toggle" @click =" toggleSidebar " title = " 隐藏侧边栏 " >
243- < span >◀</ span >
340+ <button class =" sidebar-toggle" @click =" showSidebar = false " >
341+ & times ;
244342 </button >
245343 </div >
246344 <FileTree
247345 :files =" projectFiles"
346+ :selected-path =" selectedFilePath"
248347 @file-select =" handleFileSelect"
249- :selected-path =" selectedFilePath"
348+ @file-remove =" handleFileRemove"
349+ @file-edit =" handleFileEdit"
250350 />
251351 </div >
252352
0 commit comments