فهرست منبع

feat: 添加画布功能

jiaxing.liao 4 هفته پیش
والد
کامیت
6d4f452393

+ 1 - 0
package.json

@@ -30,6 +30,7 @@
     "normalize.css": "^8.0.1",
     "pinia": "^3.0.3",
     "reka-ui": "^2.6.0",
+    "uuid": "^13.0.0",
     "vue-hooks-plus": "^2.4.1",
     "vue-i18n": "^11.1.12",
     "vue-icons-plus": "^0.1.8",

+ 9 - 0
pnpm-lock.yaml

@@ -35,6 +35,9 @@ importers:
       reka-ui:
         specifier: ^2.6.0
         version: 2.6.0(typescript@5.9.3)(vue@3.5.22(typescript@5.9.3))
+      uuid:
+        specifier: ^13.0.0
+        version: 13.0.0
       vue-hooks-plus:
         specifier: ^2.4.1
         version: 2.4.1(vue@3.5.22(typescript@5.9.3))
@@ -2979,6 +2982,10 @@ packages:
   util-deprecate@1.0.2:
     resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
 
+  uuid@13.0.0:
+    resolution: {integrity: sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==}
+    hasBin: true
+
   verror@1.10.1:
     resolution: {integrity: sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==}
     engines: {node: '>=0.6.0'}
@@ -6365,6 +6372,8 @@ snapshots:
 
   util-deprecate@1.0.2: {}
 
+  uuid@13.0.0: {}
+
   verror@1.10.1:
     dependencies:
       assert-plus: 1.0.0

+ 144 - 112
project.json5

@@ -23,7 +23,17 @@
     // 芯片配置
     "chip": {
       // 芯片型号
-      "model": "ESP32"
+      "model": "ESP32",
+      // 闪存大小
+      "flash_size": {
+        "capcity": "16",
+        "unit": "M"
+      },
+      // 内存大小
+      "ram_size": {
+        "capcity": "4",
+        "unit": "M"
+      }
     },
     // 板卡配置
     "board": {
@@ -70,6 +80,11 @@
       "id": "bin_1",
       "fileName": "bin1.bin",
       "path": "./src/bin/bin1.bin"
+    },
+    {
+      "id": "bin_2",
+      "fileName": "bin2.bin",
+      "path": "./src/bin/bin2.bin"
     }
   ],
   // 资源
@@ -82,8 +97,10 @@
         "fielType": "png",
         "path": "./src/assets/images/image1.png",
         "compressFormat": "rle", // 无压缩、RLE压缩、QOI压缩、JPEG压缩、PNG压缩
-        "alpha": 1, // 透明度0-1
-        "bin": "bin_1" // 关联的BIN ID
+        "alpha": 255, // 透明度0-255
+        "bin": "bin_1", // 关联的BIN ID
+        "colorFormat": "RGB565", // 颜色格式
+        "colorDepth": "16bit", // 颜色深度
       }
     ],
     // 字体资源
@@ -118,6 +135,122 @@
       }
     ]
   },
+  // 复用控件
+  "widgets": [
+    {
+      "id": "copy_obj_1",
+      // 控件类型
+      "widgetType": "lv_object",
+      // 属性 根据每个控件生成
+      "props": {
+        // 坐标x
+        "x": 0,
+        // 坐标y
+        "y": 0,
+        // 宽度
+        "width": 100,
+        // 高度
+        "height": 100,
+        // 布局方式 flex grid
+        "layout": "flex",
+        // 启用
+        "enable": true,
+        // 可见
+        "visible": true,
+        // 值
+        "value": {
+          "valueType": "VARIABLE",
+          "value": "page_1_a"
+        },
+      },
+      // 样式 根据每个控件生成
+      "style": {
+        // 样式
+        "style": "default",
+        "state": {
+          // 默认状态
+          "normal": {
+            // 直接使用颜色值
+            "bg_color": "#000000",
+            "border": "all", // all left right top bottom
+            // 绑定变量或主题色
+            "border_color": {
+              // valueType的值: TEXT: 文本,VARIABLE: 变量,LANGUAGE: 多语言, COLOR: 主题颜色,不同的控件可以配置不同类型的属性
+              "valueType": "TEXT", 
+              "value": "#ffffff"
+            },
+            "border_width": 1,
+            "round_radius": 4
+          },
+          // 禁用状态
+          "disabled": {
+            "bg_color": "#000000",
+            "border": "all",
+          }
+        }
+      },
+      // 事件
+      "events": [
+        {
+          "id": "event_1",
+          // 事件名称
+          "name": "lv_obj_click_event",
+          // 触发事件
+          "trigger": "click",
+          // 动作类型
+          "type": "function", // 'play_animation' | 'function' -> play_animation: 播放动画 function: 执行函数
+          // 动画ID
+          animation: "",
+          // 动画播放前函数ID
+          animationPlayerBeforeEvent: "",
+          // 动画播放后函数ID
+          animationPlayerAfterEvent: "",
+          // 函数ID
+          function: "method_1"
+        },
+        // 加载完毕播放动画
+        {
+          "id": "event_1",
+          // 事件名称
+          "name": "lv_obj_click_event",
+          // 触发事件
+          "trigger": "click",
+          // 动作类型
+          "type": "play_animation", // 'play_animation' | 'function' -> play_animation: 播放动画 function: 执行函数
+          // 动画ID
+          animation: "animation_1",
+          // 动画播放前函数ID
+          animationPlayerBeforeEvent: "method_animation_1",
+          // 动画播放后函数ID
+          animationPlayerAfterEvent: "method_animation_2",
+          // 函数ID
+          function: ""
+        }
+      ],
+      // 子对象
+      "children": [
+        {
+          "id": "label_1",
+          "name": "lv_label",
+          "parentId": "lv_obj_01",
+          "type": "object",
+          "hidden": false,
+          "locked": false,
+          "props": [
+            {
+              "id": "prop_1",
+              "name": "text",
+              "type": "string",
+              "text": {
+                "valueType": "LANGUAGE",
+                "value": "hello" 
+              }
+            }
+          ]
+        }
+      ]
+    },
+  ],
   // 全局变量定义
   "variables": [
     {
@@ -153,7 +286,7 @@
           // 颜色值
           "value": "#000000",
           // 透明度
-          "alpha": 1
+          "alpha": 255
         }
       ]
     },
