Browse Source

重构事件广播系统并优化项目结构

- 新增 `utils` workspace 包,将广播功能从主进程工具模块迁移至此
- 重构更新器模块的事件类型定义,使用字符串字面量替代枚举类型
- 调整更新进度事件的参数类型,增加详细的进度数据传递
- 修复全局类型定义中的 `IpcRendererEvent` 重复拼写错误
- 清理主页面组件代码,移除未使用的导航栏实现
- 添加应用初始化日志输出,便于调试启动过程
- 修正类型声明文件路径配置,确保 `popup-menu.d.ts` 被正确包含
- 更新依赖项版本,包括 `@intlify/shared` 从 11.1.3 升级到 11.1.5
main
谢亚昕 1 week ago
parent
commit
f72c87f562
  1. 1
      package.json
  2. 6
      packages/helper/updater/common.ts
  3. 8
      packages/helper/updater/main/handler.ts
  4. 4
      packages/helper/updater/main/hot/index.ts
  5. 0
      packages/utils/index.ts
  6. 5
      packages/utils/main/index.ts
  7. 7
      packages/utils/package.json
  8. 19
      pnpm-lock.yaml
  9. 2
      src/common/event/Tabs/main/command.ts
  10. 8
      src/common/event/Updater/index.ts
  11. 2
      src/main/App.ts
  12. 5
      src/main/utils/index.ts
  13. 83
      src/renderer/src/pages/index/index copy.vue
  14. 82
      src/renderer/src/pages/index/index.vue
  15. 1
      src/renderer/typed-router.d.ts
  16. 2
      src/types/errorHandler.d.ts
  17. 12
      src/types/global.d.ts
  18. 0
      src/types/popup-menu.d.ts
  19. 4
      tsconfig.node.json
  20. 3
      tsconfig.web.json

1
package.json

@ -73,6 +73,7 @@
"simplebar-vue": "^2.4.0",
"typescript": "^5.7.3",
"unocss": "^0.64.1",
"utils": "workspace:*",
"unplugin-auto-import": "^19.1.0",
"unplugin-icons": "^22.1.0",
"unplugin-vue-components": "^28.4.0",

6
packages/helper/updater/common.ts

@ -1,7 +1,3 @@
export const enum EventEnum {
UPDATE_PROGRESS = "update-progress",
}
export type EventMaps = {
[EventEnum.UPDATE_PROGRESS]: () => void
"update-progress": (data: { percent: number; all: number; now: number }) => void
}

8
packages/helper/updater/main/handler.ts

@ -1,8 +1,6 @@
import { broadcast } from "main/utils"
import { EventEnum } from "../common"
import { broadcast } from "utils/main"
import { EventMaps } from "../common"
export { EventEnum }
export function emit(key: EventEnum, ...args: any[]) {
export function emit(key: keyof EventMaps, ...args: Parameters<EventMaps[keyof EventMaps]>) {
broadcast(key, ...args)
}

4
packages/helper/updater/main/hot/index.ts

@ -7,7 +7,7 @@ import download from "./download"
import extract from "extract-zip"
import _logger from "logger/main"
import { emit, EventEnum } from "../handler"
import { emit } from "../handler"
const logger = _logger.createNamespace("hot-updater")
@ -92,7 +92,7 @@ export async function fetchHotUpdatePackage(updatePackageUrl: string) {
url: updatePackageUrl,
onprocess(now, all) {
logger.debug(`下载进度: ${((now / all) * 100).toFixed(2)}%`)
emit(EventEnum.UPDATE_PROGRESS, { percent: (now / all) * 100, now, all })
emit("update-progress", { percent: (now / all) * 100, now, all })
},
})
fs.writeFileSync(downloadPath, Buffer.from(arrayBuffer))

0
packages/utils/index.ts

5
packages/utils/main/index.ts

@ -0,0 +1,5 @@
import { webContents } from "electron"
export const broadcast = <T extends Record<string, (...argu: any[]) => void>>(event: keyof T, ...args: Parameters<T[keyof T]>) => {
webContents.getAllWebContents().forEach(browser => browser.send(event as any, ...args))
}

7
packages/utils/package.json

@ -0,0 +1,7 @@
{
"name": "utils",
"version": "1.0.0",
"keywords": [],
"author": "",
"license": "ISC"
}

19
pnpm-lock.yaml

