feat(clipping): implement hide/recover toggle for all section dialogs
Update all three section dialogs to support hide/show toggle: SectionAxisDialogManager: - onHideToggle now calls hideSection()/recoverSection() SectionBoxDialogManager: - onHideToggle now calls hideSection()/recoverSection() SectionPlanePanel: - Add isHidden state tracking - Change onHide to onHideToggle(isHidden) - Add setHiddenState/getHiddenState methods - Update button to toggle active state SectionPlaneDialogManager: - Switch to onHideToggle callback - Call hideSection()/recoverSection() based on toggle state Behavior: Click hide button to hide section, click again to recover.
This commit is contained in:
199
src/managers/ai-chat-manager.ts
Normal file
199
src/managers/ai-chat-manager.ts
Normal file
@@ -0,0 +1,199 @@
|
||||
/**
|
||||
* AI 聊天管理器
|
||||
* 负责管理 AI 聊天抽屉的显示、隐藏和消息交互
|
||||
*/
|
||||
import { AiChat } from '../components/ai-chat';
|
||||
import type { Message, QuestionOption, StepStatus } from '../components/ai-chat/types';
|
||||
import { ManagerRegistry } from '../core/manager-registry';
|
||||
|
||||
/**
|
||||
* AI 聊天管理器
|
||||
* 管理 AI 聊天组件的生命周期和消息交互
|
||||
*/
|
||||
export class AiChatManager {
|
||||
/** AI 聊天组件实例 */
|
||||
private aiChat: AiChat | null = null;
|
||||
/** Manager 注册表 */
|
||||
private registry: ManagerRegistry;
|
||||
/** 是否已初始化 */
|
||||
private initialized = false;
|
||||
|
||||
constructor() {
|
||||
this.registry = ManagerRegistry.getInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化 AI 聊天组件
|
||||
* 创建 AiChat 实例并注册事件
|
||||
*/
|
||||
public init(): void {
|
||||
if (this.initialized) return;
|
||||
|
||||
const wrapper = this.registry.wrapper;
|
||||
if (!wrapper) {
|
||||
console.warn('[AiChatManager] wrapper 不存在,无法初始化');
|
||||
return;
|
||||
}
|
||||
|
||||
this.aiChat = new AiChat({
|
||||
container: wrapper,
|
||||
width: 440,
|
||||
title: 'aiChat.title',
|
||||
placeholder: 'aiChat.placeholder',
|
||||
quickPrompts: [
|
||||
{ id: 'summarize', label: 'aiChat.quickPrompt.summarize' },
|
||||
{ id: 'explain', label: 'aiChat.quickPrompt.explain' },
|
||||
{ id: 'generate', label: 'aiChat.quickPrompt.generate' }
|
||||
],
|
||||
onSend: (message) => {
|
||||
console.log('[AiChatManager] 用户发送消息:', message);
|
||||
this.aiChat?.addUserMessage(message);
|
||||
this.registry.emit('aiChat:message-sent', { message });
|
||||
},
|
||||
onQuestionSubmit: (questionId, optionId, customAnswer) => {
|
||||
console.log('[AiChatManager] 用户回答问题:', { questionId, optionId, customAnswer });
|
||||
this.registry.emit('aiChat:question-answered', { questionId, optionId, customAnswer });
|
||||
},
|
||||
onNewChat: () => {
|
||||
console.log('[AiChatManager] 新建对话');
|
||||
this.registry.emit('aiChat:new-chat', {});
|
||||
},
|
||||
onHistory: () => {
|
||||
console.log('[AiChatManager] 打开历史');
|
||||
this.registry.emit('aiChat:history-opened', {});
|
||||
},
|
||||
onSettings: () => {
|
||||
console.log('[AiChatManager] 打开设置');
|
||||
this.registry.emit('aiChat:settings-opened', {});
|
||||
},
|
||||
onClose: () => {
|
||||
console.log('[AiChatManager] 关闭 AI 聊天');
|
||||
this.registry.emit('aiChat:closed', {});
|
||||
this.registry.toolbar?.setBtnActive('aiChat', false);
|
||||
}
|
||||
});
|
||||
|
||||
this.initialized = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示 AI 聊天抽屉
|
||||
*/
|
||||
public show(): void {
|
||||
if (!this.aiChat) {
|
||||
this.init();
|
||||
}
|
||||
this.aiChat?.show();
|
||||
this.registry.emit('aiChat:opened', {});
|
||||
this.registry.toolbar?.setBtnActive('aiChat', true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 隐藏 AI 聊天抽屉
|
||||
*/
|
||||
public hide(): void {
|
||||
this.aiChat?.hide();
|
||||
this.registry.emit('aiChat:closed', {});
|
||||
this.registry.toolbar?.setBtnActive('aiChat', false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换 AI 聊天抽屉显示状态
|
||||
*/
|
||||
public toggle(): void {
|
||||
if (this.aiChat?.isVisible()) {
|
||||
this.hide();
|
||||
} else {
|
||||
this.show();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查 AI 聊天抽屉是否可见
|
||||
*/
|
||||
public isVisible(): boolean {
|
||||
return this.aiChat?.isVisible() ?? false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加用户消息
|
||||
* @param content 消息内容
|
||||
* @returns 消息 ID
|
||||
*/
|
||||
public addUserMessage(content: string): string {
|
||||
return this.aiChat?.addUserMessage(content) ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加 AI 消息
|
||||
* @param content 消息内容
|
||||
* @returns 消息 ID
|
||||
*/
|
||||
public addAiMessage(content: string): string {
|
||||
return this.aiChat?.addAiMessage(content) ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加步骤消息
|
||||
* @param status 步骤状态
|
||||
* @param content 步骤描述
|
||||
* @returns 消息 ID
|
||||
*/
|
||||
public addStepMessage(status: StepStatus, content: string): string {
|
||||
return this.aiChat?.addStepMessage(status, content) ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加思考中消息
|
||||
* @returns 消息 ID
|
||||
*/
|
||||
public addThinkingMessage(): string {
|
||||
return this.aiChat?.addThinkingMessage() ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加问答卡片消息
|
||||
* @param title 问题标题
|
||||
* @param question 问题内容
|
||||
* @param options 选项列表
|
||||
* @returns 消息 ID
|
||||
*/
|
||||
public addQuestionMessage(title: string, question: string, options: QuestionOption[]): string {
|
||||
return this.aiChat?.addQuestionMessage(title, question, options) ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新消息
|
||||
* @param id 消息 ID
|
||||
* @param updates 更新内容
|
||||
*/
|
||||
public updateMessage(id: string, updates: Partial<Message>): void {
|
||||
this.aiChat?.updateMessage(id, updates);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除消息
|
||||
* @param id 消息 ID
|
||||
*/
|
||||
public removeMessage(id: string): void {
|
||||
this.aiChat?.removeMessage(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空所有消息
|
||||
*/
|
||||
public clearMessages(): void {
|
||||
this.aiChat?.clearMessages();
|
||||
}
|
||||
|
||||
/**
|
||||
* 销毁 AI 聊天管理器
|
||||
*/
|
||||
public destroy(): void {
|
||||
if (this.aiChat) {
|
||||
this.aiChat.destroy();
|
||||
this.aiChat = null;
|
||||
}
|
||||
this.initialized = false;
|
||||
}
|
||||
}
|
||||
@@ -152,7 +152,7 @@ export class ConstructTreeManagerBtn extends BaseManager {
|
||||
this.dialog = this.registry.dialog!.create({
|
||||
title: 'constructTree.title',
|
||||
minWidth: 320,
|
||||
height: 420,
|
||||
height: 600,
|
||||
content: tabMount,
|
||||
position: { x: 20, y: 20 },
|
||||
resizable: false,
|
||||
|
||||
@@ -57,8 +57,12 @@ export class SectionAxisDialogManager extends BaseDialogManager {
|
||||
defaultAxis: 'x',
|
||||
defaultHidden: false,
|
||||
onHideToggle: (isHidden) => {
|
||||
// 隐藏功能:第三方引擎无 API,仅输出日志
|
||||
console.log('[SectionAxisDialogManager] 隐藏切换(暂不支持):', isHidden);
|
||||
console.log('[SectionAxisDialogManager] 隐藏切换:', isHidden);
|
||||
if (isHidden) {
|
||||
this.registry.engine3d?.hideSection();
|
||||
} else {
|
||||
this.registry.engine3d?.recoverSection();
|
||||
}
|
||||
},
|
||||
onReverse: () => {
|
||||
// 反向功能:第三方引擎无 API,仅输出日志
|
||||
|
||||
@@ -57,8 +57,12 @@ export class SectionBoxDialogManager extends BaseDialogManager {
|
||||
defaultHidden: false,
|
||||
defaultReversed: false,
|
||||
onHideToggle: (isHidden) => {
|
||||
// 底层暂不支持隐藏功能
|
||||
console.log('[SectionBoxDialogManager] 隐藏切换(底层暂不支持):', isHidden);
|
||||
console.log('[SectionBoxDialogManager] 隐藏切换:', isHidden);
|
||||
if (isHidden) {
|
||||
this.registry.engine3d?.hideSection();
|
||||
} else {
|
||||
this.registry.engine3d?.recoverSection();
|
||||
}
|
||||
},
|
||||
onReverseToggle: (isReversed) => {
|
||||
// 底层暂不支持反向功能
|
||||
|
||||
@@ -47,9 +47,14 @@ export class SectionPlaneDialogManager extends BaseDialogManager {
|
||||
/** 创建对话框内容 */
|
||||
protected createContent(): HTMLElement {
|
||||
this.panel = new SectionPlanePanel({
|
||||
onHide: () => {
|
||||
console.log('[SectionPlaneDialogManager] 隐藏剖切面');
|
||||
this.registry.engine3d?.hideSection();
|
||||
defaultHidden: false,
|
||||
onHideToggle: (isHidden) => {
|
||||
console.log('[SectionPlaneDialogManager] 隐藏切换:', isHidden);
|
||||
if (isHidden) {
|
||||
this.registry.engine3d?.hideSection();
|
||||
} else {
|
||||
this.registry.engine3d?.recoverSection();
|
||||
}
|
||||
},
|
||||
onReverse: () => {
|
||||
console.log('[SectionPlaneDialogManager] 反向 (not supported in new API)');
|
||||
|
||||
Reference in New Issue
Block a user