Private
Public Access
1
0

重构:Wails升级/mermaid主题切换/代码高亮修复/文件系统UI重构

- Wails v2.12.0升级(App绑定新增API、runtime类型扩展)
- 修复mermaid暗色主题切换渲染失败(SVG textContent污染→data-mermaid-src保存源码)
- 修复代码高亮全语言失效(languageMap静态白名单替代运行时hljs检查)
- 文件系统:FileListPanel重写、FileItemRow合并删除、Toolbar简化
- 新增剪贴板图片粘贴(Ctrl+V粘贴图片到当前目录)
- 死代码清理:DeviceTest/errorHandler/useLocalStorage移除
- MarkdownEditor优化、theme store增强、CodeMirror加载器精简
This commit is contained in:
2026-04-11 16:46:43 +08:00
parent efc042fcd3
commit 7dbd57a8b6
40 changed files with 1274 additions and 1404 deletions

67
app.go
View File

@@ -6,11 +6,13 @@ import (
"net/http"
"os"
"path/filepath"
"regexp"
stdruntime "runtime"
"strings"
"time"
"github.com/jung-kurt/gofpdf"
"golang.org/x/sys/windows/registry"
"u-desk/internal/api"
"u-desk/internal/common"
"u-desk/internal/database"
@@ -22,6 +24,9 @@ import (
"github.com/wailsapp/wails/v2/pkg/runtime"
)
// PDF 有序列表正则(包级变量,避免循环内重复编译)
var orderedListRe = regexp.MustCompile(`^\d+\.\s+`)
// App 应用结构体
type App struct {
ctx context.Context
@@ -37,6 +42,10 @@ type App struct {
isAlwaysOnTop bool
}
// App 方法命名约定:
// - 多参数操作 → XxxRequest 结构体Wails 自动生成 TS 类型)
// - 单参数查询/简单操作 → 直接参数
// NewApp 创建新的应用实例
func NewApp() *App {
return &App{}
@@ -286,6 +295,17 @@ func (a *App) WriteFile(req WriteFileRequest) error {
return a.filesystem.WriteFile(req.Path, req.Content)
}
// SaveBase64FileRequest 保存 Base64 编码的二进制文件
type SaveBase64FileRequest struct {
Path string `json:"path"`
Content string `json:"content"` // base64 编码的文件内容
}
// SaveBase64File 将 base64 内容解码后写入文件(用于图片等二进制数据)
func (a *App) SaveBase64File(req SaveBase64FileRequest) error {
return a.filesystem.SaveBase64File(req.Path, req.Content)
}
// ListDir 列出目录
func (a *App) ListDir(path string) ([]map[string]interface{}, error) {
return a.filesystem.ListDir(path)
@@ -393,6 +413,31 @@ func (a *App) ResolveShortcut(lnkPath string) (map[string]interface{}, error) {
}, nil
}
// getWindowsSpecialFolder 从注册表读取 Windows 特殊文件夹的真实路径
// 用户可通过系统设置修改下载/桌面/文档等目录位置,注册表记录实际路径
func getWindowsSpecialFolder(guid string, fallbackName string) string {
key, err := registry.OpenKey(registry.CURRENT_USER,
`Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders`,
registry.READ)
if err != nil {
return ""
}
defer key.Close()
val, _, err := key.GetStringValue(guid)
if err != nil || val == "" {
return ""
}
// 展开 %USERPROFILE% 等环境变量
path := os.ExpandEnv(val)
// 验证路径存在
if _, err := os.Stat(path); err != nil {
return ""
}
return path
}
// GetCommonPaths 获取常用系统路径
func (a *App) GetCommonPaths() (map[string]string, error) {
homeDir, err := os.UserHomeDir()
@@ -401,10 +446,22 @@ func (a *App) GetCommonPaths() (map[string]string, error) {
}
paths := map[string]string{
"home": homeDir,
"desktop": filepath.Join(homeDir, "Desktop"),
"documents": filepath.Join(homeDir, "Documents"),
"downloads": filepath.Join(homeDir, "Downloads"),
"home": homeDir,
}
// Windows: 从注册表读取特殊文件夹真实路径(用户可能已修改位置)
folderGUIDs := map[string]string{
"desktop": "{B4BFCC3A-DB2C-424C-B029-7FE99A87C641}",
"documents": "{D20B4C7F-5EA7-40D4B25E-039F6F1FCC8A}",
"downloads": "{374DE290-123F-4565-9164-39C4925E467B}",
}
for name, guid := range folderGUIDs {
if p := getWindowsSpecialFolder(guid, name); p != "" {
paths[name] = p
} else {
// folderGUIDs 的 key 均为 ASCII无需 Unicode 处理
paths[name] = filepath.Join(homeDir, strings.ToUpper(name[:1])+name[1:])
}
}
// Windows: 动态添加所有盘符
@@ -978,7 +1035,7 @@ func (a *App) ExportMarkdownToPDF(markdownContent string) (string, error) {
pdf.Cell(10, 7, "•")
pdf.Cell(0, 7, strings.TrimPrefix(line, "- "))
pdf.Ln(7)
} else if strings.HasPrefix(line, "1. ") || strings.HasPrefix(line, "2. ") || strings.HasPrefix(line, "3. ") {
} else if orderedListRe.MatchString(line) {
// 有序列表
pdf.SetFont("Arial", "", 12)
pdf.Cell(10, 7, strings.TrimSpace(strings.SplitN(line, ".", 2)[0]) + ".")