diff --git a/package.json b/package.json
index b47b83a..9a83bab 100644
--- a/package.json
+++ b/package.json
@@ -20,6 +20,7 @@
"dat.gui": "^0.7.9",
"decimal.js": "^10.5.0",
"element-plus": "^2.9.10",
+ "hotkeys-js": "^3.13.10",
"jquery": "^3.6.0",
"less": "^4.2.1",
"localforage": "^1.10.0",
diff --git a/src/components/viewMenus/editMenu/EditMenu.ts b/src/components/viewMenus/editMenu/EditMenu.ts
deleted file mode 100644
index 7637d4e..0000000
--- a/src/components/viewMenus/editMenu/EditMenu.ts
+++ /dev/null
@@ -1,63 +0,0 @@
-import { renderIcon } from '@/utils/webutils.ts'
-import { defineMenu } from '@/runtime/DefineMenu.ts'
-import SvgCode from '@/components/icons/SvgCode'
-
-export default defineMenu((menus) => {
- menus.insertChildren('modelFile',
- {
- name: 'modelFile',
- label: '编辑',
- icon: renderIcon('ModelFile'),
- order: 1
- },
- [
- {
- name: 'find', label: '查找', icon: SvgCode.find, order: 1, tip: 'Ctrl+F', divided: true,
- click: () => {
- system.msg('查找')
- }
- },
- {
- name: 'undo', label: '撤销', icon: SvgCode.undo, order: 2, tip: 'Ctrl+Z', disabled: true,
- click: () => {
- system.msg('撤销')
- }
- },
- {
- name: 'redo', label: '重做', icon: SvgCode.redo, order: 3, tip: 'Ctrl+Y', divided: true,
- disabled() {
- return true
- },
- click() {
- system.msg('重做')
- }
- },
- {
- name: 'copy', label: '复制', icon: SvgCode.copy, order: 4, tip: 'Ctrl+C',
- disabled() {
- return true
- },
- click() {
- system.msg('复制')
- }
- },
- {
- name: 'cut', label: '剪切', icon: SvgCode.cut, order: 5, tip: 'Ctrl+X',
- disabled() {
- return true
- },
- click() {
- system.msg('剪切')
- }
- },
- {
- name: 'paste', label: '粘贴', icon: SvgCode.paste, order: 6, tip: 'Ctrl+V',
- disabled() {
- return true
- },
- click() {
- system.msg('粘贴')
- }
- }
- ])
-})
\ No newline at end of file
diff --git a/src/designer/Designer.ts b/src/designer/Designer.ts
new file mode 100644
index 0000000..6c868d1
--- /dev/null
+++ b/src/designer/Designer.ts
@@ -0,0 +1,3 @@
+export default class Designer {
+
+}
\ No newline at end of file
diff --git a/src/views/modeleditor/ModelEditor.vue b/src/designer/ModelEditor.vue
similarity index 100%
rename from src/views/modeleditor/ModelEditor.vue
rename to src/designer/ModelEditor.vue
diff --git a/src/designer/ModelView.vue b/src/designer/ModelView.vue
new file mode 100644
index 0000000..78e4ba9
--- /dev/null
+++ b/src/designer/ModelView.vue
@@ -0,0 +1,8 @@
+
+
+
+
\ No newline at end of file
diff --git a/src/designer/menus/EditMenu.ts b/src/designer/menus/EditMenu.ts
new file mode 100644
index 0000000..fa34631
--- /dev/null
+++ b/src/designer/menus/EditMenu.ts
@@ -0,0 +1,110 @@
+import { renderIcon } from '@/utils/webutils.ts'
+import { defineMenu } from '@/runtime/DefineMenu.ts'
+import SvgCode from '@/components/icons/SvgCode'
+
+export default defineMenu((menus) => {
+ menus.insertChildren('modelFile',
+ {
+ name: 'modelFile',
+ label: '编辑',
+ icon: renderIcon('ModelFile'),
+ order: 1
+ },
+ [
+ {
+ name: 'find', label: '全局查找', icon: SvgCode.find, order: 1, tip: 'Ctrl+H',
+ click: () => {
+ system.msg('全局查找')
+ }
+ },
+ {
+ name: 'resource', label: '资源定位', icon: SvgCode.find, order: 1.1, tip: 'Ctrl+Shift+R', divided: true,
+ click: () => {
+ system.msg('资源定位')
+ }
+ },
+ {
+ name: 'undo', label: '撤销', icon: SvgCode.undo, order: 2, tip: 'Ctrl+Z', disabled: true,
+ click: () => {
+ system.msg('撤销')
+ }
+ },
+ {
+ name: 'redo', label: '重做', icon: SvgCode.redo, order: 3, tip: 'Ctrl+Y', divided: true,
+ click() {
+ system.msg('重做')
+ }
+ },
+ {
+ name: 'copy', label: '复制', icon: SvgCode.copy, order: 4, tip: 'Ctrl+C',
+ click() {
+ system.msg('复制')
+ }
+ },
+ {
+ name: 'cut', label: '剪切', icon: SvgCode.cut, order: 5, tip: 'Ctrl+X',
+ click() {
+ system.msg('剪切')
+ }
+ },
+ {
+ name: 'paste', label: '粘贴', icon: SvgCode.paste, order: 6, tip: 'Ctrl+V',
+ click() {
+ system.msg('粘贴')
+ }
+ },
+ {
+ name: 'delete', label: '删除', icon: SvgCode.delete, order: 7, tip: 'key-delete', divided: true,
+ click() {
+ system.msg('删除')
+ }
+ },
+ {
+ name: 'edit_property', label: '快速转换', order: 8,
+ children: [
+ {
+ name: 'edit_property_esc', label: '取消', order: 1, tip: 'key-esc',
+ click() {
+ system.msg('ESC')
+ }
+ },
+ {
+ name: 'edit_property_rotate', label: '转向90度', order: 1, tip: 'key-r',
+ click() {
+ system.msg('转向90度')
+ }
+ },
+ {
+ name: 'edit_append', label: '快速添加', tip: 'key-q',
+ click() {
+ system.msg('快速添加')
+ }
+ },
+ {
+ name: 'edit_up', label: '上移', tip: 'key-up',
+ click() {
+ system.msg('↑')
+ }
+ },
+ {
+ name: 'edit_down', label: '下移', tip: 'key-down',
+ click() {
+ system.msg('↓')
+ }
+ },
+ {
+ name: 'edit_left', label: '左移', tip: 'key-left',
+ click() {
+ system.msg('←')
+ }
+ },
+ {
+ name: 'edit_right', label: '右移', tip: 'key-right',
+ click() {
+ system.msg('→')
+ }
+ }
+ ]
+ }
+ ])
+})
\ No newline at end of file
diff --git a/src/components/viewMenus/fileMenu/FileMenu.ts b/src/designer/menus/FileMenu.ts
similarity index 100%
rename from src/components/viewMenus/fileMenu/FileMenu.ts
rename to src/designer/menus/FileMenu.ts
diff --git a/src/components/viewWidgets/alarm/AlarmMeta.ts b/src/designer/viewWidgets/alarm/AlarmMeta.ts
similarity index 100%
rename from src/components/viewWidgets/alarm/AlarmMeta.ts
rename to src/designer/viewWidgets/alarm/AlarmMeta.ts
diff --git a/src/components/viewWidgets/alarm/AlarmView.vue b/src/designer/viewWidgets/alarm/AlarmView.vue
similarity index 100%
rename from src/components/viewWidgets/alarm/AlarmView.vue
rename to src/designer/viewWidgets/alarm/AlarmView.vue
diff --git a/src/components/viewWidgets/logger/LoggerMeta.ts b/src/designer/viewWidgets/logger/LoggerMeta.ts
similarity index 100%
rename from src/components/viewWidgets/logger/LoggerMeta.ts
rename to src/designer/viewWidgets/logger/LoggerMeta.ts
diff --git a/src/components/viewWidgets/logger/LoggerView.vue b/src/designer/viewWidgets/logger/LoggerView.vue
similarity index 100%
rename from src/components/viewWidgets/logger/LoggerView.vue
rename to src/designer/viewWidgets/logger/LoggerView.vue
diff --git a/src/components/viewWidgets/modeltree/ModeltreeMeta.ts b/src/designer/viewWidgets/modeltree/ModeltreeMeta.ts
similarity index 100%
rename from src/components/viewWidgets/modeltree/ModeltreeMeta.ts
rename to src/designer/viewWidgets/modeltree/ModeltreeMeta.ts
diff --git a/src/components/viewWidgets/modeltree/ModeltreeView.vue b/src/designer/viewWidgets/modeltree/ModeltreeView.vue
similarity index 100%
rename from src/components/viewWidgets/modeltree/ModeltreeView.vue
rename to src/designer/viewWidgets/modeltree/ModeltreeView.vue
diff --git a/src/components/viewWidgets/monitor/MonitorMeta.ts b/src/designer/viewWidgets/monitor/MonitorMeta.ts
similarity index 100%
rename from src/components/viewWidgets/monitor/MonitorMeta.ts
rename to src/designer/viewWidgets/monitor/MonitorMeta.ts
diff --git a/src/components/viewWidgets/monitor/MonitorView.vue b/src/designer/viewWidgets/monitor/MonitorView.vue
similarity index 100%
rename from src/components/viewWidgets/monitor/MonitorView.vue
rename to src/designer/viewWidgets/monitor/MonitorView.vue
diff --git a/src/components/viewWidgets/property/PropertyMeta.ts b/src/designer/viewWidgets/property/PropertyMeta.ts
similarity index 100%
rename from src/components/viewWidgets/property/PropertyMeta.ts
rename to src/designer/viewWidgets/property/PropertyMeta.ts
diff --git a/src/components/viewWidgets/property/PropertyView.vue b/src/designer/viewWidgets/property/PropertyView.vue
similarity index 100%
rename from src/components/viewWidgets/property/PropertyView.vue
rename to src/designer/viewWidgets/property/PropertyView.vue
diff --git a/src/components/viewWidgets/script/ScriptMeta.ts b/src/designer/viewWidgets/script/ScriptMeta.ts
similarity index 100%
rename from src/components/viewWidgets/script/ScriptMeta.ts
rename to src/designer/viewWidgets/script/ScriptMeta.ts
diff --git a/src/components/viewWidgets/script/ScriptView.vue b/src/designer/viewWidgets/script/ScriptView.vue
similarity index 100%
rename from src/components/viewWidgets/script/ScriptView.vue
rename to src/designer/viewWidgets/script/ScriptView.vue
diff --git a/src/components/viewWidgets/task/TaskMeta.ts b/src/designer/viewWidgets/task/TaskMeta.ts
similarity index 100%
rename from src/components/viewWidgets/task/TaskMeta.ts
rename to src/designer/viewWidgets/task/TaskMeta.ts
diff --git a/src/components/viewWidgets/task/TaskView.vue b/src/designer/viewWidgets/task/TaskView.vue
similarity index 100%
rename from src/components/viewWidgets/task/TaskView.vue
rename to src/designer/viewWidgets/task/TaskView.vue
diff --git a/src/components/viewWidgets/toolbox/ToolboxMeta.ts b/src/designer/viewWidgets/toolbox/ToolboxMeta.ts
similarity index 100%
rename from src/components/viewWidgets/toolbox/ToolboxMeta.ts
rename to src/designer/viewWidgets/toolbox/ToolboxMeta.ts
diff --git a/src/components/viewWidgets/toolbox/ToolboxView.vue b/src/designer/viewWidgets/toolbox/ToolboxView.vue
similarity index 100%
rename from src/components/viewWidgets/toolbox/ToolboxView.vue
rename to src/designer/viewWidgets/toolbox/ToolboxView.vue
diff --git a/src/runtime/DefineMenu.ts b/src/runtime/DefineMenu.ts
index bccc309..8e16e2c 100644
--- a/src/runtime/DefineMenu.ts
+++ b/src/runtime/DefineMenu.ts
@@ -1,4 +1,4 @@
-import type { Component } from 'vue'
+import _ from 'lodash'
export interface MenuOption {
name: string
@@ -72,6 +72,26 @@ export function getChildrenMenu(name: string) {
}
/**
+ * 遍历菜单
+ * @param callback 回调函数
+ */
+export function forEachMenu(callback: (menu: MenuOption) => void) {
+ // 递归遍历菜单
+ const traverse = (menu: MenuOption) => {
+ callback(menu)
+ if (menu.children) {
+ _.forEach(menu.children, (child) => {
+ traverse(child)
+ })
+ }
+ }
+
+ _.forEach(_menus.menus, (menu) => {
+ traverse(menu)
+ })
+}
+
+/**
* 定义一个 Widget
*/
export function defineMenu(func: (menus: Menus) => void): MenuDefineResult {
diff --git a/src/runtime/System.ts b/src/runtime/System.ts
index 41a713e..ac764b3 100644
--- a/src/runtime/System.ts
+++ b/src/runtime/System.ts
@@ -2,6 +2,7 @@ import $ from 'jquery'
import _ from 'lodash'
import localforage from 'localforage'
import JSON5 from 'json5'
+import hotkeys from 'hotkeys-js'
import { defineComponent, h, markRaw, nextTick, reactive, toRaw, unref, type App, createApp } from 'vue'
import { ElMessage, ElMessageBox, ElNotification } from 'element-plus'
import { QuestionFilled } from '@element-plus/icons-vue'
@@ -20,6 +21,8 @@ export default class System {
markRaw = markRaw
reactive = reactive
renderIcon = renderIcon
+ hotkeys = hotkeys
+ localforage = localforage
JSON5 = JSON5
json5 = JSON5
diff --git a/src/utils/webutils.ts b/src/utils/webutils.ts
index a959642..35353db 100644
--- a/src/utils/webutils.ts
+++ b/src/utils/webutils.ts
@@ -1,5 +1,4 @@
-import _ from 'lodash'
-import { type Component, h, toRaw } from 'vue'
+import { h } from 'vue'
import * as AntdIcon from '@vicons/antd'
import { ElIcon } from 'element-plus'
import * as FaIcon from '@vicons/fa'
diff --git a/src/views/ModelMain.vue b/src/views/ModelMain.vue
index a304c81..e2f7027 100644
--- a/src/views/ModelMain.vue
+++ b/src/views/ModelMain.vue
@@ -64,6 +64,9 @@
+
+
+
@@ -115,7 +118,7 @@