# 前端图片 URL 使用指南

## 概述
后端已优化图片访问方式，现在支持通过 Nginx 静态资源直接访问图片，提高了图片加载效率。

## 图片数据结构

### 聊天消息中的图片
```json
{
  "images": [
    {
      "id": "abc123",
      "url": "/files/img/abc123.jpg",
      "type": "image",
      "source": "文档名.pdf",
      "page": 1,
      "description": "图片描述"
    }
  ]
}
```

## URL 格式说明

### 两种 URL 格式
后端会返回以下两种格式的 URL：
1. **新格式（推荐）：`/files/img/xxx.jpg` - 通过 Nginx 静态资源访问
2. **旧格式（兼容）**：`/api/image/xxx/data` - 通过后端 API 代理访问

## 前端适配说明

### 无需修改的情况
如果您的前端目前使用如下方式处理图片，则无需修改代码：
```javascript
// 直接使用后端返回的 URL
<img src={image.url} alt={image.description} />
```

### 推荐的处理方式
```javascript
// 通用图片加载器
function loadImage(imageData) {
  const imageUrl = imageData.url;
  
  // 直接使用后端返回的 URL
  const img = document.createElement('img');
  img.src = imageUrl;
  img.alt = imageData.description || '图片';
  img.onerror = function() {
    // 图片加载失败时的处理
    console.error('图片加载失败:', imageUrl);
  };
  
  return img;
}
```

### 检查 URL 类型
```javascript
function isNginxUrl(url) {
  return url && url.startsWith('/files/');
}

function isApiUrl(url) {
  return url && url.includes('/api/image/');
}
```

## SSE 流处理示例

### JavaScript 示例
```javascript
const eventSource = new EventSource('/api/chat/stream');

eventSource.onmessage = function(event) {
  const data = JSON.parse(event.data);
  
  if (data.type === 'finish') {
    // 处理图片
    if (data.images && data.images.length > 0) {
      renderImages(data.images);
    }
  }
};

function renderImages(images) {
  const container = document.getElementById('image-container');
  
  images.forEach(image => {
    const img = document.createElement('img');
    img.src = image.url;
    img.alt = image.description || '图片';
    img.style.maxWidth = '100%';
    container.appendChild(img);
    
    // 显示图片描述
    if (image.description) {
      const desc = document.createElement('p');
      desc.textContent = image.description;
      container.appendChild(desc);
    }
  });
}
```

### React 示例
```jsx
function ChatImages({ images }) {
  return (
    <div className="chat-images">
      {images && images.map((image, index) => (
        <div key={index} className="image-item">
          <img 
            src={image.url} 
            alt={image.description}
            className="chat-image"
          />
          {image.description && (
            <div className="image-description">
              {image.description}
            </div>
          )}
        </div>
      ))}
    </div>
  );
}
```

### Vue 示例
```vue
<template>
  <div class="chat-images">
    <div v-for="(image, index) in images" :key="index" class="image-item">
      <img 
        :src="image.url" 
        :alt="image.description"
        class="chat-image"
      />
      <div v-if="image.description" class="image-description">
        {{ image.description }}
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'ChatImages',
  props: {
    images: {
      type: Array,
      default: () => []
    }
  }
}
</script>
```

## 历史记录查看
在查看历史会话时，后端已自动将图片 URL 转换为 Nginx 格式，无需额外处理。

## 注意事项

1. **向后兼容**：后端保留了对旧 URL 格式的支持，以确保旧数据仍然可用
2. **错误处理**：建议添加图片加载失败的错误处理逻辑
3. **相对路径**：`/files/` 开头的 URL 是相对路径，会自动根据当前域名拼接完整地址

## 兼容性
- 无需对现有前端代码进行大量修改
- 两种格式都支持
