This is an automated email from the ASF dual-hosted git repository.

fanjia pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/seatunnel-web.git


The following commit(s) were added to refs/heads/main by this push:
     new 2c8736f06 [Improve] improve UI (#302)
2c8736f06 is described below

commit 2c8736f06c20e8dd630dd66133b24b86c173705c
Author: Jast <[email protected]>
AuthorDate: Fri Jul 18 11:59:18 2025 +0800

    [Improve] improve UI (#302)
---
 .../dag/canvas/index.module.scss                   | 112 ++++-
 .../synchronization-definition/dag/canvas/node.tsx |  44 +-
 .../detail/dag/canvas-animations.scss              | 302 +++++++++++
 .../detail/dag/canvas-background.scss              | 345 +++++++++++++
 .../detail/dag/canvas-variables.scss               | 192 +++++++
 .../detail/dag/design-tokens.ts                    | 226 +++++++++
 .../detail/dag/edge-styles.scss                    | 305 ++++++++++++
 .../detail/dag/index.module.scss                   | 398 ++++++++++++++-
 .../detail/dag/minimap-styles.scss                 | 382 ++++++++++++++
 .../synchronization-instance/detail/dag/node.tsx   | 234 ++++++++-
 .../detail/dag/responsive-mixins.scss              | 308 ++++++++++++
 .../detail/dag/theme-manager.ts                    | 175 +++++++
 .../detail/dag/use-dag-add-shape.ts                |  49 +-
 .../detail/dag/use-dag-edge.ts                     | 287 ++++++++++-
 .../detail/dag/use-dag-graph.ts                    | 143 +++++-
 .../detail/dag/use-dag-layout.ts                   |  40 +-
 .../detail/dag/use-dag-node.ts                     | 550 ++++++++++++++++++++-
 .../detail/task-definition.tsx                     |   4 +
 18 files changed, 4013 insertions(+), 83 deletions(-)

diff --git 
a/seatunnel-ui/src/views/task/synchronization-definition/dag/canvas/index.module.scss
 
b/seatunnel-ui/src/views/task/synchronization-definition/dag/canvas/index.module.scss
index e154ba0bf..75398da0b 100644
--- 
a/seatunnel-ui/src/views/task/synchronization-definition/dag/canvas/index.module.scss
+++ 
b/seatunnel-ui/src/views/task/synchronization-definition/dag/canvas/index.module.scss
@@ -18,42 +18,140 @@
 .container {
   height: 100%;
   width: 100%;
+  position: relative;
+  background: #fafafa;
+  border: 1px solid #e5e7eb;
+  border-radius: 4px;
 }
 
 .dag-container {
   height: 100%;
   width: 100%;
+  background: transparent;
 }
 
 .minimap {
   position: absolute;
   right: 20px;
   bottom: 60px;
-  border: dashed 1px #e4e4e4;
+  border: 1px solid #e2e8f0;
+  border-radius: 6px;
+  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
+  background: rgba(255, 255, 255, 0.95);
+  backdrop-filter: blur(8px);
+  
+  transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
+  
+  &:hover {
+    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
+    transform: translateY(-2px);
+  }
+}
+
+[data-theme="dark"] {
+  .minimap {
+    background: rgba(17, 24, 39, 0.95);
+    border-color: #374151;
+    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
+    
+    &:hover {
+      box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
+    }
+  }
 }
 
 .dag-node {
   display: flex;
   align-items: center;
   height: 100%;
-  background-color: #fff;
-  border: 1px solid #c2c8d5;
-  border-radius: 4px;
-  box-shadow: 0 2px 5px 1px rgba(0, 0, 0, 0.06);
+  position: relative;
+  
+  background: #ffffff;
+  border: 1px solid #e5e7eb;
+  border-radius: 6px;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
+  
+  transition: box-shadow 0.2s ease, transform 0.2s ease;
+  
+  &:hover {
+    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
+    transform: translateY(-1px);
+  }
 
   .dag-node-icon {
     width: 20px;
     height: 20px;
     margin: 0 10px;
+    flex-shrink: 0;
   }
 
   .dag-node-label {
-    width: 90px;
+    flex: 1;
     overflow: hidden;
     text-overflow: ellipsis;
     white-space: nowrap;
     text-align: left;
-    color: #666;
+    color: #374151;
     font-size: 12px;
+    font-weight: 500;
+    line-height: 1.2;
+  }
+}
+
+.dag-node-status {
+  position: absolute;
+  top: -2px;
+  right: -2px;
+  width: 8px;
+  height: 8px;
+  border-radius: 50%;
+  border: 2px solid #fff;
+  z-index: 10;
+  
+
+  animation: status-pulse 2s ease-in-out infinite;
+}
+
+
+@keyframes node-entrance {
+  0% {
+    opacity: 0;
+    transform: scale(0.8) translateY(10px);
+  }
+  100% {
+    opacity: 1;
+    transform: scale(1) translateY(0);
+  }
+}
+
+@keyframes status-pulse {
+  0%, 100% {
+    opacity: 1;
+    transform: scale(1);
+  }
+  50% {
+    opacity: 0.7;
+    transform: scale(1.1);
+  }
+}
+
+
+[data-theme="dark"] {
+  .dag-node {
+    background: linear-gradient(135deg, rgba(31, 41, 55, 0.8) 0%, rgba(17, 24, 
39, 0.9) 100%);
+    border-color: #374151;
+    backdrop-filter: blur(8px);
+    
+    .dag-node-label {
+      color: #d1d5db;
+    }
+    
+    &:hover .dag-node-label {
+      color: #f3f4f6;
+    }
+  }
+  
+  .dag-node-status {
+    border-color: #111827;
   }
 }
diff --git 
a/seatunnel-ui/src/views/task/synchronization-definition/dag/canvas/node.tsx 
b/seatunnel-ui/src/views/task/synchronization-definition/dag/canvas/node.tsx
index 998759ca3..253653d4b 100644
--- a/seatunnel-ui/src/views/task/synchronization-definition/dag/canvas/node.tsx
+++ b/seatunnel-ui/src/views/task/synchronization-definition/dag/canvas/node.tsx
@@ -57,11 +57,45 @@ const Node = defineComponent({
       icon.value = JsonPathImg
     }
 
+
+    const getBorderStyle = () => {
+      if (isError) {
+        return '4px solid #F87171'
+      } else if (unsaved) {
+        return '4px solid #FBBF24'
+      } else if (type === 'source') {
+        return '4px solid #34D399'
+      } else if (type === 'sink') {
+        return '4px solid #60A5FA'
+      } else if (type === 'transform') {
+        return '4px solid #A78BFA'
+      } else {
+        return '4px solid #60A5FA'
+      }
+    }
+
+    const getBackgroundStyle = () => {
+      if (isError) {
+        return 'linear-gradient(135deg, #FEF2F2 0%, #FEE2E2 100%)'
+      } else if (unsaved) {
+        return 'linear-gradient(135deg, #FFFBEB 0%, #FEF3C7 100%)'
+      } else if (type === 'source') {
+        return 'linear-gradient(135deg, #ECFDF5 0%, #D1FAE5 100%)'
+      } else if (type === 'sink') {
+        return 'linear-gradient(135deg, #EFF6FF 0%, #DBEAFE 100%)'
+      } else if (type === 'transform') {
+        return 'linear-gradient(135deg, #F5F3FF 0%, #EDE9FE 100%)'
+      } else {
+        return 'linear-gradient(135deg, #F8FAFC 0%, #F1F5F9 100%)'
+      }
+    }
+
     return () => (
       <div
         class={styles['dag-node']}
         style={{
-          borderLeft: isError ? '4px solid #ff4d4f' : (unsaved ? '4px solid 
#faad14' : '4px solid #1890ff')
+          borderLeft: getBorderStyle(),
+          background: getBackgroundStyle()
         }}
       >
         <img src={icon.value} class={styles['dag-node-icon']} />
@@ -71,6 +105,14 @@ const Node = defineComponent({
             default: () => name
           }}
         </NTooltip>
+        
+        {/* 状态指示器 */}
+        {isError && (
+          <div class={styles['dag-node-status']} style={{ background: 
'#EF4444' }} />
+        )}
+        {unsaved && !isError && (
+          <div class={styles['dag-node-status']} style={{ background: 
'#F59E0B' }} />
+        )}
       </div>
     )
   }
diff --git 
a/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/canvas-animations.scss
 
b/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/canvas-animations.scss
new file mode 100644
index 000000000..8c781ddd1
--- /dev/null
+++ 
b/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/canvas-animations.scss
@@ -0,0 +1,302 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+@keyframes canvas-node-entrance {
+  0% {
+    opacity: 0;
+    transform: scale(0.8) translateY(10px);
+  }
+  100% {
+    opacity: 1;
+    transform: scale(1) translateY(0);
+  }
+}
+
+
+@keyframes canvas-node-exit {
+  0% {
+    opacity: 1;
+    transform: scale(1) translateY(0);
+  }
+  100% {
+    opacity: 0;
+    transform: scale(0.8) translateY(-10px);
+  }
+}
+
+
+@keyframes canvas-node-pulse {
+  0%, 100% {
+    box-shadow: var(--canvas-shadow-node), 0 0 0 0 rgba(59, 130, 246, 0.4);
+  }
+  50% {
+    box-shadow: var(--canvas-shadow-node), 0 0 0 8px rgba(59, 130, 246, 0);
+  }
+}
+
+
+@keyframes canvas-node-pulse-success {
+  0%, 100% {
+    box-shadow: var(--canvas-shadow-node), 0 0 0 0 rgba(16, 185, 129, 0.4);
+  }
+  50% {
+    box-shadow: var(--canvas-shadow-node), 0 0 0 8px rgba(16, 185, 129, 0);
+  }
+}
+
+
+@keyframes canvas-node-pulse-error {
+  0%, 100% {
+    box-shadow: var(--canvas-shadow-node), 0 0 0 0 rgba(239, 68, 68, 0.4);
+  }
+  50% {
+    box-shadow: var(--canvas-shadow-node), 0 0 0 8px rgba(239, 68, 68, 0);
+  }
+}
+
+
+@keyframes canvas-node-pulse-warning {
+  0%, 100% {
+    box-shadow: var(--canvas-shadow-node), 0 0 0 0 rgba(245, 158, 11, 0.4);
+  }
+  50% {
+    box-shadow: var(--canvas-shadow-node), 0 0 0 8px rgba(245, 158, 11, 0);
+  }
+}
+
+
+@keyframes canvas-node-glow {
+  0% {
+    filter: drop-shadow(0 0 0 transparent);
+  }
+  100% {
+    filter: drop-shadow(0 0 8px rgba(59, 130, 246, 0.3));
+  }
+}
+
+
+@keyframes canvas-data-flow {
+  0% {
+    stroke-dashoffset: 20;
+  }
+  100% {
+    stroke-dashoffset: 0;
+  }
+}
+
+
+@keyframes canvas-connection-pulse {
+  0%, 100% {
+    stroke-width: var(--canvas-connection-stroke-width);
+    opacity: 1;
+  }
+  50% {
+    stroke-width: calc(var(--canvas-connection-stroke-width) * 1.5);
+    opacity: 0.8;
+  }
+}
+
+
+@keyframes canvas-connection-active {
+  0% {
+    stroke-dasharray: 0, 10;
+  }
+  50% {
+    stroke-dasharray: 5, 5;
+  }
+  100% {
+    stroke-dasharray: 10, 0;
+  }
+}
+
+
+@keyframes canvas-minimap-fade-in {
+  0% {
+    opacity: 0;
+    transform: translateY(10px);
+  }
+  100% {
+    opacity: 1;
+    transform: translateY(0);
+  }
+}
+
+
+@keyframes canvas-tooltip-fade-in {
+  0% {
+    opacity: 0;
+    transform: translateY(5px) scale(0.95);
+  }
+  100% {
+    opacity: 1;
+    transform: translateY(0) scale(1);
+  }
+}
+
+
+@keyframes canvas-zoom-in {
+  0% {
+    transform: scale(0.9);
+  }
+  100% {
+    transform: scale(1);
+  }
+}
+
+
+@keyframes canvas-selection-breathe {
+  0%, 100% {
+    box-shadow: var(--canvas-shadow-node-selected);
+  }
+  50% {
+    box-shadow: 0 0 0 4px rgba(59, 130, 246, 0.2);
+  }
+}
+
+
+@keyframes canvas-drag-shadow {
+  0% {
+    box-shadow: var(--canvas-shadow-node);
+  }
+  100% {
+    box-shadow: var(--canvas-shadow-node-active);
+  }
+}
+
+
+@keyframes canvas-loading-spin {
+  0% {
+    transform: rotate(0deg);
+  }
+  100% {
+    transform: rotate(360deg);
+  }
+}
+
+
+@keyframes canvas-theme-transition {
+  0% {
+    opacity: 0.8;
+  }
+  100% {
+    opacity: 1;
+  }
+}
+
+
+@keyframes canvas-grid-scale {
+  0% {
+    opacity: 0.3;
+  }
+  100% {
+    opacity: 1;
+  }
+}
+
+
+@keyframes canvas-port-highlight {
+  0%, 100% {
+    background-color: transparent;
+    transform: scale(1);
+  }
+  50% {
+    background-color: var(--canvas-connection-selected);
+    transform: scale(1.2);
+  }
+}
+
+
+.canvas-animate-entrance {
+  animation: canvas-node-entrance var(--canvas-animation-slow) 
var(--canvas-easing-bounce) forwards;
+}
+
+.canvas-animate-exit {
+  animation: canvas-node-exit var(--canvas-animation-normal) 
var(--canvas-easing-default) forwards;
+}
+
+.canvas-animate-pulse {
+  animation: canvas-node-pulse 2s var(--canvas-easing-default) infinite;
+}
+
+.canvas-animate-pulse-success {
+  animation: canvas-node-pulse-success 2s var(--canvas-easing-default) 
infinite;
+}
+
+.canvas-animate-pulse-error {
+  animation: canvas-node-pulse-error 2s var(--canvas-easing-default) infinite;
+}
+
+.canvas-animate-pulse-warning {
+  animation: canvas-node-pulse-warning 2s var(--canvas-easing-default) 
infinite;
+}
+
+.canvas-animate-glow {
+  animation: canvas-node-glow var(--canvas-animation-normal) 
var(--canvas-easing-default) forwards;
+}
+
+.canvas-animate-data-flow {
+  stroke-dasharray: 5, 5;
+  animation: canvas-data-flow 2s linear infinite;
+}
+
+.canvas-animate-connection-pulse {
+  animation: canvas-connection-pulse 1.5s var(--canvas-easing-default) 
infinite;
+}
+
+.canvas-animate-selection-breathe {
+  animation: canvas-selection-breathe 2s var(--canvas-easing-default) infinite;
+}
+
+.canvas-animate-drag-shadow {
+  animation: canvas-drag-shadow var(--canvas-animation-fast) 
var(--canvas-easing-default) forwards;
+}
+
+.canvas-animate-loading {
+  animation: canvas-loading-spin 1s linear infinite;
+}
+
+
+.canvas-transition-all {
+  transition: all var(--canvas-animation-normal) var(--canvas-easing-default);
+}
+
+.canvas-transition-transform {
+  transition: transform var(--canvas-animation-normal) 
var(--canvas-easing-default);
+}
+
+.canvas-transition-colors {
+  transition: background-color var(--canvas-animation-normal) 
var(--canvas-easing-default),
+              border-color var(--canvas-animation-normal) 
var(--canvas-easing-default),
+              color var(--canvas-animation-normal) 
var(--canvas-easing-default);
+}
+
+.canvas-transition-shadow {
+  transition: box-shadow var(--canvas-animation-normal) 
var(--canvas-easing-default);
+}
+
+.canvas-transition-opacity {
+  transition: opacity var(--canvas-animation-fast) 
var(--canvas-easing-default);
+}
+
+
+.canvas-theme-transition {
+  transition: background-color var(--canvas-animation-normal) 
var(--canvas-easing-default),
+              border-color var(--canvas-animation-normal) 
var(--canvas-easing-default),
+              color var(--canvas-animation-normal) 
var(--canvas-easing-default),
+              box-shadow var(--canvas-animation-normal) 
var(--canvas-easing-default);
+}
\ No newline at end of file
diff --git 
a/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/canvas-background.scss
 
b/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/canvas-background.scss
new file mode 100644
index 000000000..aa1ae9ef4
--- /dev/null
+++ 
b/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/canvas-background.scss
@@ -0,0 +1,345 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@import './canvas-variables.scss';
+@import './canvas-animations.scss';
+
+
+.canvas-container {
+  position: relative;
+  width: 100%;
+  height: 100%;
+  overflow: hidden;
+  background: var(--canvas-bg);
+  
+
+  transition: background-color var(--canvas-animation-normal) 
var(--canvas-easing-default);
+}
+
+
+.canvas-grid-background {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  pointer-events: none;
+  z-index: var(--canvas-z-index-canvas);
+  
+
+  background-color: var(--canvas-bg);
+  background-image: 
+
+    radial-gradient(circle at 1px 1px, var(--canvas-grid) 1px, transparent 0),
+
+    radial-gradient(circle at 10px 10px, var(--canvas-grid-secondary) 0.5px, 
transparent 0);
+  background-size: 20px 20px, 100px 100px;
+  background-position: 0 0, 0 0;
+  
+
+  opacity: 1;
+  transition: opacity var(--canvas-animation-normal) 
var(--canvas-easing-default),
+              background-size var(--canvas-animation-normal) 
var(--canvas-easing-default);
+  
+
+  &.zoom-small {
+    background-size: 10px 10px, 50px 50px;
+    opacity: 0.6;
+  }
+  
+  &.zoom-large {
+    background-size: 40px 40px, 200px 200px;
+    opacity: 0.8;
+  }
+  
+  &.zoom-extra-large {
+    background-size: 80px 80px, 400px 400px;
+    opacity: 0.4;
+  }
+}
+
+
+.canvas-grid-dots {
+  background-image: 
+    radial-gradient(circle, var(--canvas-grid) 1px, transparent 1px);
+  background-size: 20px 20px;
+}
+
+
+.canvas-grid-lines {
+  background-image: 
+    linear-gradient(var(--canvas-grid) 1px, transparent 1px),
+    linear-gradient(90deg, var(--canvas-grid) 1px, transparent 1px);
+  background-size: 20px 20px;
+}
+
+
+.canvas-grid-cross {
+  background-image: 
+    linear-gradient(var(--canvas-grid) 1px, transparent 1px),
+    linear-gradient(90deg, var(--canvas-grid) 1px, transparent 1px),
+    radial-gradient(circle at 10px 10px, var(--canvas-grid-secondary) 2px, 
transparent 2px);
+  background-size: 20px 20px, 20px 20px, 100px 100px;
+}
+
+
+.canvas-guide-lines {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  pointer-events: none;
+  z-index: calc(var(--canvas-z-index-nodes) + 1);
+  opacity: 0;
+  transition: opacity var(--canvas-animation-fast) 
var(--canvas-easing-default);
+  
+  &.is-active {
+    opacity: 1;
+  }
+  
+  .guide-line {
+    position: absolute;
+    background: var(--canvas-guide-line);
+    opacity: 0.8;
+    
+    &.horizontal {
+      width: 100%;
+      height: 1px;
+      box-shadow: 0 0 2px rgba(59, 130, 246, 0.3);
+    }
+    
+    &.vertical {
+      width: 1px;
+      height: 100%;
+      box-shadow: 0 0 2px rgba(59, 130, 246, 0.3);
+    }
+    
+
+    animation: canvas-guide-line-pulse 1s ease-in-out;
+  }
+}
+
+
+@keyframes canvas-guide-line-pulse {
+  0%, 100% {
+    opacity: 0.8;
+    transform: scale(1);
+  }
+  50% {
+    opacity: 1;
+    transform: scale(1.02);
+  }
+}
+
+
+.canvas-watermark {
+  position: absolute;
+  bottom: var(--canvas-spacing-lg);
+  right: var(--canvas-spacing-lg);
+  font-size: 10px;
+  color: var(--canvas-grid);
+  opacity: 0.5;
+  pointer-events: none;
+  z-index: var(--canvas-z-index-canvas);
+  
+  transition: opacity var(--canvas-animation-normal) 
var(--canvas-easing-default);
+  
+  &:hover {
+    opacity: 0.8;
+  }
+}
+
+
+.canvas-boundary {
+  position: absolute;
+  border: 2px dashed var(--canvas-grid);
+  opacity: 0;
+  pointer-events: none;
+  z-index: var(--canvas-z-index-canvas);
+  
+  transition: opacity var(--canvas-animation-normal) 
var(--canvas-easing-default);
+  
+  &.is-visible {
+    opacity: 0.3;
+  }
+  
+  &.boundary-content {
+
+    border-color: var(--canvas-node-state-success);
+  }
+  
+  &.boundary-viewport {
+
+    border-color: var(--canvas-node-state-warning);
+  }
+}
+
+
+.canvas-center-indicator {
+  position: absolute;
+  top: 50%;
+  left: 50%;
+  width: 20px;
+  height: 20px;
+  margin: -10px 0 0 -10px;
+  border: 2px solid var(--canvas-guide-line);
+  border-radius: 50%;
+  opacity: 0;
+  pointer-events: none;
+  z-index: var(--canvas-z-index-canvas);
+  
+  transition: opacity var(--canvas-animation-normal) 
var(--canvas-easing-default);
+  
+  &.is-visible {
+    opacity: 0.6;
+  }
+  
+  &::before {
+    content: '';
+    position: absolute;
+    top: 50%;
+    left: 50%;
+    width: 6px;
+    height: 6px;
+    margin: -3px 0 0 -3px;
+    background: var(--canvas-guide-line);
+    border-radius: 50%;
+  }
+}
+
+
+.canvas-zoom-indicator {
+  position: absolute;
+  top: var(--canvas-spacing-lg);
+  left: var(--canvas-spacing-lg);
+  padding: var(--canvas-spacing-sm) var(--canvas-spacing-md);
+  background: rgba(255, 255, 255, 0.9);
+  border: 1px solid var(--canvas-grid);
+  border-radius: var(--canvas-border-radius-tooltip);
+  font-size: 11px;
+  color: var(--canvas-connection-default);
+  opacity: 0;
+  pointer-events: none;
+  z-index: var(--canvas-z-index-tooltip);
+  
+  transition: opacity var(--canvas-animation-normal) 
var(--canvas-easing-default);
+  
+  &.is-visible {
+    opacity: 1;
+  }
+  
+  [data-theme="dark"] & {
+    background: rgba(17, 24, 39, 0.9);
+    border-color: var(--canvas-grid);
+    color: var(--canvas-connection-default);
+  }
+}
+
+
+.canvas-performance-mode {
+  .canvas-grid-background {
+    background-image: none;
+    background-color: var(--canvas-bg);
+  }
+  
+  .canvas-guide-lines {
+    display: none;
+  }
+  
+  .canvas-center-indicator,
+  .canvas-zoom-indicator {
+    display: none;
+  }
+}
+
+
+.canvas-debug-mode {
+  .canvas-boundary {
+    opacity: 0.5 !important;
+  }
+  
+  .canvas-center-indicator {
+    opacity: 1 !important;
+  }
+  
+  .canvas-zoom-indicator {
+    opacity: 1 !important;
+  }
+  
+  .canvas-grid-background {
+    opacity: 1 !important;
+  }
+}
+
+
+@media (max-width: 768px) {
+  .canvas-grid-background {
+    background-size: 15px 15px, 75px 75px;
+  }
+  
+  .canvas-watermark {
+    display: none;
+  }
+  
+  .canvas-zoom-indicator {
+    font-size: 10px;
+    padding: var(--canvas-spacing-xs) var(--canvas-spacing-sm);
+  }
+}
+
+@media (max-width: 480px) {
+  .canvas-grid-background {
+    background-size: 12px 12px, 60px 60px;
+    opacity: 0.6;
+  }
+  
+  .canvas-guide-lines {
+    display: none;
+  }
+}
+
+
+@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
+  .canvas-grid-background {
+    background-size: 20px 20px, 100px 100px;
+  }
+  
+  .guide-line {
+    &.horizontal,
+    &.vertical {
+      transform: scale(0.5);
+      transform-origin: 0 0;
+    }
+  }
+}
+
+
+[data-theme="dark"] {
+  .canvas-grid-background {
+
+    opacity: 0.8;
+  }
+  
+  .canvas-watermark {
+    color: var(--canvas-grid-secondary);
+  }
+  
+  .canvas-zoom-indicator {
+    backdrop-filter: blur(8px);
+  }
+}
\ No newline at end of file
diff --git 
a/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/canvas-variables.scss
 
b/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/canvas-variables.scss
new file mode 100644
index 000000000..7323a2d0f
--- /dev/null
+++ 
b/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/canvas-variables.scss
@@ -0,0 +1,192 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+:root {
+
+  --canvas-node-source-primary: #10B981;
+  --canvas-node-source-secondary: #D1FAE5;
+  --canvas-node-source-border: #059669;
+  --canvas-node-source-text: #065F46;
+  --canvas-node-source-gradient: linear-gradient(135deg, #10B981 0%, #059669 
100%);
+  
+
+  --canvas-node-sink-primary: #3B82F6;
+  --canvas-node-sink-secondary: #DBEAFE;
+  --canvas-node-sink-border: #1D4ED8;
+  --canvas-node-sink-text: #1E3A8A;
+  --canvas-node-sink-gradient: linear-gradient(135deg, #3B82F6 0%, #1D4ED8 
100%);
+  
+
+  --canvas-node-transform-primary: #8B5CF6;
+  --canvas-node-transform-secondary: #EDE9FE;
+  --canvas-node-transform-border: #7C3AED;
+  --canvas-node-transform-text: #5B21B6;
+  --canvas-node-transform-gradient: linear-gradient(135deg, #8B5CF6 0%, 
#7C3AED 100%);
+  
+
+  --canvas-node-state-idle: #6B7280;
+  --canvas-node-state-running: #F59E0B;
+  --canvas-node-state-success: #10B981;
+  --canvas-node-state-error: #EF4444;
+  --canvas-node-state-warning: #F59E0B;
+  
+
+  --canvas-connection-default: #6B7280;
+  --canvas-connection-hover: #374151;
+  --canvas-connection-active: #1F2937;
+  --canvas-connection-selected: #3B82F6;
+  --canvas-connection-animated: #3B82F6;
+  --canvas-connection-gradient: linear-gradient(90deg, #6B7280 0%, #374151 
100%);
+  
+
+  --canvas-bg: #FAFAFA;
+  --canvas-grid: #E5E7EB;
+  --canvas-grid-secondary: #F3F4F6;
+  --canvas-guide-line: #3B82F6;
+  
+
+  --canvas-minimap-bg: rgba(255, 255, 255, 0.95);
+  --canvas-minimap-border: #E5E7EB;
+  --canvas-minimap-viewport: rgba(59, 130, 246, 0.2);
+  --canvas-minimap-viewport-border: #3B82F6;
+  
+
+  --canvas-shadow-node: 0 4px 12px rgba(0, 0, 0, 0.08);
+  --canvas-shadow-node-hover: 0 8px 24px rgba(0, 0, 0, 0.12);
+  --canvas-shadow-node-active: 0 12px 32px rgba(0, 0, 0, 0.16);
+  --canvas-shadow-node-selected: 0 0 0 2px rgba(59, 130, 246, 0.3);
+  --canvas-shadow-minimap: 0 4px 16px rgba(0, 0, 0, 0.1);
+  --canvas-shadow-tooltip: 0 2px 8px rgba(0, 0, 0, 0.1);
+  
+
+  --canvas-border-radius-node: 8px;
+  --canvas-border-radius-minimap: 6px;
+  --canvas-border-radius-tooltip: 4px;
+  --canvas-border-radius-button: 4px;
+  
+
+  --canvas-spacing-xs: 4px;
+  --canvas-spacing-sm: 8px;
+  --canvas-spacing-md: 12px;
+  --canvas-spacing-lg: 16px;
+  --canvas-spacing-xl: 24px;
+  --canvas-spacing-xxl: 32px;
+  
+
+  --canvas-font-size-node: 12px;
+  --canvas-font-weight-node: 500;
+  --canvas-line-height-node: 1.2;
+  --canvas-font-size-tooltip: 11px;
+  --canvas-font-weight-tooltip: 400;
+  --canvas-line-height-tooltip: 1.4;
+  --canvas-font-size-minimap: 10px;
+  --canvas-font-weight-minimap: 500;
+  --canvas-line-height-minimap: 1.2;
+  
+
+  --canvas-animation-fast: 150ms;
+  --canvas-animation-normal: 250ms;
+  --canvas-animation-slow: 350ms;
+  --canvas-animation-slower: 500ms;
+  --canvas-easing-default: cubic-bezier(0.4, 0, 0.2, 1);
+  --canvas-easing-bounce: cubic-bezier(0.68, -0.55, 0.265, 1.55);
+  --canvas-easing-smooth: cubic-bezier(0.25, 0.46, 0.45, 0.94);
+  
+
+  --canvas-node-width: 150px;
+  --canvas-node-height: 36px;
+  --canvas-node-min-width: 120px;
+  --canvas-node-max-width: 200px;
+  --canvas-minimap-width: 200px;
+  --canvas-minimap-height: 120px;
+  --canvas-connection-stroke-width: 2px;
+  --canvas-connection-stroke-width-hover: 3px;
+  --canvas-connection-arrow-size: 8px;
+  
+
+  --canvas-z-index-canvas: 1;
+  --canvas-z-index-connections: 5;
+  --canvas-z-index-nodes: 10;
+  --canvas-z-index-minimap: 1000;
+  --canvas-z-index-tooltip: 2000;
+  --canvas-z-index-modal: 3000;
+}
+
+
+[data-theme="dark"] {
+
+  --canvas-bg: #111827;
+  --canvas-grid: #374151;
+  --canvas-grid-secondary: #1F2937;
+  --canvas-guide-line: #60A5FA;
+  
+
+  --canvas-minimap-bg: rgba(17, 24, 39, 0.95);
+  --canvas-minimap-border: #374151;
+  
+
+  --canvas-node-source-secondary: rgba(16, 185, 129, 0.1);
+  --canvas-node-sink-secondary: rgba(59, 130, 246, 0.1);
+  --canvas-node-transform-secondary: rgba(139, 92, 246, 0.1);
+  
+
+  --canvas-connection-default: #9CA3AF;
+  --canvas-connection-hover: #D1D5DB;
+  --canvas-connection-active: #F3F4F6;
+}
+
+
+:root {
+  --canvas-breakpoint-mobile: 768px;
+  --canvas-breakpoint-tablet: 1024px;
+  --canvas-breakpoint-desktop: 1440px;
+  --canvas-breakpoint-wide: 1920px;
+}
+
+
+@media (max-width: 768px) {
+  :root {
+    --canvas-node-width: 120px;
+    --canvas-node-height: 32px;
+    --canvas-minimap-width: 150px;
+    --canvas-minimap-height: 90px;
+    --canvas-font-size-node: 11px;
+    --canvas-spacing-md: 8px;
+    --canvas-spacing-lg: 12px;
+  }
+}
+
+
+@media (min-width: 769px) and (max-width: 1024px) {
+  :root {
+    --canvas-node-width: 140px;
+    --canvas-node-height: 34px;
+    --canvas-minimap-width: 180px;
+    --canvas-minimap-height: 108px;
+  }
+}
+
+
+@media (min-width: 1920px) {
+  :root {
+    --canvas-node-width: 160px;
+    --canvas-node-height: 40px;
+    --canvas-minimap-width: 220px;
+    --canvas-minimap-height: 132px;
+    --canvas-font-size-node: 13px;
+  }
+}
\ No newline at end of file
diff --git 
a/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/design-tokens.ts
 
b/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/design-tokens.ts
new file mode 100644
index 000000000..0540ce891
--- /dev/null
+++ 
b/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/design-tokens.ts
@@ -0,0 +1,226 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+export const CanvasDesignTokens = {
+
+  colors: {
+
+    nodes: {
+      source: {
+        primary: '#10B981',
+        secondary: '#D1FAE5',
+        gradient: 'linear-gradient(135deg, #10B981 0%, #059669 100%)',
+        border: '#059669',
+        text: '#065F46'
+      },
+      sink: {
+        primary: '#3B82F6',
+        secondary: '#DBEAFE',
+        gradient: 'linear-gradient(135deg, #3B82F6 0%, #1D4ED8 100%)',
+        border: '#1D4ED8',
+        text: '#1E3A8A'
+      },
+      transform: {
+        primary: '#8B5CF6',
+        secondary: '#EDE9FE',
+        gradient: 'linear-gradient(135deg, #8B5CF6 0%, #7C3AED 100%)',
+        border: '#7C3AED',
+        text: '#5B21B6'
+      },
+
+      states: {
+        idle: '#6B7280',
+        running: '#F59E0B',
+        success: '#10B981',
+        error: '#EF4444',
+        warning: '#F59E0B'
+      }
+    },
+    
+
+    connections: {
+      default: '#6B7280',
+      hover: '#374151',
+      active: '#1F2937',
+      selected: '#3B82F6',
+      gradient: 'linear-gradient(90deg, #6B7280 0%, #374151 100%)',
+      animated: '#3B82F6'
+    },
+    
+
+    canvas: {
+      light: {
+        background: '#FAFAFA',
+        grid: '#E5E7EB',
+        gridSecondary: '#F3F4F6',
+        guideLine: '#3B82F6'
+      },
+      dark: {
+        background: '#111827',
+        grid: '#374151',
+        gridSecondary: '#1F2937',
+        guideLine: '#60A5FA'
+      }
+    },
+    
+
+    minimap: {
+      background: 'rgba(255, 255, 255, 0.95)',
+      backgroundDark: 'rgba(17, 24, 39, 0.95)',
+      border: '#E5E7EB',
+      borderDark: '#374151',
+      viewport: 'rgba(59, 130, 246, 0.2)',
+      viewportBorder: '#3B82F6'
+    }
+  },
+  
+
+  shadows: {
+    node: '0 4px 12px rgba(0, 0, 0, 0.08)',
+    nodeHover: '0 8px 24px rgba(0, 0, 0, 0.12)',
+    nodeActive: '0 12px 32px rgba(0, 0, 0, 0.16)',
+    nodeSelected: '0 0 0 2px rgba(59, 130, 246, 0.3)',
+    minimap: '0 4px 16px rgba(0, 0, 0, 0.1)',
+    tooltip: '0 2px 8px rgba(0, 0, 0, 0.1)'
+  },
+  
+
+  borderRadius: {
+    node: '8px',
+    minimap: '6px',
+    tooltip: '4px',
+    button: '4px'
+  },
+  
+
+  spacing: {
+    xs: '4px',
+    sm: '8px',
+    md: '12px',
+    lg: '16px',
+    xl: '24px',
+    xxl: '32px'
+  },
+  
+
+  typography: {
+    node: {
+      fontSize: '12px',
+      fontWeight: '500',
+      lineHeight: '1.2'
+    },
+    tooltip: {
+      fontSize: '11px',
+      fontWeight: '400',
+      lineHeight: '1.4'
+    },
+    minimap: {
+      fontSize: '10px',
+      fontWeight: '500',
+      lineHeight: '1.2'
+    }
+  },
+  
+
+  animations: {
+
+    duration: {
+      fast: '150ms',
+      normal: '250ms',
+      slow: '350ms',
+      slower: '500ms'
+    },
+    
+
+    easing: {
+      default: 'cubic-bezier(0.4, 0, 0.2, 1)',
+      bounce: 'cubic-bezier(0.68, -0.55, 0.265, 1.55)',
+      smooth: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)'
+    },
+    
+
+    configs: {
+      nodeEntrance: {
+        duration: '350ms',
+        easing: 'cubic-bezier(0.68, -0.55, 0.265, 1.55)',
+        delay: '0ms'
+      },
+      nodeHover: {
+        duration: '150ms',
+        easing: 'cubic-bezier(0.4, 0, 0.2, 1)'
+      },
+      edgeFlow: {
+        duration: '2000ms',
+        easing: 'linear',
+        iterationCount: 'infinite'
+      },
+      themeTransition: {
+        duration: '250ms',
+        easing: 'cubic-bezier(0.4, 0, 0.2, 1)'
+      }
+    }
+  },
+  
+
+  sizes: {
+    node: {
+      width: 150,
+      height: 36,
+      minWidth: 120,
+      maxWidth: 200
+    },
+    minimap: {
+      width: 200,
+      height: 120,
+      minWidth: 150,
+      minHeight: 90
+    },
+    connection: {
+      strokeWidth: 2,
+      strokeWidthHover: 3,
+      arrowSize: 8
+    }
+  },
+  
+
+  zIndex: {
+    canvas: 1,
+    nodes: 10,
+    connections: 5,
+    minimap: 1000,
+    tooltip: 2000,
+    modal: 3000
+  }
+} as const
+
+
+export type NodeType = 'source' | 'sink' | 'transform'
+export type NodeState = 'idle' | 'running' | 'success' | 'error' | 'warning'
+export type Theme = 'light' | 'dark'
+
+
+export const getNodeColors = (type: NodeType) => {
+  return CanvasDesignTokens.colors.nodes[type]
+}
+
+export const getNodeStateColor = (state: NodeState) => {
+  return CanvasDesignTokens.colors.nodes.states[state]
+}
+
+export const getCanvasColors = (theme: Theme) => {
+  return CanvasDesignTokens.colors.canvas[theme]
+}
\ No newline at end of file
diff --git 
a/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/edge-styles.scss
 
b/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/edge-styles.scss
new file mode 100644
index 000000000..1ba37fe9c
--- /dev/null
+++ 
b/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/edge-styles.scss
@@ -0,0 +1,305 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+@import './canvas-variables.scss';
+@import './canvas-animations.scss';
+@import './responsive-mixins.scss';
+
+
+.modern-edge {
+
+  stroke: var(--canvas-connection-default);
+  stroke-width: var(--canvas-connection-stroke-width);
+  fill: none;
+  cursor: pointer;
+  
+
+  transition: stroke var(--canvas-animation-normal) 
var(--canvas-easing-default),
+              stroke-width var(--canvas-animation-normal) 
var(--canvas-easing-default),
+              opacity var(--canvas-animation-fast) 
var(--canvas-easing-default);
+  
+
+  @include canvas-connection-responsive;
+  
+
+  &:hover {
+    stroke: var(--canvas-connection-hover);
+    stroke-width: var(--canvas-connection-stroke-width-hover);
+    filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.1));
+  }
+  
+
+  &.is-selected {
+    stroke: var(--canvas-connection-selected);
+    stroke-width: var(--canvas-connection-stroke-width-hover);
+    @extend .canvas-animate-connection-pulse;
+  }
+  
+
+  &.is-active {
+    @extend .canvas-animate-data-flow;
+  }
+  
+
+  &.is-error {
+    stroke: var(--canvas-node-state-error);
+    stroke-dasharray: 5, 5;
+    animation: canvas-connection-pulse 1s ease-in-out infinite;
+  }
+  
+
+  &.is-warning {
+    stroke: var(--canvas-node-state-warning);
+    stroke-dasharray: 3, 3;
+  }
+  
+
+  &.is-success {
+    stroke: var(--canvas-node-state-success);
+  }
+}
+
+
+.modern-edge-arrow {
+  fill: var(--canvas-connection-default);
+  stroke: none;
+  transition: fill var(--canvas-animation-normal) var(--canvas-easing-default);
+  
+  .modern-edge:hover & {
+    fill: var(--canvas-connection-hover);
+  }
+  
+  .modern-edge.is-selected & {
+    fill: var(--canvas-connection-selected);
+  }
+  
+  .modern-edge.is-error & {
+    fill: var(--canvas-node-state-error);
+  }
+  
+  .modern-edge.is-warning & {
+    fill: var(--canvas-node-state-warning);
+  }
+  
+  .modern-edge.is-success & {
+    fill: var(--canvas-node-state-success);
+  }
+}
+
+
+.modern-edge-label {
+  font-size: var(--canvas-font-size-tooltip);
+  font-weight: var(--canvas-font-weight-tooltip);
+  fill: var(--canvas-connection-default);
+  text-anchor: middle;
+  dominant-baseline: middle;
+  pointer-events: none;
+  opacity: 0;
+  transition: opacity var(--canvas-animation-normal) 
var(--canvas-easing-default);
+  
+  .modern-edge:hover & {
+    opacity: 1;
+    fill: var(--canvas-connection-hover);
+  }
+  
+  .modern-edge.is-selected & {
+    opacity: 1;
+    fill: var(--canvas-connection-selected);
+  }
+}
+
+
+.modern-edge-tooltip-bg {
+  fill: rgba(255, 255, 255, 0.95);
+  stroke: var(--canvas-connection-default);
+  stroke-width: 1;
+  rx: var(--canvas-border-radius-tooltip);
+  ry: var(--canvas-border-radius-tooltip);
+  filter: drop-shadow(0 2px 8px rgba(0, 0, 0, 0.1));
+  opacity: 0;
+  transition: opacity var(--canvas-animation-normal) 
var(--canvas-easing-default);
+  
+  .modern-edge:hover & {
+    opacity: 1;
+  }
+  
+  [data-theme="dark"] & {
+    fill: rgba(17, 24, 39, 0.95);
+    stroke: var(--canvas-grid);
+  }
+}
+
+
+.modern-edge-gradient {
+  stroke: url(#connection-gradient);
+  
+  &:hover {
+    stroke: url(#connection-gradient-hover);
+  }
+  
+  &.is-selected {
+    stroke: url(#connection-gradient-selected);
+  }
+}
+
+
+.modern-edge-animated {
+  stroke-dasharray: 8, 4;
+  animation: canvas-data-flow 2s linear infinite;
+  
+  &.flow-fast {
+    animation-duration: 1s;
+  }
+  
+  &.flow-slow {
+    animation-duration: 4s;
+  }
+  
+  &.flow-reverse {
+    animation-direction: reverse;
+  }
+}
+
+
+.modern-edge-type {
+  &.type-data {
+    stroke: var(--canvas-connection-default);
+  }
+  
+  &.type-control {
+    stroke: var(--canvas-node-state-warning);
+    stroke-dasharray: 4, 2;
+  }
+  
+  &.type-error {
+    stroke: var(--canvas-node-state-error);
+    stroke-dasharray: 2, 2;
+  }
+}
+
+
+.modern-edge-weight {
+  &.weight-thin {
+    stroke-width: 1px;
+  }
+  
+  &.weight-normal {
+    stroke-width: var(--canvas-connection-stroke-width);
+  }
+  
+  &.weight-thick {
+    stroke-width: calc(var(--canvas-connection-stroke-width) * 1.5);
+  }
+  
+  &.weight-bold {
+    stroke-width: calc(var(--canvas-connection-stroke-width) * 2);
+  }
+}
+
+
+.modern-edge-opacity {
+  &.opacity-ghost {
+    opacity: 0.3;
+  }
+  
+  &.opacity-faded {
+    opacity: 0.6;
+  }
+  
+  &.opacity-normal {
+    opacity: 1;
+  }
+}
+
+
+.modern-edge-path {
+  &.path-straight {
+
+  }
+  
+  &.path-curved {
+
+  }
+  
+  &.path-orthogonal {
+
+    stroke-linejoin: round;
+    stroke-linecap: round;
+  }
+  
+  &.path-smooth {
+
+    stroke-linecap: round;
+  }
+}
+
+
+.modern-edge-interaction {
+  stroke: transparent;
+  stroke-width: 12px;
+  fill: none;
+  cursor: pointer;
+  
+
+  @include canvas-touch-device {
+    stroke-width: 16px;
+  }
+}
+
+
+.modern-edge-highlight {
+  stroke: var(--canvas-connection-selected);
+  stroke-width: calc(var(--canvas-connection-stroke-width) * 2);
+  opacity: 0.3;
+  pointer-events: none;
+  
+  animation: canvas-connection-pulse 1.5s ease-in-out infinite;
+}
+
+
+.modern-edge-group {
+  .modern-edge {
+    stroke-width: 1px;
+    opacity: 0.7;
+  }
+  
+  &:hover .modern-edge {
+    stroke-width: var(--canvas-connection-stroke-width);
+    opacity: 1;
+  }
+  
+  .modern-edge.is-primary {
+    stroke-width: var(--canvas-connection-stroke-width);
+    opacity: 1;
+  }
+}
+
+
+[data-theme="dark"] {
+  .modern-edge {
+    filter: brightness(1.2);
+  }
+  
+  .modern-edge-label {
+    fill: var(--canvas-connection-default);
+  }
+  
+  .modern-edge:hover {
+    filter: brightness(1.4) drop-shadow(0 2px 4px rgba(0, 0, 0, 0.3));
+  }
+}
\ No newline at end of file
diff --git 
a/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/index.module.scss
 
b/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/index.module.scss
index 1ebd2fa0e..fb421c55c 100644
--- 
a/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/index.module.scss
+++ 
b/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/index.module.scss
@@ -15,22 +15,400 @@
  * limitations under the License.
  */
 
+
 .dag-node {
+  display: flex !important;
+  align-items: center !important;
+  justify-content: flex-start !important;
+  height: 100% !important;
+  width: 100% !important;
+  position: relative !important;
+  padding: 12px 18px !important;
+  min-height: 44px !important;
+  min-width: 180px !important;
+  box-sizing: border-box !important;
+  
+
+  background: linear-gradient(135deg, #ffffff 0%, #f8fafc 100%) !important;
+  border: 1px solid #e2e8f0 !important;
+  border-radius: 16px !important;
+  box-shadow: 
+    0 6px 20px rgba(0, 0, 0, 0.06),
+    0 2px 6px rgba(0, 0, 0, 0.04),
+    inset 0 1px 0 rgba(255, 255, 255, 0.8) !important;
+  
+
+  color: #1f2937 !important;
+  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 
'Helvetica Neue', Arial, sans-serif !important;
+  font-size: 13px !important;
+  font-weight: 500 !important;
+  line-height: 1.4 !important;
+  
+
+  visibility: visible !important;
+  opacity: 1 !important;
+  z-index: 100 !important;
+  overflow: visible !important;
+  
+
+  transition: all 0.35s cubic-bezier(0.4, 0, 0.2, 1) !important;
+  
+
+  &:hover {
+    background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%) !important;
+    box-shadow: 
+      0 12px 32px rgba(0, 0, 0, 0.12),
+      0 6px 16px rgba(0, 0, 0, 0.08),
+      inset 0 1px 0 rgba(255, 255, 255, 0.9) !important;
+    transform: translateY(-4px) scale(1.02) !important;
+    filter: brightness(1.05);
+  }
+  
+
+  &.selected,
+  &:focus {
+    border-color: #6366f1 !important;
+    box-shadow: 
+      0 12px 32px rgba(0, 0, 0, 0.1),
+      0 0 0 4px rgba(99, 102, 241, 0.15) !important;
+  }
+}
+
+
+@keyframes node-entrance {
+  0% {
+    opacity: 0;
+    transform: scale(0.8) translateY(10px);
+  }
+  100% {
+    opacity: 1;
+    transform: scale(1) translateY(0);
+  }
+}
+
+@keyframes pulse-running {
+  0%, 100% {
+    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08), 0 0 0 0 rgba(245, 158, 11, 
0.4);
+  }
+  50% {
+    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08), 0 0 0 8px rgba(245, 158, 11, 
0);
+  }
+}
+
+@keyframes pulse-success {
+  0%, 100% {
+    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08), 0 0 0 0 rgba(16, 185, 129, 
0.4);
+  }
+  50% {
+    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08), 0 0 0 8px rgba(16, 185, 129, 
0);
+  }
+}
+
+@keyframes pulse-error {
+  0%, 100% {
+    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08), 0 0 0 0 rgba(239, 68, 68, 0.4);
+  }
+  50% {
+    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08), 0 0 0 8px rgba(239, 68, 68, 0);
+  }
+}
+
+
+.dag-node-icon {
+  width: 24px;
+  height: 24px;
+  margin-right: 12px;
+  flex-shrink: 0;
   display: flex;
   align-items: center;
+  justify-content: center;
+  font-size: 18px;
+  
+  span {
+    display: block;
+    line-height: 1;
+    filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.1));
+  }
+}
+
+
+.dag-node-label {
+  flex: 1;
+  display: flex;
+  align-items: center;
+  overflow: hidden;
+  
+  span {
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+    text-align: left;
+    color: #1f2937 !important;
+    font-size: 14px !important;
+    font-weight: 600 !important;
+    line-height: 1.3 !important;
+    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 
sans-serif !important;
+    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
+  }
+}
+
+
+.dag-node-port {
+  position: absolute;
+  width: 10px;
+  height: 10px;
+  border-radius: 50%;
+  background: #6366f1;
+  border: 2px solid #fff;
+  opacity: 0;
+  transition: opacity 0.2s cubic-bezier(0.4, 0, 0.2, 1);
+  z-index: 200;
+  
+  &.port-input {
+    left: -6px;
+    top: 50%;
+    transform: translateY(-50%);
+  }
+  
+  &.port-output {
+    right: -6px;
+    top: 50%;
+    transform: translateY(-50%);
+  }
+  
+  &:hover,
+  &.is-active {
+    opacity: 1;
+    box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.3);
+  }
+}
+
+
+.container {
   height: 100%;
-  background-color: #fff;
-  border: 1px solid #c2c8d5;
-  border-left: 4px solid #5F95FF;
+  width: 100%;
+  position: relative;
+  background: #fafafa;
+  border: 1px solid #e5e7eb;
   border-radius: 4px;
-  box-shadow: 0 2px 5px 1px rgba(0, 0, 0, 0.06);
 }
 
