diff --git a/LianSyn-platform/app.js b/LianSyn-platform/app.js index 18d3750..68a59f5 100644 --- a/LianSyn-platform/app.js +++ b/LianSyn-platform/app.js @@ -1087,7 +1087,9 @@ function renderAccountAuthorizationPanel() { const container = $('#accountAuthorizationTypes'); if (!panel || !container) return; const account = accountList.find((item) => item.id === accountAuthorizationTargetId); - if (!account || account.role === 'admin') { + const isOpen = Boolean(account && account.role !== 'admin'); + panel.closest('.account-panel')?.classList.toggle('is-authorizing', isOpen); + if (!isOpen) { panel.hidden = true; container.replaceChildren(); accountAuthorizationTargetId = ''; diff --git a/LianSyn-platform/index.html b/LianSyn-platform/index.html index 784b7a6..a1297f0 100644 --- a/LianSyn-platform/index.html +++ b/LianSyn-platform/index.html @@ -5,7 +5,7 @@ AI操作台 · LianSyn-platform - +
@@ -407,6 +407,6 @@
- + diff --git a/LianSyn-platform/styles.css b/LianSyn-platform/styles.css index db2d4f6..9332713 100644 --- a/LianSyn-platform/styles.css +++ b/LianSyn-platform/styles.css @@ -634,10 +634,6 @@ textarea { font-size: 11px; } -.account-panel { - grid-template-rows: auto auto auto minmax(0, 1fr) auto; -} - .account-authorization-summary { color: var(--ink) !important; } @@ -3049,6 +3045,12 @@ textarea { grid-template-rows: auto auto minmax(0, 1fr) auto; } +.channels-page .channel-panel.account-panel.is-authorizing { + height: max-content; + grid-template-rows: auto auto auto auto auto; + overflow: visible; +} + .channels-page .channel-list { max-height: none; } diff --git a/control-plane/test/account-authorization.test.ts b/control-plane/test/account-authorization.test.ts index a0f5965..232f836 100644 --- a/control-plane/test/account-authorization.test.ts +++ b/control-plane/test/account-authorization.test.ts @@ -339,3 +339,30 @@ test('operator UI exposes role-aware accounts, executive drill-through, original assert.doesNotMatch(retention, /DELETE FROM tasks/); assert.doesNotMatch(retention, /DELETE FROM audit_events/); }); + +test('account authorization editor uses a scroll-safe open layout without overriding the closed account list', async () => { + const [app, index, styles] = await Promise.all([ + source('../../LianSyn-platform/app.js'), + source('../../LianSyn-platform/index.html'), + source('../../LianSyn-platform/styles.css') + ]); + const renderStart = app.indexOf('function renderAccountAuthorizationPanel()'); + const renderEnd = app.indexOf('function openAccountAuthorizationEditor(', renderStart); + const renderSource = app.slice(renderStart, renderEnd); + assert.match(renderSource, /const isOpen = Boolean\(account && account\.role !== 'admin'\)/); + assert.match(renderSource, /classList\.toggle\('is-authorizing', isOpen\)/); + assert.match(renderSource, /if \(!isOpen\)/); + + const genericLayout = styles.indexOf('.channels-page .channel-panel {'); + const openLayout = styles.indexOf('.channels-page .channel-panel.account-panel.is-authorizing {'); + assert.ok(genericLayout >= 0, 'generic management-page layout is present'); + assert.ok(openLayout > genericLayout, 'account open-state layout follows the generic layout in the cascade'); + const openLayoutSource = styles.slice(openLayout, styles.indexOf('}', openLayout) + 1); + assert.match(openLayoutSource, /height:\s*max-content/); + assert.match(openLayoutSource, /grid-template-rows:\s*auto auto auto auto auto/); + assert.match(openLayoutSource, /overflow:\s*visible/); + assert.doesNotMatch(styles, /\.account-panel\s*\{\s*grid-template-rows:/); + + assert.match(index, /styles\.css\?v=20260902-account-authorization-layout-1/); + assert.match(index, /app\.js\?v=20260902-account-authorization-layout-1/); +}); diff --git a/control-plane/test/control-plane.test.ts b/control-plane/test/control-plane.test.ts index 615b334..904e50d 100644 --- a/control-plane/test/control-plane.test.ts +++ b/control-plane/test/control-plane.test.ts @@ -1231,8 +1231,8 @@ test('operator page has a login gate and uses the durable task API', async () => const inpage = await readFile(new URL('../../chrome-extension/ltjt-order-assistant/inpage.js', import.meta.url), 'utf8'); assert.match(index, /id="loginPanel"/); assert.match(index, /id="workbench"[^>]*hidden/); - assert.match(index, /styles\.css\?v=20260902-agentbus-dashboard-metrics-filter-1/); - assert.match(index, /app\.js\?v=20260902-agentbus-dashboard-metrics-filter-1/); + assert.match(index, /styles\.css\?v=20260902-account-authorization-layout-1/); + assert.match(index, /app\.js\?v=20260902-account-authorization-layout-1/); assert.match(index, /id="statusDetailsPopover"/); assert.match(index, /id="statusDetailsRefresh"/); assert.match(app, /apiRequest\(`\/api\/tasks\?\$\{params\.toString\(\)\}`/);