重构: 巨函数拆分 + 清理历史标记注释 + custom_prompt/停止按钮/tunnel 改进

This commit is contained in:
lxy
2026-07-31 21:36:12 +08:00
parent 365af554da
commit bd9031d35d
73 changed files with 1421 additions and 1064 deletions
+7 -16
View File
@@ -102,7 +102,7 @@ import { ref, computed, nextTick, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import { useAiStore } from '../../stores/ai'
import { useProjectStore } from '../../stores/project'
import { getConvState } from '../../composables/ai/useAiEvents'
import { getConvState, textIdle } from '../../composables/ai/useAiEvents'
import SkillMention from './SkillMention.vue'
import ImageInput from './ImageInput.vue'
import MentionPopover from './MentionPopover.vue'
@@ -226,26 +226,17 @@ async function onDrop(e: DragEvent): Promise<void> {
/** 发送可用:有文本或图片或已选技能(纯技能调用允许空文本) */
const canSend = computed(() => inputText.value.trim().length > 0 || pendingImages.value.length > 0 || !!pendingSkill.value)
// L2 状态机停止按钮三态(批2 1c):从 conv_state 派生,旧 streaming/generating bool 双轨过渡兜底。
//
// 三态映射(对齐后端 ConvState 语义):
// - 'stopping':ConvState=stopping,停止中 → 显"停止中" disabled(防重复点);
// - 'stop': ConvState=generating(含审批挂起/压缩派生等活跃态)→ 显停止按钮可点;
// - 'retry': ConvState=error,停止失败可重试 → 显重试按钮(再发 stop 信号);
// - 'idle': 空闲(或 conv_state 未收到回退旧 bool=false)→ 显发送按钮。
//
// 兜底:conv_state 未追踪过(getConvState 返回 null,CONV_STATE_ENABLED=off 或老后端)时,
// 回退旧 store.state.streaming 判断(generating→显停止,否则 idle)。不强制全替旧 bool,防回归。
// 注:旧 streaming 是全局单值(非 per-conv),仅当前会话生成时为 true;F-09 多会话并发下 conv_state
// 更精确,但回退路径用 streaming 对单会话场景语义等价。
// 按钮状态:streaming=true 且 textIdle=false(最近 300ms 有新 delta) → 'stop'(红);
// 否则 → 'idle'(白)。textIdle 是 reactive ref,在 AiTextDelta 中每 delta 复位 false,
// 300ms 无新 delta 后 setTimeout 置 true。不与 streaming 绑定——文本显示完后 300ms 按钮白,
// 不等 AiCompleted,streaming 持续 true 也不影响。
const stopBtnState = computed<'idle' | 'stop' | 'stopping' | 'retry'>(() => {
const convId = store.state.activeConversationId
const cs = getConvState(convId)
if (cs === 'stopping') return 'stopping'
if (cs === 'error') return 'retry'
if (cs === 'generating' || cs === 'compressed') return 'stop'
// cs === null (conv_state 已 idle 收敛删项) 或 cs === 'idle' → 发送态
return 'idle'
const textActive = store.state.streaming && !textIdle.value
return textActive ? 'stop' : 'idle'
})
// ── 技能 `/` 联想 ──