@ -162,6 +162,9 @@ importers:
unplugin-vue-router:
specifier: ^0.11.2
version: 0.11.2(rollup@4.26.0)(vue-router@4.5.0(vue@3.5.13(typescript@5.7.3)))(vue@3.5.13(typescript@5.7.3))
utils:
specifier: workspace:*
version: link:packages/utils
vite:
specifier: ^5.4.14
version: 5.4.14(@types/node@20.17.19)(sass@1.85.0)
@ -194,6 +197,8 @@ importers:
packages/setting: {}
packages/utils: {}
packages:
7zip-bin@5.2.0:
@ -776,8 +781,8 @@ packages:
resolution: {integrity: sha512-2kGiWoXaeV8HZlhU/Nml12oTbhv7j2ufsJ5vQaa0VTjzUmZVdd/nmKFRAOJ/FtjO90Qba5AnZDwsrY7ZND5udA==}
engines: {node: '>= 16'}
'@intlify/shared@11.1.3':
resolution: {integrity: sha512-pTFBgqa/99JRA2H1qfyqv97MKWJrYngXBA/I0elZcYxvJgcCw3mApAoPW3mJ7vx3j+Ti0FyKUFZ4hWxdjKaxvA==}
'@intlify/shared@11.1.5':
resolution: {integrity: sha512-+I4vRzHm38VjLr/CAciEPJhGYFzWWW4HMTm+6H3WqknXLh0ozNX9oC8ogMUwTSXYR/wGUb1/lTpNziiCH5MybQ==}
engines: {node: '>= 16'}
'@intlify/shared@12.0.0-alpha.2':
@ -4355,7 +4360,7 @@ snapshots:
'@intlify/shared@11.1.1': {}
'@intlify/shared@11.1.3': {}
'@intlify/shared@11.1.5': {}
'@intlify/shared@12.0.0-alpha.2': {}
@ -4363,8 +4368,8 @@ snapshots:
dependencies:
'@eslint-community/eslint-utils': 4.4.1(eslint@8.57.1)
'@intlify/bundle-utils': 10.0.0(vue-i18n@11.1.1(vue@3.5.13(typescript@5.7.3)))
'@intlify/shared': 11.1.3
'@intlify/vue-i18n-extensions': 8.0.0(@intlify/shared@11.1.3)(@vue/compiler-dom@3.5.13)(vue-i18n@11.1.1(vue@3.5.13(typescript@5.7.3)))(vue@3.5.13(typescript@5.7.3))
'@intlify/shared': 11.1.5
'@intlify/vue-i18n-extensions': 8.0.0(@intlify/shared@11.1.5)(@vue/compiler-dom@3.5.13)(vue-i18n@11.1.1(vue@3.5.13(typescript@5.7.3)))(vue@3.5.13(typescript@5.7.3))
'@rollup/pluginutils': 5.1.4(rollup@4.26.0)
'@typescript-eslint/scope-manager': 8.25.0
'@typescript-eslint/typescript-estree': 8.25.0(typescript@5.7.3)
@ -4386,11 +4391,11 @@ snapshots:
- supports-color
- typescript
'@intlify/vue-i18n-extensions@8.0.0(@intlify/shared@11.1.3)(@vue/compiler-dom@3.5.13)(vue-i18n@11.1.1(vue@3.5.13(typescript@5.7.3)))(vue@3.5.13(typescript@5.7.3))':
'@intlify/vue-i18n-extensions@8.0.0(@intlify/shared@11.1.5)(@vue/compiler-dom@3.5.13)(vue-i18n@11.1.1(vue@3.5.13(typescript@5.7.3)))(vue@3.5.13(typescript@5.7.3))':
dependencies:
'@babel/parser': 7.26.9
optionalDependencies:
'@intlify/shared': 11.1.3
'@intlify/shared': 11.1.5
'@vue/compiler-dom': 3.5.13
vue: 3.5.13(typescript@5.7.3)
vue-i18n: 11.1.1(vue@3.5.13(typescript@5.7.3))

2
src/common/event/Tabs/main/command.ts

