From b34de4e078c55f28b4febb9e13dde0957cf57e23 Mon Sep 17 00:00:00 2001 From: matevip Date: Wed, 27 May 2026 15:09:04 +0800 Subject: [PATCH] refactor(approval-grants-ui): strip Element Plus, reuse project list+pagination --- mateclaw-ui/src/i18n/locales/en-US.ts | 1 + mateclaw-ui/src/i18n/locales/zh-CN.ts | 1 + .../Security/AutoApproveGrants/index.vue | 296 ++++++++++-------- mateclaw-ui/src/views/layout/MainLayout.vue | 135 ++++++-- 4 files changed, 267 insertions(+), 166 deletions(-) diff --git a/mateclaw-ui/src/i18n/locales/en-US.ts b/mateclaw-ui/src/i18n/locales/en-US.ts index a3aee32d..ef708d7e 100644 --- a/mateclaw-ui/src/i18n/locales/en-US.ts +++ b/mateclaw-ui/src/i18n/locales/en-US.ts @@ -3732,6 +3732,7 @@ export default { manage: 'Manage auto-approve rules...', }, chipLabel: 'Auto-approve active ({count})', + chipShort: 'Auto-approve {count}', menu: 'Auto-approve', title: 'Auto-approve rules', desc: 'Rules let specific tool calls skip manual approval. Safety-floor patterns (rm -rf /, pipe-to-shell, etc.) always apply, and CRITICAL severity always falls back to human approval.', diff --git a/mateclaw-ui/src/i18n/locales/zh-CN.ts b/mateclaw-ui/src/i18n/locales/zh-CN.ts index 6adc5177..0f798271 100644 --- a/mateclaw-ui/src/i18n/locales/zh-CN.ts +++ b/mateclaw-ui/src/i18n/locales/zh-CN.ts @@ -3824,6 +3824,7 @@ export default { manage: '管理自动批准策略...', }, chipLabel: '自动批准已启用 ({count})', + chipShort: '自动批准 {count}', menu: '自动批准', title: '自动批准策略', desc: '策略让特定工具调用跳过人审。地板规则(如 rm -rf /、pipe-to-shell)始终生效,CRITICAL 严重度永远人审。', diff --git a/mateclaw-ui/src/views/Security/AutoApproveGrants/index.vue b/mateclaw-ui/src/views/Security/AutoApproveGrants/index.vue index 28cdcd47..f0f507b0 100644 --- a/mateclaw-ui/src/views/Security/AutoApproveGrants/index.vue +++ b/mateclaw-ui/src/views/Security/AutoApproveGrants/index.vue @@ -16,17 +16,12 @@

{{ t('approval.grant.title') }}

- + + {{ t('approval.grant.chipLabel', { count: total }) }} - +

{{ t('approval.grant.desc') }}

