6. 创建一个Panel组件-DeepSeek辅助编程

在deepseek中输入:
创建一个vue组件
组件实现可以被拖动的Panel的功能
Panel支持全屏以及阴影禁用背后的组件

deepseek返回的代码:

DragablePanel.vue
<template>
  <div 
    class="draggable-panel"
    :style="panelStyle"
    @mousedown="handleMouseDown"
  >
    <!-- 拖拽手柄 -->
    <div 
      class="drag-handle"
      @mousedown.stop="startDrag"
    >
      {{ title }}
      <button class="close-btn" @click="$emit('close')">×</button>
    </div>

    <!-- 内容区域 -->
    <div class="panel-content">
      <slot></slot>
    </div>

    <!-- 尺寸调整手柄 -->
    <div 
      v-if="resizable"
      class="resize-handle"
      @mousedown.stop="startResize"
    ></div>
  </div>
</template>

<script setup>
import { ref, computed, onMounted, onUnmounted } from 'vue'

const props = defineProps({
  title: {
    type: String,
    default: 'Panel'
  },
  initialX: {
    type: Number,
    default: 100
  },
  initialY: {
    type: Number,
    default: 100
  },
  width: {
    type: Number,
    default: 300
  },
  height: {
    type: Number,
    default: 200
  },
  minWidth: {
    type: Number,
    default: 200
  },
  minHeight: {
    type: Number,
    default: 150
  },
  resizable: {
    type: Boolean,
    default: true
  },
  boundary: {
    type: Boolean,
    default: true
  }
})

const emit = defineEmits(['update:position', 'close'])

const panelX = ref(props.initialX)
const panelY = ref(props.initialY)
const panelWidth = ref(props.width)
const panelHeight = ref(props.height)
const isDragging = ref(false)
const isResizing = ref(false)
const startX = ref(0)
const startY = ref(0)
const initialOffsetX = ref(0)
const initialOffsetY = ref(0)

const panelStyle = computed(() => ({
  left: `${panelX.value}px`,
  top: `${panelY.value}px`,
  width: `${panelWidth.value}px`,
  height: `${panelHeight.value}px`,
  zIndex: 1000
}))

const startDrag = (e) => {
  isDragging.value = true
  startX.value = e.clientX
  startY.value = e.clientY
  initialOffsetX.value = e.clientX - panelX.value
  initialOffsetY.value = e.clientY - panelY.value
}

const startResize = (e) => {
  isResizing.value = true
  startX.value = e.clientX
  startY.value = e.clientY
  document.body.style.cursor = 'nwse-resize'
}

const handleMouseMove = (e) => {
  if (isDragging.value) {
    let newX = e.clientX - initialOffsetX.value
    let newY = e.clientY - initialOffsetY.value
    
    if (props.boundary) {
      const maxX = window.innerWidth - panelWidth.value
      const maxY = window.innerHeight - 50 // 保留底部空间
      newX = Math.max(0, Math.min(newX, maxX))
      newY = Math.max(0, Math.min(newY, maxY))
    }

    panelX.value = newX
    panelY.value = newY
    emit('update:position', { x: newX, y: newY })
  }
  
  if (isResizing.value) {
    const deltaX = e.clientX - startX.value
    const deltaY = e.clientY - startY.value
    const newWidth = Math.max(props.minWidth, panelWidth.value + deltaX)
    const newHeight = Math.max(props.minHeight, panelHeight.value + deltaY)
    
    panelWidth.value = newWidth
    panelHeight.value = newHeight
    
    startX.value = e.clientX
    startY.value = e.clientY
  }
}

const handleMouseUp = () => {
  isDragging.value = false
  isResizing.value = false
  document.body.style.cursor = 'default'
}

onMounted(() => {
  document.addEventListener('mousemove', handleMouseMove)
  document.addEventListener('mouseup', handleMouseUp)
})

onUnmounted(() => {
  document.removeEventListener('mousemove', handleMouseMove)
  document.removeEventListener('mouseup', handleMouseUp)
})
</script>

<style scoped>
.draggable-panel {
  position: fixed;
  background: white;
  border: 1px solid #ddd;
  box-shadow: 0 4px 8px rgba(0,0,0,0.1);
  border-radius: 4px;
  overflow: hidden;
  user-select: none;
}

.drag-handle {
  padding: 12px;
  background: #f5f7fa;
  border-bottom: 1px solid #ddd;
  cursor: move;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.panel-content {
  padding: 16px;
  height: calc(100% - 48px);
  overflow: auto;
}

.resize-handle {
  position: absolute;
  bottom: 0;
  right: 0;
  width: 12px;
  height: 12px;
  background: #ddd;
  cursor: nwse-resize;
}

.close-btn {
  border: none;
  background: transparent;
  cursor: pointer;
  font-size: 18px;
  padding: 0 4px;
}

.close-btn:hover {
  color: #666;
}
</style>

 

引用代码:
<template>
  <div>
    <button @click="showPanel = true">打开面板</button>

    <DraggablePanel
      v-if="showPanel"
      title="系统设置"
      :overlay="true"
      :fullscreen.sync="isFullscreen"
      @close="showPanel = false"
    >
      <div class="settings-content">
        <h3>系统配置</h3>
        <form>
          <label>主题设置:</label>
          <select>
            <option>浅色</option>
            <option>深色</option>
          </select>
          
          <label>通知设置:</label>
          <div class="checkbox-group">
            <label><input type="checkbox"> 邮件通知</label>
            <label><input type="checkbox"> 短信通知</label>
          </div>
        </form>
      </div>
    </DraggablePanel>
  </div>
</template>

<script setup>
import { ref } from 'vue'
import DraggablePanel from './components/DraggablePanel.vue'

const showPanel = ref(false)
const isFullscreen = ref(false)
</script>

<style>
.settings-content {
  padding: 20px;
}

form {
  display: flex;
  flex-direction: column;
  gap: 15px;
}

.checkbox-group {
  display: flex;
  gap: 20px;
}
</style>

 

然后运行,我们就可以看到deepseek给我们写的这个组件了
0
 
 
使用deepseek封装组件的部分就到这里了
deepseek封装的组件还有很多可以调整的地方,比如拖拽时没有紧跟鼠标,layout组件也先整屏显示页底超出底边的问题,这些可以通过多次与deepseek沟通根据问题的描述尝试解决
代码:代码地址
 
 
posted @ 2025-03-17 14:53  Terry841119  阅读(31)  评论(0)    收藏  举报