| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| |
|
| | import React, { useRef, useEffect, useCallback } from 'react';
|
| | import { Toast } from '@douyinfe/semi-ui';
|
| | import { useTranslation } from 'react-i18next';
|
| | import { usePlayground } from '../../contexts/PlaygroundContext';
|
| |
|
| | const CustomInputRender = (props) => {
|
| | const { t } = useTranslation();
|
| | const { onPasteImage, imageEnabled } = usePlayground();
|
| | const { detailProps } = props;
|
| | const { clearContextNode, uploadNode, inputNode, sendNode, onClick } =
|
| | detailProps;
|
| | const containerRef = useRef(null);
|
| |
|
| | const handlePaste = useCallback(
|
| | async (e) => {
|
| | const items = e.clipboardData?.items;
|
| | if (!items) return;
|
| |
|
| | for (let i = 0; i < items.length; i++) {
|
| | const item = items[i];
|
| |
|
| | if (item.type.indexOf('image') !== -1) {
|
| | e.preventDefault();
|
| | const file = item.getAsFile();
|
| |
|
| | if (file) {
|
| | try {
|
| | if (!imageEnabled) {
|
| | Toast.warning({
|
| | content: t('请先在设置中启用图片功能'),
|
| | duration: 3,
|
| | });
|
| | return;
|
| | }
|
| |
|
| | const reader = new FileReader();
|
| | reader.onload = (event) => {
|
| | const base64 = event.target.result;
|
| |
|
| | if (onPasteImage) {
|
| | onPasteImage(base64);
|
| | Toast.success({
|
| | content: t('图片已添加'),
|
| | duration: 2,
|
| | });
|
| | } else {
|
| | Toast.error({
|
| | content: t('无法添加图片'),
|
| | duration: 2,
|
| | });
|
| | }
|
| | };
|
| | reader.onerror = () => {
|
| | console.error('Failed to read image file:', reader.error);
|
| | Toast.error({
|
| | content: t('粘贴图片失败'),
|
| | duration: 2,
|
| | });
|
| | };
|
| | reader.readAsDataURL(file);
|
| | } catch (error) {
|
| | console.error('Failed to paste image:', error);
|
| | Toast.error({
|
| | content: t('粘贴图片失败'),
|
| | duration: 2,
|
| | });
|
| | }
|
| | }
|
| | break;
|
| | }
|
| | }
|
| | },
|
| | [onPasteImage, imageEnabled, t],
|
| | );
|
| |
|
| | useEffect(() => {
|
| | const container = containerRef.current;
|
| | if (!container) return;
|
| |
|
| | container.addEventListener('paste', handlePaste);
|
| | return () => {
|
| | container.removeEventListener('paste', handlePaste);
|
| | };
|
| | }, [handlePaste]);
|
| |
|
| |
|
| | const styledClearNode = clearContextNode
|
| | ? React.cloneElement(clearContextNode, {
|
| | className: `!rounded-full !bg-gray-100 hover:!bg-red-500 hover:!text-white flex-shrink-0 transition-all ${clearContextNode.props.className || ''}`,
|
| | style: {
|
| | ...clearContextNode.props.style,
|
| | width: '32px',
|
| | height: '32px',
|
| | minWidth: '32px',
|
| | padding: 0,
|
| | display: 'flex',
|
| | alignItems: 'center',
|
| | justifyContent: 'center',
|
| | },
|
| | })
|
| | : null;
|
| |
|
| |
|
| | const styledSendNode = React.cloneElement(sendNode, {
|
| | className: `!rounded-full !bg-purple-500 hover:!bg-purple-600 flex-shrink-0 transition-all ${sendNode.props.className || ''}`,
|
| | style: {
|
| | ...sendNode.props.style,
|
| | width: '32px',
|
| | height: '32px',
|
| | minWidth: '32px',
|
| | padding: 0,
|
| | display: 'flex',
|
| | alignItems: 'center',
|
| | justifyContent: 'center',
|
| | },
|
| | });
|
| |
|
| | return (
|
| | <div className='p-2 sm:p-4' ref={containerRef}>
|
| | <div
|
| | className='flex items-center gap-2 sm:gap-3 p-2 bg-gray-50 rounded-xl sm:rounded-2xl shadow-sm hover:shadow-md transition-shadow'
|
| | style={{ border: '1px solid var(--semi-color-border)' }}
|
| | onClick={onClick}
|
| | title={t('支持 Ctrl+V 粘贴图片')}
|
| | >
|
| | {/* 清空对话按钮 - 左边 */}
|
| | {styledClearNode}
|
| | <div className='flex-1'>{inputNode}</div>
|
| | {/* 发送按钮 - 右边 */}
|
| | {styledSendNode}
|
| | </div>
|
| | </div>
|
| | );
|
| | };
|
| |
|
| | export default CustomInputRender;
|
| |
|