feat(inspiration-board): 添加提示词工具快捷入口

在灵感创意板块标题右侧添加"提示词"按钮,点击后可在画布中心打开香蕉提示词工具,复用工具箱的插入逻辑。
This commit is contained in:
gongchengtu committed 2026-01-08 14:34:43 +08:00
1 parent bb52bc6fb0
commit c2ff40aa82
4 files changed
+98 -2

No files matched your search

@@ -19,7 +19,7 @@ import React, { useState, useEffect, useCallback, useRef, useMemo } from 'react'
import { Send, Check, ImagePlus } from 'lucide-react';
import { useBoard } from '@plait-board/react-board';
import { SelectedContentPreview } from '../shared/SelectedContentPreview';
import { getSelectedElements, ATTACHED_ELEMENT_CLASS_NAME, getRectangleByElements } from '@plait/core';
import { getSelectedElements, ATTACHED_ELEMENT_CLASS_NAME, getRectangleByElements, PlaitBoard, getViewportOrigination } from '@plait/core';
import { useI18n } from '../../i18n';
import { TaskStatus } from '../../types/task.types';
import { taskQueueService } from '../../services/task-queue-service';
@@ -31,6 +31,7 @@ import { SizeDropdown } from './SizeDropdown';
import { PromptHistoryPopover } from './PromptHistoryPopover';
import { usePromptHistory } from '../../hooks/usePromptHistory';
import { getDefaultImageModel, IMAGE_MODELS, getModelConfig, getDefaultSizeForModel } from '../../constants/model-config';
import { BUILT_IN_TOOLS, DEFAULT_TOOL_CONFIG } from '../../constants/built-in-tools';
import { initializeMCP, setCanvasBoard, setBoard, mcpRegistry } from '../../mcp';
import { initializeLongVideoChainService } from '../../services/long-video-chain-service';
import { gridImageService } from '../../services/photo-wall';
@@ -49,6 +50,7 @@ import type { WorkflowRetryContext, PostProcessingStatus } from '../../types/cha
import { workflowCompletionService } from '../../services/workflow-completion-service';
import { BoardTransforms } from '@plait/core';
import { WorkZoneTransforms } from '../../plugins/with-workzone';
import { ToolTransforms } from '../../plugins/with-tool';
import type { PlaitWorkZone } from '../../types/workzone.types';
/**
@@ -533,6 +535,53 @@ export const AIInputBar: React.FC<AIInputBarProps> = React.memo(({ className })
inputRef.current?.focus();
}, []);
// 处理打开提示词工具(香蕉提示词)- 复用工具箱的逻辑
const handleOpenPromptTool = useCallback(() => {
const board = SelectionWatcherBoardRef.current;
if (!board) {
console.warn('[AIInputBar] Board not ready for prompt tool');
return;
}
// 从内置工具列表中获取香蕉提示词工具配置
const tool = BUILT_IN_TOOLS.find(t => t.id === 'banana-prompt');
if (!tool) {
console.warn('[AIInputBar] Banana prompt tool not found');
return;
}
// 计算画布中心位置(与 ToolboxDrawer 相同的逻辑)
const boardContainerRect = PlaitBoard.getBoardContainer(board).getBoundingClientRect();
const focusPoint = [
boardContainerRect.width / 2,
boardContainerRect.height / 2,
];
const zoom = board.viewport.zoom;
const origination = getViewportOrigination(board);
const centerX = origination![0] + focusPoint[0] / zoom;
const centerY = origination![1] + focusPoint[1] / zoom;
// 工具尺寸
const width = tool.defaultWidth || DEFAULT_TOOL_CONFIG.defaultWidth;
const height = tool.defaultHeight || DEFAULT_TOOL_CONFIG.defaultHeight;
// 插入到画布(中心对齐)
ToolTransforms.insertTool(
board,
tool.id,
tool.url,
[centerX - width / 2, centerY - height / 2],
{ width, height },
{
name: tool.name,
category: tool.category,
permissions: tool.permissions,
}
);
console.log('[AIInputBar] Prompt tool inserted to canvas');
}, []);
// 处理上传按钮点击
const handleUploadClick = useCallback(() => {
fileInputRef.current?.click();
@@ -1386,6 +1435,7 @@ export const AIInputBar: React.FC<AIInputBarProps> = React.memo(({ className })
<InspirationBoard
isCanvasEmpty={isCanvasEmpty}
onSelectPrompt={handleSelectInspirationPrompt}
onOpenPromptTool={handleOpenPromptTool}
/>
{/* Main input container - flex-column-reverse to expand upward */}
@@ -6,6 +6,7 @@
import React, { useState, useCallback } from 'react';
import { ChevronLeftIcon, ChevronRightIcon } from 'tdesign-icons-react';
import { Lightbulb } from 'lucide-react';
import { InspirationCard } from './InspirationCard';
import { INSPIRATION_TEMPLATES, ITEMS_PER_PAGE } from './constants';
import type { InspirationBoardProps } from './types';
@@ -14,6 +15,7 @@ import './inspiration-board.scss';
export const InspirationBoard: React.FC<InspirationBoardProps> = ({
isCanvasEmpty,
onSelectPrompt,
onOpenPromptTool,
visible = true,
className = '',
}) => {
@@ -57,10 +59,24 @@ export const InspirationBoard: React.FC<InspirationBoardProps> = ({
<div
className={`inspiration-board ${className}`}
>
{/* 头部:标题 + 切换按钮 */}
{/* 头部:标题 + 提示词按钮 + 切换按钮 */}
<div className="inspiration-board__header">
<h3 className="inspiration-board__title">灵感创意</h3>
{/* 提示词工具按钮 */}
{onOpenPromptTool && (
<button
className="inspiration-board__prompt-btn"
onClick={onOpenPromptTool}
onMouseDown={(e) => e.preventDefault()}
title="提示词工具"
data-track="inspiration_click_prompt_tool"
>
<Lightbulb size={14} />
<span>提示词</span>
</button>
)}
{hasMultiplePages && (
<div className="inspiration-board__pagination">
<span className="inspiration-board__page-indicator">
@@ -41,6 +41,34 @@ $animation-duration: 0.3s;
font-size: 14px;
font-weight: 600;
color: var(--td-text-color-primary);
flex: 1; // 占据剩余空间,把右侧按钮推到最右边
}
// 提示词工具按钮
&__prompt-btn {
display: flex;
align-items: center;
gap: 4px;
padding: 4px 10px;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 12px;
font-weight: 500;
transition: all 0.2s ease;
margin-right: 8px;
&:active {
transform: scale(0.97);
}
svg {
flex-shrink: 0;
}
}
&__pagination {
@@ -44,6 +44,8 @@ export interface InspirationBoardProps {
isCanvasEmpty: boolean;
/** 选择提示词回调 */
onSelectPrompt: (prompt: string) => void;
/** 打开提示词工具回调 */
onOpenPromptTool?: () => void;
/** 外部控制显示(可选) */
visible?: boolean;
/** 自定义类名 */