# UDhold — 完整文档
> 站点: https://udhold.cn · 索引: https://udhold.cn/llms.txt
---
# LLMs.txt
来源: https://udhold.cn/docs/development/ai/llms-txt
[llms.txt](https://llmstxt.org) 是一个专为大型语言模型设计的站点索引文件,思路类似 `robots.txt`,但目标不同:robots.txt 告诉搜索引擎爬虫「什么能爬」,llms.txt 则为 AI 工具提供网站内容的结构化摘要,帮助它们更快、更准地理解和引用文档。
UDhold 开发文档已全量适配这一标准,并且**随文档更新自动同步**——你读到这篇指南时,AI 拿到的就是最新内容。
## 可用资源
| 地址 | 内容 | 适合场景 |
|------|------|----------|
| [https://udhold.cn/llms.txt](https://udhold.cn/llms.txt) | 全站结构化索引:每个文档页的标题、链接与一句话简介 | 加入工具的文档索引、让 AI 先知道「有什么」 |
| [https://udhold.cn/llms-full.txt](https://udhold.cn/llms-full.txt) | 全部文档的 Markdown 全文(含 plugin.json 契约、API 用法、完整示例代码) | 一次性投喂给 AI,或接入上下文知识库 |
本地开发调试时同样可访问:`http://localhost:7013/llms.txt`。
## 在 AI 工具中使用
### Cursor
1. 打开 `Settings` → `Indexing & Docs` → `Docs` → `Add doc`
2. 填入 `https://udhold.cn/llms-full.txt`,保存
3. 编码时用 `@Docs` 引用,例如:
```text
@Docs 按 UDhold 插件契约帮我生成一个「待办清单」插件的工程骨架,
包含 plugin.json、Vue 3 入口和一个待办列表页面。
```
### TRAE
1. 打开「设置」→「文档集」(或对话输入框的 `#Docs` 上下文)
2. 添加文档集,URL 填 `https://udhold.cn/llms-full.txt`
3. 对话时 `#` 选中该文档集即可引用
### Claude Code / Codex 等 CLI 编码代理
在项目(或全局)的 `AGENTS.md` / 规则文件里加一行指引,代理会在开发 UDhold 插件前主动抓取文档:
```markdown
## UDhold 插件开发
开发 UDhold 插件相关代码前,先读取 https://udhold.cn/llms-full.txt 了解
plugin.json 契约、权限模型与设计系统,再动手写代码。
```
### 网页版 AI 对话(Claude / ChatGPT 等)
- 支持联网的模型:直接把 `https://udhold.cn/llms-full.txt` 链接发给它,让它基于文档回答
- 不联网的模型:先打开 llms.txt 找到相关章节,把对应文档页内容粘贴进对话
### 其他工具
任何支持 llms.txt 标准或 URL 摄取的工具(知识库、RAG 管道、IDE 插件等)都可以直接使用上面两个地址,无需额外适配。
## 让 AI 写出能跑的插件
投喂文档只是第一步,提问方式决定产出质量:
- **先文档后代码**:让 AI 先通读 llms-full.txt 再动手,避免它按 uTools 或浏览器扩展的旧经验瞎编 API
- **点明两件事**:宿主方法统一返回 `IpcResult` 信封(失败不抛异常,要检查 `code`);敏感能力必须在 `plugin.json` 的 `permissions` 里声明
- **要完整骨架**:让 AI 按「目录结构 → plugin.json → package.json → 入口文件」的顺序输出,与[快速上手](/docs/development/quick-start/getting-started)的工程结构对齐,生成后可直接进宿主调试
## 延伸阅读
- [llmstxt.org](https://llmstxt.org):llms.txt 标准规范
- [快速上手](/docs/development/quick-start/getting-started):跟着文档走一遍完整开发流程
---
# 基础样式类
来源: https://udhold.cn/docs/development/design-system/base-styles
`global.css` 除了设计令牌,还内置了一组高频控件的样式类。轻量插件直接写 class 就有合格的控件外观,不必引组件库、不必手写样式;重度界面则可以与组件库配合使用。
## 按钮
```html
```
| 类 | 说明 |
|----|------|
| `.btn` | 中性按钮:内嵌底色 + 发丝线描边,hover 反馈 |
| `.btn-solid` | 主色实心,一屏最多出现一个(主操作) |
| `.btn-danger` | 危险色实心,用于删除等不可逆操作 |
| `.btn-sm` | 小尺寸修饰,可与上面任意组合 |
| `.icon-btn` | 28×28 透明图标按钮,配图标类使用 |
## 表单
```html
```
| 类 | 说明 |
|----|------|
| `.input` | 文本输入框:`--field` 底色、聚焦时主色光圈(`--focus-ring`) |
| `.select` | 下拉框:与 `.input` 同构,原生弹出面板跟随系统明暗 |
| `.toggle` + `.toggle-slider` | 开关:checkbox 驱动,选中态主色。两个元素必须成对出现 |
## 卡片与浮层
```html
```
| 类 | 说明 |
|----|------|
| `.card` | `--surface` 底色 + `--radius-lg` 圆角,内容区最常用的容器 |
| `.floating-shell` / `.floating-panel` | 无边框浮窗形态:大圆角 + 四周留边投影,做脱离宿主的悬浮小窗时使用 |
## 全局细节
这些是 `global.css` 顺手处理好的事,知道即可,不用自己做:
- **高度链**:`html`、`body`、`#app` 均为 `height: 100%`,插件根布局可以直接用百分比高度撑满。
- **正文排版**:`body` 上设定 14px / 1.5 倍行距 / `--ink` 文字色 / `--bg-color` 底色。
- **文本选中**:选中态是主色 22% 透明度,不再是默认的浏览器蓝。
- **键盘焦点**:`:focus-visible` 显主色焦点环(鼠标点击不显示,键盘导航才显示)。
- **滚动条**:6px 窄滚动条,圆角 thumb,hover 加深,track 透明——与宿主完全一致。
## 与 UnoCSS 配合
工程里配好 UnoCSS 后(见[图标体系](./icons)的完整配置),原子类与这组样式类可以混用:
```html
```
::callout{icon="i-lucide-info" color="primary"}
`.toggle` 与 `.toggle-slider` 必须相邻(样式选择器是 `input:checked + .toggle-slider`),中间插别的元素开关就不动了。
::
控件之外还需要更复杂的组件(消息提示、确认弹窗、快捷键录制……)?看[通用组件](./components)。
---
# 通用组件
来源: https://udhold.cn/docs/development/design-system/components
`@udhold/udhold-ui` 是官方共享组件库,随官方插件工程仓库分发(`workspace:*` 引用,见[快速上手](../quick-start/getting-started))。组件按需 import,没有全局注册,样式与令牌体系一体。
## 引入方式
```ts
// 组件
import { Message, ConfirmDialog, Dropdown, Slider } from '@udhold/udhold-ui/components/common'
// 或分别引:'@udhold/udhold-ui/components/Message'
// 组合式函数与工具
import { useMessage } from '@udhold/udhold-ui/components/common'
import { useColorScheme } from '@udhold/udhold-ui/composables'
```
## Message:全局消息提示
**挂载一次,全局调用。** 根组件里挂容器(`useMessage()` 返回的响应式状态接给组件),之后任何地方 `useMessage()` 直接弹消息:
```vue
```
```ts
// 任何业务组件里
import { useMessage } from '@udhold/udhold-ui/components/common'
const message = useMessage()
message.success('已复制颜色 #2f6fec')
message.error('导出失败:文件被占用')
message.warning('列表已过期,正在刷新')
message.info('已切换到紧凑模式')
```
| 参数 | 说明 |
|------|------|
| `type` | `success` / `error` / `warning` / `info` / `primary`,对应语义前置圆点 |
| `duration` | 停留时长,默认 3000ms |
| `position` | `top` / `bottom` |
## ConfirmDialog:确认弹窗
与 `useMessage()` 同源,命令式调用,返回 Promise——不用自己管理弹窗状态:
```ts
const { confirm, confirmWithExtra, alert } = useMessage()
// 二选一确认
const ok: boolean = await confirm({
title: '删除记录',
message: '删除后不可恢复,确定删除这 3 条记录吗?',
type: 'danger', // info / warning / danger,控制确认按钮风格
confirmText: '删除'
})
if (ok) { /* 执行删除 */ }
// 带附加复选项(如「同时删除云端数据」)
const result = await confirmWithExtra({
title: '卸载插件',
message: '将删除插件及其全部数据。',
type: 'danger',
extra: [{ id: 'keepData', message: '保留插件数据', defaultChecked: false }]
})
// result.confirmed: boolean, result.extra: { keepData: boolean }
// 纯提示(单按钮)
await alert({ title: '导入完成', message: '共导入 128 条记录。' })
```
容器同样在根组件挂一次:``,模板见上面 Message 的 App.vue 示例。
## Dropdown:下拉选择
原生 `select` 的样式化封装(弹出面板跟随系统明暗):
```vue
```
## HotkeyInput:快捷键录制
点击进入录制态,按下组合键即完成录入,支持修饰键组合(含 400ms 内双击同一修饰键,如 `Ctrl+Ctrl`)与 F1–F12:
```vue
```
优先走宿主后端录制(结果与全局快捷键注册系统一致),宿主不支持时自动回退前端按键监听;不支持的按键会以 toast 提示。
## Slider:滑杆
```vue
```
轨道已按主色渐变渲染,无需额外样式。
## DetailPanel:二级详情面板
覆盖在内容区上方的二级页面(无遮罩、带滑入过渡),配「返回」顶栏——列表页点进详情页的标准形态:
```vue
```
组件自带 `slide` / `slide-reverse` 过渡类,供 `` 做一级↔二级切换动画。
::callout{icon="i-lucide-info" color="primary"}
`DetailPanel` 内部使用 `i-z-back` 图标——你的工程图标集里必须有 `back.svg`(见[图标体系](./icons)),否则返回按钮空白。
::
## AdaptiveIcon:自适应位图图标
位图 logo 在暗色模式下会隐形的痛点,交给它处理:自动分析图片主色,需要时反色:
```vue
```
懒分析(进入视口前 100px 才开始),`forceAdaptive` 属性可跳过检测强制暗色反色。
## 工具函数
`@udhold/udhold-ui/utils` 里几个高频工具:
| 函数 | 用途 |
|------|------|
| `setupThemeSync()` | 主题联动总入口([主题与明暗模式](./theming)) |
| `isDarkMode()` | 同步判断当前是否暗色 |
| `weightedSearch(items, query, fields)` | 多字段加权搜索:`fields` 里给每个字段配权重,命中累加按分数排序,做插件内列表过滤很好用 |
| `setupPlatformClass()` | 给 `html` 加 `os-windows` / `os-mac` / `os-linux` 类,CSS 里做平台差异适配 |
```ts
import { weightedSearch } from '@udhold/udhold-ui/utils'
const result = weightedSearch(commands, keyword, [
{ value: c => c.name, weight: 3 },
{ value: c => c.description, weight: 1 }
])
```
更高层的场景组件(加载态、搜索列表、代码块、侧边导航)看下一篇[场景组件](./scene-components)。
---
# 图标体系
来源: https://udhold.cn/docs/development/design-system/icons
UDhold 插件的图标方案是**本地 SVG 图标集 + UnoCSS**:图标文件放在自己工程里、离线可用、构建时内联、颜色自动跟随主题。这一章给出完整配置与用法。
## 图标跟随主题的原理
图标加载器会把 SVG 的 `fill` / `stroke` 替换成 `currentColor`:
```html
```
于是图标的颜色 = 所在元素的 `color`。文字是 `var(--ink)`,图标就是 `--ink`;放在主色按钮里就是主色;暗色主题自动反色,零额外代码。
## 工程配置
**第一步**:SVG 图标放进 `src/assets/icons/`,文件名即图标名:
```
src/assets/icons/
├── back.svg
├── copy.svg
└── search.svg
```
**第二步**:`uno.config.ts` 注册图标集:
```ts
import { defineConfig, presetAttributify, presetWind3 } from 'unocss'
import presetIcons from '@unocss/preset-icons'
import { FileSystemIconLoader } from '@iconify/utils/lib/loader/node-loaders'
import { fileURLToPath, URL } from 'node:url'
import transformerDirectives from '@unocss/transformer-directives'
export default defineConfig({
presets: [
presetWind3(),
presetAttributify(),
presetIcons({
collections: {
// z 图标集:本插件 src/assets/icons 目录
z: FileSystemIconLoader(
fileURLToPath(new URL('./src/assets/icons', import.meta.url)),
(svg: any) => {
// fill/stroke 替换为 currentColor,跟随主题色
return svg
.replace(/(
```
::callout{icon="i-lucide-info" color="primary"}
官方组件库的 `DetailPanel` 组件内部使用了 `i-z-back` 图标——使用它的插件,自己的图标集里必须包含 `back.svg`(文件名一致),否则返回按钮不显示。
::
## 位图图标的自适应
`logo.png`、第三方服务的图标等**位图**没有 `currentColor` 可言,暗色主题下深色图标会隐形。这种情况用组件库的 `AdaptiveIcon` 组件:它自动分析图片主色,在暗色模式下给深色图标做反色处理。用法见[通用组件](./components)。
另外,宿主有一套 `udhold-icon:` 资源协议用于指令图标;开发态直连 dev server 时需要在 `vite.config.ts` 里加 CSP 中间件放行该协议——工程模板(见[快速上手](../quick-start/getting-started)的 vite 配置)已包含这段配置。
## 插件 logo 规范
`plugin.json` 里的 `logo` 字段(png / jpg,放插件根目录,与 `plugin.json` 同级):
- 建议正方形、透明底、256×256 以上;
- 它会出现在搜索结果、活动栏、插件中心、任务栏(分离窗口)等多个位置,过于细长的图会被压变形;
- 深色 logo 记得同时准备浅色环境下的表现,或直接用中性色系。
---
# 场景组件
来源: https://udhold.cn/docs/development/design-system/scene-components
场景组件(beautiful 系列)解决特定页面形态的问题:等待、检索、代码展示、多栏导航。它们与宿主的视觉语言同源,用对了插件气质立刻对味。
## LoadingState:加载态
像素风格的加载动画,三形态可选手式,内置耗时计时与减少动态偏好(`prefers-reduced-motion`)适配:
```vue
```
**与 plugin.json 联动**:清单里的 `loading` 字段声明的就是这套视觉——
```json
{ "loading": { "variant": "Drive", "label": "加载中" } }
```
它解决的是 webview 创建到插件挂载 `#app` 之间的白屏期:宿主直接注入纯 CSS 版骨架,插件 mount 后自动消失,零接入成本。`LoadingState` 组件则用于插件**运行中**的异步等待场景(请求返回前的占位、切换数据源的过渡),两者互补。
## SearchList:搜索列表
带搜索框、空态、清空按钮的列表容器,输入即过滤(包含匹配),选中高亮动画:
```vue
```
| 参数 | 说明 |
|------|------|
| `items` | 字符串数组(复杂对象先用 `weightedSearch` 过滤出标签再传入) |
| `previewCount` | 无输入时默认展示的条数 |
| 空态 | 自定义 `empty-title` / `empty-hint` |
## CodeBlock:代码块
行号 + 复制按钮的代码展示,支持流式输出(AI 场景):
```vue
```
## SidebarNav:分组侧边导航
分组侧栏(滑动高亮浮层、徽标、可选的工作区行 / 搜索框 / 主操作按钮):
```vue
```
`items` 不带 `section` 的归入默认组「常用」;`embedded` 属性去掉卡片外壳,让导航融入你自己的容器。
## 取材与扩展
组件库的 `components/beautiful/raw/` 目录还保留着约 20 个**原始参考组件**(对话页、思维链状态、任务行、差异对比表、筛选表格等),它们是未受控的源码参考——带演示数据、不能直接 import。想用其中某个:
1. 从 `raw/` 复制到你的插件工程(或提 PR 受控化进组件库);
2. 剥离演示数据,改造成 `props` / `emits` 驱动;
3. 样式里只消费设计令牌(缺失的令牌补到全局体系,不要在组件内写死色值)。
这套「受控化」流程与官方维护组件库的方式一致,改造后的组件在明暗主题下天然可用。
## 设计系统小结
到这里,令牌 → 主题 → 样式类 → 图标 → 组件的完整链路就走完了。回到你的插件:先把[快速上手](../quick-start/getting-started)的工程骨架搭起来,遇到界面问题再回到对应章节查参考。祝开发顺利!
---
# 主题与明暗模式
来源: https://udhold.cn/docs/development/design-system/theming
设计令牌的两套值(亮 / 暗)靠 `html` 上的 class 切换。这一章讲清楚切换机制,以及插件接入主题联动的标准做法。
## 切换机制
体系支持三条通道,优先级从高到低:
| 通道 | 触发方式 | 效果 |
|------|----------|------|
| 强制暗色 | `html.dark` | 应用整套暗色变量,`color-scheme: dark` |
| 强制亮色 | `html.light` | 应用亮色变量,`color-scheme: light` |
| 跟随系统 | 无 class | 按系统 `prefers-color-scheme` 自动切换 |
`color-scheme` 同时让原生控件(`