news 2026/8/13 12:04:30

我让 AI 封装了一个 ImageUpload 组件,它设计的 5 层校验链路比我想的周全

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
我让 AI 封装了一个 ImageUpload 组件,它设计的 5 层校验链路比我想的周全

需求是"各种场景都要上传图片,但每次限制都不一样——有的要精确尺寸、有的要最小尺寸、有的要比例、有的要限格式限大小"。

我让 AI 设计这个组件的整体架构,它给出的"5 层校验管道"比我最初的方案好很多。我原本只想到 3 层。

需求场景

场景 A(分类标签图):精确 150×90,≤50KB,仅 png 场景 B(分类顶部图):精确 789×96,≤100KB,jpg/png/gif 场景 C(商品主图):最小 750×750,≤2MB 场景 D(Banner):比例 16:9,≤500KB 场景 E(头像):任意尺寸,≤1MB

一个组件要覆盖所有场景,Props 设计是关键。

AI 设计的 5 层校验管道

我把需求描述给 AI 后,它提出了管道式校验架构:

beforeUpload 执行顺序: ┌─────────────────────────────────────────┐ │ Layer0:customBeforeUpload(用户自定义) │ ← 最高优先级 ├─────────────────────────────────────────┤ │ Layer1:validateType(格式校验) │ ← accept:['jpg','png']├─────────────────────────────────────────┤ │ Layer2:validateSize(体积校验) │ ← maxSize+sizeUnit ├─────────────────────────────────────────┤ │ Layer3:validateExactSize(精确尺寸) │ ← limitRect:{w,h}├─────────────────────────────────────────┤ │ Layer4:validateMinSize(最小尺寸) │ ← assertSize:{width,height}├─────────────────────────────────────────┤ │ Layer5:validateRatio(比例校验) │ ← ratioLimit:{widthRatio,heightRatio}└─────────────────────────────────────────┘ │ ↓ 全部通过 开始上传

每一层独立、可选、互不干扰。不需要的校验层直接跳过(对应 prop 不传就行)。

我原本的方案 vs AI 的方案

我的方案(3 层): ├── 格式校验 ├── 大小校验 └── 尺寸校验(一个函数里判断精确/最小/比例) └── 问题:逻辑耦合,后续加新校验类型要改这个函数 AI 的方案(5 层): ├── 每种校验独立函数 ├── customBeforeUpload 作为逃生舱 ├── 任意一层 return false 就中断 └── 优势:新增校验类型只需加一个函数,不改现有逻辑

AI 的方案更符合开放封闭原则——对扩展开放,对修改关闭。

核心实现

