fix(composer): 断连时禁止发送并消除输入扩展迟滞

This commit is contained in:
JOJO 2026-05-06 19:19:08 +08:00
parent d036ef5ccd
commit 91739840ee
3 changed files with 33 additions and 15 deletions

View File

@ -132,6 +132,14 @@ export const messageMethods = {
if (this.streamingUi) { if (this.streamingUi) {
return; return;
} }
if (!this.isConnected) {
this.uiPushToast({
title: '连接已断开',
message: '当前无法发送消息,请等待连接恢复后重试',
type: 'warning'
});
return;
}
if (this.mediaUploading) { if (this.mediaUploading) {
this.uiPushToast({ this.uiPushToast({
title: '上传中', title: '上传中',

View File

@ -60,11 +60,15 @@
+ +
</button> </button>
<textarea <textarea
:key="composerInputKey"
ref="stadiumInput" ref="stadiumInput"
class="stadium-input" class="stadium-input"
rows="1" rows="1"
:value="inputMessage" :value="inputMessage"
:disabled="!isConnected || streamingMessage || inputLocked" :disabled="!isConnected || streamingMessage || inputLocked"
autocomplete="off"
autocorrect="off"
autocapitalize="off"
placeholder="输入消息... (Ctrl+Enter 发送)" placeholder="输入消息... (Ctrl+Enter 发送)"
@input="onInput" @input="onInput"
@focus="$emit('input-focus')" @focus="$emit('input-focus')"
@ -306,12 +310,15 @@ const applyLineMetrics = (lines: number, multiline: boolean) => {
inputStore.setInputMultiline(multiline); inputStore.setInputMultiline(multiline);
}; };
const composerInputKey = computed(
() => `${props.currentConversationId || 'new'}:${props.isConnected ? 'online' : 'offline'}`
);
const adjustTextareaSize = () => { const adjustTextareaSize = () => {
const textarea = stadiumInput.value; const textarea = stadiumInput.value;
if (!textarea) { if (!textarea) {
return; return;
} }
const previousHeight = textarea.offsetHeight;
textarea.style.height = 'auto'; textarea.style.height = 'auto';
const computedStyle = window.getComputedStyle(textarea); const computedStyle = window.getComputedStyle(textarea);
const lineHeight = parseFloat(computedStyle.lineHeight || '20') || 20; const lineHeight = parseFloat(computedStyle.lineHeight || '20') || 20;
@ -320,20 +327,15 @@ const adjustTextareaSize = () => {
const lines = Math.max(1, Math.round(targetHeight / lineHeight)); const lines = Math.max(1, Math.round(targetHeight / lineHeight));
const multiline = targetHeight > lineHeight * 1.4; const multiline = targetHeight > lineHeight * 1.4;
applyLineMetrics(lines, multiline); applyLineMetrics(lines, multiline);
textarea.style.height = `${targetHeight}px`;
if (Math.abs(targetHeight - previousHeight) <= 0.5) {
textarea.style.height = `${targetHeight}px`;
return;
}
textarea.style.height = `${previousHeight}px`;
void textarea.offsetHeight;
requestAnimationFrame(() => {
textarea.style.height = `${targetHeight}px`;
});
}; };
const onInput = (event: Event) => { const onInput = (event: Event) => {
const target = event.target as HTMLTextAreaElement; const target = event.target as HTMLTextAreaElement;
if (!props.isConnected || props.streamingMessage || props.inputLocked) {
target.value = props.inputMessage || '';
return;
}
emit('update:input-message', target.value); emit('update:input-message', target.value);
emit('input-change'); emit('input-change');
adjustTextareaSize(); adjustTextareaSize();
@ -435,6 +437,17 @@ watch(
} }
); );
watch(
() => props.isConnected,
async (connected) => {
if (!connected && stadiumInput.value) {
stadiumInput.value.blur();
}
await nextTick();
adjustTextareaSize();
}
);
onMounted(() => { onMounted(() => {
adjustTextareaSize(); adjustTextareaSize();
}); });

View File

@ -232,8 +232,6 @@
display: flex; display: flex;
gap: 12px; gap: 12px;
transition: transition:
padding 0.2s ease,
min-height 0.2s ease,
box-shadow 0.45s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.45s cubic-bezier(0.4, 0, 0.2, 1),
border-color 0.45s cubic-bezier(0.4, 0, 0.2, 1); border-color 0.45s cubic-bezier(0.4, 0, 0.2, 1);
} }
@ -327,8 +325,7 @@
outline: none; outline: none;
overflow-y: auto; overflow-y: auto;
scrollbar-width: none; scrollbar-width: none;
transition: height 0.28s cubic-bezier(0.4, 0, 0.2, 1); transition: none;
will-change: height;
} }
.stadium-input:disabled { .stadium-input:disabled {