@@ -172,7 +305,7 @@
           // 颜色值
           "value": "#ffffff",
           // 透明度
-          "alpha": 1
+          "alpha": 255
         }
       ]
     }
@@ -301,12 +434,12 @@
           "children": [
             {
               "id": "lv_obj_01",
+              // 复用控件ID
+              "widgetId": "obj_1",
               // 控件名称
-              "name": "obj_01",
+              "name": "容器",
               // 类型
               "type": "widget",
-              // 控件类型
-              "widgetType": "lv_obj",
               // 隐藏
               "hidden": false,
               // 锁定
@@ -314,111 +447,10 @@
               // 属性 根据每个控件生成
               "props": {
                 // 坐标x
-                "x": 0,
+                "x": 100,
                 // 坐标y
-                "y": 0,
-                // 宽度
-                "width": 100,
-                // 高度
-                "height": 100,
-                // 布局方式 flex grid
-                "layout": "flex",
-                // 启用
-                "enable": true,
-                // 可见
-                "visible": true,
-                // 值
-                "value": {
-                  "valueType": "VARIABLE",
-                  "value": "page_1_a"
-                },
-              },
-              // 样式 根据每个控件生成
-              "style": {
-                // 样式
-                "style": "default",
-                "state": {
-                  // 默认状态
-                  "normal": {
-                    // 直接使用颜色值
-                    "bg_color": "#000000",
-                    "border": "all", // all left right top bottom
-                    // 绑定变量或主题色
-                    "border_color": {
-                      // valueType的值: TEXT: 文本,VARIABLE: 变量,LANGUAGE: 多语言, COLOR: 主题颜色,不同的控件可以配置不同类型的属性
-                      "valueType": "TEXT", 
-                      "value": "#ffffff"
-                    },
-                    "border_width": 1,
-                    "round_radius": 4
-                  },
-                  // 禁用状态
-                  "disabled": {
-                    "bg_color": "#000000",
-                    "border": "all",
-                  }
-                }
-              },
-              // 事件
-              "events": [
-                {
-                  "id": "event_1",
-                  // 事件名称
-                  "name": "lv_obj_click_event",
-                  // 触发事件
-                  "trigger": "click",
-                  // 动作类型
-                  "type": "function", // 'play_animation' | 'function' -> play_animation: 播放动画 function: 执行函数
-                  // 动画ID
-                  animation: "",
-                  // 动画播放前函数ID
-                  animationPlayerBeforeEvent: "",
-                  // 动画播放后函数ID
-                  animationPlayerAfterEvent: "",
-                  // 函数ID
-                  function: "method_1"
-                },
-                // 加载完毕播放动画
-                {
-                  "id": "event_1",
-                  // 事件名称
-                  "name": "lv_obj_click_event",
-                  // 触发事件
-                  "trigger": "click",
-                  // 动作类型
-                  "type": "play_animation", // 'play_animation' | 'function' -> play_animation: 播放动画 function: 执行函数
-                  // 动画ID
-                  animation: "animation_1",
-                  // 动画播放前函数ID
-                  animationPlayerBeforeEvent: "method_animation_1",
-                  // 动画播放后函数ID
-                  animationPlayerAfterEvent: "method_animation_2",
-                  // 函数ID
-                  function: ""
-                }
-              ],
-              // 子对象
-              "children": [
-                {
-                  "id": "label_1",
-                  "name": "lv_label",
-                  "parentId": "lv_obj_01",
-                  "type": "object",
-                  "hidden": false,
-                  "locked": false,
-                  "props": [
-                    {
-                      "id": "prop_1",
-                      "name": "text",
-                      "type": "string",
-                      "text": {
-                        "valueType": "LANGUAGE",
-                        "value": "hello" 
-                      }
-                    }
-                  ]
-                }
-              ]
+                "y": 100
+              }
             }
           ]
         }

+ 1 - 0
src/renderer/components.d.ts

