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

📅 2026/8/13 12:04:32
我让 AI 封装了一个 ImageUpload 组件,它设计的 5 层校验链路比我想的周全
需求是各种场景都要上传图片但每次限制都不一样——有的要精确尺寸、有的要最小尺寸、有的要比例、有的要限格式限大小。我让 AI 设计这个组件的整体架构它给出的5 层校验管道比我最初的方案好很多。我原本只想到 3 层。需求场景场景 A分类标签图精确 150×90≤50KB仅 png 场景 B分类顶部图精确 789×96≤100KBjpg/png/gif 场景 C商品主图最小 750×750≤2MB 场景 DBanner比例 16:9≤500KB 场景 E头像任意尺寸≤1MB一个组件要覆盖所有场景Props 设计是关键。AI 设计的 5 层校验管道我把需求描述给 AI 后它提出了管道式校验架构beforeUpload 执行顺序 ┌─────────────────────────────────────────┐ │ Layer0:customBeforeUpload用户自定义 │ ← 最高优先级 ├─────────────────────────────────────────┤ │ Layer1:validateType格式校验 │ ← accept:[jpg,png]├─────────────────────────────────────────┤ │ Layer2:validateSize体积校验 │ ← maxSizesizeUnit ├─────────────────────────────────────────┤ │ 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 的方案更符合开放封闭原则——对扩展开放对修改关闭。核心实现constbeforeUploadasync(file:File):Promiseany{// Layer 0: 自定义钩子if(customBeforeUpload){constresultawaitcustomBeforeUpload(file)if(resultfalse)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的——因为需要加载图片获取实际尺寸constvalidateExactSizeasync(file:File):Promiseboolean{if(!limitRect)returntrue// 不传 prop 则跳过此层constobjectURLURL.createObjectURL(file)try{constimgawaitloadImage(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} sizeUnitKB / // 最小尺寸 ImageUpload assertSize{{width: 750, height: 750}} / // 比例限制 ImageUpload ratioLimit{{widthRatio: 16, heightRatio: 9}} maxSize{500} sizeUnitKB / // 无校验只限制数量 ImageUpload maxCount{3} /AI 帮我发现的细节在实现过程中AI 还主动提出了几个我没想到的点ObjectURL 必须手动释放——否则每次校验都会内存泄漏视频和图片要分开处理——视频尺寸要用video元素获取不能用imgfuzzy 模式——有时设计稿标注是约 750px需要容忍 ±2px 误差多选时数量校验要提前——在校验尺寸之前就判断数量避免无意义的图片加载这些边界情况我如果自己写大概率第一版会漏线上出 bug 才补。和 Form 的集成maxCount1时组件自动适配 Form.Itemvalue 接收string单张 URL onChange 返回string | undefined不需要getValueFromEvent/getValueProps转换。这个设计让使用侧代码简洁了很多Form.Item namelabelImage label分类标签图 ImageUpload maxCount{1} limitRect{{w: 150, h: 90}} maxSize{50} sizeUnitKB / /Form.Item零 adapter 代码。 你们项目的图片上传是怎么处理校验的有统一的组件还是每个页面各写各的完整 Skills 源码已开源github.com/sleepyccat/ai-native-workflow欢迎 Star ⭐ 和 PR。