constbeforeUpload=async(file:File):Promise<any>=>{// Layer 0: 自定义钩子if(customBeforeUpload){constresult=awaitcustomBeforeUpload(file)if(result===false)returnUpload.LIST_IGNORE}// Layer 1: 格式if(!validateType(file))returnUpload.LIST_IGNORE// Layer 2: 体积if(!validateSize(file))returnUpload.LIST_IGNORE// Layer 3: 精确尺寸if(!(awaitvalidateExactSize(file)))returnUpload.LIST_IGNORE// Layer 4: 最小尺寸if(!(awaitvalidateMinSize(file)))returnUpload.LIST_IGNORE// Layer 5: 比例if(!(awaitvalidateRatio(file)))returnUpload.LIST_IGNOREreturnfile}

注意 Layer 3-5 是async的——因为需要加载图片获取实际尺寸:

constvalidateExactSize=async(file:File):Promise<boolean>=>{if(!limitRect)returntrue// 不传 prop 则跳过此层constobjectURL=URL.createObjectURL(file)try{constimg=awaitloadImage(objectURL)if(img.naturalWidth!==limitRect.w){message.error(`图片宽度必须为${limitRect.w},当前为${img.naturalWidth}`)returnfalse}if(img.naturalHeight!==limitRect.h){message.error(`图片高度必须为${limitRect.h},当前为${img.naturalHeight}`)returnfalse}returntrue}finally{URL.revokeObjectURL(objectURL)// 防止内存泄漏}}

使用时的简洁度

5 层校验,使用者只需要传对应的 prop:

// 精确尺寸 + 体积限制 <ImageUpload limitRect={{w: 150, h: 90}} maxSize={50} sizeUnit="KB" /> // 最小尺寸 <ImageUpload assertSize={{width: 750, height: 750}} /> // 比例限制 <ImageUpload ratioLimit={{widthRatio: 16, heightRatio: 9}} maxSize={500} sizeUnit="KB" /> // 无校验(只限制数量) <ImageUpload maxCount={3} />

AI 帮我发现的细节

在实现过程中,AI 还主动提出了几个我没想到的点:

  1. ObjectURL 必须手动释放——否则每次校验都会内存泄漏
  2. 视频和图片要分开处理——视频尺寸要用<video>元素获取,不能用<img>
  3. fuzzy 模式——有时设计稿标注是"约 750px",需要容忍 ±2px 误差
  4. 多选时数量校验要提前——在校验尺寸之前就判断数量,避免无意义的图片加载

这些边界情况我如果自己写,大概率第一版会漏,线上出 bug 才补。

和 Form 的集成

maxCount=1时,组件自动适配 Form.Item:

value 接收:string(单张 URL) onChange 返回:string | undefined

不需要getValueFromEvent/getValueProps转换。这个设计让使用侧代码简洁了很多:

<Form.Item name="labelImage" label="分类标签图"> <ImageUpload maxCount={1} limitRect={{w: 150, h: 90}} maxSize={50} sizeUnit="KB" /> </Form.Item>

零 adapter 代码。


💬 你们项目的图片上传是怎么处理校验的?有统一的组件还是每个页面各写各的?


🔗完整 Skills 源码已开源:github.com/sleepyccat/ai-native-workflow,欢迎 Star ⭐ 和 PR。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/13 12:02:21

SAP FI计税基础选择:基于净额与基于总额的差异详解

1. 一个看似简单的选择&#xff0c;背后是税务逻辑的差异 在SAP FI模块的日常操作中&#xff0c;录入一张手工发票&#xff08;FB60/FB70&#xff09;是财务人员再熟悉不过的流程。然而&#xff0c;当涉及到含税业务时&#xff0c;界面上一个不起眼的选项——“基于净额计税”和…

作者头像 李华
网站建设 2026/8/13 12:01:25

HarmonyOS 7.0 / API 26 跨设备续接一致性:手机到平板后筛选条件、滚动位置和任务进度如何恢复

先把问题摆出来 这篇只讲一个点&#xff1a;跨设备续接一致性。我不按官方说明书那种顺序铺概念&#xff0c;而是按开发时最容易出事的路径来拆&#xff1a;什么时候会坏、怎么复现、怎么修、怎么验证&#xff0c;以及这个判断以后能不能复用。 跨设备续接最容易漏的是细节状态…

作者头像 李华
网站建设 2026/8/13 12:00:49

终极PDF对比神器diff-pdf:5分钟快速上手,告别手动核对烦恼!

终极PDF对比神器diff-pdf&#xff1a;5分钟快速上手&#xff0c;告别手动核对烦恼&#xff01; 【免费下载链接】diff-pdf A simple tool for visually comparing two PDF files 项目地址: https://gitcode.com/gh_mirrors/di/diff-pdf 还在为PDF文档版本对比而烦恼吗&a…

作者头像 李华
网站建设 2026/8/13 12:00:42

串口通信全解析:从硬件连接到协议配置与调试实战

1. 项目概述&#xff1a;从“线”到“话”的旅程 干了这么多年嵌入式开发&#xff0c;调试过无数板子&#xff0c;要说最让我又爱又恨的通信接口&#xff0c;串口绝对排第一。爱它&#xff0c;是因为它简单、直接、无处不在&#xff0c;是工程师和硬件“对话”最原始也最可靠的…

作者头像 李华
网站建设 2026/8/13 12:00:03

pysnowball深度解析:Python金融数据API架构设计与实战指南

pysnowball深度解析&#xff1a;Python金融数据API架构设计与实战指南 【免费下载链接】pysnowball 雪球股票数据接口 python edition 项目地址: https://gitcode.com/gh_mirrors/py/pysnowball 在金融科技快速发展的今天&#xff0c;数据驱动决策已成为投资分析的核心竞…

作者头像 李华
网站建设 2026/8/13 11:59:58

始祖正考父~第1世(宣靖父)— 第65世(希尧公)全表

远古始祖 燧人氏&#xff08;火祖&#xff0c;首创钻木取火&#xff09;华胥氏&#xff08;燧人后裔&#xff0c;伏羲之母&#xff09;伏羲&#xff08;太昊庖牺氏&#xff0c;风姓&#xff09;&#xff1a;画八卦、定嫁娶&#xff0c;人文始祖&#xff1b;生子少典少典&#…

作者头像 李华