Uc 是一个 AI 原生 的基于 .NET 10 + WebView2的Windows 桌面浏览器。
更新日志 v1.3.2
fix: 视频增强功能全面重构修复
注入机制/iframe 通信/防抖/性能优化
add:大声朗读功能
微软件Edge
更新日志 v1.3.1
🚀 性能
WebView2 预热池
- 新增
WebView2Pool — 后台预初始化 2 个 WebView2 实例
RentAsync() 绕过 EnsureCoreWebView2Async 启动延迟,冷启动提速 ~40%
- 首次
newTab/settings 导航不再等待 CoreWebView2 初始化
自适应休眠调度
SleepManager 重写:基于 GlobalMemoryStatusEx 实时感知可用物理内存
- 4 级压力阈值(1.0 / 0.7 / 0.4 / 0.2),根据剩余内存自动缩放
- 窗口最小化时主动
GC.Collect() 回收后台标签
AdBlock 零分配过滤
IsBlocked 采用 HashSet<string>.GetAlternateLookup<ReadOnlySpan<char>> + Span 切片
- 每请求从 3~5 次堆分配降至 0 分配
IsSiteAllowed:volatile + copy-on-write,移除 ReaderWriterLockSlim
- 启动时
Task.Run 预加载黑名单,避免首次请求同步 I/O
视频增强按需注入
- 移除全量注入,改为导航完成后检测
<video> 元素,有视频才注入
MainWindow 用户切换/设置变更时对已有标签按需补注
其他优化
- Chrome flags: 禁用
Sync / msWebView2OriginTrials / FieldTrialConfig 减少启动开销
SessionStore 保存间隔 4s → 1s,多窗口 ActiveIndex 跟踪
- YouTube 跳过脚本轮询 200ms → 500ms
✨ 新功能
新标签页
- Widget 粒子爆炸动效 — 关闭卡片时网格粒子以风偏角 + 重力 + 随机旋转飘散淡出(仿 HarmonyOS 7)
- Widget 折叠/展开 — 每卡片添加 ▼/▶ 折叠按钮,状态持久化到配置
- 折叠语义重构 — Heading 移出
widget-body,折叠时 display: none 整个 body,彻底避免内部复杂 DOM(如翻转时钟)残留高度
- 跨桌面 Pomodoro 通知 —
PomoNotificationWindow 独立 WPF 窗口,所有虚拟桌面可见,10s 自动关闭
- 天气城市管理 — 城市 Tab 添加 × 移除按钮,
removeCity() 支持
Windows 11 集成
Windows11Theme.cs:启用 DWMWCP_ROUND 圆角 corners + Mica 云母材质
- 加载进度条:3px
ProgressBar 由 SourceChanged / NavigationCompleted 驱动
🐛 修复
WebView2 生命周期
DestroyView: 从 LocalizationResource 跟踪列表注销 WebView,防止悬挂引用
MainWindow.Closed: dispose 所有 tab WebView2 实例以释放渲染器进程
NavigateAsync: cw.Navigate() + 事件订阅 dispatch 到 UI 线程
NewWindowRequested: dispatch 到 UI 线程 via Dispatcher.InvokeAsync
- 5 处窗口操作:
Dispatcher.Invoke → Dispatcher.InvokeAsync 非阻塞
ReaderWriterLockSlim 递归锁
Bookmarks.cs 4 处 LockRecursionException:写→读/写→写重入
- 修复: 提取
RemoveInternal / AllUrlsUnsynchronized 无锁私有方法,外层 Save() 统一触发 Changed 事件
绘画/滚动
GetScrollPosition: 先反序列化 JSON 再解析,避免 ExecuteScriptAsync 竞态
📦 发布
# 单文件绿色版构建
.\publish.ps1
更新日志:V1.3.0
v1.3.0重大更新:
性能优化
1. 网站加载速度
| 变更 |
说明 |
--disable-async-dns |
使用 Windows OS getaddrinfo 替代 Chromium 异步 DNS 解析器。避免后者在国内网络下激进缓存假 NXDOMAIN 导致连续秒级无响应 |
--disable-quic |
禁用 QUIC/HTTP3(基于 UDP)。国内多家 ISP 对 UDP 限速/干扰,QUIC 连接超时后再回退 TCP 浪费 5-30s |
--disable-ipv6 |
跳过 IPv6 CDN 节点。国内 IPv6 基础设施不稳定,超时后回退 IPv4 增加延迟 |
| 移除所有 Google 服务依赖 |
通过 --disable-features 禁用 SafeBrowsingEnhancedProtection、OptimizationGuideModelDownloading、MediaRouter、TranslateUI、PasswordLeakDetection,以及 --disable-background-networking、--disable-component-update。避免 Google 导致的请求超时 |
2. 地址栏与图标
- Favicon 超时 15s → 5s + 失败 host 缓存(避免重复请求黑名单域名)
- 地址栏建议 200ms 防抖(
OmniboxController debounce)
- 地址栏右键菜单:复制 / 粘贴。
IsInactiveSelectionHighlightEnabled=true 使失焦时选中仍可见,Menu.Opened 重选恢复文本
3. 视频增强注入优化
从 AddScriptToExecuteOnDocumentCreatedAsync(全局注入)改为 NavigationCompleted 事件 + document.querySelector('video') 检测,仅在有视频的页面注入。减少无谓的 JS 执行和 DOM 操作
4. 渲染进程参数
--js-flags=--scavenger_max_new_space_capacity_mb=32 // 减少 SPA 站点 GC 频率
--renderer-process-limit=12/20 // MemorySaver 模式 12,否则 20
--disk-cache-size=268435456 // 256MB 磁盘缓存上限
--enable-gpu-rasterization // GPU 光栅化
--enable-accelerated-video-decode // GPU 视频解码
--disable-site-isolation-trials // MemorySaver 模式关闭站点隔离
5. Feature Flag 启用
| Flag |
作用 |
MemoryPurgeOnFreezeLimit |
冻结标签时回收内存 |
msWebView2TreatAppSuspendAsDeviceSuspend |
窗口最小化时节省资源 |
CanvasOopRasterization |
Canvas 走 GPU 渲染 |
ParallelDownloading |
分片并行下载 |
功能新增
1. AI 功能
- 双引擎 MCP Server:本地 MCP Server 支持 OpenAI + Anthropic 双驱动(
AiService.cs)
- AI 对话自动压缩:对话历史过长时自动压缩上下文
- 只读工具跳过审批:
snapshot、get_page_html 等只读工具不再需要用户人工确认
- 默认 auto mode:新对话默认 auto 模式
- translate/aisummary 改为交互式:不再自动抓取页面执行,改为插入命令名等待用户输入参数
- 命令面板优化(Ctrl+K):选 skill 先插入命令名,允许输入参数后再执行
- 输入框命令精确匹配:避免
/command 输入后 Enter 循环触发执行
2. 书签系统
- 列表弹窗文件夹层级树:展开/折叠文件夹
- 书签栏拖拽排序:拖拽重排书签位置
- 搜索过滤:支持按标题/URL 搜索,显示文件夹上下文中
3. 扩展与权限
- WebView2 扩展安装支持:从 Chrome Web Store 安装扩展
- 站点权限弹窗:摄像头、麦克风、位置、通知、剪贴板读取 — 自定义 Uc 风格弹窗,不阻塞页面加载
- 权限记忆:用户选择后可记住(存在
AppSettings.SitePermissions)
4. 代理设置
- 代理配置支持:直接 / 固定代理(HTTP/HTTPS/SOCKS5)/ 系统代理
- 代理热更新(
ProxyHelper generation 机制使 HttpClient 实例自动刷新)
重大重构
1. Chrome 控制器架构
从 ChromeController(单体 ~2000 行)拆分为多个子 Controller:
| 文件 |
职责 |
WindowStateController.cs |
窗口状态(全屏/最大化/最小化/普通) |
AiController.cs |
AI 面板管理 |
SettingsController.cs |
设置页面 |
SkillsController.cs |
技能管理 |
OmniboxController.cs |
地址栏与建议 |
SidePanelController.cs |
侧边栏 |
ListPopupController.cs |
书签/历史弹出列表 |
2. Windows 7 TFM 迁移
- 目标框架从
net10.0-windows10.0.17763 改为 net10.0-windows7.0
- 移除全部 WinRT API 调用
OsAuth.VerifyAsync 始终返回 true(WinRT 不可用,设计限制)
- 从 Edge 导入逻辑移除 WinRT 路径
修复(Bug Fixes)
线程安全
| 问题 |
文件 |
修复 |
| ExtensionController NRE |
ExtensionController.cs |
空引用检查 |
| AiChat NavigationCompleted 顺序 |
AiChat.cs |
确保事件先注册再导航 |
| Http 属性竞态 |
AiService.cs |
OpenAiProvider/AnthropicProvider 的 Http 属性加 _httpLock |
async void Tick 未捕获异常 |
SleepManager.cs:43 |
外层 try-catch |
| InvokeAsync 非阻塞 |
AiChat.cs |
fire-and-forget 改为 await |
| AdBlockEngine 锁争用 |
AdBlockEngine.cs |
ReaderWriterLockSlim |
NewWindowRequested 后台线程 |
TabManager.cs:713 |
用 host.Dispatcher.InvokeAsync 封送到 UI 线程 |
| 5 个窗口操作阻塞 Dispatcher.Invoke |
BuiltinBrowserEngine.cs:470-527 |
改为 async InvokeAsync |
| SetScrollPosition JSON 反序列化 |
BuiltinBrowserEngine.cs:710 |
修复解析,恢复 AI 滚动功能 |
内存泄漏
| 问题 |
修复 |
| 窗口关闭未释放 WebView2 |
MainWindow.xaml.cs:348 — Closed 事件中 dispose 所有 tab 的 WebView2 |
| VideoEnhancer 事件 handler 泄漏 |
字段存储 handler 引用,取消订阅时移除 |
JsonDocument.Parse 未释放 |
BuiltinBrowserEngine.Observation.cs 8 处添加 using |
| Mutex 退出时未清理 |
MainWindow.xaml.cs OnExit 补充 ReleaseMutex |
| DestroyView 未反注册 localization |
TabManager.cs:834 补充 LocalizationResource.UnregisterWebView |
| TrackWebView 未配对 UnregisterWebView |
6 处补充(MainWindow、SidePanelController、ExtensionController、VideoEnhancerPopupWindow、TabManager.OpenPopupWindowAsync) |
其他修复
| 问题 |
说明 |
| Permission JSON 键格式 |
PermissionRequested 处理修复 |
| 会话保存竞态 |
SessionStore.Save 改为 WriteAtomic(先写 temp 再原子替换) |
| 重复 AdBlock guard |
移除重复的 WebResourceRequested handler |
| WindowStateController null-check |
修复空引用 |
| AiService IsTransient |
修复判断逻辑 |
| XAML CloseBtn 命名不匹配 |
CloseBtn 重命名 |
| GroupBrush 缓存 |
减少重复创建 Brush |
| AiChat tool definition 缓存 |
减少重复序列化 |
| 地址栏焦点全选 |
GotFocus + BeginInvoke + SelectAll() |
IsInactiveSelectionHighlightEnabled |
地址栏失焦时选中文本保持可见 |
| 主窗口 AboutToChangeEvent |
添加延迟器防止过快更新 |
| 主窗口确保所有标签具有初始化的 View |
打开标签页时先行创建 WebView2 |
| 主窗口中 Cookie 对话框大小调整 |
窗口自适应 |
v1.2.1增加:
1. 内置浏览器自动化工具
2. 内置文件系统工具
3. 修复若干BUG
v1.2.0增加:
1. 多语言支持( i18n 功能)
2. 把 720P 看出 4K 的体验……不换设备,不开会员,一键开启视频画质增强
3. 独立重写的专业视频增强引擎。
4. 画面更清晰锐利(独立重写)
5. 添加代理设置WebView2及所有 HttpClient 遵循代理设置
🤖 AI 能力
AI 聊天侧面板
Ctrl+Shift+A 随时呼出。侧面板打开时,AI 能感知你当前正在看的页面——你可以直接问"这页讲了什么"、"帮我翻译成英文"、"这段代码有什么问题"。
支持多模型切换,一次配置多个提供商,随时换着用:OpenAI、Anthropic、DeepSeek、Google Gemini、OpenRouter、GitHub Models等。
对话历史本地保存修改删除等,支持搜索、重命名、继续对话。API 密钥使用 Windows DPAPI 加密存储,不会明文泄露。
🧠 MCP(模型上下文协议)
Uc 是 首批在浏览器层面原生支持 MCP 协议 的浏览器之一。
通过 MCP,AI 不再只能"说话"——它能调用你本地的工具:读文件、操作命令行、查询数据库、访问浏览器等等——真正帮你完成操作。你在聊天里说一句"帮我查一下这个项目的 Test 覆盖率",AI 就能自己去读代码、跑测试、把结果呈现给你。
- 支持 stdio 传输,可配置任意多个 MCP 服务器
- 自动连接、断线重试、状态管理
- 内置文件系统 MCP 服务
- 管理页面实时查看每个服务器的连接状态和可用工具
- 第三方 MCP 服务器即插即用
🛠️ AI 技能系统(Skills)
技能是告诉 AI "遇到这类任务该怎么做" 的能力模块,用 Markdown + YAML 定义,放在指定目录即可加载。
内置技能:
| 技能 |
一句话 |
explore |
浏览代码库或页面,帮你找到需要的信息 |
review |
审查代码或文本,发现问题和改进点 |
summarize |
总结当前页面或选中文本的核心要点 |
translate |
自动检测语言,中英互译 |
explain |
用简单语言解释选中的复杂内容 |
在聊天中输入 /技能名 即可调用。你也可以自己写技能——管理页面支持创建、编辑、启用、禁用,满足特定工作流。
🖱️ AI 右键菜单
在任何页面上选中文字,右键即用:
- "Ask AI about..." — 把选中内容作为问题发送给 AI
- "Explain..." — 用大白话解释选中的内容
- "Translate..." — 自动检测并翻译
不用离开当前页面,不用复制粘贴,选中即问。
🖥️ 不止是 AI
AI 是核心,但浏览器该有的它都有。
原生广告拦截 — 网络级别的广告和追踪器拦截。内置数千条规则,每个站点可单独开关,实时显示拦截数量。
Chrome 扩展支持 — 直接从 Chrome Web Store 安装扩展。弹窗、侧面板、工具栏图标、徽章——该有的都有,和 Chrome 一致。
全暗色主题 + 无痕模式 — 整站暗色完美,遇到浅色网站可强制变暗。无痕窗口使用完全隔离的临时 Profile,关闭即焚。
标签页内存管理 — 闲置标签页自动经历"冻结 → 挂起 → 回收"三级降级,释放大量内存。点回来时瞬间恢复。播放音频的标签页不会被冻结,也可以手动标记保持唤醒。
数据导入 — 从 Chrome、Brave、Edge、Vivaldi、Opera 等 Chromium 浏览器一键导入书签、密码、Cookie、历史记录。迁移无痛。
日常好用的细节 — 画中画、截图、页面翻译、搜索关键字快捷跳转、恢复关闭标签页、下载管理器、多窗口支持、标签拖拽分离成独立窗口、会话恢复——都不少。
⌨️ 快捷键
| 快捷键 |
功能 |
Ctrl+Shift+A |
打开/关闭 AI 聊天侧面板 |
Ctrl+, |
打开设置 |
Ctrl+L / Alt+D |
定位到地址栏 |
Ctrl+T |
新建标签页 |
Ctrl+W |
关闭标签页 |
Ctrl+Shift+T |
恢复关闭的标签页 |
Ctrl+Tab |
下一个标签页 |
Ctrl+Shift+Tab |
上一个标签页 |
Ctrl+R / F5 |
刷新 |
F11 |
全屏 |
Ctrl+Shift+N |
新建无痕窗口 |
Ctrl+J |
下载管理 |
Ctrl+H |
历史记录 |
Ctrl+F |
页面内查找 |
Ctrl++ / Ctrl+- |
放大 / 缩小 |
Ctrl+0 |
重置缩放 |
内置协议页面(uc://)
这些页面运行在独立的 WebView2 实例中,作为浏览器自己的管理界面,不依赖外部服务。各自有对应的 HTML 放在资源目录下。
| 协议 |
用途 |
打开方式 |
uc://settings(或 uc://newtab/settings.html) |
浏览器设置 |
Ctrl+, 或 AI 工具 |
uc://newtab/history.html |
浏览历史 |
Ctrl+H 或 AI 工具 |
uc://newtab/ai-history.html |
AI 对话历史 |
AI 助手可打开 |
uc://newtab/skills.html |
技能管理(创建/编辑/启禁) |
AI 聊天面板内置页面 |
uc://mcp(或 uc://newtab/mcp.html) |
MCP 服务器管理 |
AI 工具 open_mcp |
uc://newtab/video-enhancer.html |
视频增强控制面板 |
视频页面弹出 |
uc://newtab |
新标签页(可自定义布局) |
新建标签页 |
这些都是内置的,不联网也能打开。
AI 聊天面板
Ctrl+Shift+A 呼出/隐藏侧面板。聊天面板本身是一个独立的 HTML 页面(uc.ai 域下本地加载),通过 PostWebMessageAsString 与 C# 后端双向通信。
基本操作
- 发消息:输入框回车,支持粘贴代码/文本
- 中止:AI 输出时点停止按钮,或再按一次
Ctrl+Shift+A
- 新建:点"新建"或发
new
- 切模型:面板顶部下拉菜单
- 编辑重发:改自己的某条消息,回车,AI 基于修改后的上下文重新回复
- 删除消息:批量选择后删除
对话管理
- 自动保存:每轮结束后写
%APPDATA%\Uc\conversations\conv_*.json
- 标题自动生成:取首条 user 消息前 60 字,可以手动改(
.titles.json 侧边存储)
- 历史列表:按更新时间排序,显示模型和摘要。列表用
Utf8JsonReader 流式解析,不反序列化整个文件
- 全文搜索:先对比元数据,未命中的再搜索消息内容(限 64KB 以内文件)
- 回收站:删除的对话进
.trash/ 子目录,可恢复或永久删除
- 继续对话:点任意历史对话,上下文完整保留
上下文感知
面板打开时,前端通过 context 消息类型上报当前标签页的 URL 和标题。后端在构建 system prompt 时附加到 BuildSystemPrompt() 里。每次切换页面都会自动更新。
MCP:内置与外部工具
MCP(Model Context Protocol)是模型-工具通信协议。Uc 在浏览器层面原生支持,内置了两个工具集,同时也支持配置任意外部 MCP 服务器。
内置浏览器自动化工具(uc-browser)
编译在二进制里,不依赖任何外部进程。全部 53+ 个工具按功能分组:
浏览器独有能力(17 个):获取标签页列表、切换/关闭/新建标签页、分组标签页、管理书签(增删查)、搜索/清除历史、查看下载列表、窗口大小/位置/最小化/最大化/全屏、打开设置/历史/AI 历史/技能/MCP 管理页面。
导航(5 个):navigate、back、forward、reload(可选忽略缓存)、stop。
鼠标操作(7 个):click(支持 CSS 选择器和无障碍树 nodeId)、right_click、double_click、hover、drag(起点到终点坐标)、scroll(方向和距离)、scroll_to(滚动到元素)。
键盘操作(2 个):type(输入框键入)、press_key(单键或组合键,Enter 后等待导航完成)。
截图与页面执行(7 个):screenshot(jpeg/png,支持全页,自动保存到 screenshots/)、screenshot_element、screenshot_zoom(局部放大)、evaluate(执行 JS)、get_page_html、get_page_text、get_page_url。
页面理解(5 个):snapshot(无障碍树,支持 data-ref 标识,返回数字 nodeId,可直接用于 click/type 等工具的 selector)、find_element(按文本或角色搜索,返回 ref_id)、form_input、select_option、highlight_element(标记 AI 正在操作的部位)。
调试能力(6 个):get_console(可过滤/正则/清空)、clear_console、get_network(按 URL 过滤/清空)、clear_network、block_urls、unblock_urls。
存储管理(7 个):Cookie 增删查清、localStorage 读写删清、sessionStorage 读写删清。
其他(约 10 个):wait_for(超时 30 秒)、dialog_accept/dialog_dismiss、fill、mouse_down/mouse_up、set_viewport、pin_tab/unpin_tab、duplicate_tab、mute_tab/unmute_tab。
每个工具先尝试 Chrome DevTools Protocol(CallDevToolsProtocolMethodAsync),失败时回退到 JS 注入(ExecuteScriptAsync)。工具名以 uc-browser__{tool} 格式注入 AI。
内置文件系统工具(uc-fs)
同样编译在二进制里。13 个工具:
read_file(大文件流式读取+自动编码检测)、write_file(支持二进制 base64)、delete_file(递归或非空检测)、move_file、copy_file、search_files(通配符+按内容搜索)、get_file_info(大小/时间/MD5)、list_directory(排序/过滤/隐藏)、create_directory、compress(zip 压缩/解压)、edit_file(查找替换/正则)、read_multiple_files(最多 10 个)、run_powershell。
所有文件操作会验证路径是否在允许的基目录内(默认用户目录和所有就绪的驱动器根目录)。
配置外部 MCP
打开 uc://mcp 管理页面,添加 JSON 配置:
{
"Name": "playwright",
"Type": "stdio",
"Command": "npx",
"Args": ["-y", "@playwright/mcp@latest"],
"AutoStart": true
}
技能系统(Skills)
技能是告诉 AI"这类任务该怎么做"的指令模块,用 Markdown + YAML 头定义。
内置技能(编译在 Resources 中)
| 技能 |
作用 |
| explore |
浏览代码库或页面,帮找信息 |
| review |
审查代码或文本,发现问题 |
| summarize |
总结当前页面或选中文本核心要点 |
| translate |
自动识别语言,中英互译 |
| explain |
用大白话解释选中的复杂内容 |
使用方式
聊天框输入 /技能名 调用,例如 /explain 这段代码用了什么设计模式。
自定义技能
技能管理页面(uc://newtab/skills.html)支持创建/编辑/启用/禁用。技能文件的 YAML 头支持字段别名(runAs/agent/context 都映射到 RunAs),支持多行和 inline 列表。
加载优先级:自定义路径 > 全局目录 > 内置技能。每个技能可以限制使用的模型、运行模式(inline / subagent)、允许调用的工具白名单。
AI 右键菜单
选中文字→右键,出现三项(需要先配好 AI):
- Ask AI about... — 选中内容作为问题发给 AI
- Explain... — 解释选中的内容
- Translate... — 自动检测并翻译
通过 WebView2 的 ContextMenuRequested 事件注入,选中文字过长时会截断。
阅读模式与 AI 摘要
基于 Mozilla Readability 提取正文,渲染成暗色阅读视图。AI 总结按钮调用 AiService.SummarizeAsync(30 秒超时),把文章传给当前配置的模型生成中文摘要。适合长文、论文、文档速览。
WebView2 ↔ C# 双向消息传递
浏览器所有的管理界面和 AI 聊天都运行在 WebView2 中,通过 PostWebMessageAsString / WebMessageReceived 与 C# 后端通信。整个项目共两种协议模式:
AI 聊天协议(JSON 类型路由)
AI 聊天面板(ai-chat.html ↔ AiChat.cs)使用 JSON 格式的消息,通过 type 字段路由:
JS → C#: post({ type: "send", content: "Hello" })
post({ type: "command", action: "skills" })
post({ type: "runSkill", name: "explain", arguments: "..." })
C# → JS: { type: "delta", content: "正在生成..." }
{ type: "done", msgIdx: 3 }
{ type: "skillsList", list: [...] }
JS 发送端(ai-chat.html):
function post(msg) {
try { window.chrome.webview.postMessage(JSON.stringify(msg)); } catch(e) {}
}
C# 接收端(AiChat.cs OnWebMessageReceived):
private async void OnWebMessageReceived(object? sender, CoreWebView2WebMessageReceivedEventArgs e)
{
var raw = e.TryGetWebMessageAsString();
using var doc = JsonDocument.Parse(raw);
var root = doc.RootElement;
var type = root.TryGetProperty("type", out var t) ? t.GetString() : null;
switch (type)
{
case "send":
var content = root.TryGetProperty("content", out var c) ? c.GetString() : null;
if (!string.IsNullOrEmpty(content)) await HandleSendAsync(content);
break;
case "command":
var action = root.TryGetProperty("action", out var a) ? a.GetString() : null;
if (!string.IsNullOrEmpty(action)) main.OnAcceleratorRequested(action);
break;
case "runSkill":
var name = root.TryGetProperty("name", out var n) ? n.GetString() : null;
var args = root.TryGetProperty("arguments", out var ar) ? ar.GetString() : "";
main.OnAcceleratorRequested("runSkill:" + Uri.EscapeDataString(name) + ":" + Uri.EscapeDataString(args));
break;
}
}
C# 发送端(AiChat.cs PostToPage):
private void PostToPage(object obj)
{
var json = JsonSerializer.Serialize(obj);
_view.Dispatcher.Invoke(() =>
{
_view.CoreWebView2?.PostWebMessageAsString(json);
});
}
JS 接收端(ai-chat.html):
window.chrome.webview.addEventListener('message', function(e) {
var msg = JSON.parse(e.data);
switch (msg.type) {
case 'delta': appendDelta(msg.content); break;
case 'done': finishResponse(msg.msgIdx); break;
case 'skillsList': loadSkills(msg.list); break;
// ...
}
});
内置页面协议(字符串前缀路由)
设置页、历史页、技能管理等内置页面使用字符串消息,以 uc:页面名:操作 格式约定:
JS → C#: "uc:settings:get"
"uc:settings:set:" + JSON.stringify(state)
"uc:skills:run:translate"
"uc:ai-history:list"
"uc:video-enhancer:get-settings"
C# → JS: "uc:settings:data:" + json
"uc:skills:data:" + json
"uc:newtab:mv:" + json
两种协议共用同一个底层通道(PostWebMessageAsString),C# 端通过 MainWindow.cs 的 OnAcceleratorRequested 和各个 Handle*Message 方法分发处理。AI 聊天消息走 AiChat.cs,内置页面消息走 MainWindow.xaml.cs 中的 switch/case 分发。