Browse Source

大刀阔斧

feat/优化
谢亚昕 1 week ago
parent
commit
161b691a6c
  1. 12
      build/entitlements.mac.plist
  2. 11
      config/app_config.json
  3. 16
      config/exe_config.json
  4. 52
      config/index.ts
  5. 41
      electron-builder-prod.js
  6. 4
      electron-builder.backup.yml
  7. 6
      package.json
  8. 4
      packages/helper/updater/main/index.ts
  9. 4
      packages/logger/main.ts
  10. 10
      packages/setting/main.ts
  11. 4
      src/common/event/PlatForm/main/command.ts
  12. 30
      src/common/event/Snippet/main/command.ts
  13. 8
      src/common/event/Updater/index.ts
  14. 8
      src/main/modules/window-manager/windowsMap.ts
  15. 8
      src/renderer/components.d.ts
  16. 12
      src/renderer/src/ui/NavBar.vue
  17. 24
      src/types/global.d.ts

12
build/entitlements.mac.plist

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
<true/>
</dict>
</plist>

11
config/app_config.json

@ -0,0 +1,11 @@
{
"storagePath": "$storagePath$",
"language": "zh",
"dev:debug": 2,
"common.theme": "auto",
"update.hoturl": "https://alist.xieyaxin.top/d/%E8%B5%84%E6%BA%90/%E6%B5%8B%E8%AF%95%E6%96%87%E4%BB%B6.zip?sign=eqy35CR-J1SOQZz0iUN2P3B0BiyZPdYH0362nLXbUhE=:1749085071",
"update.repo": "wood-desktop",
"update.owner": "npmrun",
"update.allowDowngrade": false,
"update.allowPrerelease": false
}

16
config/exe_config.json

@ -0,0 +1,16 @@
{
"name": "zephyr",
"appId": "com.zephyr.app",
"win": {
"executableName": "zephyr"
},
"linux": {
"target": ["AppImage", "snap", "deb"],
"maintainer": "electronjs.org",
"category": "Utility"
},
"publish": {
"provider": "generic",
"url": "https://example.com/auto-updates"
}
}

52
config/index.ts

@ -1,52 +1,20 @@
import { LogLevel } from "logger/common"
import AppConfig from "./app_config.json"
import ExeConfig from "./exe_config.json"
// 定义主题类型
type ThemeType = "light" | "dark" | "auto"
// 定义语言类型
type LanguageType = "zh" | "en"
// 定义编辑器logo类型
type LogoType = "logo" | "bg"
// 配置接口定义
export interface IDefaultConfig {
export type IConfig = typeof AppConfig &
Pick<Partial<typeof AppConfig>, "common.theme"> & {
language: LanguageType
"common.theme": ThemeType
debug: LogLevel
"desktop:wallpaper": string
"update.hoturl": string
"update.repo"?: string
"update.owner"?: string
"update.allowDowngrade": boolean
"update.allowPrerelease": boolean
"editor.bg": string
"editor.logoType": LogoType
"editor.fontFamily": string
"snippet.storagePath": string
storagePath: string
}
"dev:debug": LogLevel
}
interface IConfig {
app_title: string
default_config: IDefaultConfig
}
// 默认配置导出
export default {
app_title: "zephyr", // 和风
default_config: {
storagePath: "$storagePath$",
language: "zh",
debug: LogLevel.INFO,
"common.theme": "auto",
"desktop:wallpaper": "",
"editor.bg": "",
"editor.logoType": "logo",
"editor.fontFamily": "Cascadia Mono, Consolas, 'Courier New', monospace",
"update.hoturl":
"https://alist.xieyaxin.top/d/%E8%B5%84%E6%BA%90/%E6%B5%8B%E8%AF%95%E6%96%87%E4%BB%B6.zip?sign=eqy35CR-J1SOQZz0iUN2P3B0BiyZPdYH0362nLXbUhE=:1749085071",
"update.repo": "wood-desktop",
"update.owner": "npmrun",
"update.allowDowngrade": false,
"update.allowPrerelease": false,
"snippet.storagePath": "$storagePath$/snippets",
},
} as const satisfies IConfig
AppConfig,
ExeConfig,
}

41
electron-builder-prod.js

