Files

233 lines
12 KiB
C#

// OcrSettingsForm:OCR 引擎与 Key 设置(百度 OCR / 智谱 GLM-OCR / 千帆 / UApiPro / Umi-OCR 本地)
// 保存 → OcrPaths.ConfigPath 的 baidu_ocr.json(engine/api_key/secret_key/glm_api_key/qianfan_api_key/uapis_api_key/umi_url)
// + 热更新 OcrClient + 作废百度 token 缓存。
using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;
using System.Web.Script.Serialization;
namespace 成套报价软件
{
public partial class OcrSettingsForm : Form
{
private readonly OcrClient _ocr;
public OcrSettingsForm(OcrClient ocr)
{
InitializeComponent();
this.BackColor = System.Drawing.Color.White;
_ocr = ocr;
// 回填现有配置(默认 Key 在 Designer 的 Text 里,密码遮罩显示;保存过则文件值优先)
string engine = "baidu";
try
{
string cfgPath = OcrPaths.ConfigPath;
if (File.Exists(cfgPath))
{
var jsv = new JavaScriptSerializer().Deserialize<Dictionary<string, string>>(File.ReadAllText(cfgPath));
if (jsv != null)
{
if (jsv.ContainsKey("engine")) engine = jsv["engine"] ?? "baidu";
txtApiKey.Text = jsv.ContainsKey("api_key") ? (jsv["api_key"] ?? "") : "";
txtSecretKey.Text = jsv.ContainsKey("secret_key") ? (jsv["secret_key"] ?? "") : "";
txtGlmKey.Text = jsv.ContainsKey("glm_api_key") ? (jsv["glm_api_key"] ?? "") : "";
txtQianfanKey.Text = jsv.ContainsKey("qianfan_api_key") ? (jsv["qianfan_api_key"] ?? "") : "";
txtUapisKey.Text = jsv.ContainsKey("uapis_api_key") ? (jsv["uapis_api_key"] ?? "") : "";
txtUmiUrl.Text = jsv.ContainsKey("umi_url") && !string.IsNullOrWhiteSpace(jsv["umi_url"])
? jsv["umi_url"] : "http://127.0.0.1:1224";
}
}
}
catch { }
cboEngine.SelectedIndex =
engine == "glm" ? 1 :
engine == "qianfan" ? 2 :
engine == "uapis" ? 3 :
engine == "umi" ? 4 : 0;
UpdateEnginePanels();
}
/// <summary>按引擎下拉显示对应的输入区(百度=两格;智谱/千帆/UApiPro=Key一格;Umi-OCR=服务地址一格)。</summary>
private void UpdateEnginePanels()
{
int sel = cboEngine.SelectedIndex;
bool glm = sel == 1;
bool qf = sel == 2;
bool ua = sel == 3;
bool umi = sel == 4;
bool baidu = !glm && !qf && !ua && !umi;
lblApiKey.Visible = baidu;
txtApiKey.Visible = baidu;
lblSecretKey.Visible = baidu;
txtSecretKey.Visible = baidu;
lblGlmKey.Visible = glm;
txtGlmKey.Visible = glm;
lblQianfanKey.Visible = qf;
txtQianfanKey.Visible = qf;
lblUapisKey.Visible = ua;
txtUapisKey.Visible = ua;
lblUmiUrl.Visible = umi;
txtUmiUrl.Visible = umi;
btnUmi下载.Visible = umi;
btnUmi检测.Visible = umi;
lblUmi状态.Visible = umi;
if (umi) RefreshUmiStatus();
}
/// <summary>刷新 Umi 本体三态状态显示。</summary>
private void RefreshUmiStatus()
{
try { lblUmi状态.Text = UmiOcrHost.DetectText(); } catch { }
}
/// <summary>检测 OCR 本体:刷新状态(未安装/已安装未运行/运行中)。</summary>
private void btnUmi检测_Click(object sender, EventArgs e)
{
RefreshUmiStatus();
MessageBox.Show(this, UmiOcrHost.DetectText(), "检测 OCR 本体",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
/// <summary>下载 OCR 本体:网盘直链(~179MB)→解压到程序目录 Umi-OCR\→验证→删 zip。</summary>
private void btnUmi下载_Click(object sender, EventArgs e)
{
if (UmiOcrHost.IsInstalled)
{
var r = MessageBox.Show(this, "OCR 本体已存在,重新下载将覆盖安装。继续吗?", "下载 OCR 本体",
MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
if (r != DialogResult.OK) return;
}
btnUmi下载.Enabled = false;
btnUmi检测.Enabled = false;
lblUmi状态.ForeColor = System.Drawing.Color.DimGray;
lblUmi状态.Text = "正在下载… 0%";
int lastPct = -1;
UmiOcrHost.DownloadAndInstallAsync(pct =>
{
if (pct == lastPct) return;
lastPct = pct;
try { this.BeginInvoke((MethodInvoker)delegate
{
lblUmi状态.Text = pct >= 100 ? "下载完成,正在解压安装…" : "正在下载… " + pct + "%";
}); } catch { }
}).ContinueWith(t =>
{
try { this.BeginInvoke((MethodInvoker)delegate
{
btnUmi下载.Enabled = true;
btnUmi检测.Enabled = true;
lblUmi状态.ForeColor = System.Drawing.SystemColors.GrayText;
if (t.IsFaulted)
{
Exception root = t.Exception;
while (root is AggregateException && root.InnerException != null) root = root.InnerException;
lblUmi状态.Text = "下载/安装失败: " + root.Message;
MessageBox.Show(this, "下载/安装失败:\n" + root.Message, "下载 OCR 本体",
MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
else
{
RefreshUmiStatus();
MessageBox.Show(this, "OCR 本体安装完成!\n" + UmiOcrHost.DetectText() +
"\n\n选 Umi-OCR 引擎保存后即可使用(识别时自动启动)。",
"下载 OCR 本体", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}); } catch { }
});
}
private void cboEngine_SelectedIndexChanged(object sender, EventArgs e)
{
UpdateEnginePanels();
}
/// <summary>帮助:全部引擎的 Key 获取方式与本地 OCR 设置流程。</summary>
private void btn帮助_Click(object sender, EventArgs e)
{
string help =
"════════ OCR 识别引擎使用帮助 ════════\r\n" +
"\r\n" +
"【1. 百度 OCR 高精度(含位置)】 默认引擎,已内置 Key 可直接用\r\n" +
" · 获取自己的 Key(更稳,免费额度足够日常):\r\n" +
" ① 打开 console.baidu.com 登录百度账号\r\n" +
" ② 进入\"产品服务 / 文字识别\"→ 创建应用\r\n" +
" ③ 勾选\"文字识别\"全部接口,创建完成\r\n" +
" ④ 在应用详情里复制 API Key 和 Secret Key 填入本窗口\r\n" +
"\r\n" +
"【2. 智谱 GLM-OCR(版面解析/手写强)】\r\n" +
" · 到 open.bigmodel.cn 注册并实名 → API Keys 页面新建密钥\r\n" +
" · 把密钥填入\"智谱 API Key\"\r\n" +
" · 计费约 0.2 元/百万 tokens,适合手写体/复杂版面\r\n" +
"\r\n" +
"【3. 百度 PaddleOCR-VL(千帆版面解析)】\r\n" +
" · 到 console.bce.baidu.com → 千帆 ModelBuilder → 应用管理\r\n" +
" · 创建应用后复制 API Key 填入\"千帆 API Key\"\r\n" +
" · 需在千帆控制台开通 PaddleOCR-VL 模型服务\r\n" +
"\r\n" +
"【4. UApiPro 通用OCR(免费积分/带位置)】\r\n" +
" · 到 uapis.cn 注册账号 → 控制台 → API Keys → 新建\r\n" +
" · 把 Key 填入\"UApiPro Key\"\r\n" +
" · 注册送免费积分(约 4 积分/次识别),小量使用零成本\r\n" +
"\r\n" +
"【5. Umi-OCR 本地引擎(离线免费,无限次)】\r\n" +
" · 本地引擎无需任何 Key,识别全在本机完成,数据不出电脑\r\n" +
" · 设置流程:\r\n" +
" ① 选本引擎后点\"下载 OCR 本体\"(约 179MB,自动下载安装)\r\n" +
" ② 点\"检测 OCR 本体\"确认状态为\"运行中\"或\"已安装\"\r\n" +
" ③ 点\"保存\"完成,之后识别时自动启动、关窗自动关闭\r\n" +
" · 服务地址保持默认 http://127.0.0.1:1224 即可\r\n" +
" (只有你在 Umi-OCR 软件里改过 HTTP 端口才需要改这里)\r\n" +
"\r\n" +
"════════════════════════════\r\n" +
"提示: Key 全部以密码方式显示,点\"保存\"后立即生效;\r\n" +
"所有 Key 统一保存在程序目录 baidu_ocr.json。";
MessageBox.Show(this, help, "OCR 使用帮助",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
private void btn确定_Click(object sender, EventArgs e)
{
try
{
string cfgPath = OcrPaths.ConfigPath;
string engineValue =
cboEngine.SelectedIndex == 1 ? "glm" :
cboEngine.SelectedIndex == 2 ? "qianfan" :
cboEngine.SelectedIndex == 3 ? "uapis" :
cboEngine.SelectedIndex == 4 ? "umi" : "baidu";
var jsv = new JavaScriptSerializer();
File.WriteAllText(cfgPath, jsv.Serialize(new Dictionary<string, string>
{
{ "engine", engineValue },
{ "api_key", txtApiKey.Text.Trim() },
{ "secret_key", txtSecretKey.Text.Trim() },
{ "glm_api_key", txtGlmKey.Text.Trim() },
{ "qianfan_api_key", txtQianfanKey.Text.Trim() },
{ "uapis_api_key", txtUapisKey.Text.Trim() },
{ "umi_url", string.IsNullOrWhiteSpace(txtUmiUrl.Text.Trim()) ? "http://127.0.0.1:1224" : txtUmiUrl.Text.Trim() }
}));
// 热更新引擎/Key + 作废百度 token 缓存(下次识别重新换取)
if (_ocr != null)
{
_ocr.LoadConfig();
try { File.Delete(OcrPaths.TokenCachePath); } catch { }
}
// 选了 Umi-OCR 但还没装本体:提示引导下载(不阻断保存)
if (engineValue == "umi" && !UmiOcrHost.IsInstalled)
{
MessageBox.Show(this, "Umi-OCR 本体尚未安装。\n请点\"下载 OCR 本体\"完成安装后即可使用。",
"OCR 设置", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
catch (Exception ex)
{
MessageBox.Show(this, "保存失败: " + ex.Message, "OCR 设置",
MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
}
}