import gradio as gr import re import json # 初始文件结构 initial_files = { "children": [ {"name": "index.html", "type": "file", "content": "\n\n\n\n 示例\n\n\n

Hello World

\n\n"}, {"name": "styles", "type": "folder", "children": [ {"name": "main.css", "type": "file", "content": "/* CSS文件 */\nbody {\n background-color: #f0f0f0;\n}"} ]} ] } # HTML语法高亮函数 def highlight_html(html_str): # 处理注释 html_str = re.sub(r'(<!--.*?-->)', r'\1', html_str) # 处理元素名 html_str = re.sub(r'(</?\w+)', r'\1', html_str) # 处理属性名 html_str = re.sub(r'(\s\w+)=', r'\1=', html_str) # 处理属性值 html_str = re.sub(r'=("[^"]*"|\'[^\']*\')', r'=\1', html_str) # 处理结束符 html_str = re.sub(r'(>)', r'\1', html_str) return f'
{html_str}
' # 文件选择处理函数 def handle_file_select(evt: gr.SelectData): if evt.value["type"] == "file": content = evt.value["content"] if evt.value["name"].endswith(".html"): escaped = content.replace("<", "<").replace(">", ">") return highlight_html(escaped), content return gr.update(visible=False), content return gr.update(visible=False), "" # 创建新文件 def create_file(file_name, current_tree): if not file_name.strip(): return current_tree, "文件名不能为空!" new_file = { "name": file_name, "type": "file", "content": f"// {file_name} 的内容" } updated_tree = json.loads(current_tree) updated_tree["children"].append(new_file) return json.dumps(updated_tree), f"已创建文件: {file_name}" # 创建新文件夹 def create_folder(folder_name, current_tree): if not folder_name.strip(): return current_tree, "文件夹名不能为空!" new_folder = { "name": folder_name, "type": "folder", "children": [] } updated_tree = json.loads(current_tree) updated_tree["children"].append(new_folder) return json.dumps(updated_tree), f"已创建文件夹: {folder_name}" # 保存文件内容 def save_file_content(file_tree, file_content, selected_file): if not selected_file: return "未选择文件!", file_tree tree_data = json.loads(file_tree) def update_content(node): if node.get("name") == selected_file: node["content"] = file_content return True if "children" in node: for child in node["children"]: if update_content(child): return True return False if update_content(tree_data): return "文件已保存!", json.dumps(tree_data) return "保存失败!", file_tree # 创建文件树组件 def create_file_tree(): return gr.Tree( value=initial_files, label="文件浏览器", show_label=True, elem_classes=["file-tree"], ) # Gradio界面 with gr.Blocks(theme=gr.themes.Soft(), css=".file-tree {height: 500px;}") as demo: gr.Markdown("# 🧩 网页开发IDE") file_tree = gr.State(json.dumps(initial_files)) selected_file = gr.State("") with gr.Row(): # 左侧文件操作面板 with gr.Column(scale=1, min_width=250): create_file_btn = gr.Button("📄 新建文件", variant="primary") new_file_name = gr.Textbox(placeholder="输入文件名 (如: script.js)") create_folder_btn = gr.Button("📁 新建文件夹") new_folder_name = gr.Textbox(placeholder="输入文件夹名") status = gr.Textbox(label="操作状态", interactive=False) tree = create_file_tree() # 右侧代码编辑区 with gr.Column(scale=3): file_name_display = gr.Textbox(label="当前文件", interactive=False) html_preview = gr.HTML(visible=False) code_editor = gr.Code( language="html", label="代码编辑器", lines=20, interactive=True ) save_btn = gr.Button("💾 保存文件", variant="primary") save_status = gr.Textbox(interactive=False) # 事件处理 tree.select(handle_file_select, outputs=[html_preview, code_editor]) tree.select(lambda evt: evt.value["name"] if evt.value["type"]=="file" else "", outputs=[file_name_display]) tree.select(lambda evt: evt.value["name"] if evt.value["type"]=="file" else "", outputs=[selected_file]) create_file_btn.click( create_file, [new_file_name, file_tree], [file_tree, status] ).then(lambda: gr.Tree(value=json.loads(file_tree.value)), tree) create_folder_btn.click( create_folder, [new_folder_name, file_tree], [file_tree, status] ).then(lambda: gr.Tree(value=json.loads(file_tree.value)), tree) save_btn.click( save_file_content, [file_tree, code_editor, selected_file], [save_status, file_tree] ) if __name__ == "__main__": demo.launch()