文档权限面板
SharePoint 权限页范式的资源级 ACL 面板:继承 banner 三态(继承含父链 / 已断继承警示 / 例外 N 项 is-partial)、授权行主体五类(user/group/org/anyone/link,组行带「24 成员 · 由 IT 管理」注记)、显式 deny 一票否决置顶红(order:-1)、Limited Access 类系统行不可删(is-system 隐藏删除钮)、链接授权带范围与到期(is-expiring)、exposureCount 过度授权警示「对 1,204 人可见」(不去重计数)。renderKbAcl(el, model, opts?) 快照渲染;求值语义(先显式 deny → allow 并集 → 默认拒绝)由 kb-core evaluateAcl 提供。
继承自:公司库 › 财务部空间
竞对黑名单
拒绝
finance-team
可编辑
Limited Access
可查看
deny 行置顶红 · 组织内链接行 2026-11-01 到期(is-expiring)· 系统行无删除钮 · 底部「对 1,204 人可见」为过度授权警示
<div id="kb-acl-demo"> <section class="kb-acl"> <div class="kb-acl-inherit">继承自:公司库 <span class="kb-acl-chain-link">›</span> 财务部空间 <span class="kb-meta">例外 1 项</span></div> <div class="kb-acl-grant is-deny"> <span class="kb-acl-subject" data-kind="user">竞对黑名单</span> <span class="kb-acl-role kb-chip">拒绝</span> <span class="kb-acl-meta">直接 · 一票否决</span> </div> <div class="kb-acl-grant"> <span class="kb-acl-subject" data-kind="group">finance-team</span> <span class="kb-acl-role kb-chip">可编辑</span> <span class="kb-acl-meta">继承自 财务部空间 · 24 成员 · 由 IT 管理</span> </div> <div class="kb-acl-grant is-system"> <span class="kb-acl-subject" data-kind="org">Limited Access</span> <span class="kb-acl-role kb-chip">可查看</span> <span class="kb-acl-meta">系统管理 · 不可手工增删</span> </div> <footer class="kb-acl-foot"> <span class="kb-meta">对 <span class="kb-num">1,204</span> 人可见</span> </footer> </section></div><p class="demo-label" id="kb-acl-log" style="margin-top:8px">deny 行置顶红 · 组织内链接行 2026-11-01 到期(is-expiring)· 系统行无删除钮 · 底部「对 1,204 人可见」为过度授权警示</p> 安装
bun add @icen.ai/ui pnpm add @icen.ai/ui npm install @icen.ai/ui yarn add @icen.ai/ui 一行引入该组件(CSS 与 behavior 自动带上,无需关心内部 CSS 文件名):
import '@icen.ai/ui/kit/kb-acl'; 也可以用脚手架直接打印引入行:
bunx --bun @icen.ai/ui add kb-acl
Astro 项目注意:kit 入口里的 CSS import 在页面 <script> 里会被 Astro 的 client bundle 摇掉——请改在布局 frontmatter 里引 CSS(import '@icen.ai/ui/components/kb-perm.css';),JS 行为仍可走 kit。Vite SPA / webpack 项目无此问题。
用法
import { renderKbAcl } from '@icen.ai/ui/kit/kb-acl'; const request = { resource: '2026 财务规划', parentChain: ['公司库', '财务部空间'], // 继承 banner 父链;broken: true 转已断警示态 broken: false, exceptions: { label: 'Q3 并购草案.docx', count: 1 }, // 部分继承(例外 N 项,is-partial) entries: [ { subject: { kind: 'group', id: 'finance-team', label: 'finance-team', note: '24 成员 · 由 IT 管理' }, role: 'editor', inheritedFrom: '财务部空间' }, { subject: { kind: 'user', id: 'u-lisi', label: '李四' }, role: 'owner' }, { subject: { kind: 'user', id: 'u-rival', label: '竞对黑名单' }, role: 'viewer', deny: true }, // 一票否决置顶 { subject: { kind: 'org', id: 'sys-limited', label: 'Limited Access', note: '系统自动' }, role: 'viewer', system: true }, // 系统行不可删 ], links: [ { subject: { kind: 'link', id: 'l-org', label: '组织内任何有链接者' }, role: 'viewer', expiresAt: '2026-11-01T00:00:00.000Z' }, // 到期一等公民 ], exposureCount: 1204, // 「对 1,204 人可见」过度授权警示(不去重计数)};renderKbAcl(el, request, { onGrant: () => openSubjectPicker(), // 与 icen:kb-acl-grant 双通道 onRemove: (subject) => api.revoke(subject.id), // 与 icen:kb-acl-remove 双通道 onBreak: () => api.breakInheritance(request.resource), // 与 icen:kb-acl-inherit {action:'break'} 双通道 onRestore: () => api.restoreInheritance(request.resource),});// 事件:icen:kb-acl-grant {} / icen:kb-acl-remove {subject} / icen:kb-acl-inherit {action:'break'|'restore'}