mirror of
https://github.com/Ed1s0nZ/CyberStrikeAI.git
synced 2026-07-13 07:36:35 +02:00
Add files via upload
This commit is contained in:
@@ -36249,16 +36249,88 @@ html[data-theme="dark"] .form-group select {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.rbac-summary-toggle {
|
||||
margin-left: 4px;
|
||||
vertical-align: middle;
|
||||
.rbac-summary-count {
|
||||
display: block;
|
||||
margin-top: 3px;
|
||||
color: var(--text-primary);
|
||||
font-size: 0.9375rem;
|
||||
font-weight: 700;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.rbac-effective-permissions {
|
||||
margin: 0 16px 12px;
|
||||
.rbac-summary-count--interactive {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
margin-top: 3px;
|
||||
padding: 0 0 1px;
|
||||
border: none;
|
||||
border-bottom: 1px dashed color-mix(in srgb, var(--text-secondary) 55%, transparent);
|
||||
border-radius: 0;
|
||||
background: none;
|
||||
color: var(--text-secondary);
|
||||
font-size: 0.9375rem;
|
||||
font-weight: 700;
|
||||
line-height: 1.2;
|
||||
cursor: pointer;
|
||||
transition: color 0.15s ease, border-color 0.15s ease;
|
||||
}
|
||||
|
||||
.rbac-summary-count--interactive:hover {
|
||||
color: var(--text-primary);
|
||||
border-bottom-color: color-mix(in srgb, var(--text-secondary) 80%, transparent);
|
||||
}
|
||||
|
||||
.rbac-summary-count--interactive[aria-expanded="true"] {
|
||||
color: var(--text-primary);
|
||||
border-bottom-color: var(--text-secondary);
|
||||
border-bottom-style: solid;
|
||||
}
|
||||
|
||||
.rbac-summary-count--interactive:focus-visible {
|
||||
outline: 2px solid color-mix(in srgb, var(--text-secondary) 35%, transparent);
|
||||
outline-offset: 3px;
|
||||
}
|
||||
|
||||
.rbac-permissions-popover {
|
||||
position: fixed;
|
||||
z-index: 220;
|
||||
width: min(380px, calc(100vw - 32px));
|
||||
}
|
||||
|
||||
.rbac-permissions-popover[hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.rbac-permissions-popover-inner {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 8px;
|
||||
border-radius: 10px;
|
||||
background: var(--bg-primary);
|
||||
box-shadow: var(--shadow-md, 0 8px 24px rgba(15, 23, 42, 0.12));
|
||||
}
|
||||
|
||||
.rbac-permissions-popover-inner::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -5px;
|
||||
left: var(--rbac-popover-arrow-left, 18px);
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
background: var(--bg-primary);
|
||||
border-left: 1px solid var(--border-color);
|
||||
border-top: 1px solid var(--border-color);
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.rbac-permissions-popover-count {
|
||||
color: var(--text-muted);
|
||||
font-size: 0.75rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.rbac-permissions-popover .rbac-effective-permissions-body {
|
||||
max-height: min(320px, calc(100vh - 180px));
|
||||
}
|
||||
|
||||
.rbac-effective-permissions-head,
|
||||
@@ -36744,6 +36816,11 @@ html[data-theme="dark"] .form-group select {
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.rbac-panel-detail .rbac-selected-summary .rbac-summary-count--interactive {
|
||||
margin-top: 2px;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.rbac-panel-detail .rbac-detail-head {
|
||||
min-height: 0;
|
||||
padding: 8px 14px;
|
||||
|
||||
+113
-30
@@ -251,43 +251,120 @@ function resolveUserEffectiveAccess(user) {
|
||||
return { userRoles, effectivePermissions, permissionsByModule, effectiveScope, assignmentCount };
|
||||
}
|
||||
|
||||
function toggleRbacEffectivePermissions() {
|
||||
rbacState.showEffectivePermissions = !rbacState.showEffectivePermissions;
|
||||
renderRbacEffectivePermissions(selectedRbacUser());
|
||||
let rbacPermissionsPopoverDocBound = false;
|
||||
|
||||
function positionRbacPermissionsPopover() {
|
||||
const popover = document.getElementById('rbac-permissions-popover');
|
||||
const btn = document.querySelector('.rbac-summary-count--interactive');
|
||||
if (!popover || !btn || popover.hidden) return;
|
||||
const rect = btn.getBoundingClientRect();
|
||||
const width = Math.min(380, window.innerWidth - 32);
|
||||
let left = rect.left;
|
||||
if (left + width > window.innerWidth - 16) left = window.innerWidth - width - 16;
|
||||
left = Math.max(16, left);
|
||||
const top = Math.min(rect.bottom + 8, window.innerHeight - 16);
|
||||
popover.style.width = `${width}px`;
|
||||
popover.style.left = `${left}px`;
|
||||
popover.style.top = `${top}px`;
|
||||
const arrowLeft = Math.min(Math.max(rect.left + rect.width / 2 - left - 5, 12), width - 22);
|
||||
popover.style.setProperty('--rbac-popover-arrow-left', `${arrowLeft}px`);
|
||||
}
|
||||
|
||||
function renderRbacEffectivePermissions(user) {
|
||||
const box = document.getElementById('rbac-effective-permissions');
|
||||
if (!box) return;
|
||||
if (!user || !rbacState.showEffectivePermissions) {
|
||||
box.hidden = true;
|
||||
box.innerHTML = '';
|
||||
return;
|
||||
function onRbacPermissionsPopoverReposition() {
|
||||
if (rbacState.showEffectivePermissions) positionRbacPermissionsPopover();
|
||||
}
|
||||
|
||||
function setRbacPermissionsPopoverOpen(open) {
|
||||
rbacState.showEffectivePermissions = open;
|
||||
const popover = document.getElementById('rbac-permissions-popover');
|
||||
const btn = document.querySelector('.rbac-summary-count--interactive');
|
||||
if (popover) popover.hidden = !open;
|
||||
if (btn) btn.setAttribute('aria-expanded', open ? 'true' : 'false');
|
||||
if (open) {
|
||||
requestAnimationFrame(() => positionRbacPermissionsPopover());
|
||||
}
|
||||
}
|
||||
|
||||
function closeRbacPermissionsPopover() {
|
||||
setRbacPermissionsPopoverOpen(false);
|
||||
}
|
||||
|
||||
function toggleRbacEffectivePermissions(ev) {
|
||||
if (ev) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
}
|
||||
const opening = !rbacState.showEffectivePermissions;
|
||||
if (opening) renderRbacEffectivePermissionsContent(selectedRbacUser());
|
||||
setRbacPermissionsPopoverOpen(opening);
|
||||
}
|
||||
|
||||
function onRbacPermissionsPopoverPointerDown(ev) {
|
||||
if (!rbacState.showEffectivePermissions) return;
|
||||
const popover = document.getElementById('rbac-permissions-popover');
|
||||
const btn = document.querySelector('.rbac-summary-count--interactive');
|
||||
if (popover && popover.contains(ev.target)) return;
|
||||
if (btn && btn.contains(ev.target)) return;
|
||||
closeRbacPermissionsPopover();
|
||||
}
|
||||
|
||||
function bindRbacPermissionsPopoverDismiss() {
|
||||
if (rbacPermissionsPopoverDocBound) return;
|
||||
rbacPermissionsPopoverDocBound = true;
|
||||
document.addEventListener('mousedown', onRbacPermissionsPopoverPointerDown);
|
||||
document.addEventListener('keydown', ev => {
|
||||
if (ev.key === 'Escape' && rbacState.showEffectivePermissions) closeRbacPermissionsPopover();
|
||||
});
|
||||
window.addEventListener('resize', onRbacPermissionsPopoverReposition);
|
||||
window.addEventListener('scroll', onRbacPermissionsPopoverReposition, true);
|
||||
}
|
||||
|
||||
function renderRbacEffectivePermissionsContent(user) {
|
||||
const popover = document.getElementById('rbac-permissions-popover');
|
||||
if (!popover || !user) return;
|
||||
const access = resolveUserEffectiveAccess(user);
|
||||
const modules = Object.keys(access.permissionsByModule).sort();
|
||||
if (!modules.length) {
|
||||
box.hidden = false;
|
||||
box.innerHTML = `<div class="rbac-empty"><strong>${rbacT('rbac.empty.noEffectivePermissions', '暂无有效权限')}</strong><span>${rbacEscape(rbacT('rbac.empty.assignRoleFirst', '分配角色后即可查看权限明细'))}</span></div>`;
|
||||
popover.innerHTML = `<div class="rbac-permissions-popover-inner"><div class="rbac-empty"><strong>${rbacT('rbac.empty.noEffectivePermissions', '暂无有效权限')}</strong><span>${rbacEscape(rbacT('rbac.empty.assignRoleFirst', '分配角色后即可查看权限明细'))}</span></div></div>`;
|
||||
return;
|
||||
}
|
||||
box.hidden = false;
|
||||
box.innerHTML = `
|
||||
<div class="rbac-effective-permissions-head">
|
||||
<strong>${rbacEscape(rbacT('rbac.effectivePermissionsDetail', '有效权限明细'))}</strong>
|
||||
<button type="button" class="btn-link btn-small" onclick="toggleRbacEffectivePermissions()">${rbacEscape(rbacT('common.close', '关闭'))}</button>
|
||||
</div>
|
||||
<div class="rbac-effective-permissions-body">
|
||||
${modules.map(module => `
|
||||
<section class="rbac-effective-module">
|
||||
<h4>${rbacEscape(rbacPermissionModuleLabel(module))}<span>${access.permissionsByModule[module].length}</span></h4>
|
||||
<div class="rbac-effective-permission-tags">
|
||||
${access.permissionsByModule[module].sort().map(key => `<span title="${rbacEscape(rbacPermissionLabel(key))}">${rbacEscape(rbacPermissionLabel(key))}</span>`).join('')}
|
||||
</div>
|
||||
</section>`).join('')}
|
||||
popover.innerHTML = `
|
||||
<div class="rbac-permissions-popover-inner">
|
||||
<div class="rbac-effective-permissions-head">
|
||||
<strong>${rbacEscape(rbacT('rbac.effectivePermissionsDetail', '有效权限明细'))}</strong>
|
||||
<span class="rbac-permissions-popover-count">${access.effectivePermissions.size}</span>
|
||||
</div>
|
||||
<div class="rbac-effective-permissions-body">
|
||||
${modules.map(module => `
|
||||
<section class="rbac-effective-module">
|
||||
<h4>${rbacEscape(rbacPermissionModuleLabel(module))}<span>${access.permissionsByModule[module].length}</span></h4>
|
||||
<div class="rbac-effective-permission-tags">
|
||||
${access.permissionsByModule[module].sort().map(key => `<span title="${rbacEscape(rbacPermissionLabel(key))}">${rbacEscape(rbacPermissionLabel(key))}</span>`).join('')}
|
||||
</div>
|
||||
</section>`).join('')}
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
function renderRbacEffectivePermissions(user) {
|
||||
const popover = document.getElementById('rbac-permissions-popover');
|
||||
const btn = document.querySelector('.rbac-summary-count--interactive');
|
||||
if (!popover) return;
|
||||
if (!user) {
|
||||
popover.hidden = true;
|
||||
popover.innerHTML = '';
|
||||
rbacState.showEffectivePermissions = false;
|
||||
if (btn) btn.setAttribute('aria-expanded', 'false');
|
||||
return;
|
||||
}
|
||||
if (btn) btn.setAttribute('aria-expanded', rbacState.showEffectivePermissions ? 'true' : 'false');
|
||||
popover.hidden = !rbacState.showEffectivePermissions;
|
||||
if (rbacState.showEffectivePermissions) {
|
||||
renderRbacEffectivePermissionsContent(user);
|
||||
requestAnimationFrame(() => positionRbacPermissionsPopover());
|
||||
}
|
||||
}
|
||||
|
||||
function rbacRoleIsSystem(role) {
|
||||
return !!(role && (role.isSystem || role.is_system));
|
||||
}
|
||||
@@ -306,6 +383,7 @@ async function initPlatformRbacPage() {
|
||||
if (typeof window !== 'undefined' && window.i18nReady) await window.i18nReady;
|
||||
const typeInput = document.getElementById('rbac-assignment-type');
|
||||
if (typeInput) rbacState.assignmentResourceType = typeInput.value || 'conversation';
|
||||
bindRbacPermissionsPopoverDismiss();
|
||||
await rbacRun(loadPlatformRbac, rbacT('rbac.errors.loadFailed', '加载失败'));
|
||||
initRbacSelects();
|
||||
}
|
||||
@@ -562,12 +640,17 @@ function renderRbacRoles() {
|
||||
} else {
|
||||
const access = resolveUserEffectiveAccess(user);
|
||||
const scope = rbacScopeInfo(access.effectiveScope);
|
||||
const permissionsToggle = access.effectivePermissions.size
|
||||
? ` <button type="button" class="btn-link btn-small rbac-summary-toggle" onclick="toggleRbacEffectivePermissions()">${rbacEscape(rbacT(rbacState.showEffectivePermissions ? 'rbac.hidePermissions' : 'rbac.viewPermissionsDetail', rbacState.showEffectivePermissions ? '收起明细' : '查看明细'))}</button>`
|
||||
: '';
|
||||
const permissionCount = access.effectivePermissions.size;
|
||||
const permissionCountHtml = permissionCount
|
||||
? `<button type="button" class="rbac-summary-count rbac-summary-count--interactive" aria-expanded="${rbacState.showEffectivePermissions ? 'true' : 'false'}" aria-haspopup="dialog" aria-controls="rbac-permissions-popover" title="${rbacEscape(rbacT('rbac.viewPermissionsDetail', '查看明细'))}" onclick="toggleRbacEffectivePermissions(event)">${permissionCount}</button>`
|
||||
: `<strong class="rbac-summary-count">${permissionCount}</strong>`;
|
||||
summary.innerHTML = `
|
||||
<div><span>${rbacT('rbac.roles', '角色')}</span><strong>${access.userRoles.length}</strong></div>
|
||||
<div class="rbac-summary-permissions"><span>${rbacT('rbac.effectivePermissions', '有效权限')}</span><strong>${access.effectivePermissions.size}</strong>${permissionsToggle}</div>
|
||||
<div class="rbac-summary-permissions">
|
||||
<span>${rbacT('rbac.effectivePermissions', '有效权限')}</span>
|
||||
${permissionCountHtml}
|
||||
<div id="rbac-permissions-popover" class="rbac-permissions-popover" role="dialog" aria-label="${rbacEscape(rbacT('rbac.effectivePermissionsDetail', '有效权限明细'))}" hidden></div>
|
||||
</div>
|
||||
<div><span>${rbacT('rbac.effectiveScope', '有效资源范围')}</span><strong title="${rbacEscape(scope.hint)}">${rbacEscape(scope.label)}</strong></div>
|
||||
<div><span>${rbacT('rbac.metricAssignments', '资源授权')}</span><strong>${access.assignmentCount}</strong></div>
|
||||
`;
|
||||
|
||||
@@ -4219,7 +4219,6 @@
|
||||
</div>
|
||||
</div>
|
||||
<div id="rbac-selected-summary" class="rbac-selected-summary"></div>
|
||||
<div id="rbac-effective-permissions" class="rbac-effective-permissions" hidden></div>
|
||||
<div id="rbac-no-role-notice" class="rbac-no-role-notice" hidden></div>
|
||||
<div class="rbac-tabs" role="tablist">
|
||||
<button type="button" class="rbac-tab is-active" data-rbac-tab="roles" onclick="switchRbacTab('roles')" data-i18n="rbac.tabRoles">角色权限</button>
|
||||
|
||||
Reference in New Issue
Block a user