@@ -23,6 +23,7 @@ declare module 'vue' {
     ElHeader: typeof import('element-plus/es')['ElHeader']
     ElMain: typeof import('element-plus/es')['ElMain']
     ElSlider: typeof import('element-plus/es')['ElSlider']
+    ElSpace: typeof import('element-plus/es')['ElSpace']
     ElSplitter: typeof import('element-plus/es')['ElSplitter']
     ElSplitterPanel: typeof import('element-plus/es')['ElSplitterPanel']
     ElTabPane: typeof import('element-plus/es')['ElTabPane']

+ 58 - 0
src/renderer/src/config/analog_display_config.json

@@ -0,0 +1,58 @@
+{
+  "simulation_display": {
+    "display_mode": {
+      "options": ["single", "dual"],
+      "default": "single"
+    },
+    "image_compression": {
+      "RLE": true,
+      "QOI": true,
+      "PNG": true,
+      "JPEG": true
+    },    
+    "single_screen": {
+      "resolutions": {
+        "options": ["1920x1080", "1920x720", "1280x800", "1280x720", "1280x480", "1024x600", "800x600", "800x480", "480x272", "320x240"],
+        "default": "800x600"
+      },
+      "color_depth": {
+        "options": ["16bit", "24bit", "32bit"],
+        "default": "32bit"
+      },
+      "color_format": {
+        "options": ["BGR", "RGB"],
+        "default": "RGB"
+      }
+    },
+    "dual_screen": {
+      "screen0": {
+        "resolutions": {
+          "options": ["1920x1080", "1920x720", "1280x800", "1280x720", "1280x480", "1024x600", "800x600", "800x480", "480x272", "320x240"],
+          "default": "800x600"
+        },
+        "color_depth": {
+          "options": ["16bit", "24bit", "32bit"],
+          "default": "32bit"
+        },
+        "color_format": {
+          "options": ["BGR", "RGB"],
+          "default": "RGB"
+        }
+      },
+      "screen1": {
+        "resolutions": {
+          "options": ["1920x1080", "1920x720", "1280x800", "1280x720", "1280x480", "1024x600", "800x600", "800x480", "480x272", "320x240"],
+          "default": "800x600"
+        },
+        "color_depth": {
+          "options": ["16bit", "24bit", "32bit"],
+          "default": "32bit"
+        },
+        "color_format": {
+          "options": ["BGR", "RGB"],
+          "default": "RGB"
+        }
+      }
+    }
+  }
+}

+ 26 - 0
src/renderer/src/config/board_card_config.json

@@ -0,0 +1,26 @@
+{
+  "boards": [
+    {
+      "board_name": "DC80128M070",
+      "description":" screen_resolution: 1920*720\n screen_size: 11.3英寸\n",
+      "pic_path":"./images/project.jpeg",
+      "image_compression": {
+        "RLE": true,
+        "QOI": true,
+        "PNG": true,
+        "JPEG": true
+      }      
+    },
+    {
+      "board_name": "DC80128M080",
+      "description":" screen_resolution: 1920*720\n screen_size: 11.3英寸\n",
+      "pic_path":"./images/project1.jpeg",
+      "image_compression": {
+        "RLE": true,
+        "QOI": true,
+        "PNG": true,
+        "JPEG": true
+      } 
+    }
+  ]
+}

+ 642 - 0
src/renderer/src/config/multi_chip_config.json

@@ -0,0 +1,642 @@
+{
+  "chips": {
+    "HPM6800": {
+      "model": "HPM6800",
+      "flash_size": {
+        "capacity_options": ["8", "16", "32"],
+        "unit_options": ["KB", "MB", "GB"],
+        "capacity_default": "8",          
+        "unit_default": "MB"
+      },
+      "ram_size": {
+        "capacity_options": ["64", "128", "256"],
+        "unit_options": ["KB", "MB", "GB"],
+        "capacity_default": "64",
+        "unit_default": "MB"
+      },      
+      "screen_mode": {
+        "options": ["single", "dual"],
+        "default": "single"
+      },
+      "image_compression": {
+        "RLE": true,
+        "QOI": true,
+        "PNG": true,
+        "JPEG": true
+      },
+      "resolution_presets": {
+        "1920x1080": {
+          "width": 1920,
+          "height": 1080,
+          "PCLK": 150.0,
+          "VBP": 36,
+          "VFP": 4,
+          "HBP": 148,
+          "HFP": 88,
+          "HSYNC": 44,
+          "VSYNC": 5,
+          "HsyncWidth": 44,
+          "VsyncWidth": 5
+        },
+        "1920x720": {
+          "width": 1920,
+          "height": 720,
+          "PCLK": 92.0,
+          "VBP": 28,
+          "VFP": 5,
+          "HBP": 110,
+          "HFP": 40,
+          "HSYNC": 18,
+          "VSYNC": 5,
+          "HsyncWidth": 18,
+          "VsyncWidth": 5
+        },
+        "1280x800": {
+          "width": 1280,
+          "height": 800,
+          "PCLK": 75.0,
+          "VBP": 18,
+          "VFP": 3,
+          "HBP": 84,
+          "HFP": 40,
+          "HSYNC": 32,
+          "VSYNC": 6,
+          "HsyncWidth": 32,
+          "VsyncWidth": 6
+        },
+        "1280x720": {
+          "width": 1280,
+          "height": 720,
+          "PCLK": 76.0,
+          "VBP": 20,
+          "VFP": 5,
+          "HBP": 112,
+          "HFP": 20,
+          "HSYNC": 40,
+          "VSYNC": 5,
+          "HsyncWidth": 40,
+          "VsyncWidth": 5
+        },
+        "1280x480": {
+          "width": 1280,
+          "height": 480,
+          "PCLK": 42.0,
+          "VBP": 12,
+          "VFP": 8,
+          "HBP": 42,
+          "HFP": 40,
+          "HSYNC": 10,
+          "VSYNC": 4,
+          "HsyncWidth": 10,
+          "VsyncWidth": 4
+        },
+        "1024x600": {
+          "width": 1024,
+          "height": 600,
+          "PCLK": 55.0,
+          "VBP": 24,
+          "VFP": 2,
+          "HBP": 170,
+          "HFP": 160,
+          "HSYNC": 20,
+          "VSYNC": 3,
+          "HsyncWidth": 20,
+          "VsyncWidth": 3
+        },
+        "800x600": {
+          "width": 800,
+          "height": 600,
+          "PCLK": 42.0,
+          "VBP": 25,
+          "VFP": 1,
+          "HBP": 90,
+          "HFP": 40,
+          "HSYNC": 130,
+          "VSYNC": 4,
+          "HsyncWidth": 130,
+          "VsyncWidth": 4
+        },
+        "800x480": {
+          "width": 800,
+          "height": 480,
+          "PCLK": 40.0,
+          "VBP": 15,
+          "VFP": 5,
+          "HBP": 40,
+          "HFP": 40,
+          "HSYNC": 5,
+          "VSYNC": 5,
+          "HsyncWidth": 5,
+          "VsyncWidth": 5
+        },
+        "480x272": {
+          "width": 480,
+          "height": 272,
+          "PCLK": 10.0,
+          "VBP": 4,
+          "VFP": 2,
+          "HBP": 4,
+          "HFP": 4,
+          "HSYNC": 10,
+          "VSYNC": 4,
+          "HsyncWidth": 10,
+          "VsyncWidth": 4
+        },
+        "320x240": {
+          "width": 320,
+          "height": 240,
+          "PCLK": 6.5,
+          "VBP": 16,
+          "VFP": 4,
+          "HBP": 40,
+          "HFP": 12,
+          "HSYNC": 30,
+          "VSYNC": 3,
+          "HsyncWidth": 30,
+          "VsyncWidth": 3
+        }
+      },
+      "single_screen": {
+        "interface": {
+          "options": ["RGB", "LVDS0", "LVDS1", "LVDS0+LVDS1"],
+          "default": "RGB"
+        },
+        "color_format": {
+          "options": ["BGR", "RGB"],
+          "default": "BGR"
+        },
+        "color_depth": {
+          "options": ["16bit", "24bit", "32bit"],
+          "default": "32bit"
+        },
+        "resolutions": {
+          "options": ["1920x1080", "1920x720", "1280x800", "1280x720", "1280x480", "1024x600", "800x600", "800x480", "480x272", "320x240"],
+          "default": "800x600"
+        }
+      },
+      "dual_screen": {
+        "screen0": {
+          "interface": {
+            "options": ["RGB", "LVDS0", "LVDS1", "LVDS0+LVDS1"],
+            "default": "RGB"
+          },
+          "color_format": {
+            "options": ["BGR", "RGB"],
+            "default": "BGR"
+          },
+          "color_depth": {
+            "options": ["16bit", "24bit", "32bit"],
+            "default": "32bit"
+          },
+          "resolutions": {
+            "options": ["1920x1080", "1920x720", "1280x800", "1280x720", "1280x480", "1024x600", "800x600", "800x480", "480x272", "320x240"],
+            "default": "1920x1080"
+          }
+        },
+        "screen1": {
+          "interface": {
+            "options": ["RGB", "LVDS0", "LVDS1", "LVDS0+LVDS1"],
+            "default": "RGB"
+          },
+          "color_format": {
+            "options": ["BGR", "RGB"],
+            "default": "BGR"
+          },
+          "color_depth": {
+            "options": ["16bit", "24bit", "32bit"],
+            "default": "32bit"
+          },
+          "resolutions": {
+            "options": ["1920x1080", "1920x720", "1280x800", "1280x720", "1280x480", "1024x600", "800x600", "800x480", "480x272", "320x240"],
+            "default": "1920x1080"
+          }
+        }
+      }
+    },
+    "HPM6880": {
+      "model": "HPM6880",
+      "flash_size": {
+        "capacity_options": ["16", "32", "64", "128"],
+        "unit_options": ["KB", "MB", "GB"],
+        "capacity_default": "16",          
+        "unit_default": "MB"
+      },
+      "ram_size": {
+        "capacity_options": ["64", "128", "256", "512"],
+        "unit_options": ["KB", "MB", "GB"],
+        "capacity_default": "64",
+        "unit_default": "MB"
+      },            
+      "screen_mode": {
+        "options": ["single", "dual"],
+        "default": "single"
+      },
+      "image_compression": {
+        "RLE": true,
+        "QOI": true,
+        "PNG": true,
+        "JPEG": true
+      },          
+      "resolution_presets": {
+        "1920x1080": {
+          "width": 1920,
+          "height": 1080,
+          "PCLK": 150.0,
+          "VBP": 36,
+          "VFP": 4,
+          "HBP": 148,
+          "HFP": 88,
+          "HSYNC": 44,
+          "VSYNC": 5,
+          "HsyncWidth": 44,
+          "VsyncWidth": 5
+        },
+        "1920x720": {
+          "width": 1920,
+          "height": 720,
+          "PCLK": 92.0,
+          "VBP": 28,
+          "VFP": 5,
+          "HBP": 110,
+          "HFP": 40,
+          "HSYNC": 18,
+          "VSYNC": 5,
+          "HsyncWidth": 18,
+          "VsyncWidth": 5
+        },
+        "1280x800": {
+          "width": 1280,
+          "height": 800,
+          "PCLK": 75.0,
+          "VBP": 18,
+          "VFP": 3,
+          "HBP": 84,
+          "HFP": 40,
+          "HSYNC": 32,
+          "VSYNC": 6,
+          "HsyncWidth": 32,
+          "VsyncWidth": 6
+        },
+        "1280x720": {
+          "width": 1280,
+          "height": 720,
+          "PCLK": 76.0,
+          "VBP": 20,
+          "VFP": 5,
+          "HBP": 112,
+          "HFP": 20,
+          "HSYNC": 40,
+          "VSYNC": 5,
+          "HsyncWidth": 40,
+          "VsyncWidth": 5
+        },
+        "1280x480": {
+          "width": 1280,
+          "height": 480,
+          "PCLK": 42.0,
+          "VBP": 12,
+          "VFP": 8,
+          "HBP": 42,
+          "HFP": 40,
+          "HSYNC": 10,
+          "VSYNC": 4,
+          "HsyncWidth": 10,
+          "VsyncWidth": 4
+        },
+        "1024x600": {
+          "width": 1024,
+          "height": 600,
+          "PCLK": 55.0,
+          "VBP": 24,
+          "VFP": 2,
+          "HBP": 170,
+          "HFP": 160,
+          "HSYNC": 20,
+          "VSYNC": 3,
+          "HsyncWidth": 20,
+          "VsyncWidth": 3
+        },
+        "800x600": {
+          "width": 800,
+          "height": 600,
+          "PCLK": 42.0,
+          "VBP": 25,
+          "VFP": 1,
+          "HBP": 90,
+          "HFP": 40,
+          "HSYNC": 130,
+          "VSYNC": 4,
+          "HsyncWidth": 130,
+          "VsyncWidth": 4
+        },
+        "800x480": {
+          "width": 800,
+          "height": 480,
+          "PCLK": 40.0,
+          "VBP": 15,
+          "VFP": 5,
+          "HBP": 40,
+          "HFP": 40,
+          "HSYNC": 5,
+          "VSYNC": 5,
+          "HsyncWidth": 5,
+          "VsyncWidth": 5
+        },
+        "480x272": {
+          "width": 480,
+          "height": 272,
+          "PCLK": 10.0,
+          "VBP": 4,
+          "VFP": 2,
+          "HBP": 4,
+          "HFP": 4,
+          "HSYNC": 10,
+          "VSYNC": 4,
+          "HsyncWidth": 10,
+          "VsyncWidth": 4
+        },
+        "320x240": {
+          "width": 320,
+          "height": 240,
+          "PCLK": 6.5,
+          "VBP": 16,
+          "VFP": 4,
+          "HBP": 40,
+          "HFP": 12,
+          "HSYNC": 30,
+          "VSYNC": 3,
+          "HsyncWidth": 30,
+          "VsyncWidth": 3
+        }
+      },
+      "single_screen": {
+        "interface": {
+          "options": ["RGB", "LVDS0", "LVDS1", "LVDS0+LVDS1"],
+          "default": "RGB"
+        },
+        "color_format": {
+          "options": ["RGB", "BGR"],
+          "default": "RGB"
+        },
+        "color_depth": {
+          "options": ["16bit", "24bit", "32bit"],
+          "default": "32bit"
+        },
+        "resolutions": {
+          "options": ["1920x1080", "1920x720", "1280x800", "1280x720", "1280x480", "1024x600", "800x600", "800x480", "480x272", "320x240"],
+          "default": "800x600"
+        }
+      },
+      "dual_screen": {
+        "screen0": {
+          "interface": {
+            "options": ["RGB", "LVDS0", "LVDS1", "LVDS0+LVDS1"],
+            "default": "RGB"
+          },
+          "color_format": {
+            "options": ["RGB", "BGR"],
+            "default": "RGB"
+          },
+          "color_depth": {
+            "options": ["16bit", "24bit", "32bit"],
+            "default": "32bit"
+          },
+          "resolutions": {
+            "options": ["1920x1080", "1920x720", "1280x800", "1280x720", "1280x480", "1024x600", "800x600", "800x480", "480x272", "320x240"],
+            "default": "1920x1080"
+          }
+        },
+        "screen1": {
+          "interface": {
+            "options": ["RGB", "LVDS0", "LVDS1", "LVDS0+LVDS1"],
+            "default": "RGB"
+          },
+          "color_format": {
+            "options": ["RGB", "BGR"],
+            "default": "RGB"
+          },
+          "color_depth": {
+            "options": ["16bit", "24bit", "32bit"],
+            "default": "32bit"
+          },
+          "resolutions": {
+            "options": ["1920x1080", "1920x720", "1280x800", "1280x720", "1280x480", "1024x600", "800x600", "800x480", "480x272", "320x240"],
+            "default": "1920x1080"
+          }
+        }
+      }
+    },
+    "ATM630HV100": {
+      "model": "ATM630HV100",
+      "flash_size": {
+        "capacity_options": ["32", "64", "128"],
+        "unit_options": ["KB", "MB", "GB"],
+        "capacity_default": "32",          
+        "unit_default": "MB"
+      },
+      "ram_size": {
+        "capacity_options": ["128", "256", "512"],
+        "unit_options": ["KB", "MB", "GB"],
+        "capacity_default": "128",
+        "unit_default": "MB"
+      },   
+      "screen_mode": {
+        "options": ["single", "dual"],
+        "default": "single"
+      },
+      "image_compression": {
+        "RLE": true,
+        "QOI": true,
+        "PNG": true
+      },          
+      "resolution_presets": {
+        "1920x1080": {
+          "width": 1920,
+          "height": 1080,
+          "PCLK": 150.0,
+          "VBP": 36,
+          "VFP": 4,
+          "HBP": 148,
+          "HFP": 88,
+          "HSYNC": 44,
+          "VSYNC": 5,
+          "HsyncWidth": 44,
+          "VsyncWidth": 5
+        },
+        "1920x720": {
+          "width": 1920,
+          "height": 720,
+          "PCLK": 92.0,
+          "VBP": 28,
+          "VFP": 5,
+          "HBP": 110,
+          "HFP": 40,
+          "HSYNC": 18,
+          "VSYNC": 5,
+          "HsyncWidth": 18,
+          "VsyncWidth": 5
+        },
+        "1280x800": {
+          "width": 1280,
+          "height": 800,
+          "PCLK": 75.0,
+          "VBP": 18,
+          "VFP": 3,
+          "HBP": 84,
+          "HFP": 40,
+          "HSYNC": 32,
+          "VSYNC": 6,
+          "HsyncWidth": 32,
+          "VsyncWidth": 6
+        },
+        "1280x720": {
+          "width": 1280,
+          "height": 720,
+          "PCLK": 76.0,
+          "VBP": 20,
+          "VFP": 5,
+          "HBP": 112,
+          "HFP": 20,
+          "HSYNC": 40,
+          "VSYNC": 5,
+          "HsyncWidth": 40,
+          "VsyncWidth": 5
+        },
+        "1280x480": {
+          "width": 1280,
+          "height": 480,
+          "PCLK": 42.0,
+          "VBP": 12,
+          "VFP": 8,
+          "HBP": 42,
+          "HFP": 40,
+          "HSYNC": 10,
+          "VSYNC": 4,
+          "HsyncWidth": 10,
+          "VsyncWidth": 4
+        },
+        "1024x600": {
+          "width": 1024,
+          "height": 600,
+          "PCLK": 55.0,
+          "VBP": 24,
+          "VFP": 2,
+          "HBP": 170,
+          "HFP": 160,
+          "HSYNC": 20,
+          "VSYNC": 3,
+          "HsyncWidth": 20,
+          "VsyncWidth": 3
+        },
+        "800x600": {
+          "width": 800,
+          "height": 600,
+          "PCLK": 42.0,
+          "VBP": 25,
+          "VFP": 1,
+          "HBP": 90,
+          "HFP": 40,
+          "HSYNC": 130,
+          "VSYNC": 4,
+          "HsyncWidth": 130,
+          "VsyncWidth": 4
+        },
+        "800x480": {
+          "width": 800,
+          "height": 480,
+          "PCLK": 40.0,
+          "VBP": 15,
+          "VFP": 5,
+          "HBP": 40,
+          "HFP": 40,
+          "HSYNC": 5,
+          "VSYNC": 5,
+          "HsyncWidth": 5,
+          "VsyncWidth": 5
+        },
+        "480x272": {
+          "width": 480,
+          "height": 272,
+          "PCLK": 10.0,
+          "VBP": 4,
+          "VFP": 2,
+          "HBP": 4,
+          "HFP": 4,
+          "HSYNC": 10,
+          "VSYNC": 4,
+          "HsyncWidth": 10,
+          "VsyncWidth": 4
+        },
+        "320x240": {
+          "width": 320,
+          "height": 240,
+          "PCLK": 6.5,
+          "VBP": 16,
+          "VFP": 4,
+          "HBP": 40,
+          "HFP": 12,
+          "HSYNC": 30,
+          "VSYNC": 3,
+          "HsyncWidth": 30,
+          "VsyncWidth": 3
+        }
+      },
+      "single_screen": {
+        "interface": {
+          "options": ["MIPI", "LVDS0", "LVDS1", "LVDS0+LVDS1"],
+          "default": "MIPI"
+        },
+        "color_format": {
+          "options": ["RGB", "BGR"],
+          "default": "RGB"
+        },
+        "color_depth": {
+          "options": ["16bit", "24bit", "32bit"],
+          "default": "32bit"
+        },
+        "resolutions": {
+          "options": ["1920x1080", "1920x720", "1280x800", "1280x720", "1280x480", "1024x600", "800x600", "800x480", "480x272", "320x240"],
+          "default": "800x600"
+        }
+      },
+      "dual_screen": {
+        "screen0": {
+          "interface": {
+            "options": ["MIPI", "LVDS0", "LVDS1", "LVDS0+LVDS1"],
+            "default": "MIPI"
+          },
+          "color_format": {
+            "options": ["RGB", "BGR"],
+            "default": "RGB"
+          },
+          "color_depth": {
+            "options": ["16bit", "24bit", "32bit"],
+            "default": "32bit"
+          },
+          "resolutions": {
+            "options": ["1920x1080", "1920x720", "1280x800", "1280x720", "1280x480", "1024x600", "800x600", "800x480", "480x272", "320x240"],
+            "default": "1920x1080"
+          }
+        },
+        "screen1": {
+          "interface": {
+            "options": ["MIPI", "LVDS0", "LVDS1", "LVDS0+LVDS1"],
+            "default": "MIPI"
+          },
+          "color_format": {
+            "options": ["RGB", "BGR"],
+            "default": "RGB"
+          },
+          "color_depth": {
+            "options": ["16bit", "24bit", "32bit"],
+            "default": "32bit"
+          },
+          "resolutions": {
+            "options": ["1920x1080", "1920x720", "1280x800", "1280x720", "1280x480", "1024x600", "800x600", "800x480", "480x272", "320x240"],
+            "default": "1920x1080"
+          }
+        }
+      }
+    }
+  }
+}

+ 9 - 1
src/renderer/src/views/designer/config/index.vue

@@ -1,5 +1,13 @@
 <template>
-  <div>右侧面板</div>
+  <div>
+    <el-tabs size="small">
+      <el-tab-pane label="属性"></el-tab-pane>
+      <el-tab-pane label="变量"></el-tab-pane>
+      <el-tab-pane label="动画"></el-tab-pane>
+      <el-tab-pane label="多语言"></el-tab-pane>
+      <el-tab-pane label="历史"></el-tab-pane>
+    </el-tabs>
+  </div>
 </template>
 
 <script setup lang="ts"></script>

+ 5 - 1
src/renderer/src/views/designer/sidebar/Libary.vue

@@ -1,6 +1,10 @@
 <template>
   <SplitterCollapse>
-    <SplitterCollapseItem title="基础" name="base" :min="200"> </SplitterCollapseItem>
+    <SplitterCollapseItem title="基础" name="base" :min="200">
+      <el-space>
+        <div v-for="item in 10" :key="item">控件{{ item }}</div>
+      </el-space>
+    </SplitterCollapseItem>
     <SplitterCollapseItem title="表单" name="form" :min="200"> </SplitterCollapseItem>
     <SplitterCollapseItem title="容器" name="coniner" :min="200"> </SplitterCollapseItem>
     <SplitterCollapseItem title="图文" name="image_text" :min="200"> </SplitterCollapseItem>

+ 40 - 8
src/renderer/src/views/designer/workspace/stage/DesignerCanvas.vue

@@ -1,5 +1,5 @@
 <template>
-  <div class="stage-wrapper" ref="stageWrapperRef">
+  <div class="stage-wrapper" ref="stageWrapperRef" :style="getWrapperStyle">
     <div class="stage" ref="stageRef" :style="getStyles.stageStyle">
       <div ref="tipRef" class="tip-txt" :style="getStyles.tipStyle">页面名称</div>
       <div class="absolute transparent-bg" :style="getStyles.transpartBg"></div>
@@ -10,6 +10,7 @@
         :style="getStyles.canvasStyle"
         @drop="handleDrop"
       >
+        <div class="canvas-grid" v-show="state.showBgGrid"></div>
         <!-- <ComponentWrapper
           v-for="item in projectStore.elements"
           v-show="item.visible"
@@ -37,7 +38,7 @@ import {
   defineEmits
 } from 'vue'
 
-import { useScroll, useElementSize, set } from '@vueuse/core'
+import { useScroll, useElementSize } from '@vueuse/core'
 import ComponentWrapper from './ComponentWrapper.vue'
 
 const props = defineProps<{
@@ -51,6 +52,16 @@ const stageRef: Ref<HTMLElement | null> = ref(null)
 const canvasRef: Ref<HTMLElement | null> = ref(null)
 const { width: clientWidth, height: clientHeight } = useElementSize(stageWrapperRef)
 
+const getWrapperStyle = computed(() => {
+  const { showRuler } = props.state
+  return {
+    width: showRuler ? 'calc(100% - 20px)' : '100%',
+    height: showRuler ? 'calc(100% - 20px)' : '100%',
+    left: showRuler ? '20px' : '0',
+    top: showRuler ? '20px' : '0'
+  }
+})
+
 const STAGE_SCALE = 3
 const getStyles = computed(() => {
   const { width = 1280, height = 720, scale } = props.state
@@ -102,8 +113,8 @@ const getStyles = computed(() => {
       'transform-origin': '50% 50%',
       transform: `scale(${scale})`,
       left: `${canvasLeft}px`,
-      top: `${canvasTop}px`
-      // background: '#fff'
+      top: `${canvasTop}px`,
+      background: '#fff'
     },
     // 提示样式
     tipStyle: {
@@ -198,11 +209,7 @@ onBeforeUnmount(() => {
 
 <style lang="less" scoped>
 .stage-wrapper {
-  height: calc(100% - 20px);
-  width: calc(100% - 20px);
   position: absolute;
-  top: 20px;
-  left: 20px;
   overflow: auto;
 }
 .stage {
@@ -231,4 +238,29 @@ onBeforeUnmount(() => {
     -5px 5px,
     5px 0px;
 }
+.canvas-grid {
+  position: absolute;
+  left: 0;
+  top: 0;
+  width: 100%;
+  height: 100%;
+  background-size: 20px 20px;
+  background-position: 0 0;
+  background-image:
+    linear-gradient(to right, #c5c3c3 1px, transparent 1px),
+    linear-gradient(to bottom, #c5c3c3 1px, transparent 1px);
+  &::before {
+    content: '';
+    position: absolute;
+    left: 0;
+    top: 0;
+    width: 100%;
+    height: 100%;
+    background-size: 100px 100px;
+    background-position: 0 0;
+    background-image:
+      linear-gradient(to right, #8d8b8b 2px, transparent 1px),
+      linear-gradient(to bottom, #8d8b8b 2px, transparent 1px);
+  }
+}
 </style>

+ 46 - 24
src/renderer/src/views/designer/workspace/stage/index.vue

@@ -7,24 +7,45 @@
     @mouseup="handleMouseUp"
   >
     <div class="workspace flex flex-col">
+      <div class="h-24px bg-bg-secondary">
+        <div class="px-12px leading-24px text-14px">屏幕</div>
+      </div>
       <div class="workspace-top">
+        <!-- 画布 -->
         <DesignerCanvas :state="state" ref="canvasRef" @changeState="handleSetState" />
-        <Scaleplate :state="state" />
+        <!-- 标尺 -->
+        <Scaleplate :state="state" v-show="state.showRuler" />
       </div>
-      <div class="workspace-bottom flex justify-between items-center">
+      <!-- 底部工具栏 -->
+      <div
+        class="workspace-bottom flex justify-between items-center overflow-hidden bg-bg-secondary"
+      >
         <div class="bottom-left">
           <span style="margin-right: 12px">画布尺寸:</span>
-          <span>画布自适应:</span>
+          <span>{{ state.width }} * {{ state.height }}</span>
         </div>
-        <div class="bottom-right flex items-center">
-          <el-button
-            size="small"
-            type="text"
-            :disabled="state.scale <= 0.1"
-            @click="handleSizeChange(Number(state.scale) - 0.1)"
+        <div class="bottom-right flex items-center gap-8px">
+          <div
+            class="w-20px h-20px flex items-center justify-center cursor-pointer border-1px border-solid border-transparent"
+            :class="state.showRuler ? 'border-blue! border-1px border-solid bg-bg-primary' : ''"
+            @click="state.showRuler = !state.showRuler"
+          >
+            <LuRuler :size="16" />
+          </div>
+          <div
+            class="w-20px h-20px flex items-center justify-center cursor-pointer border-1px border-solid border-transparent"
+            :class="state.showBorder ? 'border-blue! border-1px border-solid bg-bg-primary' : ''"
+            @click="state.showBorder = !state.showBorder"
           >
-            <LuMinusCircle :size="16" />
-          </el-button>
+            <LuBoxSelect :size="16" />
+          </div>
+          <div
+            class="w-20px h-20px flex items-center justify-center cursor-pointer border-1px border-solid border-transparent"
+            :class="state.showBgGrid ? 'border-blue! border-1px border-solid bg-bg-primary' : ''"
+            @click="state.showBgGrid = !state.showBgGrid"
+          >
+            <LuGrid3X3 :size="16" />
+          </div>
           <el-slider
             v-model="state.scale"
             :min="0.1"
@@ -34,14 +55,7 @@
             size="small"
             style="width: 140px"
           ></el-slider>
-          <el-button
-            size="small"
-            type="text"
-            :disabled="state.scale >= 4"
-            @click="handleSizeChange(Number(state.scale) + 0.1)"
-          >
-            <LuPlusCircle :size="16" />
-          </el-button>
+          <span>{{ (state.scale * 100).toFixed(0) }}%</span>
         </div>
       </div>
     </div>
@@ -58,6 +72,7 @@ import { LuMinusCircle, LuPlusCircle } from 'vue-icons-plus/lu'
 import Scaleplate from './Scaleplate.vue'
 import DesignerCanvas from './DesignerCanvas.vue'
 import { throttle } from 'lodash'
+import { LuGrid3X3, LuRuler, LuBoxSelect } from 'vue-icons-plus/lu'
 
 const canvasRef = ref<{ getPosition: HTMLElement['getBoundingClientRect'] } | null>()
 const state = reactive<StageState>({
@@ -73,7 +88,10 @@ const state = reactive<StageState>({
   scrollX: 0,
   scrollY: 0,
   wrapperWidth: 0,
-  wrapperHeight: 0
+  wrapperHeight: 0,
+  showBorder: false,
+  showRuler: true,
+  showBgGrid: false
 })
 
 // 修改状态
@@ -84,10 +102,12 @@ const handleSetState = (newState: Partial<StageState>) => {
 }
 
 const handleSizeChange = (n: number) => {
-  if (Number.isNaN(n) && n >= 10 && n <= 400) {
-    state.scale = Number((n / 100).toFixed(2))
-  } else {
+  if (n < 0.1) {
     state.scale = 0.1
+  } else if (n > 4) {
+    state.scale = 4
+  } else {
+    state.scale = n
   }
 }
 
@@ -181,7 +201,6 @@ const handleSelectComponent = (startX: number, startY: number, endX: number, end
   &-bottom {
     padding: 0 20px;
     height: 24px;
-    background: var(--background-primary);
     border-top: solid 1px var(--border-color);
     font-size: 12px;
     color: #666;
@@ -199,4 +218,7 @@ const handleSelectComponent = (startX: number, startY: number, endX: number, end
   width: 0;
   height: 0;
 }
+::v-deep(.el-slider) {
+  --el-slider-button-size: 10px;
+}
 </style>

+ 6 - 0
src/renderer/src/views/designer/workspace/stage/type.d.ts

@@ -25,4 +25,10 @@ export type StageState = {
   wrapperWidth: number
   // 容器高度
   wrapperHeight: number
+  // 边框
+  showBorder: boolean
+  // 刻度
+  showRuler: boolean
+  // 背景网格
+  showBgGrid: boolean
 }

+ 1 - 1
src/renderer/src/views/designer/workspace/stage/utils.ts

@@ -109,7 +109,7 @@ function drawMaxTick(
   ctx.strokeStyle = '#666'
   ctx.lineWidth = 1 * drp
   ctx.stroke()
-  ctx.fillStyle = '#666'
+  ctx.fillStyle = '#eee'
   ctx.font = '16px Arial'
   if (direcotion === 'horizontal') {
     ctx.fillText(num.toString(), x + 5, 10 * drp)