《60天AI学习计划启动 | Day 31:前端 + 多模态 AI(图片 / 文件 / 截图》

Day 31:前端 + 多模态 AI(图片 / 文件 / 截图)

学习目标

  • 理解 前端如何把图片/文件接入 AI(不只文本)
  • 掌握 基础多模态场景:图片描述、表格截图识别、PDF/Excel 解析入口
  • 会设计 通用的「上传 → 预览 → 调用 AI → 展示结果」前端流程

核心知识点

  • 多模态入口形态

    • 上传文件:图片(JPG/PNG)、PDF、Excel、纯文本
    • 截图/粘贴onPaste + DataTransfer 处理图片/富文本
    • 拖拽dragover/drop 区域快速投喂文件
    • 统一抽象:{ id, type: 'image'|'pdf'|'excel'|'text', file|url|content, meta }
  • 与后端交互模式

    • 模式 A:先上传 → 返回 fileId/url → 携带 question + files[] 调 AI
    • 模式 B:前端直接读小文件内容(txt/csv),拼进 prompt 作为 context
    • Payload 示例:
      {
        "question": "帮我总结这张表格的关键信息",
        "files": [
          { "id": "file_xxx", "type": "image", "url": "https://..." }
        ]
      }
      
  • UI / UX 要点

    • 上传区:空态 / 上传中 / 成功 / 失败
    • 文件列表:名称、类型、大小、删除、缩略图/图标预览
    • 与聊天结合:消息中展示「附带了 N 个文件」+ 可点击预览;AI 回答中可以引用「文件1」

实战作业 + 代码示例

  • 作业 1:多模态输入组件 props
export type MultiModalFileType = 'image' | 'pdf' | 'excel' | 'text' | 'other'

export interface MultiModalFile {
  id: string
  type: MultiModalFileType
  file: File
  previewUrl?: string
  meta?: Record<string, any>
}

export interface MultiModalInputProps {
  acceptTypes?: string[]
  maxSize?: number
  multiple?: boolean
  maxCount?: number
  disabled?: boolean
  onFilesChange: (files: MultiModalFile[]) => void
  onError?: (msg: string) => void
}
  • 作业 2:图片 + 问题调用流程(简化版)
function ImageQA() {
  const [file, setFile] = useState<File | null>(null)
  const [preview, setPreview] = useState<string | null>(null)
  const [question, setQuestion] = useState('')
  const [answer, setAnswer] = useState('')
  const [loading, setLoading] = useState(false)

  const onFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const f = e.target.files?.[0]
    if (!f) return
    if (!f.type.startsWith('image/') || f.size > 5 * 1024 * 1024) {
      alert('只支持 5MB 以内图片')
      return
    }
    setFile(f)
    setPreview(URL.createObjectURL(f))
  }

  const onSend = async () => {
    if (!file || !question.trim()) return
    setLoading(true); setAnswer('')
    try {
      const form = new FormData()
      form.append('file', file)
      const upRes = await fetch('/api/upload', { method: 'POST', body: form })
      const { fileId } = await upRes.json()
      const chatRes = await fetch('/api/image-qa', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ question: question.trim(), files: [{ id: fileId, type: 'image' }] })
      })
      const data = await chatRes.json()
      setAnswer(data.answer)
    } finally {
      setLoading(false)
    }
  }

  return (
    <div>
      <input type="file" accept="image/*" onChange={onFileChange} />
      {preview && <img src={preview} style={{ maxWidth: 200 }} />}
      <textarea value={question} onChange={e => setQuestion(e.target.value)} />
      <button disabled={loading || !file || !question.trim()} onClick={onSend}>
        {loading ? '分析中…' : '发送'}
      </button>
      {answer && <div>AI:{answer}</div>}
    </div>
  )
}
  • 作业 3:5 个多模态场景(demo)
    • 报表截图 → AI 解释趋势
    • UI 截图 → AI 找间距/对齐问题
    • 表格截图 → AI 抽取为 JSON
    • 报错弹窗截图 → AI 分析原因
    • 线框草图 → AI 生成初版 HTML/CSS 结构建议
posted @ 2025-12-17 09:52  XiaoZhengTou  阅读(1)  评论(0)    收藏  举报