关于 docyrus-app-dev-react
这项技能指导构建基于 Docyrus 的 React 和 TypeScript 应用,涵盖身份验证、数据访问、租户感知工具及界面工作流。内容还包括生成式集合、共享缓存、访问控制和开发工具的实现模式。
主要功能
- 01配置身份验证与应用 Provider
- 02通过生成的集合读取和修改数据
- 03共享租户级缓存与偏好设置
- 04构建 ACL、角色及记录共享流程
- 05持久化应用设置和已保存网格视图
- 06使用 Docyrus devtools 进行应用诊测
适用场景
- 01初始化 Docyrus React 应用
- 02实现数据驱动的表单和仪表板
- 03添加基于角色的访问与记录共享
- 04保存用户设置和网格视图
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ docyrus/ agent-skills --skill docyrus-app-dev-react安装后在 Claude Code 中输入/docyrus-app-dev-react确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/api-client-and-auth.mdapp-utils-readme.mdcollections-and-patterns.mdcomponent-selection-guide.mddevtools-readme.mdguidy-integration.mdhost-communication-integration.mdicon-usage-guide.mdpreferred-components-catalog.mdREADME.mdsignin-readme.md详细介绍
Docyrus App Dev React
端到端构建 Docyrus React TypeScript 应用。本技能将应用架构、身份验证、数据访问、查询模式和生产级 UI 指南整合于一处。
推荐技术栈
- React 19 + TypeScript + Vite
- TanStack Router(基于代码)、TanStack Query(服务端状态)、TanStack Form
- Tailwind CSS v4、shadcn/ui 组件
@docyrus/api-client+@docyrus/signin+@docyrus/app-utils@docyrus/devtools— 推荐在开发期间为每个 Docyrus 应用集成的开发者面板(网络、错误、问题、控制台、iframe 消息、OpenAPI 请求浏览器、DOM 元素选择器);仅在非生产构建中启用- 根据 OpenAPI 规范自动生成的集合
- 首选 UI 库:shadcn、diceui、animate-ui、docyrus-ui、reui
何时使用本技能
在以下情况下使用本技能:
- 构建或修改基于 Docyrus 的 React 应用
- 使用
@docyrus/signin设置身份验证 - 使用
@docyrus/app-utils初始化支持租户的运行时工具 - 使用自动生成的集合或
@docyrus/api-client获取或修改数据 - 使用
AppConfig、UserAppConfig和DataViews持久化应用级配置、用户级配置或已保存的网格视图 - 构建记录共享、角色管理或由 ACL 驱动的 UI 流程
- 设计功能 UI,例如仪表板、表单、表格、布局、对话框、分析或详情页面
- 在 shadcn、diceui、animate-ui、docyrus-ui 和 reui 组件之间进行选择
- 实现结合数据访问与精致 UI 的完整功能流程
端到端功能工作流
- 设置应用身份验证、路由和查询提供程序。
@docyrus/signin已从/v1/users/me获取已登录用户——通过useDocyrusAuth().user读取,不要自行添加用户请求。 - 在根组件附近挂载
@docyrus/devtools(仅限开发构建),并注册经过身份验证的客户端,以便从一开始就监控请求、错误和控制台。 - 登录后,创建一个共享的
InventoryClient(createInventoryClient),并在进度条下调用其load(),预热应用、数据源、用户、品牌、偏好设置和此应用的配置。 - 初始化
TenantPreferences、日期/数字工具和共享应用运行时辅助工具,并将共享 inventory 接入每个 app-utils 客户端。 - 使用自动生成的 Docyrus 集合 Hooks 或 REST 客户端访问数据。
- 正确配置
columns、筛选条件、公式、子查询和修改操作。 - 使用
AppConfig保存每个应用的持久化设置,使用UserAppConfig保存每个用户针对每个应用的设置,使用DataViews保存已保存的网格视图。 - 在自定义构建任何内容之前,先检查首选 UI 组件。
- 在创建、编辑、项目详情和可编辑网格流程中采用 Docyrus 表单和详情模式。
- 将 UI 操作连接到 TanStack Query 修改操作,并使相关查询失效。
快速开始:应用初始化
根级提供程序设置
import { DocyrusAuthProvider } from '@docyrus/signin'
<DocyrusAuthProvider
apiUrl={import.meta.env.VITE_API_BASE_URL}
clientId={import.meta.env.VITE_OAUTH2_CLIENT_ID}
redirectUri={import.meta.env.VITE_OAUTH2_REDIRECT_URI}
scopes={['offline_access', 'Read.All', 'DS.ReadWrite.All', 'Users.Read']}
callbackPath="/auth/callback"
>
<QueryClientProvider client={queryClient}>
<RouterProvider router={router} />
</QueryClientProvider>
</DocyrusAuthProvider>
身份验证门控和当前用户访问
const { status, user, hasRole, hasPermission } = useDocyrusAuth()
if (status === 'loading') return <Spinner />
if (status === 'unauthenticated') return <SignInButton />
// user is auto-fetched from /v1/users/me after authentication
// hasRole('super_admin') — check role by slug or uid
// hasPermission('edit', dataSourceId) — check ACL permission on a data source
@docyrus/signin 已经会获取已登录用户。 身份验证时,它会调用一次 /v1/users/me,并通过 useDocyrusAuth().user 提供结果(角色、权限、aclRules、身份信息)。从这里读取当前用户,并完成所有身份验证、角色和权限检查——绝不要自行添加 /v1/users/me 请求。角色变更后,调用 refreshUser() 重新获取用户信息。只有在需要获取身份验证用户中没有的个人资料字段时,才使用 useUsersCollection().getMyInfo()。
登录后预热清单缓存
@docyrus/signin 报告会话已认证后,立即从 @docyrus/app-utils 创建一个共享的 InventoryClient,并在进度条下调用 load()。清单是一个覆盖整个租户的内存缓存,包含应用、数据源(含嵌入的视图/表单/字段)、用户、品牌、租户偏好设置,以及此应用的 config/user-config。预热一次后,应用中几乎所有后续元数据读取都会命中缓存(无需网络请求),并且传递给它的所有 app-utils 客户端都会共用同一个实例。
在引导阶段创建唯一实例,并将其接入每个 app-utils 客户端:
// services/docyrus.ts — one cache, shared by every client
import {
createInventoryClient,
createDataSourceClient,
createBrandClient,
createAppConfigClient,
createUserAppConfigClient,
createDataViewClient,
} from '@docyrus/app-utils'
const appId = import.meta.env.VITE_APP_ID
export const inventory = createInventoryClient(apiClient)
export const dataSources = createDataSourceClient(apiClient, { inventory })
export const brands = createBrandClient(apiClient, { inventory })
export const appConfig = createAppConfigClient(apiClient, appId, { inventory })
export const userAppConfig = createUserAppConfigClient(apiClient, appId, { inventory })
// View/form clients are per data source — construct on demand, always sharing `inventory`
export const viewsFor = (appSlug: string, dsSlug: string) =>
createDataViewClient(apiClient, appSlug, dsSlug, { inventory })
登录后、跳转到主页前,预热一次缓存:
// Runs after useDocyrusAuth() reports an authenticated session.
async function bootstrapAfterSignIn(setProgress: (p: { label: string; value: number }) => void) {
await inventory.load({
// Drop 'users' from `include` if the signed-in user may lack the Users.Read.All scope.
onProgress: ({ message, ratio, phase }) => {
setProgress({ label: message, value: Math.round(ratio * 100) })
if (phase === 'complete') setProgress({ label: 'Ready', value: 100 })
},
})
}
- 登录后再创建清单——它需要经过身份验证的
apiClient。 - 将同一个
inventory传递给每个 app-utils 客户端,使它们共用一个缓存;通过这些客户端执行的变更会自动更新缓存。 load()会预热应用、数据源、用户、品牌和偏好设置;如果设置了VITE_APP_ID,还会加载此应用的 config/user-config;它会发出进度事件,供登录后的进度条使用。- 完整的页面重新加载会导致缓存变冷——因此每次登录后都会调用
load()。如果切换租户时没有重新加载页面,请调用inventory.refresh(),以新租户的数据替换旧数据。
有关 load() 选项、作用域处理和缓存失效辅助函数,请参阅 references/app-utils-readme.md 中的“createInventoryClient”部分。
租户感知型应用工具
使用 @docyrus/app-utils 作为运行时的默认层,以处理租户级格式化和持久化的应用/网格偏好设置。
import {
createAppConfigClient,
createUserAppConfigClient,
createDataViewClient,
createDateUtils,
createNumberUtils,
getTenantPreferences,
} from '@docyrus/app-utils'
function useAppRuntime(appId: string) {
const client = useDocyrusClient()
const { getMyInfo } = useUsersCollection()
return useQuery({
queryKey: ['app-runtime', appId],
enabled: !!client && !!appId,
queryFn: async () => {
const [preferences, me] = await Promise.all([
getTenantPreferences(client!),
getMyInfo(),
])
return {
preferences,
me,
dateUtils: createDateUtils({
preferences,
userTimezone: me.timeZone?.id,
}),
numberUtils: createNumberUtils({ preferences }),
appConfig: createAppConfigClient(client!, appId),
userConfig: createUserAppConfigClient(client!, appId),
dataViews: createDataViewClient(client!, appId),
}
},
})
}
使用此运行时来:
- 使用租户格式字符串和用户时区格式化日期和日期时间。
- 使用租户分隔符和精度格式化数字、类似货币的值和小数。
- 读取并更新应用唯一的持久化
AppConfig文档。 - 读取并更新当前用户的
UserAppConfig文档(每个用户针对每个应用的设置)。 - 通过
DataViews读取并持久化已保存的网格视图。
如果已预热共享清单(见上文),请将 { inventory } 传递给这些客户端,并通过 inventory.getPreferences() 读取 preferences,而不要新调用 getTenantPreferences(client)——这样每次读取都会从预热后的缓存中获取。
使用生成的集合获取数据
const { list } = useBaseProjectCollection()
const { data: projects } = useQuery({
queryKey: ['projects'],
queryFn: () =>
list({
columns: ['name', 'status', 'record_owner(firstname,lastname)'],
filters: { rules: [{ field: 'status', operator: '!=', value: 'archived' }] },
orderBy: 'created_on DESC',
limit: 50,
}),
})
ACL、角色和记录共享
ACL 功能请直接调用 useDocyrusClient()。这些路由可能不会显示在生成的 OpenAPI 输出中,因此通常无法通过生成的集合钩子使用。
const client = useDocyrusClient()
const { data: roles } = useQuery({
queryKey: ['acl', 'roles'],
queryFn: () => client!.get('/v1/users/acl/roles'),
})
const replaceUserRoles = useMutation({
mutationFn: ({ userId, roleIds }: { userId: string; roleIds: string[] }) =>
client!.put(`/v1/users/acl/users/${userId}/roles`, { roleIds }),
})
const createRoleQuery = useMutation({
mutationFn: (payload: Record<string, unknown>) =>
client!.post('/v1/users/acl/role-queries', payload),
})
发送用户角色更新或角色查询负载中的 roleIds 时,优先使用 API 返回的角色 uid 值。
已保存的数据网格视图
将 DataGridViewSelect 作为 Docyrus 网格默认的已保存视图 UI,并使用 createDataViewClient(client, appId) 持久化这些视图。
DataGridViewSelect是用于显示和编辑已保存网格视图的默认组件。- 通过
table传入 TanStack 表格实例,以便选择器/编辑器读取列定义。 - 如果要在编辑器中启用内置筛选器构建器,请传入
fields。 - 使用
DataViewsCRUD 操作处理views、onViewCreate、onViewSave、onViewDelete、onViewHide和onViewUnhide。 - 仅当需要在选择器之外单独使用编辑器时,才单独使用
DataGridViewEditor。
使用 @docyrus/devtools 进行开发工具配置
在每个 Docyrus 应用中接入 @docyrus/devtools。它会挂载一个浮动触发器和一个停靠面板,面板包含 Network、Errors、Issues、Explore、Console 和 Messages 标签页,可监测 @docyrus/api-client 请求(并检测重复和缓慢请求)、TanStack Query 问题、控制台输出,以及 iframe ↔ 宿主的 postMessage 流量;还提供由 OpenAPI 驱动的请求探索器,可通过应用经过身份验证的客户端重放端点。
import { DocyrusDevtools, useRegisterDocyrusClient } from '@docyrus/devtools'
import { DocyrusAuthProvider, useDocyrusClient } from '@docyrus/signin'
function RegisterDevtoolsClient() {
// Register the auth-managed client once it exists so requests are instrumented.
useRegisterDocyrusClient(useDocyrusClient())
return null
}
export function App() {
return (
<QueryClientProvider client={queryClient}>
{/* enabled gates ALL instrumentation — keep devtools out of production */}
<DocyrusDevtools enabled={import.meta.env.DEV} queryClient={queryClient} openApiSpecPath="/openapi-spec.json">
<DocyrusAuthProvider apiUrl={/* … */} clientId={/* … */}>
<RegisterDevtoolsClient />
<YourRoutes />
</DocyrusAuthProvider>
</DocyrusDevtools>
</QueryClientProvider>
)
}
- 使用
enabled={import.meta.env.DEV}控制是否启用(也可以通过activationShortcut将其设为休眠状态,以便在生产环境中按需启用)。当enabled为false时,它只会渲染子元素,不会注册监听器,也不会显示界面。 - 传入现有的
queryClient,以便在Issues标签页中显示 TanStack Query 问题。 - 在挂载后调用
useRegisterDocyrusClient(useDocyrusClient()),以便在身份验证管理的客户端就绪后立即对其进行监测。 - 将
openApiSpecPath指向已提供服务的规范文件,以启用请求探索器。
完整的属性列表、宿主桥接、iframe 消息监听、DOM 元素选择器,以及 CDP/Agent 页面内 API,请参阅 references/devtools-readme.md。
应用/数据关键规则
- 在
.list()和.get()调用中始终传入columns。否则只会返回id。 - 集合是 React hooks——在 React 组件中调用
useBaseProjectCollection()、useUsersCollection()及类似钩子。 - 数据源端点是动态的——只有在租户 OpenAPI 规范中定义了数据源时,它们才会存在。
- 计算
count时使用id。计算sum、avg、min和max时使用实际字段 slug。 - 子查询键必须出现在
columns中。 - 公式键必须出现在
columns中。 - 从
useDocyrusAuth().user读取已登录用户——@docyrus/signin会在登录时从/v1/users/me获取该用户(角色、权限、aclRules、身份)。切勿自行添加/v1/users/me调用;角色更改后使用refreshUser(),只有在需要获取认证用户中没有的个人资料字段时才使用useUsersCollection().getMyInfo()。 - 每个应用运行时只初始化一次
TenantPreferences,并从@docyrus/app-utils创建共享的dateUtils/numberUtils实例。 @docyrus/app-utils中的格式化函数会根据区域设置调整——当租户偏好设置应决定格式时,不要硬编码区域设置、日期格式、小数分隔符、千位分隔符或小数精度。- 使用
createAppConfigClient(client, appId)处理应用唯一的持久化配置文档;默认写入方式为upsert。 - 使用
createUserAppConfigClient(client, appId)处理当前用户在应用范围内的持久化配置文档(例如主题、布局偏好、侧边栏状态);默认写入方式为upsert。 - 使用
createDataViewClient(client, appId)执行已保存网格视图的 CRUD 操作。 - 使用
DataViews和DataGridViewSelect来显示、创建、编辑、重新排序、隐藏、取消隐藏、软删除和硬删除已保存的数据网格视图。 DataGridViewSelect需要 TanStack 表格实例;如果要使用内置筛选器构建器/编辑器体验,还应传入fields。- 创建数据视图时必须提供
name和tenant_data_source_id。 - 使用
dataViews.update(viewId, { archived: true })执行软删除;仅在需要不可逆的硬删除时使用dataViews.remove(viewId)。 - 架构更改后重新生成集合:重建租户 OpenAPI 规范,下载最新的
openapi.json,然后重新运行集合生成器。 - ACL 端点通常通过原始客户端集成——使用
useDocyrusClient()或RestApiClient处理角色、用户角色分配、角色查询、记录共享和所有权转移。 - 在 ACL 角色写入、用户角色
roleIds和角色查询roleIds中,优先使用角色uid值。 - 将
PUT /v1/users/acl/users/:userId/roles视为完全替换操作,将POST /v1/users/acl/users/:userId/roles视为追加操作。 - 角色查询的
query应以原始 JSON 形式发送;当存在dataSourceId时,省略tenantAppId,后端会自动推导。 - 删除角色后,使依赖的应用查询缓存失效,包括角色列表、用户角色列表、角色查询列表,以及任何用于呈现主角色标签的 UI。
- 登录后创建一个共享的
InventoryClient并调用其load()——将这同一个实例传递给每个 app-utils 客户端,以便它们共享预热后的缓存;切换租户时调用inventory.refresh()。 - 在开发构建中挂载
@docyrus/devtools,使用enabled={import.meta.env.DEV}控制是否启用,传入应用的queryClient,并使用useRegisterDocyrusClient(useDocyrusClient())注册认证客户端。
关键 UI/UX 规则
- 创建自定义组件前,务必先检查首选组件。
- 仪表板使用
AwesomeCard,除非用户明确要求其他卡片样式。 - 应用布局使用 animate-ui 的
Sidebar,除非用户要求其他布局。 - 一般功能 UI 中的图表优先使用 Recharts。**例外情况——仪表板/分析/报告:**使用 docyrus-dashboard-design 技能,该技能要求使用 Bklit UI 图表、
AwesomeCard面板和AwesomeStatsKPI 卡片。 - 按以下顺序选择图标:hugeicons,然后是 fontawesome light,最后是 lucide。
- 创建条目表单使用
AwesomeDialog。- 简单的小型表单:
container="sheet",并设置side="right" - 较长或复杂的表单:
container="modal"或container="drawer"
- 简单的小型表单:
- 根据条目复杂度选择详情容器。
- 大型条目:专用页面
- 小型条目:
AwesomeDialog右侧 sheet
- 所有表单都必须使用 TanStack Form + Docyrus 表单系统。不要直接使用原生 HTML 表单或 React Hook Form 构建功能表单。
- 条目详情视图中的内联编辑使用
EditableRecordDetail。 - 可编辑详情和网格体验始终启用
trackChanges。 - 已保存的网格视图使用
DataGridViewSelect,并通过@docyrus/app-utils中的DataViews提供支持。 - 仅在选择器组件之外需要独立的网格视图编辑器时,才优先使用
DataGridViewEditor。
默认 UI 选项
| 使用场景 | 默认组件 | 库 |
|---|---|---|
| 条目创建表单 | AwesomeDialog | docyrus |
| 快速创建记录 | CreateRecordDialog | docyrus |
| 条目详情(小型) | AwesomeDialog 右侧 sheet | docyrus |
| 条目详情(大型) | 专用页面 | — |
| 内联编辑 | EditableRecordDetail | docyrus |
| 仪表板卡片 | AwesomeCard | docyrus |
| 统计仪表板 | AwesomeStats | docyrus |
| 应用导航 | Sidebar | animate-ui |
| 数据表格 | DataTable | diceui |
| 可编辑网格 | Data Grid | docyrus |
| 网格已保存视图 | DataGridViewSelect + DataViews | docyrus + @docyrus/app-utils |
| 表单 | Docyrus 表单字段 + TanStack Form | docyrus |
| 图表(一般用途) | shadcn chart + Recharts | shadcn |
| 仪表板/分析/KPI | Bklit 图表 + AwesomeCard + AwesomeStats(参见 docyrus-dashboard-design) | bklit + docyrus |
| 文件上传 | File Upload | diceui |
| 甘特图/项目排期 | Gantt | docyrus |
| 资源排期 | ResourceSchedulerPanel | docyrus |
| 团队聊天 | TeamChatChannel | docyrus |
| AI 界面 | DocyrusAgent | docyrus |
| 定价/报价 | PricingEnginePanel | docyrus |
| 分析/数据透视 | PivotGrid | docyrus |
快速 UI 模式
条目创建表单
<AwesomeDialog open={open} onOpenChange={setOpen} container="sheet" side="right" size="default">
<AwesomeDialogHeader title="Create Task" icon="far-plus" />
<AwesomeDialogBody>
<form.Field name="title">{(field) => <TextFormField field={field} label="Title" />}</form.Field>
<form.Field name="status">{(field) => <SelectFormField field={field} label="Status" />}</form.Field>
</AwesomeDialogBody>
<AwesomeDialogFooter>
<Button variant="outline" onClick={() => setOpen(false)}>Cancel</Button>
<Button onClick={handleSubmit}>Create</Button>
</AwesomeDialogFooter>
</AwesomeDialog>
带内联编辑的条目详情
<AwesomeDialog open={open} onOpenChange={setOpen} container="sheet" side="right" size="lg" fullscreenable>
<AwesomeDialogHeader
title="Task Detail"
description="Review and edit task fields inline"
headerButtons={<Button variant="outline" size="sm" onClick={switchToFullForm}>Edit All</Button>}
/>
<AwesomeDialogBody>
<EditableRecordDetail fields={fields} record={record} onSave={handleSave} trackChanges>
<EditableRecordDetailField slug="title" />
<EditableRecordDetailField slug="status" />
<EditableRecordDetailField slug="assignee" />
<EditableRecordDetailField slug="due_date" />
</EditableRecordDetail>
</AwesomeDialogBody>
</AwesomeDialog>
TanStack Query 模式
function useProjects(params?: ICollectionListParams) {
const { list } = useBaseProjectCollection()
return useQuery({
queryKey: ['projects', 'list', params],
queryFn: () => list({ columns: PROJECT_COLUMNS, ...params }),
})
}
function useCreateProject() {
const { create } = useBaseProjectCollection()
const qc = useQueryClient()
return useMutation({
mutationFn: (data: Record<string, unknown>) => create(data),
onSuccess: () => {
void qc.invalidateQueries({ queryKey: ['projects'] })
},
})
}
集合 CRUD 方法
const { list, get, create, update, delete: deleteOne, deleteMany } = useBaseProjectCollection()
list(params?: ICollectionListParams)
get(id, { columns })
create(data)
update(id, data)
deleteOne(id)
deleteMany({ recordIds })
API 端点模式:/v1/apps/{appSlug}/data-sources/{slug}/items
查询功能摘要
.list() 方法支持:
columnsfiltersfilterKeywordorderBylimit和offsetfullCountcalculationsformulaschildQueriespivotexpand
组件安装模式
pnpm dlx shadcn@latest add button
pnpm dlx shadcn@latest add @diceui/data-table
pnpm dlx shadcn@latest add @animate-ui/sidebar
pnpm dlx @docyrus/cli add @docyrus/ui-awesome-card
pnpm dlx shadcn@latest add @reui/file-upload-default
参考资料
如需深入了解,请阅读:
references/README.md— 应用开发和 UI 设计综合参考索引references/api-client-and-auth.mdreferences/collections-and-patterns.mdreferences/signin-readme.md—@docyrus/signin软件包的完整 README(身份验证提供方、钩子、iframe/宿主桥接、SSR、角色与权限)。已在 npm 上发布为@docyrus/signin;源代码位于docyrus-devkit/packages/signinreferences/host-communication-integration.md— 嵌入式应用 ↔ 宿主外壳的postMessage集成,不包括 Guidy:宿主→应用导航(useDocyrusHostNavigation)和通知(useDocyrusHostNotification)、应用→宿主路由同步(syncRouteToHost/useDocyrusHostRouteSync/notifyRouteChange)和导航请求(requestHostNavigation)、来源验证、Vue 对应实现references/guidy-integration.md— 让嵌入式应用兼容 Guidy(由宿主 AI 助手操控应用的 UI):enableGuidyBridge、可定位的控件(稳定 ID + 无障碍标签)以及已声明的路由(guidyRoutes/useDocyrusGuidyRoutes);路由还需要使用宿主通信参考资料中的useDocyrusHostNavigationreferences/app-utils-readme.md—@docyrus/app-utils软件包的完整 README(租户偏好设置、日期/数字格式化、应用/用户配置、数据视图/表单、数据源元数据和 Inventory Cache)。已在 npm 上发布为@docyrus/app-utils;源代码位于docyrus-devkit/packages/app-utilsreferences/devtools-readme.md—@docyrus/devtools软件包的完整 README(应用内开发面板、请求/控制台/消息检测、OpenAPI 浏览器、元素选择器、CDP/Agent API)。已在 npm 上发布为@docyrus/devtools;源代码位于docyrus-devkit/packages/devtools- docyrus-app-settings 技能 — 使用
createAppConfigClient/createUserAppConfigClient设计和使用应用级(AppConfig)及用户级(UserAppConfig)设置文档:作用域选择、整体替换和空文档注意事项,以及 REST/CLI 合约 - docyrus-acl-design 技能 — ACL 角色、权限和角色查询(
docyrus acl);以及 docyrus-api-dev 的 SKILL.md 中的 ACL REST 端点 ../docyrus-api-dev/references/data-source-query-guide.md../docyrus-api-dev/references/formula-design-guide-llm.md../docyrus-api-dev/references/query-guide.mdreferences/preferred-components-catalog.mdreferences/component-selection-guide.mdreferences/icon-usage-guide.md