摘要
OnAddinLoad 在加载项生命周期早期注册 ApiEvent、恢复模型索引并异步 loadModelList。openAIAssistantDialog 使用 Util.GetUrlPath 与 GetRouterHash 拼接 SPA 地址,是与 WPS ShowDialog 强耦合的关键路径。
关键词
OnAddinLoad;ShowDialog;ribbon
扩展阅读与维护提示
本篇围绕「从 Ribbon 加载到 AI 对话框 URL 拼装」组织材料。仓库内与主题最直接相关的检索词包括:OnAddinLoad、ShowDialog、ribbon。建议在阅读正文所列片段后,用 IDE 全局搜索这些符号,沿 import 与调用栈向上追问「谁在什么时机调用」,而不是只记住单文件路径。
摘要所概括的要点为:OnAddinLoad 在加载项生命周期早期注册 ApiEvent、恢复模型索引并异步 loadModelList。openAIAssistantDialog 使用 Util.GetUrlPath 与 GetRouterHash 拼接 SPA 地址,是与 WPS ShowDialog 强耦合的关键路径。落地到排障时,可把现象粗分为三类交叉验证:配置是否按预期写入持久化介质;WPS COM 上下文是否可用(例如是否缺少 ActiveDocument);以及网络与证书策略是否拦截了 fetch。本篇涉及的模块通常只覆盖其中一两类,需要与相邻篇目拼成完整拼图。
教程文件名「12-yuanma-fenceng-yu-AI-bianma-zai-ben-xiangmu.md」仅用于导航与排序,不等价于源码模块名。若正文中的行号与本地分支不一致,多半因合并导致行偏移,此时应以函数名、导出名为锚重新检索;团队若维护了生成脚本,可在变更大段源码后重新运行以保持摘录大致对齐。
本文刻意避免对产品能力做营销式承诺:所述行为均以当前仓库可见实现为准。若组织策略要求离线或内网模型,应在网关、证书与代理层收口,而不是假设加载项能绕过浏览器安全模型。
若你同时阅读 docs/chayuan-llm-chain-series,可先对照其中的总体链路图理解「请求从 UI 到 chatApi」的次序,再回到本教程看数据结构、默认值与修改风险面;两者互补,不重复堆砌功能列表。
正文
1. 启动钩子
枚举注入、PluginStorage 标记位、文档事件监听均在此处完成。
阅读源码摘录时,请把它当作「定位入口」而非完整实现:同一函数可能在其他分支还有早退条件或 try/catch。修改默认行为前,建议用最小文档手工走一遍相关助手或对话框,并观察任务清单与日志中的字段是否与预期一致,再决定是否做数据迁移或配置重置。
// src/components/ribbon.js 第51-93行
//这个函数在整个wps加载项中是第一个执行的
function OnAddinLoad(ribbonUI) {
if (typeof window.Application.ribbonUI != 'object') {
window.Application.ribbonUI = ribbonUI
}
if (typeof window.Application.Enum != 'object') {
// 如果没有内置枚举值
window.Application.Enum = Util.WPS_Enum
}
//这几个导出函数是给外部业务系统调用的
window.openOfficeFileFromSystemDemo = SystemDemo.openOfficeFileFromSystemDemo
window.InvokeFromSystemDemo = SystemDemo.InvokeFromSystemDemo
window.Application.PluginStorage.setItem('EnableFlag', false) //往PluginStorage中设置一个标记,用于控制两个按钮的置灰
window.Application.PluginStorage.setItem('ApiEventFlag', false) //往PluginStorage中设置一个标记,用于控制ApiEvent的按钮label
// 文档打开或切换时刷新表单模式按钮状态(从文档变量/保护类型读取)
try {
if (window.Application.ApiEvent) {
window.Application.ApiEvent.AddApiEventListener('DocumentOpen', 'ribbon.OnDocumentOpenForFormMode')
window.Application.ApiEvent.AddApiEventListener('WindowActivate', 'ribbon.OnWindowActivateForFormMode')
window.Application.ApiEvent.AddApiEventListener('DocumentBeforeSave', 'ribbon.OnDocumentBeforeSave')
}
} catch (e) {
console.warn('注册文档事件失败:', e)
}
// 先设置默认模型列表,确保有数据显示
setDefaultModels()
// 从存储恢复选中的模型索引;无有效选中时默认选中 OpenAI
const storedIndex = window.Application.PluginStorage.getItem('selectedModelIndex')
if (storedIndex !== undefined && storedIndex !== null) {
const idx = parseInt(storedIndex, 10)
if (!isNaN(idx)) selectedModelIndex = idx
} else {
selectedModelIndex = getOpenAIModelIndex(getModelList())
}
// 然后尝试从接口加载(异步)
loadModelList()
return true
2. AI 助手 URL
ShowDialog 第一个参数必须是可加载的完整 URL,含 hash 与路由段。
阅读源码摘录时,请把它当作「定位入口」而非完整实现:同一函数可能在其他分支还有早退条件或 try/catch。修改默认行为前,建议用最小文档手工走一遍相关助手或对话框,并观察任务清单与日志中的字段是否与预期一致,再决定是否做数据迁移或配置重置。
// src/components/ribbon.js 第96-105行
function openAIAssistantDialog(query = {}) {
const queryString = new URLSearchParams(query).toString()
const aiUrl = Util.GetUrlPath() + Util.GetRouterHash() + `/ai-assistant${queryString ? `?${queryString}` : ''}`
window.Application.ShowDialog(
aiUrl,
'察元 AI 助手',
900 * (window.devicePixelRatio || 1),
700 * (window.devicePixelRatio || 1),
false
)

