fix(export): tune sns rank strip size and theme compatibility

This commit is contained in:
aits2026
2026-03-05 20:10:47 +08:00
parent ba2cdbf8cf
commit 7cea8b4fb3
2 changed files with 98 additions and 46 deletions

View File

@@ -1794,7 +1794,7 @@
} }
} }
.row-action-cell { .row-action-cell {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: flex-end; align-items: flex-end;
@@ -1804,7 +1804,7 @@
.row-action-main { .row-action-main {
display: inline-flex; display: inline-flex;
align-items: center; align-items: flex-start;
gap: 6px; gap: 6px;
} }
@@ -1831,47 +1831,95 @@
} }
} }
.row-export-btn { .row-export-action-stack {
display: inline-flex;
flex-direction: column;
align-items: center;
gap: 2px;
min-width: 84px;
}
.row-export-link {
border: none; border: none;
border-radius: 8px; padding: 0;
padding: 7px 10px; margin: 0;
background: var(--primary); background: transparent;
color: #fff; color: var(--primary);
font-size: 12px; font-size: 12px;
cursor: pointer; cursor: pointer;
display: flex; line-height: 1.2;
align-items: center; font-weight: 600;
gap: 5px; white-space: nowrap;
&:hover:not(:disabled) { &:hover:not(:disabled) {
background: var(--primary-hover); color: var(--primary-hover);
text-decoration: underline;
text-underline-offset: 2px;
} }
&:disabled { &:disabled {
opacity: 0.75;
cursor: not-allowed; cursor: not-allowed;
} }
&.running { &:focus-visible {
background: color-mix(in srgb, var(--primary) 80%, #000); outline: 2px solid color-mix(in srgb, var(--primary) 30%, transparent);
outline-offset: 2px;
border-radius: 4px;
} }
&.paused { &.state-running {
background: rgba(250, 173, 20, 0.16); cursor: progress;
color: #d48806;
border: 1px solid rgba(250, 173, 20, 0.38);
} }
&.no-session { &.state-disabled {
background: var(--bg-secondary);
color: var(--text-tertiary); color: var(--text-tertiary);
border: 1px dashed var(--border-color); text-decoration: none;
} }
} }
.row-export-meta {
display: inline-flex;
flex-direction: column;
align-items: center;
gap: 1px;
}
.row-export-meta-label {
font-size: 10px;
line-height: 1.2;
color: var(--text-tertiary);
font-weight: 500;
}
.row-export-time { .row-export-time {
font-size: 11px; font-size: 11px;
line-height: 1.2;
color: var(--text-tertiary); color: var(--text-tertiary);
font-variant-numeric: tabular-nums;
white-space: nowrap;
text-align: center;
}
.row-export-link.state-running + .row-export-meta .row-export-time {
color: var(--primary);
font-weight: 600;
}
.row-export-link.state-running:hover:not(:disabled),
.row-export-link.state-running:focus-visible {
color: var(--primary);
text-decoration: none;
}
.row-export-link.state-disabled + .row-export-meta .row-export-meta-label,
.row-export-link.state-disabled + .row-export-meta .row-export-time {
color: var(--text-tertiary);
}
.row-export-link.state-disabled:hover:not(:disabled),
.row-export-link.state-disabled:focus-visible {
color: var(--text-tertiary);
text-decoration: none;
} }
} }
@@ -2323,11 +2371,11 @@
top: calc(100% + 8px); top: calc(100% + 8px);
right: 0; right: 0;
width: 248px; width: 248px;
max-height: 220px; max-height: calc((28px * 15) + 16px);
overflow-y: auto; overflow-y: auto;
border: 1px solid color-mix(in srgb, var(--primary) 30%, var(--border-color)); border: 1px solid color-mix(in srgb, var(--primary) 30%, var(--border-color));
border-radius: 10px; border-radius: 10px;
background: var(--bg-primary-solid, #fff); background: var(--bg-primary);
box-shadow: 0 14px 26px rgba(0, 0, 0, 0.18); box-shadow: 0 14px 26px rgba(0, 0, 0, 0.18);
padding: 8px; padding: 8px;
z-index: 12; z-index: 12;
@@ -3292,7 +3340,8 @@
font-size: 12px; font-size: 12px;
} }
.table-wrap .row-open-chat-link { .table-wrap .row-open-chat-link,
.table-wrap .row-export-link {
font-size: 11px; font-size: 11px;
} }
@@ -3363,7 +3412,7 @@
.sns-dialog-rank-panel { .sns-dialog-rank-panel {
width: min(78vw, 232px); width: min(78vw, 232px);
max-height: 190px; max-height: calc((28px * 15) + 16px);
} }
.sns-dialog-tip { .sns-dialog-tip {

View File

@@ -444,7 +444,7 @@ const formatPathBrief = (value: string, maxLength = 52): string => {
} }
const formatRecentExportTime = (timestamp?: number, now = Date.now()): string => { const formatRecentExportTime = (timestamp?: number, now = Date.now()): string => {
if (!timestamp) return '' if (!timestamp) return '未导出'
const diff = Math.max(0, now - timestamp) const diff = Math.max(0, now - timestamp)
const minute = 60 * 1000 const minute = 60 * 1000
const hour = 60 * minute const hour = 60 * minute
@@ -5067,7 +5067,7 @@ function ExportPage() {
const checked = canExport && selectedSessions.has(contact.username) const checked = canExport && selectedSessions.has(contact.username)
const isRunning = canExport && runningSessionIds.has(contact.username) const isRunning = canExport && runningSessionIds.has(contact.username)
const isQueued = canExport && queuedSessionIds.has(contact.username) const isQueued = canExport && queuedSessionIds.has(contact.username)
const recent = canExport ? formatRecentExportTime(lastExportBySession[contact.username], nowTick) : '' const recentExportTime = canExport ? formatRecentExportTime(lastExportBySession[contact.username], nowTick) : ''
const countedMessages = normalizeMessageCount(sessionMessageCounts[contact.username]) const countedMessages = normalizeMessageCount(sessionMessageCounts[contact.username])
const hintedMessages = normalizeMessageCount(matchedSession?.messageCountHint) const hintedMessages = normalizeMessageCount(matchedSession?.messageCountHint)
const displayedMessageCount = countedMessages ?? hintedMessages const displayedMessageCount = countedMessages ?? hintedMessages
@@ -5214,26 +5214,29 @@ function ExportPage() {
> >
</button> </button>
<button <div className="row-export-action-stack">
className={`row-export-btn ${isRunning ? 'running' : ''} ${!canExport ? 'no-session' : ''}`} <button
disabled={!canExport || isRunning} type="button"
onClick={() => { className={`row-export-link ${isRunning ? 'state-running' : ''} ${!canExport ? 'state-disabled' : ''}`}
if (!matchedSession || !matchedSession.hasSession) return disabled={!canExport || isRunning}
openSingleExport({ onClick={() => {
...matchedSession, if (!matchedSession || !matchedSession.hasSession) return
displayName: contact.displayName || matchedSession.displayName || matchedSession.username openSingleExport({
}) ...matchedSession,
}} displayName: contact.displayName || matchedSession.displayName || matchedSession.username
> })
{isRunning ? ( }}
<> >
<Loader2 size={14} className="spin" /> {!canExport ? '暂无会话' : isRunning ? '导出中...' : isQueued ? '排队中' : '单会话导出'}
</button>
</> {canExport && (
) : !canExport ? '暂无会话' : isQueued ? '排队中' : '单会话导出'} <div className="row-export-meta">
</button> <span className="row-export-meta-label"></span>
<span className="row-export-time">{recentExportTime}</span>
</div>
)}
</div>
</div> </div>
{recent && <span className="row-export-time">{recent}</span>}
</div> </div>
</div> </div>
</div> </div>