diff --git a/src/assets/icons/canvas-assistant-menu.svg b/src/assets/icons/canvas-assistant-menu.svg
new file mode 100644
index 0000000..ced38ea
--- /dev/null
+++ b/src/assets/icons/canvas-assistant-menu.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/components/Assistant/assistant.vue b/src/components/Assistant/assistant.vue
new file mode 100644
index 0000000..64a8193
--- /dev/null
+++ b/src/components/Assistant/assistant.vue
@@ -0,0 +1,165 @@
+
+
+
+
+
diff --git a/src/components/Assistant/component/List.vue b/src/components/Assistant/component/List.vue
new file mode 100644
index 0000000..1c6efd4
--- /dev/null
+++ b/src/components/Assistant/component/List.vue
@@ -0,0 +1,43 @@
+
+
+
+
+
diff --git a/src/components/Assistant/component/useDraggable.ts b/src/components/Assistant/component/useDraggable.ts
new file mode 100644
index 0000000..804edc9
--- /dev/null
+++ b/src/components/Assistant/component/useDraggable.ts
@@ -0,0 +1,61 @@
+import { ref, onUnmounted, type Ref } from 'vue'
+
+interface UseDraggableOptions {
+ onDragStart?: () => void
+ onDragEnd?: () => void
+}
+
+export function useDraggable(targetRef: Ref, options?: UseDraggableOptions) {
+ const isDragging = ref(false)
+ const startX = ref(0)
+ const startY = ref(0)
+ const startLeft = ref(0)
+ const startTop = ref(0)
+
+ const handleMouseDown = (e: MouseEvent) => {
+ // 只允许左键拖拽
+ if (e.button !== 0) return
+
+ isDragging.value = true
+ startX.value = e.clientX
+ startY.value = e.clientY
+
+ if (targetRef.value) {
+ const rect = targetRef.value.getBoundingClientRect()
+ startLeft.value = rect.left
+ startTop.value = rect.top
+ }
+
+ options?.onDragStart?.()
+
+ document.addEventListener('mousemove', handleMouseMove)
+ document.addEventListener('mouseup', handleMouseUp)
+ }
+
+ const handleMouseMove = (e: MouseEvent) => {
+ if (!isDragging.value || !targetRef.value) return
+
+ const deltaX = e.clientX - startX.value
+ const deltaY = e.clientY - startY.value
+
+ targetRef.value.style.left = `${startLeft.value + deltaX}px`
+ targetRef.value.style.top = `${startTop.value + deltaY}px`
+ }
+
+ const handleMouseUp = () => {
+ isDragging.value = false
+ document.removeEventListener('mousemove', handleMouseMove)
+ document.removeEventListener('mouseup', handleMouseUp)
+ options?.onDragEnd?.()
+ }
+
+ onUnmounted(() => {
+ document.removeEventListener('mousemove', handleMouseMove)
+ document.removeEventListener('mouseup', handleMouseUp)
+ })
+
+ return {
+ isDragging,
+ handleMouseDown
+ }
+}
diff --git a/src/components/Canvas/CanvasTest.vue b/src/components/Canvas/CanvasTest.vue
index 17817df..fa90539 100644
--- a/src/components/Canvas/CanvasTest.vue
+++ b/src/components/Canvas/CanvasTest.vue
@@ -25,12 +25,14 @@
-->
+