Repository navigation
feat(upload prop:crop,aspectRatio): from Upload component accept prop… - #7095
Hidden character warning
Conversation
… crop,aspectRatio
|
📝 WalkthroughWalkthroughAdds an image-cropping flow to upload previews (Modal + VCropper) that converts cropped base64 to Blob for upload, refactors ApiSelect/ApiTreeSelect registrations to use ApiComponent with withDefaultPlaceholder, and adds locale and playground example strings and form usage for cropping. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant UploadComponent
participant beforeUploadHook
participant ModalCropper
participant base64ToBlob
participant Uploader
participant Server
User->>UploadComponent: select file
UploadComponent->>beforeUploadHook: beforeUpload(file, attrs)
beforeUploadHook->>beforeUploadHook: check isImageFile && crop enabled && single-file
alt crop path
beforeUploadHook->>ModalCropper: open crop modal (VCropper)
ModalCropper->>User: show crop UI
User->>ModalCropper: confirm crop
ModalCropper-->>beforeUploadHook: return base64 dataURL
beforeUploadHook->>base64ToBlob: convert base64 -> Blob
base64ToBlob-->>beforeUploadHook: Blob
beforeUploadHook-->>UploadComponent: provide Blob for upload
else
beforeUploadHook-->>UploadComponent: provide original file
end
UploadComponent->>Uploader: upload(file/blob)
Uploader->>Server: POST file
Server-->>Uploader: upload result (URL)
Uploader-->>User: show upload result
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Fix all issues with AI agents
In @apps/web-antd/src/adapter/component/index.ts:
- Around line 328-341: The blob URL created by URL.createObjectURL(file) inside
the CropperWrapper render causes a memory leak; fix by creating and storing the
object URL in an outer scope (e.g., a variable alongside cropperRef) instead of
in the render call that constructs VCropper, pass that stored URL to VCropper,
and ensure you call URL.revokeObjectURL(storedUrl) inside the closeModal cleanup
(the modal teardown that unmounts CropperWrapper) so the object URL is revoked
when the cropper is closed.
In @playground/src/adapter/component/index.ts:
- Around line 389-404: The code may resolve with undefined because base64ToBlob
can return undefined; modify the Promise in the crop branch (the block using
attrs.crop, originFileList, cropImage and base64ToBlob) to check the result of
base64ToBlob and reject if it's undefined (e.g., reject(new
Error($t('ui.crop.invalid')) or an appropriate error message) instead of
resolving undefined; ensure you only call resolve(blob) when base64ToBlob
returns a valid Blob and propagate the error/path consistently so downstream
upload handlers never receive undefined.
- Around line 328-341: The blob URL created by URL.createObjectURL(file) is
never revoked, causing a memory leak; change the code to assign the URL to a
local variable (e.g., blobUrl) and pass that to VCropper (ref: VCropper,
cropperRef), then revoke the URL via URL.revokeObjectURL(blobUrl) when the modal
closes or the cropper is disposed—specifically call revoke in the onOk and
onCancel handlers (where resolve/dataUrl and resolve('') are used) and also on
component unmount/cleanup to ensure the blob URL is always released.
In @playground/src/views/examples/form/basic.vue:
- Around line 390-394: The code calls toRaw(values.cropImage) and immediately
treats it as an array, which will throw if cropImage is undefined; update the
logic in the crop handling (the toRaw(values.cropImage) usage that defines
cropImage and the derived arrays doneCrop and failedCrop) to guard against
undefined by normalizing cropImage to an empty array when falsy (or check it
before calling .filter()), then compute doneCrop and failedCrop from that safe
array so .filter() never runs on undefined.
🧹 Nitpick comments (4)
playground/src/adapter/component/index.ts (2)
140-152: URL query strings may cause incorrect extension detection.The extension extraction via
file.url?.split('.').pop()will fail for URLs with query parameters (e.g.,image.png?v=123returnspng?v=123). Consider parsing the URL pathname first.♻️ Suggested fix
if (file.url) { - const ext = file.url?.split('.').pop()?.toLowerCase(); + try { + const pathname = new URL(file.url, 'http://localhost').pathname; + const ext = pathname.split('.').pop()?.toLowerCase(); + return ext ? imageExtensions.has(ext) : false; + } catch { + const ext = file.url?.split('.').pop()?.toLowerCase(); + return ext ? imageExtensions.has(ext) : false; + } - return ext ? imageExtensions.has(ext) : false; }
351-362: PrefercharCodeAtovercodePointAtfor base64 decoding.
codePointAtcan returnundefinedand handles surrogate pairs differently thancharCodeAt. For decoding base64 binary data (which produces Latin-1 characters 0-255),charCodeAtis the standard approach and avoids the need for the type assertion.♻️ Suggested fix
const base64ToBlob = (base64: Base64URLString) => { const [typeStr, encodeStr] = base64.split(','); if (!typeStr || !encodeStr) return; const mime = typeStr.match(/:(.*?);/)?.[1]; const raw = window.atob(encodeStr); const rawLength = raw.length; const uInt8Array = new Uint8Array(rawLength); for (let i = 0; i < rawLength; ++i) { - uInt8Array[i] = raw.codePointAt(i) as number; + uInt8Array[i] = raw.charCodeAt(i); } return new Blob([uInt8Array], { type: mime }); };apps/web-antd/src/adapter/component/index.ts (2)
349-350: PrefercharCodeAtfor base64 decoding.Same issue as in the playground adapter. Use
charCodeAtinstead ofcodePointAtfor proper binary data handling.♻️ Suggested fix
for (let i = 0; i < rawLength; ++i) { - uInt8Array[i] = raw.codePointAt(i) as number; + uInt8Array[i] = raw.charCodeAt(i); }
128-149: Significant code duplication between adapter files.The
isImageFile,cropImage,base64ToBlobfunctions and the cropping logic are duplicated betweenplayground/src/adapter/component/index.tsandapps/web-antd/src/adapter/component/index.ts. Consider extracting these utilities to a shared module in@vben/common-uior@vben/utilsto reduce maintenance burden and ensure consistent behavior.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
apps/web-antd/src/adapter/component/index.tspackages/locales/src/langs/en-US/ui.jsonpackages/locales/src/langs/zh-CN/ui.jsonplayground/src/adapter/component/index.tsplayground/src/locales/langs/en-US/examples.jsonplayground/src/locales/langs/zh-CN/examples.jsonplayground/src/views/examples/form/basic.vue
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-01-21T05:03:44.466Z
Learnt from: mynetfan
Repo: vbenjs/vue-vben-admin PR: 5446
File: packages/effects/common-ui/src/components/icon-picker/icons.ts:0-0
Timestamp: 2025-01-21T05:03:44.466Z
Learning: In the vue-vben-admin project's icon-picker component, requests to the Iconify API should be deduplicated using a PENDING_REQUESTS cache to prevent multiple simultaneous requests for the same prefix, and should include a 10-second timeout using AbortController.
Applied to files:
playground/src/adapter/component/index.tsapps/web-antd/src/adapter/component/index.ts
📚 Learning: 2024-12-09T04:41:58.914Z
Learnt from: mynetfan
Repo: vbenjs/vue-vben-admin PR: 5075
File: packages/effects/common-ui/src/components/api-select/api-select.vue:61-62
Timestamp: 2024-12-09T04:41:58.914Z
Learning: 在文件 `packages/effects/common-ui/src/components/api-select/api-select.vue` 的组件 `ApiSelect` 中,`childrenField` 的默认值设置为空字符串是有意的,因为并非所有组件都使用树形数据。
Applied to files:
apps/web-antd/src/adapter/component/index.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: Check (ubuntu-latest)
- GitHub Check: Check (windows-latest)
- GitHub Check: Test (windows-latest)
- GitHub Check: post-update (windows-latest)
- GitHub Check: post-update (ubuntu-latest)
🔇 Additional comments (7)
packages/locales/src/langs/zh-CN/ui.json (1)
57-61: LGTM!The crop-related locale strings are well-structured and consistent with the existing localization patterns. The translations appropriately match the en-US counterparts.
playground/src/locales/langs/zh-CN/examples.json (1)
29-29: LGTM!The translation entry for the new crop-image form field is correctly added and consistent with the en-US locale.
playground/src/locales/langs/en-US/examples.json (1)
26-26: LGTM!The translation entry is appropriately added for the new crop-image form field.
packages/locales/src/langs/en-US/ui.json (1)
57-61: LGTM!The crop-related locale strings are correctly added and follow the established localization structure.
playground/src/adapter/component/index.ts (1)
29-39: LGTM!The imports for
VCropperandModalare correctly added to support the new cropping functionality.playground/src/views/examples/form/basic.vue (1)
361-382: LGTM!The new
cropImageupload field properly demonstrates the crop feature with appropriate configuration options. The inline comments provide useful context for the example.apps/web-antd/src/adapter/component/index.ts (1)
497-510: LGTM!The
ApiSelectandApiTreeSelectregistrations are correctly refactored to use thewithDefaultPlaceholderpattern withApiComponent, consistent with the existingApiCascaderregistration.
… crop,aspectRatio
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In @playground/src/adapter/component/index.ts:
- Around line 333-343: The onOk handler uses cropperRef.value and calls
cropper.getCropImage() without safety checks; wrap the await
cropper.getCropImage() call in a try-catch and validate the returned dataUrl
before calling resolve, calling reject(err) on any thrown error or if the result
is invalid, and ensure closeModal() runs in a finally block so the modal always
closes; reference the onOk function, cropperRef.value / cropper.getCropImage(),
and the resolve/reject/closeModal calls when making the change.
- Around line 402-421: The branch uses isImageFile(file) but calls
cropImage(originFileList[0]), which is inconsistent and confusing; update the
crop flow to use the same file object (use file.originFileObj or ensure
originFileList[0] === file) so cropping operates on the checked file: replace
originFileList[0] with file.originFileObj when calling cropImage and
base64ToBlob (or add a short comment explaining why originFileList[0] is
intentionally used), keeping the guards attrs.crop && !attrs.multiple and the
existing error handling intact.
In @playground/src/views/examples/form/basic.vue:
- Around line 415-424: The success branch currently shows an upload-URLs message
even when no crop images exist; update the conditional around failedCrop to
first check that cropImage (or the list/array that holds uploaded crop images)
is non-empty before calling message.success, e.g., only call message.success
with msgCrop when cropImage.length > 0 (or equivalent) and skip the success
message when cropImage is empty; keep the existing message.error and return
behavior for the failedCrop path and continue to reference failedCrop, cropImage
and msgCrop in the fix.
🧹 Nitpick comments (2)
playground/src/adapter/component/index.ts (2)
138-148: Consider hoisting the image extensions Set.The
imageExtensionsSet is recreated on every call toisImageFile. Since this is a constant, consider moving it outside the function for a minor performance improvement.♻️ Suggested refactor
+const IMAGE_EXTENSIONS = new Set([ + 'bmp', + 'gif', + 'jpeg', + 'jpg', + 'png', + 'svg', + 'webp', +]); + const withPreviewUpload = () => { - // 检查是否为图片文件的辅助函数 - const isImageFile = (file: UploadFile): boolean => { - const imageExtensions = new Set([ - 'bmp', - 'gif', - 'jpeg', - 'jpg', - 'png', - 'svg', - 'webp', - ]); + const isImageFile = (file: UploadFile): boolean => { if (file.url) { try { const pathname = new URL(file.url, 'http://localhost').pathname; const ext = pathname.split('.').pop()?.toLowerCase(); - return ext ? imageExtensions.has(ext) : false; + return ext ? IMAGE_EXTENSIONS.has(ext) : false;
364-375: PrefercharCodeAtovercodePointAtfor base64 decoding.Since base64 encoding only uses ASCII characters (code points 0-127),
charCodeAtis more appropriate and semantically clearer thancodePointAt. Both work identically for ASCII, butcharCodeAtavoids the need for the type assertion.♻️ Suggested refactor
const base64ToBlob = (base64: Base64URLString) => { const [typeStr, encodeStr] = base64.split(','); if (!typeStr || !encodeStr) return; const mime = typeStr.match(/:(.*?);/)?.[1]; const raw = window.atob(encodeStr); const rawLength = raw.length; const uInt8Array = new Uint8Array(rawLength); for (let i = 0; i < rawLength; ++i) { - uInt8Array[i] = raw.codePointAt(i) as number; + uInt8Array[i] = raw.charCodeAt(i); } return new Blob([uInt8Array], { type: mime }); };
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
packages/locales/src/langs/en-US/ui.jsonpackages/locales/src/langs/zh-CN/ui.jsonplayground/src/adapter/component/index.tsplayground/src/views/examples/form/basic.vue
🚧 Files skipped from review as they are similar to previous changes (1)
- packages/locales/src/langs/zh-CN/ui.json
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-01-21T05:03:44.466Z
Learnt from: mynetfan
Repo: vbenjs/vue-vben-admin PR: 5446
File: packages/effects/common-ui/src/components/icon-picker/icons.ts:0-0
Timestamp: 2025-01-21T05:03:44.466Z
Learning: In the vue-vben-admin project's icon-picker component, requests to the Iconify API should be deduplicated using a PENDING_REQUESTS cache to prevent multiple simultaneous requests for the same prefix, and should include a 10-second timeout using AbortController.
Applied to files:
playground/src/adapter/component/index.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
- GitHub Check: Check (ubuntu-latest)
- GitHub Check: Lint (windows-latest)
- GitHub Check: Test (windows-latest)
- GitHub Check: Check (windows-latest)
- GitHub Check: post-update (ubuntu-latest)
- GitHub Check: post-update (windows-latest)
🔇 Additional comments (3)
packages/locales/src/langs/en-US/ui.json (1)
57-62: LGTM!The crop-related locale entries are well-structured and consistent with the existing translation patterns in this file.
playground/src/adapter/component/index.ts (1)
29-39: LGTM!The new imports for
VCropperandModalare appropriate for the image cropping feature.playground/src/views/examples/form/basic.vue (1)
361-382: LGTM!Good demonstration of the new crop feature with appropriate configuration. The
crop: trueandaspectRatio: '1:1'props clearly showcase the new functionality.
… crop,aspectRatio
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In @apps/web-antd/src/adapter/component/index.ts:
- Around line 360-371: The base64ToBlob function uses String.codePointAt
(incorrect for byte values) and lacks error handling for window.atob and
malformed input; replace codePointAt with charCodeAt when populating the
Uint8Array, wrap the atob call in a try/catch to handle and log/return on decode
errors, validate that base64.split(',') produced both parts and that mime is
present (or default to 'application/octet-stream'), and ensure the function
returns undefined or throws consistently on invalid input; update function name
base64ToBlob accordingly.
🧹 Nitpick comments (3)
playground/src/adapter/component/index.ts (2)
286-367: Add explicit return type forcropImageand handle edge cases.The function returns a
Promisethat resolves to a data URL string or empty string, but this isn't typed. Also, if the modal fails to render orgetCropImagereturns an unexpected value, behavior may be undefined.Suggested improvement
- const cropImage = (file: File, aspectRatio: string | undefined) => { - return new Promise((resolve, reject) => { + const cropImage = (file: File, aspectRatio: string | undefined): Promise<string> => { + return new Promise<string>((resolve, reject) => {
398-426: Consider simplifying the nested Promise pattern.The code awaits
cropImage, then wraps the result processing in a newPromise. This can be simplified to avoid the anti-pattern of creating a Promise inside an async function when you already have the value.Simplified approach
if ( attrs.crop && !attrs.multiple && originFileList[0] && isImageFile(file) ) { file.status = 'removed'; const base64 = await cropImage(originFileList[0], attrs.aspectRatio); - return new Promise((resolve, reject) => { - if (!base64) { - return reject(new Error($t('ui.crop.cancel'))); - } - const blob = base64ToBlob(base64 as string); - if (!blob) { - return reject(new Error($t('ui.crop.errorTip'))); - } - resolve(blob); - }); + if (!base64) { + throw new Error($t('ui.crop.cancel')); + } + const blob = base64ToBlob(base64 as string); + if (!blob) { + throw new Error($t('ui.crop.errorTip')); + } + return blob; }apps/web-antd/src/adapter/component/index.ts (1)
128-474: Significant code duplication withplayground/src/adapter/component/index.ts.The
isImageFile,cropImage,base64ToBlobhelpers and the entirewithPreviewUploadfactory are duplicated. Consider extracting these utilities to@vben/common-uior@vben/utilsto maintain a single source of truth and reduce maintenance burden.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
apps/web-antd/src/adapter/component/index.tsplayground/src/adapter/component/index.tsplayground/src/views/examples/form/basic.vue
🚧 Files skipped from review as they are similar to previous changes (1)
- playground/src/views/examples/form/basic.vue
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-01-21T05:03:44.466Z
Learnt from: mynetfan
Repo: vbenjs/vue-vben-admin PR: 5446
File: packages/effects/common-ui/src/components/icon-picker/icons.ts:0-0
Timestamp: 2025-01-21T05:03:44.466Z
Learning: In the vue-vben-admin project's icon-picker component, requests to the Iconify API should be deduplicated using a PENDING_REQUESTS cache to prevent multiple simultaneous requests for the same prefix, and should include a 10-second timeout using AbortController.
Applied to files:
apps/web-antd/src/adapter/component/index.tsplayground/src/adapter/component/index.ts
📚 Learning: 2024-12-09T04:41:58.914Z
Learnt from: mynetfan
Repo: vbenjs/vue-vben-admin PR: 5075
File: packages/effects/common-ui/src/components/api-select/api-select.vue:61-62
Timestamp: 2024-12-09T04:41:58.914Z
Learning: 在文件 `packages/effects/common-ui/src/components/api-select/api-select.vue` 的组件 `ApiSelect` 中,`childrenField` 的默认值设置为空字符串是有意的,因为并非所有组件都使用树形数据。
Applied to files:
apps/web-antd/src/adapter/component/index.ts
🧬 Code graph analysis (1)
playground/src/adapter/component/index.ts (6)
packages/locales/src/index.ts (1)
$t(13-13)apps/web-antd/src/locales/index.ts (1)
$t(102-102)apps/web-ele/src/locales/index.ts (1)
$t(102-102)apps/web-naive/src/locales/index.ts (1)
$t(38-38)playground/src/locales/index.ts (1)
$t(102-102)scripts/clean.mjs (1)
i(78-78)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
- GitHub Check: post-update (windows-latest)
- GitHub Check: post-update (ubuntu-latest)
- GitHub Check: Check (windows-latest)
- GitHub Check: Check (ubuntu-latest)
- GitHub Check: Lint (windows-latest)
- GitHub Check: Test (windows-latest)
- GitHub Check: Lint (ubuntu-latest)
🔇 Additional comments (4)
playground/src/adapter/component/index.ts (2)
139-164: Image detection logic looks correct.The
isImageFilehelper properly handles multiple scenarios: URL-based detection with fallback for URL parsing failures, MIME type detection, and filename extension fallback. The set of supported extensions is comprehensive.
529-542: ApiSelect and ApiTreeSelect refactored to use ApiComponent.The registrations now consistently use the
ApiComponentwrapper with appropriate configuration. This aligns with the pattern used forApiCascader.apps/web-antd/src/adapter/component/index.ts (2)
520-533: ApiSelect and ApiTreeSelect registrations updated consistently.The component registrations now use the
ApiComponentpattern matchingApiCascader, providing a consistent approach across API-driven select components.
389-420: Verify rejection behavior when cropping is canceled.When the user cancels the crop modal,
cropImageresolves with an empty string, which then causeshandleBeforeUploadto reject with$t('ui.crop.cancel'). This rejection will be caught by ant-design-vue's Upload, but verify the UX is acceptable (e.g., no error toast shown to user for intentional cancel).
… crop,aspectRatio
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (4)
playground/src/adapter/component/index.ts (3)
140-148: URL with query parameters may cause false negatives.When parsing
file.url, if the URL contains query parameters (e.g.,https://example.com/image.jpg?token=abc), thepathnamecorrectly strips them. However, in the catch block fallback (line 146),file.url.split('.').pop()would extractjpg?token=abc, failing the extension check.Suggested fix
} catch { - const ext = file.url?.split('.').pop()?.toLowerCase(); + const urlWithoutQuery = file.url?.split('?')[0]; + const ext = urlWithoutQuery?.split('.').pop()?.toLowerCase(); return ext ? imageExtensions.has(ext) : false; }
360-375: UsecharCodeAtinstead ofcodePointAtfor byte conversion.
codePointAtis designed for Unicode code points and can returnundefinedat the end of strings. For converting raw bytes fromatob()output (which is always single-byte characters),charCodeAtis the correct method and never returnsundefined.Additionally,
Base64URLStringis a WebAuthn credential type, not a data URL type. Consider usingstringinstead.Suggested fix
- const base64ToBlob = (base64: Base64URLString) => { + const base64ToBlob = (base64: string) => { try { const [typeStr, encodeStr] = base64.split(','); if (!typeStr || !encodeStr) return; const mime = typeStr.match(/:(.*?);/)?.[1]; const raw = window.atob(encodeStr); const rawLength = raw.length; const uInt8Array = new Uint8Array(rawLength); for (let i = 0; i < rawLength; ++i) { - uInt8Array[i] = raw.codePointAt(i) as number; + uInt8Array[i] = raw.charCodeAt(i); } return new Blob([uInt8Array], { type: mime }); } catch { return undefined; } };
402-422: Simplify error handling and avoid unnecessary nested Promise.The nested
new Promise()at lines 412-421 is unnecessary sincehandleBeforeUploadis already async. You can throw directly or return the blob.Suggested simplification
// 多选或者非图片不唤起裁剪框 if ( attrs.crop && !attrs.multiple && originFileList[0] && isImageFile(file) ) { file.status = 'removed'; // antd Upload组件问题 file参数获取的是UploadFile类型对象无法取到File类型 所以通过originFileList[0]获取 const base64 = await cropImage(originFileList[0], attrs.aspectRatio); - return new Promise((resolve, reject) => { - if (!base64) { - return reject(new Error($t('ui.crop.cancel'))); - } - const blob = base64ToBlob(base64 as string); - if (!blob) { - return reject(new Error($t('ui.crop.errorTip'))); - } - resolve(blob); - }); + if (!base64) { + throw new Error($t('ui.crop.cancel')); + } + const blob = base64ToBlob(base64 as string); + if (!blob) { + throw new Error($t('ui.crop.errorTip')); + } + return blob; }apps/web-antd/src/adapter/component/index.ts (1)
128-375: Extract shared cropping logic to reduce duplication.The entire
isImageFile,cropImage, andbase64ToBlobimplementations are duplicated between this file andplayground/src/adapter/component/index.ts. This creates maintenance burden and risks inconsistencies.Consider extracting these utilities to a shared module in
@vben/common-uior@vben/utils.Note: The same issues flagged in the playground file apply here:
- Use
charCodeAtinstead ofcodePointAtinbase64ToBlob- Change
Base64URLStringtype tostring- Handle query parameters in URL fallback parsing in
isImageFile- Simplify nested Promise in
handleBeforeUpload
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
apps/web-antd/src/adapter/component/index.tsplayground/src/adapter/component/index.ts
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-01-21T05:03:44.466Z
Learnt from: mynetfan
Repo: vbenjs/vue-vben-admin PR: 5446
File: packages/effects/common-ui/src/components/icon-picker/icons.ts:0-0
Timestamp: 2025-01-21T05:03:44.466Z
Learning: In the vue-vben-admin project's icon-picker component, requests to the Iconify API should be deduplicated using a PENDING_REQUESTS cache to prevent multiple simultaneous requests for the same prefix, and should include a 10-second timeout using AbortController.
Applied to files:
playground/src/adapter/component/index.tsapps/web-antd/src/adapter/component/index.ts
📚 Learning: 2024-12-09T04:41:58.914Z
Learnt from: mynetfan
Repo: vbenjs/vue-vben-admin PR: 5075
File: packages/effects/common-ui/src/components/api-select/api-select.vue:61-62
Timestamp: 2024-12-09T04:41:58.914Z
Learning: 在文件 `packages/effects/common-ui/src/components/api-select/api-select.vue` 的组件 `ApiSelect` 中,`childrenField` 的默认值设置为空字符串是有意的,因为并非所有组件都使用树形数据。
Applied to files:
apps/web-antd/src/adapter/component/index.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: post-update (ubuntu-latest)
- GitHub Check: post-update (windows-latest)
- GitHub Check: Check (ubuntu-latest)
- GitHub Check: Test (windows-latest)
- GitHub Check: Check (windows-latest)
🔇 Additional comments (3)
playground/src/adapter/component/index.ts (2)
525-538: LGTM on ApiSelect/ApiTreeSelect refactor.The transition to
ApiComponent-based registration withwithDefaultPlaceholderis consistent with theApiCascaderpattern and properly configures the component props.
277-277: No action needed. TheaspectRatioparameter type ofstring | undefinedis correct—VCropper expects aspect ratios in string format (e.g.,"16:9","1:1") and parses them internally to numeric values.Likely an incorrect or invalid review comment.
apps/web-antd/src/adapter/component/index.ts (1)
525-538: LGTM on ApiSelect/ApiTreeSelect refactor.The
ApiComponent-based registration is consistent with the existingApiCascaderpattern.
… crop,aspectRatio
Description
antd Upload组件支持上传前裁剪,新增支持参数crop和aspectRatio,多选或者非图片不唤起裁剪框。Type of change
Please delete options that are not relevant.
pnpm-lock.yamlunless you introduce a new test example.Checklist
pnpm run docs:devcommand.pnpm test.feat:,fix:,perf:,docs:, orchore:.Summary by CodeRabbit
New Features
Documentation
✏️ Tip: You can customize this high-level summary in your review settings.