Place teacher prompt buttons above the composer

This commit is contained in:
鲨鱼辣椒 committed 2026-09-29 20:06:31 +08:00
1 parent bb96941461
commit efd1894269
6 files changed
+96 -24

No files matched your search

+10 -9
View File
@@ -606,20 +606,21 @@ export function TeacherChatPanel({
</div>
</details>}
{references.length > 0 && <div className="mb-2 rounded-lg bg-white p-3 text-xs"><p className="line-clamp-3 whitespace-pre-wrap">{references.map((ref) => ref.text).join('\n')}</p><button type="button" className="mt-1 underline" onClick={removeReferences}>移除引用</button></div>}
{!draftRevision && !text.trim() && (definition?.shortcuts == null || definition.shortcuts.length > 0) &&
<div className="consultation-shortcuts" role="group" aria-label="快捷提问" data-testid="consultation-shortcuts">
{definition?.shortcuts == null
? <button type="button" disabled={helpUnavailable || voiceInput.state !== 'idle'} onClick={askForSuggestions} className="consultation-hint">帮我整体看🧠</button>
: definition.shortcuts.map((shortcut, index) => <button
key={index} type="button" disabled={helpUnavailable || voiceInput.state !== 'idle'}
onClick={() => void send({ text: shortcut.prompt })}
className="consultation-hint"
>{shortcut.label}</button>)}
</div>}
<div className="consultation-composer rounded-2xl border bg-white p-3 focus-within:ring-2 focus-within:ring-black/5">
<textarea ref={inputRef} aria-label={`向${label}提问`} value={text} disabled={busy} maxLength={6000} onChange={(e) => changeText(e.target.value)} placeholder="和老师聊聊" rows={2}
onKeyDown={(e) => { if (e.key === 'Enter' && !e.shiftKey && !e.nativeEvent.isComposing) { e.preventDefault(); void send(); } }}
className="min-h-[60px] w-full resize-none border-0 bg-transparent text-[13px] leading-6 outline-none placeholder:text-muted-foreground/65" />
<div className="mt-2 flex min-h-[68px] flex-wrap items-center justify-between gap-x-2 gap-y-2" data-testid="consultation-composer-actions">
<div className="flex max-h-48 min-w-0 grow flex-wrap gap-2 overflow-y-auto pb-1">
{!draftRevision && !text.trim() && (definition?.shortcuts == null
? <button type="button" disabled={helpUnavailable || voiceInput.state !== 'idle'} onClick={askForSuggestions} className="consultation-hint">帮我整体看🧠</button>
: definition.shortcuts.map((shortcut, index) => <button
key={index} type="button" disabled={helpUnavailable || voiceInput.state !== 'idle'}
onClick={() => void send({ text: shortcut.prompt })}
className="consultation-hint max-w-full whitespace-normal break-words text-left"
>{shortcut.label}</button>))}
</div>
<div className="ml-auto flex min-w-0 max-w-full items-center gap-1" data-testid="teacher-composer-runtime-controls">
<TeacherModelSelect key={modelScope + (definition?.runtime ?? 'local')} runtime={definition?.runtime ?? 'local'} scope={modelScope} defaultModel={definition?.model.model_id}
modelId={modelChoice.modelId} onChange={modelChoice.select} disabled={busy || !topicEnabled || Boolean(running)} />
+8 -3
View File
@@ -49,9 +49,14 @@
.classroom-consultation-resizer { position: absolute; inset: 0 auto 0 -4px; width: 8px; z-index: 2; cursor: col-resize; }
.classroom-consultation-resizer:hover, .classroom-consultation-resizer:focus-visible { background: #7994b533; }
.consultation-pane { background: #fffdf8; color: #30465f; }
.consultation-hint, .consultation-retry { display: inline-flex; align-items: center; justify-content: center; align-self: flex-start; min-height: 44px; max-width: 100%; padding: 8px 16px; border: 1.5px solid #e3ce8f; border-radius: 16px 16px 16px 6px; background: #fff2c9; color: #6f5127; box-shadow: 0 3px 0 #e7d7a6, inset 0 1px 0 #fff9e8; font-size: 14px; font-weight: 600; line-height: 24px; cursor: pointer; transition: background-color 160ms ease, border-color 160ms ease, box-shadow 160ms ease, transform 160ms ease; }
.consultation-hint:hover:not(:disabled), .consultation-retry:hover:not(:disabled) { background: #ffe9a9; border-color: #d6b76f; }
.consultation-hint:active:not(:disabled), .consultation-retry:active:not(:disabled) { transform: translateY(2px); box-shadow: 0 1px 0 #e7d7a6, inset 0 1px 0 #fff9e8; }
.consultation-retry { display: inline-flex; align-items: center; justify-content: center; align-self: flex-start; min-height: 44px; max-width: 100%; padding: 8px 16px; border: 1.5px solid #e3ce8f; border-radius: 16px 16px 16px 6px; background: #fff2c9; color: #6f5127; box-shadow: 0 3px 0 #e7d7a6, inset 0 1px 0 #fff9e8; font-size: 14px; font-weight: 600; line-height: 24px; cursor: pointer; transition: background-color 160ms ease, border-color 160ms ease, box-shadow 160ms ease, transform 160ms ease; }
.consultation-retry:hover:not(:disabled) { background: #ffe9a9; border-color: #d6b76f; }
.consultation-retry:active:not(:disabled) { transform: translateY(2px); box-shadow: 0 1px 0 #e7d7a6, inset 0 1px 0 #fff9e8; }
.consultation-shortcuts { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 8px; max-height: min(192px, 24vh); overflow-y: auto; margin-bottom: 10px; padding: 3px; }
.consultation-hint { display: inline-flex; align-items: center; max-width: 100%; min-height: 36px; padding: 6px 12px; border: 1px solid #e5ddc7; border-radius: 12px; background: #faf5e8; color: #5b503b; font-size: 13px; font-weight: 400; line-height: 22px; text-align: left; white-space: normal; overflow-wrap: anywhere; cursor: pointer; transition: background-color 160ms ease, border-color 160ms ease; }
.consultation-hint:hover:not(:disabled) { background: #f4ecd6; border-color: #d7c9a5; }
.consultation-hint:active:not(:disabled) { background: #eee3c7; }
.consultation-hint:focus-visible { outline: 2px solid #7891af; outline-offset: 2px; }
.consultation-hint:disabled, .consultation-retry:disabled { cursor: not-allowed; opacity: 0.5; }
@media (prefers-reduced-motion: reduce) { .consultation-hint, .consultation-retry { transition: none; } .consultation-hint:active:not(:disabled), .consultation-retry:active:not(:disabled) { transform: none; } }
.consultation-pane button:focus-visible { outline: 2px solid #71845f; outline-offset: 3px; }