@ -0,0 +1,41 @@
import fs from "node:fs"
const text = fs.readFileSync("./config/exe_config.json", "utf8")
const ExeConfig = JSON.parse(text)
export default {
appId: ExeConfig.appId,
productName: ExeConfig.name,
directories: {
buildResources: "build",
},
files: [
"!**/.vscode/*",
"!src/*",
"!electron.vite.config.{js,ts,mjs,cjs}",
"!{.eslintignore,.eslintrc.cjs,.prettierignore,.prettierrc.yaml,dev-app-update.yml,CHANGELOG.md,README.md}",
"!{.env,.env.*,.npmrc,pnpm-lock.yaml}",
"!{tsconfig.json,tsconfig.node.json,tsconfig.web.json}",
],
asarUnpack: ["node_modules/sqlite3", "out/main/chunks/*.node", "resources/*"],
win: {
executableName: ExeConfig.win.executableName,
},
nsis: {
artifactName: "${name}-${version}-setup.${ext}",
shortcutName: "${productName}",
uninstallDisplayName: "${productName}",
createDesktopShortcut: "always",
},
dmg: {
artifactName: "${name}-${version}.${ext}",
},
linux: ExeConfig.linux,
appImage: {
artifactName: "${name}-${version}.${ext}",
},
npmRebuild: false,
publish: ExeConfig.publish,
electronDownload: {
mirror: "https://npmmirror.com/mirrors/electron/",
},
}

4
electron-builder.yml → electron-builder.backup.yml