-.dag-node-label {
-  display: inline-block;
-  flex-shrink: 0;
+.dag-container {
+  height: 100%;
   width: 100%;
-  text-align: center;
-  color: #666;
-  font-size: 12px;
+  background: transparent;
+}
+
+
+.minimap {
+  position: absolute;
+  right: 20px;
+  bottom: 60px;
+  border: 1px solid #e2e8f0;
+  border-radius: 6px;
+  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
+  background: rgba(255, 255, 255, 0.95);
+  backdrop-filter: blur(8px);
+  
+
+  transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
+  
+
+  &:hover {
+    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
+    transform: translateY(-2px);
+  }
+}
+
+
+:global {
+  /* 连接线创建时的样式 */
+  .x6-edge.x6-edge-creating .x6-edge-path {
+    stroke: #6366f1 !important;
+    stroke-width: 2px !important;
+    stroke-dasharray: 5, 5 !important;
+    animation: edge-creating 0.5s linear infinite !important;
+  }
+  
+  @keyframes edge-creating {
+    to {
+      stroke-dashoffset: -10;
+    }
+  }
+  
+
+  .x6-node-tool-remove,
+  .x6-node-tool-button {
+    display: none !important;
+    visibility: hidden !important;
+    opacity: 0 !important;
+  }
+  
+
+  .x6-node-tools {
+    visibility: visible !important;
+    opacity: 1 !important;
+    display: block !important;
+  }
+  
+  .x6-node-tool {
+    visibility: visible !important;
+    opacity: 1 !important;
+    display: block !important;
+  }
+  
+
+  .x6-node-tool text {
+    visibility: visible !important;
+    opacity: 1 !important;
+    display: block !important;
+    font-size: 12px !important;
+    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 
sans-serif !important;
+  }
+  
+
+  .x6-port,
+  .x6-port-body {
+    opacity: 0 !important;
+    visibility: hidden !important;
+  }
+  
+
+  .x6-node {
+    .x6-node-content {
+      visibility: visible !important;
+      opacity: 1 !important;
+      display: block !important;
+    }
+  }
+  
+
+  .x6-edge {
+    .x6-edge-path {
+      stroke: #9CA3AF !important;
+      stroke-width: 2px !important;
+      stroke-linecap: round !important;
+      stroke-linejoin: round !important;
+      filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.1)) !important;
+      transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1) !important;
+    }
+    
+
+    .x6-edge-marker {
+      fill: #9CA3AF !important;
+      stroke: #9CA3AF !important;
+      filter: none !important;
+    }
+    
+
+    &:hover {
+      .x6-edge-path {
+        stroke: #4B5563 !important;
+        stroke-width: 2.5px !important;
+        filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.15)) !important;
+      }
+      
+      .x6-edge-marker {
+        fill: #4B5563 !important;
+        stroke: #4B5563 !important;
+      }
+    }
+    
+
+    &.selected {
+      .x6-edge-path {
+        stroke: #3b82f6 !important;
+        stroke-width: 4px !important;
+        stroke-dasharray: 8 4 !important;
+        animation: edge-flow 2s linear infinite !important;
+      }
+    }
+  }
+  
+
+  @keyframes edge-flow {
+    0% {
+      stroke-dashoffset: 0;
+    }
+    100% {
+      stroke-dashoffset: 12;
+    }
+  }
+  
+
+  .x6-edge-label {
+    background: rgba(255, 255, 255, 0.95) !important;
+    border: 1px solid #e2e8f0 !important;
+    border-radius: 6px !important;
+    padding: 4px 8px !important;
+    font-size: 12px !important;
+    font-weight: 500 !important;
+    color: #374151 !important;
+    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1) !important;
+    backdrop-filter: blur(8px) !important;
+  }
+}
+
+
+[data-theme="dark"] {
+  .container {
+    background: #111827;
+    border-color: #374151;
+  }
+  
+  .minimap {
+    background: rgba(17, 24, 39, 0.95);
+    border-color: #374151;
+    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
+    
+    &:hover {
+      box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
+    }
+  }
+  
+  .dag-node {
+    background: linear-gradient(135deg, rgba(31, 41, 55, 0.8) 0%, rgba(17, 24, 
39, 0.9) 100%);
+    border-color: #374151;
+    backdrop-filter: blur(8px);
+    
+    .dag-node-label {
+      color: #d1d5db;
+    }
+    
+    &:hover .dag-node-label {
+      color: #f3f4f6;
+    }
+  }
+  
+  .dag-node-port {
+    border-color: #111827;
+  }
+  
+
+  :global {
+    .x6-edge {
+      .x6-edge-path {
+        stroke: #8b5cf6 !important;
+        filter: drop-shadow(0 2px 4px rgba(139, 92, 246, 0.3)) !important;
+      }
+      
+      .x6-edge-marker {
+        fill: #8b5cf6 !important;
+        stroke: #8b5cf6 !important;
+      }
+      
+      &:hover {
+        .x6-edge-path {
+          stroke: #a78bfa !important;
+          filter: drop-shadow(0 4px 8px rgba(167, 139, 250, 0.4)) !important;
+        }
+      }
+    }
+    
+    .x6-edge-label {
+      background: rgba(17, 24, 39, 0.95) !important;
+      border-color: #374151 !important;
+      color: #d1d5db !important;
+    }
+  }
 }
