Sfoglia il codice sorgente

feat: 左右面板支持拖拽调整宽度

何文松 4 settimane fa
parent
commit
36cfa3086c
1 ha cambiato i file con 91 aggiunte e 4 eliminazioni
  1. 91 4
      frontend/vue-demo/src/views/Editor.vue

+ 91 - 4
frontend/vue-demo/src/views/Editor.vue

@@ -34,7 +34,7 @@
     <!-- 主体 -->
     <div class="editor-body">
       <!-- 左侧文件面板 -->
-      <div class="left-panel">
+      <div class="left-panel" :style="{ width: leftPanelWidth + 'px' }">
         <div class="panel-header">
           <span>📁 来源文件</span>
           <span class="file-count">{{ sourceFiles.length }}个</span>
@@ -92,6 +92,12 @@
         </div>
       </div>
 
+      <!-- 左侧拖拽分隔条 -->
+      <div 
+        class="resize-handle left-resize"
+        @mousedown="startResizeLeft"
+      ></div>
+
       <!-- 中间编辑区 -->
       <div class="center-panel">
         <div class="editor-title-bar">
@@ -114,8 +120,14 @@
         </div>
       </div>
 
+      <!-- 右侧拖拽分隔条 -->
+      <div 
+        class="resize-handle right-resize"
+        @mousedown="startResizeRight"
+      ></div>
+
       <!-- 右侧要素面板 -->
-      <div class="right-panel">
+      <div class="right-panel" :style="{ width: rightPanelWidth + 'px' }">
         <!-- 要素管理(展示文档中识别的实体) -->
         <div class="element-section">
           <div class="element-header">
@@ -369,6 +381,55 @@ const editorRef = ref(null)
 const loading = ref(false)
 const regenerating = ref(false)
 
+// 面板宽度(可拖拽调整)
+const leftPanelWidth = ref(260)
+const rightPanelWidth = ref(380)
+const isResizing = ref(false)
+const resizeType = ref('') // 'left' or 'right'
+
+// 开始拖拽左侧分隔条
+function startResizeLeft(e) {
+  isResizing.value = true
+  resizeType.value = 'left'
+  document.addEventListener('mousemove', handleResize)
+  document.addEventListener('mouseup', stopResize)
+  document.body.style.cursor = 'col-resize'
+  document.body.style.userSelect = 'none'
+}
+
+// 开始拖拽右侧分隔条
+function startResizeRight(e) {
+  isResizing.value = true
+  resizeType.value = 'right'
+  document.addEventListener('mousemove', handleResize)
+  document.addEventListener('mouseup', stopResize)
+  document.body.style.cursor = 'col-resize'
+  document.body.style.userSelect = 'none'
+}
+
+// 处理拖拽
+function handleResize(e) {
+  if (!isResizing.value) return
+  
+  if (resizeType.value === 'left') {
+    const newWidth = e.clientX
+    leftPanelWidth.value = Math.max(180, Math.min(400, newWidth))
+  } else if (resizeType.value === 'right') {
+    const newWidth = window.innerWidth - e.clientX
+    rightPanelWidth.value = Math.max(280, Math.min(500, newWidth))
+  }
+}
+
+// 停止拖拽
+function stopResize() {
+  isResizing.value = false
+  resizeType.value = ''
+  document.removeEventListener('mousemove', handleResize)
+  document.removeEventListener('mouseup', stopResize)
+  document.body.style.cursor = ''
+  document.body.style.userSelect = ''
+}
+
 // 动态计算标题输入框宽度
 watch(reportTitle, () => {
   nextTick(() => {
@@ -1661,13 +1722,38 @@ onUnmounted(() => {
   overflow: hidden;
 }
 
+// 拖拽分隔条
+.resize-handle {
+  width: 4px;
+  background: transparent;
+  cursor: col-resize;
+  flex-shrink: 0;
+  position: relative;
+  z-index: 10;
+  transition: background 0.2s;
+  
+  &:hover, &:active {
+    background: var(--primary);
+  }
+  
+  &::before {
+    content: '';
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    left: -3px;
+    right: -3px;
+  }
+}
+
 .left-panel {
-  width: 260px;
   background: #fff;
   border-right: 1px solid var(--border);
   display: flex;
   flex-direction: column;
   flex-shrink: 0;
+  min-width: 180px;
+  max-width: 400px;
 
   .panel-header {
     padding: 14px 16px;
@@ -2060,11 +2146,12 @@ onUnmounted(() => {
 }
 
 .right-panel {
-  width: 380px;
   background: #fff;
   border-left: 1px solid var(--border);
   overflow-y: auto;
   flex-shrink: 0;
+  min-width: 280px;
+  max-width: 500px;
 }
 
 .element-section {