@ -10,7 +10,9 @@ files:
- "!{.env,.env.*,.npmrc,pnpm-lock.yaml}"
- "!{tsconfig.json,tsconfig.node.json,tsconfig.web.json}"
asarUnpack:
- resources/**
- node_modules/sqlite3
- out/main/chunks/*.node
- resources/*
win:
executableName: zephyr
nsis:

6
package.json

@ -20,9 +20,9 @@
"build": "npm run typecheck && electron-vite build",
"postinstall": "electron-builder install-app-deps",
"build:unpack": "npm run build && electron-builder --dir",
"build:win": "npm run build && electron-builder --win",
"build:mac": "npm run build && electron-builder --mac",
"build:linux": "npm run build && electron-builder --linux"
"build:win": "npm run build && electron-builder --win --config=electron-builder-prod.js",
"build:mac": "npm run build && electron-builder --mac --config=electron-builder-prod.js",
"build:linux": "npm run build && electron-builder --linux --config=electron-builder-prod.js"
},
"dependencies": {
"@electron-toolkit/preload": "^3.0.1",

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

@ -1,17 +1,17 @@
import pkg from "electron-updater"
import { app, dialog } from "electron"
import Setting from "setting/main"
import EventEmitter from "events"
import { BaseSingleton } from "base"
import { fetchHotUpdatePackage, flagNeedUpdate } from "./hot"
import Locales from "locales/main"
import _logger from "logger/main"
import { buildEmitter } from "base/event/main"
const logger = _logger.createNamespace("updater")
const { autoUpdater } = pkg
class _Updater extends BaseSingleton {
public events = new EventEmitter()
public events = buildEmitter()
private timer: ReturnType<typeof setInterval> | null = null
// autoReplace = false
async triggerHotUpdate(autoReplace = false) {

4
packages/logger/main.ts

@ -21,7 +21,7 @@ export interface LoggerOptions {
// 默认配置
const DEFAULT_OPTIONS: LoggerOptions = {
level: config.default_config.debug,
level: config.AppConfig["dev:debug"],
namespace: "app",
console: true,
file: true,
@ -261,7 +261,7 @@ export class Logger {
const logger = Logger.getInstance()
logger.init()
emitter.on("update", setting => {
logger.setLevel(setting.debug)
logger.setLevel(setting["dev:debug"])
})
// 应用退出时关闭日志流

10
packages/setting/main.ts

@ -3,24 +3,22 @@ import { app } from "electron"
import path from "path"
import { cloneDeep } from "lodash"
import Config from "config"
import type { IDefaultConfig } from "config"
import type { IConfig } from "config"
import _logger from "logger/main"
const logger = _logger.createNamespace("setting")
type IConfig = IDefaultConfig
type IOnFunc = (n: IConfig, c: IConfig, keys?: (keyof IConfig)[]) => void
type IT = (keyof IConfig)[] | keyof IConfig | "_"
let storagePath = path.join(app.getPath("documents"), Config.app_title)
const storagePathDev = path.join(app.getPath("documents"), Config.app_title + "-dev")
let storagePath = path.join(app.getPath("documents"), Config.ExeConfig.name)
const storagePathDev = path.join(app.getPath("documents"), Config.ExeConfig.name + "-dev")
if (process.env.NODE_ENV === "development") {
storagePath = storagePathDev
}
const _tempConfig = cloneDeep(Config.default_config as IConfig)
const _tempConfig = cloneDeep(Config.AppConfig as IConfig)
Object.keys(_tempConfig).forEach(key => {
if (typeof _tempConfig[key] === "string" && _tempConfig[key].includes("$storagePath$")) {
_tempConfig[key] = _tempConfig[key].replace(/\$storagePath\$/g, storagePath)

4
src/common/event/PlatForm/main/command.ts

@ -19,11 +19,11 @@ export default class PlatFormCommand {
}
logSetLevel(level: LogLevel) {
return setting.set("debug", level)
return setting.set("dev:debug", level)
}
logGetLevel() {
return setting.values("debug")
return setting.values("dev:debug")
}
setTitlBar(options: TitleBarOverlayOptions) {

30
src/common/event/Snippet/main/command.ts

@ -1,13 +1,13 @@
import fs from "fs-extra"
import path from "path/posix"
import Setting from "setting/main"
// import fs from "fs-extra"
// import path from "path/posix"
// import Setting from "setting/main"
// 代码片段命令处理器
// base/__snippet__.json 基础信息
// 路径做为ID, 当前文件夹的信息
export default class SnippetCommand {
storagePath: string = Setting.values("snippet.storagePath")
// storagePath: string = Setting.values("snippet.storagePath")
constructor() {
const handler = {
@ -26,19 +26,19 @@ export default class SnippetCommand {
}
async check() {
const stat = await fs.statSync(this.storagePath)
const inforFile = path.resolve(this.storagePath, "__snippet__.json")
if (stat.isDirectory() && stat.size == 0) {
await fs.writeJSON(inforFile, {})
// 空文件夹, 初始化信息
return true
} else {
const isExist = await fs.pathExists(inforFile)
return isExist
}
// const stat = await fs.statSync(this.storagePath)
// const inforFile = path.resolve(this.storagePath, "__snippet__.json")
// if (stat.isDirectory() && stat.size == 0) {
// await fs.writeJSON(inforFile, {})
// // 空文件夹, 初始化信息
// return true
// } else {
// const isExist = await fs.pathExists(inforFile)
// return isExist
// }
}
getTree() {
return this.storagePath
// return this.storagePath
}
}

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

@ -1,10 +1,10 @@
import { EventEnum } from "helper/updater/common"
// import { EventEnum } from "helper/updater/common"
const curProgress = ref(0)
api.on(EventEnum.UPDATE_PROGRESS, ({ percent, now, all }) => {
curProgress.value = percent
})
// .on(EventEnum.UPDATE_PROGRESS, ({ percent, now, all }) => {
// curProgress.value = percent
// })
function useUpdate() {
return {

8
src/main/modules/window-manager/windowsMap.ts

@ -1,4 +1,4 @@
import config from "config"
import Config from "config"
import { BrowserWindowConstructorOptions } from "electron"
import { getFileUrl, getPreloadUrl } from "main/utils"
import icon from "@res/icon.png?asset"
@ -49,7 +49,7 @@ export function getWindowsMap(): Record<string, IConfig> {
url: getFileUrl("index.html"),
confrimWindowClose: true,
confrimWindowCloseText: {
title: config.app_title,
title: Config.ExeConfig.name,
defaultId: 0,
cancelId: 0,
message: "确定要关闭吗?",
@ -73,7 +73,7 @@ export function getWindowsMap(): Record<string, IConfig> {
overideWindowOpts: false,
confrimWindowClose: true,
confrimWindowCloseText: {
title: config.app_title,
title: Config.ExeConfig.name,
defaultId: 0,
cancelId: 0,
message: "确定要关闭吗?",
@ -92,7 +92,7 @@ export function getWindowsMap(): Record<string, IConfig> {
transparent: false,
alwaysOnTop: false,
icon: icon,
title: config.app_title,
title: Config.ExeConfig.name,
webPreferences: {
devTools: false,
sandbox: true,

8
src/renderer/components.d.ts

@ -10,19 +10,11 @@ declare module 'vue' {
export interface GlobalComponents {
AdjustLine: typeof import('./src/components/AdjustLine.vue')['default']
CodeEditor: typeof import('./src/components/CodeEditor/code-editor.vue')['default']
IconBiCollectionFill: typeof import('~icons/bi/collection-fill')['default']
IconBiTrashFill: typeof import('~icons/bi/trash-fill')['default']
IconFluentCollections24Regular: typeof import('~icons/fluent/collections24-regular')['default']
IconFluentCollectionsEmpty16Filled: typeof import('~icons/fluent/collections-empty16-filled')['default']
IconHugeiconsInbox: typeof import('~icons/hugeicons/inbox')['default']
IconIconParkSolidCollectComputer: typeof import('~icons/icon-park-solid/collect-computer')['default']
IconIconParkTwotoneDataAll: typeof import('~icons/icon-park-twotone/data-all')['default']
IconMdiLightInbox: typeof import('~icons/mdi-light/inbox')['default']
IconMynauiTrash: typeof import('~icons/mynaui/trash')['default']
IconSolarBoxBoldDuotone: typeof import('~icons/solar/box-bold-duotone')['default']
IconSolarHome2Outline: typeof import('~icons/solar/home2-outline')['default']
'IconStash:arrowReplyDuotone': typeof import('~icons/stash/arrow-reply-duotone')['default']
IconTdesignMapCollection: typeof import('~icons/tdesign/map-collection')['default']
NavBar: typeof import('./src/ui/NavBar.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']

12
src/renderer/src/ui/NavBar.vue

@ -13,7 +13,7 @@
<div h-full px-2 flex items-center gap-1 justify-between>
<div flex items-center gap-1>
<img w="16px" h="16px" :src="icon" />
<div relative h-full inline-flex items-center text-sm>{{ config.app_title }}</div>
<div relative h-full inline-flex items-center text-sm>{{ Config.ExeConfig.name }}</div>
<div relative class="list">
<div class="item" @click="onClickMenu">{{ t("browser.navbar.menu.label") }}</div>
<div class="item" @click="onClickPage">{{ ModuleStore.curModule?.label ?? "选择模块" }}</div>
@ -57,7 +57,7 @@
<script setup lang="ts">
import icon from "@res/icon.png"
import config from "config"
import Config from "config"
import { PopupMenu } from "@/bridge/PopupMenu"
import { usePlatForm } from "common/event/PlatForm/hook"
import { LogLevel } from "logger/common"
@ -143,17 +143,15 @@
const menu = new PopupMenu(toRaw(ModuleStore.modules as any))
menu.setClickEvent(item => {
ModuleStore.setModule(item.id)
if(item.id === ModuleStore.ModuleType.CommonPanel) {
}
// if (item.id === ModuleStore.ModuleType.CommonPanel) {}
})
const obj = e.target.getBoundingClientRect()
menu.show({ x: ~~obj.x, y: ~~(obj.y + obj.height) })
}
const onClickSetting = () => {
const onClickSetting = () => {
router.push("/setting")
}
}
</script>
<style lang="scss" scoped>

24
src/types/global.d.ts

@ -1,20 +1,24 @@
type Api = {
call: (command: string, ...args: any[]) => Promise<any>
callLong: (command: string, ...args: any[]) => Promise<any>
callSync: (command: string, ...args: any[]) => any
send: (command: string, ...argu: any[]) => any
sendSync: (command: string, ...argu: any[]) => any
on: <T extends string>(command: T, cb: (event: IpcRendererEvent, ...args: any[]) => void) => () => void
once: (command: string, cb: (event: IpcRendererEvent, ...args: any[]) => void) => () => void
off: (command: string, cb: (event: IpcRendererEvent, ...args: any[]) => void) => void
offAll: (command: string) => void
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
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
popupMenu: (options: IPopupMenuOption) => void
}
declare const electron: typeof import("@electron-toolkit/preload").electronAPI
declare const api: Api
declare const getApi: <T>() => Api<T>
interface Window {
electron: typeof import("@electron-toolkit/preload").electronAPI
api: Api
getApi: getApi
}

Loading…
Cancel
Save