\ No newline at end of file
diff --git 
a/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/minimap-styles.scss
 
b/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/minimap-styles.scss
new file mode 100644
index 000000000..22cc71084
--- /dev/null
+++ 
b/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/minimap-styles.scss
@@ -0,0 +1,382 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@import './canvas-variables.scss';
+@import './canvas-animations.scss';
+@import './responsive-mixins.scss';
+
+
+.modern-minimap {
+  position: absolute;
+  right: var(--canvas-spacing-lg);
+  bottom: var(--canvas-spacing-lg);
+  width: var(--canvas-minimap-width);
+  height: var(--canvas-minimap-height);
+  background: var(--canvas-minimap-bg);
+  border: 1px solid var(--canvas-minimap-border);
+  border-radius: var(--canvas-border-radius-minimap);
+  box-shadow: var(--canvas-shadow-minimap);
+  backdrop-filter: blur(8px);
+  z-index: var(--canvas-z-index-minimap);
+  
+
+  @include canvas-minimap-responsive;
+  
+
+  transition: all var(--canvas-animation-normal) var(--canvas-easing-default);
+  
+
+  &:hover {
+    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
+    transform: translateY(-2px);
+  }
+  
+
+  animation: canvas-minimap-fade-in var(--canvas-animation-slow) 
var(--canvas-easing-bounce);
+}
+
+
+.modern-minimap__header {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  padding: var(--canvas-spacing-sm) var(--canvas-spacing-md);
+  border-bottom: 1px solid var(--canvas-minimap-border);
+  background: rgba(255, 255, 255, 0.5);
+  border-radius: var(--canvas-border-radius-minimap) 
var(--canvas-border-radius-minimap) 0 0;
+  
+  [data-theme="dark"] & {
+    background: rgba(17, 24, 39, 0.5);
+    border-bottom-color: var(--canvas-grid);
+  }
+}
+
+
+.modern-minimap__title {
+  font-size: var(--canvas-font-size-minimap);
+  font-weight: var(--canvas-font-weight-minimap);
+  color: var(--canvas-connection-default);
+  margin: 0;
+  
+
+  @include canvas-typography-responsive;
+}
+
+
+.modern-minimap__controls {
+  display: flex;
+  gap: var(--canvas-spacing-xs);
+}
+
+
+.modern-minimap__zoom-in,
+.modern-minimap__zoom-out,
+.modern-minimap__reset,
+.modern-minimap__toggle {
+  width: 20px;
+  height: 20px;
+  border: none;
+  background: transparent;
+  color: var(--canvas-connection-default);
+  border-radius: var(--canvas-border-radius-button);
+  cursor: pointer;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  font-size: 12px;
+  font-weight: 500;
+  
+
+  transition: all var(--canvas-animation-fast) var(--canvas-easing-default);
+  
+  &:hover {
+    background: var(--canvas-minimap-viewport);
+    color: var(--canvas-connection-hover);
+    transform: scale(1.1);
+  }
+  
+  &:active {
+    transform: scale(0.95);
+  }
+  
+
+  @include canvas-respond-to-max('mobile') {
+    width: 18px;
+    height: 18px;
+    font-size: 11px;
+  }
+}
+
+
+.modern-minimap__viewport {
+  position: relative;
+  width: 100%;
+  height: calc(100% - 40px);
+  overflow: hidden;
+  border-radius: 0 0 var(--canvas-border-radius-minimap) 
var(--canvas-border-radius-minimap);
+}
+
+
+.modern-minimap__content {
+  width: 100%;
+  height: 100%;
+  position: relative;
+  
+
+  .x6-graph-minimap {
+    border: none !important;
+    border-radius: 0 !important;
+    box-shadow: none !important;
+    background: transparent !important;
+  }
+  
+
+  .x6-node {
+    opacity: 0.8;
+    
+    rect {
+      fill: var(--canvas-grid-secondary) !important;
+      stroke: var(--canvas-grid) !important;
+      stroke-width: 1 !important;
+      rx: 2 !important;
+      ry: 2 !important;
+    }
+    
+
+    &[data-node-type="source"] rect {
+      fill: var(--canvas-node-source-secondary) !important;
+      stroke: var(--canvas-node-source-primary) !important;
+    }
+    
+    &[data-node-type="sink"] rect {
+      fill: var(--canvas-node-sink-secondary) !important;
+      stroke: var(--canvas-node-sink-primary) !important;
+    }
+    
+    &[data-node-type="transform"] rect {
+      fill: var(--canvas-node-transform-secondary) !important;
+      stroke: var(--canvas-node-transform-primary) !important;
+    }
+  }
+  
+
+  .x6-edge {
+    opacity: 0.6;
+    
+    path {
+      stroke: var(--canvas-connection-default) !important;
+      stroke-width: 1 !important;
+    }
+  }
+}
+
+
+.modern-minimap__indicator {
+  position: absolute;
+  border: 2px solid var(--canvas-minimap-viewport-border);
+  background: var(--canvas-minimap-viewport);
+  border-radius: 2px;
+  pointer-events: none;
+  z-index: 10;
+  
+
+  transition: all var(--canvas-animation-fast) var(--canvas-easing-default);
+  
+
+  &.is-moving {
+    transition: none;
+  }
+  
+  &.is-resizing {
+    border-style: dashed;
+    animation: canvas-minimap-indicator-pulse 1s ease-in-out infinite;
+  }
+}
+
+
+@keyframes canvas-minimap-indicator-pulse {
+  0%, 100% {
+    opacity: 0.6;
+  }
+  50% {
+    opacity: 1;
+  }
+}
+
+
+.modern-minimap__tooltip {
+  position: absolute;
+  bottom: 100%;
+  left: 50%;
+  transform: translateX(-50%);
+  margin-bottom: var(--canvas-spacing-sm);
+  padding: var(--canvas-spacing-xs) var(--canvas-spacing-sm);
+  background: rgba(0, 0, 0, 0.8);
+  color: white;
+  font-size: 10px;
+  border-radius: var(--canvas-border-radius-tooltip);
+  white-space: nowrap;
+  opacity: 0;
+  pointer-events: none;
+  z-index: var(--canvas-z-index-tooltip);
+  
+
+  transition: opacity var(--canvas-animation-normal) 
var(--canvas-easing-default);
+  
+  &.is-visible {
+    opacity: 1;
+  }
+  
+
+  &::after {
+    content: '';
+    position: absolute;
+    top: 100%;
+    left: 50%;
+    transform: translateX(-50%);
+    border: 4px solid transparent;
+    border-top-color: rgba(0, 0, 0, 0.8);
+  }
+}
+
+
+.modern-minimap__status {
+  position: absolute;
+  top: var(--canvas-spacing-sm);
+  right: var(--canvas-spacing-sm);
+  width: 8px;
+  height: 8px;
+  border-radius: 50%;
+  z-index: 10;
+  
+  &.status-loading {
+    background: var(--canvas-node-state-warning);
+    animation: canvas-loading-spin 1s linear infinite;
+  }
+  
+  &.status-ready {
+    background: var(--canvas-node-state-success);
+  }
+  
+  &.status-error {
+    background: var(--canvas-node-state-error);
+    animation: canvas-node-pulse-error 2s ease-in-out infinite;
+  }
+}
+
+
+.modern-minimap.is-collapsed {
+  width: 40px;
+  height: 40px;
+  
+  .modern-minimap__header {
+    padding: var(--canvas-spacing-xs);
+    border-bottom: none;
+  }
+  
+  .modern-minimap__title {
+    display: none;
+  }
+  
+  .modern-minimap__viewport {
+    display: none;
+  }
+  
+  .modern-minimap__toggle {
+    transform: rotate(180deg);
+  }
+}
+
+
+.modern-minimap.is-dragging {
+  cursor: grabbing;
+  transform: rotate(2deg);
+  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.2);
+}
+
+
+.modern-minimap.is-fullscreen {
+  position: fixed;
+  top: 50%;
+  left: 50%;
+  transform: translate(-50%, -50%);
+  width: 60vw;
+  height: 60vh;
+  max-width: 800px;
+  max-height: 600px;
+  z-index: var(--canvas-z-index-modal);
+  
+  .modern-minimap__header {
+    padding: var(--canvas-spacing-md) var(--canvas-spacing-lg);
+  }
+  
+  .modern-minimap__title {
+    font-size: 14px;
+  }
+  
+  .modern-minimap__controls {
+    gap: var(--canvas-spacing-sm);
+  }
+  
+  .modern-minimap__zoom-in,
+  .modern-minimap__zoom-out,
+  .modern-minimap__reset,
+  .modern-minimap__toggle {
+    width: 24px;
+    height: 24px;
+    font-size: 14px;
+  }
+}
+
+
+.modern-minimap-overlay {
+  position: fixed;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  background: rgba(0, 0, 0, 0.5);
+  z-index: calc(var(--canvas-z-index-modal) - 1);
+  opacity: 0;
+  
+  transition: opacity var(--canvas-animation-normal) 
var(--canvas-easing-default);
+  
+  &.is-visible {
+    opacity: 1;
+  }
+}
+
+
+[data-theme="dark"] {
+  .modern-minimap {
+    border-color: var(--canvas-grid);
+    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
+  }
+  
+  .modern-minimap__tooltip {
+    background: rgba(255, 255, 255, 0.9);
+    color: var(--canvas-connection-default);
+    
+    &::after {
+      border-top-color: rgba(255, 255, 255, 0.9);
+    }
+  }
+  
+  .modern-minimap-overlay {
+    background: rgba(0, 0, 0, 0.7);
+  }
+}
\ No newline at end of file
diff --git 
a/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/node.tsx 
b/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/node.tsx
index b1ccc0615..161dd7047 100644
--- a/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/node.tsx
+++ b/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/node.tsx
@@ -15,18 +15,244 @@
  * limitations under the License.
  */
 
