feat: 全新 Logo 设计 + 扩展工具一键安装功能

Logo 设计:
- 现代化爪印图标,紫蓝渐变配色
- 生成全套尺寸 PNG (16-1024px) + @2x 版本
- macOS icns + Windows ico + SVG 源文件
- 系统托盘和应用图标全面更新

扩展工具增强:
- cftunnel 支持一键安装(自动下载安装脚本)
- 实时显示安装进度和日志输出
- 安装完成后自动刷新状态
- 优化未安装状态的 UI 提示
This commit is contained in:
晴天
2026-02-28 15:11:48 +08:00
parent 6946ffda17
commit 333a3e54bb
29 changed files with 188 additions and 2 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 19 KiB

BIN
src-tauri/icons/16x16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 704 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
src-tauri/icons/256x256.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 448 B

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

BIN
src-tauri/icons/512x512.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

BIN
src-tauri/icons/64x64.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 715 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 442 B

After

Width:  |  Height:  |  Size: 704 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 806 B

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 806 B

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

48
src-tauri/icons/icon.svg Normal file
View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="512" height="512" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#6366f1;stop-opacity:1" />
<stop offset="100%" style="stop-color:#4f46e5;stop-opacity:1" />
</linearGradient>
<filter id="shadow">
<feGaussianBlur in="SourceAlpha" stdDeviation="8"/>
<feOffset dx="0" dy="4" result="offsetblur"/>
<feComponentTransfer>
<feFuncA type="linear" slope="0.3"/>
</feComponentTransfer>
<feMerge>
<feMergeNode/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
</defs>
<!-- 背景圆形 -->
<circle cx="256" cy="256" r="240" fill="url(#grad1)" filter="url(#shadow)"/>
<!-- 爪印主体 - 中心大圆 -->
<ellipse cx="256" cy="280" rx="70" ry="85" fill="white" opacity="0.95"/>
<!-- 四个爪尖 -->
<!-- 左上 -->
<ellipse cx="160" cy="180" rx="35" ry="55" fill="white" opacity="0.95"
transform="rotate(-25 160 180)"/>
<!-- 左下 -->
<ellipse cx="180" cy="360" rx="35" ry="55" fill="white" opacity="0.95"
transform="rotate(15 180 360)"/>
<!-- 右上 -->
<ellipse cx="352" cy="180" rx="35" ry="55" fill="white" opacity="0.95"
transform="rotate(25 352 180)"/>
<!-- 右下 -->
<ellipse cx="332" cy="360" rx="35" ry="55" fill="white" opacity="0.95"
transform="rotate(-15 332 360)"/>
<!-- 面板网格装饰(科技感) -->
<g opacity="0.15" stroke="white" stroke-width="2" fill="none">
<line x1="256" y1="80" x2="256" y2="432"/>
<line x1="80" y1="256" x2="432" y2="256"/>
<circle cx="256" cy="256" r="120"/>
<circle cx="256" cy="256" r="180"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -194,3 +194,77 @@ pub fn get_clawapp_status() -> Result<Value, String> {
result.insert("url".into(), Value::String("http://localhost:3210".into()));
Ok(Value::Object(result))
}
/// 一键安装 cftunnel
#[tauri::command]
pub async fn install_cftunnel(app: tauri::AppHandle) -> Result<String, String> {
use std::process::Stdio;
use std::io::{BufRead, BufReader};
use tauri::Emitter;
let _ = app.emit("install-log", "开始安装 cftunnel...");
let _ = app.emit("install-progress", 10);
// 下载并安装脚本
let install_script = r#"
#!/bin/bash
set -e
cd /tmp
echo "下载 cftunnel..."
curl -fsSL https://raw.githubusercontent.com/qingchencloud/cftunnel/main/install.sh -o cftunnel-install.sh
chmod +x cftunnel-install.sh
echo "执行安装..."
./cftunnel-install.sh
echo "安装完成"
"#;
let _ = app.emit("install-log", "下载安装脚本...");
let _ = app.emit("install-progress", 30);
let mut child = Command::new("bash")
.arg("-c")
.arg(install_script)
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()
.map_err(|e| format!("启动安装进程失败: {e}"))?;
let stderr = child.stderr.take();
let stdout = child.stdout.take();
// 读取 stderr
let app2 = app.clone();
let handle = std::thread::spawn(move || {
if let Some(pipe) = stderr {
for line in BufReader::new(pipe).lines().map_while(Result::ok) {
let _ = app2.emit("install-log", &line);
}
}
});
// 读取 stdout
let mut progress = 40;
if let Some(pipe) = stdout {
for line in BufReader::new(pipe).lines().map_while(Result::ok) {
let _ = app.emit("install-log", &line);
if progress < 90 {
progress += 5;
let _ = app.emit("install-progress", progress);
}
}
}
let _ = handle.join();
let _ = app.emit("install-progress", 95);
let status = child.wait().map_err(|e| format!("等待安装进程失败: {e}"))?;
let _ = app.emit("install-progress", 100);
if !status.success() {
let _ = app.emit("install-log", "❌ 安装失败");
return Err("安装失败,请查看日志".into());
}
let _ = app.emit("install-log", "✅ cftunnel 安装成功");
Ok("安装成功".into())
}

View File

@@ -46,6 +46,7 @@ pub fn run() {
extensions::cftunnel_action,
extensions::get_cftunnel_logs,
extensions::get_clawapp_status,
extensions::install_cftunnel,
])
.run(tauri::generate_context!())
.expect("启动 ClawPanel 失败");