[{"data":1,"prerenderedAt":1231},["ShallowReactive",2],{"navigation":3,"\u002Fdocs\u002Fdevelopment\u002Fquick-start\u002Fintroduction":199,"\u002Fdocs\u002Fdevelopment\u002Fquick-start\u002Fintroduction-surround":1226},[4,9,41,111,116,132],{"title":5,"path":6,"stem":7,"icon":8},"准备","\u002Fdocs\u002Fpreparation","1.docs\u002F1.preparation","i-lucide-rocket",{"title":10,"icon":11,"path":12,"stem":13,"children":14,"page":40},"用户手册","i-lucide-book-open","\u002Fdocs\u002Fgetting-started","1.docs\u002F2.getting-started",[15,20,25,30,35],{"title":16,"path":17,"stem":18,"icon":19},"认识 UDhold","\u002Fdocs\u002Fgetting-started\u002Fwhat-is-udhold","1.docs\u002F2.getting-started\u002F1.what-is-udhold","i-lucide-info",{"title":21,"path":22,"stem":23,"icon":24},"核心概念","\u002Fdocs\u002Fgetting-started\u002Fcore-concepts","1.docs\u002F2.getting-started\u002F2.core-concepts","i-lucide-lightbulb",{"title":26,"path":27,"stem":28,"icon":29},"主面板布局","\u002Fdocs\u002Fgetting-started\u002Fmain-interface","1.docs\u002F2.getting-started\u002F3.main-interface","i-lucide-monitor",{"title":31,"path":32,"stem":33,"icon":34},"快速上手 5 分钟","\u002Fdocs\u002Fgetting-started\u002Fquick-tour","1.docs\u002F2.getting-started\u002F4.quick-tour","i-lucide-zap",{"title":36,"path":37,"stem":38,"icon":39},"常用快捷键","\u002Fdocs\u002Fgetting-started\u002Fshortcut-keys","1.docs\u002F2.getting-started\u002F5.shortcut-keys","i-lucide-keyboard",false,{"title":42,"path":43,"stem":44,"children":45,"icon":110},"核心功能","\u002Fdocs\u002Ffeatures","1.docs\u002F3.features\u002F1.index",[46,49,53,58,63,67,71,76,81,86,91,96,101,106],{"title":47,"path":43,"stem":44,"icon":48},"功能总览","i-lucide-layout-grid",{"title":50,"path":51,"stem":52,"icon":39},"快捷键","\u002Fdocs\u002Ffeatures\u002Fshortcuts","1.docs\u002F3.features\u002F10.shortcuts",{"title":54,"path":55,"stem":56,"icon":57},"AI 模型","\u002Fdocs\u002Ffeatures\u002Fai-models","1.docs\u002F3.features\u002F16.ai-models","i-lucide-bot",{"title":59,"path":60,"stem":61,"icon":62},"AI 助手","\u002Fdocs\u002Ffeatures\u002Fai-helper","1.docs\u002F3.features\u002F17.ai-helper","i-lucide-bot-message-square",{"title":64,"path":65,"stem":66,"icon":19},"关于","\u002Fdocs\u002Ffeatures\u002Fabout","1.docs\u002F3.features\u002F19.about",{"title":68,"path":69,"stem":70,"icon":29},"系统命令","\u002Fdocs\u002Ffeatures\u002Fsystem","1.docs\u002F3.features\u002F2.system",{"title":72,"path":73,"stem":74,"icon":75},"调试日志","\u002Fdocs\u002Ffeatures\u002Fdebug","1.docs\u002F3.features\u002F20.debug","i-lucide-terminal",{"title":77,"path":78,"stem":79,"icon":80},"通用设置","\u002Fdocs\u002Ffeatures\u002Fsettings","1.docs\u002F3.features\u002F21.settings","i-mdi-cog-outline",{"title":82,"path":83,"stem":84,"icon":85},"文件资源管理器","\u002Fdocs\u002Ffeatures\u002Ffiles","1.docs\u002F3.features\u002F3.files","i-lucide-folder-tree",{"title":87,"path":88,"stem":89,"icon":90},"文件树","\u002Fdocs\u002Ffeatures\u002Ffiles-tree","1.docs\u002F3.features\u002F4.files-tree","i-lucide-list-tree",{"title":92,"path":93,"stem":94,"icon":95},"文件预览","\u002Fdocs\u002Ffeatures\u002Fpreview","1.docs\u002F3.features\u002F5.preview","i-lucide-eye",{"title":97,"path":98,"stem":99,"icon":100},"本地启动","\u002Fdocs\u002Ffeatures\u002Flocal-launch","1.docs\u002F3.features\u002F6.local-launch","i-lucide-app-window",{"title":102,"path":103,"stem":104,"icon":105},"插件中心","\u002Fdocs\u002Ffeatures\u002Fplugins","1.docs\u002F3.features\u002F7.plugins","i-lucide-puzzle",{"title":107,"path":108,"stem":109,"icon":8},"快速启动","\u002Fdocs\u002Ffeatures\u002Fquick-start","1.docs\u002F3.features\u002F8.quick-start","i-lucide-star",{"title":112,"path":113,"stem":114,"icon":115},"主题","\u002Fdocs\u002Fthemes","1.docs\u002F4.themes","i-lucide-palette",{"title":117,"icon":118,"path":119,"stem":120,"children":121,"page":40},"相关协议","i-lucide-scroll","\u002Fdocs\u002Flegal","1.docs\u002F5.legal",[122,127],{"title":123,"path":124,"stem":125,"icon":126},"用户须知","\u002Fdocs\u002Flegal\u002Fuser-notice","1.docs\u002F5.legal\u002F1.user-notice","i-lucide-file-text",{"title":128,"path":129,"stem":130,"icon":131},"隐私协议","\u002Fdocs\u002Flegal\u002Fprivacy","1.docs\u002F5.legal\u002F2.privacy","i-lucide-shield-check",{"title":133,"icon":134,"path":135,"stem":136,"children":137,"page":40},"开发指南","i-lucide-code","\u002Fdocs\u002Fdevelopment","1.docs\u002F6.development",[138,156,190],{"title":139,"icon":8,"path":140,"stem":141,"children":142,"page":40},"快速开始","\u002Fdocs\u002Fdevelopment\u002Fquick-start","1.docs\u002F6.development\u002F1.quick-start",[143,147,151],{"title":144,"path":145,"stem":146,"icon":19},"介绍","\u002Fdocs\u002Fdevelopment\u002Fquick-start\u002Fintroduction","1.docs\u002F6.development\u002F1.quick-start\u002F1.introduction",{"title":148,"path":149,"stem":150,"icon":34},"快速上手","\u002Fdocs\u002Fdevelopment\u002Fquick-start\u002Fgetting-started","1.docs\u002F6.development\u002F1.quick-start\u002F2.getting-started",{"title":152,"path":153,"stem":154,"icon":155},"常见问题","\u002Fdocs\u002Fdevelopment\u002Fquick-start\u002Ffaq","1.docs\u002F6.development\u002F1.quick-start\u002F3.faq","i-lucide-circle-help",{"title":157,"icon":115,"path":158,"stem":159,"children":160,"page":40},"设计系统","\u002Fdocs\u002Fdevelopment\u002Fdesign-system","1.docs\u002F6.development\u002F2.design-system",[161,166,171,176,181,186],{"title":162,"path":163,"stem":164,"icon":165},"设计令牌","\u002Fdocs\u002Fdevelopment\u002Fdesign-system\u002Ftokens","1.docs\u002F6.development\u002F2.design-system\u002F1.tokens","i-lucide-pipette",{"title":167,"path":168,"stem":169,"icon":170},"主题与明暗模式","\u002Fdocs\u002Fdevelopment\u002Fdesign-system\u002Ftheming","1.docs\u002F6.development\u002F2.design-system\u002F2.theming","i-lucide-sun-moon",{"title":172,"path":173,"stem":174,"icon":175},"基础样式类","\u002Fdocs\u002Fdevelopment\u002Fdesign-system\u002Fbase-styles","1.docs\u002F6.development\u002F2.design-system\u002F3.base-styles","i-lucide-layout-template",{"title":177,"path":178,"stem":179,"icon":180},"图标体系","\u002Fdocs\u002Fdevelopment\u002Fdesign-system\u002Ficons","1.docs\u002F6.development\u002F2.design-system\u002F4.icons","i-lucide-shapes",{"title":182,"path":183,"stem":184,"icon":185},"通用组件","\u002Fdocs\u002Fdevelopment\u002Fdesign-system\u002Fcomponents","1.docs\u002F6.development\u002F2.design-system\u002F5.components","i-lucide-component",{"title":187,"path":188,"stem":189,"icon":48},"场景组件","\u002Fdocs\u002Fdevelopment\u002Fdesign-system\u002Fscene-components","1.docs\u002F6.development\u002F2.design-system\u002F6.scene-components",{"title":191,"icon":57,"path":192,"stem":193,"children":194,"page":40},"AI","\u002Fdocs\u002Fdevelopment\u002Fai","1.docs\u002F6.development\u002F3.ai",[195],{"title":196,"path":197,"stem":198,"icon":126},"LLMs.txt","\u002Fdocs\u002Fdevelopment\u002Fai\u002Fllms-txt","1.docs\u002F6.development\u002F3.ai\u002F1.llms-txt",{"id":200,"title":144,"body":201,"description":1219,"extension":1220,"meta":1221,"navigation":1222,"path":145,"rawbody":1223,"seo":1224,"stem":146,"__hash__":1225},"docs\u002F1.docs\u002F6.development\u002F1.quick-start\u002F1.introduction.md",{"type":202,"value":203,"toc":1210},"minimark",[204,208,212,220,230,237,240,342,366,369,375,584,598,601,611,680,695,698,701,1098,1124,1127,1147,1150,1200,1206],[205,206,207],"p",{},"这一章回答三个问题：插件在 UDhold 里是什么、能做成什么形态、能调用哪些能力。读完你就能判断自己的点子适不适合做成插件，该做成哪种形态。",[209,210,211],"h2",{"id":211},"插件是什么",[205,213,214,215,219],{},"UDhold 宿主基于 Tauri 2 构建。每个插件打开时，宿主会为它创建一个独立的 WebView（网页容器），加载插件声明的前端页面；插件与宿主之间通过注入的 ",[216,217,218],"code",{},"window.udhold"," 桥对象通信。",[221,222,227],"pre",{"className":223,"code":225,"language":226},[224],"language-text","┌─────────────── UDhold 宿主（Tauri 2 \u002F Rust）───────────────┐\n│  主面板（活动栏 \u002F 左侧面板 \u002F 工作区 \u002F 右侧面板）            │\n│  ┌────────────┐  ┌──────────────────┐  ┌────────────┐    │\n│  │ 插件 A      │  │ 插件 B（你的插件） │  │ 插件 C      │    │\n│  │ WebView     │  │ WebView          │  │ 服务进程    │    │\n│  └────────────┘  └────────┬─────────┘  └────────────┘    │\n│                           │ window.udhold（桥 + 权限网关） │\n│  文件 \u002F 剪贴板 \u002F 数据库 \u002F AI \u002F 系统命令 ……（26 个能力域）   │\n└──────────────────────────────────────────────────────────┘\n","text",[216,228,225],{"__ignoreMap":229},"",[205,231,232,233,236],{},"插件工程的唯一契约是根目录的 ",[216,234,235],{},"plugin.json","——名字、入口、面板槽位、搜索关键词、权限需求全部声明在这一个文件里，宿主按声明加载与管控。清单体系兼容 uTools 插件协议，熟悉 uTools 开发的开发者可以无缝迁移。",[209,238,239],{"id":239},"插件的四种形态",[241,242,243,262],"table",{},[244,245,246],"thead",{},[247,248,249,253,256,259],"tr",{},[250,251,252],"th",{},"形态",[250,254,255],{},"构成",[250,257,258],{},"典型例子",[250,260,261],{},"适合场景",[263,264,265,283,306,326],"tbody",{},[247,266,267,274,277,280],{},[268,269,270],"td",{},[271,272,273],"strong",{},"页面插件",[268,275,276],{},"前端工程（Vue \u002F React \u002F 纯 HTML），构建出静态产物",[268,278,279],{},"计算器、JSON Tools、待办清单",[268,281,282],{},"有界面的工具",[247,284,285,290,300,303],{},[268,286,287],{},[271,288,289],{},"免构建静态插件",[268,291,292,293,296,297,299],{},"一个 ",[216,294,295],{},"index.html"," + ",[216,298,235],{},"，无需 Node 工程",[268,301,302],{},"简单的小工具页",[268,304,305],{},"轻量工具、快速验证想法",[247,307,308,313,320,323],{},[268,309,310],{},[271,311,312],{},"纯服务插件",[268,314,315,316,319],{},"只有 ",[216,317,318],{},"services[]"," 声明（Node \u002F Python \u002F exe），没有界面",[268,321,322],{},"后台服务、绿色软件封装",[268,324,325],{},"无界面的后台能力",[247,327,328,333,336,339],{},[268,329,330],{},[271,331,332],{},"页面 + 服务",[268,334,335],{},"前端页面 + 声明式服务进程",[268,337,338],{},"需要本地后端的复杂插件",[268,340,341],{},"本地数据库、爬虫、编译类工具",[205,343,344,345,348,349,352,353,356,357,360,361,365],{},"页面插件还可以通过 ",[216,346,347],{},"pluginSetting"," 进一步定制形态：嵌入工作区面板、挂在左右侧栏、打开即分离成独立窗口（",[216,350,351],{},"Detach","）、进活动栏顶部\u002F底部菜单（",[216,354,355],{},"Menu"," \u002F ",[216,358,359],{},"MenuBottom","）等，详见",[362,363,148],"a",{"href":364},".\u002Fgetting-started","的清单字段说明。",[209,367,368],{"id":368},"能调用哪些能力",[205,370,371,372,374],{},"插件通过 ",[216,373,218],{}," 调用宿主能力，共 26 个命名空间、200 多个方法。常用的能力域：",[241,376,377,390],{},[244,378,379],{},[247,380,381,384,387],{},[250,382,383],{},"能力域",[250,385,386],{},"说明",[250,388,389],{},"示例调用",[263,391,392,413,434,449,464,482,500,515,530,545,563],{},[247,393,394,405,408],{},[268,395,396,356,399,356,402],{},[216,397,398],{},"db",[216,400,401],{},"dbStorage",[216,403,404],{},"dbCryptoStorage",[268,406,407],{},"文档数据库 \u002F 键值存储 \u002F 加密键值存储，数据自动按插件隔离",[268,409,410],{},[216,411,412],{},"udhold.dbStorage.setItem('k', 'v')",[247,414,415,426,429],{},[268,416,417,356,420,356,423],{},[216,418,419],{},"plugin",[216,421,422],{},"router",[216,424,425],{},"route",[268,427,428],{},"插件运行时：生命周期钩子、跨插件调用、tab 操作",[268,430,431],{},[216,432,433],{},"udhold.router.push('files')",[247,435,436,441,444],{},[268,437,438],{},[216,439,440],{},"files",[268,442,443],{},"文件资源管理：列举、新建、重命名、删除、批量复制、监听",[268,445,446],{},[216,447,448],{},"udhold.files.list('D:\\\\')",[247,450,451,456,459],{},[268,452,453],{},[216,454,455],{},"clipboard",[268,457,458],{},"剪贴板历史与读写",[268,460,461],{},[216,462,463],{},"udhold.copyText('文本')",[247,465,466,474,477],{},[268,467,468,356,471],{},[216,469,470],{},"ai",[216,472,473],{},"ai.models",[268,475,476],{},"大模型推理（流式）、模型配置",[268,478,479],{},[216,480,481],{},"udhold.ai({ model, messages })",[247,483,484,492,495],{},[268,485,486,356,489],{},[216,487,488],{},"system",[216,490,491],{},"shell",[268,493,494],{},"系统命令、通知、打开文件\u002F网址",[268,496,497],{},[216,498,499],{},"udhold.shellOpenExternal(url)",[247,501,502,507,510],{},[268,503,504],{},[216,505,506],{},"search",[268,508,509],{},"唤起全局搜索框",[268,511,512],{},[216,513,514],{},"udhold.search.openWithKeyword('kw')",[247,516,517,522,525],{},[268,518,519],{},[216,520,521],{},"setting",[268,523,524],{},"宿主外观与行为配置",[268,526,527],{},[216,528,529],{},"udhold.setting.setTheme('dark')",[247,531,532,537,540],{},[268,533,534],{},[216,535,536],{},"udbrowser",[268,538,539],{},"内嵌浏览器自动化（打开页面、点击、取数）",[268,541,542],{},[216,543,544],{},"udhold.udbrowser.create()",[247,546,547,555,558],{},[268,548,549,356,552],{},[216,550,551],{},"service",[216,553,554],{},"node",[268,556,557],{},"拉起并管理本地服务进程",[268,559,560],{},[216,561,562],{},"udhold.service.spawn(cfg)",[247,564,565,576,579],{},[268,566,567,356,570,356,573],{},[216,568,569],{},"user",[216,571,572],{},"sync",[216,574,575],{},"netdisk",[268,577,578],{},"登录态、WebDAV 同步、简盘",[268,580,581],{},[216,582,583],{},"udhold.user.isLogin()",[205,585,586,587,296,590,593,594,597],{},"除了直接调用，插件还能通过 ",[216,588,589],{},"exports",[216,591,592],{},"registerTool"," ",[271,595,596],{},"对外暴露接口","供其他插件（以及宿主的 MCP 服务）调用，形成插件间的协作生态。",[209,599,600],{"id":600},"权限模型",[205,602,603,604,606,607,610],{},"UDhold 采用三层声明式权限：用到什么，就在 ",[216,605,235],{}," 里声明什么，未声明的调用会被宿主权限网关拒绝（返回 ",[216,608,609],{},"PERMISSION_DENIED","）。",[241,612,613,626],{},[244,614,615],{},[247,616,617,620,623],{},[250,618,619],{},"声明字段",[250,621,622],{},"管什么",[250,624,625],{},"示例",[263,627,628,643,658],{},[247,629,630,635,638],{},[268,631,632],{},[216,633,634],{},"permissions[]",[268,636,637],{},"平台能力路径：敏感域（文件、剪贴板历史、AI、登录态等）必须声明；存储、路由等基础能力免声明",[268,639,640],{},[216,641,642],{},"\"permissions\": [\"files.list\", \"ai.*\"]",[247,644,645,650,653],{},[268,646,647],{},[216,648,649],{},"tauri[]",[268,651,652],{},"原生能力：对话框、通知、文件选择器等",[268,654,655],{},[216,656,657],{},"\"tauri\": [\"dialog:default\"]",[247,659,660,665,675],{},[268,661,662],{},[216,663,664],{},"plugins[]",[268,666,667,668,356,671,674],{},"跨插件调用白名单：要 ",[216,669,670],{},"push",[216,672,673],{},"invoke"," 其他插件，先在这里登记目标插件名",[268,676,677],{},[216,678,679],{},"\"plugins\": [\"files\"]",[205,681,682,683,686,687,690,691,694],{},"通配符只支持后缀：",[216,684,685],{},"user.*"," 放行整个 user 域，",[216,688,689],{},"ai.models.list"," 精确到单个方法。不要声明 ",[216,692,693],{},"\"*\"","（全量授权，市场审核时视为最高风险）。",[209,696,697],{"id":697},"生命周期",[205,699,700],{},"插件实例有 12 个生命周期钩子，覆盖从打开到销毁的完整过程：",[221,702,706],{"className":703,"code":704,"language":705,"meta":229,"style":229},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","udhold.plugin.onMounted((action) => {})     \u002F\u002F 页面就绪，action.code 区分被哪个 feature 唤起\nudhold.plugin.onActivated((p) => {})        \u002F\u002F tab 切入\nudhold.plugin.onDeactivated((p) => {})      \u002F\u002F tab 被切走\nudhold.plugin.onDetached((p) => {})         \u002F\u002F 分离成独立窗口\nudhold.plugin.onAttached((p) => {})         \u002F\u002F 从独立窗口回归面板\nudhold.plugin.onBeforeUnmount((p) => {})    \u002F\u002F 实例销毁前（唯一清理时机，宿主等 200ms）\nudhold.plugin.onShow((p) => {})             \u002F\u002F 获得焦点\nudhold.plugin.onBlur((p) => {})             \u002F\u002F 失去焦点\nudhold.plugin.onMinimized((p) => {})        \u002F\u002F 承载窗口最小化\nudhold.plugin.onRestored((p) => {})         \u002F\u002F 承载窗口还原\nudhold.plugin.onAppLaunched((p) => {})      \u002F\u002F 宿主启动（粘性）\nudhold.plugin.onAppBeforeQuit(() => {})     \u002F\u002F 宿主退出前\n","ts",[216,707,708,755,787,819,851,882,914,946,977,1008,1039,1070],{"__ignoreMap":229},[709,710,713,717,721,723,725,729,732,734,738,741,745,748,751],"span",{"class":711,"line":712},"line",1,[709,714,716],{"class":715},"sTEyZ","udhold",[709,718,720],{"class":719},"sMK4o",".",[709,722,419],{"class":715},[709,724,720],{"class":719},[709,726,728],{"class":727},"s2Zo4","onMounted",[709,730,731],{"class":715},"(",[709,733,731],{"class":719},[709,735,737],{"class":736},"sHdIc","action",[709,739,740],{"class":719},")",[709,742,744],{"class":743},"spNyl"," =>",[709,746,747],{"class":719}," {}",[709,749,750],{"class":715},")     ",[709,752,754],{"class":753},"sHwdD","\u002F\u002F 页面就绪，action.code 区分被哪个 feature 唤起\n",[709,756,758,760,762,764,766,769,771,773,775,777,779,781,784],{"class":711,"line":757},2,[709,759,716],{"class":715},[709,761,720],{"class":719},[709,763,419],{"class":715},[709,765,720],{"class":719},[709,767,768],{"class":727},"onActivated",[709,770,731],{"class":715},[709,772,731],{"class":719},[709,774,205],{"class":736},[709,776,740],{"class":719},[709,778,744],{"class":743},[709,780,747],{"class":719},[709,782,783],{"class":715},")        ",[709,785,786],{"class":753},"\u002F\u002F tab 切入\n",[709,788,790,792,794,796,798,801,803,805,807,809,811,813,816],{"class":711,"line":789},3,[709,791,716],{"class":715},[709,793,720],{"class":719},[709,795,419],{"class":715},[709,797,720],{"class":719},[709,799,800],{"class":727},"onDeactivated",[709,802,731],{"class":715},[709,804,731],{"class":719},[709,806,205],{"class":736},[709,808,740],{"class":719},[709,810,744],{"class":743},[709,812,747],{"class":719},[709,814,815],{"class":715},")      ",[709,817,818],{"class":753},"\u002F\u002F tab 被切走\n",[709,820,822,824,826,828,830,833,835,837,839,841,843,845,848],{"class":711,"line":821},4,[709,823,716],{"class":715},[709,825,720],{"class":719},[709,827,419],{"class":715},[709,829,720],{"class":719},[709,831,832],{"class":727},"onDetached",[709,834,731],{"class":715},[709,836,731],{"class":719},[709,838,205],{"class":736},[709,840,740],{"class":719},[709,842,744],{"class":743},[709,844,747],{"class":719},[709,846,847],{"class":715},")         ",[709,849,850],{"class":753},"\u002F\u002F 分离成独立窗口\n",[709,852,854,856,858,860,862,865,867,869,871,873,875,877,879],{"class":711,"line":853},5,[709,855,716],{"class":715},[709,857,720],{"class":719},[709,859,419],{"class":715},[709,861,720],{"class":719},[709,863,864],{"class":727},"onAttached",[709,866,731],{"class":715},[709,868,731],{"class":719},[709,870,205],{"class":736},[709,872,740],{"class":719},[709,874,744],{"class":743},[709,876,747],{"class":719},[709,878,847],{"class":715},[709,880,881],{"class":753},"\u002F\u002F 从独立窗口回归面板\n",[709,883,885,887,889,891,893,896,898,900,902,904,906,908,911],{"class":711,"line":884},6,[709,886,716],{"class":715},[709,888,720],{"class":719},[709,890,419],{"class":715},[709,892,720],{"class":719},[709,894,895],{"class":727},"onBeforeUnmount",[709,897,731],{"class":715},[709,899,731],{"class":719},[709,901,205],{"class":736},[709,903,740],{"class":719},[709,905,744],{"class":743},[709,907,747],{"class":719},[709,909,910],{"class":715},")    ",[709,912,913],{"class":753},"\u002F\u002F 实例销毁前（唯一清理时机，宿主等 200ms）\n",[709,915,917,919,921,923,925,928,930,932,934,936,938,940,943],{"class":711,"line":916},7,[709,918,716],{"class":715},[709,920,720],{"class":719},[709,922,419],{"class":715},[709,924,720],{"class":719},[709,926,927],{"class":727},"onShow",[709,929,731],{"class":715},[709,931,731],{"class":719},[709,933,205],{"class":736},[709,935,740],{"class":719},[709,937,744],{"class":743},[709,939,747],{"class":719},[709,941,942],{"class":715},")             ",[709,944,945],{"class":753},"\u002F\u002F 获得焦点\n",[709,947,949,951,953,955,957,960,962,964,966,968,970,972,974],{"class":711,"line":948},8,[709,950,716],{"class":715},[709,952,720],{"class":719},[709,954,419],{"class":715},[709,956,720],{"class":719},[709,958,959],{"class":727},"onBlur",[709,961,731],{"class":715},[709,963,731],{"class":719},[709,965,205],{"class":736},[709,967,740],{"class":719},[709,969,744],{"class":743},[709,971,747],{"class":719},[709,973,942],{"class":715},[709,975,976],{"class":753},"\u002F\u002F 失去焦点\n",[709,978,980,982,984,986,988,991,993,995,997,999,1001,1003,1005],{"class":711,"line":979},9,[709,981,716],{"class":715},[709,983,720],{"class":719},[709,985,419],{"class":715},[709,987,720],{"class":719},[709,989,990],{"class":727},"onMinimized",[709,992,731],{"class":715},[709,994,731],{"class":719},[709,996,205],{"class":736},[709,998,740],{"class":719},[709,1000,744],{"class":743},[709,1002,747],{"class":719},[709,1004,783],{"class":715},[709,1006,1007],{"class":753},"\u002F\u002F 承载窗口最小化\n",[709,1009,1011,1013,1015,1017,1019,1022,1024,1026,1028,1030,1032,1034,1036],{"class":711,"line":1010},10,[709,1012,716],{"class":715},[709,1014,720],{"class":719},[709,1016,419],{"class":715},[709,1018,720],{"class":719},[709,1020,1021],{"class":727},"onRestored",[709,1023,731],{"class":715},[709,1025,731],{"class":719},[709,1027,205],{"class":736},[709,1029,740],{"class":719},[709,1031,744],{"class":743},[709,1033,747],{"class":719},[709,1035,847],{"class":715},[709,1037,1038],{"class":753},"\u002F\u002F 承载窗口还原\n",[709,1040,1042,1044,1046,1048,1050,1053,1055,1057,1059,1061,1063,1065,1067],{"class":711,"line":1041},11,[709,1043,716],{"class":715},[709,1045,720],{"class":719},[709,1047,419],{"class":715},[709,1049,720],{"class":719},[709,1051,1052],{"class":727},"onAppLaunched",[709,1054,731],{"class":715},[709,1056,731],{"class":719},[709,1058,205],{"class":736},[709,1060,740],{"class":719},[709,1062,744],{"class":743},[709,1064,747],{"class":719},[709,1066,815],{"class":715},[709,1068,1069],{"class":753},"\u002F\u002F 宿主启动（粘性）\n",[709,1071,1073,1075,1077,1079,1081,1084,1086,1089,1091,1093,1095],{"class":711,"line":1072},12,[709,1074,716],{"class":715},[709,1076,720],{"class":719},[709,1078,419],{"class":715},[709,1080,720],{"class":719},[709,1082,1083],{"class":727},"onAppBeforeQuit",[709,1085,731],{"class":715},[709,1087,1088],{"class":719},"()",[709,1090,744],{"class":743},[709,1092,747],{"class":719},[709,1094,750],{"class":715},[709,1096,1097],{"class":753},"\u002F\u002F 宿主退出前\n",[205,1099,1100,1101,1103,1104,1107,1108,1111,1112,1115,1116,1119,1120,1123],{},"所有钩子返回取消函数，可多次注册叠加。",[216,1102,728],{}," 的 ",[216,1105,1106],{},"action.from"," 能区分唤起来源（主输入框 ",[216,1109,1110],{},"main","、面板 ",[216,1113,1114],{},"panel","、快捷键 ",[216,1117,1118],{},"hotkey","、其他插件跳转 ",[216,1121,1122],{},"redirect"," 等）。",[209,1125,1126],{"id":1126},"分发方式",[1128,1129,1130,1137],"ul",{},[1131,1132,1133,1136],"li",{},[271,1134,1135],{},"插件市场","：在「插件开发者」里一键打包上传，审核通过后全平台用户可搜可装；已装用户打开插件时宿主自动检查更新。",[1131,1138,1139,1142,1143,1146],{},[271,1140,1141],{},"本地安装包","：打包为 ",[216,1144,1145],{},".zip","，可以发给朋友双击安装，或在插件中心手动安装，适合内部分发与灰度测试。",[209,1148,1149],{"id":1149},"开发前的准备",[241,1151,1152,1161],{},[244,1153,1154],{},[247,1155,1156,1159],{},[250,1157,1158],{},"需要",[250,1160,386],{},[263,1162,1163,1176,1184,1192],{},[247,1164,1165,1168],{},[268,1166,1167],{},"UDhold 桌面端",[268,1169,1170,1171,1175],{},"调试与打包都在宿主里完成，",[362,1172,1174],{"href":1173},"\u002F#download","下载","安装",[247,1177,1178,1181],{},[268,1179,1180],{},"HTML \u002F CSS \u002F JavaScript 基础",[268,1182,1183],{},"插件本质是 Web 页面；推荐用 Vue 3（官方插件与组件库同栈，生态最顺）",[247,1185,1186,1189],{},[268,1187,1188],{},"Node.js 20+ 与 pnpm",[268,1190,1191],{},"工程型插件需要；纯静态插件可跳过",[247,1193,1194,1197],{},[268,1195,1196],{},"一个想法",[268,1198,1199],{},"从自己每天会重复做的小事开始，最容易做出好插件",[205,1201,1202,1203,1205],{},"准备好了？进入",[362,1204,148],{"href":364},"，20 分钟跑起你的第一个插件。",[1207,1208,1209],"style",{},"html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":229,"searchDepth":757,"depth":757,"links":1211},[1212,1213,1214,1215,1216,1217,1218],{"id":211,"depth":757,"text":211},{"id":239,"depth":757,"text":239},{"id":368,"depth":757,"text":368},{"id":600,"depth":757,"text":600},{"id":697,"depth":757,"text":697},{"id":1126,"depth":757,"text":1126},{"id":1149,"depth":757,"text":1149},"了解 UDhold 插件的运行机制、形态分类、能力域与权限模型。","md",{},{"icon":19},"---\ntitle: 介绍\ndescription: 了解 UDhold 插件的运行机制、形态分类、能力域与权限模型。\nnavigation:\n  icon: i-lucide-info\n---\n\n这一章回答三个问题：插件在 UDhold 里是什么、能做成什么形态、能调用哪些能力。读完你就能判断自己的点子适不适合做成插件，该做成哪种形态。\n\n## 插件是什么\n\nUDhold 宿主基于 Tauri 2 构建。每个插件打开时，宿主会为它创建一个独立的 WebView（网页容器），加载插件声明的前端页面；插件与宿主之间通过注入的 `window.udhold` 桥对象通信。\n\n```\n┌─────────────── UDhold 宿主（Tauri 2 \u002F Rust）───────────────┐\n│  主面板（活动栏 \u002F 左侧面板 \u002F 工作区 \u002F 右侧面板）            │\n│  ┌────────────┐  ┌──────────────────┐  ┌────────────┐    │\n│  │ 插件 A      │  │ 插件 B（你的插件） │  │ 插件 C      │    │\n│  │ WebView     │  │ WebView          │  │ 服务进程    │    │\n│  └────────────┘  └────────┬─────────┘  └────────────┘    │\n│                           │ window.udhold（桥 + 权限网关） │\n│  文件 \u002F 剪贴板 \u002F 数据库 \u002F AI \u002F 系统命令 ……（26 个能力域）   │\n└──────────────────────────────────────────────────────────┘\n```\n\n插件工程的唯一契约是根目录的 `plugin.json`——名字、入口、面板槽位、搜索关键词、权限需求全部声明在这一个文件里，宿主按声明加载与管控。清单体系兼容 uTools 插件协议，熟悉 uTools 开发的开发者可以无缝迁移。\n\n## 插件的四种形态\n\n| 形态 | 构成 | 典型例子 | 适合场景 |\n|------|------|----------|----------|\n| **页面插件** | 前端工程（Vue \u002F React \u002F 纯 HTML），构建出静态产物 | 计算器、JSON Tools、待办清单 | 有界面的工具 |\n| **免构建静态插件** | 一个 `index.html` + `plugin.json`，无需 Node 工程 | 简单的小工具页 | 轻量工具、快速验证想法 |\n| **纯服务插件** | 只有 `services[]` 声明（Node \u002F Python \u002F exe），没有界面 | 后台服务、绿色软件封装 | 无界面的后台能力 |\n| **页面 + 服务** | 前端页面 + 声明式服务进程 | 需要本地后端的复杂插件 | 本地数据库、爬虫、编译类工具 |\n\n页面插件还可以通过 `pluginSetting` 进一步定制形态：嵌入工作区面板、挂在左右侧栏、打开即分离成独立窗口（`Detach`）、进活动栏顶部\u002F底部菜单（`Menu` \u002F `MenuBottom`）等，详见[快速上手](.\u002Fgetting-started)的清单字段说明。\n\n## 能调用哪些能力\n\n插件通过 `window.udhold` 调用宿主能力，共 26 个命名空间、200 多个方法。常用的能力域：\n\n| 能力域 | 说明 | 示例调用 |\n|--------|------|----------|\n| `db` \u002F `dbStorage` \u002F `dbCryptoStorage` | 文档数据库 \u002F 键值存储 \u002F 加密键值存储，数据自动按插件隔离 | `udhold.dbStorage.setItem('k', 'v')` |\n| `plugin` \u002F `router` \u002F `route` | 插件运行时：生命周期钩子、跨插件调用、tab 操作 | `udhold.router.push('files')` |\n| `files` | 文件资源管理：列举、新建、重命名、删除、批量复制、监听 | `udhold.files.list('D:\\\\')` |\n| `clipboard` | 剪贴板历史与读写 | `udhold.copyText('文本')` |\n| `ai` \u002F `ai.models` | 大模型推理（流式）、模型配置 | `udhold.ai({ model, messages })` |\n| `system` \u002F `shell` | 系统命令、通知、打开文件\u002F网址 | `udhold.shellOpenExternal(url)` |\n| `search` | 唤起全局搜索框 | `udhold.search.openWithKeyword('kw')` |\n| `setting` | 宿主外观与行为配置 | `udhold.setting.setTheme('dark')` |\n| `udbrowser` | 内嵌浏览器自动化（打开页面、点击、取数） | `udhold.udbrowser.create()` |\n| `service` \u002F `node` | 拉起并管理本地服务进程 | `udhold.service.spawn(cfg)` |\n| `user` \u002F `sync` \u002F `netdisk` | 登录态、WebDAV 同步、简盘 | `udhold.user.isLogin()` |\n\n除了直接调用，插件还能通过 `exports` + `registerTool` **对外暴露接口**供其他插件（以及宿主的 MCP 服务）调用，形成插件间的协作生态。\n\n## 权限模型\n\nUDhold 采用三层声明式权限：用到什么，就在 `plugin.json` 里声明什么，未声明的调用会被宿主权限网关拒绝（返回 `PERMISSION_DENIED`）。\n\n| 声明字段 | 管什么 | 示例 |\n|----------|--------|------|\n| `permissions[]` | 平台能力路径：敏感域（文件、剪贴板历史、AI、登录态等）必须声明；存储、路由等基础能力免声明 | `\"permissions\": [\"files.list\", \"ai.*\"]` |\n| `tauri[]` | 原生能力：对话框、通知、文件选择器等 | `\"tauri\": [\"dialog:default\"]` |\n| `plugins[]` | 跨插件调用白名单：要 `push` \u002F `invoke` 其他插件，先在这里登记目标插件名 | `\"plugins\": [\"files\"]` |\n\n通配符只支持后缀：`user.*` 放行整个 user 域，`ai.models.list` 精确到单个方法。不要声明 `\"*\"`（全量授权，市场审核时视为最高风险）。\n\n## 生命周期\n\n插件实例有 12 个生命周期钩子，覆盖从打开到销毁的完整过程：\n\n```ts\nudhold.plugin.onMounted((action) => {})     \u002F\u002F 页面就绪，action.code 区分被哪个 feature 唤起\nudhold.plugin.onActivated((p) => {})        \u002F\u002F tab 切入\nudhold.plugin.onDeactivated((p) => {})      \u002F\u002F tab 被切走\nudhold.plugin.onDetached((p) => {})         \u002F\u002F 分离成独立窗口\nudhold.plugin.onAttached((p) => {})         \u002F\u002F 从独立窗口回归面板\nudhold.plugin.onBeforeUnmount((p) => {})    \u002F\u002F 实例销毁前（唯一清理时机，宿主等 200ms）\nudhold.plugin.onShow((p) => {})             \u002F\u002F 获得焦点\nudhold.plugin.onBlur((p) => {})             \u002F\u002F 失去焦点\nudhold.plugin.onMinimized((p) => {})        \u002F\u002F 承载窗口最小化\nudhold.plugin.onRestored((p) => {})         \u002F\u002F 承载窗口还原\nudhold.plugin.onAppLaunched((p) => {})      \u002F\u002F 宿主启动（粘性）\nudhold.plugin.onAppBeforeQuit(() => {})     \u002F\u002F 宿主退出前\n```\n\n所有钩子返回取消函数，可多次注册叠加。`onMounted` 的 `action.from` 能区分唤起来源（主输入框 `main`、面板 `panel`、快捷键 `hotkey`、其他插件跳转 `redirect` 等）。\n\n## 分发方式\n\n- **插件市场**：在「插件开发者」里一键打包上传，审核通过后全平台用户可搜可装；已装用户打开插件时宿主自动检查更新。\n- **本地安装包**：打包为 `.zip`，可以发给朋友双击安装，或在插件中心手动安装，适合内部分发与灰度测试。\n\n## 开发前的准备\n\n| 需要 | 说明 |\n|------|------|\n| UDhold 桌面端 | 调试与打包都在宿主里完成，[下载](\u002F#download)安装 |\n| HTML \u002F CSS \u002F JavaScript 基础 | 插件本质是 Web 页面；推荐用 Vue 3（官方插件与组件库同栈，生态最顺） |\n| Node.js 20+ 与 pnpm | 工程型插件需要；纯静态插件可跳过 |\n| 一个想法 | 从自己每天会重复做的小事开始，最容易做出好插件 |\n\n准备好了？进入[快速上手](.\u002Fgetting-started)，20 分钟跑起你的第一个插件。\n",{"title":144,"description":1219},"H7GnVtVL_K4NXF4k5-BBR2ZYlX_4ffxMPRC7fr_l56Y",[1227,1229],{"title":128,"path":129,"stem":130,"description":1228,"icon":131},"了解 UDhold 如何收集、使用和保护您的个人信息与数据。",{"title":148,"path":149,"stem":150,"description":1230,"icon":34},"从环境准备到发布市场的完整实操：创建工程、运行调试、调用宿主能力、打包发布。",1793010250289]