GAZ-12: 防止 Session 多选时选中文本 #13

Merged
dev merged 1 commits from agent/docker/86e8574c into main 2026-08-03 20:02:38 +00:00
3 changed files with 3 additions and 1 deletions

View File

@ -41,6 +41,7 @@ describe("SessionTable", () => {
expect(screen.getByText("已选择 2 项")).toBeInTheDocument(); expect(screen.getByText("已选择 2 项")).toBeInTheDocument();
expect(screen.getByText("12 / 200")).toBeInTheDocument(); expect(screen.getByText("12 / 200")).toBeInTheDocument();
expect(screen.queryByRole("checkbox", { name: /选择 (当前页|S-)/ })).not.toBeInTheDocument(); expect(screen.queryByRole("checkbox", { name: /选择 (当前页|S-)/ })).not.toBeInTheDocument();
expect(first).toHaveClass("session-data-row");
}); });
it("筛选和排序产生显式查询意图", () => { it("筛选和排序产生显式查询意图", () => {

View File

@ -138,7 +138,7 @@ export function SessionTable({ rows, state, capabilities, page, onStateChange, o
})} })}
<span role="columnheader" /> <span role="columnheader" />
</div> </div>
</div><div role="rowgroup">{rows.map((session, index) => <div className={`table-row ${session.id === state.focusedSessionId ? "focused" : ""}`} role="row" aria-selected={selected.has(session.id)} key={session.id} tabIndex={session.id === state.focusedSessionId || (!state.focusedSessionId && index === 0) ? 0 : -1} ref={(element) => { if (element) rowRefs.current.set(session.id, element); else rowRefs.current.delete(session.id); }} onFocus={() => state.focusedSessionId !== session.id && onStateChange({ ...state, focusedSessionId: session.id })} onClick={(event) => handleRowClick(event, index, session.id)} onKeyDown={(event) => handleRowKeyDown(event, index, session.id)}> </div><div role="rowgroup">{rows.map((session, index) => <div className={`table-row session-data-row ${session.id === state.focusedSessionId ? "focused" : ""}`} role="row" aria-selected={selected.has(session.id)} key={session.id} tabIndex={session.id === state.focusedSessionId || (!state.focusedSessionId && index === 0) ? 0 : -1} ref={(element) => { if (element) rowRefs.current.set(session.id, element); else rowRefs.current.delete(session.id); }} onFocus={() => state.focusedSessionId !== session.id && onStateChange({ ...state, focusedSessionId: session.id })} onClick={(event) => handleRowClick(event, index, session.id)} onKeyDown={(event) => handleRowKeyDown(event, index, session.id)}>
{visible.has("status") && <span role="cell"><em className={`status-mark ${session.status.toLowerCase()}`} aria-hidden="true" /><span className="sr-only"></span>{session.status}</span>} {visible.has("status") && <span role="cell"><em className={`status-mark ${session.status.toLowerCase()}`} aria-hidden="true" /><span className="sr-only"></span>{session.status}</span>}
{visible.has("id") && <strong role="cell" className="mono">{session.id}</strong>} {visible.has("id") && <strong role="cell" className="mono">{session.id}</strong>}
{visible.has("identity") && <span role="cell"><b>{session.host}</b><small>{session.user}</small></span>} {visible.has("identity") && <span role="cell"><b>{session.host}</b><small>{session.user}</small></span>}

View File

@ -72,6 +72,7 @@ nav strong { color: #f1888f; font: 600 10px ui-monospace, monospace; }
.table-row:hover { background: var(--hover); } .table-row:hover { background: var(--hover); }
.table-row.focused { background: #202a35; box-shadow: inset 2px 0 var(--info); } .table-row.focused { background: #202a35; box-shadow: inset 2px 0 var(--info); }
.table-row[aria-selected="true"] { background: #243346; box-shadow: inset 2px 0 var(--info); } .table-row[aria-selected="true"] { background: #243346; box-shadow: inset 2px 0 var(--info); }
.session-data-row { user-select: none; -webkit-user-select: none; }
.table-head { position: sticky; top: -22px; z-index: 2; min-height: 30px; background: #111419; color: #78818e; font-size: 9px; font-weight: 650; letter-spacing: .04em; } .table-head { position: sticky; top: -22px; z-index: 2; min-height: 30px; background: #111419; color: #78818e; font-size: 9px; font-weight: 650; letter-spacing: .04em; }
.sort-button { width: 100%; height: 100%; padding: 0; border: 0; background: transparent; color: inherit; text-align: left; text-transform: uppercase; } .sort-button { width: 100%; height: 100%; padding: 0; border: 0; background: transparent; color: inherit; text-align: left; text-transform: uppercase; }
.table-row b { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 550; color: #dde1e7; } .table-row b { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 550; color: #dde1e7; }