agent-Specialization/static/src/app/computed.ts
JOJO 05e8ea5e40 feat(frontend): 输入栏现代化重设计 + 配套高度/配色修复
- 输入栏由体育场形改为圆角矩形,输入区与按钮行分离
- +/发送按钮移至底部行(左下/右下),缩小尺寸、圆角 hover、同心圆角对齐
- 发送按钮去光晕:浅色黑底白三角、深色白底黑三角,仅留浅阴影
- logo 旁思考模式按钮去除扩散光晕,focus 仅留描边环
- 对话区预留高度基准 80→90 适配更高输入栏,欢迎语 padding 同步加大
- /菜单命令名配色:经典 accent 橙、浅/深色保留 state-info 蓝
- /菜单及深色 + 菜单 hover 统一为侧边栏同款 --theme-tab-active(修复深色全黑)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 18:25:20 +08:00

223 lines
6.8 KiB
TypeScript

// @ts-nocheck
import { mapState, mapWritableState } from 'pinia';
import { useConnectionStore } from '../stores/connection';
import { useFileStore } from '../stores/file';
import { useUiStore } from '../stores/ui';
import { useConversationStore } from '../stores/conversation';
import { useModelStore } from '../stores/model';
import { useChatStore } from '../stores/chat';
import { useInputStore } from '../stores/input';
import { useToolStore } from '../stores/tool';
import { useResourceStore } from '../stores/resource';
import { useFocusStore } from '../stores/focus';
import { useUploadStore } from '../stores/upload';
import { useMonitorStore } from '../stores/monitor';
import { usePolicyStore } from '../stores/policy';
export const computed = {
...mapWritableState(useConnectionStore, [
'isConnected',
'socket',
'stopRequested',
'projectPath',
'agentVersion',
'thinkingMode',
'runMode'
]),
...mapState(useFileStore, ['contextMenu', 'fileTree', 'expandedFolders', 'todoList']),
...mapWritableState(useUiStore, [
'sidebarCollapsed',
'workspaceCollapsed',
'chatDisplayMode',
'panelMode',
'panelMenuOpen',
'leftWidth',
'rightWidth',
'rightCollapsed',
'isResizing',
'resizingPanel',
'minPanelWidth',
'maxPanelWidth',
'quotaToast',
'toastQueue',
'confirmDialog',
'easterEgg',
'isMobileViewport',
'mobileOverlayMenuOpen',
'activeMobileOverlay'
]),
...mapWritableState(useConversationStore, [
'conversations',
'conversationsLoading',
'hasMoreConversations',
'loadingMoreConversations',
'currentConversationId',
'currentConversationTitle',
'searchQuery',
'searchTimer',
'searchResults',
'conversationInsertAnimations',
'conversationListAnimationMode',
'pendingDeletingConversationIds',
'searchActive',
'searchInProgress',
'searchMoreAvailable',
'searchOffset',
'searchTotal',
'conversationsOffset',
'conversationsLimit',
'runningWorkspaceTasks',
'acknowledgedCompletedTaskIds'
]),
...mapWritableState(useModelStore, ['currentModelKey']),
...mapState(useModelStore, ['models']),
...mapWritableState(useChatStore, [
'messages',
'currentMessageIndex',
'streamingMessage',
'expandedBlocks',
'autoScrollEnabled',
'userScrolling',
'thinkingScrollLocks'
]),
...mapWritableState(useInputStore, [
'inputMessage',
'inputLineCount',
'inputIsMultiline',
'inputIsFocused',
'quickMenuOpen',
'toolMenuOpen',
'settingsOpen',
'imagePickerOpen',
'videoPickerOpen',
'selectedImages',
'selectedVideos',
'goalModeArmed',
'goalRunning',
'goalProgress',
'goalDialogOpen'
]),
resolvedRunMode() {
const allowed = ['fast', 'thinking', 'deep'];
if (allowed.includes(this.runMode)) {
return this.runMode;
}
return this.thinkingMode ? 'thinking' : 'fast';
},
headerRunModeOptions() {
return [
{ value: 'fast', label: '快速模式', desc: '低思考,响应更快' },
{ value: 'thinking', label: '思考模式', desc: '更长思考,综合回答' },
{ value: 'deep', label: '深度思考', desc: '持续推理,适合复杂任务' }
];
},
headerRunModeLabel() {
const current = this.headerRunModeOptions.find((o) => o.value === this.resolvedRunMode);
return current ? current.label : '快速模式';
},
currentModelLabel() {
const modelStore = useModelStore();
return modelStore.currentModel?.label || '未选择模型';
},
policyUiBlocks() {
const store = usePolicyStore();
return store.uiBlocks || {};
},
adminDisabledModels() {
const store = usePolicyStore();
return store.disabledModelSet;
},
modelOptions() {
const disabledSet = this.adminDisabledModels || new Set();
const options = this.models || [];
return options.map((opt) => ({
...opt,
disabled: disabledSet.has(opt.key)
}));
},
titleRibbonVisible() {
return !this.isMobileViewport && this.chatDisplayMode === 'chat';
},
chatContainerStyle() {
const minHeight = 90;
const raw = Number(this.composerReservedHeight || 0);
const height = Number.isFinite(raw) ? Math.max(minHeight, Math.round(raw)) : minHeight;
const growth = Math.max(0, height - minHeight);
return {
'--composer-base-height': `calc(${minHeight}px + var(--app-bottom-inset, 0px))`,
'--composer-reserved-height': `calc(${height}px + var(--app-bottom-inset, 0px))`,
'--composer-growth-height': `${growth}px`
};
},
...mapWritableState(useToolStore, [
'preparingTools',
'activeTools',
'toolActionIndex',
'toolStacks',
'toolSettings',
'toolSettingsLoading'
]),
...mapWritableState(useResourceStore, [
'tokenPanelCollapsed',
'currentContextTokens',
'currentConversationTokens',
'projectStorage',
'containerStatus',
'containerNetRate',
'usageQuota'
]),
...mapWritableState(useFocusStore, ['focusedFiles']),
...mapWritableState(useUploadStore, ['uploading', 'mediaUploading']),
...mapState(useMonitorStore, {
monitorIsLocked: (store) => store.isLocked
}),
displayModeSwitchDisabled() {
return !!this.policyUiBlocks.block_virtual_monitor;
},
displayLockEngaged() {
return !!this.compressionInProgress || !!this.compressing || !!this.currentWorkspaceHasRunningTask;
},
currentWorkspaceHasRunningTask() {
if (!(this.versioningHostMode || this.dockerProjectMode) || !this.currentHostWorkspaceId) {
return false;
}
const tasks = Array.isArray(this.runningWorkspaceTasks) ? this.runningWorkspaceTasks : [];
return tasks.some((task: any) => {
const status = String(task?.status || '');
return (
task?.workspace_id === this.currentHostWorkspaceId &&
task?.conversation_id !== this.currentConversationId &&
['pending', 'running', 'cancel_requested'].includes(status)
);
});
},
streamingUi() {
return this.streamingMessage || this.hasPendingToolActions();
},
composerBusy() {
const monitorLock = this.monitorIsLocked && this.chatDisplayMode === 'monitor';
return (
this.streamingUi ||
this.taskInProgress ||
monitorLock ||
this.stopRequested ||
this.compressionInProgress ||
this.compressing
);
},
composerStreamingForInput() {
return this.composerBusy && !this.displayLockEngaged;
},
composerHeroActive() {
return (this.blankHeroActive || this.blankHeroExiting) && !this.composerInteractionActive;
},
composerInteractionActive() {
const hasText = !!(this.inputMessage && this.inputMessage.trim().length > 0);
const hasImages = Array.isArray(this.selectedImages) && this.selectedImages.length > 0;
return this.quickMenuOpen || hasText || hasImages;
},
showScrollToBottomButton() {
return this.chatDisplayMode === 'chat' && !this.stickIsNearBottom;
}
};