-import { defineComponent, inject } from 'vue'
+import { defineComponent, inject, computed } from 'vue'
+import { NTooltip, NProgress } from 'naive-ui'
 import styles from './index.module.scss'
+import { ModernNodeData, determineNodeType } from './use-dag-node'
+import { CanvasDesignTokens, getNodeStateColor, NodeType } from 
'./design-tokens'
 
 const Node = defineComponent({
   name: 'Node',
   setup() {
     const getNode = inject('getNode') as any
+    
+    if (!getNode) {
+      console.error('getNode function not found in inject')
+      return () => <div class={styles['dag-node']}>Error: Node data not 
available</div>
+    }
+    
     const node = getNode()
-    const { name } = node.getData()
+    const nodeData = node?.getData() || {} as ModernNodeData
+    
+
+    const {
+      name = 'Unknown',
+      nodeType,
+      connectorType,
+      status = 'idle',
+      theme,
+      isSelected = false,
+      isHovered = false,
+      isDragging = false,
+      isDisabled = false,
+      animations = {},
+      style = {},
+      progress = 0,
+      statusMessage,
+      metadata = {}
+    } = nodeData
+    
+
+    const actualNodeType = computed(() => 
+      determineNodeType(nodeType, connectorType, name)
+    )
+    
+
+    const getNodeIcon = (type: NodeType) => {
+
+      if (metadata.icon) {
+        return metadata.icon
+      }
+      
+      switch (type) {
+        case 'source':
+          return '📊'
+        case 'sink':
+          return '🎯'
+        case 'transform':
+          return '⚙️'
+        default:
+          return null
+      }
+    }
+    
+
+    const nodeClass = computed(() => {
+      return {
+        [styles['dag-node']]: true,
+        [styles[`dag-node--${actualNodeType.value}`]]: true,
+        [styles['dag-node--selected']]: isSelected,
+        [styles['dag-node--hovered']]: isHovered,
+        [styles['dag-node--dragging']]: isDragging,
+        [styles['dag-node--disabled']]: isDisabled,
+        [styles[`dag-node--${status}`]]: true,
+        [styles['dag-node--entrance']]: animations.entrance,
+        [styles['dag-node--pulse']]: animations.pulse,
+        [styles['dag-node--glow']]: animations.glow,
+        [styles['dag-node--shake']]: animations.shake
+      }
+    })
+    
+
+    const getBorderStyle = () => {
+
+      if (theme) {
+        if (status === 'error') {
+          return `4px solid ${getNodeStateColor('error')}`
+        } else if (status === 'warning') {
+          return `4px solid ${getNodeStateColor('warning')}`
+        } else {
+          return `4px solid ${theme.borderColor}`
+        }
+      }
+      
+
+      if (status === 'error') {
+        return '4px solid #F87171'
+      } else if (status === 'warning') {
+        return '4px solid #FBBF24'
+      } else if (actualNodeType.value === 'source') {
+        return '4px solid #34D399'
+      } else if (actualNodeType.value === 'sink') {
+        return '4px solid #60A5FA'
+      } else if (actualNodeType.value === 'transform') {
+        return '4px solid #A78BFA'
+      } else {
+        return '4px solid #60A5FA'
+      }
+    }
+
+
+    const getBackgroundStyle = () => {
+
+      if (theme) {
+        if (status === 'error') {
+          return 'linear-gradient(135deg, #FEF2F2 0%, #FEE2E2 100%)'
+        } else if (status === 'warning') {
+          return 'linear-gradient(135deg, #FFFBEB 0%, #FEF3C7 100%)'
+        } else {
+          return theme.gradient
+        }
+      }
+      
+
+      if (status === 'error') {
+        return 'linear-gradient(135deg, #FEF2F2 0%, #FEE2E2 100%)'
+      } else if (status === 'warning') {
+        return 'linear-gradient(135deg, #FFFBEB 0%, #FEF3C7 100%)'
+      } else if (actualNodeType.value === 'source') {
+        return 'linear-gradient(135deg, #ECFDF5 0%, #D1FAE5 100%)'
+      } else if (actualNodeType.value === 'sink') {
+        return 'linear-gradient(135deg, #EFF6FF 0%, #DBEAFE 100%)'
+      } else if (actualNodeType.value === 'transform') {
+        return 'linear-gradient(135deg, #F5F3FF 0%, #EDE9FE 100%)'
+      } else {
+        return 'linear-gradient(135deg, #F8FAFC 0%, #F1F5F9 100%)'
+      }
+    }
+    
+
+    const getShadowStyle = () => {
+      if (isSelected) {
+        return CanvasDesignTokens.shadows.nodeSelected
+      } else if (isHovered) {
+        return CanvasDesignTokens.shadows.nodeHover
+      } else if (isDragging) {
+        return CanvasDesignTokens.shadows.nodeActive
+      } else {
+        return style.shadow || CanvasDesignTokens.shadows.node
+      }
+    }
+    
+
+    const getStatusColor = () => {
+      return getNodeStateColor(status)
+    }
+    
+
+    const nodeStyle = computed(() => ({
+      borderLeft: getBorderStyle(),
+      background: getBackgroundStyle(),
+      boxShadow: getShadowStyle(),
+      borderRadius: style.borderRadius || CanvasDesignTokens.borderRadius.node,
+      opacity: isDisabled ? 0.6 : (style.opacity || 1),
+      width: style.width ? `${style.width}px` : 'auto',
+      height: style.height ? `${style.height}px` : 'auto',
+      zIndex: style.zIndex || CanvasDesignTokens.zIndex.nodes
+    }))
+    
+
+    const getTextColor = () => {
+      return theme?.textColor || '#374151'
+    }
+    
     return () => (
-      <div class={styles['dag-node']}>
-        <span class={styles['dag-node-label']}>{name}</span>
+      <div
+        class={nodeClass.value}
+        style={nodeStyle.value}
+      >
+        {/* 节点图标 */}
+        
+        {/* 节点标签 */}
+        <NTooltip trigger='hover' placement='top'>
+          {{
+            trigger: () => (
+              <div class={styles['dag-node-label']} style={{ color: 
getTextColor() }}>
+                <span>{name}</span>
+              </div>
+            ),
+            default: () => (
+              <div>
+                <div><strong>{name}</strong></div>
+                <div style={{ fontSize: '12px', opacity: 0.8 }}>
+                  类型: {actualNodeType.value === 'source' ? '数据源' : 
actualNodeType.value === 'sink' ? '数据目标' : '数据转换'}
+                </div>
+                {status !== 'idle' && (
+                  <div style={{ fontSize: '12px', opacity: 0.8 }}>
+                    状态: {status === 'running' ? '运行中' : status === 'success' ? 
'成功' : status === 'error' ? '错误' : status === 'warning' ? '警告' : status}
+                  </div>
+                )}
+                {statusMessage && (
+                  <div style={{ fontSize: '12px', opacity: 0.8 }}>
+                    信息: {statusMessage}
+                  </div>
+                )}
+                {metadata.description && (
+                  <div style={{ fontSize: '12px', opacity: 0.8 }}>
+                    描述: {metadata.description}
+                  </div>
+                )}
+                {metadata.tags && metadata.tags.length > 0 && (
+                  <div style={{ fontSize: '12px', opacity: 0.8 }}>
+                    标签: {metadata.tags.join(', ')}
+                  </div>
+                )}
+              </div>
+            )
+          }}
+        </NTooltip>
+        
+        {/* 状态指示器 */}
+        
+        {/* 进度条 - 仅在运行状态显示 */}
+        {status === 'running' && progress > 0 && (
+          <div class={styles['dag-node-progress']}>
+            <NProgress 
+              type="line" 
+              percentage={progress} 
+              height={4}
+              color={getNodeStateColor('running')}
+              railColor="rgba(100, 116, 139, 0.2)"
+            />
+          </div>
+        )}
+        
+        {/* 发光效果 - 用于成功状态 */}
+        {animations.glow && (
+          <div class={styles['dag-node-glow']} />
+        )}
+        
+        {/* 不再使用自定义连接点,改用X6原生连接点 */}
       </div>
     )
   }
diff --git 
a/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/responsive-mixins.scss
 
b/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/responsive-mixins.scss
new file mode 100644
index 000000000..d4ed0d1b2
--- /dev/null
+++ 
b/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/responsive-mixins.scss
@@ -0,0 +1,308 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+$canvas-breakpoints: (
+  'mobile': 768px,
+  'tablet': 1024px,
+  'desktop': 1440px,
+  'wide': 1920px
+) !default;
+
+
+@mixin canvas-respond-to($breakpoint) {
+  @if map-has-key($canvas-breakpoints, $breakpoint) {
+    @media (min-width: map-get($canvas-breakpoints, $breakpoint)) {
+      @content;
+    }
+  } @else {
+    @warn "Unknown breakpoint: #{$breakpoint}";
+  }
+}
+
+
+@mixin canvas-respond-to-max($breakpoint) {
+  @if map-has-key($canvas-breakpoints, $breakpoint) {
+    @media (max-width: map-get($canvas-breakpoints, $breakpoint) - 1px) {
+      @content;
+    }
+  } @else {
+    @warn "Unknown breakpoint: #{$breakpoint}";
+  }
+}
+
+
+@mixin canvas-respond-between($min-breakpoint, $max-breakpoint) {
+  @if map-has-key($canvas-breakpoints, $min-breakpoint) and 
map-has-key($canvas-breakpoints, $max-breakpoint) {
+    @media (min-width: map-get($canvas-breakpoints, $min-breakpoint)) and 
(max-width: map-get($canvas-breakpoints, $max-breakpoint) - 1px) {
+      @content;
+    }
+  } @else {
+    @warn "Unknown breakpoints: #{$min-breakpoint} or #{$max-breakpoint}";
+  }
+}
+
+
+@mixin canvas-high-dpi {
+  @media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
+    @content;
+  }
+}
+
+
+@mixin canvas-touch-device {
+  @media (hover: none) and (pointer: coarse) {
+    @content;
+  }
+}
+
+
+@mixin canvas-no-touch {
+  @media (hover: hover) and (pointer: fine) {
+    @content;
+  }
+}
+
+
+@mixin canvas-node-responsive {
+
+  @include canvas-respond-to-max('mobile') {
+    width: var(--canvas-node-width);
+    height: var(--canvas-node-height);
+    font-size: var(--canvas-font-size-node);
+    padding: var(--canvas-spacing-sm);
+    
+    .canvas-node-icon {
+      width: 16px;
+      height: 16px;
+    }
+  }
+  
+
+  @include canvas-respond-between('mobile', 'desktop') {
+    width: calc(var(--canvas-node-width) * 0.9);
+    height: calc(var(--canvas-node-height) * 0.95);
+  }
+  
+
+  @include canvas-respond-to('desktop') {
+    width: var(--canvas-node-width);
+    height: var(--canvas-node-height);
+  }
+  
+
+  @include canvas-respond-to('wide') {
+    width: calc(var(--canvas-node-width) * 1.1);
+    height: calc(var(--canvas-node-height) * 1.1);
+    font-size: calc(var(--canvas-font-size-node) * 1.1);
+  }
+}
+
+
+@mixin canvas-minimap-responsive {
+
+  @include canvas-respond-to-max('mobile') {
+    width: calc(var(--canvas-minimap-width) * 0.75);
+    height: calc(var(--canvas-minimap-height) * 0.75);
+    right: var(--canvas-spacing-md);
+    bottom: var(--canvas-spacing-md);
+    
+
+    @media (max-width: 480px) {
+      display: none;
+    }
+  }
+  
+
+  @include canvas-respond-between('mobile', 'desktop') {
+    width: calc(var(--canvas-minimap-width) * 0.9);
+    height: calc(var(--canvas-minimap-height) * 0.9);
+  }
+  
+
+  @include canvas-respond-to('desktop') {
+    width: var(--canvas-minimap-width);
+    height: var(--canvas-minimap-height);
+  }
+  
+
+  @include canvas-respond-to('wide') {
+    width: calc(var(--canvas-minimap-width) * 1.1);
+    height: calc(var(--canvas-minimap-height) * 1.1);
+  }
+}
+
+
+@mixin canvas-connection-responsive {
+
+  @include canvas-respond-to-max('mobile') {
+    stroke-width: calc(var(--canvas-connection-stroke-width) * 1.5);
+    
+    &:hover {
+      stroke-width: calc(var(--canvas-connection-stroke-width-hover) * 1.5);
+    }
+  }
+  
+
+  @include canvas-touch-device {
+    stroke-width: calc(var(--canvas-connection-stroke-width) * 1.2);
+    
+
+    &::before {
+      content: '';
+      position: absolute;
+      top: -10px;
+      bottom: -10px;
+      left: -10px;
+      right: -10px;
+      pointer-events: all;
+      background: transparent;
+    }
+  }
+}
+
+
+@mixin canvas-container-responsive {
+
+  @include canvas-respond-to-max('mobile') {
+    padding: var(--canvas-spacing-sm);
+    
+    .canvas-toolbar {
+      flex-direction: column;
+      gap: var(--canvas-spacing-sm);
+    }
+    
+    .canvas-sidebar {
+      position: fixed;
+      bottom: 0;
+      left: 0;
+      right: 0;
+      height: 40vh;
+      transform: translateY(100%);
+      transition: transform var(--canvas-animation-normal) 
var(--canvas-easing-default);
+      
+      &.is-open {
+        transform: translateY(0);
+      }
+    }
+  }
+  
+
+  @include canvas-respond-between('mobile', 'desktop') {
+    .canvas-sidebar {
+      width: 280px;
+    }
+  }
+  
+
+  @include canvas-respond-to('desktop') {
+    .canvas-sidebar {
+      width: 320px;
+    }
+  }
+}
+
+
+@mixin canvas-typography-responsive {
+
+  @include canvas-respond-to-max('mobile') {
+    font-size: calc(var(--canvas-font-size-node) * 0.9);
+    line-height: calc(var(--canvas-line-height-node) * 1.1);
+  }
+  
+
+  @include canvas-high-dpi {
+    font-weight: calc(var(--canvas-font-weight-node) - 100);
+  }
+  
+
+  @include canvas-respond-to('wide') {
+    font-size: calc(var(--canvas-font-size-node) * 1.1);
+  }
+}
+
+
+@mixin canvas-spacing-responsive($property: 'padding') {
+
+  @include canvas-respond-to-max('mobile') {
+    #{$property}: calc(var(--canvas-spacing-md) * 0.75);
+  }
+  
+
+  @include canvas-respond-between('mobile', 'desktop') {
+    #{$property}: calc(var(--canvas-spacing-md) * 0.9);
+  }
+  
+
+  @include canvas-respond-to('desktop') {
+    #{$property}: var(--canvas-spacing-md);
+  }
+  
+
+  @include canvas-respond-to('wide') {
+    #{$property}: calc(var(--canvas-spacing-md) * 1.2);
+  }
+}
+
+
+@mixin canvas-shadow-responsive {
+
+  @include canvas-respond-to-max('mobile') {
+    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
+    
+    &:hover {
+      box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
+    }
+  }
+  
+
+  @include canvas-respond-to('desktop') {
+    box-shadow: var(--canvas-shadow-node);
+    
+    &:hover {
+      box-shadow: var(--canvas-shadow-node-hover);
+    }
+  }
+  
+
+  @include canvas-high-dpi {
+    box-shadow: 0 6px 16px rgba(0, 0, 0, 0.1);
+    
+    &:hover {
+      box-shadow: 0 12px 32px rgba(0, 0, 0, 0.15);
+    }
+  }
+}
+
+
+@mixin canvas-animation-responsive {
+
+  @include canvas-respond-to-max('mobile') {
+    transition-duration: calc(var(--canvas-animation-normal) * 0.8);
+  }
+  
+
+  @media (prefers-reduced-motion: reduce) {
+    transition: none !important;
+    animation: none !important;
+  }
+  
+
+  @media (update: slow) {
+    transition-duration: calc(var(--canvas-animation-fast) * 0.5);
+    animation-duration: calc(var(--canvas-animation-normal) * 0.5);
+  }
+}
\ No newline at end of file
diff --git 
a/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/theme-manager.ts
 
b/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/theme-manager.ts
new file mode 100644
index 000000000..30dfa26c7
--- /dev/null
+++ 
b/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/theme-manager.ts
@@ -0,0 +1,175 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { ref, computed, watch } from 'vue'
+import { CanvasDesignTokens, type Theme, type NodeType } from './design-tokens'
+
+
+export class CanvasThemeManager {
+  private currentTheme = ref<Theme>('light')
+  
+  constructor() {
+
+    this.initTheme()
+    
+
+    watch(this.currentTheme, (newTheme) => {
+      this.applyTheme(newTheme)
+    })
+  }
+  
+
+  private initTheme() {
+
+    const savedTheme = localStorage.getItem('canvas-theme') as Theme
+    const systemPrefersDark = window.matchMedia('(prefers-color-scheme: 
dark)').matches
+    
+    this.currentTheme.value = savedTheme || (systemPrefersDark ? 'dark' : 
'light')
+    
+
+    window.matchMedia('(prefers-color-scheme: 
dark)').addEventListener('change', (e) => {
+      if (!localStorage.getItem('canvas-theme')) {
+        this.currentTheme.value = e.matches ? 'dark' : 'light'
+      }
+    })
+  }
+  
+
+  private applyTheme(theme: Theme) {
+    const root = document.documentElement
+    
+
+    root.setAttribute('data-theme', theme)
+    
+
+    localStorage.setItem('canvas-theme', theme)
+    
+
+    window.dispatchEvent(new CustomEvent('canvas-theme-change', {
+      detail: { theme }
+    }))
+  }
+  
+
+  toggleTheme() {
+    this.currentTheme.value = this.currentTheme.value === 'light' ? 'dark' : 
'light'
+  }
+  
+
+  setTheme(theme: Theme) {
+    this.currentTheme.value = theme
+  }
+  
+
+  get theme() {
+    return this.currentTheme.value
+  }
+  
+
+  get themeRef() {
+    return this.currentTheme
+  }
+  
+
+  get canvasColors() {
+    return computed(() => 
CanvasDesignTokens.colors.canvas[this.currentTheme.value])
+  }
+  
+
+  getNodeColors(type: NodeType) {
+    return CanvasDesignTokens.colors.nodes[type]
+  }
+  
+
+  get connectionColors() {
+    return CanvasDesignTokens.colors.connections
+  }
+  
+
+  get minimapColors() {
+    return computed(() => ({
+      background: this.currentTheme.value === 'light' 
+        ? CanvasDesignTokens.colors.minimap.background
+        : CanvasDesignTokens.colors.minimap.backgroundDark,
+      border: this.currentTheme.value === 'light'
+        ? CanvasDesignTokens.colors.minimap.border
+        : CanvasDesignTokens.colors.minimap.borderDark,
+      viewport: CanvasDesignTokens.colors.minimap.viewport,
+      viewportBorder: CanvasDesignTokens.colors.minimap.viewportBorder
+    }))
+  }
+  
+
+  getCSSVariable(variableName: string): string {
+    return getComputedStyle(document.documentElement)
+      .getPropertyValue(`--canvas-${variableName}`)
+      .trim()
+  }
+  
+
+  setCSSVariable(variableName: string, value: string) {
+    document.documentElement.style.setProperty(`--canvas-${variableName}`, 
value)
+  }
+  
+
+  get animations() {
+    return CanvasDesignTokens.animations
+  }
+  
+
+  get sizes() {
+    return CanvasDesignTokens.sizes
+  }
+  
+
+  get spacing() {
+    return CanvasDesignTokens.spacing
+  }
+  
+
+  get isDark() {
+    return computed(() => this.currentTheme.value === 'dark')
+  }
+  
+
+  get isLight() {
+    return computed(() => this.currentTheme.value === 'light')
+  }
+}
+
+
+export const canvasThemeManager = new CanvasThemeManager()
+
+
+export function useCanvasTheme() {
+  return {
+    theme: canvasThemeManager.themeRef,
+    isDark: canvasThemeManager.isDark,
+    isLight: canvasThemeManager.isLight,
+    canvasColors: canvasThemeManager.canvasColors,
+    minimapColors: canvasThemeManager.minimapColors,
+    connectionColors: canvasThemeManager.connectionColors,
+    animations: canvasThemeManager.animations,
+    sizes: canvasThemeManager.sizes,
+    spacing: canvasThemeManager.spacing,
+    toggleTheme: () => canvasThemeManager.toggleTheme(),
+    setTheme: (theme: Theme) => canvasThemeManager.setTheme(theme),
+    getNodeColors: (type: NodeType) => canvasThemeManager.getNodeColors(type),
+    getCSSVariable: (name: string) => canvasThemeManager.getCSSVariable(name),
+    setCSSVariable: (name: string, value: string) => 
canvasThemeManager.setCSSVariable(name, value)
+  }
+}
\ No newline at end of file
diff --git 
a/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/use-dag-add-shape.ts
 