@@ -54,113 +49,93 @@
-
- - - - + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
{{ t('approval.grant.columns.scope') }}{{ t('approval.grant.columns.tool') }}{{ t('approval.grant.columns.rule') }}{{ t('approval.grant.columns.severity') }}{{ t('approval.grant.columns.kind') }}{{ t('approval.grant.columns.expire') }}{{ t('approval.grant.columns.grantedBy') }}{{ t('approval.grant.columns.note') }}{{ t('approval.grant.columns.actions') }}
+ + {{ t(`approval.grant.scope.${scopeI18nKey(row.scopeType)}`) }} + +
{{ row.scopeId }}
+
+ {{ row.toolName }} + ∗ any + + {{ row.ruleId }} + + + + {{ row.maxSeverity }} + + {{ t(`approval.grant.kind.${kindI18nKey(row.grantKind)}`) }}{{ formatDate(row.expireAt) }}{{ row.grantedBy }}{{ row.note }} + + {{ t('common.revoked') }} +
+
{{ t('common.loading') }}
+
{{ t('approval.grant.empty') }}
+
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - +
@@ -312,6 +287,7 @@ import { WarningFilled, } from '@element-plus/icons-vue' import { approvalApi } from '@/api' +import McPagination from '@/components/common/McPagination.vue' import type { ApprovalGrant, CreateGrantPayload, @@ -365,6 +341,16 @@ const requiresPassword = computed(() => { return noTool && (form.scopeType === 'WORKSPACE' || form.scopeType === 'AGENT') }) +function onPageChange(p: number) { + currentPage.value = p + loadGrants() +} +function onSizeChange(s: number) { + pageSize.value = s + currentPage.value = 1 + loadGrants() +} + async function loadGrants() { loading.value = true try { @@ -471,23 +457,6 @@ function scopeI18nKey(scope: GrantScope): string { } } -function scopeTagType(scope: GrantScope): 'primary' | 'success' | 'warning' | 'danger' | 'info' { - switch (scope) { - case 'CONVERSATION': return 'primary' - case 'AGENT': return 'warning' - case 'USER': return 'success' - case 'WORKSPACE': return 'danger' - } -} - -function severityTagType(sev: GrantSeverity): 'success' | 'warning' | 'danger' { - switch (sev) { - case 'LOW': return 'success' - case 'MEDIUM': return 'warning' - case 'HIGH': return 'danger' - } -} - function kindI18nKey(kind: GrantKind): string { switch (kind) { case 'ALWAYS': return 'always' @@ -523,8 +492,19 @@ onMounted(loadGrants) flex-basis: 100%; margin: 4px 0 0; } -.active-summary { +/* Summary pill — reuses the same danger-tinted tokens as the sidebar chip + so the two surfaces feel like one design language; no el-tag here. */ +.summary-pill { + display: inline-flex; + align-items: center; + padding: 2px 10px; + border-radius: 999px; + background: var(--mc-danger-bg, rgba(192, 57, 43, 0.12)); + color: var(--mc-danger, #C0392B); + border: 1px solid var(--mc-danger-border, rgba(192, 57, 43, 0.4)); + font-size: 12px; font-weight: 600; + line-height: 1.5; } /* Header actions: matches McpServers / ToolGuard layout (.section-header__actions @@ -567,17 +547,36 @@ onMounted(loadGrants) color: #991b1b; } +/* Scope badge — same family as .severity-badge in shared.css, 4 token-driven + color variants for CONVERSATION / AGENT / USER / WORKSPACE. */ +.scope-badge { + display: inline-block; + padding: 2px 8px; + border-radius: 4px; + font-size: 11px; + font-weight: 600; + line-height: 1.5; +} +.scope-conversation { background: rgba(59, 130, 246, 0.12); color: #3b82f6; } +.scope-agent { background: rgba(245, 158, 11, 0.12); color: #f59e0b; } +.scope-user { background: rgba(16, 185, 129, 0.12); color: #10b981; } +.scope-workspace { background: var(--mc-danger-bg, rgba(192, 57, 43, 0.12)); + color: var(--mc-danger, #C0392B); } .scope-id { - margin-left: 8px; + margin-top: 2px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; - font-size: 12px; + font-size: 11px; color: var(--mc-text-tertiary, #94a3b8); + max-width: 180px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; } .mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; - background: var(--mc-surface-tertiary, #f1f5f9); + background: var(--mc-surface-tertiary, var(--mc-bg-muted, rgba(0, 0, 0, 0.04))); padding: 1px 6px; border-radius: 3px; } @@ -596,8 +595,29 @@ onMounted(loadGrants) font-size: 12px; } -.grants-pagination { - margin-top: 16px; +/* Revoked rows: dim out so live rows stay visually dominant. */ +.row-revoked { opacity: 0.55; } +.row-revoked .scope-badge { filter: grayscale(0.5); } + +/* Actions column header sits right-aligned, matches ToolGuard. */ +.col-actions { text-align: center; width: 80px; } + +/* This page has more columns than ToolGuard / AuditLogs, so the wrapper needs + to allow horizontal scroll on narrow viewports — shared.css uses + overflow:hidden which would chop the rightmost columns off. Scoped override + only affects this view; the shared style stays untouched. */ +.rules-table-wrapper { + overflow-x: auto; +} +.rules-table { + min-width: 900px; +} + +/* Pagination row — right-aligned beneath the table. McPagination provides + its own pill background, so just lay it out. */ +.grants-pagination-row { + margin-top: 14px; + display: flex; justify-content: flex-end; } diff --git a/mateclaw-ui/src/views/layout/MainLayout.vue b/mateclaw-ui/src/views/layout/MainLayout.vue index 7820be46..aa0e38b0 100644 --- a/mateclaw-ui/src/views/layout/MainLayout.vue +++ b/mateclaw-ui/src/views/layout/MainLayout.vue @@ -80,11 +80,34 @@