vue+python实现类似cursor的ai编程助手前端交互html代码
代码语言:html
所属分类:其他
代码描述:vue+python实现类似cursor的ai编程助手前端交互html代码
代码标签: vue python 类似 cursor ai 编程 助手 前端 交互 html 代码
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Code Editor</title> <link rel='stylesheet' href='//repo.bfw.wiki/bfwrepo/js/codemirror/lib/codemirror.css'> <link rel='stylesheet' href='//repo.bfw.wiki/bfwrepo/js/codemirror/theme/material.css'> <style> .maineditor { display: flex; flex-direction: row; height: 100vh; width: 100vw; overflow: hidden; } .selected-label { color: green; margin-left: 10px; } /* 自定义滚动条样式 */ ::-webkit-scrollbar { width: 10px; height: 10px; } ::-webkit-scrollbar-track { background: #1e1e1e; border-radius: 5px; } ::-webkit-scrollbar-thumb { background: #444; border-radius: 5px; } ::-webkit-scrollbar-thumb:hover { background: #555; } /* Firefox 滚动条样式 */ * { scrollbar-color: #444 #1e1e1e; scrollbar-width: thin; } body { margin: 0; padding: 0; display: flex; height: 100vh; font-family: Arial, sans-serif; background-color: #1e1e1e; color: white; overflow: hidden; } #sidebar { width: 250px; background-color: #252526; padding: 10px; overflow-y: auto; border-right: 1px solid #444; } #editor { flex: 1; background-color: #1e1e1e; display: flex; flex-direction: column; overflow: hidden; } .file-item, .folder-item, .project-item { cursor: pointer; padding: 5px; margin: 5px 0; border-radius: 3px; display: flex; align-items: center; } .file-item:hover, .folder-item:hover, .project-item:hover { background-color: #2a2d2e; } .context-btn { margin-left: 10px; cursor: pointer; color: #ccc; font-size: 12px; } .folder-item::before, .file-item::before { content: ''; display: inline-block; width: 16px; height: 16px; margin-right: 5px; background-size: cover; } .folder-item::before { background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0id2hpdGUiPjxwYXRoIGQ9Ik0xMCA0SDRjLTEuMSAwLTEuOTkuOS0xLjk5IDJMMiAxOGMwIDEuMS45IDIgMiAyaDE2YzEuMSAwIDItLjkgMi0yVjhjMC0xLjEtLjktMi0yLTJoLThsLTItMnoiLz48L3N2Zz4='); } .file-item::before { background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0id2hpdGUiPjxwYXRoIGQ9Ik0xNCAySDZjLTEuMSAwLTEuOTkuOS0xLjk5IDJMMyAyMGMwIDEuMS45IDIgMiAyaDEyYzEuMSAwIDItLjkgMi0yVjhsLTYtNnptNCAxOEg2VjRoN3Y1aDV2MTF6Ii8+PC9zdmc+'); } .folder-item.collapsed::before { background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0id2hpdGUiPjxwYXRoIGQ9Ik0xMCA4SDRjLTEuMSAwLTEuOTkuOS0xLjk5IDJMMiAxOGMwIDEuMS45IDIgMiAyaDE2YzEuMSAwIDItLjkgMi0yVjhjMC0xLjEtLjktMi0yLTJoLThsLTItMnoiLz48L3N2Zz4='); } .folder-item.expanded::before { background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0id2hpdGUiPjxwYXRoIGQ9Ik0xOSAxMEg1Yy0xLjEgMC0yIC45LTIgMnY4YzAgMS4xLjkgMiAyIDJoMTRjMS4xIDAgMi0uOSAyLTJ2LThjMC0xLjEtLjktMi0yLTJ6bS04IDZIOXYtMmgydjJ6bTAtNEg5di0yaDJ2MnptNC40IDRoLTMuOGMtLjMgMC0uNi0uMi0uOC0uNGwtMS4yLTEuNmgxLjJsLjYuOWg4LjJsLjYtLjkxIDEuMiAxLjYxYy0uMi4yLS41LjQtLjguNHoiLz48L3N2Zz4='); } #tabs { display: flex; background-color: #252526; padding: 5px; border-bottom: 1px solid #444; } .tab { display: flex; align-items: center; padding: 8px 12px; margin-right: 5px; cursor: pointer; background-color: #2a2d2e; border-radius: 3px; position: relative; } .tab.active { background-color: #0e639c; } .close-button { margin-left: 8px; cursor: pointer; font-size: 14px; color: #ccc; } .close-button:hover { color: white; } #save-button { position: absolute; top: 10px; right: 10px; background-color: #0e639c; color: white; border: none; padding: 8px 12px; border-radius: 3px; cursor: pointer; } #save-button:hover { background-color: #1177bb; } .CodeMirror { height: 100%; /* 确保编辑器占据整个容器高度 */ } .sub-container { margin-left: 20px; display: none; } .folder-item.expanded+.sub-container { display: block; } #code-editor-container { flex: 1; /* 默认隐藏 */ height: 100vh; overflow: hidden; } #code-editor-container.active { display: block; /* 显示编辑器容器 */ } .code-editor-wrapper { height: 100%; /* 确保编辑器占据整个容器高度 */ } /* 聊天窗口样式 */ #chat-window { position: fixed; bottom: 20px; right: 20px; width: 300px; height: 600px; background-color: #252526; border: 1px solid #444; border-radius: 5px; display: flex; flex-direction: column; overflow: hidden; z-index: 1000; } #chat-icon { position: fixed; bottom: 20px; right: 20px; cursor: pointer; } #minimize-btn { float: right; background: none; border: none; font-size: 20px; cursor: pointer; } /* 开关样式 */ .switch { position: relative; display: inline-block; width: 40px; height: 18px; margin-left: 10px; } .switch input { opacity: 0; width: 0; height: 0; } .slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: #444; transition: 0.4s; border-radius: 18px; } .slider:before { position: absolute; content: ''; height: 14px; width: 14px; left: 2px; bottom: 2px; background-color: white; transition: 0.4s; border-radius: 50%; } input:checked+.slider { background-color: #0e639c; } input:checked+.slider:before { transform: translateX(20px); } /* 开关标签样式 */ .switch-label { display: flex; align-items: center; color: white; font-size: 12px; } /* 聊天窗口头部布局 */ #chat-header { display: flex; justify-content: space-between; align-items: center; padding: 10px; background-color: #1e1e1e; cursor: move; border-bottom: 1px solid #444; } #chat-body { flex: 1; padding: 10px; overflow-y: auto; background-color: #252526; font-size: 12px; line-height: 20px; } #chat-body ol, #chat-body ul { margin: 0; padding: 10px; } #chat-input { padding: 10px; background-color: #1e1e1e; border-top: 1px solid #444; } #chat-input textarea { width: 100%; height: 50px; background-color: #252526; color: white; border: 1px solid #444; border-radius: 3px; padding: 5px; } .message { margin-bottom: 10px; word-wrap: break-word; } .message.user { color: #4CAF50; } .message.ai { color: #2196F3; } /* 代码块样式 */ .message.ai pre { position: relative; background-color: #1e1e1e; padding: 10px; border-radius: 5px; overflow-x: auto; } .message.ai code { font-family: monospace; background-color: #1e1e1e; padding: 2px 4px; border-radius: 3px; } /* 复制按钮样式 */ .copy-button { position: absolute; top: 5px; right: 5px; background-color: #444; color: white; border: none; padding: 5px 10px; border-radius: 3px; cursor: pointer; font-size: 12px; } .copy-button:hover { background-color: #555; } /* 右键菜单样式 */ #context-menu { position: absolute; background-color: #252526; border: 1px solid #444; border-radius: 3px; padding: 5px 0; z-index: 1000; } #context-menu .menu-item { padding: 8px 12px; color: white; cursor: pointer; } #context-menu .menu-item:hover { background-color: #2a2d2e; } #chat-context { margin-bottom: 10px; } #context-selector { display: flex; gap: 10px; margin-bottom: 10px; } #context-list { display: flex; flex-wrap: wrap; gap: 5px; } .context-item { display: flex; align-items: center; background-color: #2a2d2e; padding: 5px 10px; border-radius: 3px; font-size: 14px; } .context-item .remove-button { margin-left: 10px; cursor: pointer; color: #ff6b6b; } .context-item .remove-button:hover { color: #ff3b3b; } /* 模态框样式 */ .modal { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.5); justify-content: center; align-items: center; z-index: 1000; } .modal-content { background-color: #252526; padding: 20px; margin-left: calc((100vw - 400px) / 2); margin-top: calc((100vh - 300px) / 2); border-radius: 5px; width: 400px; max-height: 300px; overflow-y: auto; } .modal-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; } .modal-header h3 { margin: 0; } .modal-header button { background: none; border: none; color: white; font-size: 20px; cursor: pointer; } .modal-body { margin-bottom: 10px; } #editbtn { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; } #editbtn button { background-color: #0e639c; margin: 0 4px; color: white; width: 100%; border: none; padding: 8px 12px; border-radius: 3px; cursor: pointer; } #chat-icon { z-index: 111111; } #cancel-button { text-align: center; padding: 10px; } .cancel-btn { background-color: #ff4444; color: white; border: none; padding: 8px 16px; border-radius: 4px; cursor: pointer; font-size: 12px; transition: background-color 0.3s; } .cancel-btn:hover { background-color: #cc0000; } .empty-project { color: thistle; text-align: center; margin: 100px auto; } .now-project { color: #2196F3; text-align: center; margin: 10px auto; } /* 添加提示框样式 */ #toast-container { position: fixed; top: 20px; right: 20px; z-index: 10000; } .toast { min-width: 250px; margin-bottom: 10px; padding: 15px; border-radius: 4px; color: white; font-size: 14px; display: flex; justify-content: space-between; align-items: center; box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); animation: slideIn 0.3s ease-in-out; transition: opacity 0.3s ease-in-out; } .toast.success { background-color: #4caf50; } .toast.error { background-color: #f44336; } .toast.info { background-color: #2196F3; } .toast.warning { background-color: #ff9800; } @keyframes slideIn { from { transform: translateX(100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } } @keyframes slideOut { from { transform: translateX(0); opacity: 1; } to { transform: translateX(100%); opacity: 0; } } </style> </head> <body> <div id="app"> <div class="maineditor"> <!-- 侧边栏 --> <div id="sidebar"> <div class="edit-buttons" id="editbtn"> <button @click="openProject" v-show="!hasProject">open</button> <button @click="createProject" v-show="!hasProject">create</button> <button @click="closeProject" v-show="hasProject">close</button> <button @click="refreshFileTree" v-show="hasProject">refresh</button> </div> <div v-if="nowproject!=''" class="now-project">now project:{{nowproject}}</div> <div v-if="nowproject==''" class="empty-project">open or create</div> <div id="file-tree" ref="fileTree"></div> </div> <!-- 编辑器区域 --> <div id="editor"> <div id="tabs"> <div v-for="(tab, path) in tabs" :key="path" class="tab" :class="{ active: currentTab === path }" @click="switchTab(path)"> <span><i v-if="tab.modified">*</i>{{ tab.name }}</span> <span class="close-button" @click.stop="closeTab(path)">×</span> </div> </div> <div id="code-editor-container" ref="editorContainer"></div> <!-- <button @click="saveFile" v-show="currentTab">Save</button> --> </div> </div> <!-- 聊天窗口 --> <div id="chat-window" v-show="!chatMinimized" :style="chatWindowStyle"> <div id="chat-header" @mousedown="startDragging"> <span>AI Chat</span> <div class="switch-label"> <span>Read-Only</span> <label class="switch"> <input type="checkbox" v-model="readOnly"> <span class="slider"></span> </label> <span>Write</span> </div> <button @click="minimizeChat">−</button> </div> <div id="chat-body" ref="chatBody"> <div v-for="(message, index) in messages" :key="index" :class="['message', message.sender]" v-html="renderMessage(message)"> </div> </div> <div id="chat-context"> <div id="context-selector" class="context-btn"> <span @click="showFileSelector">Add Context</span> <span @click="clearContext">Clear All</span> </div> <div id="context-list"> <div v-for="(item, index) in selectedContext" :key="index" class="context-item"> <span :title="item.path">{{ item.path }}</span> <span class="remove-button" @click="removeContext(index)">×</span> </div> </div> </div> <!-- 添加取消按钮 --> <div id="cancel-button" v-if="isGenerating"> <button @click="cancelGeneration" class="cancel-btn">Stop Generating</button> </div> <div id="chat-input"> <textarea v-model="chatInput" @keydown.enter.prevent="sendMessage" placeholder="Type your message..." :disabled="isGenerating"> </textarea> </div> </div> <!-- 右键菜单 --> <div id="context-menu" v-show="contextMenu.show" :style="{ position: 'fixed', left: contextMenu.x + 'px', top: contextMenu.y + 'px', zIndex: 1000 }"> <div v-for="item in contextMenu.items" :key="item" class="menu-item" @click="handleContextMenuClick(item)"> {{ item.replace(/-/g, ' ') }} </div> </div> <!-- 聊天图标 --> <div id="chat-icon" v-show="chatMinimized" @click="showChat"> <img src="//repo.bfw.wiki/bfwrepo/icon/6413f21abdbea.png" alt="Chat Icon" width="50" height="50"> </div> <!-- 文件选择模态框 --> <div id="file-selector-modal" v-show="showFileSelectorModal" class="modal"> <div class="modal-content"> <div class="modal-header"> <h3>Select Files</h3> <button @click="closeFileSelector">×</button> </div> <div class="modal-body"> <div id="file-list"> <div v-for="file in availableFiles" :key="file.path" class="file-item" :class="{ selected: isFileSelected(file) }" @click="toggleFileSelection(file)"> <input type="checkbox" :checked="isFileSelected(file)" @click.stop> <span>{{ file.path }}</span> </div> </div> </div> <!-- <div class="modal-footer"> <button @click="confirmFileSelection">Confirm</button> <button @click="closeFileSelector">Cancel</button> </div> --> </div> </div> <!-- 项目选择模态框 --> <div id="project-selector-modal" v-show="showProjectModal" class="modal"> <div class="modal-content"> <div class="modal-header"> <h3>Select Project</h3> <button @click="closeProjectModal">×</button> </div> <div class="modal-body"> <div id="project-list"> <div v-for="project in projects" :key="project.path" class="project-item" @click="selectProject(project)"> {{ project.path }} </div> </div> </div> </div> </div> </div> <!-- 在 body 末尾添加提示容器 --> <div id="toast-container"></div> <!-- CodeMirror and other scripts --> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/vue@2.6.1-dev.js"></script> <script src='//repo.bfw.wiki/bfwrepo/js/codemirror/codemirror.5.26.js'></script> <script src='//repo.bfw.wiki/bfwrepo/js/codemirror/mode/xml/xml.js'></script> <script src='//repo.bfw.wiki/bfwrepo/js/codemirror/mode/javascript/javascript.js'></script> <script src='//repo.bfw.wiki/bfwrepo/js/codemirror/addon/edit/matchbrackets.js'></script> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/marked.umd.min.js"></script> <script> new Vue({ el: '#app', data: { // 项目相关 nowproject: '', hasProject: false, projects: [], .........完整代码请登录后点击上方下载按钮下载查看
网友评论0