feat: 新增6个背景选项并修复系统托盘图标重复问题
- 新增bg4-bg9共6个背景图片及对应配置 - 修复热更新时系统托盘图标重复叠加的问题 - 更新中英文文案及开发文档相关说明
@@ -55,6 +55,22 @@ Layout布局content区域的磨砂玻璃卡片圆角样式我要改动一下:
|
||||
- 隧道列表卡片、新建隧道弹窗的背景效果都改成透明磨砂玻璃效果
|
||||
- Frpc下载列表卡片的背景效果都改成透明磨砂玻璃效果
|
||||
|
||||
#### 2.5 外观设置新增卡片透明度和弹窗透明度修改
|
||||
|
||||
- 在外观设置新增两个进度条,用于拖动控制卡片磨砂玻璃效果的透明度和弹窗磨砂玻璃效果的透明度
|
||||
- 拖动进度条设置透明度的时候可以实时看到效果
|
||||
|
||||
#### 2.6 明暗主题切换,部分字体颜色没有跟随主题变化
|
||||
|
||||
- 切换暗色主题之后,部分字体颜色没有随主题切换
|
||||
- 仪表盘页面里面,系统信息卡片、CPU和内存占用卡片、frpc版本、实时日志这些卡片里面的字体应该没有随主题变化
|
||||
- 服务器页面里面,服务器三个字没有变化颜色
|
||||
- 隧道列表页面里面,隧道列表三个字没有改变颜色
|
||||
- Frpc卸载页面里面,Frpc下载、所有架构Frpc、所有架构Frps这些没有改变颜色
|
||||
- 侧边栏的CPU/内存占用,状态文字没有改变颜色
|
||||
- 设置页面里面也有一些没有随主题改变颜色
|
||||
- 整体全部检查并且修复一下
|
||||
|
||||
### 3. 功能开发
|
||||
|
||||
#### 3.1 开发服务器配置功能
|
||||
@@ -138,4 +154,9 @@ Layout布局content区域的磨砂玻璃卡片圆角样式我要改动一下:
|
||||
- 点击退出,整个程序退出,如果穿透正在启动运行,一并停止并退出软件
|
||||
- 点击Header栏里面的关闭按钮,目前是直接退出整个程序,现在改成先出现一个对话框,对话框内有两个单选项分别是最小化到系统托盘、直接退出,如果选择最小化到系统托盘,则保持程序运行状态,隐藏到系统托盘,如果是直接退出,则停止穿透并退出软件(Mac和Windows同步)
|
||||
|
||||
开发过程中使用到的组件尽可能全部使用Antdv库里面的,另外我引入的有tailwindcss原子化组件、auto-import和components依赖可以简化引入,开发之前尽可能先阅读一下package.json,看一下有哪些依赖可以简化代码开发
|
||||
开发过程中使用到的组件尽可能全部使用Antdv库里面的,另外我引入的有tailwindcss原子化组件、auto-import和components依赖可以简化引入,开发之前尽可能先阅读一下package.json,看一下有哪些依赖可以简化代码开发
|
||||
|
||||
#### 3.8 系统托盘图标BUG修改
|
||||
|
||||
- 开发阶段每次修改代码热更新之后,系统托盘图标就会新增一个
|
||||
- 需要修复确保只有一个系统托盘图标
|
||||
|
Before Width: | Height: | Size: 359 KiB After Width: | Height: | Size: 339 KiB |
|
After Width: | Height: | Size: 192 KiB |
|
After Width: | Height: | Size: 300 KiB |
|
After Width: | Height: | Size: 321 KiB |
|
After Width: | Height: | Size: 292 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 684 KiB |
@@ -5,13 +5,47 @@ import { useFrpcStore } from "@/stores/frpc"
|
||||
import { useWindowStore } from "@/stores/window"
|
||||
import { isTauri } from "@/utils/window"
|
||||
|
||||
/** 托盘图标固定 id(便于热更新 / 重载时清理残留的旧图标) */
|
||||
const TRAY_ID = "frpilot-tray"
|
||||
|
||||
/** 是否已初始化,避免重复创建托盘 */
|
||||
let initialized = false
|
||||
|
||||
/** 停止状态 / 语言监听,热更新时释放,避免旧实例订阅残留 */
|
||||
let stopWatchers: (() => void) | null = null
|
||||
|
||||
function errMsg(e: unknown) {
|
||||
return e instanceof Error ? e.message : String(e)
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除所有同 id 的残留托盘图标。
|
||||
*
|
||||
* Tauri 在 Rust 侧用 `Vec` 保存托盘图标,且 JS 资源不会随页面卸载 / GC 自动释放
|
||||
* (官方文档明确说明 JS 无法在对象被回收时执行清理),因此开发时每次热更新或
|
||||
* 页面重载都会保留旧图标并叠加出一个新的。创建前先按 id 清空,保证始终只有一个。
|
||||
*
|
||||
* `removeById` 在找不到对应托盘时会抛错,据此作为循环终止条件(同时兜底清理
|
||||
* 先前已经叠加的多个图标)。
|
||||
*/
|
||||
async function removeExistingTrays(TrayIcon: typeof import("@tauri-apps/api/tray").TrayIcon) {
|
||||
for (let i = 0; i < 10; i += 1) {
|
||||
try {
|
||||
await TrayIcon.removeById(TRAY_ID)
|
||||
} catch {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 开发模式热更新:模块被替换时释放监听,避免旧实例的订阅残留
|
||||
if (import.meta.hot) {
|
||||
import.meta.hot.dispose(() => {
|
||||
stopWatchers?.()
|
||||
stopWatchers = null
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化系统托盘(Tauri 前端 API 方式,参见 Tauri 文档「系统托盘」)。
|
||||
*
|
||||
@@ -43,6 +77,9 @@ async function createTray() {
|
||||
import("@tauri-apps/api/app"),
|
||||
])
|
||||
|
||||
// 先清理开发时热更新 / 页面重载残留的托盘图标,避免叠加出多个
|
||||
await removeExistingTrays(TrayIcon)
|
||||
|
||||
// 显示窗口(始终可用)
|
||||
const showItem = await MenuItem.new({
|
||||
id: "tray-show",
|
||||
@@ -86,7 +123,7 @@ async function createTray() {
|
||||
const icon = await defaultWindowIcon().catch(() => null)
|
||||
|
||||
await TrayIcon.new({
|
||||
id: "frpilot-tray",
|
||||
id: TRAY_ID,
|
||||
icon: icon ?? undefined,
|
||||
tooltip: "Frpilot",
|
||||
menu,
|
||||
@@ -101,7 +138,7 @@ async function createTray() {
|
||||
})
|
||||
|
||||
// Frpc 运行状态变化时同步菜单可用状态
|
||||
watch(
|
||||
const stopStatusWatch = watch(
|
||||
[() => frpcStore.canStart, () => frpcStore.canStop],
|
||||
([canStart, canStop]) => {
|
||||
void startItem.setEnabled(canStart)
|
||||
@@ -110,7 +147,7 @@ async function createTray() {
|
||||
)
|
||||
|
||||
// 语言切换时同步菜单文案
|
||||
watch(
|
||||
const stopTextWatch = watch(
|
||||
() => appStore.language,
|
||||
() => {
|
||||
void showItem.setText(translate("tray.show"))
|
||||
@@ -119,6 +156,11 @@ async function createTray() {
|
||||
void quitItem.setText(translate("tray.quit"))
|
||||
},
|
||||
)
|
||||
|
||||
stopWatchers = () => {
|
||||
stopStatusWatch()
|
||||
stopTextWatch()
|
||||
}
|
||||
}
|
||||
|
||||
/** 托盘「启动穿透」:复用仪表盘的一键启动逻辑 */
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
import bg1 from "@/assets/images/bg-1.webp"
|
||||
import bg2 from "@/assets/images/bg-2.webp"
|
||||
// import bg3 from "@/assets/images/bg-3.webp" // 暂时下架「背景三」,需要时与下方选项一并恢复
|
||||
import bg3 from "@/assets/images/bg-3.webp"
|
||||
import bg4 from "@/assets/images/bg-4.webp"
|
||||
import bg5 from "@/assets/images/bg-5.webp"
|
||||
import bg6 from "@/assets/images/bg-6.webp"
|
||||
import bg7 from "@/assets/images/bg-7.webp"
|
||||
import bg8 from "@/assets/images/bg-8.webp"
|
||||
import bg9 from "@/assets/images/bg-9.webp"
|
||||
|
||||
/** 窗口背景图片标识 */
|
||||
export type BackgroundKey = "none" | "bg-1" | "bg-2" | "bg-3"
|
||||
export type BackgroundKey = "none" | "bg-1" | "bg-2" | "bg-3" | "bg-4" | "bg-5" | "bg-6" | "bg-7" | "bg-8" | "bg-9"
|
||||
|
||||
export interface BackgroundOption {
|
||||
/** 唯一标识 */
|
||||
@@ -19,7 +25,13 @@ export const backgroundOptions: BackgroundOption[] = [
|
||||
{ key: "none", label: "settings.appearance.none", url: "" },
|
||||
{ key: "bg-1", label: "settings.appearance.bg1", url: bg1 },
|
||||
{ key: "bg-2", label: "settings.appearance.bg2", url: bg2 },
|
||||
// { key: "bg-3", label: "settings.appearance.bg3", url: bg3 },
|
||||
{ key: "bg-3", label: "settings.appearance.bg3", url: bg3 },
|
||||
{ key: "bg-4", label: "settings.appearance.bg4", url: bg4 },
|
||||
{ key: "bg-5", label: "settings.appearance.bg5", url: bg5 },
|
||||
{ key: "bg-6", label: "settings.appearance.bg6", url: bg6 },
|
||||
{ key: "bg-7", label: "settings.appearance.bg7", url: bg7 },
|
||||
{ key: "bg-8", label: "settings.appearance.bg8", url: bg8 },
|
||||
{ key: "bg-9", label: "settings.appearance.bg9", url: bg9 },
|
||||
]
|
||||
|
||||
export const DEFAULT_BACKGROUND: BackgroundKey = "none"
|
||||
|
||||
@@ -88,7 +88,13 @@
|
||||
"none": "Default",
|
||||
"bg1": "Background 1",
|
||||
"bg2": "Background 2",
|
||||
"bg3": "Background 3"
|
||||
"bg3": "Background 3",
|
||||
"bg4": "Background 4",
|
||||
"bg5": "Background 5",
|
||||
"bg6": "Background 6",
|
||||
"bg7": "Background 7",
|
||||
"bg8": "Background 8",
|
||||
"bg9": "Background 9"
|
||||
}
|
||||
},
|
||||
"server": {
|
||||
|
||||
@@ -88,7 +88,13 @@
|
||||
"none": "默认",
|
||||
"bg1": "背景一",
|
||||
"bg2": "背景二",
|
||||
"bg3": "背景三"
|
||||
"bg3": "背景三",
|
||||
"bg4": "背景四",
|
||||
"bg5": "背景五",
|
||||
"bg6": "背景六",
|
||||
"bg7": "背景七",
|
||||
"bg8": "背景八",
|
||||
"bg9": "背景九"
|
||||
}
|
||||
},
|
||||
"server": {
|
||||
|
||||