فهرست منبع

feat: 添加工具栏

jiaxing.liao 2 هفته پیش
والد
کامیت
5864a6f31d

+ 2 - 1
src/renderer/src/locales/en_US.json

@@ -47,5 +47,6 @@
   "language": "Language",
   "light": "Light",
   "link": "Link",
-  "theme": "Theme"
+  "theme": "Theme",
+  "editProject": "Edit Project"
 }

+ 2 - 1
src/renderer/src/locales/zh_CN.json

@@ -47,5 +47,6 @@
   "dark": "暗黑",
   "light": "亮色",
   "link": "连接",
-  "download": "下载"
+  "download": "下载",
+  "editProject": "编辑项目"
 }

+ 2 - 1
src/renderer/src/model/index.ts

@@ -2,7 +2,7 @@ import type { Page } from '@/types/page'
 import type { Screen } from '@/types/screen'
 import type { ScreenConfig } from '@/types/appMeta'
 import type { Bin } from '@/types/bins'
-import type { Resource, ImageResource, FontResource, OtherResource } from '@/types/resource'
+import type { Resource } from '@/types/resource'
 
 import { v4 } from 'uuid'
 
@@ -96,6 +96,7 @@ export const createFileResource = (path: string, type: 'image' | 'font' | 'other
         fielType: fileName.split('.').pop() || '',
         path,
         compressFormat: 'none',
+        colorFormat: '',
         alpha: 255,
         bin: ''
       }

+ 1 - 1
src/renderer/src/theme/vars.css

@@ -24,7 +24,7 @@
   --el-color-info: #bfbfbf;
 
   --el-bg-color: var(--bg-primary);
-  --el-bg-color-overlay: var(--bg-secondary);
+  --el-bg-color-overlay: var(--bg-secondary) !important;
 
   --el-text-color-primary: var(--text-secondary);
   --el-text-color-regular: var(--text-secondary);

+ 2 - 0
src/renderer/src/types/resource.d.ts

