From 8dec7d676e0688fab75fb7a0f80de2095abcf993 Mon Sep 17 00:00:00 2001 From: DEV_DSW <562304744@qq.com> Date: Thu, 18 Dec 2025 14:35:04 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E7=AA=97=E5=8F=A3?= =?UTF-8?q?=E5=A4=B4=E9=83=A8=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- env.d.ts | 7 - global.d.ts | 37 ++++- index.html | 2 +- package-lock.json | 32 ++++ package.json | 2 + src/common/constants.ts | 9 +- src/main/main.ts | 2 + src/preload.ts | 18 ++- src/renderer/components/HeaderBar/index.vue | 76 +++++++++ .../components/NativeTooltip/index.vue | 43 ++++++ src/renderer/components/TitleBar/index.vue | 0 src/renderer/hooks/useWinManager.ts | 31 ++++ src/renderer/main.ts | 12 +- src/renderer/utils/logger.ts | 12 ++ src/renderer/views/login/index.vue | 144 +++++++++--------- tsconfig.app.json | 6 +- vite.renderer.config.ts | 2 + 17 files changed, 342 insertions(+), 93 deletions(-) delete mode 100644 env.d.ts create mode 100644 src/renderer/components/HeaderBar/index.vue create mode 100644 src/renderer/components/NativeTooltip/index.vue delete mode 100644 src/renderer/components/TitleBar/index.vue create mode 100644 src/renderer/utils/logger.ts diff --git a/env.d.ts b/env.d.ts deleted file mode 100644 index 4acc8d0..0000000 --- a/env.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -declare module "@store/*"; -declare module "@modules/*"; -declare module "@utils/*"; -declare module "@assets/images/*"; -declare module "@constant/*"; -declare module "@remixicon/vue"; -declare module "vue-router"; \ No newline at end of file diff --git a/global.d.ts b/global.d.ts index f4dacf2..da0c6fd 100644 --- a/global.d.ts +++ b/global.d.ts @@ -49,11 +49,12 @@ declare global { external: { open: (url: string) => void }, - window: { - minimize: () => void, - maximize: () => void, - close: () => void - }, + minimizeWindow: () => void, + maximizeWindow: () => void, + closeWindow: () => void, + onWindowMaximized: (callback: (isMaximized: boolean) => void) => void, + isWindowMaximized: () => Promise, + viewIsReady: () => void app: { setFrameless: (route?: string) => void }, @@ -69,10 +70,34 @@ declare global { on: (event: 'tab-updated' | 'tab-created' | 'tab-closed' | 'tab-switched', handler: (payload: any) => void) => void }, readFile: (filePath: string) => Promise<{success: boolean, data?: string, error?: string}>, - logToMain: (logLevel: string, message: string) => void, + logger: { + debug: (message: string, ...meta?: any[]) => void; + info: (message: string, ...meta?: any[]) => void; + warn: (message: string, ...meta?: any[]) => void; + error: (message: string, ...meta?: any[]) => void; + }, } declare interface Window { api: WindowApi; } } + +declare module "@store/*"; +declare module "@modules/*"; +declare module "@utils/*"; +declare module "@assets/images/*"; +declare module "@constant/*"; +declare module "@remixicon/vue"; +declare module "vue-router"; +declare module '@iconify/vue' { + import { DefineComponent } from 'vue' + export const Icon: DefineComponent<{ + icon: string + width?: string | number + height?: string | number + color?: string + flip?: string + rotate?: number + }> +} \ No newline at end of file diff --git a/index.html b/index.html index 65ac6d5..ef53d65 100644 --- a/index.html +++ b/index.html @@ -6,7 +6,7 @@ diff --git a/package-lock.json b/package-lock.json index 8d0abba..fd18193 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,8 @@ "version": "1.0.0", "license": "MIT", "dependencies": { + "@iconify-json/material-symbols": "^1.2.50", + "@iconify/vue": "^5.0.0", "@remixicon/vue": "^4.7.0", "@types/js-cookie": "^3.0.6", "@vueuse/core": "^14.1.0", @@ -1533,6 +1535,36 @@ "dev": true, "license": "MIT" }, + "node_modules/@iconify-json/material-symbols": { + "version": "1.2.50", + "resolved": "https://registry.npmmirror.com/@iconify-json/material-symbols/-/material-symbols-1.2.50.tgz", + "integrity": "sha512-71tjHR70h46LHtBFab3fAd2V/wPTO7JMV5lKnRn3IcF303LaFgAlO0BZeTJDcmCv9d0snRZmnoLZAJVD7/eisw==", + "license": "Apache-2.0", + "dependencies": { + "@iconify/types": "*" + } + }, + "node_modules/@iconify/types": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/@iconify/types/-/types-2.0.0.tgz", + "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==", + "license": "MIT" + }, + "node_modules/@iconify/vue": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/@iconify/vue/-/vue-5.0.0.tgz", + "integrity": "sha512-C+KuEWIF5nSBrobFJhT//JS87OZ++QDORB6f2q2Wm6fl2mueSTpFBeBsveK0KW9hWiZ4mNiPjsh6Zs4jjdROSg==", + "license": "MIT", + "dependencies": { + "@iconify/types": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/cyberalien" + }, + "peerDependencies": { + "vue": ">=3" + } + }, "node_modules/@inquirer/checkbox": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-3.0.1.tgz", diff --git a/package.json b/package.json index 75c013f..d124b1c 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,8 @@ "vite": "^7.1.9" }, "dependencies": { + "@iconify-json/material-symbols": "^1.2.50", + "@iconify/vue": "^5.0.0", "@remixicon/vue": "^4.7.0", "@types/js-cookie": "^3.0.6", "@vueuse/core": "^14.1.0", diff --git a/src/common/constants.ts b/src/common/constants.ts index aaa7ee3..56fc15e 100644 --- a/src/common/constants.ts +++ b/src/common/constants.ts @@ -25,7 +25,14 @@ export enum IPC_EVENTS { FILE_WRITE = 'file:write', GET_WINDOW_ID='get-window-id', CUSTOM_EVENT ='custom:event', - TIME_UPDATE = 'time:update' + TIME_UPDATE = 'time:update', + RENDERER_IS_READY = 'renderer-ready', + + // 发送日志 + LOG_DEBUG = 'log-debug', + LOG_INFO = 'log-info', + LOG_WARN = 'log-warn', + LOG_ERROR = 'log-error', } export const MAIN_WIN_SIZE = { diff --git a/src/main/main.ts b/src/main/main.ts index 5fb1cf2..eb809ae 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -30,6 +30,8 @@ class AppMain { resizable: true, maximizable: true, minimizable: true, + titleBarStyle: 'hidden', + title: 'NIANXX', webPreferences: { devTools: this.isDev, nodeIntegration: false, diff --git a/src/preload.ts b/src/preload.ts index 31d298a..b35e351 100644 --- a/src/preload.ts +++ b/src/preload.ts @@ -8,11 +8,12 @@ const api: WindowApi = { open: (url: string) => ipcRenderer.invoke('external-open', url) }, - window: { - minimize: () => ipcRenderer.send(IPC_EVENTS.WINDOW_MINIMIZE), - maximize: () => ipcRenderer.send(IPC_EVENTS.WINDOW_MAXIMIZE), - close: () => ipcRenderer.send(IPC_EVENTS.WINDOW_CLOSE) - }, + closeWindow: () => ipcRenderer.send(IPC_EVENTS.WINDOW_CLOSE), + minimizeWindow: () => ipcRenderer.send(IPC_EVENTS.WINDOW_MINIMIZE), + maximizeWindow: () => ipcRenderer.send(IPC_EVENTS.WINDOW_MAXIMIZE), + onWindowMaximized: (callback: (isMaximized: boolean) => void) => ipcRenderer.on(IPC_EVENTS.WINDOW_MAXIMIZE + 'back', (_, isMaximized) => callback(isMaximized)), + isWindowMaximized: () => ipcRenderer.invoke(IPC_EVENTS.WINDOW_MAXIMIZE), + viewIsReady: () => ipcRenderer.send(IPC_EVENTS.RENDERER_IS_READY), app: { setFrameless: (route?: string) => ipcRenderer.invoke(IPC_EVENTS.APP_SET_FRAMELESS, route) @@ -63,7 +64,12 @@ const api: WindowApi = { getCurrentWindowId: () => ipcRenderer.sendSync(IPC_EVENTS.GET_WINDOW_ID), // 发送日志 - logToMain: (logLevel: string, message: string) => ipcRenderer.send(IPC_EVENTS.LOG_TO_MAIN, logLevel, message), + logger: { + debug: (message: string, ...meta: any[]) => ipcRenderer.send(IPC_EVENTS.LOG_DEBUG, message, ...meta), + info: (message: string, ...meta: any[]) => ipcRenderer.send(IPC_EVENTS.LOG_INFO, message, ...meta), + warn: (message: string, ...meta: any[]) => ipcRenderer.send(IPC_EVENTS.LOG_WARN, message, ...meta), + error: (message: string, ...meta: any[]) => ipcRenderer.send(IPC_EVENTS.LOG_ERROR, message, ...meta), + } } contextBridge.exposeInMainWorld('api', api) \ No newline at end of file diff --git a/src/renderer/components/HeaderBar/index.vue b/src/renderer/components/HeaderBar/index.vue new file mode 100644 index 0000000..8888b30 --- /dev/null +++ b/src/renderer/components/HeaderBar/index.vue @@ -0,0 +1,76 @@ + + + + + diff --git a/src/renderer/components/NativeTooltip/index.vue b/src/renderer/components/NativeTooltip/index.vue new file mode 100644 index 0000000..42a9b93 --- /dev/null +++ b/src/renderer/components/NativeTooltip/index.vue @@ -0,0 +1,43 @@ + + + \ No newline at end of file diff --git a/src/renderer/components/TitleBar/index.vue b/src/renderer/components/TitleBar/index.vue deleted file mode 100644 index e69de29..0000000 diff --git a/src/renderer/hooks/useWinManager.ts b/src/renderer/hooks/useWinManager.ts index e69de29..5d67d6d 100644 --- a/src/renderer/hooks/useWinManager.ts +++ b/src/renderer/hooks/useWinManager.ts @@ -0,0 +1,31 @@ +export function useWinManager() { + const isMaximized = ref(false) + + function closeWindow() { + window.api.closeWindow(); + } + + function minimizeWindow() { + window.api.minimizeWindow(); + } + + function maximizeWindow() { + window.api.maximizeWindow(); + } + + onMounted(async () => { + await nextTick(); + window.api.viewIsReady(); + isMaximized.value = await window.api.isWindowMaximized(); + window.api.onWindowMaximized((_isMaximized: boolean) => isMaximized.value = _isMaximized); + }) + + return { + isMaximized, + closeWindow, + minimizeWindow, + maximizeWindow + } +}; + +export default useWinManager; diff --git a/src/renderer/main.ts b/src/renderer/main.ts index 25dc64a..496ea52 100644 --- a/src/renderer/main.ts +++ b/src/renderer/main.ts @@ -1,4 +1,4 @@ -import { createApp } from "vue"; +import { createApp, type Plugin } from "vue"; import { createPinia } from "pinia"; import router from "./router"; import App from "./App.vue"; @@ -10,6 +10,15 @@ import locale from 'element-plus/es/locale/lang/zh-cn' import "./styles/index.css"; import 'element-plus/dist/index.css' +// 引入全局组件 +import HeaderBar from './components/HeaderBar/index.vue' +import DragRegion from './components/DragRegion/index.vue' + +const components: Plugin = (app) => { + app.component('HeaderBar', HeaderBar); + app.component('DragRegion', DragRegion); +} + // 创建 Vue 应用实例 const app = createApp(App); @@ -20,6 +29,7 @@ app.use(createPinia()); // 使用 Vue Router app.use(router); app.use(ElementPlus, { locale }) +app.use(components) // 挂载应用到 DOM app.mount("#app"); diff --git a/src/renderer/utils/logger.ts b/src/renderer/utils/logger.ts new file mode 100644 index 0000000..e71cc26 --- /dev/null +++ b/src/renderer/utils/logger.ts @@ -0,0 +1,12 @@ + +export const logger = window.api.logger ?? console; + +if (window.api.logger) { + console.debug = logger.debug; + console.log = logger.info; + console.info = logger.info; + console.warn = logger.warn; + console.error = logger.error; +} + +export default logger; diff --git a/src/renderer/views/login/index.vue b/src/renderer/views/login/index.vue index 4ccd9ca..496baad 100644 --- a/src/renderer/views/login/index.vue +++ b/src/renderer/views/login/index.vue @@ -1,86 +1,92 @@