diff --git a/plugins/f-provider/public/plugin.json b/plugins/f-provider/public/plugin.json
index 4dcaa083..820887b6 100644
--- a/plugins/f-provider/public/plugin.json
+++ b/plugins/f-provider/public/plugin.json
@@ -4,7 +4,7 @@
"title": "ZTools 提供商",
"description": "OCR + 翻译提供商集合(百度/谷歌/有道/微软翻译、微信 OCR)",
"author": "kaineooo",
- "version": "1.0.0",
+ "version": "1.0.1",
"main": "index.html",
"preload": "preload/services.js",
"logo": "logo.png",
@@ -44,9 +44,7 @@
"explain": "OCR 识别与翻译(关键词进入管理;图片/选中文本进入识别或翻译)",
"icon": "logo.png",
"cmds": [
- {
- "label": "ZTools 提供商"
- },
+ "ZTools 提供商",
{
"type": "img",
"label": "识别图片文字"
@@ -84,9 +82,7 @@
"icon": "logo.png",
"platform": ["win32", "darwin"],
"cmds": [
- {
- "label": "截图识别文字"
- }
+ "截图识别文字"
]
}
],
diff --git a/plugins/f-provider/public/preload/services.js b/plugins/f-provider/public/preload/services.js
index df206595..13e65e76 100644
--- a/plugins/f-provider/public/preload/services.js
+++ b/plugins/f-provider/public/preload/services.js
@@ -71,6 +71,36 @@ window.services = {
return filePath
},
+ // 插件 logo 绝对路径(用于 createBrowserWindow 的 icon,让子窗口任务栏/标题栏用插件图标)。
+ // logo.png 位于插件根目录(plugin.json 的 logo 字段)。
+ pluginLogoPath() {
+ return path.join(__dirname, '..', 'logo.png')
+ },
+
+ // 插件 logo 的 data URI(用于子窗口
展示图标,注入到渲染层)。
+ pluginLogoDataUrl() {
+ try {
+ const p = path.join(__dirname, '..', 'logo.png')
+ const buf = fs.readFileSync(p)
+ return 'data:image/png;base64,' + buf.toString('base64')
+ } catch (_) {
+ return ''
+ }
+ },
+
+ // 插件 logo 的 NativeImage 对象(用于 createBrowserWindow 的 icon)。
+ // Windows 下传字符串路径时任务栏按钮仍按 AppID 取宿主 exe 图标,
+ // 传 NativeImage 才能让任务栏真正显示插件图标。
+ pluginLogoNativeImage() {
+ try {
+ // ZTools 在 preload 提供 require('electron').nativeImage
+ const { nativeImage } = require('electron')
+ return nativeImage.createFromPath(path.join(__dirname, '..', 'logo.png'))
+ } catch (_) {
+ return null
+ }
+ },
+
// ─── 微信 OCR(基于 wechat_ocr.node 原生模块)─────────────────────────
// 原生模块懒加载:首次调用时才 require + init,避免插件加载即拉起
// WeChatOCR.exe 子进程(Windows)。
diff --git a/plugins/f-provider/screen-ocr-result.html b/plugins/f-provider/screen-ocr-result.html
new file mode 100644
index 00000000..c38207d9
--- /dev/null
+++ b/plugins/f-provider/screen-ocr-result.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+ 截图识别结果
+
+
+
+
+
+
diff --git a/plugins/f-provider/src/env.d.ts b/plugins/f-provider/src/env.d.ts
index 251a76ac..77375bc1 100644
--- a/plugins/f-provider/src/env.d.ts
+++ b/plugins/f-provider/src/env.d.ts
@@ -94,6 +94,12 @@ declare global {
readFileAsDataURL: (file: string) => string
writeTextFile: (text: string) => string
writeImageFile: (base64Url: string) => string | undefined
+ /** 插件 logo 绝对路径(用于 createBrowserWindow 的 icon)。 */
+ pluginLogoPath: () => string
+ /** 插件 logo 的 data URI(用于子窗口
展示图标)。 */
+ pluginLogoDataUrl: () => string
+ /** 插件 logo 的 NativeImage(用于 createBrowserWindow 的 icon,Windows 任务栏更可靠)。 */
+ pluginLogoNativeImage: () => BrowserWindow.NativeImage | null
/**
* OCR Provider 核心能力:image 为 本地路径 / data URI / http(s) URL。
* 返回 provider 契约结构;失败抛错。
diff --git a/plugins/f-provider/src/screenOcrResult.ts b/plugins/f-provider/src/screenOcrResult.ts
new file mode 100644
index 00000000..a004ee50
--- /dev/null
+++ b/plugins/f-provider/src/screenOcrResult.ts
@@ -0,0 +1,23 @@
+import { createApp } from 'vue'
+import ZToolsUI from 'ztools-ui'
+import 'ztools-ui/style'
+import { useZtoolsTheme } from 'ztools-ui'
+import './main.css'
+import ScreenOcrResult from './views/ScreenOcrResult.vue'
+
+// 结果展示窗口入口(由 ztools.createBrowserWindow 打开)。
+//
+// 与主窗口的区别:该窗口由 createBrowserWindow 创建,**不带 preload**,
+// 也没有可靠的 window.ztools API(子窗口未必注入)。因此窗口只做展示——
+// 主窗口在外层完成「截图 + OCR 识别」后,通过 webContents.executeJavaScript
+// 把识别结果(imageSrc + lines + isDark)注入到本窗口。
+//
+// 注入方式:主窗口调用 executeJavaScript('window.__loadScreenOcrResult({...})')。
+// 本入口在挂载后挂载 window.__loadScreenOcrResult,并把数据交给组件渲染。
+
+// useZtoolsTheme 在无 window.ztools 时会优雅降级(不报错),主题以注入的 isDark 为准。
+useZtoolsTheme()
+
+const app = createApp(ScreenOcrResult)
+app.use(ZToolsUI)
+app.mount('#app')
diff --git a/plugins/f-provider/src/views/ScreenOcr.vue b/plugins/f-provider/src/views/ScreenOcr.vue
index e753b4dd..fc14ff21 100644
--- a/plugins/f-provider/src/views/ScreenOcr.vue
+++ b/plugins/f-provider/src/views/ScreenOcr.vue
@@ -1,93 +1,108 @@
-
-
- 截图识别
-
-
- 引擎就绪
-
-
- 检查中…
-
-
- 引擎未就绪
-
-
- {{ phase === 'capturing' ? '截图中…' : '重新截图' }}
-
-
复制全部
+
+
+
+
+
+
+
+ {{ phase === 'capturing' ? '✂️' : phase === 'recognizing' ? '🔍' : '📷' }}
+
+
+ 请在屏幕上框选要识别的区域…
+ 正在识别…
+ {{ errorText || '识别失败' }}
+ 识别完成,已打开结果窗口
+
+ {{ nativeState === 'checking' ? '检查引擎中…' : '准备截图…' }}
+
-
-
-
-
-
-
-
-
-
- {{ errorText }}
-
+
重试截图
+
diff --git a/plugins/f-provider/src/views/ScreenOcrResult.vue b/plugins/f-provider/src/views/ScreenOcrResult.vue
new file mode 100644
index 00000000..5a9ebbdf
--- /dev/null
+++ b/plugins/f-provider/src/views/ScreenOcrResult.vue
@@ -0,0 +1,841 @@
+
+
+
+
+
+
+
+
![]()
+
截图识别结果
+
+
+
+
+
+
+
+
+
+
识别中…
+
{{ errorText }}
+
无图片
+
+
+
+
+
+ {{ Math.round(scale * 100) }}%
+
+
+
+
+
+
+
+
+
+ 识别结果({{ lines.length }} 行)
+
+ 已复制
+
+
+
+
+
识别中…
+
{{ errorText }}
+
未识别到文字
+
+
+ {{ (line.rate * 100).toFixed(0) }}%
+ {{ line.text }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/plugins/f-provider/vite.config.js b/plugins/f-provider/vite.config.js
index 7bfab103..d88f4f29 100644
--- a/plugins/f-provider/vite.config.js
+++ b/plugins/f-provider/vite.config.js
@@ -1,8 +1,26 @@
import { defineConfig } from 'vite'
+import { resolve } from 'node:path'
import vue from '@vitejs/plugin-vue'
-// https://vitejs.dev/config/
+// https://vite.dev/config/
+//
+// 多页入口:
+// - index.html 主窗口(设置/识别/翻译/截图识别触发器)
+// - screen-ocr-result.html 截图识别结果展示窗口(由 ztools.createBrowserWindow 打开,
+// 纯展示:左图右文,不带 preload,不调 window.ztools API)
export default defineConfig({
plugins: [vue()],
- base: './'
+ base: './',
+ build: {
+ // dist/ 内含手动放置的 native/(.node 原生模块,运行中的 ZTools 会加载并锁定)
+ // 与 preload/,不能被 emptyOutDir 清空,否则构建时会因文件被占用而失败。
+ // Vite 仍会覆盖它自己产出的 html / assets,无需清空整个目录。
+ emptyOutDir: false,
+ rollupOptions: {
+ input: {
+ main: resolve(__dirname, 'index.html'),
+ screenOcrResult: resolve(__dirname, 'screen-ocr-result.html')
+ }
+ }
+ }
})