@@ -10,6 +10,8 @@ export type ImageResource = {
   path: string
   // 压缩格式
   compressFormat: CompressFormat
+  // 颜色格式
+  colorFormat: string
   // 透明度 0-255
   alpha: number
   // 绑定BinId

+ 5 - 5
src/renderer/src/views/designer/index.vue

@@ -37,12 +37,12 @@ import Info from './info/index.vue'
 import ProjectModal from './modals/projectModal/index.vue'
 import { ref, provide } from 'vue'
 
-const projectModel = ref()
+const projectModel = ref<InstanceType<typeof ProjectModal>>()
 
-const handleMenuClick = (item: { label: string; img: string }) => {
-  switch (item.label) {
-    case '新建项目':
-      projectModel.value.open()
+const handleMenuClick = (menuKey: string) => {
+  switch (menuKey) {
+    case 'new':
+      projectModel.value?.create()
   }
 }
 

+ 25 - 6
src/renderer/src/views/designer/modals/projectModal/index.vue

@@ -1,7 +1,7 @@
 <template>
   <el-dialog
     v-model="showModal"
-    :title="$t('createProject')"
+    :title="mode === 'add' ? $t('createProject') : $t('editProject')"
     width="1000px"
     body-class="h-500px overflow-y-auto overflow-x-hidden modal-body-scroll px-12px"
     :modal="false"
@@ -22,7 +22,9 @@
         <el-form-item :label="$t('projectPath')" prop="path" required>
           <el-input v-model="formData.path" readonly>
             <template #append>
-              <el-button @click="selectPath"><LuFolder :size="16" /></el-button>
+              <el-button @click="selectPath"
+                ><LuFolder :size="16" :disabled="mode === 'edit'"
+              /></el-button>
             </template>
           </el-input>
         </el-form-item>
@@ -361,7 +363,9 @@
         </el-form-item>
       </el-form>
       <template #footer>
-        <el-button type="primary" @click="handleSetScreen">{{ $t('confirm') }}</el-button>
+        <el-button type="primary" @click="mode === 'add' ? handleSetScreen : handleEdit">{{
+          $t('confirm')
+        }}</el-button>
       </template>
     </el-dialog>
   </el-dialog>
@@ -370,7 +374,7 @@
 <script setup lang="ts">
 import type { AppMeta } from '@/types/appMeta'
 import type { FormInstance } from 'element-plus'
-import { computed, reactive, ref, defineExpose } from 'vue'
+import { computed, reactive, ref, defineExpose, nextTick } from 'vue'
 import { LuFolder } from 'vue-icons-plus/lu'
 import { useProjectStore } from '@/store/modules/project'
 import { useAppStore } from '@/store/modules/app'
@@ -379,8 +383,10 @@ import { useI18n } from 'vue-i18n'
 import chipConfig from '@/config/multi_chip_config.json'
 import boardConfig from '@/config/board_card_config.json'
 import displayConfig from '@/config/analog_display_config.json'
+import { klona } from 'klona'
 
 const { t } = useI18n()
+const mode = ref<'add' | 'edit'>('add')
 const formData = reactive<
   AppMeta & {
     path: string
@@ -734,12 +740,25 @@ const handleSubmit = async () => {
   showModal.value = false
 }
 
+// 编辑项目
+const handleEdit = async () => {
+  await form.value?.validate()
+}
+
 // expose
 defineExpose({
-  open: () => {
+  create: async () => {
+    mode.value = 'add'
     showModal.value = true
+    await nextTick()
+    form.value?.resetFields()
   },
-  close: () => {
+  edit: () => {
+    const data = klona(projectStore.project?.meta || {})
+    Object.entries(data).forEach(([key, value]) => {
+      formData[key] = value
+    })
+    mode.value = 'edit'
     showModal.value = false
   }
 })

+ 43 - 0
src/renderer/src/views/designer/sidebar/components/EditImageModal.vue

@@ -38,6 +38,16 @@
           ></el-option>
         </el-select>
       </el-form-item>
+      <el-form-item label="颜色格式" prop="colorFormat">
+        <el-select v-model="formData.colorFormat">
+          <el-option
+            v-for="item in colorFormatOptions"
+            :key="item.key"
+            :label="item.label"
+            :value="item.value"
+          ></el-option>
+        </el-select>
+      </el-form-item>
       <el-form-item label="透明度" prop="alpha">
         <el-slider v-model="formData.alpha" :min="0" :max="255" show-input />
       </el-form-item>
@@ -78,12 +88,45 @@ const projectStore = useProjectStore()
 const show = ref(false)
 const form = ref<FormInstance>()
 const editBinModalRef = ref<InstanceType<typeof EditBinModal>>()
+const colorFormatOptions = [
+  {
+    key: '1',
+    label: 'ARGB8888',
+    value: 'ARGB8888'
+  },
+  {
+    key: '2',
+    label: 'RGB888',
+    value: 'RGB888'
+  },
+  {
+    key: '3',
+    label: 'RGB565',
+    value: 'RGB565'
+  },
+  {
+    key: '4',
+    label: 'RGB555',
+    value: 'RGB555'
+  },
+  {
+    key: '5',
+    label: 'ARGB4444',
+    value: 'ARGB4444'
+  },
+  {
+    key: '6',
+    label: 'RGB444',
+    value: 'RGB444'
+  }
+]
 const formData = ref<ImageResource>({
   id: '',
   fileName: '',
   fielType: '',
   path: '',
   compressFormat: 'none',
+  colorFormat: '',
   alpha: 255,
   bin: ''
 })

+ 45 - 0
src/renderer/src/views/designer/tools/Custom.vue

@@ -0,0 +1,45 @@
+<template>
+  <div
+    v-for="item in projectMenu"
+    :key="item.label"
+    class="flex flex-col justify-center items-center w-50px h-50px cursor-pointer mr-10px hover:bg-bg-tertiary rounded-4px"
+    @click="handleClick(item.key)"
+  >
+    <div class="w-30px h-30px flex items-center justify-center">
+      <img
+        v-if="typeof item.img === 'string'"
+        :src="item.img"
+        class="w-24px h-24px"
+        :alt="item.label"
+      />
+      <component v-else :is="item.img" size="20px"></component>
+    </div>
+    <div class="text-12px">{{ item.label }}</div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { reactive, inject } from 'vue'
+import { LuBoomBox, LuBookOpen } from 'vue-icons-plus/lu'
+
+const onMenuClick = inject<(menuKey: string) => void>('onMenuClick', () => {})
+
+const projectMenu = reactive([
+  {
+    key: 'custom1',
+    label: '自定义1',
+    img: LuBoomBox
+  },
+  {
+    key: 'custom2',
+    label: '自定义2',
+    img: LuBookOpen
+  }
+])
+
+const handleClick = (menuKey: string) => {
+  onMenuClick?.(menuKey)
+}
+</script>
+
+<style lang="less" scoped></style>

+ 50 - 0
src/renderer/src/views/designer/tools/Help.vue

@@ -0,0 +1,50 @@
+<template>
+  <div
+    v-for="item in projectMenu"
+    :key="item.label"
+    class="flex flex-col justify-center items-center w-50px h-50px cursor-pointer mr-10px hover:bg-bg-tertiary rounded-4px"
+    @click="handleClick(item.key)"
+  >
+    <div class="w-30px h-30px flex items-center justify-center">
+      <img
+        v-if="typeof item.img === 'string'"
+        :src="item.img"
+        class="w-24px h-24px"
+        :alt="item.label"
+      />
+      <component v-else :is="item.img" size="20px"></component>
+    </div>
+    <div class="text-12px">{{ item.label }}</div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { reactive, inject } from 'vue'
+import { LuHelpCircle, LuFileKey, LuBadgeInfo } from 'vue-icons-plus/lu'
+
+const onMenuClick = inject<(menuKey: string) => void>('onMenuClick', () => {})
+
+const projectMenu = reactive([
+  {
+    key: 'lincense',
+    label: '授权信息',
+    img: LuFileKey
+  },
+  {
+    key: 'help',
+    label: '帮助文档',
+    img: LuHelpCircle
+  },
+  {
+    key: 'about',
+    label: '关于',
+    img: LuBadgeInfo
+  }
+])
+
+const handleClick = (menuKey: string) => {
+  onMenuClick?.(menuKey)
+}
+</script>
+
+<style lang="less" scoped></style>

+ 136 - 0
src/renderer/src/views/designer/tools/Operate.vue

@@ -0,0 +1,136 @@
+<template>
+  <template v-for="item in projectMenu" :key="item.label">
+    <el-divider direction="vertical" v-if="item.type" />
+    <div
+      v-else
+      class="flex flex-col justify-center items-center w-50px h-50px cursor-pointer mr-10px hover:bg-bg-tertiary rounded-4px"
+      @click="handleClick(item.key)"
+    >
+      <div class="w-30px h-30px flex items-center justify-center">
+        <img
+          v-if="typeof item.img === 'string'"
+          :src="item.img"
+          class="w-24px h-24px"
+          :alt="item.label"
+        />
+        <component v-else :is="item.img" size="20px"></component>
+      </div>
+      <div class="text-12px">{{ item.label }}</div>
+    </div>
+  </template>
+</template>
+
+<script setup lang="ts">
+import { reactive, inject } from 'vue'
+import {
+  LuUndo,
+  LuRedo,
+  LuAlignStartHorizontal,
+  LuAlignCenterHorizontal,
+  LuAlignEndHorizontal,
+  LuAlignStartVertical,
+  LuAlignCenterVertical,
+  LuAlignEndVertical,
+  LuAlignHorizontalSpaceBetween,
+  LuAlignVerticalSpaceBetween,
+  LuLayoutGrid,
+  LuArrowUp,
+  LuArrowUpToLine,
+  LuArrowDownToLine
+} from 'vue-icons-plus/lu'
+
+const onMenuClick = inject<(menuKey: string) => void>('onMenuClick', () => {})
+
+const projectMenu = reactive([
+  {
+    key: 'undo',
+    label: '撤销',
+    img: LuUndo
+  },
+  {
+    key: 'redo',
+    label: '重做',
+    img: LuRedo
+  },
+  {
+    type: 'divider'
+  },
+  {
+    key: 'alignLeft',
+    label: '左对齐',
+    img: LuAlignStartVertical
+  },
+  {
+    key: 'alignHorizontal',
+    label: '水平对齐',
+    img: LuAlignCenterVertical
+  },
+  {
+    key: 'alignRight',
+    label: '右对齐',
+    img: LuAlignEndVertical
+  },
+  {
+    key: 'alignTop',
+    label: '顶对齐',
+    img: LuAlignStartHorizontal
+  },
+  {
+    key: 'alignVertical',
+    label: '垂直居中',
+    img: LuAlignCenterHorizontal
+  },
+  {
+    key: 'alignBottom',
+    label: '底对齐',
+    img: LuAlignEndHorizontal
+  },
+  {
+    type: 'divider'
+  },
+  {
+    key: 'alignWidth',
+    label: '宽度匹配',
+    img: LuAlignHorizontalSpaceBetween
+  },
+  {
+    key: 'alignHeight',
+    label: '高度匹配',
+    img: LuAlignVerticalSpaceBetween
+  },
+  {
+    key: 'alignAll',
+    label: '宽高匹配',
+    img: LuLayoutGrid
+  },
+  {
+    type: 'divider'
+  },
+  {
+    key: 'up',
+    label: '上移一层',
+    img: LuArrowUp
+  },
+  {
+    key: 'down',
+    label: '下移一层',
+    img: LuLayoutGrid
+  },
+  {
+    key: 'top',
+    label: '置于顶层',
+    img: LuArrowUpToLine
+  },
+  {
+    key: 'bottom',
+    label: '置于底层',
+    img: LuArrowDownToLine
+  }
+])
+
+const handleClick = (menuKey: string) => {
+  onMenuClick?.(menuKey)
+}
+</script>
+
+<style lang="less" scoped></style>

+ 16 - 6
src/renderer/src/views/designer/tools/index.vue

@@ -1,25 +1,35 @@
 <template>
   <el-tabs v-model="activeMenu" type="border-card">
     <el-tab-pane label="项目" name="project">
-      <div class="h-50px flex flex-row">
-        <projectPage />
+      <div class="h-50px flex items-center">
+        <Project />
       </div>
     </el-tab-pane>
     <el-tab-pane label="编辑" name="page">
-      <div class="h-50px">编辑菜单</div>
+      <div class="h-50px flex items-center">
+        <Opreate />
+      </div>
     </el-tab-pane>
     <el-tab-pane label="工具" name="tool">
-      <div class="h-50px">工具菜单</div>
+      <div class="h-50px flex items-center">
+        <Custom />
+      </div>
     </el-tab-pane>
     <el-tab-pane label="帮助" name="help">
-      <div class="h-50px">帮助菜单</div>
+      <div class="h-50px flex items-center">
+        <Help />
+      </div>
     </el-tab-pane>
   </el-tabs>
 </template>
 
 <script setup lang="ts">
 import { ref } from 'vue'
-import projectPage from './project.vue'
+import Project from './Project.vue'
+import Opreate from './Operate.vue'
+import Custom from './Custom.vue'
+import Help from './Help.vue'
+
 const activeMenu = ref('project')
 </script>
 

+ 42 - 14
src/renderer/src/views/designer/tools/project.vue

@@ -2,58 +2,86 @@
   <div
     v-for="item in projectMenu"
     :key="item.label"
-    class="flex flex-col justify-center items-center h-full w-60px cursor-pointer mr-10px"
-    @click="handleClick(item)"
+    class="flex flex-col justify-center items-center w-50px h-50px cursor-pointer mr-10px hover:bg-bg-tertiary rounded-4px"
+    @click="handleClick(item.key)"
   >
-    <img :src="item.img" class="w-35px h-35px" :alt="item.label" />
+    <div class="w-30px h-30px flex items-center justify-center">
+      <img
+        v-if="typeof item.img === 'string'"
+        :src="item.img"
+        class="w-24px h-24px"
+        :alt="item.label"
+      />
+      <component v-else :is="item.img" size="20px"></component>
+    </div>
     <div class="text-12px">{{ item.label }}</div>
   </div>
 </template>
 
 <script setup lang="ts">
 import { reactive, inject } from 'vue'
-const onMenuClick = inject<(item: { label: string; img: string }) => void>('onMenuClick', () => {})
+import {
+  LuSave,
+  LuSquareCode,
+  LuTerminalSquare,
+  LuPlaySquare,
+  LuPlay,
+  LuHardDriveDownload,
+  LuUnplug
+} from 'vue-icons-plus/lu'
+
+const onMenuClick = inject<(menuKey: string) => void>('onMenuClick', () => {})
+
 const projectMenu = reactive([
   {
+    key: 'new',
     label: '新建项目',
     img: new URL('@/assets/project-add.svg', import.meta.url).href
   },
   {
+    key: 'open',
     label: '打开项目',
     img: new URL('@/assets/open-project.svg', import.meta.url).href
   },
   {
+    key: 'save',
     label: '保存',
-    img: new URL('@/assets/project-save.svg', import.meta.url).href
+    img: LuSave
   },
   {
+    key: 'generate',
     label: '生成代码',
-    img: new URL('@/assets/generate-code.svg', import.meta.url).href
+    img: LuSquareCode
   },
   {
+    key: 'compile',
     label: '编译',
-    img: new URL('@/assets/compile.svg', import.meta.url).href
+    img: LuTerminalSquare
   },
   {
+    key: 'run',
     label: '运行',
-    img: new URL('@/assets/project-run.svg', import.meta.url).href
+    img: LuPlay
   },
   {
+    key: 'preview',
     label: '预览',
-    img: new URL('@/assets/preview.svg', import.meta.url).href
+    img: LuPlaySquare
   },
   {
-    label: '链接',
-    img: new URL('@/assets/project-link.svg', import.meta.url).href
+    key: 'connect',
+    label: '连接',
+    img: LuUnplug
   },
   {
+    key: 'download',
     label: '下载',
-    img: new URL('@/assets/down.svg', import.meta.url).href
+    img: LuHardDriveDownload
   }
 ])
 
-const handleClick = (item: { label: string; img: string }) => {
-  onMenuClick?.(item)
+const handleClick = (menuKey: string) => {
+  onMenuClick?.(menuKey)
 }
 </script>