b/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/use-dag-add-shape.ts
index ada1c6d67..d31eb3e1a 100644
--- 
a/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/use-dag-add-shape.ts
+++ 
b/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/use-dag-add-shape.ts
@@ -114,28 +114,33 @@ export function useDagAddShape(
     })
 
     nodes[i].child.forEach((n: any) => {
+
+      const nodeType = (n.nodeType && n.nodeType.toLowerCase()) || 
+        (n.label.toLowerCase().includes('source') ? 'source' : 
+         n.label.toLowerCase().includes('sink') ? 'sink' : 'transform');
+      
+
+      const portItems = [];
+
+      
       group.addChild(
         graph.addNode({
           id: n.id,
-          // x: 50,
-          // y: 50,
-          // width: 120,
-          // height: 40,
+          x: 50,
+          y: 50,
+          width: 180,
+          height: 44,
           shape: DagNodeName,
-          // label: n.label,
           zIndex: 10,
-          // attrs: {
-          //   body: {
-          //     stroke: 'none',
-          //     fill: '#858585'
-          //   },
-          //   label: {
-          //     fill: '#fff',
-          //     fontSize: 12
-          //   }
-          // },
+          ports: {
+            items: portItems
+          },
           data: {
-            name: n.label
+            name: n.label,
+            nodeType: nodeType,
+            connectorType: n.label,
+            status: 'idle',
+            vertexId: n.vertexId
           }
         })
       )
@@ -146,12 +151,18 @@ export function useDagAddShape(
     graph.addEdge({
       shape: DagEdgeName,
       source: {
-        cell: e.source
+        cell: e.source,
+        port: 'output'
       },
       target: {
-        cell: e.target
+        cell: e.target,
+        port: 'input'
       },
-      id: e.id
+      id: e.id,
+      zIndex: 5,
+      data: {
+        animated: true
+      }
     })
   })
 }
