Tag 管理 + OCR 识别
本来只是基于Wails模版做点功能验证,结果一不小心,越改越像一个“能用的产品”了,这次主要做了两件事:
🏷️ Tag 标签管理🧠 OCR 图文识别
虽然功能不大,但组合起来,体验直接提升一个档次,更方便直接上手二次扩展开发。
🏷️ 一、Tag标签管理
效果图如下:
一开始这个只是做“信息管理”的,内容越来越多之后,很快就遇到一个问题:
找不到想要的东西了
这其实是工具软件都会遇到的阶段:
• 数据少 → 靠记忆 • 数据多 → 必须分类
所以我加了一个 Tag 管理页面,核心目标就两个👉 分类👉 快速检索
✨ 设计上
• Tag 独立管理 • 支持关键词匹配(为后续自动分类做准备) • 前端轻量交互(不做复杂嵌套) • 图标和背景自定义(方便多模式扩展)
最终效果是:
内容不再是“堆着”,而是“有结构地存在”。一眼图标即可锁定
🧠 二、OCR图文识别
另一个我觉得非常实用的点,是 OCR 图片识别。很多时候,我们的信息来源不是文本,而是:
• 截图 • 聊天记录 • 网页图片
如果每次都手动输入,其实挺浪费时间的。所以我做了一个很简单但很爽的能力:👉 拖一张图 → 自动识别 → 可变成可编辑文本
2.1、效果图如下

2.2、技术实现
简单说下:都是采用了调用系统内置OCR识别。macOS OCR:直接走系统 API
func RecognizeImageBase64(base64str string) (string, error) { data, err := base64.StdEncoding.DecodeString(base64str) if err != nil { return "", fmt.Errorf("base64 decode failed: %w", err) } tmp := C.CBytes(data) defer C.free(tmp) result := C.VisionOCRFromMemory(tmp, C.int(len(data))) defer C.free(unsafe.Pointer(result)) return C.GoString(result), nil}Windows OCR:调用 Windows Runtime OCR(为了减少额外安装工具包),通过 PowerShell + Go 执行
const ocrScript = `[Console]::OutputEncoding=[System.Text.Encoding]::UTF8$OutputEncoding=[System.Text.Encoding]::UTF8Add-Type -AssemblyName System.Runtime.WindowsRuntime[void][Windows.Graphics.Imaging.BitmapDecoder, Windows.Graphics, ContentType=WindowsRuntime][void][Windows.Graphics.Imaging.SoftwareBitmap, Windows.Graphics, ContentType=WindowsRuntime][void][Windows.Media.Ocr.OcrEngine, Windows.Foundation, ContentType=WindowsRuntime][void][Windows.Media.Ocr.OcrResult, Windows.Foundation, ContentType=WindowsRuntime][void][Windows.Storage.Streams.InMemoryRandomAccessStream, Windows.Storage, ContentType=WindowsRuntime][void][Windows.Storage.Streams.DataWriter, Windows.Storage, ContentType=WindowsRuntime]function Await($WinRtTask, $ResultType) { $methods = [System.WindowsRuntimeSystemExtensions].GetMethods() | Where-Object { $_.Name -eq 'AsTask' -and $_.IsGenericMethodDefinition -and $_.GetParameters().Count -eq 1 } $method = $methods[0].MakeGenericMethod($ResultType) $netTask = $method.Invoke($null, @($WinRtTask)) $netTask.Wait(-1) | Out-Null $netTask.Result}$bytes = [System.IO.File]::ReadAllBytes('{{IMAGE_PATH}}')$stream = [Windows.Storage.Streams.InMemoryRandomAccessStream]::new()$writer = [Windows.Storage.Streams.DataWriter]::new($stream)$writer.WriteBytes($bytes)$storeTask = $writer.StoreAsync()$storeAsTask = [System.WindowsRuntimeSystemExtensions].GetMethods() | Where-Object { $_.Name -eq 'AsTask' -and $_.IsGenericMethodDefinition -and $_.GetParameters().Count -eq 1} | Select-Object -First 1$storeNetTask = $storeAsTask.MakeGenericMethod([uint32]).Invoke($null, @($storeTask))$storeNetTask.Wait(-1) | Out-Null$stream.Seek(0)$decoder = Await ([Windows.Graphics.Imaging.BitmapDecoder]::CreateAsync($stream)) ([Windows.Graphics.Imaging.BitmapDecoder])$bitmap = Await ($decoder.GetSoftwareBitmapAsync()) ([Windows.Graphics.Imaging.SoftwareBitmap])$engine = [Windows.Media.Ocr.OcrEngine]::TryCreateFromUserProfileLanguages()$result = Await ($engine.RecognizeAsync($bitmap)) ([Windows.Media.Ocr.OcrResult])Write-Output $result.Text`func RecognizeImageBase64(base64str string) (string, error) { if idx := strings.Index(base64str, ","); idx != -1 { base64str = base64str[idx+1:] } data, err := base64.StdEncoding.DecodeString(base64str) if err != nil { return "", fmt.Errorf("base64 decode failed: %w", err) } tmp, err := os.CreateTemp("", "ocr-*.png") if err != nil { return "", fmt.Errorf("create temp file failed: %w", err) } imgPath := tmp.Name() tmp.Write(data) tmp.Close() defer os.Remove(imgPath) imgPath = strings.ReplaceAll(imgPath, "/", `\`) script := strings.ReplaceAll(ocrScript, "{{IMAGE_PATH}}", imgPath) cmd := exec.Command("powershell", "-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-Command", script, ) var stdout, stderr bytes.Buffer cmd.Stdout = &stdout cmd.Stderr = &stderr if err = cmd.Run(); err != nil { return "", fmt.Errorf("powershell error: %w\nstderr: %s", err, stderr.String()) } text := strings.TrimSpace(stdout.String()) if text == "" { return "", errors.New("OCR returned empty string") } return text, nil}三、组合起来后的体验
当 Tag + OCR 放在一起,其实就变成:一个“半自动信息整理工具”可以无限制整合到应用中,不管是AI工具、聊天、应用工具都适合这些功能。组合起来,就变成一个“有生产力”的东西。这其实也是做工具类产品的一个核心思路:
不做复杂功能,而是把几个简单功能都“串起来”。慢慢把它从“工具”做成“助手”。
四、运用方式
项目地址如下:Git 地址:https://github.com/JinGongX/SuiDemoGitee 地址:https://gitee.com/GG20190213/sui-demo
使用方式如下:
# git运用模版创建项目wails3 init -n myproject -t https://github.com/JinGongX/SuiDemocd myproject# gitee运用模版创建项目wails3 init -n myproject -t https://gitee.com/GG20190213/sui-demo#启动开发模式wails3 dev演示

夜雨聆风