fix: improve image block layout and spacing (#9754)

- Adjust image block margin from 10px to 1em for better consistency
- Fix single vs multi-image display logic with proper layout
- Update ImageBlock component to handle single/multi display modes
- Fix image model detection logic for better compatibility
- Improve overall spacing between content blocks

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
亢奋猫 2025-09-01 12:44:24 +08:00 committed by GitHub
parent de8c7dbc93
commit f599b2c846
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 38 additions and 17 deletions

View File

@ -202,7 +202,7 @@
img {
max-width: 100%;
height: auto;
margin: 10px 0;
margin: 1em 0;
}
a,
@ -321,6 +321,10 @@ emoji-picker {
--border-size: 0;
}
.block-wrapper + .block-wrapper {
margin-top: 1em;
}
.katex,
mjx-container {
display: inline-block;

View File

@ -3045,10 +3045,8 @@ export function isGenerateImageModel(model: Model): boolean {
}
const modelId = getLowerBaseModelName(model.id, '/')
if (GENERATE_IMAGE_MODELS.includes(modelId)) {
return true
}
return false
return GENERATE_IMAGE_MODELS.some((imageModel) => modelId.includes(imageModel))
}
export function isSupportedDisableGenerationModel(model: Model): boolean {

View File

@ -7,32 +7,42 @@ import styled from 'styled-components'
interface Props {
block: ImageMessageBlock
isSingle?: boolean
}
const ImageBlock: React.FC<Props> = ({ block }) => {
if (block.status === MessageBlockStatus.PENDING) return <Skeleton.Image active style={{ width: 200, height: 200 }} />
const ImageBlock: React.FC<Props> = ({ block, isSingle = false }) => {
if (block.status === MessageBlockStatus.PENDING) {
return <Skeleton.Image active style={{ width: 200, height: 200 }} />
}
if (block.status === MessageBlockStatus.STREAMING || block.status === MessageBlockStatus.SUCCESS) {
const images = block.metadata?.generateImageResponse?.images?.length
? block.metadata?.generateImageResponse?.images
: block?.file
? [`file://${FileManager.getFilePath(block?.file)}`]
: []
return (
<Container>
{images.map((src, index) => (
<ImageViewer
src={src}
key={`image-${index}`}
style={{ maxWidth: 500, maxHeight: 'min(500px, 50vh)', padding: 0, borderRadius: 8 }}
style={
isSingle
? { maxWidth: 500, maxHeight: 'min(500px, 50vh)', padding: 0, borderRadius: 8 }
: { width: 280, height: 280, objectFit: 'cover', padding: 0, borderRadius: 8 }
}
/>
))}
</Container>
)
} else return null
}
return null
}
const Container = styled.div`
display: flex;
flex-direction: row;
gap: 10px;
display: block;
`
export default React.memo(ImageBlock)

View File

@ -87,11 +87,20 @@ const MessageBlockRenderer: React.FC<Props> = ({ blocks, message }) => {
{groupedBlocks.map((block) => {
if (Array.isArray(block)) {
const groupKey = block.map((imageBlock) => imageBlock.id).join('-')
// 单张图片不使用 ImageBlockGroup 包装
if (block.length === 1) {
return (
<AnimatedBlockWrapper key={groupKey} enableAnimation={message.status.includes('ing')}>
<ImageBlock key={block[0].id} block={block[0] as ImageMessageBlock} isSingle={true} />
</AnimatedBlockWrapper>
)
}
// 多张图片使用 ImageBlockGroup 包装
return (
<AnimatedBlockWrapper key={groupKey} enableAnimation={message.status.includes('ing')}>
<ImageBlockGroup count={block.length}>
{block.map((imageBlock) => (
<ImageBlock key={imageBlock.id} block={imageBlock as ImageMessageBlock} />
<ImageBlock key={imageBlock.id} block={imageBlock as ImageMessageBlock} isSingle={false} />
))}
</ImageBlockGroup>
</AnimatedBlockWrapper>
@ -166,8 +175,8 @@ const MessageBlockRenderer: React.FC<Props> = ({ blocks, message }) => {
export default React.memo(MessageBlockRenderer)
const ImageBlockGroup = styled.div<{ count: number }>`
display: grid;
grid-template-columns: repeat(${({ count }) => Math.min(count, 3)}, minmax(200px, 1fr));
gap: 8px;
max-width: 960px;
display: flex;
flex-wrap: wrap;
gap: 10px;
max-width: 100%;
`