diff --git 
a/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/use-dag-edge.ts
 
b/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/use-dag-edge.ts
index 15a3f4f41..52e42ed40 100644
--- 
a/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/use-dag-edge.ts
+++ 
b/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/use-dag-edge.ts
@@ -15,13 +15,294 @@
  * limitations under the License.
  */
 
-export function useDagEdge() {
+import { CanvasDesignTokens } from './design-tokens'
+
+
+export interface ModernEdgeData {
+  id: string
+  source: string
+  target: string
+  
+
+  style?: {
+    stroke?: string
+    strokeWidth?: number
+    strokeDasharray?: string
+    animated?: boolean
+  }
+  
+
+  status?: 'normal' | 'active' | 'error' | 'warning' | 'success'
+  
+
+  dataFlow?: {
+    direction?: 'forward' | 'backward' | 'bidirectional'
+    speed?: 'slow' | 'normal' | 'fast'
+    volume?: number
+  }
+  
+
+  isSelected?: boolean
+  isHovered?: boolean
+  
+
+  label?: string
+  
+
+  metadata?: {
+    [key: string]: any
+  }
+}
+
+
+export interface EdgeOptions {
+  router?: 'normal' | 'smooth' | 'orthogonal'
+  connector?: 'normal' | 'rounded' | 'smooth'
+  animated?: boolean
+  showArrow?: boolean
+  interactive?: boolean
+}
+
+export function useDagEdge(options: EdgeOptions = {}) {
+  const defaultOptions: EdgeOptions = {
+    router: 'smooth',
+    connector: 'smooth',
+    animated: false,
+    showArrow: true,
+    interactive: true
+  }
+  
+  const finalOptions = { ...defaultOptions, ...options }
+  
   return {
+    inherit: 'edge',
+    
+
+    router: {
+      name: 'orth'
+    },
+    connector: {
+      name: 'normal'
+    },
     attrs: {
       line: {
-        stroke: '#C2C8D5',
-        strokeWidth: 1
+        stroke: CanvasDesignTokens.colors.connections.default,
+        strokeWidth: CanvasDesignTokens.sizes.connection.strokeWidth,
+        strokeLinecap: 'round',
+        strokeLinejoin: 'round',
+        fill: 'none',
+        class: 'modern-edge',
+        
+
+        ...(finalOptions.animated && {
+          strokeDasharray: '8,4',
+          class: 'modern-edge modern-edge-animated'
+        })
+      },
+      
+
+      ...(finalOptions.showArrow && {
+        targetMarker: {
+          name: 'block',
+          size: CanvasDesignTokens.sizes.connection.arrowSize,
+          fill: CanvasDesignTokens.colors.connections.default,
+          stroke: CanvasDesignTokens.colors.connections.default,
+          strokeWidth: 1,
+          class: 'modern-edge-arrow'
+        }
+      }),
+      
+
+      ...(finalOptions.interactive && {
+        wrap: {
+          stroke: 'transparent',
+          strokeWidth: 12,
+          fill: 'none',
+          cursor: 'pointer',
+          class: 'modern-edge-interaction'
+        }
+      })
+    },
+    
+
+    defaultLabel: {
+      markup: [
+        {
+          tagName: 'rect',
+          selector: 'body'
+        },
+        {
+          tagName: 'text',
+          selector: 'label'
+        }
+      ],
+      attrs: {
+        body: {
+          ref: 'label',
+          fill: 'rgba(255, 255, 255, 0.95)',
+          stroke: CanvasDesignTokens.colors.connections.default,
+          strokeWidth: 1,
+          rx: 4,
+          ry: 4,
+          refWidth: '100%',
+          refHeight: '100%',
+          refX: '-50%',
+          refY: '-50%',
+          class: 'modern-edge-tooltip-bg'
+        },
+        label: {
+          fontSize: CanvasDesignTokens.typography.tooltip.fontSize,
+          fontWeight: CanvasDesignTokens.typography.tooltip.fontWeight,
+          fill: CanvasDesignTokens.colors.connections.default,
+          textAnchor: 'middle',
+          textVerticalAnchor: 'middle',
+          class: 'modern-edge-label'
+        }
+      },
+      position: {
+        distance: 0.5,
+        offset: 0
+      }
+    },
+    
+
+    events: {
+      'edge:mouseenter': ({ edge }: any) => {
+        const data = edge.getData() || {}
+        edge.setData({ ...data, isHovered: true })
+        
+
+        edge.attr('line/class', 'modern-edge modern-edge:hover')
+        edge.attr('line/stroke', CanvasDesignTokens.colors.connections.hover)
+        edge.attr('line/strokeWidth', 
CanvasDesignTokens.sizes.connection.strokeWidthHover)
+      },
+      
+      'edge:mouseleave': ({ edge }: any) => {
+        const data = edge.getData() || {}
+        edge.setData({ ...data, isHovered: false })
+        
+
+        const isSelected = data.isSelected
+        edge.attr('line/class', isSelected ? 'modern-edge is-selected' : 
'modern-edge')
+        edge.attr('line/stroke', isSelected 
+          ? CanvasDesignTokens.colors.connections.selected 
+          : CanvasDesignTokens.colors.connections.default)
+        edge.attr('line/strokeWidth', isSelected 
+          ? CanvasDesignTokens.sizes.connection.strokeWidthHover
+          : CanvasDesignTokens.sizes.connection.strokeWidth)
+      },
+      
+      'edge:selected': ({ edge }: any) => {
+        const data = edge.getData() || {}
+        edge.setData({ ...data, isSelected: true })
+        
+
+        edge.attr('line/class', 'modern-edge is-selected')
+        edge.attr('line/stroke', 
CanvasDesignTokens.colors.connections.selected)
+        edge.attr('line/strokeWidth', 
CanvasDesignTokens.sizes.connection.strokeWidthHover)
+      },
+      
+      'edge:unselected': ({ edge }: any) => {
+        const data = edge.getData() || {}
+        edge.setData({ ...data, isSelected: false })
+        
+
+        edge.attr('line/class', 'modern-edge')
+        edge.attr('line/stroke', CanvasDesignTokens.colors.connections.default)
+        edge.attr('line/strokeWidth', 
CanvasDesignTokens.sizes.connection.strokeWidth)
       }
     }
   }
 }
+
+
+export function createEdgeData(
+  id: string,
+  source: string,
+  target: string,
+  options: Partial<ModernEdgeData> = {}
+): ModernEdgeData {
+  return {
+    id,
+    source,
+    target,
+    status: 'normal',
+    isSelected: false,
+    isHovered: false,
+    style: {
+      animated: false
+    },
+    dataFlow: {
+      direction: 'forward',
+      speed: 'normal'
+    },
+    metadata: {},
+    ...options
+  }
+}
+
+
+export function updateEdgeStatus(
+  edge: any,
+  status: 'normal' | 'active' | 'error' | 'warning' | 'success'
+) {
+  const data = edge.getData() || {}
+  edge.setData({ ...data, status })
+  
+
+  const statusColors = {
+    normal: CanvasDesignTokens.colors.connections.default,
+    active: CanvasDesignTokens.colors.connections.animated,
+    error: CanvasDesignTokens.colors.nodes.states.error,
+    warning: CanvasDesignTokens.colors.nodes.states.warning,
+    success: CanvasDesignTokens.colors.nodes.states.success
+  }
+  
+  const statusClasses = {
+    normal: 'modern-edge',
+    active: 'modern-edge is-active',
+    error: 'modern-edge is-error',
+    warning: 'modern-edge is-warning',
+    success: 'modern-edge is-success'
+  }
+  
+  edge.attr('line/stroke', statusColors[status])
+  edge.attr('line/class', statusClasses[status])
+  
+
+  if (status === 'error') {
+    edge.attr('line/strokeDasharray', '5,5')
+  } else if (status === 'warning') {
+    edge.attr('line/strokeDasharray', '3,3')
+  } else {
+    edge.attr('line/strokeDasharray', 'none')
+  }
+}
+
+
+export function enableDataFlowAnimation(
+  edge: any,
+  speed: 'slow' | 'normal' | 'fast' = 'normal'
+) {
+  const data = edge.getData() || {}
+  edge.setData({ 
+    ...data, 
+    style: { 
+      ...data.style, 
+      animated: true 
+    },
+    dataFlow: {
+      ...data.dataFlow,
+      speed
+    }
+  })
+  
+  const speedClasses = {
+    slow: 'modern-edge modern-edge-animated flow-slow',
+    normal: 'modern-edge modern-edge-animated',
+    fast: 'modern-edge modern-edge-animated flow-fast'
+  }
+  
+  edge.attr('line/class', speedClasses[speed])
+  edge.attr('line/strokeDasharray', '8,4')
+}
diff --git 
a/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/use-dag-graph.ts
 
b/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/use-dag-graph.ts
index ebf95d8a3..9b1bc84c6 100644
--- 
a/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/use-dag-graph.ts
+++ 
b/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/use-dag-graph.ts
@@ -16,33 +16,146 @@
  */
 
 import { Graph } from '@antv/x6'
-import { DagEdgeName } from './dag-setting'
+import { useCanvasTheme } from './theme-manager'
+
+
+export interface CanvasOptions {
+  enableGrid?: boolean
+  enableMinimap?: boolean
+  enableScroller?: boolean
+  enableSelection?: boolean
+  enableKeyboard?: boolean
+  enableClipboard?: boolean
+  enableHistory?: boolean
+  gridSize?: number
+  minimapSize?: { width: number; height: number }
+  background?: {
+    color?: string
+    image?: string
+    size?: string
+    position?: string
+  }
+}
 
 export function useDagGraph(
   graph: any,
   dagContainer: HTMLElement,
-  minimapContainer: HTMLElement
+  minimapContainer: HTMLElement,
+  options: CanvasOptions = {}
 ) {
-  return new Graph({
+
+  const graphInstance = new Graph({
     container: dagContainer,
-    scroller: true,
+    autoResize: true,
+    
+
     grid: {
-      size: 10,
-      visible: true
+      size: 20,
+      visible: true,
+      type: 'dot'
     },
-    connecting: {
-      // router: 'orth',
-      allowBlank: false,
-      allowLoop: false,
-      createEdge() {
-        return graph.value?.createEdge({ shape: DagEdgeName })
-      }
+    
+
+    background: {
+      color: '#FAFAFA'
     },
-    minimap: {
+    
+
+    minimap: minimapContainer ? {
       enabled: true,
+      container: minimapContainer,
       width: 200,
       height: 120,
-      container: minimapContainer
+      padding: 10
+    } : false,
+    
+
+    selecting: {
+      enabled: true,
+      multiple: true,
+      rubberband: true,
+      movable: true
+    },
+    
+
+    connecting: {
+      allowBlank: false,
+      allowLoop: false,
+      allowNode: false,
+      allowEdge: false,
+      allowPort: true
     }
   })
+  
+  console.log('Graph instance created:', graphInstance)
+  console.log('Container element:', dagContainer)
+  
+
+  const { canvasColors } = useCanvasTheme()
+  const updateTheme = () => {
+    const colors = canvasColors.value
+    
+
+    graphInstance.drawBackground({
+      color: colors.background
+    })
+  }
+  
+
+  window.addEventListener('canvas-theme-change', updateTheme)
+  
+
+  graphInstance.on('scale', ({ sx }: any) => {
+    const container = dagContainer
+    const gridElement = container.querySelector('.x6-graph-grid')
+    
+    if (gridElement) {
+
+      let opacity = 1
+      if (sx < 0.5) {
+        opacity = 0.3
+        gridElement.classList.add('zoom-small')
+      } else if (sx > 2) {
+        opacity = 0.6
+        gridElement.classList.add('zoom-large')
+      } else if (sx > 4) {
+        opacity = 0.4
+        gridElement.classList.add('zoom-extra-large')
+      } else {
+        gridElement.classList.remove('zoom-small', 'zoom-large', 
'zoom-extra-large')
+      }
+      
+      ;(gridElement as HTMLElement).style.opacity = opacity.toString()
+    }
+  })
+  
+
+  let frameCount = 0
+  let lastTime = performance.now()
+  
+  const monitorPerformance = () => {
+    frameCount++
+    const currentTime = performance.now()
+    
+    if (currentTime - lastTime >= 1000) {
+      const fps = Math.round((frameCount * 1000) / (currentTime - lastTime))
+      
+
+      if (fps < 30) {
+        dagContainer.classList.add('canvas-performance-mode')
+      } else {
+        dagContainer.classList.remove('canvas-performance-mode')
+      }
+      
+      frameCount = 0
+      lastTime = currentTime
+    }
+    
+    requestAnimationFrame(monitorPerformance)
+  }
+  
+
+  requestAnimationFrame(monitorPerformance)
+  
+  return graphInstance
 }
diff --git 
a/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/use-dag-layout.ts
 
b/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/use-dag-layout.ts
index 5dc800bfb..e55d95c92 100644
--- 
a/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/use-dag-layout.ts
+++ 
b/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/use-dag-layout.ts
@@ -22,25 +22,31 @@ import { DagEdgeName, DagNodeName } from './dag-setting'
 const updateParentNodePosition = (nodes: any, node: any) => {
   if (node.children && node.children.length) {
     const children = node.children
-    let minX = Number.MAX_VALUE
-    let maxX = 0
-    let minY = Number.MAX_VALUE
-    let maxY = 0
-    nodes
-      .filter((node: any) => children.includes(node.id))
-      .map((node: any) => {
-        minX = Math.min(minX, node.x)
-        maxX = Math.max(maxX, node.x)
-        minY = Math.min(minY, node.y)
-        maxY = Math.max(maxY, node.y)
-      })
+    const childNodes = nodes.filter((n: any) => children.includes(n.id));
+    if (childNodes.length === 0) return;
 
-    node.x = minX - 20
-    node.y = minY - 20
+    let minX = Infinity, maxX = -Infinity, minY = Infinity, maxY = -Infinity;
+
+    childNodes.forEach((child: any) => {
+        const childX = child.x;
+        const childY = child.y;
+        const childWidth = child.size?.width || 180;
+        const childHeight = child.size?.height || 44;
+
+        minX = Math.min(minX, childX);
+        minY = Math.min(minY, childY);
+        maxX = Math.max(maxX, childX + childWidth);
+        maxY = Math.max(maxY, childY + childHeight);
+    });
+
+    const padding = 40;
+
+    node.x = minX - padding;
+    node.y = minY - padding;
     node.size = {
-      width: maxX - minX + 200,
-      height: maxY - minY + 80
-    }
+      width: (maxX - minX) + (2 * padding),
+      height: (maxY - minY) + (2 * padding)
+    };
   }
 }
 
diff --git 
a/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/use-dag-node.ts
 
b/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/use-dag-node.ts
index 9aeaff364..08f22e938 100644
--- 
a/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/use-dag-node.ts
+++ 
b/seatunnel-ui/src/views/task/synchronization-instance/detail/dag/use-dag-node.ts
@@ -17,17 +17,553 @@
 
 import '@antv/x6-vue-shape'
 import Node from './node'
-import { createVNode } from 'vue'
+import { CanvasDesignTokens, getNodeColors, getNodeStateColor, NodeType, 
NodeState } from './design-tokens'
 
-export function useDagNode() {
+
+export interface ModernNodeData {
+
+  id: string
+  name: string
+  nodeType?: NodeType
+  connectorType?: string
+  
+
+  theme?: {
+    primaryColor: string
+    secondaryColor: string
+    gradient: string
+    borderColor: string
+    textColor: string
+    iconColor?: string
+  }
+  
+
+  status?: NodeState
+  progress?: number
+  statusMessage?: string
+  
+
+  isSelected?: boolean
+  isHovered?: boolean
+  isDragging?: boolean
+  isDisabled?: boolean
+  
+
+  animations?: {
+    entrance?: boolean
+    pulse?: boolean
+    glow?: boolean
+    shake?: boolean
+  }
+  
+
+  style?: {
+    width?: number
+    height?: number
+    borderRadius?: string
+    shadow?: string
+    opacity?: number
+    zIndex?: number
+  }
+  
+
+  metadata?: {
+    vertexId?: string
+    description?: string
+    tags?: string[]
+    icon?: string
+    createdAt?: string
+    updatedAt?: string
+    [key: string]: any
+  }
+}
+
+
+export interface NodeOptions {
+  width?: number
+  height?: number
+  minWidth?: number
+  maxWidth?: number
+  resizable?: boolean
+  rotatable?: boolean
+  selectable?: boolean
+  movable?: boolean
+  portVisible?: boolean
+  animationEnabled?: boolean
+  themeEnabled?: boolean
+}
+
+
+export function useDagNode(options: NodeOptions = {}) {
+  const defaultOptions: NodeOptions = {
+    width: CanvasDesignTokens.sizes.node.width,
+    height: CanvasDesignTokens.sizes.node.height,
+    minWidth: CanvasDesignTokens.sizes.node.minWidth,
+    maxWidth: CanvasDesignTokens.sizes.node.maxWidth,
+    resizable: false,
+    rotatable: false,
+    selectable: true,
+    movable: true,
+    portVisible: true,
+    animationEnabled: true,
+    themeEnabled: true
+  }
+  
+  const finalOptions = { ...defaultOptions, ...options }
+  
   return {
     inherit: 'vue-shape',
-    width: 150,
-    height: 36,
-    component: {
-      render: () => {
-        return createVNode(Node)
+    width: finalOptions.width,
+    height: finalOptions.height,
+    resizing: finalOptions.resizable ? {
+      enabled: true,
+      minWidth: finalOptions.minWidth,
+      maxWidth: finalOptions.maxWidth,
+      preserveAspectRatio: false
+    } : false,
+    rotating: finalOptions.rotatable,
+    selecting: finalOptions.selectable,
+    moving: finalOptions.movable,
+    
+
+    attrs: {
+      body: {
+        stroke: 'transparent',
+        fill: 'transparent',
+        rx: parseInt(CanvasDesignTokens.borderRadius.node),
+        ry: parseInt(CanvasDesignTokens.borderRadius.node)
+      }
+    },
+    
+
+    ports: {
+      groups: {
+        input: {
+          position: 'left',
+          attrs: {
+            circle: {
+              r: 5,
+              magnet: true,
+              stroke: CanvasDesignTokens.colors.connections.default,
+              strokeWidth: 2,
+              fill: '#fff',
+              opacity: 0
+            }
+          }
+        },
+        output: {
+          position: 'right',
+          attrs: {
+            circle: {
+              r: 5,
+              magnet: true,
+              stroke: CanvasDesignTokens.colors.connections.default,
+              strokeWidth: 2,
+              fill: '#fff',
+              opacity: 0
+            }
+          }
+        }
+      },
+
+      items: []
+    },
+    
+
+    component: Node,
+    
+
+    events: {
+
+      'node:mouseenter': ({ node }: any) => {
+        const data = node.getData() as ModernNodeData
+        if (data.isDisabled) return
+        
+
+        node.setData({ 
+          ...data, 
+          isHovered: true,
+
+          animations: finalOptions.animationEnabled ? {
+            ...data.animations,
+            glow: data.status === 'success' ? true : data.animations?.glow
+          } : data.animations
+        })
+        
+
+        if (finalOptions.portVisible) {
+
+          const ports = node.getPorts() || [];
+          const hasInputPort = ports.some((port: any) => port.id === 'input');
+          const hasOutputPort = ports.some((port: any) => port.id === 
'output');
+          
+          if (hasInputPort) {
+            node.setPortProp('input', 'attrs/circle/opacity', 1);
+            node.setPortProp('input', 'attrs/circle/magnet', true);
+          }
+          if (hasOutputPort) {
+            node.setPortProp('output', 'attrs/circle/opacity', 1);
+            node.setPortProp('output', 'attrs/circle/magnet', true);
+          }
+        }
+      },
+      
+
+      'node:mouseleave': ({ node }: any) => {
+        const data = node.getData() as ModernNodeData
+        if (data.isDisabled) return
+        
+
+        node.setData({ 
+          ...data, 
+          isHovered: false,
+
+          animations: finalOptions.animationEnabled ? {
+            ...data.animations,
+            glow: data.status === 'success'
+          } : data.animations
+        })
+        
+
+        if (finalOptions.portVisible && !data.isSelected) {
+
+          const ports = node.getPorts() || [];
+          const hasInputPort = ports.some((port: any) => port.id === 'input');
+          const hasOutputPort = ports.some((port: any) => port.id === 
'output');
+          
+          if (hasInputPort) {
+            node.setPortProp('input', 'attrs/circle/opacity', 0);
+          }
+          if (hasOutputPort) {
+            node.setPortProp('output', 'attrs/circle/opacity', 0);
+          }
+        }
+      },
+      
+
+      'node:selected': ({ node }: any) => {
+        const data = node.getData() as ModernNodeData
+        if (data.isDisabled) return
+        
+
+        node.setData({ ...data, isSelected: true })
+        
+
+        if (finalOptions.portVisible) {
+
+          const ports = node.getPorts() || [];
+          const hasInputPort = ports.some((port: any) => port.id === 'input');
+          const hasOutputPort = ports.some((port: any) => port.id === 
'output');
+          
+          if (hasInputPort) {
+            node.setPortProp('input', 'attrs/circle/opacity', 1);
+            node.setPortProp('input', 'attrs/circle/magnet', true);
+          }
+          if (hasOutputPort) {
+            node.setPortProp('output', 'attrs/circle/opacity', 1);
+            node.setPortProp('output', 'attrs/circle/magnet', true);
+          }
+        }
+      },
+      
+
+      'node:unselected': ({ node }: any) => {
+        const data = node.getData() as ModernNodeData
+        
+
+        node.setData({ ...data, isSelected: false })
+        
+
+        if (finalOptions.portVisible && !data.isHovered) {
+
+          const ports = node.getPorts() || [];
+          const hasInputPort = ports.some((port: any) => port.id === 'input');
+          const hasOutputPort = ports.some((port: any) => port.id === 
'output');
+          
+          if (hasInputPort) {
+            node.setPortProp('input', 'attrs/circle/opacity', 0);
+          }
+          if (hasOutputPort) {
+            node.setPortProp('output', 'attrs/circle/opacity', 0);
+          }
+        }
+      },
+      
+
+      'node:move': ({ node }: any) => {
+        const data = node.getData() as ModernNodeData
+        if (data.isDisabled) return
+        
+
+        node.setData({ 
+          ...data, 
+          isDragging: true,
+
+          animations: finalOptions.animationEnabled ? {
+            ...data.animations,
+            entrance: false
+          } : data.animations
+        })
+      },
+      
+
+      'node:moved': ({ node }: any) => {
+        const data = node.getData() as ModernNodeData
+        
+
+        node.setData({ 
+          ...data, 
+          isDragging: false,
+
+          metadata: {
+            ...data.metadata,
+            position: node.getPosition(),
+            updatedAt: new Date().toISOString()
+          }
+        })
+      },
+      
+
+      'node:resize': ({ node }: any) => {
+        const data = node.getData() as ModernNodeData
+        if (data.isDisabled) return
+        
+
+        const size = node.getSize()
+        node.setData({
+          ...data,
+          style: {
+            ...data.style,
+            width: size.width,
+            height: size.height
+          }
+        })
+      },
+      
+
+      'node:added': ({ node }: any) => {
+        const data = node.getData() as ModernNodeData
+        
+
+        if (finalOptions.animationEnabled) {
+          node.setData({
+            ...data,
+            animations: {
+              ...data.animations,
+              entrance: true
+            }
+          })
+        }
+        
+
+        if (finalOptions.themeEnabled && data.nodeType && !data.theme) {
+          updateNodeTheme(node, data.nodeType)
+        }
+        
+
+        const nodeType = data.nodeType || determineNodeType(undefined, 
data.connectorType, data.name);
+        
+
+        node.removePorts();
+        
+
+        if (nodeType !== 'sink') {
+          node.addPort({
+            id: 'output',
+            group: 'output',
+            attrs: {
+              circle: {
+                magnet: true,
+                r: 5,
+                stroke: CanvasDesignTokens.colors.connections.default,
+                strokeWidth: 2,
+                fill: '#fff'
+              }
+            }
+          });
+        }
+        
+        if (nodeType !== 'source') {
+          node.addPort({
+            id: 'input',
+            group: 'input',
+            attrs: {
+              circle: {
+                magnet: true,
+                r: 5,
+                stroke: CanvasDesignTokens.colors.connections.default,
+                strokeWidth: 2,
+                fill: '#fff'
+              }
+            }
+          });
+        }
       }
     }
   }
 }
+
+
+export function generateNodeTheme(type: NodeType) {
+  const colors = getNodeColors(type)
+  return {
+    primaryColor: colors.primary,
+    secondaryColor: colors.secondary,
+    gradient: colors.gradient,
+    borderColor: colors.border,
+    textColor: colors.text,
+    iconColor: colors.primary
+  }
+}
+
+
+export function getStatusColor(status: NodeState) {
+  return getNodeStateColor(status)
+}
+
+
+export function determineNodeType(
+  type?: string,
+  connector?: string,
+  nodeName?: string
+): NodeType {
+  if (type && ['source', 'sink', 'transform'].includes(type)) {
+    return type as NodeType;
+  }
+  
+  const lowerText = [(connector || ''), (nodeName || '')].join(' 
').toLowerCase()
+  
+  if (lowerText.includes('source') || lowerText.includes('input')) {
+    return 'source'
+  } else if (lowerText.includes('sink') || lowerText.includes('output')) {
+    return 'sink'
+  } else {
+    return 'transform'
+  }
+}
+
+export function createNodeData(
+  id: string,
+  name: string,
+  type: NodeType,
+  options: Partial<ModernNodeData> = {}
+): ModernNodeData {
+
+  const theme = generateNodeTheme(type)
+  
+
+  const defaultStyle = {
+    width: CanvasDesignTokens.sizes.node.width,
+    height: CanvasDesignTokens.sizes.node.height,
+    borderRadius: CanvasDesignTokens.borderRadius.node,
+    shadow: CanvasDesignTokens.shadows.node,
+    opacity: 1,
+    zIndex: CanvasDesignTokens.zIndex.nodes
+  }
+  
+  return {
+    id,
+    name,
+    nodeType: type,
+    theme,
+    status: 'idle',
+    progress: 0,
+    isSelected: false,
+    isHovered: false,
+    isDragging: false,
+    isDisabled: false,
+    animations: {
+      entrance: true,
+      pulse: false,
+      glow: false,
+      shake: false
+    },
+    style: {
+      ...defaultStyle,
+      ...(options.style || {})
+    },
+    metadata: {
+      icon: getNodeTypeIcon(type),
+      ...(options.metadata || {})
+    },
+    ...options
+  }
+}
+
+
+function getNodeTypeIcon(type: NodeType): string {
+  switch (type) {
+    case 'source':
+      return 'data-source'
+    case 'sink':
+      return 'data-target'
+    case 'transform':
+      return 'data-transform'
+    default:
+      return 'default-node'
+  }
+}
+
+export function updateNodeStatus(
+  node: any,
+  status: NodeState,
+  progress?: number,
+  statusMessage?: string
+) {
+  const data = node.getData() as ModernNodeData
+
+
+  const animations = {
+    ...data.animations,
+    pulse: status === 'running',
+    glow: status === 'success',
+    shake: status === 'error'
+  }
+
+  node.setData({
+    ...data,
+    status,
+    progress,
+    statusMessage,
+    animations
+  })
+}
+
+
+export function updateNodeTheme(node: any, type: NodeType) {
+  const data = node.getData() as ModernNodeData
+  const theme = generateNodeTheme(type)
+
+  node.setData({
+    ...data,
+    nodeType: type,
+    theme
+  })
+}
+
+export function updateNodeMetadata(node: any, metadata: 
Partial<ModernNodeData['metadata']>) {
+  const data = node.getData() as ModernNodeData
+
+  node.setData({
+    ...data,
+    metadata: {
+      ...data.metadata,
+      ...metadata,
+      updatedAt: new Date().toISOString()
+    }
+  })
+}
+
+
+export function updateNodeStyle(node: any, style: 
Partial<ModernNodeData['style']>) {
+  const data = node.getData() as ModernNodeData
+
+  node.setData({
+    ...data,
+    style: {
+      ...data.style,
+      ...style
+    }
+  })
+}
+
diff --git 
a/seatunnel-ui/src/views/task/synchronization-instance/detail/task-definition.tsx
 
b/seatunnel-ui/src/views/task/synchronization-instance/detail/task-definition.tsx
index c4376bbaf..a74e41cc4 100644
--- 
a/seatunnel-ui/src/views/task/synchronization-instance/detail/task-definition.tsx
+++ 
b/seatunnel-ui/src/views/task/synchronization-instance/detail/task-definition.tsx
@@ -27,6 +27,7 @@ import { useDagEdge } from './dag/use-dag-edge'
 import { useTaskDefinition } from './use-task-definition'
 import styles from './task-definition.module.scss'
 import { useDagNode } from './dag/use-dag-node'
+import { useCanvasTheme } from './dag/theme-manager'
 
 interface IJobConfig {
   name: string
@@ -46,6 +47,9 @@ const TaskDefinition = defineComponent({
     const graph = ref<Graph>()
     const { getJobConfig, getJobDag } = useTaskDefinition(t)
 
+
+    const { } = useCanvasTheme()
+
     const initGraph = () => {
       graph.value = useDagGraph(
         graph,

Reply via email to