Explorar o código

feat: 添加侧边栏菜单

jiaxing.liao hai 1 día
pai
achega
9292a28921

+ 1 - 0
.vscode/settings.json

@@ -1,4 +1,5 @@
 {
+  "editor.formatOnSave": true,
   "[typescript]": {
     "editor.defaultFormatter": "esbenp.prettier-vscode"
   },

+ 3 - 3
electron.vite.config.ts

@@ -1,5 +1,5 @@
 import { resolve } from 'path'
-import { defineConfig, externalizeDepsPlugin } from 'electron-vite'
+import { defineConfig, externalizeDepsPlugin, bytecodePlugin } from 'electron-vite'
 import vue from '@vitejs/plugin-vue'
 import monacoEditorPlugin from 'vite-plugin-monaco-editor'
 import AutoImport from 'unplugin-auto-import/vite'
@@ -9,10 +9,10 @@ import UnoCSS from 'unocss/vite'
 
 export default defineConfig({
   main: {
-    plugins: [externalizeDepsPlugin()]
+    plugins: [externalizeDepsPlugin(), bytecodePlugin()]
   },
   preload: {
-    plugins: [externalizeDepsPlugin()]
+    plugins: [externalizeDepsPlugin(), bytecodePlugin()]
   },
   renderer: {
     resolve: {

+ 28 - 0
src/main/index.ts

@@ -3,6 +3,8 @@ import { join } from 'path'
 import { electronApp, optimizer, is } from '@electron-toolkit/utils'
 import icon from '../../resources/icon.png?asset'
 
+const net = require('net')
+
 function createWindow(): void {
   // Create the browser window.
   const mainWindow = new BrowserWindow({
@@ -38,6 +40,32 @@ function createWindow(): void {
   if (is.dev) {
     mainWindow.webContents.openDevTools()
   }
+
+  // pipe命名管道通信
+  ipcMain.on('connect-pipe', () => {
+    try {
+      const pipe = net.connect('\\\\.\\Pipe\\MyPipeServer')
+
+      pipe.on('connect', () => {
+        mainWindow.webContents.send('pipe-connected', pipe)
+      })
+
+      pipe.on('data', (data) => {
+        mainWindow.webContents.send('pipe-message', data.toString())
+      })
+
+      pipe.on('error', (data) => {
+        mainWindow.webContents.send('pipe-error', data.toString())
+        console.log('pipe error:', data)
+      })
+
+      ipcMain.on('pipe-end', () => {
+        pipe.end()
+      })
+    } catch (error) {
+      console.error('Error connecting to pipe:', error)
+    }
+  })
 }
 
 // This method will be called when Electron has finished

+ 3 - 1
src/renderer/auto-imports.d.ts

@@ -5,4 +5,6 @@
 // Generated by unplugin-auto-import
 // biome-ignore lint: disable
 export {}
-declare global {}
+declare global {
+
+}

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

@@ -19,6 +19,7 @@ declare module 'vue' {
     ElSplitterPanel: typeof import('element-plus/es')['ElSplitterPanel']
     ElTabPane: typeof import('element-plus/es')['ElTabPane']
     ElTabs: typeof import('element-plus/es')['ElTabs']
+    ElTooltip: typeof import('element-plus/es')['ElTooltip']
     RouterLink: typeof import('vue-router')['RouterLink']
     RouterView: typeof import('vue-router')['RouterView']
     SplitterCollapse: typeof import('./src/components/SplitterCollapse/index.vue')['default']

+ 2 - 2
src/renderer/src/components/SplitterCollapse/SplitterCollapseItem.vue

@@ -6,11 +6,11 @@
       @click="parent?.change(name)"
     >
       <div class="left">
-        <span class="mr-8px">
+        <span class="mr-8px text-text-secondary">
           <ai-outline-down :size="12" v-if="opened" />
           <ai-outline-right :size="12" v-else />
         </span>
-        <span class="text-14px text-secondary">{{ title }}</span>
+        <span class="text-14px text-text-secondary">{{ title }}</span>
       </div>
       <div class="right">
         <slot name="header-right"></slot>

+ 7 - 1
src/renderer/src/locale/en_US.json

@@ -1 +1,7 @@
-{}
+{
+  "directory": "Directory",
+  "widgetLibrary": "Widget Library",
+  "resourceManager": "Resource Manager",
+  "codeView": "Code View",
+  "projectJSON": "Project JSON"
+}

+ 7 - 1
src/renderer/src/locale/zh_CN.json

@@ -1 +1,7 @@
-{}
+{
+  "directory": "目录",
+  "widgetLibrary": "控件库",
+  "resourceManager": "资源管理",
+  "codeView": "代码查看",
+  "projectJSON": "项目JSON"
+}

+ 2 - 0
src/renderer/src/theme/vars.css

@@ -5,6 +5,7 @@
   --bg-tertiary: #2d2d2d; /* 工具栏/三级背景 */
   --text-primary: #d4d4d4; /* 主要文本 */
   --text-secondary: #858585; /* 次要文本 */
+  --text-active: #ffffff; /* 激活文本 */
   --accent-blue: #569cd6; /* 蓝色强调色 (VS Code blue) */
   --accent-green: #6a9955; /* 绿色强调色 (VS Code green) */
   --accent-yellow: #d7ba7d; /* 黄色强调色 (VS Code yellow) */
@@ -65,6 +66,7 @@
   --bg-tertiary: #e4e4e4;
   --text-primary: #333333;
   --text-secondary: #666666;
+  --text-active: #000000; /* 激活文本 */
   --accent-blue: #0078d4;
   --accent-green: #388a34;
   --accent-yellow: #d7ba7d;

+ 12 - 0
src/renderer/src/views/designer/sidebar/Hierarchy.vue

@@ -0,0 +1,12 @@
+<template>
+  <SplitterCollapse>
+    <SplitterCollapseItem title="屏幕页面" name="page" :min="200"> </SplitterCollapseItem>
+    <SplitterCollapseItem title="图层" name="hierarchy" :min="200"> </SplitterCollapseItem>
+  </SplitterCollapse>
+</template>
+
+<script setup lang="ts">
+import { SplitterCollapse, SplitterCollapseItem } from '@/components/SplitterCollapse'
+</script>
+
+<style scoped></style>

+ 96 - 10
src/renderer/src/views/designer/sidebar/index.vue

@@ -1,18 +1,59 @@
 <template>
   <div class="w-full h-full flex">
     <div class="w-50px h-full bg-bg-sidebar flex flex-col items-center justify-between">
-      <div class="flex-1">
-        <ul class="list-none p-0 m-0">
-          <li class="w-full h-40px flex items-center justify-center"><LuFiles /></li>
-          <li class="w-full h-40px flex items-center justify-center"><LuBoxes /></li>
-          <li class="w-full h-40px flex items-center justify-center"><LuBoxes /></li>
-          <li class="w-full h-40px flex items-center justify-center"><LuBoxes /></li>
-          <li class="w-full h-40px flex items-center justify-center"><LuBoxes /></li>
+      <div class="w-full flex-1">
+        <ul class="list-none p-0 m-0 text-12px text-text-secondary sidebar-menu">
+          <li
+            class="sidebar-menu-item"
+            v-for="item in sidebarMenu"
+            :key="item.key"
+            :class="activeMenu === item.key ? 'text-text-active bg-bg-primary' : ''"
+            @click="activeMenu = item.key"
+          >
+            <el-tooltip
+              :content="item.tooltip"
+              :enterable="false"
+              placement="right"
+              trigger="hover"
+              :focus-on-show="false"
+            >
+              <component :is="item.title" />
+            </el-tooltip>
+          </li>
+        </ul>
+      </div>
+      <div class="w-full flex flex-col">
+        <ul class="list-none p-0 m-0 text-12px text-text-secondary">
+          <li class="sidebar-menu-item"><LuSettings2 /></li>
         </ul>
       </div>
-      <div class="flex flex-col"></div>
     </div>
-    <div class="flex-1">
+    <!-- 目录大纲 -->
+    <div class="flex-1" v-show="activeMenu === 'file'"></div>
+    <!-- 控件库 -->
+    <div class="flex-1" v-show="activeMenu === 'widget'">
+      <SplitterCollapse>
+        <SplitterCollapseItem title="屏幕页面" name="page" :min="200"> </SplitterCollapseItem>
+        <SplitterCollapseItem title="页面大纲" name="hierarchy"> </SplitterCollapseItem>
+      </SplitterCollapse>
+    </div>
+    <!-- 资源管理 -->
+    <div class="flex-1" v-show="activeMenu === 'resource'">
+      <SplitterCollapse>
+        <SplitterCollapseItem title="图片" name="image" :min="200"> </SplitterCollapseItem>
+        <SplitterCollapseItem title="字体" name="font"> </SplitterCollapseItem>
+        <SplitterCollapseItem title="其他数据" name="other"> </SplitterCollapseItem>
+      </SplitterCollapse>
+    </div>
+    <!-- 代码查看 -->
+    <div class="flex-1" v-show="activeMenu === 'code'">
+      <SplitterCollapse>
+        <SplitterCollapseItem title="屏幕页面" name="page" :min="200"> </SplitterCollapseItem>
+        <SplitterCollapseItem title="页面大纲" name="hierarchy"> </SplitterCollapseItem>
+      </SplitterCollapse>
+    </div>
+    <!-- json预览 -->
+    <div class="flex-1" v-show="activeMenu === 'json'">
       <SplitterCollapse>
         <SplitterCollapseItem title="屏幕页面" name="page" :min="200"> </SplitterCollapseItem>
         <SplitterCollapseItem title="页面大纲" name="hierarchy"> </SplitterCollapseItem>
@@ -22,8 +63,42 @@
 </template>
 
 <script setup lang="ts">
+import { ref, h } from 'vue'
 import { SplitterCollapse, SplitterCollapseItem } from '@/components/SplitterCollapse'
-import { LuFiles, LuBoxes } from 'vue-icons-plus/lu';
+import { LuFiles, LuBoxes, LuFileStack, LuSquareCode, LuSettings2 } from 'vue-icons-plus/lu'
+import { useI18n } from 'vue-i18n'
+
+const { t } = useI18n()
+
+const sidebarMenu = [
+  {
+    key: 'file',
+    title: LuFiles,
+    tooltip: t('directory')
+  },
+  {
+    key: 'widget',
+    title: LuBoxes,
+    tooltip: t('widgetLibrary')
+  },
+  {
+    key: 'resource',
+    title: LuFileStack,
+    tooltip: t('resourceManager')
+  },
+  {
+    key: 'code',
+    title: LuSquareCode,
+    tooltip: t('codeView')
+  },
+  {
+    key: 'json',
+    title: h('span', null, 'JSON'),
+    tooltip: t('projectJSON')
+  }
+]
+
+const activeMenu = ref('file')
 </script>
 
 <style scoped lang="less">
@@ -33,4 +108,15 @@ import { LuFiles, LuBoxes } from 'vue-icons-plus/lu';
     box-sizing: border-box;
   }
 }
+.sidebar-menu-item {
+  width: 100%;
+  height: 40px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  cursor: pointer;
+  &:hover {
+    color: var(--text-primary);
+  }
+}
 </style>

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

@@ -1,7 +1,29 @@
 <template>
-  <div>中间区域</div>
+  <div>
+    中间区域
+    <div style="word-break: keep-all">
+      {{ content }}
+    </div>
+  </div>
 </template>
 
-<script setup lang="ts"></script>
+<script setup lang="ts">
+import { ref, onMounted } from 'vue'
+
+const content = ref('')
+
+onMounted(() => {
+  window.electron.ipcRenderer.send('connect-pipe')
+
+  window.electron.ipcRenderer.on('pipe-message', (_event, data) => {
+    console.log('pipe message', data)
+    content.value += data.toString() + '\n'
+  })
+
+  window.electron.ipcRenderer.on('pipe-connected', () => {
+    console.log('pipe connected')
+  })
+})
+</script>
 
 <style scoped></style>

+ 2 - 1
uno.config.ts

@@ -16,7 +16,8 @@ export default defineConfig({
       // 文本色
       text: {
         primary: 'var(--text-primary)',
-        secondary: 'var(--text-secondary)'
+        secondary: 'var(--text-secondary)',
+        active: 'var(--text-active)'
       },
       // 强调色
       accent: {