agent-Specialization/static/src/app/lifecycle.ts
JOJO d2dd097248 fix(chat): 修复移动端运行期滚动脱锁失效,流式渲染分块防重建
- ChatArea: 新增触摸手势脱锁(手指下拉>8px 视为脱锁意图),与桌面端 wheel-up 同路径;嵌套滚动容器内触摸不解除外层锁定
- ChatArea: 展开锚定改为按条件跳过——仅贴底锁定中的运行态块交给逐帧追底,手动展开(含脱锁后历史块)走锚定,修复外框与内容移动不同步
- scroll: 脱锁标志重置改为严格贴底判定(<=4px),nearBottom 70px 容差与意图冷却期内不再误清脱锁标志,修复移动端第一次上滑必被拽回底部
- lifecycle: 移动端视口 watcher 提前到路由/对话加载前,避免加载期按桌面布局渲染
- MarkdownRenderer: 文本段按顶层块分片渲染+分段级缓存,流式期间已完成前缀块 DOM 不再重设,保护 show_file 卡片/表格/KaTeX 不被反复重建
- view_image: 工具结果携带 size,前端按 path 走 /api/file/content 加载原图,图片限高 480px 防长截图占满对话区
2026-08-07 11:32:20 +08:00

139 lines
5.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// @ts-nocheck
import { useChatActionStore } from '../stores/chatActions';
import { normalizeScrollLock } from '../composables/useScrollControl';
import { setupShowImageObserver, teardownShowImageObserver } from './bootstrap';
import { debugLog } from './methods/common';
export function created() {
const actionStore = useChatActionStore();
actionStore.registerDependencies({
pushToast: (payload) => this.uiPushToast(payload),
autoResizeInput: () => this.autoResizeInput(),
focusComposer: () => {
const inputEl = this.getComposerElement('stadiumInput');
if (inputEl && typeof inputEl.focus === 'function') {
inputEl.focus();
}
},
isConnected: () => this.isConnected,
executeCommand: async (command) => this.executeSystemCommand(command, { showToast: false }),
downloadResource: (url, filename) => this.downloadResource(url, filename)
});
}
export async function mounted() {
debugLog('Vue应用已挂载');
if (window.ensureCsrfToken) {
window.ensureCsrfToken().catch((err) => {
console.warn('CSRF token 初始化失败:', err);
});
}
// 移动端视口判断必须在路由/对话加载前生效,
// 否则加载期间移动端会按桌面布局渲染QuickDock 挤压页面)。
this.setupMobileViewportWatcher();
// 并行启动路由解析与初始化数据,网页端不再依赖 WebSocket 初始化
const routePromise = this.bootstrapRoute();
await routePromise;
this.$nextTick(() => {
this.ensureScrollListener();
// 刷新后若无输出,自动解锁滚动锁定
normalizeScrollLock(this);
});
setupShowImageObserver();
// 立即加载初始数据(并行获取状态,优先同步运行模式)
const initialDataPromise = this.loadInitialData();
this.startProjectGitSummaryIdleRefresh?.();
this.startConnectionHeartbeat();
this.fetchTerminalCount();
this.startTerminalCountIdleRefresh();
this.checkTutorialPrompt();
if (initialDataPromise && typeof initialDataPromise.then === 'function') {
initialDataPromise
.then(() => {
// 初始数据加载完成后再刷新 git 摘要,确保 workspace/project_path 已就绪
this.refreshProjectGitSummary?.();
// 避免在初始加载阶段被覆盖,加载完成后再兜底检查一次
this.checkTutorialPrompt();
})
.catch(() => {});
}
// 注册全局事件处理器(用于任务轮询)
(window as any).__taskEventHandler = (event: any) => {
if (typeof this.handleTaskEvent === 'function') {
this.handleTaskEvent(event);
}
};
// 立即尝试恢复运行中的任务(不延迟)
if (typeof this.restoreTaskState === 'function') {
this.restoreTaskState();
}
document.addEventListener('click', this.handleClickOutsideQuickMenu);
document.addEventListener('click', this.handleClickOutsideHeaderMenu);
document.addEventListener('click', this.handleClickOutsideMobileMenu);
document.addEventListener('click', this.handleCopyCodeClick);
window.addEventListener('popstate', this.handlePopState);
window.addEventListener('keydown', this.handleMobileOverlayEscape);
window.addEventListener('beforeunload', this.handleBeforeUnloadDraftPersist);
this.subAgentFetch();
this.backgroundCommandFetch();
this.$nextTick(() => {
this.autoResizeInput();
});
this.resourceBindContainerVisibilityWatcher();
this.resourceStartContainerStatsPolling();
this.resourceStartProjectStoragePolling();
this.resourceStartUsageQuotaPolling();
// 设置拖拽上传
this.setupDragAndDrop();
}
export function beforeUnmount() {
if (this._todoRefreshTimer) {
clearTimeout(this._todoRefreshTimer);
this._todoRefreshTimer = null;
}
// 停止任务轮询
try {
const { useTaskStore } = require('../stores/task');
const taskStore = useTaskStore();
taskStore.stopPolling();
} catch (error) {
// ignore
}
document.removeEventListener('click', this.handleClickOutsideQuickMenu);
document.removeEventListener('click', this.handleClickOutsideHeaderMenu);
document.removeEventListener('click', this.handleClickOutsideMobileMenu);
document.removeEventListener('click', this.handleCopyCodeClick);
window.removeEventListener('popstate', this.handlePopState);
window.removeEventListener('keydown', this.handleMobileOverlayEscape);
window.removeEventListener('beforeunload', this.handleBeforeUnloadDraftPersist);
this.teardownMobileViewportWatcher();
this.stopProjectGitSummaryIdleRefresh?.();
this.stopTerminalCountIdleRefresh?.();
this.resourceStopContainerStatsPolling();
this.resourceStopProjectStoragePolling();
this.resourceStopUsageQuotaPolling();
this.stopConnectionHeartbeat();
teardownShowImageObserver();
// 移除拖拽上传监听
this.teardownDragAndDrop();
if (this.titleTypingTimer) {
clearInterval(this.titleTypingTimer);
this.titleTypingTimer = null;
}
const cleanup = this.destroyEasterEggEffect(true);
if (cleanup && typeof cleanup.catch === 'function') {
cleanup.catch(() => {});
}
}