Browse Source
- 新增 `electron.vite.config.1749712333417.mjs` 配置文件,配置Vite构建相关插件和参数 - 创建 `packages/utils/index.ts` 工具类文件,添加通用工具函数 `isPromise` 和 `slash` - 扩展 `packages/utils/main/index.ts` 工具类,新增 `getFileUrl` 和 `getPreloadUrl` 方法 - 新增 `packages/utils/main/session/cookies.ts` 实现Electron会话cookie管理功能 - 新增 `packages/utils/main/session/index.ts` 实现Electron多会话隔离功能 - 重构多处代码引用路径,将原 `main/utils` 迁移至 `packages/utils` 统一管理 - 新增设置模块相关代码:`src/common/event/Setting/*` 实现配置同步保存功能 - 新增设置页面 `src/renderer/src/pages/setting/index.vue` 提供UI交互 - 优化导航栏菜单逻辑,移除模块切换功能,整合为统一菜单main
26 changed files with 532 additions and 273 deletions
@ -0,0 +1,133 @@ |
|||
// electron.vite.config.ts
|
|||
import { resolve } from "path"; |
|||
import { defineConfig, externalizeDepsPlugin } from "electron-vite"; |
|||
import vue from "@vitejs/plugin-vue"; |
|||
import vueJsx from "@vitejs/plugin-vue-jsx"; |
|||
import UnoCSS from "unocss/vite"; |
|||
import AutoImport from "unplugin-auto-import/vite"; |
|||
import Components from "unplugin-vue-components/vite"; |
|||
import VueMacros from "unplugin-vue-macros/vite"; |
|||
import { VueRouterAutoImports } from "unplugin-vue-router"; |
|||
import VueRouter from "unplugin-vue-router/vite"; |
|||
import Layouts from "vite-plugin-vue-layouts"; |
|||
import VueI18nPlugin from "@intlify/unplugin-vue-i18n/vite"; |
|||
import monacoEditorPlugin from "vite-plugin-monaco-editor"; |
|||
import IconsResolver from "unplugin-icons/resolver"; |
|||
import Icons from "unplugin-icons/vite"; |
|||
var __electron_vite_injected_dirname = "D:\\@code\\xyx\\electron-app"; |
|||
var electron_vite_config_default = defineConfig({ |
|||
main: { |
|||
resolve: { |
|||
alias: { |
|||
config: resolve("config"), |
|||
main: resolve("src/main"), |
|||
common: resolve("src/common"), |
|||
"@res": resolve("resources") |
|||
} |
|||
}, |
|||
plugins: [externalizeDepsPlugin()] |
|||
}, |
|||
preload: { |
|||
build: { |
|||
lib: { |
|||
entry: { |
|||
index: resolve(__electron_vite_injected_dirname, "./src/preload/index.ts"), |
|||
plugin: resolve(__electron_vite_injected_dirname, "./src/preload/plugin.ts") |
|||
} |
|||
} |
|||
}, |
|||
plugins: [externalizeDepsPlugin()] |
|||
}, |
|||
renderer: { |
|||
root: resolve(__electron_vite_injected_dirname, "./src/renderer"), |
|||
resolve: { |
|||
alias: { |
|||
config: resolve("config"), |
|||
common: resolve("src/common"), |
|||
"@": resolve("src/renderer/src"), |
|||
"@res": resolve("resources") |
|||
} |
|||
}, |
|||
css: { |
|||
preprocessorOptions: { |
|||
scss: { |
|||
additionalData: `@use "@/assets/style/global" as *;
|
|||
`,
|
|||
api: "modern-compiler" |
|||
} |
|||
} |
|||
}, |
|||
build: { |
|||
rollupOptions: { |
|||
input: { |
|||
main: resolve(__electron_vite_injected_dirname, "./src/renderer/index.html"), |
|||
about: resolve(__electron_vite_injected_dirname, "./src/renderer/about.html") |
|||
} |
|||
} |
|||
}, |
|||
plugins: [ |
|||
UnoCSS(), |
|||
VueMacros({ |
|||
plugins: { |
|||
vue: vue(), |
|||
vueJsx: vueJsx(), |
|||
vueRouter: VueRouter({ |
|||
root: resolve(__electron_vite_injected_dirname, "src/renderer"), |
|||
// https://github.com/posva/unplugin-vue-router
|
|||
extensions: [".vue", ".setup.tsx"], |
|||
exclude: ["**/_ui"] |
|||
}) |
|||
} |
|||
}), |
|||
VueI18nPlugin({ |
|||
compositionOnly: false, |
|||
include: resolve(__electron_vite_injected_dirname, "packages/locales/languages/**") |
|||
}), |
|||
Layouts({ |
|||
layoutsDirs: "src/layouts", |
|||
pagesDirs: "src/pages", |
|||
defaultLayout: "default", |
|||
extensions: ["vue", "setup.tsx"], |
|||
exclude: ["**/_ui"] |
|||
}), |
|||
// https://github.com/antfu/unplugin-auto-import
|
|||
AutoImport({ |
|||
imports: [ |
|||
"vue", |
|||
"@vueuse/core", |
|||
VueRouterAutoImports, |
|||
{ |
|||
// add any other imports you were relying on
|
|||
"vue-router/auto": ["useLink"] |
|||
}, |
|||
"vue-i18n" |
|||
], |
|||
dts: true, |
|||
dirs: ["src/composables"], |
|||
vueTemplate: true |
|||
}), |
|||
// https://github.com/antfu/vite-plugin-components
|
|||
Components({ |
|||
dts: true, |
|||
dirs: ["src/components", "src/ui"], |
|||
resolvers: [ |
|||
IconsResolver({ |
|||
prefix: "icon" |
|||
}) |
|||
] |
|||
}), |
|||
Icons(), |
|||
// https://wf0.github.io/example/plugins/Formatter.html
|
|||
// @ts-ignore ...
|
|||
monacoEditorPlugin.default({ |
|||
publicPath: "monacoeditorwork", |
|||
customDistPath() { |
|||
return resolve(__electron_vite_injected_dirname, "out/renderer/monacoeditorwork"); |
|||
} |
|||
}) |
|||
] |
|||
} |
|||
}); |
|||
export { |
|||
electron_vite_config_default as default |
|||
}; |
@ -0,0 +1,11 @@ |
|||
export function isPromise(value: () => any) { |
|||
return value && Object.prototype.toString.call(value) === "[object Promise]" |
|||
} |
|||
|
|||
export function slash(path: string) { |
|||
const isExtendedLengthPath = path.startsWith("\\\\?\\") |
|||
if (isExtendedLengthPath) { |
|||
return path |
|||
} |
|||
return path.replace(/\\/g, "/") |
|||
} |
@ -1,5 +1,22 @@ |
|||
import { is } from "@electron-toolkit/utils" |
|||
import { webContents } from "electron" |
|||
import { join } from "node:path" |
|||
import { slash } from "utils" |
|||
|
|||
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)) |
|||
} |
|||
|
|||
export function getFileUrl(app: string) { |
|||
let winURL = "" |
|||
if (is.dev && process.env["ELECTRON_RENDERER_URL"]) { |
|||
winURL = process.env["ELECTRON_RENDERER_URL"] + `/${app}#/` |
|||
} else { |
|||
winURL = join(__dirname, `../renderer/${app}#/`) |
|||
} |
|||
return slash(winURL) |
|||
} |
|||
|
|||
export function getPreloadUrl(file) { |
|||
return join(__dirname, `../preload/${file}.mjs`) |
|||
} |
|||
|
@ -0,0 +1,63 @@ |
|||
import { defineStore } from "pinia" |
|||
import { Setting } from "." |
|||
import type { IConfig } from "config" |
|||
|
|||
let rawConfig: IConfig = Setting.getInstance().sync() as unknown as IConfig |
|||
|
|||
export const useSettingStore = defineStore( |
|||
"Setting", |
|||
() => { |
|||
const config = ref(JSON.parse(JSON.stringify(rawConfig))) |
|||
const diffKeys = ref<(keyof IConfig)[]>([]) |
|||
const isSame = computed(() => { |
|||
return diffKeys.value.length === 0 |
|||
}) |
|||
watch( |
|||
() => config.value, |
|||
() => { |
|||
diffKeys.value = [] |
|||
;(Object.keys(config.value) as (keyof IConfig)[]).forEach((key: keyof IConfig) => { |
|||
if (config.value[key] !== rawConfig[key]) { |
|||
diffKeys.value.push(key) |
|||
} |
|||
}) |
|||
}, |
|||
{ |
|||
deep: true, |
|||
immediate: true, |
|||
}, |
|||
) |
|||
const reset = () => { |
|||
const tempConfig = JSON.parse(JSON.stringify(rawConfig)) |
|||
config.value = tempConfig |
|||
} |
|||
const isSaving = ref(false) |
|||
const save = async () => { |
|||
if (isSaving.value) { |
|||
return |
|||
} |
|||
isSaving.value = true |
|||
try { |
|||
const tempConfig = JSON.parse(JSON.stringify(unref(config))) |
|||
await Setting.getInstance().save(tempConfig) |
|||
isSaving.value = false |
|||
rawConfig = JSON.parse(JSON.stringify(tempConfig)) |
|||
config.value = tempConfig |
|||
} catch (error) { |
|||
isSaving.value = false |
|||
throw error |
|||
} |
|||
} |
|||
return { |
|||
config, |
|||
isSame, |
|||
isSaving, |
|||
diffKeys, |
|||
reset, |
|||
save, |
|||
} |
|||
}, |
|||
{ |
|||
persist: false, |
|||
}, |
|||
) |
@ -0,0 +1,23 @@ |
|||
import { ApiFactory } from "common/lib/abstract" |
|||
import { BaseSingleton } from "base" |
|||
import { IConfig } from "config" |
|||
|
|||
class Setting extends BaseSingleton { |
|||
constructor() { |
|||
super() |
|||
} |
|||
|
|||
private get api() { |
|||
return ApiFactory.getApiClient() |
|||
} |
|||
|
|||
sync() { |
|||
return this.api.callSync("SettingCommand.sync") |
|||
} |
|||
|
|||
save(config: IConfig) { |
|||
return this.api.call("SettingCommand.save", config) |
|||
} |
|||
} |
|||
|
|||
export { Setting } |
@ -0,0 +1,13 @@ |
|||
import Setting, { IConfig } from "setting/main" |
|||
|
|||
export default class SettingCommand { |
|||
static init() { |
|||
console.log("SettingCommand init") |
|||
} |
|||
sync() { |
|||
return Setting.config() |
|||
} |
|||
save(config: IConfig) { |
|||
return Setting.set(config) |
|||
} |
|||
} |
@ -0,0 +1,16 @@ |
|||
import { EventMaps } from "helper/updater/common" |
|||
import { defineStore } from "pinia" |
|||
|
|||
export const useSettingStore = defineStore( |
|||
"Updater", |
|||
() => { |
|||
getApi<EventMaps>().on("update-progress", (_, data) => { |
|||
console.log(data) |
|||
}) |
|||
|
|||
return {} |
|||
}, |
|||
{ |
|||
persist: false, |
|||
}, |
|||
) |
@ -1,15 +1,13 @@ |
|||
import { EventMaps } from "helper/updater/common" |
|||
import { BaseEvent } from "common/lib/abstract" |
|||
|
|||
const curProgress = ref(0) |
|||
|
|||
getApi<EventMaps>().on("update-progress", (_, data) => { |
|||
console.log(data) |
|||
}) |
|||
class Updater extends BaseEvent { |
|||
constructor() { |
|||
super() |
|||
} |
|||
|
|||
function useUpdate() { |
|||
return { |
|||
curProgress, |
|||
test() { |
|||
this.api |
|||
} |
|||
} |
|||
|
|||
export { useUpdate } |
|||
export { Updater } |
|||
|
@ -1,28 +0,0 @@ |
|||
import { is } from "@electron-toolkit/utils" |
|||
import { join } from "node:path" |
|||
|
|||
export function getFileUrl(app: string) { |
|||
let winURL = "" |
|||
if (is.dev && process.env["ELECTRON_RENDERER_URL"]) { |
|||
winURL = process.env["ELECTRON_RENDERER_URL"] + `/${app}#/` |
|||
} else { |
|||
winURL = join(__dirname, `../renderer/${app}#/`) |
|||
} |
|||
return slash(winURL) |
|||
} |
|||
|
|||
export function getPreloadUrl(file) { |
|||
return join(__dirname, `../preload/${file}.mjs`) |
|||
} |
|||
|
|||
export function isPromise(value: () => any) { |
|||
return value && Object.prototype.toString.call(value) === "[object Promise]" |
|||
} |
|||
|
|||
export function slash(path: string) { |
|||
const isExtendedLengthPath = path.startsWith("\\\\?\\") |
|||
if (isExtendedLengthPath) { |
|||
return path |
|||
} |
|||
return path.replace(/\\/g, "/") |
|||
} |
@ -1,9 +1,7 @@ |
|||
<script setup lang="ts"></script> |
|||
|
|||
<template> |
|||
<div h-full flex flex-col> |
|||
<div v-for="i in 200" :key="i">{{ i }}</div> |
|||
</div> |
|||
<div h-full flex flex-col>sad</div> |
|||
</template> |
|||
|
|||
<style lang="scss" scoped></style> |
|||
|
@ -0,0 +1,18 @@ |
|||
<template> |
|||
<div h-full flex> |
|||
<div w="200px" border-r="#E5E5E5 solid 1px">左侧菜单</div> |
|||
<div flex="1" w="0"> |
|||
{{ settingStore.isSame }}--{{ settingStore.diffKeys }} |
|||
<input v-model="settingStore.config['update.repo']" type="text" /> |
|||
{{ settingStore.config["update.repo"] }} |
|||
<button v-if="!settingStore.isSame" :disabled="settingStore.isSaving" @click="settingStore.save()">保存</button> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup lang="ts"> |
|||
import { useSettingStore } from "common/event/Setting/hook" |
|||
|
|||
const settingStore = useSettingStore() |
|||
console.log(settingStore.config) |
|||
</script> |
@ -1,11 +1,8 @@ |
|||
|
|||
import { createPinia } from 'pinia' |
|||
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate' |
|||
import { createPinia } from "pinia" |
|||
import piniaPluginPersistedstate from "pinia-plugin-persistedstate" |
|||
|
|||
const pinia = createPinia() |
|||
pinia.use(piniaPluginPersistedstate) |
|||
|
|||
export default pinia |
|||
export { |
|||
pinia |
|||
} |
|||
export { pinia } |
|||
|
@ -1,30 +0,0 @@ |
|||
import { defineStore } from "pinia" |
|||
|
|||
export enum ModuleType { |
|||
CommonPanel = 0, |
|||
CodeMgr = 1, |
|||
LinkBox = 2, |
|||
} |
|||
export const useModuleStore = defineStore("module", () => { |
|||
const curModuleId = ref<ModuleType>(ModuleType.CommonPanel) |
|||
|
|||
const modules: Record<"id" | "label", string | ModuleType>[] = [ |
|||
{ id: ModuleType.CommonPanel, label: "全能面板" }, |
|||
{ id: ModuleType.CodeMgr, label: "代码管家" }, |
|||
{ id: ModuleType.LinkBox, label: "超链鉴宝" }, |
|||
] |
|||
|
|||
const setModule = (type: ModuleType) => { |
|||
console.log(type); |
|||
curModuleId.value = type |
|||
} |
|||
const curModule = computed(() => { |
|||
return modules.find(m => m.id === curModuleId.value) |
|||
}) |
|||
return { |
|||
ModuleType, |
|||
setModule, |
|||
modules, |
|||
curModule, |
|||
} |
|||
}) |
Loading…
Reference in new issue