[{"data":1,"prerenderedAt":4046},["ShallowReactive",2],{"navigation":3,"\u002Fdocs\u002Fdevelopment\u002Fquick-start\u002Fgetting-started":199,"\u002Fdocs\u002Fdevelopment\u002Fquick-start\u002Fgetting-started-surround":4041},[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":148,"body":201,"description":4034,"extension":4035,"meta":4036,"navigation":4037,"path":149,"rawbody":4038,"seo":4039,"stem":150,"__hash__":4040},"docs\u002F1.docs\u002F6.development\u002F1.quick-start\u002F2.getting-started.md",{"type":202,"value":203,"toc":4018},"minimark",[204,208,213,290,302,318,323,329,348,486,491,517,543,547,550,606,609,623,627,642,646,653,710,742,763,767,863,868,872,893,898,908,916,941,945,1469,1472,1717,1721,2141,2151,2202,2206,2706,2721,2725,2851,3325,3331,3335,3363,3366,3399,3403,3422,3693,3710,3828,3838,3888,3892,3951,3962,3966,3999,4002,4014],[205,206,207],"p",{},"这一章是一条完整的开发流水线：环境 → 创建工程 → 运行调试 → 调用能力 → 打包 → 发布。跟着做，20 分钟跑起你的第一个插件。",[209,210,212],"h2",{"id":211},"第-1-步准备环境","第 1 步：准备环境",[214,215,216,232],"table",{},[217,218,219],"thead",{},[220,221,222,226,229],"tr",{},[223,224,225],"th",{},"依赖",[223,227,228],{},"要求",[223,230,231],{},"用途",[233,234,235,252,263,279],"tbody",{},[220,236,237,241,249],{},[238,239,240],"td",{},"UDhold 桌面端",[238,242,243,244],{},"最新版，",[245,246,248],"a",{"href":247},"\u002F#download","下载安装",[238,250,251],{},"调试容器与打包发布都在宿主内完成",[220,253,254,257,260],{},[238,255,256],{},"Node.js",[238,258,259],{},"20 LTS 或更高",[238,261,262],{},"工程型插件的构建工具链",[220,264,265,268,276],{},[238,266,267],{},"pnpm",[238,269,270,271,275],{},"9+（",[272,273,274],"code",{},"npm i -g pnpm","）",[238,277,278],{},"官方插件工程的包管理器",[220,280,281,284,287],{},[238,282,283],{},"UDhold 账号",[238,285,286],{},"已登录",[238,288,289],{},"向导建项目、发布市场需要",[291,292,294],"callout",{"color":293,"icon":19},"primary",[205,295,296,297,301],{},"只做",[298,299,300],"strong",{},"免构建静态插件","（纯 HTML）或全程用「插件开发者」向导的话，Node.js 可以先不装——UDhold 会用内置运行时代劳。要做工程型插件（Vue\u002FReact），再按下面步骤装。",[205,303,304,305,309,310,313,314,317],{},"装好宿主后，呼出主搜索框（默认 ",[306,307,308],"kbd",{},"Alt","+",[306,311,312],{},"Z","）输入「",[298,315,316],{},"插件开发者","」回车——这是 UDhold 内置的插件开发工作台，接下来的创建、调试、发布都在它里面完成。",[319,320,322],"h3",{"id":321},"安装-nodejs-和-npm","安装 Node.js 和 npm",[205,324,325,328],{},[298,326,327],{},"npm 不用单独装","——它随 Node.js 安装包一起分发，装好 Node.js 就有了 npm。步骤：",[330,331,332,341],"ol",{},[333,334,335,336],"li",{},"打开 Node.js 官网下载页：",[245,337,338],{"href":338,"rel":339},"https:\u002F\u002Fnodejs.org\u002Fzh-cn\u002Fdownload",[340],"nofollow",[333,342,343,344,347],{},"选择 ",[298,345,346],{},"LTS 版本","（长期支持版，标绿的按钮），按操作系统下载安装包：",[349,350,351,389,439],"tabs",{},[352,353,355,366],"tabs-item",{"label":354},"Windows",[205,356,357,358,361,362,365],{},"下载 ",[272,359,360],{},"*.msi"," 安装包（如 ",[272,363,364],{},"node-v22.x-x64.msi","），双击安装：",[330,367,368,379,382],{},[333,369,370,371,374,375,378],{},"一路「下一步」，默认会勾选 ",[298,372,373],{},"Add to PATH","（自动配置环境变量）和 ",[298,376,377],{},"npm components","，保持默认即可",[333,380,381],{},"「Tools for Native Modules」页面可以不勾（插件开发用不到原生编译工具链）",[333,383,384,385,388],{},"装完",[298,386,387],{},"重开一个终端窗口","（让 PATH 生效）",[352,390,392,395,414],{"label":391},"macOS",[205,393,394],{},"两种方式任选：",[396,397,398,408],"ul",{},[333,399,400,403,404,407],{},[298,401,402],{},"官网安装包","：下载 ",[272,405,406],{},"*.pkg"," 双击，按提示安装",[333,409,410,413],{},[298,411,412],{},"Homebrew","（已装 brew 的话更省事）：",[415,416,421],"pre",{"className":417,"code":418,"language":419,"meta":420,"style":420},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","brew install node@22\n","bash","",[272,422,423],{"__ignoreMap":420},[424,425,428,432,436],"span",{"class":426,"line":427},"line",1,[424,429,431],{"class":430},"sBMFI","brew",[424,433,435],{"class":434},"sfazB"," install",[424,437,438],{"class":434}," node@22\n",[352,440,442,445],{"label":441},"Linux",[205,443,444],{},"推荐用 nvm 管理版本（免 sudo、可多版本切换）：",[415,446,448],{"className":417,"code":447,"language":419,"meta":420,"style":420},"curl -o- https:\u002F\u002Fraw.githubusercontent.com\u002Fnvm-sh\u002Fnvm\u002Fmaster\u002Finstall.sh | bash\n# 重开终端后：\nnvm install --lts\n",[272,449,450,468,475],{"__ignoreMap":420},[424,451,452,455,458,461,465],{"class":426,"line":427},[424,453,454],{"class":430},"curl",[424,456,457],{"class":434}," -o-",[424,459,460],{"class":434}," https:\u002F\u002Fraw.githubusercontent.com\u002Fnvm-sh\u002Fnvm\u002Fmaster\u002Finstall.sh",[424,462,464],{"class":463},"sMK4o"," |",[424,466,467],{"class":430}," bash\n",[424,469,471],{"class":426,"line":470},2,[424,472,474],{"class":473},"sHwdD","# 重开终端后：\n",[424,476,478,481,483],{"class":426,"line":477},3,[424,479,480],{"class":430},"nvm",[424,482,435],{"class":434},[424,484,485],{"class":434}," --lts\n",[330,487,488],{"start":477},[333,489,490],{},"验证安装——打开终端（Windows 用 PowerShell），能打印出版本号即成功：",[415,492,494],{"className":417,"code":493,"language":419,"meta":420,"style":420},"node -v   # v22.x.x 这样的输出（≥ v20 即满足要求）\nnpm -v    # 10.x 这样的输出\n",[272,495,496,507],{"__ignoreMap":420},[424,497,498,501,504],{"class":426,"line":427},[424,499,500],{"class":430},"node",[424,502,503],{"class":434}," -v",[424,505,506],{"class":473},"   # v22.x.x 这样的输出（≥ v20 即满足要求）\n",[424,508,509,512,514],{"class":426,"line":470},[424,510,511],{"class":430},"npm",[424,513,503],{"class":434},[424,515,516],{"class":473},"    # 10.x 这样的输出\n",[291,518,519,522],{"color":293,"icon":19},[205,520,521],{},"国内网络拉取 npm 包慢或超时，可切换国内镜像源（可选，仅影响下载速度）：",[415,523,525],{"className":417,"code":524,"language":419,"meta":420,"style":420},"npm config set registry https:\u002F\u002Fregistry.npmmirror.com\n",[272,526,527],{"__ignoreMap":420},[424,528,529,531,534,537,540],{"class":426,"line":427},[424,530,511],{"class":430},[424,532,533],{"class":434}," config",[424,535,536],{"class":434}," set",[424,538,539],{"class":434}," registry",[424,541,542],{"class":434}," https:\u002F\u002Fregistry.npmmirror.com\n",[319,544,546],{"id":545},"安装-pnpm","安装 pnpm",[205,548,549],{},"工程型插件（见下面「方式三」）用 pnpm 管理依赖，任选一种方式安装：",[349,551,552,571,591],{},[352,553,554],{"label":511},[415,555,557],{"className":417,"code":556,"language":419,"meta":420,"style":420},"npm install -g pnpm\n",[272,558,559],{"__ignoreMap":420},[424,560,561,563,565,568],{"class":426,"line":427},[424,562,511],{"class":430},[424,564,435],{"class":434},[424,566,567],{"class":434}," -g",[424,569,570],{"class":434}," pnpm\n",[352,572,574,577],{"label":573},"corepack",[205,575,576],{},"Node.js 自带 corepack（v16.13+），启用即得 pnpm：",[415,578,580],{"className":417,"code":579,"language":419,"meta":420,"style":420},"corepack enable pnpm\n",[272,581,582],{"__ignoreMap":420},[424,583,584,586,589],{"class":426,"line":427},[424,585,573],{"class":430},[424,587,588],{"class":434}," enable",[424,590,570],{"class":434},[352,592,593],{"label":412},[415,594,596],{"className":417,"code":595,"language":419,"meta":420,"style":420},"brew install pnpm\n",[272,597,598],{"__ignoreMap":420},[424,599,600,602,604],{"class":426,"line":427},[424,601,431],{"class":430},[424,603,435],{"class":434},[424,605,570],{"class":434},[205,607,608],{},"验证：",[415,610,612],{"className":417,"code":611,"language":419,"meta":420,"style":420},"pnpm -v   # 9.x 或更高\n",[272,613,614],{"__ignoreMap":420},[424,615,616,618,620],{"class":426,"line":427},[424,617,267],{"class":430},[424,619,503],{"class":434},[424,621,622],{"class":473},"   # 9.x 或更高\n",[209,624,626],{"id":625},"第-2-步创建工程","第 2 步：创建工程",[205,628,629,630,633,634,637,638,641],{},"三种方式任选：",[298,631,632],{},"CLI 脚手架一键创建","最快；",[298,635,636],{},"向导创建","适合快速起步和纯服务\u002F静态插件；",[298,639,640],{},"手动搭建","适合理解每个文件、向官方插件仓库贡献插件。",[319,643,645],{"id":644},"方式一cli-脚手架一键创建推荐","方式一：CLI 脚手架一键创建（推荐）",[205,647,648,649,652],{},"装好 ",[245,650,256],{"href":651},"#%E5%AE%89%E8%A3%85-nodejs-%E5%92%8C-npm"," 后，用官方脚手架交互式生成完整插件框架：",[349,654,655,685],{},[352,656,657],{"label":267},[415,658,660],{"className":417,"code":659,"language":419,"meta":420,"style":420},"pnpm add -g @udhold\u002Fplugin-cli\nudhold create my-plugin\n",[272,661,662,674],{"__ignoreMap":420},[424,663,664,666,669,671],{"class":426,"line":427},[424,665,267],{"class":430},[424,667,668],{"class":434}," add",[424,670,567],{"class":434},[424,672,673],{"class":434}," @udhold\u002Fplugin-cli\n",[424,675,676,679,682],{"class":426,"line":470},[424,677,678],{"class":430},"udhold",[424,680,681],{"class":434}," create",[424,683,684],{"class":434}," my-plugin\n",[352,686,687],{"label":511},[415,688,690],{"className":417,"code":689,"language":419,"meta":420,"style":420},"npm install -g @udhold\u002Fplugin-cli\nudhold create my-plugin\n",[272,691,692,702],{"__ignoreMap":420},[424,693,694,696,698,700],{"class":426,"line":427},[424,695,511],{"class":430},[424,697,435],{"class":434},[424,699,567],{"class":434},[424,701,673],{"class":434},[424,703,704,706,708],{"class":426,"line":470},[424,705,678],{"class":430},[424,707,681],{"class":434},[424,709,684],{"class":434},[205,711,712,713,716,717,720,721,724,725,728,729,733,734,737,738,741],{},"按提示完成四步：项目名 → 选模板（",[298,714,715],{},"Vue 3 + 设计系统","（推荐）\u002F ",[298,718,719],{},"React + Vite"," \u002F ",[298,722,723],{},"免构建静态 HTML","）→ 填插件信息（ID、标题、描述、作者）→ 自动生成工程。生成后进入工程目录 ",[272,726,727],{},"pnpm install && pnpm dev","（静态模板免安装），直接跳到",[245,730,732],{"href":731},"#%E7%AC%AC-3-%E6%AD%A5%E8%BF%90%E8%A1%8C%E8%B0%83%E8%AF%95","第 3 步","调试；dev 端口等细节在生成工程的 ",[272,735,736],{},"plugin.json"," 与 ",[272,739,740],{},"vite.config"," 中调整。",[291,743,744],{"color":293,"icon":19},[205,745,746,747,750,751,754,755,758,759,762],{},"脚手架生成的工程是",[298,748,749],{},"独立目录","，不依赖官方仓库（",[272,752,753],{},"@udhold\u002Fudhold-ui"," 等依赖来自 npm）。想向官方插件仓库贡献插件，把生成目录挪进 ",[272,756,757],{},"udhold-plugin\u002Fplugins\u002F"," 下并把依赖改成 ",[272,760,761],{},"workspace:*"," 即可。",[319,764,766],{"id":765},"方式二向导创建推荐起步","方式二：向导创建（推荐起步）",[330,768,769,776,779,849,856],{},[333,770,771,772,775],{},"在「插件开发者」的开发页点「",[298,773,774],{},"新建项目","」。",[333,777,778],{},"填写插件标题、描述、简介，选择工程存放目录。",[333,780,781,782],{},"选择插件形态，向导会生成对应的最小工程：",[214,783,784,794],{},[217,785,786],{},[220,787,788,791],{},[223,789,790],{},"形态",[223,792,793],{},"生成内容",[233,795,796,810,825,833,841],{},[220,797,798,801],{},[238,799,800],{},"静态 HTML",[238,802,803,806,807,809],{},[272,804,805],{},"index.html"," + ",[272,808,736],{},"，免构建、零依赖",[220,811,812,815],{},[238,813,814],{},"页面 + Node 服务",[238,816,817,818,821,822,275],{},"页面 + ",[272,819,820],{},"server.js"," 后端（声明式 ",[272,823,824],{},"services",[220,826,827,830],{},[238,828,829],{},"页面 + Python 服务",[238,831,832],{},"页面 + Python 后端",[220,834,835,838],{},[238,836,837],{},"纯 Node 服务",[238,839,840],{},"只有后端，无界面（纯服务插件）",[220,842,843,846],{},[238,844,845],{},"纯 Python 服务",[238,847,848],{},"同上",[333,850,851,852,855],{},"需要登录：向导会先在市场登记插件条目（拿到全局唯一的插件 ",[272,853,854],{},"name","），再落盘工程文件。",[333,857,858,859,862],{},"完成后工程自动出现在工作台列表里，点「",[298,860,861],{},"运行调试","」即可看到插件跑起来。",[291,864,865],{"color":293,"icon":19},[205,866,867],{},"向导生成的工程是独立目录，不依赖任何仓库。形态选错了不要紧——工程文件都是普通文件，随时可以改造成工程化开发。",[319,869,871],{"id":870},"方式三手动搭建vue-3-官方设计系统","方式三：手动搭建（Vue 3 + 官方设计系统）",[205,873,874,875,877,878,881,882,886,887,889,890,892],{},"官方插件（计算器、JSON Tools……）都在官方插件工程仓库里开发：仓库内置 ",[272,876,753],{}," 组件库与 ",[272,879,880],{},"@udhold\u002Fudhold-api-types"," 类型包（见",[245,883,885],{"href":884},"\u002Fdevelopers","开发者资源","），把你的插件放在 ",[272,888,757],{}," 下即可直接以 ",[272,891,761],{}," 引用它们。",[894,895,897],"h4",{"id":896},"_21-目录结构","2.1 目录结构",[205,899,900,901,903,904,907],{},"在 ",[272,902,757],{}," 下新建 ",[272,905,906],{},"my-plugin\u002F","：",[415,909,914],{"className":910,"code":912,"language":913},[911],"language-text","my-plugin\u002F\n├── src\u002F\n│   ├── main.ts          # 入口\n│   ├── App.vue          # 根组件\n│   └── ...              # 你的页面与组件\n├── dist\u002F                # 构建产物（pnpm build 生成）\n├── index.html           # Vite HTML 模板\n├── logo.png             # 插件图标\n├── plugin.json          # 插件清单（放插件根目录，与官方插件一致）\n├── package.json\n├── tsconfig.json\n├── uno.config.ts\n└── vite.config.ts\n","text",[272,915,912],{"__ignoreMap":420},[291,917,918],{"color":293,"icon":19},[205,919,920,922,923,926,927,930,931,934,935,937,938,940],{},[272,921,736],{}," 和 ",[272,924,925],{},"logo.png"," 放在",[298,928,929],{},"插件根目录","，不要放进 ",[272,932,933],{},"public\u002F","。打包时打包器会把 ",[272,936,736],{}," 原文和 logo 固定收进安装包根目录，不依赖构建产物；放进 ",[272,939,933],{}," 只会让构建在 dist 里多出一份冗余副本。",[894,942,944],{"id":943},"_22-pluginjson","2.2 plugin.json",[415,946,950],{"className":947,"code":948,"language":949,"meta":420,"style":420},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","{\n  \"name\": \"my-plugin\",\n  \"title\": \"我的插件\",\n  \"description\": \"一句话描述插件做什么\",\n  \"author\": \"你的名字\",\n  \"version\": \"1.0.0\",\n  \"logo\": \"logo.png\",\n  \"loading\": { \"variant\": \"Drive\", \"label\": \"加载中\" },\n  \"permissions\": [],\n  \"pluginSetting\": {\n    \"slot\": \"workspace\",\n    \"Detach\": true,\n    \"Menu\": true,\n    \"DesktopShortcut\": true\n  },\n  \"development\": { \"main\": \"http:\u002F\u002Flocalhost:5261\" },\n  \"features\": [\n    {\n      \"code\": \"main\",\n      \"explain\": \"我的插件主功能\",\n      \"icon\": \"logo.png\",\n      \"cmds\": [\"我的插件\", \"mypl\"]\n    }\n  ],\n  \"dist\": \"dist\u002Findex.html\",\n  \"build\": [\"dist\"],\n  \"readme\": \"这里是插件详情页展示的完整介绍，支持 Markdown。\"\n}\n","json",[272,951,952,957,982,1002,1023,1044,1065,1085,1138,1153,1168,1190,1205,1219,1234,1240,1272,1287,1293,1313,1334,1354,1387,1393,1399,1420,1443,1463],{"__ignoreMap":420},[424,953,954],{"class":426,"line":427},[424,955,956],{"class":463},"{\n",[424,958,959,962,965,968,971,974,977,979],{"class":426,"line":470},[424,960,961],{"class":463},"  \"",[424,963,854],{"class":964},"spNyl",[424,966,967],{"class":463},"\"",[424,969,970],{"class":463},":",[424,972,973],{"class":463}," \"",[424,975,976],{"class":434},"my-plugin",[424,978,967],{"class":463},[424,980,981],{"class":463},",\n",[424,983,984,986,989,991,993,995,998,1000],{"class":426,"line":477},[424,985,961],{"class":463},[424,987,988],{"class":964},"title",[424,990,967],{"class":463},[424,992,970],{"class":463},[424,994,973],{"class":463},[424,996,997],{"class":434},"我的插件",[424,999,967],{"class":463},[424,1001,981],{"class":463},[424,1003,1005,1007,1010,1012,1014,1016,1019,1021],{"class":426,"line":1004},4,[424,1006,961],{"class":463},[424,1008,1009],{"class":964},"description",[424,1011,967],{"class":463},[424,1013,970],{"class":463},[424,1015,973],{"class":463},[424,1017,1018],{"class":434},"一句话描述插件做什么",[424,1020,967],{"class":463},[424,1022,981],{"class":463},[424,1024,1026,1028,1031,1033,1035,1037,1040,1042],{"class":426,"line":1025},5,[424,1027,961],{"class":463},[424,1029,1030],{"class":964},"author",[424,1032,967],{"class":463},[424,1034,970],{"class":463},[424,1036,973],{"class":463},[424,1038,1039],{"class":434},"你的名字",[424,1041,967],{"class":463},[424,1043,981],{"class":463},[424,1045,1047,1049,1052,1054,1056,1058,1061,1063],{"class":426,"line":1046},6,[424,1048,961],{"class":463},[424,1050,1051],{"class":964},"version",[424,1053,967],{"class":463},[424,1055,970],{"class":463},[424,1057,973],{"class":463},[424,1059,1060],{"class":434},"1.0.0",[424,1062,967],{"class":463},[424,1064,981],{"class":463},[424,1066,1068,1070,1073,1075,1077,1079,1081,1083],{"class":426,"line":1067},7,[424,1069,961],{"class":463},[424,1071,1072],{"class":964},"logo",[424,1074,967],{"class":463},[424,1076,970],{"class":463},[424,1078,973],{"class":463},[424,1080,925],{"class":434},[424,1082,967],{"class":463},[424,1084,981],{"class":463},[424,1086,1088,1090,1093,1095,1097,1100,1102,1105,1107,1109,1111,1114,1116,1119,1121,1124,1126,1128,1130,1133,1135],{"class":426,"line":1087},8,[424,1089,961],{"class":463},[424,1091,1092],{"class":964},"loading",[424,1094,967],{"class":463},[424,1096,970],{"class":463},[424,1098,1099],{"class":463}," {",[424,1101,973],{"class":463},[424,1103,1104],{"class":430},"variant",[424,1106,967],{"class":463},[424,1108,970],{"class":463},[424,1110,973],{"class":463},[424,1112,1113],{"class":434},"Drive",[424,1115,967],{"class":463},[424,1117,1118],{"class":463},",",[424,1120,973],{"class":463},[424,1122,1123],{"class":430},"label",[424,1125,967],{"class":463},[424,1127,970],{"class":463},[424,1129,973],{"class":463},[424,1131,1132],{"class":434},"加载中",[424,1134,967],{"class":463},[424,1136,1137],{"class":463}," },\n",[424,1139,1141,1143,1146,1148,1150],{"class":426,"line":1140},9,[424,1142,961],{"class":463},[424,1144,1145],{"class":964},"permissions",[424,1147,967],{"class":463},[424,1149,970],{"class":463},[424,1151,1152],{"class":463}," [],\n",[424,1154,1156,1158,1161,1163,1165],{"class":426,"line":1155},10,[424,1157,961],{"class":463},[424,1159,1160],{"class":964},"pluginSetting",[424,1162,967],{"class":463},[424,1164,970],{"class":463},[424,1166,1167],{"class":463}," {\n",[424,1169,1171,1174,1177,1179,1181,1183,1186,1188],{"class":426,"line":1170},11,[424,1172,1173],{"class":463},"    \"",[424,1175,1176],{"class":430},"slot",[424,1178,967],{"class":463},[424,1180,970],{"class":463},[424,1182,973],{"class":463},[424,1184,1185],{"class":434},"workspace",[424,1187,967],{"class":463},[424,1189,981],{"class":463},[424,1191,1193,1195,1198,1200,1202],{"class":426,"line":1192},12,[424,1194,1173],{"class":463},[424,1196,1197],{"class":430},"Detach",[424,1199,967],{"class":463},[424,1201,970],{"class":463},[424,1203,1204],{"class":463}," true,\n",[424,1206,1208,1210,1213,1215,1217],{"class":426,"line":1207},13,[424,1209,1173],{"class":463},[424,1211,1212],{"class":430},"Menu",[424,1214,967],{"class":463},[424,1216,970],{"class":463},[424,1218,1204],{"class":463},[424,1220,1222,1224,1227,1229,1231],{"class":426,"line":1221},14,[424,1223,1173],{"class":463},[424,1225,1226],{"class":430},"DesktopShortcut",[424,1228,967],{"class":463},[424,1230,970],{"class":463},[424,1232,1233],{"class":463}," true\n",[424,1235,1237],{"class":426,"line":1236},15,[424,1238,1239],{"class":463},"  },\n",[424,1241,1243,1245,1248,1250,1252,1254,1256,1259,1261,1263,1265,1268,1270],{"class":426,"line":1242},16,[424,1244,961],{"class":463},[424,1246,1247],{"class":964},"development",[424,1249,967],{"class":463},[424,1251,970],{"class":463},[424,1253,1099],{"class":463},[424,1255,973],{"class":463},[424,1257,1258],{"class":430},"main",[424,1260,967],{"class":463},[424,1262,970],{"class":463},[424,1264,973],{"class":463},[424,1266,1267],{"class":434},"http:\u002F\u002Flocalhost:5261",[424,1269,967],{"class":463},[424,1271,1137],{"class":463},[424,1273,1275,1277,1280,1282,1284],{"class":426,"line":1274},17,[424,1276,961],{"class":463},[424,1278,1279],{"class":964},"features",[424,1281,967],{"class":463},[424,1283,970],{"class":463},[424,1285,1286],{"class":463}," [\n",[424,1288,1290],{"class":426,"line":1289},18,[424,1291,1292],{"class":463},"    {\n",[424,1294,1296,1299,1301,1303,1305,1307,1309,1311],{"class":426,"line":1295},19,[424,1297,1298],{"class":463},"      \"",[424,1300,272],{"class":430},[424,1302,967],{"class":463},[424,1304,970],{"class":463},[424,1306,973],{"class":463},[424,1308,1258],{"class":434},[424,1310,967],{"class":463},[424,1312,981],{"class":463},[424,1314,1316,1318,1321,1323,1325,1327,1330,1332],{"class":426,"line":1315},20,[424,1317,1298],{"class":463},[424,1319,1320],{"class":430},"explain",[424,1322,967],{"class":463},[424,1324,970],{"class":463},[424,1326,973],{"class":463},[424,1328,1329],{"class":434},"我的插件主功能",[424,1331,967],{"class":463},[424,1333,981],{"class":463},[424,1335,1337,1339,1342,1344,1346,1348,1350,1352],{"class":426,"line":1336},21,[424,1338,1298],{"class":463},[424,1340,1341],{"class":430},"icon",[424,1343,967],{"class":463},[424,1345,970],{"class":463},[424,1347,973],{"class":463},[424,1349,925],{"class":434},[424,1351,967],{"class":463},[424,1353,981],{"class":463},[424,1355,1357,1359,1362,1364,1366,1369,1371,1373,1375,1377,1379,1382,1384],{"class":426,"line":1356},22,[424,1358,1298],{"class":463},[424,1360,1361],{"class":430},"cmds",[424,1363,967],{"class":463},[424,1365,970],{"class":463},[424,1367,1368],{"class":463}," [",[424,1370,967],{"class":463},[424,1372,997],{"class":434},[424,1374,967],{"class":463},[424,1376,1118],{"class":463},[424,1378,973],{"class":463},[424,1380,1381],{"class":434},"mypl",[424,1383,967],{"class":463},[424,1385,1386],{"class":463},"]\n",[424,1388,1390],{"class":426,"line":1389},23,[424,1391,1392],{"class":463},"    }\n",[424,1394,1396],{"class":426,"line":1395},24,[424,1397,1398],{"class":463},"  ],\n",[424,1400,1402,1404,1407,1409,1411,1413,1416,1418],{"class":426,"line":1401},25,[424,1403,961],{"class":463},[424,1405,1406],{"class":964},"dist",[424,1408,967],{"class":463},[424,1410,970],{"class":463},[424,1412,973],{"class":463},[424,1414,1415],{"class":434},"dist\u002Findex.html",[424,1417,967],{"class":463},[424,1419,981],{"class":463},[424,1421,1423,1425,1428,1430,1432,1434,1436,1438,1440],{"class":426,"line":1422},26,[424,1424,961],{"class":463},[424,1426,1427],{"class":964},"build",[424,1429,967],{"class":463},[424,1431,970],{"class":463},[424,1433,1368],{"class":463},[424,1435,967],{"class":463},[424,1437,1406],{"class":434},[424,1439,967],{"class":463},[424,1441,1442],{"class":463},"],\n",[424,1444,1446,1448,1451,1453,1455,1457,1460],{"class":426,"line":1445},27,[424,1447,961],{"class":463},[424,1449,1450],{"class":964},"readme",[424,1452,967],{"class":463},[424,1454,970],{"class":463},[424,1456,973],{"class":463},[424,1458,1459],{"class":434},"这里是插件详情页展示的完整介绍，支持 Markdown。",[424,1461,1462],{"class":463},"\"\n",[424,1464,1466],{"class":426,"line":1465},28,[424,1467,1468],{"class":463},"}\n",[205,1470,1471],{},"常用字段速查（完整契约见类型包内的 schema）：",[214,1473,1474,1484],{},[217,1475,1476],{},[220,1477,1478,1481],{},[223,1479,1480],{},"字段",[223,1482,1483],{},"说明",[233,1485,1486,1499,1510,1527,1537,1556,1569,1582,1595,1605,1631,1648,1661,1671,1681,1694,1707],{},[220,1487,1488,1496],{},[238,1489,1490,720,1492,720,1494],{},[272,1491,854],{},[272,1493,988],{},[272,1495,1051],{},[238,1497,1498],{},"全局唯一标识 \u002F 显示名 \u002F semver 版本（更新的唯一判定来源）",[220,1500,1501,1505],{},[238,1502,1503],{},[272,1504,1406],{},[238,1506,1507,1508],{},"构建产物入口；免构建插件直接写 ",[272,1509,805],{},[220,1511,1512,1516],{},[238,1513,1514],{},[272,1515,1427],{},[238,1517,1518,1519,1522,1523,1526],{},"打包收录清单：",[272,1520,1521],{},"[\"dist\"]"," 只收 dist 目录；",[272,1524,1525],{},"[\".\"]"," 收整个插件根（自动排除 node_modules 等）",[220,1528,1529,1534],{},[238,1530,1531],{},[272,1532,1533],{},"development.main",[238,1535,1536],{},"开发态 dev server 地址，调试时宿主直连它（仅允许 localhost）",[220,1538,1539,1544],{},[238,1540,1541],{},[272,1542,1543],{},"pluginSetting.slot",[238,1545,1546,1547,1549,1550,720,1553],{},"面板槽位：",[272,1548,1185],{},"（工作区）\u002F ",[272,1551,1552],{},"leftPanel",[272,1554,1555],{},"rightPanel",[220,1557,1558,1563],{},[238,1559,1560],{},[272,1561,1562],{},"pluginSetting.Detach",[238,1564,1565,1568],{},[272,1566,1567],{},"true"," 时打开即分离为独立窗口",[220,1570,1571,1579],{},[238,1572,1573,720,1576],{},[272,1574,1575],{},"pluginSetting.Menu",[272,1577,1578],{},"MenuBottom",[238,1580,1581],{},"进活动栏顶部 \u002F 底部菜单",[220,1583,1584,1589],{},[238,1585,1586],{},[272,1587,1588],{},"pluginSetting.SubSearch",[238,1590,1591,1592,275],{},"分离窗口标题栏带搜索框（配合 ",[272,1593,1594],{},"SubSearchPlaceholder",[220,1596,1597,1602],{},[238,1598,1599],{},[272,1600,1601],{},"features[].code",[238,1603,1604],{},"功能唯一标识，打开时作为启动参数回传给插件",[220,1606,1607,1612],{},[238,1608,1609],{},[272,1610,1611],{},"features[].cmds",[238,1613,1614,1615,720,1618,720,1621,720,1624,720,1627,1630],{},"主搜索框关键词：字符串直接匹配（支持拼音、首字母）；对象可声明 ",[272,1616,1617],{},"regex",[272,1619,1620],{},"over",[272,1622,1623],{},"img",[272,1625,1626],{},"files",[272,1628,1629],{},"window"," 五种匹配规则",[220,1632,1633,1637],{},[238,1634,1635],{},[272,1636,1145],{},[238,1638,1639,1640,1643,1644,1647],{},"平台能力路径，如 ",[272,1641,1642],{},"[\"files.list\", \"ai.*\"]","，见",[245,1645,144],{"href":1646},".\u002Fintroduction","的权限模型",[220,1649,1650,1655],{},[238,1651,1652],{},[272,1653,1654],{},"tauri",[238,1656,1657,1658],{},"原生能力标识，如 ",[272,1659,1660],{},"[\"dialog:default\", \"notification:default\"]",[220,1662,1663,1668],{},[238,1664,1665],{},[272,1666,1667],{},"plugins",[238,1669,1670],{},"跨插件调用白名单",[220,1672,1673,1678],{},[238,1674,1675],{},[272,1676,1677],{},"services[]",[238,1679,1680],{},"声明式服务进程（node \u002F python \u002F exe），配 `startup: \"open\"",[220,1682,1683,1688],{},[238,1684,1685],{},[272,1686,1687],{},"startup",[238,1689,1690,1693],{},[272,1691,1692],{},"\"background\""," 随宿主后台启动",[220,1695,1696,1704],{},[238,1697,1698,720,1701],{},[272,1699,1700],{},"exports",[272,1702,1703],{},"events",[238,1705,1706],{},"对外暴露接口与事件的声明（同时会作为 MCP 工具暴露）",[220,1708,1709,1714],{},[238,1710,1711],{},[272,1712,1713],{},"contextMenu[]",[238,1715,1716],{},"Windows 资源管理器右键菜单注册",[894,1718,1720],{"id":1719},"_23-packagejson","2.3 package.json",[415,1722,1724],{"className":947,"code":1723,"language":949,"meta":420,"style":420},"{\n  \"name\": \"@udhold-plugin\u002Fmy-plugin\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"typecheck\": \"vue-tsc --noEmit\"\n  },\n  \"dependencies\": {\n    \"vue\": \"^3.5.13\",\n    \"@udhold\u002Fudhold-ui\": \"workspace:*\",\n    \"@udhold\u002Fudhold-api-types\": \"workspace:*\"\n  },\n  \"devDependencies\": {\n    \"@iconify\u002Futils\": \"^3.1.0\",\n    \"@unocss\u002Fpreset-attributify\": \"^66.6.6\",\n    \"@unocss\u002Fpreset-icons\": \"^66.6.6\",\n    \"@unocss\u002Ftransformer-directives\": \"^66.6.6\",\n    \"@vitejs\u002Fplugin-vue\": \"^5.2.1\",\n    \"typescript\": \"~5.6.2\",\n    \"unocss\": \"^66.6.6\",\n    \"vite\": \"^6.0.3\",\n    \"vue-tsc\": \"^2.1.10\"\n  }\n}\n",[272,1725,1726,1730,1749,1762,1780,1800,1813,1833,1852,1870,1874,1887,1907,1925,1941,1945,1958,1978,1998,2017,2036,2056,2076,2095,2114,2132,2137],{"__ignoreMap":420},[424,1727,1728],{"class":426,"line":427},[424,1729,956],{"class":463},[424,1731,1732,1734,1736,1738,1740,1742,1745,1747],{"class":426,"line":470},[424,1733,961],{"class":463},[424,1735,854],{"class":964},[424,1737,967],{"class":463},[424,1739,970],{"class":463},[424,1741,973],{"class":463},[424,1743,1744],{"class":434},"@udhold-plugin\u002Fmy-plugin",[424,1746,967],{"class":463},[424,1748,981],{"class":463},[424,1750,1751,1753,1756,1758,1760],{"class":426,"line":477},[424,1752,961],{"class":463},[424,1754,1755],{"class":964},"private",[424,1757,967],{"class":463},[424,1759,970],{"class":463},[424,1761,1204],{"class":463},[424,1763,1764,1766,1768,1770,1772,1774,1776,1778],{"class":426,"line":1004},[424,1765,961],{"class":463},[424,1767,1051],{"class":964},[424,1769,967],{"class":463},[424,1771,970],{"class":463},[424,1773,973],{"class":463},[424,1775,1060],{"class":434},[424,1777,967],{"class":463},[424,1779,981],{"class":463},[424,1781,1782,1784,1787,1789,1791,1793,1796,1798],{"class":426,"line":1025},[424,1783,961],{"class":463},[424,1785,1786],{"class":964},"type",[424,1788,967],{"class":463},[424,1790,970],{"class":463},[424,1792,973],{"class":463},[424,1794,1795],{"class":434},"module",[424,1797,967],{"class":463},[424,1799,981],{"class":463},[424,1801,1802,1804,1807,1809,1811],{"class":426,"line":1046},[424,1803,961],{"class":463},[424,1805,1806],{"class":964},"scripts",[424,1808,967],{"class":463},[424,1810,970],{"class":463},[424,1812,1167],{"class":463},[424,1814,1815,1817,1820,1822,1824,1826,1829,1831],{"class":426,"line":1067},[424,1816,1173],{"class":463},[424,1818,1819],{"class":430},"dev",[424,1821,967],{"class":463},[424,1823,970],{"class":463},[424,1825,973],{"class":463},[424,1827,1828],{"class":434},"vite",[424,1830,967],{"class":463},[424,1832,981],{"class":463},[424,1834,1835,1837,1839,1841,1843,1845,1848,1850],{"class":426,"line":1087},[424,1836,1173],{"class":463},[424,1838,1427],{"class":430},[424,1840,967],{"class":463},[424,1842,970],{"class":463},[424,1844,973],{"class":463},[424,1846,1847],{"class":434},"vite build",[424,1849,967],{"class":463},[424,1851,981],{"class":463},[424,1853,1854,1856,1859,1861,1863,1865,1868],{"class":426,"line":1140},[424,1855,1173],{"class":463},[424,1857,1858],{"class":430},"typecheck",[424,1860,967],{"class":463},[424,1862,970],{"class":463},[424,1864,973],{"class":463},[424,1866,1867],{"class":434},"vue-tsc --noEmit",[424,1869,1462],{"class":463},[424,1871,1872],{"class":426,"line":1155},[424,1873,1239],{"class":463},[424,1875,1876,1878,1881,1883,1885],{"class":426,"line":1170},[424,1877,961],{"class":463},[424,1879,1880],{"class":964},"dependencies",[424,1882,967],{"class":463},[424,1884,970],{"class":463},[424,1886,1167],{"class":463},[424,1888,1889,1891,1894,1896,1898,1900,1903,1905],{"class":426,"line":1192},[424,1890,1173],{"class":463},[424,1892,1893],{"class":430},"vue",[424,1895,967],{"class":463},[424,1897,970],{"class":463},[424,1899,973],{"class":463},[424,1901,1902],{"class":434},"^3.5.13",[424,1904,967],{"class":463},[424,1906,981],{"class":463},[424,1908,1909,1911,1913,1915,1917,1919,1921,1923],{"class":426,"line":1207},[424,1910,1173],{"class":463},[424,1912,753],{"class":430},[424,1914,967],{"class":463},[424,1916,970],{"class":463},[424,1918,973],{"class":463},[424,1920,761],{"class":434},[424,1922,967],{"class":463},[424,1924,981],{"class":463},[424,1926,1927,1929,1931,1933,1935,1937,1939],{"class":426,"line":1221},[424,1928,1173],{"class":463},[424,1930,880],{"class":430},[424,1932,967],{"class":463},[424,1934,970],{"class":463},[424,1936,973],{"class":463},[424,1938,761],{"class":434},[424,1940,1462],{"class":463},[424,1942,1943],{"class":426,"line":1236},[424,1944,1239],{"class":463},[424,1946,1947,1949,1952,1954,1956],{"class":426,"line":1242},[424,1948,961],{"class":463},[424,1950,1951],{"class":964},"devDependencies",[424,1953,967],{"class":463},[424,1955,970],{"class":463},[424,1957,1167],{"class":463},[424,1959,1960,1962,1965,1967,1969,1971,1974,1976],{"class":426,"line":1274},[424,1961,1173],{"class":463},[424,1963,1964],{"class":430},"@iconify\u002Futils",[424,1966,967],{"class":463},[424,1968,970],{"class":463},[424,1970,973],{"class":463},[424,1972,1973],{"class":434},"^3.1.0",[424,1975,967],{"class":463},[424,1977,981],{"class":463},[424,1979,1980,1982,1985,1987,1989,1991,1994,1996],{"class":426,"line":1289},[424,1981,1173],{"class":463},[424,1983,1984],{"class":430},"@unocss\u002Fpreset-attributify",[424,1986,967],{"class":463},[424,1988,970],{"class":463},[424,1990,973],{"class":463},[424,1992,1993],{"class":434},"^66.6.6",[424,1995,967],{"class":463},[424,1997,981],{"class":463},[424,1999,2000,2002,2005,2007,2009,2011,2013,2015],{"class":426,"line":1295},[424,2001,1173],{"class":463},[424,2003,2004],{"class":430},"@unocss\u002Fpreset-icons",[424,2006,967],{"class":463},[424,2008,970],{"class":463},[424,2010,973],{"class":463},[424,2012,1993],{"class":434},[424,2014,967],{"class":463},[424,2016,981],{"class":463},[424,2018,2019,2021,2024,2026,2028,2030,2032,2034],{"class":426,"line":1315},[424,2020,1173],{"class":463},[424,2022,2023],{"class":430},"@unocss\u002Ftransformer-directives",[424,2025,967],{"class":463},[424,2027,970],{"class":463},[424,2029,973],{"class":463},[424,2031,1993],{"class":434},[424,2033,967],{"class":463},[424,2035,981],{"class":463},[424,2037,2038,2040,2043,2045,2047,2049,2052,2054],{"class":426,"line":1336},[424,2039,1173],{"class":463},[424,2041,2042],{"class":430},"@vitejs\u002Fplugin-vue",[424,2044,967],{"class":463},[424,2046,970],{"class":463},[424,2048,973],{"class":463},[424,2050,2051],{"class":434},"^5.2.1",[424,2053,967],{"class":463},[424,2055,981],{"class":463},[424,2057,2058,2060,2063,2065,2067,2069,2072,2074],{"class":426,"line":1356},[424,2059,1173],{"class":463},[424,2061,2062],{"class":430},"typescript",[424,2064,967],{"class":463},[424,2066,970],{"class":463},[424,2068,973],{"class":463},[424,2070,2071],{"class":434},"~5.6.2",[424,2073,967],{"class":463},[424,2075,981],{"class":463},[424,2077,2078,2080,2083,2085,2087,2089,2091,2093],{"class":426,"line":1389},[424,2079,1173],{"class":463},[424,2081,2082],{"class":430},"unocss",[424,2084,967],{"class":463},[424,2086,970],{"class":463},[424,2088,973],{"class":463},[424,2090,1993],{"class":434},[424,2092,967],{"class":463},[424,2094,981],{"class":463},[424,2096,2097,2099,2101,2103,2105,2107,2110,2112],{"class":426,"line":1395},[424,2098,1173],{"class":463},[424,2100,1828],{"class":430},[424,2102,967],{"class":463},[424,2104,970],{"class":463},[424,2106,973],{"class":463},[424,2108,2109],{"class":434},"^6.0.3",[424,2111,967],{"class":463},[424,2113,981],{"class":463},[424,2115,2116,2118,2121,2123,2125,2127,2130],{"class":426,"line":1401},[424,2117,1173],{"class":463},[424,2119,2120],{"class":430},"vue-tsc",[424,2122,967],{"class":463},[424,2124,970],{"class":463},[424,2126,973],{"class":463},[424,2128,2129],{"class":434},"^2.1.10",[424,2131,1462],{"class":463},[424,2133,2134],{"class":426,"line":1422},[424,2135,2136],{"class":463},"  }\n",[424,2138,2139],{"class":426,"line":1445},[424,2140,1468],{"class":463},[205,2142,2143,2146,2147,2150],{},[272,2144,2145],{},"tsconfig.json"," 里加上类型包，",[272,2148,2149],{},"window.udhold.*"," 就有完整代码提示：",[415,2152,2154],{"className":947,"code":2153,"language":949,"meta":420,"style":420},"{\n  \"compilerOptions\": {\n    \"types\": [\"@udhold\u002Fudhold-api-types\"]\n  }\n}\n",[272,2155,2156,2160,2173,2194,2198],{"__ignoreMap":420},[424,2157,2158],{"class":426,"line":427},[424,2159,956],{"class":463},[424,2161,2162,2164,2167,2169,2171],{"class":426,"line":470},[424,2163,961],{"class":463},[424,2165,2166],{"class":964},"compilerOptions",[424,2168,967],{"class":463},[424,2170,970],{"class":463},[424,2172,1167],{"class":463},[424,2174,2175,2177,2180,2182,2184,2186,2188,2190,2192],{"class":426,"line":477},[424,2176,1173],{"class":463},[424,2178,2179],{"class":430},"types",[424,2181,967],{"class":463},[424,2183,970],{"class":463},[424,2185,1368],{"class":463},[424,2187,967],{"class":463},[424,2189,880],{"class":434},[424,2191,967],{"class":463},[424,2193,1386],{"class":463},[424,2195,2196],{"class":426,"line":1004},[424,2197,2136],{"class":463},[424,2199,2200],{"class":426,"line":1025},[424,2201,1468],{"class":463},[894,2203,2205],{"id":2204},"_24-viteconfigts","2.4 vite.config.ts",[415,2207,2211],{"className":2208,"code":2209,"language":2210,"meta":420,"style":420},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import { defineConfig } from 'vite'\nimport vue from '@vitejs\u002Fplugin-vue'\nimport UnoCSS from 'unocss\u002Fvite'\nimport { fileURLToPath, URL } from 'node:url'\n\nexport default defineConfig({\n  base: '.\u002F',\n  \u002F\u002F 端口自定义，避开常用端口即可；strictPort 防止 vite 自行换端口导致宿主连不上\n  server: { port: 5261, strictPort: true, open: false },\n  plugins: [\n    vue(),\n    UnoCSS(),\n    {\n      \u002F\u002F 与内置插件对齐：允许 file:\u002Fudhold-icon: 资源源（指令图标协议）\n      name: 'configure-response-headers',\n      configureServer: (server) => {\n        server.middlewares.use((_req, res, next) => {\n          res.setHeader(\n            'Content-Security-Policy',\n            \"default-src * 'unsafe-inline' 'unsafe-eval' data: blob: udhold-icon: file:; img-src * data: blob: udhold-icon: file:;\"\n          )\n          next()\n        })\n      }\n    }\n  ],\n  resolve: {\n    optimizeDeps: { exclude: ['@udhold\u002Fudhold-ui'] },\n    ssr: { noExternal: ['@udhold\u002Fudhold-ui'] },\n    alias: {\n      '@': fileURLToPath(new URL('.\u002Fsrc', import.meta.url))\n    }\n  }\n})\n","ts",[272,2212,2213,2239,2255,2271,2296,2302,2318,2336,2341,2382,2391,2401,2410,2414,2419,2435,2457,2496,2509,2521,2531,2536,2544,2552,2557,2561,2568,2577,2605,2632,2642,2688,2693,2698],{"__ignoreMap":420},[424,2214,2215,2219,2221,2225,2228,2231,2234,2236],{"class":426,"line":427},[424,2216,2218],{"class":2217},"s7zQu","import",[424,2220,1099],{"class":463},[424,2222,2224],{"class":2223},"sTEyZ"," defineConfig",[424,2226,2227],{"class":463}," }",[424,2229,2230],{"class":2217}," from",[424,2232,2233],{"class":463}," '",[424,2235,1828],{"class":434},[424,2237,2238],{"class":463},"'\n",[424,2240,2241,2243,2246,2249,2251,2253],{"class":426,"line":470},[424,2242,2218],{"class":2217},[424,2244,2245],{"class":2223}," vue ",[424,2247,2248],{"class":2217},"from",[424,2250,2233],{"class":463},[424,2252,2042],{"class":434},[424,2254,2238],{"class":463},[424,2256,2257,2259,2262,2264,2266,2269],{"class":426,"line":477},[424,2258,2218],{"class":2217},[424,2260,2261],{"class":2223}," UnoCSS ",[424,2263,2248],{"class":2217},[424,2265,2233],{"class":463},[424,2267,2268],{"class":434},"unocss\u002Fvite",[424,2270,2238],{"class":463},[424,2272,2273,2275,2277,2280,2282,2285,2287,2289,2291,2294],{"class":426,"line":1004},[424,2274,2218],{"class":2217},[424,2276,1099],{"class":463},[424,2278,2279],{"class":2223}," fileURLToPath",[424,2281,1118],{"class":463},[424,2283,2284],{"class":2223}," URL",[424,2286,2227],{"class":463},[424,2288,2230],{"class":2217},[424,2290,2233],{"class":463},[424,2292,2293],{"class":434},"node:url",[424,2295,2238],{"class":463},[424,2297,2298],{"class":426,"line":1025},[424,2299,2301],{"emptyLinePlaceholder":2300},true,"\n",[424,2303,2304,2307,2310,2313,2316],{"class":426,"line":1046},[424,2305,2306],{"class":2217},"export",[424,2308,2309],{"class":2217}," default",[424,2311,2224],{"class":2312},"s2Zo4",[424,2314,2315],{"class":2223},"(",[424,2317,956],{"class":463},[424,2319,2320,2324,2326,2328,2331,2334],{"class":426,"line":1067},[424,2321,2323],{"class":2322},"swJcz","  base",[424,2325,970],{"class":463},[424,2327,2233],{"class":463},[424,2329,2330],{"class":434},".\u002F",[424,2332,2333],{"class":463},"'",[424,2335,981],{"class":463},[424,2337,2338],{"class":426,"line":1087},[424,2339,2340],{"class":473},"  \u002F\u002F 端口自定义，避开常用端口即可；strictPort 防止 vite 自行换端口导致宿主连不上\n",[424,2342,2343,2346,2348,2350,2353,2355,2359,2361,2364,2366,2370,2372,2375,2377,2380],{"class":426,"line":1140},[424,2344,2345],{"class":2322},"  server",[424,2347,970],{"class":463},[424,2349,1099],{"class":463},[424,2351,2352],{"class":2322}," port",[424,2354,970],{"class":463},[424,2356,2358],{"class":2357},"sbssI"," 5261",[424,2360,1118],{"class":463},[424,2362,2363],{"class":2322}," strictPort",[424,2365,970],{"class":463},[424,2367,2369],{"class":2368},"sfNiH"," true",[424,2371,1118],{"class":463},[424,2373,2374],{"class":2322}," open",[424,2376,970],{"class":463},[424,2378,2379],{"class":2368}," false",[424,2381,1137],{"class":463},[424,2383,2384,2387,2389],{"class":426,"line":1155},[424,2385,2386],{"class":2322},"  plugins",[424,2388,970],{"class":463},[424,2390,1286],{"class":2223},[424,2392,2393,2396,2399],{"class":426,"line":1170},[424,2394,2395],{"class":2312},"    vue",[424,2397,2398],{"class":2223},"()",[424,2400,981],{"class":463},[424,2402,2403,2406,2408],{"class":426,"line":1192},[424,2404,2405],{"class":2312},"    UnoCSS",[424,2407,2398],{"class":2223},[424,2409,981],{"class":463},[424,2411,2412],{"class":426,"line":1207},[424,2413,1292],{"class":463},[424,2415,2416],{"class":426,"line":1221},[424,2417,2418],{"class":473},"      \u002F\u002F 与内置插件对齐：允许 file:\u002Fudhold-icon: 资源源（指令图标协议）\n",[424,2420,2421,2424,2426,2428,2431,2433],{"class":426,"line":1236},[424,2422,2423],{"class":2322},"      name",[424,2425,970],{"class":463},[424,2427,2233],{"class":463},[424,2429,2430],{"class":434},"configure-response-headers",[424,2432,2333],{"class":463},[424,2434,981],{"class":463},[424,2436,2437,2440,2442,2445,2449,2452,2455],{"class":426,"line":1242},[424,2438,2439],{"class":2312},"      configureServer",[424,2441,970],{"class":463},[424,2443,2444],{"class":463}," (",[424,2446,2448],{"class":2447},"sHdIc","server",[424,2450,2451],{"class":463},")",[424,2453,2454],{"class":964}," =>",[424,2456,1167],{"class":463},[424,2458,2459,2462,2465,2468,2470,2473,2475,2477,2480,2482,2485,2487,2490,2492,2494],{"class":426,"line":1274},[424,2460,2461],{"class":2223},"        server",[424,2463,2464],{"class":463},".",[424,2466,2467],{"class":2223},"middlewares",[424,2469,2464],{"class":463},[424,2471,2472],{"class":2312},"use",[424,2474,2315],{"class":2322},[424,2476,2315],{"class":463},[424,2478,2479],{"class":2447},"_req",[424,2481,1118],{"class":463},[424,2483,2484],{"class":2447}," res",[424,2486,1118],{"class":463},[424,2488,2489],{"class":2447}," next",[424,2491,2451],{"class":463},[424,2493,2454],{"class":964},[424,2495,1167],{"class":463},[424,2497,2498,2501,2503,2506],{"class":426,"line":1289},[424,2499,2500],{"class":2223},"          res",[424,2502,2464],{"class":463},[424,2504,2505],{"class":2312},"setHeader",[424,2507,2508],{"class":2322},"(\n",[424,2510,2511,2514,2517,2519],{"class":426,"line":1295},[424,2512,2513],{"class":463},"            '",[424,2515,2516],{"class":434},"Content-Security-Policy",[424,2518,2333],{"class":463},[424,2520,981],{"class":463},[424,2522,2523,2526,2529],{"class":426,"line":1315},[424,2524,2525],{"class":463},"            \"",[424,2527,2528],{"class":434},"default-src * 'unsafe-inline' 'unsafe-eval' data: blob: udhold-icon: file:; img-src * data: blob: udhold-icon: file:;",[424,2530,1462],{"class":463},[424,2532,2533],{"class":426,"line":1336},[424,2534,2535],{"class":2322},"          )\n",[424,2537,2538,2541],{"class":426,"line":1356},[424,2539,2540],{"class":2312},"          next",[424,2542,2543],{"class":2322},"()\n",[424,2545,2546,2549],{"class":426,"line":1389},[424,2547,2548],{"class":463},"        }",[424,2550,2551],{"class":2322},")\n",[424,2553,2554],{"class":426,"line":1395},[424,2555,2556],{"class":463},"      }\n",[424,2558,2559],{"class":426,"line":1401},[424,2560,1392],{"class":463},[424,2562,2563,2566],{"class":426,"line":1422},[424,2564,2565],{"class":2223},"  ]",[424,2567,981],{"class":463},[424,2569,2570,2573,2575],{"class":426,"line":1445},[424,2571,2572],{"class":2322},"  resolve",[424,2574,970],{"class":463},[424,2576,1167],{"class":463},[424,2578,2579,2582,2584,2586,2589,2591,2593,2595,2597,2599,2602],{"class":426,"line":1465},[424,2580,2581],{"class":2322},"    optimizeDeps",[424,2583,970],{"class":463},[424,2585,1099],{"class":463},[424,2587,2588],{"class":2322}," exclude",[424,2590,970],{"class":463},[424,2592,1368],{"class":2223},[424,2594,2333],{"class":463},[424,2596,753],{"class":434},[424,2598,2333],{"class":463},[424,2600,2601],{"class":2223},"] ",[424,2603,2604],{"class":463},"},\n",[424,2606,2608,2611,2613,2615,2618,2620,2622,2624,2626,2628,2630],{"class":426,"line":2607},29,[424,2609,2610],{"class":2322},"    ssr",[424,2612,970],{"class":463},[424,2614,1099],{"class":463},[424,2616,2617],{"class":2322}," noExternal",[424,2619,970],{"class":463},[424,2621,1368],{"class":2223},[424,2623,2333],{"class":463},[424,2625,753],{"class":434},[424,2627,2333],{"class":463},[424,2629,2601],{"class":2223},[424,2631,2604],{"class":463},[424,2633,2635,2638,2640],{"class":426,"line":2634},30,[424,2636,2637],{"class":2322},"    alias",[424,2639,970],{"class":463},[424,2641,1167],{"class":463},[424,2643,2645,2648,2651,2653,2655,2657,2659,2662,2664,2666,2668,2671,2673,2675,2678,2680,2683,2685],{"class":426,"line":2644},31,[424,2646,2647],{"class":463},"      '",[424,2649,2650],{"class":2322},"@",[424,2652,2333],{"class":463},[424,2654,970],{"class":463},[424,2656,2279],{"class":2312},[424,2658,2315],{"class":2223},[424,2660,2661],{"class":463},"new",[424,2663,2284],{"class":2312},[424,2665,2315],{"class":2223},[424,2667,2333],{"class":463},[424,2669,2670],{"class":434},".\u002Fsrc",[424,2672,2333],{"class":463},[424,2674,1118],{"class":463},[424,2676,2677],{"class":2217}," import",[424,2679,2464],{"class":463},[424,2681,2682],{"class":2223},"meta",[424,2684,2464],{"class":463},[424,2686,2687],{"class":2223},"url))\n",[424,2689,2691],{"class":426,"line":2690},32,[424,2692,1392],{"class":463},[424,2694,2696],{"class":426,"line":2695},33,[424,2697,2136],{"class":463},[424,2699,2701,2704],{"class":426,"line":2700},34,[424,2702,2703],{"class":463},"}",[424,2705,2551],{"class":2223},[2707,2708,2709],"blockquote",{},[205,2710,2711,2713,2714,737,2717,2720],{},[272,2712,753],{}," 是源码直引包（无预构建产物），必须保留 ",[272,2715,2716],{},"optimizeDeps.exclude",[272,2718,2719],{},"ssr.noExternal"," 两项配置，否则 Vite 依赖预扫描会报错。",[894,2722,2724],{"id":2723},"_25-srcmaints-与-srcappvue","2.5 src\u002Fmain.ts 与 src\u002FApp.vue",[415,2726,2728],{"className":2208,"code":2727,"language":2210,"meta":420,"style":420},"import { createApp } from 'vue'\nimport App from '.\u002FApp.vue'\nimport 'virtual:uno.css'\nimport '@udhold\u002Fudhold-ui\u002Fstyles\u002Fglobal.css'\nimport { setupThemeSync } from '@udhold\u002Fudhold-ui\u002Futils'\n\n\u002F\u002F 应用宿主主题（明暗 + 主题色），并注册后续变更监听\nsetupThemeSync()\n\ncreateApp(App).mount('#app')\n",[272,2729,2730,2749,2765,2776,2787,2807,2811,2816,2823,2827],{"__ignoreMap":420},[424,2731,2732,2734,2736,2739,2741,2743,2745,2747],{"class":426,"line":427},[424,2733,2218],{"class":2217},[424,2735,1099],{"class":463},[424,2737,2738],{"class":2223}," createApp",[424,2740,2227],{"class":463},[424,2742,2230],{"class":2217},[424,2744,2233],{"class":463},[424,2746,1893],{"class":434},[424,2748,2238],{"class":463},[424,2750,2751,2753,2756,2758,2760,2763],{"class":426,"line":470},[424,2752,2218],{"class":2217},[424,2754,2755],{"class":2223}," App ",[424,2757,2248],{"class":2217},[424,2759,2233],{"class":463},[424,2761,2762],{"class":434},".\u002FApp.vue",[424,2764,2238],{"class":463},[424,2766,2767,2769,2771,2774],{"class":426,"line":477},[424,2768,2218],{"class":2217},[424,2770,2233],{"class":463},[424,2772,2773],{"class":434},"virtual:uno.css",[424,2775,2238],{"class":463},[424,2777,2778,2780,2782,2785],{"class":426,"line":1004},[424,2779,2218],{"class":2217},[424,2781,2233],{"class":463},[424,2783,2784],{"class":434},"@udhold\u002Fudhold-ui\u002Fstyles\u002Fglobal.css",[424,2786,2238],{"class":463},[424,2788,2789,2791,2793,2796,2798,2800,2802,2805],{"class":426,"line":1025},[424,2790,2218],{"class":2217},[424,2792,1099],{"class":463},[424,2794,2795],{"class":2223}," setupThemeSync",[424,2797,2227],{"class":463},[424,2799,2230],{"class":2217},[424,2801,2233],{"class":463},[424,2803,2804],{"class":434},"@udhold\u002Fudhold-ui\u002Futils",[424,2806,2238],{"class":463},[424,2808,2809],{"class":426,"line":1046},[424,2810,2301],{"emptyLinePlaceholder":2300},[424,2812,2813],{"class":426,"line":1067},[424,2814,2815],{"class":473},"\u002F\u002F 应用宿主主题（明暗 + 主题色），并注册后续变更监听\n",[424,2817,2818,2821],{"class":426,"line":1087},[424,2819,2820],{"class":2312},"setupThemeSync",[424,2822,2543],{"class":2223},[424,2824,2825],{"class":426,"line":1140},[424,2826,2301],{"emptyLinePlaceholder":2300},[424,2828,2829,2832,2835,2837,2840,2842,2844,2847,2849],{"class":426,"line":1155},[424,2830,2831],{"class":2312},"createApp",[424,2833,2834],{"class":2223},"(App)",[424,2836,2464],{"class":463},[424,2838,2839],{"class":2312},"mount",[424,2841,2315],{"class":2223},[424,2843,2333],{"class":463},[424,2845,2846],{"class":434},"#app",[424,2848,2333],{"class":463},[424,2850,2551],{"class":2223},[415,2852,2855],{"className":2853,"code":2854,"language":1893,"meta":420,"style":420},"language-vue shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u003Cscript setup lang=\"ts\">\nimport { ref } from 'vue'\nimport { Message, ConfirmDialog, useMessage } from '@udhold\u002Fudhold-ui\u002Fcomponents\u002Fcommon'\n\nconst { messageState, handleClose, handleAction, confirmState, handleConfirm, handleCancel } = useMessage()\nconst count = ref(0)\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cdiv class=\"p-4\">\n    \u003Ch1 class=\"text-base text-highlighted\">我的插件\u003C\u002Fh1>\n    \u003Cbutton class=\"btn-solid\" @click=\"count++\">点了 {{ count }} 次\u003C\u002Fbutton>\n  \u003C\u002Fdiv>\n\n  \u003C!-- 全局消息与确认弹窗，挂一次即可全局使用 -->\n  \u003CMessage :items=\"messageState\" @close=\"handleClose\" @action-click=\"handleAction\" \u002F>\n  \u003CConfirmDialog\n    v-model:visible=\"confirmState.visible\" v-model:extra-values=\"confirmState.extraValues\"\n    :title=\"confirmState.title\" :message=\"confirmState.message\" :type=\"confirmState.type\"\n    :confirm-text=\"confirmState.confirmText\" :cancel-text=\"confirmState.cancelText\" :extra=\"confirmState.extra\"\n    @confirm=\"handleConfirm\" @cancel=\"handleCancel\"\n  \u002F>\n\u003C\u002Ftemplate>\n",[272,2856,2857,2883,2902,2932,2936,2980,2998,3007,3011,3020,3042,3072,3113,3122,3126,3131,3177,3184,3210,3248,3286,3312,3317],{"__ignoreMap":420},[424,2858,2859,2862,2865,2868,2871,2874,2876,2878,2880],{"class":426,"line":427},[424,2860,2861],{"class":463},"\u003C",[424,2863,2864],{"class":2322},"script",[424,2866,2867],{"class":964}," setup",[424,2869,2870],{"class":964}," lang",[424,2872,2873],{"class":463},"=",[424,2875,967],{"class":463},[424,2877,2210],{"class":434},[424,2879,967],{"class":463},[424,2881,2882],{"class":463},">\n",[424,2884,2885,2887,2889,2892,2894,2896,2898,2900],{"class":426,"line":470},[424,2886,2218],{"class":2217},[424,2888,1099],{"class":463},[424,2890,2891],{"class":2223}," ref",[424,2893,2227],{"class":463},[424,2895,2230],{"class":2217},[424,2897,2233],{"class":463},[424,2899,1893],{"class":434},[424,2901,2238],{"class":463},[424,2903,2904,2906,2908,2911,2913,2916,2918,2921,2923,2925,2927,2930],{"class":426,"line":477},[424,2905,2218],{"class":2217},[424,2907,1099],{"class":463},[424,2909,2910],{"class":2223}," Message",[424,2912,1118],{"class":463},[424,2914,2915],{"class":2223}," ConfirmDialog",[424,2917,1118],{"class":463},[424,2919,2920],{"class":2223}," useMessage",[424,2922,2227],{"class":463},[424,2924,2230],{"class":2217},[424,2926,2233],{"class":463},[424,2928,2929],{"class":434},"@udhold\u002Fudhold-ui\u002Fcomponents\u002Fcommon",[424,2931,2238],{"class":463},[424,2933,2934],{"class":426,"line":1004},[424,2935,2301],{"emptyLinePlaceholder":2300},[424,2937,2938,2941,2943,2946,2948,2951,2953,2956,2958,2961,2963,2966,2968,2971,2973,2976,2978],{"class":426,"line":1025},[424,2939,2940],{"class":964},"const",[424,2942,1099],{"class":463},[424,2944,2945],{"class":2223}," messageState",[424,2947,1118],{"class":463},[424,2949,2950],{"class":2223}," handleClose",[424,2952,1118],{"class":463},[424,2954,2955],{"class":2223}," handleAction",[424,2957,1118],{"class":463},[424,2959,2960],{"class":2223}," confirmState",[424,2962,1118],{"class":463},[424,2964,2965],{"class":2223}," handleConfirm",[424,2967,1118],{"class":463},[424,2969,2970],{"class":2223}," handleCancel ",[424,2972,2703],{"class":463},[424,2974,2975],{"class":463}," =",[424,2977,2920],{"class":2312},[424,2979,2543],{"class":2223},[424,2981,2982,2984,2987,2989,2991,2993,2996],{"class":426,"line":1046},[424,2983,2940],{"class":964},[424,2985,2986],{"class":2223}," count ",[424,2988,2873],{"class":463},[424,2990,2891],{"class":2312},[424,2992,2315],{"class":2223},[424,2994,2995],{"class":2357},"0",[424,2997,2551],{"class":2223},[424,2999,3000,3003,3005],{"class":426,"line":1067},[424,3001,3002],{"class":463},"\u003C\u002F",[424,3004,2864],{"class":2322},[424,3006,2882],{"class":463},[424,3008,3009],{"class":426,"line":1087},[424,3010,2301],{"emptyLinePlaceholder":2300},[424,3012,3013,3015,3018],{"class":426,"line":1140},[424,3014,2861],{"class":463},[424,3016,3017],{"class":2322},"template",[424,3019,2882],{"class":463},[424,3021,3022,3025,3028,3031,3033,3035,3038,3040],{"class":426,"line":1155},[424,3023,3024],{"class":463},"  \u003C",[424,3026,3027],{"class":2322},"div",[424,3029,3030],{"class":964}," class",[424,3032,2873],{"class":463},[424,3034,967],{"class":463},[424,3036,3037],{"class":434},"p-4",[424,3039,967],{"class":463},[424,3041,2882],{"class":463},[424,3043,3044,3047,3050,3052,3054,3056,3059,3061,3064,3066,3068,3070],{"class":426,"line":1170},[424,3045,3046],{"class":463},"    \u003C",[424,3048,3049],{"class":2322},"h1",[424,3051,3030],{"class":964},[424,3053,2873],{"class":463},[424,3055,967],{"class":463},[424,3057,3058],{"class":434},"text-base text-highlighted",[424,3060,967],{"class":463},[424,3062,3063],{"class":463},">",[424,3065,997],{"class":2223},[424,3067,3002],{"class":463},[424,3069,3049],{"class":2322},[424,3071,2882],{"class":463},[424,3073,3074,3076,3079,3081,3083,3085,3088,3090,3093,3095,3097,3100,3102,3104,3107,3109,3111],{"class":426,"line":1192},[424,3075,3046],{"class":463},[424,3077,3078],{"class":2322},"button",[424,3080,3030],{"class":964},[424,3082,2873],{"class":463},[424,3084,967],{"class":463},[424,3086,3087],{"class":434},"btn-solid",[424,3089,967],{"class":463},[424,3091,3092],{"class":964}," @click",[424,3094,2873],{"class":463},[424,3096,967],{"class":463},[424,3098,3099],{"class":434},"count++",[424,3101,967],{"class":463},[424,3103,3063],{"class":463},[424,3105,3106],{"class":2223},"点了 {{ count }} 次",[424,3108,3002],{"class":463},[424,3110,3078],{"class":2322},[424,3112,2882],{"class":463},[424,3114,3115,3118,3120],{"class":426,"line":1207},[424,3116,3117],{"class":463},"  \u003C\u002F",[424,3119,3027],{"class":2322},[424,3121,2882],{"class":463},[424,3123,3124],{"class":426,"line":1221},[424,3125,2301],{"emptyLinePlaceholder":2300},[424,3127,3128],{"class":426,"line":1236},[424,3129,3130],{"class":473},"  \u003C!-- 全局消息与确认弹窗，挂一次即可全局使用 -->\n",[424,3132,3133,3135,3138,3141,3143,3145,3148,3150,3153,3155,3157,3160,3162,3165,3167,3169,3172,3174],{"class":426,"line":1242},[424,3134,3024],{"class":463},[424,3136,3137],{"class":2322},"Message",[424,3139,3140],{"class":964}," :items",[424,3142,2873],{"class":463},[424,3144,967],{"class":463},[424,3146,3147],{"class":434},"messageState",[424,3149,967],{"class":463},[424,3151,3152],{"class":964}," @close",[424,3154,2873],{"class":463},[424,3156,967],{"class":463},[424,3158,3159],{"class":434},"handleClose",[424,3161,967],{"class":463},[424,3163,3164],{"class":964}," @action-click",[424,3166,2873],{"class":463},[424,3168,967],{"class":463},[424,3170,3171],{"class":434},"handleAction",[424,3173,967],{"class":463},[424,3175,3176],{"class":463}," \u002F>\n",[424,3178,3179,3181],{"class":426,"line":1274},[424,3180,3024],{"class":463},[424,3182,3183],{"class":2322},"ConfirmDialog\n",[424,3185,3186,3189,3191,3193,3196,3198,3201,3203,3205,3208],{"class":426,"line":1289},[424,3187,3188],{"class":964},"    v-model:visible",[424,3190,2873],{"class":463},[424,3192,967],{"class":463},[424,3194,3195],{"class":434},"confirmState.visible",[424,3197,967],{"class":463},[424,3199,3200],{"class":964}," v-model:extra-values",[424,3202,2873],{"class":463},[424,3204,967],{"class":463},[424,3206,3207],{"class":434},"confirmState.extraValues",[424,3209,1462],{"class":463},[424,3211,3212,3215,3217,3219,3222,3224,3227,3229,3231,3234,3236,3239,3241,3243,3246],{"class":426,"line":1295},[424,3213,3214],{"class":964},"    :title",[424,3216,2873],{"class":463},[424,3218,967],{"class":463},[424,3220,3221],{"class":434},"confirmState.title",[424,3223,967],{"class":463},[424,3225,3226],{"class":964}," :message",[424,3228,2873],{"class":463},[424,3230,967],{"class":463},[424,3232,3233],{"class":434},"confirmState.message",[424,3235,967],{"class":463},[424,3237,3238],{"class":964}," :type",[424,3240,2873],{"class":463},[424,3242,967],{"class":463},[424,3244,3245],{"class":434},"confirmState.type",[424,3247,1462],{"class":463},[424,3249,3250,3253,3255,3257,3260,3262,3265,3267,3269,3272,3274,3277,3279,3281,3284],{"class":426,"line":1315},[424,3251,3252],{"class":964},"    :confirm-text",[424,3254,2873],{"class":463},[424,3256,967],{"class":463},[424,3258,3259],{"class":434},"confirmState.confirmText",[424,3261,967],{"class":463},[424,3263,3264],{"class":964}," :cancel-text",[424,3266,2873],{"class":463},[424,3268,967],{"class":463},[424,3270,3271],{"class":434},"confirmState.cancelText",[424,3273,967],{"class":463},[424,3275,3276],{"class":964}," :extra",[424,3278,2873],{"class":463},[424,3280,967],{"class":463},[424,3282,3283],{"class":434},"confirmState.extra",[424,3285,1462],{"class":463},[424,3287,3288,3291,3293,3295,3298,3300,3303,3305,3307,3310],{"class":426,"line":1336},[424,3289,3290],{"class":964},"    @confirm",[424,3292,2873],{"class":463},[424,3294,967],{"class":463},[424,3296,3297],{"class":434},"handleConfirm",[424,3299,967],{"class":463},[424,3301,3302],{"class":964}," @cancel",[424,3304,2873],{"class":463},[424,3306,967],{"class":463},[424,3308,3309],{"class":434},"handleCancel",[424,3311,1462],{"class":463},[424,3313,3314],{"class":426,"line":1356},[424,3315,3316],{"class":463},"  \u002F>\n",[424,3318,3319,3321,3323],{"class":426,"line":1389},[424,3320,3002],{"class":463},[424,3322,3017],{"class":2322},[424,3324,2882],{"class":463},[205,3326,3327,3328,3330],{},"样式与组件的完整用法见",[245,3329,157],{"href":163},"系列文档。",[209,3332,3334],{"id":3333},"第-3-步运行调试","第 3 步：运行调试",[330,3336,3337,3344,3357],{},[333,3338,3339,3340,3343],{},"工程目录里启动 dev server：",[272,3341,3342],{},"pnpm dev","（向导创建的工程在「插件开发者」里点「运行调试」会自动完成安装依赖、启动、登记全流程）。",[333,3345,3346,3347,3349,3350,3352,3353,3356],{},"在「插件开发者」工作台选中工程，点「",[298,3348,861],{},"」。宿主会登记该工程并以 ",[272,3351,1533],{}," 的地址直连 dev server——",[298,3354,3355],{},"改代码即时热更新（HMR），不用重启宿主","。",[333,3358,3359,3360,3362],{},"呼出主搜索框，输入你在 ",[272,3361,1361],{}," 里声明的关键词（如「我的插件」），回车打开插件。",[205,3364,3365],{},"调试要点：",[396,3367,3368,3380,3390,3393],{},[333,3369,3370,3372,3373,720,3376,3379],{},[272,3371,1533],{}," 只允许 ",[272,3374,3375],{},"http:\u002F\u002Flocalhost:*",[272,3377,3378],{},"127.0.0.1"," 地址（安全限制，防远程页面注入）。",[333,3381,3382,3383,3386,3387,3389],{},"dev server 没启动时，宿主探测不到端口会",[298,3384,3385],{},"回退加载本地 dist 产物","——如果你看到的是旧界面，先确认 dev server 是否在跑、端口是否与 ",[272,3388,1533],{}," 一致。",[333,3391,3392],{},"「运行调试」的登记关系存在内存里，宿主重启后失效，重新点一次即可。",[333,3394,3395,3396,3398],{},"免构建工程（无 ",[272,3397,1533],{},"）以「链接」语义直接加载工程目录里的文件。",[209,3400,3402],{"id":3401},"第-4-步调用宿主能力","第 4 步：调用宿主能力",[205,3404,3405,3406,907,3409,3356,3412,3415,3416,3419,3420,907],{},"大多数宿主方法返回统一信封 ",[272,3407,3408],{},"IpcResult\u003CT>",[272,3410,3411],{},"{ code, success, data, msg }",[272,3413,3414],{},"code !== 0"," 即失败（403 = 权限未声明），失败",[298,3417,3418],{},"不会抛异常","，要靠检查 ",[272,3421,272],{},[415,3423,3425],{"className":2208,"code":3424,"language":2210,"meta":420,"style":420},"\u002F\u002F 基础能力（免权限声明）\nudhold.dbStorage.setItem('launchCount', String((Number(udhold.dbStorage.getItem('launchCount')) || 0) + 1))\nudhold.shellOpenExternal('https:\u002F\u002Fudhold.cn')\nawait udhold.copyText('已复制的内容')\n\n\u002F\u002F 敏感能力：先在 plugin.json 声明 permissions，再按信封处理结果\nconst res = await udhold.clipboard.getHistory(1, 20)\nif (res.code !== 0) {\n  console.error('调用失败：', res.msg)   \u002F\u002F 403 → 检查 permissions 声明\n} else {\n  console.log('历史条目：', res.data)\n}\n",[272,3426,3427,3432,3506,3526,3550,3554,3559,3595,3617,3651,3660,3689],{"__ignoreMap":420},[424,3428,3429],{"class":426,"line":427},[424,3430,3431],{"class":473},"\u002F\u002F 基础能力（免权限声明）\n",[424,3433,3434,3436,3438,3441,3443,3446,3448,3450,3453,3455,3457,3460,3463,3466,3469,3471,3473,3475,3478,3480,3482,3484,3486,3489,3492,3495,3498,3500,3503],{"class":426,"line":470},[424,3435,678],{"class":2223},[424,3437,2464],{"class":463},[424,3439,3440],{"class":2223},"dbStorage",[424,3442,2464],{"class":463},[424,3444,3445],{"class":2312},"setItem",[424,3447,2315],{"class":2223},[424,3449,2333],{"class":463},[424,3451,3452],{"class":434},"launchCount",[424,3454,2333],{"class":463},[424,3456,1118],{"class":463},[424,3458,3459],{"class":2312}," String",[424,3461,3462],{"class":2223},"((",[424,3464,3465],{"class":2312},"Number",[424,3467,3468],{"class":2223},"(udhold",[424,3470,2464],{"class":463},[424,3472,3440],{"class":2223},[424,3474,2464],{"class":463},[424,3476,3477],{"class":2312},"getItem",[424,3479,2315],{"class":2223},[424,3481,2333],{"class":463},[424,3483,3452],{"class":434},[424,3485,2333],{"class":463},[424,3487,3488],{"class":2223},")) ",[424,3490,3491],{"class":463},"||",[424,3493,3494],{"class":2357}," 0",[424,3496,3497],{"class":2223},") ",[424,3499,309],{"class":463},[424,3501,3502],{"class":2357}," 1",[424,3504,3505],{"class":2223},"))\n",[424,3507,3508,3510,3512,3515,3517,3519,3522,3524],{"class":426,"line":477},[424,3509,678],{"class":2223},[424,3511,2464],{"class":463},[424,3513,3514],{"class":2312},"shellOpenExternal",[424,3516,2315],{"class":2223},[424,3518,2333],{"class":463},[424,3520,3521],{"class":434},"https:\u002F\u002Fudhold.cn",[424,3523,2333],{"class":463},[424,3525,2551],{"class":2223},[424,3527,3528,3531,3534,3536,3539,3541,3543,3546,3548],{"class":426,"line":1004},[424,3529,3530],{"class":2217},"await",[424,3532,3533],{"class":2223}," udhold",[424,3535,2464],{"class":463},[424,3537,3538],{"class":2312},"copyText",[424,3540,2315],{"class":2223},[424,3542,2333],{"class":463},[424,3544,3545],{"class":434},"已复制的内容",[424,3547,2333],{"class":463},[424,3549,2551],{"class":2223},[424,3551,3552],{"class":426,"line":1025},[424,3553,2301],{"emptyLinePlaceholder":2300},[424,3555,3556],{"class":426,"line":1046},[424,3557,3558],{"class":473},"\u002F\u002F 敏感能力：先在 plugin.json 声明 permissions，再按信封处理结果\n",[424,3560,3561,3563,3566,3568,3571,3573,3575,3578,3580,3583,3585,3588,3590,3593],{"class":426,"line":1067},[424,3562,2940],{"class":964},[424,3564,3565],{"class":2223}," res ",[424,3567,2873],{"class":463},[424,3569,3570],{"class":2217}," await",[424,3572,3533],{"class":2223},[424,3574,2464],{"class":463},[424,3576,3577],{"class":2223},"clipboard",[424,3579,2464],{"class":463},[424,3581,3582],{"class":2312},"getHistory",[424,3584,2315],{"class":2223},[424,3586,3587],{"class":2357},"1",[424,3589,1118],{"class":463},[424,3591,3592],{"class":2357}," 20",[424,3594,2551],{"class":2223},[424,3596,3597,3600,3603,3605,3608,3611,3613,3615],{"class":426,"line":1087},[424,3598,3599],{"class":2217},"if",[424,3601,3602],{"class":2223}," (res",[424,3604,2464],{"class":463},[424,3606,3607],{"class":2223},"code ",[424,3609,3610],{"class":463},"!==",[424,3612,3494],{"class":2357},[424,3614,3497],{"class":2223},[424,3616,956],{"class":463},[424,3618,3619,3622,3624,3627,3629,3631,3634,3636,3638,3640,3642,3645,3648],{"class":426,"line":1140},[424,3620,3621],{"class":2223},"  console",[424,3623,2464],{"class":463},[424,3625,3626],{"class":2312},"error",[424,3628,2315],{"class":2322},[424,3630,2333],{"class":463},[424,3632,3633],{"class":434},"调用失败：",[424,3635,2333],{"class":463},[424,3637,1118],{"class":463},[424,3639,2484],{"class":2223},[424,3641,2464],{"class":463},[424,3643,3644],{"class":2223},"msg",[424,3646,3647],{"class":2322},")   ",[424,3649,3650],{"class":473},"\u002F\u002F 403 → 检查 permissions 声明\n",[424,3652,3653,3655,3658],{"class":426,"line":1155},[424,3654,2703],{"class":463},[424,3656,3657],{"class":2217}," else",[424,3659,1167],{"class":463},[424,3661,3662,3664,3666,3669,3671,3673,3676,3678,3680,3682,3684,3687],{"class":426,"line":1170},[424,3663,3621],{"class":2223},[424,3665,2464],{"class":463},[424,3667,3668],{"class":2312},"log",[424,3670,2315],{"class":2322},[424,3672,2333],{"class":463},[424,3674,3675],{"class":434},"历史条目：",[424,3677,2333],{"class":463},[424,3679,1118],{"class":463},[424,3681,2484],{"class":2223},[424,3683,2464],{"class":463},[424,3685,3686],{"class":2223},"data",[424,3688,2551],{"class":2322},[424,3690,3691],{"class":426,"line":1192},[424,3692,1468],{"class":463},[205,3694,3695,3698,3699,3701,3702,3705,3706,3709],{},[298,3696,3697],{},"启动参数","：用户从搜索框打开插件时，命中的 feature 的 ",[272,3700,272],{}," 会回传；跳转方通过 ",[272,3703,3704],{},"router.push"," 传的 ",[272,3707,3708],{},"query"," 也在其中。在生命周期钩子里读取：",[415,3711,3713],{"className":2208,"code":3712,"language":2210,"meta":420,"style":420},"udhold.plugin.onMounted((action) => {\n  \u002F\u002F action.code：命中的 feature 标识（缺省 'main'）\n  \u002F\u002F action.payload：启动参数（即 router.push 的 query）\n  \u002F\u002F action.from：唤起来源 main \u002F panel \u002F hotkey \u002F redirect \u002F workflow \u002F api\n  if (action.code === 'convert') {\n    const input = action.payload?.text ?? ''\n    \u002F\u002F ...\n  }\n})\n",[272,3714,3715,3742,3747,3752,3757,3784,3813,3818,3822],{"__ignoreMap":420},[424,3716,3717,3719,3721,3724,3726,3729,3731,3733,3736,3738,3740],{"class":426,"line":427},[424,3718,678],{"class":2223},[424,3720,2464],{"class":463},[424,3722,3723],{"class":2223},"plugin",[424,3725,2464],{"class":463},[424,3727,3728],{"class":2312},"onMounted",[424,3730,2315],{"class":2223},[424,3732,2315],{"class":463},[424,3734,3735],{"class":2447},"action",[424,3737,2451],{"class":463},[424,3739,2454],{"class":964},[424,3741,1167],{"class":463},[424,3743,3744],{"class":426,"line":470},[424,3745,3746],{"class":473},"  \u002F\u002F action.code：命中的 feature 标识（缺省 'main'）\n",[424,3748,3749],{"class":426,"line":477},[424,3750,3751],{"class":473},"  \u002F\u002F action.payload：启动参数（即 router.push 的 query）\n",[424,3753,3754],{"class":426,"line":1004},[424,3755,3756],{"class":473},"  \u002F\u002F action.from：唤起来源 main \u002F panel \u002F hotkey \u002F redirect \u002F workflow \u002F api\n",[424,3758,3759,3762,3764,3766,3768,3770,3773,3775,3778,3780,3782],{"class":426,"line":1025},[424,3760,3761],{"class":2217},"  if",[424,3763,2444],{"class":2322},[424,3765,3735],{"class":2223},[424,3767,2464],{"class":463},[424,3769,272],{"class":2223},[424,3771,3772],{"class":463}," ===",[424,3774,2233],{"class":463},[424,3776,3777],{"class":434},"convert",[424,3779,2333],{"class":463},[424,3781,3497],{"class":2322},[424,3783,956],{"class":463},[424,3785,3786,3789,3792,3794,3797,3799,3802,3805,3807,3810],{"class":426,"line":1046},[424,3787,3788],{"class":964},"    const",[424,3790,3791],{"class":2223}," input",[424,3793,2975],{"class":463},[424,3795,3796],{"class":2223}," action",[424,3798,2464],{"class":463},[424,3800,3801],{"class":2223},"payload",[424,3803,3804],{"class":463},"?.",[424,3806,913],{"class":2223},[424,3808,3809],{"class":463}," ??",[424,3811,3812],{"class":463}," ''\n",[424,3814,3815],{"class":426,"line":1067},[424,3816,3817],{"class":473},"    \u002F\u002F ...\n",[424,3819,3820],{"class":426,"line":1087},[424,3821,2136],{"class":463},[424,3823,3824,3826],{"class":426,"line":1140},[424,3825,2703],{"class":463},[424,3827,2551],{"class":2223},[205,3829,3830,3833,3834,3837],{},[298,3831,3832],{},"清理时机","：定时器、文件监听、服务进程一律在 ",[272,3835,3836],{},"onBeforeUnmount"," 里释放（宿主销毁前给 200ms 宽限）：",[415,3839,3841],{"className":2208,"code":3840,"language":2210,"meta":420,"style":420},"const off = udhold.plugin.onBeforeUnmount(() => {\n  clearInterval(timer)\n})\n",[272,3842,3843,3870,3882],{"__ignoreMap":420},[424,3844,3845,3847,3850,3852,3854,3856,3858,3860,3862,3864,3866,3868],{"class":426,"line":427},[424,3846,2940],{"class":964},[424,3848,3849],{"class":2223}," off ",[424,3851,2873],{"class":463},[424,3853,3533],{"class":2223},[424,3855,2464],{"class":463},[424,3857,3723],{"class":2223},[424,3859,2464],{"class":463},[424,3861,3836],{"class":2312},[424,3863,2315],{"class":2223},[424,3865,2398],{"class":463},[424,3867,2454],{"class":964},[424,3869,1167],{"class":463},[424,3871,3872,3875,3877,3880],{"class":426,"line":470},[424,3873,3874],{"class":2312},"  clearInterval",[424,3876,2315],{"class":2322},[424,3878,3879],{"class":2223},"timer",[424,3881,2551],{"class":2322},[424,3883,3884,3886],{"class":426,"line":477},[424,3885,2703],{"class":463},[424,3887,2551],{"class":2223},[209,3889,3891],{"id":3890},"第-5-步打包与本地验证","第 5 步：打包与本地验证",[330,3893,3894,3917,3942,3948],{},[333,3895,3896,3897,3909,3912,3913,3916],{},"构建产物。在插件工程目录执行：",[415,3898,3900],{"className":417,"code":3899,"language":419,"meta":420,"style":420},"pnpm build\n",[272,3901,3902],{"__ignoreMap":420},[424,3903,3904,3906],{"class":426,"line":427},[424,3905,267],{"class":430},[424,3907,3908],{"class":434}," build\n",[3910,3911],"br",{},"产出 ",[272,3914,3915],{},"dist\u002F"," 目录。",[333,3918,3919,3920,3922,3923,3925,3926,3928,3929,3932,3933,3936,3937,737,3939,3941],{},"打包规则由 ",[272,3921,736],{}," 的 ",[272,3924,1427],{}," 字段决定：",[272,3927,1521],{}," 只收录 dist 目录；缺省时收录整个插件根（自动排除 ",[272,3930,3931],{},"node_modules","、",[272,3934,3935],{},".git"," 等）。",[272,3938,736],{},[272,3940,1072],{}," 会固定打进包根。",[333,3943,3944,3945,3356],{},"在「插件开发者」的发布页选中工程，一键打包为 ",[272,3946,3947],{},"my-plugin-v1.0.0.zip",[333,3949,3950],{},"本地验证：把 zip 发给测试者，在插件中心选「本地安装」导入（也支持双击安装），检查真实安装态下的表现。",[291,3952,3953],{"color":293,"icon":19},[205,3954,3955,3956,3958,3959,3961],{},"免构建静态插件没有构建环节，",[272,3957,1427],{}," 声明 ",[272,3960,1525],{}," 或留空即可，发布页会直接按目录打包。",[209,3963,3965],{"id":3964},"第-6-步发布市场","第 6 步：发布市场",[330,3967,3968,3971,3974,3984,3987],{},[333,3969,3970],{},"确保已登录 UDhold 账号，且插件已在市场登记（向导创建建项目时自动完成；CLI 与手动搭建在发布页先「登记」）。",[333,3972,3973],{},"发布页上传 zip 包，填写版本说明，选择上架状态（先「测试」再转「正式」是常见的灰度节奏）。",[333,3975,3976,3977,3979,3980,3983],{},"等待审核：审核重点包括 ",[272,3978,1145],{}," 与实际功能是否匹配、",[272,3981,3982],{},"plugins: ['*']"," 等高风险声明、导出接口是否构成权限泄漏。",[333,3985,3986],{},"审核通过即上架，全平台用户可在插件市场搜到。",[333,3988,3989,3990,3922,3992,3994,3995,3998],{},"发新版本：改 ",[272,3991,736],{},[272,3993,1051],{}," → 重新构建打包 → 上传。已安装用户",[298,3996,3997],{},"打开插件时宿主自动检查并静默更新","，无需手动催更。",[209,4000,4001],{"id":4001},"接下来",[205,4003,4004,4005,4007,4008,4010,4011,3356],{},"功能逻辑跑通了，就该打磨界面了。去看",[245,4006,157],{"href":163},"：一套设计令牌 + 现成组件，让你的插件和 UDhold 原生功能长得像一家人。想用 Cursor、Claude 等 AI 工具辅助编码，看 ",[245,4009,196],{"href":197},"；卡住了先翻",[245,4012,152],{"href":4013},".\u002Ffaq",[4015,4016,4017],"style",{},"html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}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 pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}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 .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);}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}",{"title":420,"searchDepth":470,"depth":470,"links":4019},[4020,4024,4029,4030,4031,4032,4033],{"id":211,"depth":470,"text":212,"children":4021},[4022,4023],{"id":321,"depth":477,"text":322},{"id":545,"depth":477,"text":546},{"id":625,"depth":470,"text":626,"children":4025},[4026,4027,4028],{"id":644,"depth":477,"text":645},{"id":765,"depth":477,"text":766},{"id":870,"depth":477,"text":871},{"id":3333,"depth":470,"text":3334},{"id":3401,"depth":470,"text":3402},{"id":3890,"depth":470,"text":3891},{"id":3964,"depth":470,"text":3965},{"id":4001,"depth":470,"text":4001},"从环境准备到发布市场的完整实操：创建工程、运行调试、调用宿主能力、打包发布。","md",{},{"icon":34},"---\ntitle: 快速上手\ndescription: 从环境准备到发布市场的完整实操：创建工程、运行调试、调用宿主能力、打包发布。\nnavigation:\n  icon: i-lucide-zap\n---\n\n这一章是一条完整的开发流水线：环境 → 创建工程 → 运行调试 → 调用能力 → 打包 → 发布。跟着做，20 分钟跑起你的第一个插件。\n\n## 第 1 步：准备环境\n\n| 依赖 | 要求 | 用途 |\n|------|------|------|\n| UDhold 桌面端 | 最新版，[下载安装](\u002F#download) | 调试容器与打包发布都在宿主内完成 |\n| Node.js | 20 LTS 或更高 | 工程型插件的构建工具链 |\n| pnpm | 9+（`npm i -g pnpm`） | 官方插件工程的包管理器 |\n| UDhold 账号 | 已登录 | 向导建项目、发布市场需要 |\n\n::callout{icon=\"i-lucide-info\" color=\"primary\"}\n只做**免构建静态插件**（纯 HTML）或全程用「插件开发者」向导的话，Node.js 可以先不装——UDhold 会用内置运行时代劳。要做工程型插件（Vue\u002FReact），再按下面步骤装。\n::\n\n装好宿主后，呼出主搜索框（默认 \u003Ckbd>Alt\u003C\u002Fkbd>+\u003Ckbd>Z\u003C\u002Fkbd>）输入「**插件开发者**」回车——这是 UDhold 内置的插件开发工作台，接下来的创建、调试、发布都在它里面完成。\n\n### 安装 Node.js 和 npm\n\n**npm 不用单独装**——它随 Node.js 安装包一起分发，装好 Node.js 就有了 npm。步骤：\n\n1. 打开 Node.js 官网下载页：\u003Chttps:\u002F\u002Fnodejs.org\u002Fzh-cn\u002Fdownload>\n2. 选择 **LTS 版本**（长期支持版，标绿的按钮），按操作系统下载安装包：\n\n::tabs\n:::tabs-item{label=\"Windows\"}\n\n下载 `*.msi` 安装包（如 `node-v22.x-x64.msi`），双击安装：\n\n1. 一路「下一步」，默认会勾选 **Add to PATH**（自动配置环境变量）和 **npm components**，保持默认即可\n2. 「Tools for Native Modules」页面可以不勾（插件开发用不到原生编译工具链）\n3. 装完**重开一个终端窗口**（让 PATH 生效）\n\n:::\n\n:::tabs-item{label=\"macOS\"}\n\n两种方式任选：\n\n- **官网安装包**：下载 `*.pkg` 双击，按提示安装\n- **Homebrew**（已装 brew 的话更省事）：\n\n```bash\nbrew install node@22\n```\n\n:::\n\n:::tabs-item{label=\"Linux\"}\n\n推荐用 nvm 管理版本（免 sudo、可多版本切换）：\n\n```bash\ncurl -o- https:\u002F\u002Fraw.githubusercontent.com\u002Fnvm-sh\u002Fnvm\u002Fmaster\u002Finstall.sh | bash\n# 重开终端后：\nnvm install --lts\n```\n\n:::\n::\n\n3. 验证安装——打开终端（Windows 用 PowerShell），能打印出版本号即成功：\n\n```bash\nnode -v   # v22.x.x 这样的输出（≥ v20 即满足要求）\nnpm -v    # 10.x 这样的输出\n```\n\n::callout{icon=\"i-lucide-info\" color=\"primary\"}\n国内网络拉取 npm 包慢或超时，可切换国内镜像源（可选，仅影响下载速度）：\n\n```bash\nnpm config set registry https:\u002F\u002Fregistry.npmmirror.com\n```\n::\n\n### 安装 pnpm\n\n工程型插件（见下面「方式三」）用 pnpm 管理依赖，任选一种方式安装：\n\n::tabs\n:::tabs-item{label=\"npm\"}\n\n```bash\nnpm install -g pnpm\n```\n\n:::\n\n:::tabs-item{label=\"corepack\"}\n\nNode.js 自带 corepack（v16.13+），启用即得 pnpm：\n\n```bash\ncorepack enable pnpm\n```\n\n:::\n\n:::tabs-item{label=\"Homebrew\"}\n\n```bash\nbrew install pnpm\n```\n\n:::\n::\n\n验证：\n\n```bash\npnpm -v   # 9.x 或更高\n```\n\n## 第 2 步：创建工程\n\n三种方式任选：**CLI 脚手架一键创建**最快；**向导创建**适合快速起步和纯服务\u002F静态插件；**手动搭建**适合理解每个文件、向官方插件仓库贡献插件。\n\n### 方式一：CLI 脚手架一键创建（推荐）\n\n装好 [Node.js](#安装-nodejs-和-npm) 后，用官方脚手架交互式生成完整插件框架：\n\n::tabs\n:::tabs-item{label=\"pnpm\"}\n\n```bash\npnpm add -g @udhold\u002Fplugin-cli\nudhold create my-plugin\n```\n\n:::\n\n:::tabs-item{label=\"npm\"}\n\n```bash\nnpm install -g @udhold\u002Fplugin-cli\nudhold create my-plugin\n```\n\n:::\n::\n\n按提示完成四步：项目名 → 选模板（**Vue 3 + 设计系统**（推荐）\u002F **React + Vite** \u002F **免构建静态 HTML**）→ 填插件信息（ID、标题、描述、作者）→ 自动生成工程。生成后进入工程目录 `pnpm install && pnpm dev`（静态模板免安装），直接跳到[第 3 步](#第-3-步运行调试)调试；dev 端口等细节在生成工程的 `plugin.json` 与 `vite.config` 中调整。\n\n::callout{icon=\"i-lucide-info\" color=\"primary\"}\n脚手架生成的工程是**独立目录**，不依赖官方仓库（`@udhold\u002Fudhold-ui` 等依赖来自 npm）。想向官方插件仓库贡献插件，把生成目录挪进 `udhold-plugin\u002Fplugins\u002F` 下并把依赖改成 `workspace:*` 即可。\n::\n\n### 方式二：向导创建（推荐起步）\n\n1. 在「插件开发者」的开发页点「**新建项目**」。\n2. 填写插件标题、描述、简介，选择工程存放目录。\n3. 选择插件形态，向导会生成对应的最小工程：\n\n   | 形态 | 生成内容 |\n   |------|----------|\n   | 静态 HTML | `index.html` + `plugin.json`，免构建、零依赖 |\n   | 页面 + Node 服务 | 页面 + `server.js` 后端（声明式 `services`） |\n   | 页面 + Python 服务 | 页面 + Python 后端 |\n   | 纯 Node 服务 | 只有后端，无界面（纯服务插件） |\n   | 纯 Python 服务 | 同上 |\n\n4. 需要登录：向导会先在市场登记插件条目（拿到全局唯一的插件 `name`），再落盘工程文件。\n5. 完成后工程自动出现在工作台列表里，点「**运行调试**」即可看到插件跑起来。\n\n::callout{icon=\"i-lucide-info\" color=\"primary\"}\n向导生成的工程是独立目录，不依赖任何仓库。形态选错了不要紧——工程文件都是普通文件，随时可以改造成工程化开发。\n::\n\n### 方式三：手动搭建（Vue 3 + 官方设计系统）\n\n官方插件（计算器、JSON Tools……）都在官方插件工程仓库里开发：仓库内置 `@udhold\u002Fudhold-ui` 组件库与 `@udhold\u002Fudhold-api-types` 类型包（见[开发者资源](\u002Fdevelopers)），把你的插件放在 `udhold-plugin\u002Fplugins\u002F` 下即可直接以 `workspace:*` 引用它们。\n\n#### 2.1 目录结构\n\n在 `udhold-plugin\u002Fplugins\u002F` 下新建 `my-plugin\u002F`：\n\n```\nmy-plugin\u002F\n├── src\u002F\n│   ├── main.ts          # 入口\n│   ├── App.vue          # 根组件\n│   └── ...              # 你的页面与组件\n├── dist\u002F                # 构建产物（pnpm build 生成）\n├── index.html           # Vite HTML 模板\n├── logo.png             # 插件图标\n├── plugin.json          # 插件清单（放插件根目录，与官方插件一致）\n├── package.json\n├── tsconfig.json\n├── uno.config.ts\n└── vite.config.ts\n```\n\n::callout{icon=\"i-lucide-info\" color=\"primary\"}\n`plugin.json` 和 `logo.png` 放在**插件根目录**，不要放进 `public\u002F`。打包时打包器会把 `plugin.json` 原文和 logo 固定收进安装包根目录，不依赖构建产物；放进 `public\u002F` 只会让构建在 dist 里多出一份冗余副本。\n::\n\n#### 2.2 plugin.json\n\n```json\n{\n  \"name\": \"my-plugin\",\n  \"title\": \"我的插件\",\n  \"description\": \"一句话描述插件做什么\",\n  \"author\": \"你的名字\",\n  \"version\": \"1.0.0\",\n  \"logo\": \"logo.png\",\n  \"loading\": { \"variant\": \"Drive\", \"label\": \"加载中\" },\n  \"permissions\": [],\n  \"pluginSetting\": {\n    \"slot\": \"workspace\",\n    \"Detach\": true,\n    \"Menu\": true,\n    \"DesktopShortcut\": true\n  },\n  \"development\": { \"main\": \"http:\u002F\u002Flocalhost:5261\" },\n  \"features\": [\n    {\n      \"code\": \"main\",\n      \"explain\": \"我的插件主功能\",\n      \"icon\": \"logo.png\",\n      \"cmds\": [\"我的插件\", \"mypl\"]\n    }\n  ],\n  \"dist\": \"dist\u002Findex.html\",\n  \"build\": [\"dist\"],\n  \"readme\": \"这里是插件详情页展示的完整介绍，支持 Markdown。\"\n}\n```\n\n常用字段速查（完整契约见类型包内的 schema）：\n\n| 字段 | 说明 |\n|------|------|\n| `name` \u002F `title` \u002F `version` | 全局唯一标识 \u002F 显示名 \u002F semver 版本（更新的唯一判定来源） |\n| `dist` | 构建产物入口；免构建插件直接写 `index.html` |\n| `build` | 打包收录清单：`[\"dist\"]` 只收 dist 目录；`[\".\"]` 收整个插件根（自动排除 node_modules 等） |\n| `development.main` | 开发态 dev server 地址，调试时宿主直连它（仅允许 localhost） |\n| `pluginSetting.slot` | 面板槽位：`workspace`（工作区）\u002F `leftPanel` \u002F `rightPanel` |\n| `pluginSetting.Detach` | `true` 时打开即分离为独立窗口 |\n| `pluginSetting.Menu` \u002F `MenuBottom` | 进活动栏顶部 \u002F 底部菜单 |\n| `pluginSetting.SubSearch` | 分离窗口标题栏带搜索框（配合 `SubSearchPlaceholder`） |\n| `features[].code` | 功能唯一标识，打开时作为启动参数回传给插件 |\n| `features[].cmds` | 主搜索框关键词：字符串直接匹配（支持拼音、首字母）；对象可声明 `regex` \u002F `over` \u002F `img` \u002F `files` \u002F `window` 五种匹配规则 |\n| `permissions` | 平台能力路径，如 `[\"files.list\", \"ai.*\"]`，见[介绍](.\u002Fintroduction)的权限模型 |\n| `tauri` | 原生能力标识，如 `[\"dialog:default\", \"notification:default\"]` |\n| `plugins` | 跨插件调用白名单 |\n| `services[]` | 声明式服务进程（node \u002F python \u002F exe），配 `startup: \"open\" | \"manual\" | \"host\"` |\n| `startup` | `\"background\"` 随宿主后台启动 |\n| `exports` \u002F `events` | 对外暴露接口与事件的声明（同时会作为 MCP 工具暴露） |\n| `contextMenu[]` | Windows 资源管理器右键菜单注册 |\n\n#### 2.3 package.json\n\n```json\n{\n  \"name\": \"@udhold-plugin\u002Fmy-plugin\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"typecheck\": \"vue-tsc --noEmit\"\n  },\n  \"dependencies\": {\n    \"vue\": \"^3.5.13\",\n    \"@udhold\u002Fudhold-ui\": \"workspace:*\",\n    \"@udhold\u002Fudhold-api-types\": \"workspace:*\"\n  },\n  \"devDependencies\": {\n    \"@iconify\u002Futils\": \"^3.1.0\",\n    \"@unocss\u002Fpreset-attributify\": \"^66.6.6\",\n    \"@unocss\u002Fpreset-icons\": \"^66.6.6\",\n    \"@unocss\u002Ftransformer-directives\": \"^66.6.6\",\n    \"@vitejs\u002Fplugin-vue\": \"^5.2.1\",\n    \"typescript\": \"~5.6.2\",\n    \"unocss\": \"^66.6.6\",\n    \"vite\": \"^6.0.3\",\n    \"vue-tsc\": \"^2.1.10\"\n  }\n}\n```\n\n`tsconfig.json` 里加上类型包，`window.udhold.*` 就有完整代码提示：\n\n```json\n{\n  \"compilerOptions\": {\n    \"types\": [\"@udhold\u002Fudhold-api-types\"]\n  }\n}\n```\n\n#### 2.4 vite.config.ts\n\n```ts\nimport { defineConfig } from 'vite'\nimport vue from '@vitejs\u002Fplugin-vue'\nimport UnoCSS from 'unocss\u002Fvite'\nimport { fileURLToPath, URL } from 'node:url'\n\nexport default defineConfig({\n  base: '.\u002F',\n  \u002F\u002F 端口自定义，避开常用端口即可；strictPort 防止 vite 自行换端口导致宿主连不上\n  server: { port: 5261, strictPort: true, open: false },\n  plugins: [\n    vue(),\n    UnoCSS(),\n    {\n      \u002F\u002F 与内置插件对齐：允许 file:\u002Fudhold-icon: 资源源（指令图标协议）\n      name: 'configure-response-headers',\n      configureServer: (server) => {\n        server.middlewares.use((_req, res, next) => {\n          res.setHeader(\n            'Content-Security-Policy',\n            \"default-src * 'unsafe-inline' 'unsafe-eval' data: blob: udhold-icon: file:; img-src * data: blob: udhold-icon: file:;\"\n          )\n          next()\n        })\n      }\n    }\n  ],\n  resolve: {\n    optimizeDeps: { exclude: ['@udhold\u002Fudhold-ui'] },\n    ssr: { noExternal: ['@udhold\u002Fudhold-ui'] },\n    alias: {\n      '@': fileURLToPath(new URL('.\u002Fsrc', import.meta.url))\n    }\n  }\n})\n```\n\n> `@udhold\u002Fudhold-ui` 是源码直引包（无预构建产物），必须保留 `optimizeDeps.exclude` 与 `ssr.noExternal` 两项配置，否则 Vite 依赖预扫描会报错。\n\n#### 2.5 src\u002Fmain.ts 与 src\u002FApp.vue\n\n```ts\nimport { createApp } from 'vue'\nimport App from '.\u002FApp.vue'\nimport 'virtual:uno.css'\nimport '@udhold\u002Fudhold-ui\u002Fstyles\u002Fglobal.css'\nimport { setupThemeSync } from '@udhold\u002Fudhold-ui\u002Futils'\n\n\u002F\u002F 应用宿主主题（明暗 + 主题色），并注册后续变更监听\nsetupThemeSync()\n\ncreateApp(App).mount('#app')\n```\n\n```vue\n\u003Cscript setup lang=\"ts\">\nimport { ref } from 'vue'\nimport { Message, ConfirmDialog, useMessage } from '@udhold\u002Fudhold-ui\u002Fcomponents\u002Fcommon'\n\nconst { messageState, handleClose, handleAction, confirmState, handleConfirm, handleCancel } = useMessage()\nconst count = ref(0)\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cdiv class=\"p-4\">\n    \u003Ch1 class=\"text-base text-highlighted\">我的插件\u003C\u002Fh1>\n    \u003Cbutton class=\"btn-solid\" @click=\"count++\">点了 {{ count }} 次\u003C\u002Fbutton>\n  \u003C\u002Fdiv>\n\n  \u003C!-- 全局消息与确认弹窗，挂一次即可全局使用 -->\n  \u003CMessage :items=\"messageState\" @close=\"handleClose\" @action-click=\"handleAction\" \u002F>\n  \u003CConfirmDialog\n    v-model:visible=\"confirmState.visible\" v-model:extra-values=\"confirmState.extraValues\"\n    :title=\"confirmState.title\" :message=\"confirmState.message\" :type=\"confirmState.type\"\n    :confirm-text=\"confirmState.confirmText\" :cancel-text=\"confirmState.cancelText\" :extra=\"confirmState.extra\"\n    @confirm=\"handleConfirm\" @cancel=\"handleCancel\"\n  \u002F>\n\u003C\u002Ftemplate>\n```\n\n样式与组件的完整用法见[设计系统](\u002Fdocs\u002Fdevelopment\u002Fdesign-system\u002Ftokens)系列文档。\n\n## 第 3 步：运行调试\n\n1. 工程目录里启动 dev server：`pnpm dev`（向导创建的工程在「插件开发者」里点「运行调试」会自动完成安装依赖、启动、登记全流程）。\n2. 在「插件开发者」工作台选中工程，点「**运行调试**」。宿主会登记该工程并以 `development.main` 的地址直连 dev server——**改代码即时热更新（HMR），不用重启宿主**。\n3. 呼出主搜索框，输入你在 `cmds` 里声明的关键词（如「我的插件」），回车打开插件。\n\n调试要点：\n\n- `development.main` 只允许 `http:\u002F\u002Flocalhost:*` \u002F `127.0.0.1` 地址（安全限制，防远程页面注入）。\n- dev server 没启动时，宿主探测不到端口会**回退加载本地 dist 产物**——如果你看到的是旧界面，先确认 dev server 是否在跑、端口是否与 `development.main` 一致。\n- 「运行调试」的登记关系存在内存里，宿主重启后失效，重新点一次即可。\n- 免构建工程（无 `development.main`）以「链接」语义直接加载工程目录里的文件。\n\n## 第 4 步：调用宿主能力\n\n大多数宿主方法返回统一信封 `IpcResult\u003CT>`：`{ code, success, data, msg }`。`code !== 0` 即失败（403 = 权限未声明），失败**不会抛异常**，要靠检查 `code`：\n\n```ts\n\u002F\u002F 基础能力（免权限声明）\nudhold.dbStorage.setItem('launchCount', String((Number(udhold.dbStorage.getItem('launchCount')) || 0) + 1))\nudhold.shellOpenExternal('https:\u002F\u002Fudhold.cn')\nawait udhold.copyText('已复制的内容')\n\n\u002F\u002F 敏感能力：先在 plugin.json 声明 permissions，再按信封处理结果\nconst res = await udhold.clipboard.getHistory(1, 20)\nif (res.code !== 0) {\n  console.error('调用失败：', res.msg)   \u002F\u002F 403 → 检查 permissions 声明\n} else {\n  console.log('历史条目：', res.data)\n}\n```\n\n**启动参数**：用户从搜索框打开插件时，命中的 feature 的 `code` 会回传；跳转方通过 `router.push` 传的 `query` 也在其中。在生命周期钩子里读取：\n\n```ts\nudhold.plugin.onMounted((action) => {\n  \u002F\u002F action.code：命中的 feature 标识（缺省 'main'）\n  \u002F\u002F action.payload：启动参数（即 router.push 的 query）\n  \u002F\u002F action.from：唤起来源 main \u002F panel \u002F hotkey \u002F redirect \u002F workflow \u002F api\n  if (action.code === 'convert') {\n    const input = action.payload?.text ?? ''\n    \u002F\u002F ...\n  }\n})\n```\n\n**清理时机**：定时器、文件监听、服务进程一律在 `onBeforeUnmount` 里释放（宿主销毁前给 200ms 宽限）：\n\n```ts\nconst off = udhold.plugin.onBeforeUnmount(() => {\n  clearInterval(timer)\n})\n```\n\n## 第 5 步：打包与本地验证\n\n1. 构建产物。在插件工程目录执行：\n\n   ```bash\n   pnpm build\n   ```\n\n   产出 `dist\u002F` 目录。\n2. 打包规则由 `plugin.json` 的 `build` 字段决定：`[\"dist\"]` 只收录 dist 目录；缺省时收录整个插件根（自动排除 `node_modules`、`.git` 等）。`plugin.json` 与 `logo` 会固定打进包根。\n3. 在「插件开发者」的发布页选中工程，一键打包为 `my-plugin-v1.0.0.zip`。\n4. 本地验证：把 zip 发给测试者，在插件中心选「本地安装」导入（也支持双击安装），检查真实安装态下的表现。\n\n::callout{icon=\"i-lucide-info\" color=\"primary\"}\n免构建静态插件没有构建环节，`build` 声明 `[\".\"]` 或留空即可，发布页会直接按目录打包。\n::\n\n## 第 6 步：发布市场\n\n1. 确保已登录 UDhold 账号，且插件已在市场登记（向导创建建项目时自动完成；CLI 与手动搭建在发布页先「登记」）。\n2. 发布页上传 zip 包，填写版本说明，选择上架状态（先「测试」再转「正式」是常见的灰度节奏）。\n3. 等待审核：审核重点包括 `permissions` 与实际功能是否匹配、`plugins: ['*']` 等高风险声明、导出接口是否构成权限泄漏。\n4. 审核通过即上架，全平台用户可在插件市场搜到。\n5. 发新版本：改 `plugin.json` 的 `version` → 重新构建打包 → 上传。已安装用户**打开插件时宿主自动检查并静默更新**，无需手动催更。\n\n## 接下来\n\n功能逻辑跑通了，就该打磨界面了。去看[设计系统](\u002Fdocs\u002Fdevelopment\u002Fdesign-system\u002Ftokens)：一套设计令牌 + 现成组件，让你的插件和 UDhold 原生功能长得像一家人。想用 Cursor、Claude 等 AI 工具辅助编码，看 [LLMs.txt](\u002Fdocs\u002Fdevelopment\u002Fai\u002Fllms-txt)；卡住了先翻[常见问题](.\u002Ffaq)。\n",{"title":148,"description":4034},"dFbhu8Ya3oBv6kzhMt3XFjMbbbW6X8TVZqd9JCQscbI",[4042,4044],{"title":144,"path":145,"stem":146,"description":4043,"icon":19,"children":-1},"了解 UDhold 插件的运行机制、形态分类、能力域与权限模型。",{"title":152,"path":153,"stem":154,"description":4045,"icon":155,"children":-1},"插件开发中高频问题的排查手册：调试不生效、权限被拒、主题不跟随、打包缺文件等。",1793010251372]