@ -1,7 +1,7 @@
import { inject } from "inversify"
import Tabs from "main/modules/tabs"
import WindowManager from "main/modules/window-manager"
import { broadcast } from "main/utils"
import { broadcast } from "utils/main"
class TabsCommand {
constructor(

8
src/common/event/Updater/index.ts

@ -1,10 +1,10 @@
// import { EventEnum } from "helper/updater/common"
import { EventMaps } from "helper/updater/common"
const curProgress = ref(0)
// .on(EventEnum.UPDATE_PROGRESS, ({ percent, now, all }) => {
// curProgress.value = percent
// })
getApi<EventMaps>().on("update-progress", (_, data) => {
console.log(data)
})
function useUpdate() {
return {

2
src/main/App.ts

@ -11,6 +11,7 @@ import IOC from "./_ioc"
import DB from "./modules/db"
import Zephyr from "./modules/zephyr"
import { crashHandler } from "logger/crash-handler"
import logger from "logger/main"
protocol.registerSchemesAsPrivileged([
// {
@ -60,6 +61,7 @@ class App extends BaseClass {
}
async init() {
logger.debug("初始化App")
// 新开窗口的时候,会有个窗口闪烁的问题,也可以理解为渐入效果
// 主进程中添加如下代码即可
app.commandLine.appendSwitch("wm-window-animations-disabled")

5
src/main/utils/index.ts

@ -1,6 +1,5 @@
import { is } from "@electron-toolkit/utils"
import { join } from "node:path"
import { webContents } from "electron"
export function getFileUrl(app: string) {
let winURL = ""
@ -20,10 +19,6 @@ export function isPromise(value: () => any) {
return value && Object.prototype.toString.call(value) === "[object Promise]"
}
export const broadcast = <T extends string>(event: T, ...args: any[]) => {
webContents.getAllWebContents().forEach(browser => browser.send(event, ...args))
}
export function slash(path: string) {
const isExtendedLengthPath = path.startsWith("\\\\?\\")
if (isExtendedLengthPath) {

83
src/renderer/src/pages/index/index copy.vue

@ -0,0 +1,83 @@
<script setup lang="ts">
import { useSnippet } from "common/event/Snippet/hook"
definePage({
meta: {
home: true,
},
})
const { getTree } = useSnippet()
const activeLeft = ref<number | null>(null)
function clickActive(e: any) {
const el = e.target as HTMLDivElement
const { x } = el.getBoundingClientRect()
const { width: parentWidth } = el.parentElement!.getBoundingClientRect()
const newLeft = +((x / parentWidth) * 100).toFixed(2)
if (newLeft === activeLeft.value) {
activeLeft.value = null
return
}
activeLeft.value = +((x / parentWidth) * 100).toFixed(2)
}
async function click() {
console.log(await getTree())
}
</script>
<template>
<div h-full flex>
<div border-r-coolGray-200 border-r-1 border-r-solid flex flex-col max-w-300px w="3/10">
<div class="list">
<div v-if="activeLeft !== null" class="active" :style="{ left: activeLeft + '%' }"></div>
<div class="item" @click="clickActive">
<IconHugeiconsInbox class="icon" />
<span class="text">盒子</span>
</div>
<div class="item" @click="clickActive">
<IconFluentCollections24Regular class="icon" />
<span class="text">收藏</span>
</div>
<div class="item" @click="clickActive">
<IconSolarHome2Outline class="icon" />
<span class="text">全部</span>
</div>
<div class="item" @click="clickActive">
<IconMynauiTrash class="icon" />
<span class="text">废纸篓</span>
</div>
</div>
<div @click="click">文件树</div>
</div>
<div max-w-300px w="3/10" border-r-coolGray-200 border-r-1 border-r-solid>文件树</div>
<div>aa</div>
</div>
</template>
<style lang="scss" scoped>
.list {
@apply flex border-b-solid border-b-1 border-b-coolGray-200 relative;
.active {
position: absolute;
left: 0;
transition: left 0.5s ease;
width: 25%;
height: 100%;
pointer-events: none;
background-color: rgba(193, 193, 193, 0.2);
z-index: -1;
}
.item {
@apply p-x-3 p-y-2 cursor-pointer flex flex-col gap-1 flex-1 items-center hover:bg-gray-100;
.icon {
@apply w-5 h-5;
pointer-events: none;
}
.text {
@apply text-xs;
pointer-events: none;
}
}
}
</style>

82
src/renderer/src/pages/index/index.vue

@ -1,83 +1,9 @@
<script setup lang="ts">
import { useSnippet } from "common/event/Snippet/hook"
definePage({
meta: {
home: true,
},
})
const { getTree } = useSnippet()
const activeLeft = ref<number | null>(null)
function clickActive(e: any) {
const el = e.target as HTMLDivElement
const { x } = el.getBoundingClientRect()
const { width: parentWidth } = el.parentElement!.getBoundingClientRect()
const newLeft = +((x / parentWidth) * 100).toFixed(2)
if (newLeft === activeLeft.value) {
activeLeft.value = null
return
}
activeLeft.value = +((x / parentWidth) * 100).toFixed(2)
}
async function click() {
console.log(await getTree())
}
</script>
<script setup lang="ts"></script>
<template>
<div h-full flex>
<div border-r-coolGray-200 border-r-1 border-r-solid flex flex-col max-w-300px w="3/10">
<div class="list">
<div v-if="activeLeft !== null" class="active" :style="{ left: activeLeft + '%' }"></div>
<div class="item" @click="clickActive">
<IconHugeiconsInbox class="icon" />
<span class="text">盒子</span>
</div>
<div class="item" @click="clickActive">
<IconFluentCollections24Regular class="icon" />
<span class="text">收藏</span>
</div>
<div class="item" @click="clickActive">
<IconSolarHome2Outline class="icon" />
<span class="text">全部</span>
</div>
<div class="item" @click="clickActive">
<IconMynauiTrash class="icon" />
<span class="text">废纸篓</span>
</div>
</div>
<div @click="click">文件树</div>
</div>
<div max-w-300px w="3/10" border-r-coolGray-200 border-r-1 border-r-solid>文件树</div>
<div>aa</div>
<div h-full flex flex-col>
<div v-for="i in 200" :key="i">{{ i }}</div>
</div>
</template>
<style lang="scss" scoped>
.list {
@apply flex border-b-solid border-b-1 border-b-coolGray-200 relative;
.active {
position: absolute;
left: 0;
transition: left 0.5s ease;
width: 25%;
height: 100%;
pointer-events: none;
background-color: rgba(193, 193, 193, 0.2);
z-index: -1;
}
.item {
@apply p-x-3 p-y-2 cursor-pointer flex flex-col gap-1 flex-1 items-center hover:bg-gray-100;
.icon {
@apply w-5 h-5;
pointer-events: none;
}
.text {
@apply text-xs;
pointer-events: none;
}
}
}
</style>
<style lang="scss" scoped></style>

1
src/renderer/typed-router.d.ts

@ -19,6 +19,7 @@ declare module 'vue-router/auto-routes' {
*/
export interface RouteNamedMap {
'//': RouteRecordInfo<'//', '/', Record<never, never>, Record<never, never>>,
'//index copy': RouteRecordInfo<'//index copy', '/index copy', Record<never, never>, Record<never, never>>,
'/[...all]': RouteRecordInfo<'/[...all]', '/:all(.*)', { all: ParamValue<true> }, { all: ParamValue<false> }>,
'about': RouteRecordInfo<'about', '/about', Record<never, never>, Record<never, never>>,
'/browser': RouteRecordInfo<'/browser', '/browser', Record<never, never>, Record<never, never>>,

2
src/types/errorHandler.d.ts

@ -2,4 +2,4 @@ declare const errorHandler: import("logger/preload-error").IRendererErrorHandler
interface Window {
errorHandler: import("logger/preload-error").IRendererErrorHandler
}
}

12
src/types/global.d.ts

@ -1,12 +1,12 @@
type FireFN = (...argu: any[]) => void
type Api<T extends Record<string | symbol, FireFN>> = {
call: <S extends keyof T>(command: S, ...args: Parameters<T[S]>) => ReturnType<T[S]>
callLong: <S extends keyof T>(command: S, ...args: Parameters<T[S]>) => ReturnType<T[S]>
callSync: <S extends keyof T>(command: S, ...args: Parameters<T[S]>) => ReturnType<T[S]>
send: <S extends keyof T>(command: S, ...argu: Parameters<T[S]>) => ReturnType<T[S]>
sendSync: <S extends keyof T>(command: S, ...argu: Parameters<T[S]>) => ReturnType<T[S]>
on: <S extends keyof T>(command: S, cb: (event: IpcRendererEvent, ...args: Parameters<T[S]>) => void) => () => void
call: (command: string, ...args: any[]) => any
callLong: (command: string, ...args: any[]) => any
callSync: (command: string, ...args: any[]) => any
send: (command: string, ...argu: any[]) => any
sendSync: (command: string, ...argu: any[]) => any
on: <S extends keyof T>(command: S, cb: (event: IpcRendererEventIpcRendererEvent, ...args: Parameters<T[S]>) => void) => () => void
once: <S extends keyof T>(command: S, cb: (event: IpcRendererEvent, ...args: Parameters<T[S]>) => void) => () => void
off: <S extends keyof T>(command: S, cb: (event: IpcRendererEvent, ...args: Parameters<T[S]>) => void) => void
offAll: <S extends keyof T>(command: S) => void

0
src/types/popup-menu.ts → src/types/popup-menu.d.ts

4
tsconfig.node.json

@ -3,6 +3,7 @@
"include": [
"electron.vite.config.*",
"src/main/**/*",
"src/types/popup-menu.d.ts",
"src/preload/**/*",
"config/**/*",
"packages/locales/main.ts",
@ -67,6 +68,9 @@
"base/*": [
"packages/base/*"
],
"utils/*": [
"packages/utils/*"
],
}
}
}

3
tsconfig.web.json

@ -67,6 +67,9 @@
"base/*": [
"packages/base/*"
],
"utils/*": [
"packages/utils/*"
],
}
}
}

Loading…
Cancel
Save