refactor: optimize the display for input image

This commit is contained in:
2025-10-30 19:59:38 +08:00
parent 1f138f5097
commit f00ec0588c
2 changed files with 65 additions and 10 deletions

View File

@@ -20,6 +20,20 @@
box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.15); box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.15);
} }
/* 禁用态:浅灰背景与文字,明确不可编辑 */
.input-panel .ant-input[disabled],
.input-panel .ant-input-disabled,
.input-panel .ant-input-outlined.ant-input-disabled {
background: #f3f4f6; /* gray-100 */
color: #9ca3af; /* gray-400 */
border-color: #e5e7eb; /* gray-200 */
cursor: not-allowed;
-webkit-text-fill-color: #9ca3af; /* Safari 禁用态颜色 */
}
.input-panel .ant-input[disabled]::placeholder {
color: #cbd5e1; /* gray-300 */
}
.input-actions { .input-actions {
display: flex; display: flex;
align-items: center; align-items: center;
@@ -28,4 +42,15 @@
} }
.input-actions .ant-btn-text { color: var(--text-secondary); } .input-actions .ant-btn-text { color: var(--text-secondary); }
.input-actions .ant-btn-text:hover { color: var(--color-primary-600); } .input-actions .ant-btn-text:hover { color: var(--color-primary-600); }
/* 左侧文件标签样式,保持短名及紧凑展示 */
.selected-image-tag {
max-width: 60%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
margin-right: auto; /* 保持标签在左侧,按钮在右侧 */
}
/* 移除右侧容器样式,按钮直接在 input-actions 中对齐 */

View File

@@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import { Input, Upload, message, Button, Spin } from 'antd'; import { Input, Upload, message, Button, Spin, Tag } from 'antd';
import { PictureOutlined, SendOutlined, LoadingOutlined, SearchOutlined } from '@ant-design/icons'; import { PictureOutlined, SendOutlined, LoadingOutlined, SearchOutlined } from '@ant-design/icons';
import { postInput, postInputImage, getPeoples } from '../apis'; import { postInput, postInputImage, getPeoples } from '../apis';
import './InputPanel.css'; import './InputPanel.css';
@@ -16,6 +16,7 @@ const InputPanel: React.FC<InputPanelProps> = ({ onResult, showUpload = true, mo
const [value, setValue] = React.useState(''); const [value, setValue] = React.useState('');
const [fileList, setFileList] = React.useState<any[]>([]); const [fileList, setFileList] = React.useState<any[]>([]);
const [loading, setLoading] = React.useState(false); const [loading, setLoading] = React.useState(false);
const [savedText, setSavedText] = React.useState<string>('');
// 统一显示短文件名image.{ext} // 统一显示短文件名image.{ext}
const getImageExt = (file: any): string => { const getImageExt = (file: any): string => {
@@ -95,6 +96,7 @@ const InputPanel: React.FC<InputPanelProps> = ({ onResult, showUpload = true, mo
// 清空输入 // 清空输入
setValue(''); setValue('');
setFileList([]); setFileList([]);
setSavedText('');
} else { } else {
message.error(response.error_info || '处理失败,请重试'); message.error(response.error_info || '处理失败,请重试');
} }
@@ -154,6 +156,10 @@ const InputPanel: React.FC<InputPanelProps> = ({ onResult, showUpload = true, mo
} as any; } as any;
// 仅保留一张:新图直接替换旧图 // 仅保留一张:新图直接替换旧图
if (fileList.length === 0) {
setSavedText(value);
}
setValue('');
setFileList([entry]); setFileList([entry]);
message.success('已添加剪贴板图片'); message.success('已添加剪贴板图片');
} }
@@ -166,39 +172,63 @@ const InputPanel: React.FC<InputPanelProps> = ({ onResult, showUpload = true, mo
tip="正在处理中,请稍候..." tip="正在处理中,请稍候..."
indicator={<LoadingOutlined style={{ fontSize: 24 }} spin />} indicator={<LoadingOutlined style={{ fontSize: 24 }} spin />}
> >
{/** 根据禁用状态动态占位符文案 */}
{(() => {
return null;
})()}
<TextArea <TextArea
value={value} value={value}
onChange={(e) => setValue(e.target.value)} onChange={(e) => setValue(e.target.value)}
placeholder={showUpload ? '请输入个人信息描述,或上传图片…' : '请输入个人信息描述…'} placeholder={
showUpload && fileList.length > 0
? '不可在添加图片时输入信息...'
: (showUpload ? '请输入个人信息描述,或上传图片…' : '请输入个人信息描述…')
}
autoSize={{ minRows: 6, maxRows: 12 }} autoSize={{ minRows: 6, maxRows: 12 }}
style={{ fontSize: 14 }} style={{ fontSize: 16 }}
onKeyDown={onKeyDown} onKeyDown={onKeyDown}
onPaste={onPaste} onPaste={onPaste}
disabled={loading} disabled={loading || (showUpload && fileList.length > 0)}
/> />
</Spin> </Spin>
<div className="input-actions"> <div className="input-actions">
{/* 左侧文件标签显示 */}
{showUpload && fileList.length > 0 && (
<Tag
className="selected-image-tag"
color="processing"
closable
onClose={() => { setFileList([]); setValue(savedText); setSavedText(''); }}
bordered={false}
>
{`image.${new Date().getSeconds()}.${getImageExt(fileList[0]?.originFileObj || fileList[0])}`}
</Tag>
)}
{showUpload && ( {showUpload && (
<Upload <Upload
accept="image/*" accept="image/*"
multiple={false} multiple={false}
beforeUpload={() => false} beforeUpload={() => false}
fileList={fileList} fileList={fileList}
onChange={({ file, fileList }) => { onChange={({ file, fileList: nextFileList }) => {
// 只保留最新一个,并重命名为 image.{ext} // 只保留最新一个,并重命名为 image.{ext}
if (fileList.length === 0) { if (nextFileList.length === 0) {
setFileList([]); setFileList([]);
return; return;
} }
const latest = fileList[fileList.length - 1] as any; const latest = nextFileList[nextFileList.length - 1] as any;
const raw = latest.originFileObj || file; // UploadFile 或原始 File const raw = latest.originFileObj || file; // UploadFile 或原始 File
const ext = getImageExt(raw); const ext = getImageExt(raw);
const renamed = { ...latest, name: `image.${ext}` }; const renamed = { ...latest, name: `image.${ext}` };
if (fileList.length === 0) {
setSavedText(value);
}
setValue('');
setFileList([renamed]); setFileList([renamed]);
}} }}
onRemove={() => { setFileList([]); return true; }} onRemove={() => { setFileList([]); setValue(savedText); setSavedText(''); return true; }}
maxCount={1} maxCount={1}
showUploadList={{ showPreviewIcon: false, showRemoveIcon: true }} showUploadList={false}
disabled={loading} disabled={loading}
> >
<Button type="text" icon={<PictureOutlined />} disabled={loading} /> <Button type="text" icon={<PictureOutlined />} disabled={loading} />