feat(inspiration-board): 添加提示词工具快捷入口
在灵感创意板块标题右侧添加"提示词"按钮,点击后可在画布中心打开香蕉提示词工具,复用工具箱的插入逻辑。
This commit is contained in:
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;
|
||||
/** 自定义类名 */
|
||||
|
||||
Reference in new issue
Block a user