chore: replace all cn comments of fe to en version by volc api (#320)
This commit is contained in:
@@ -22,49 +22,49 @@ import { CustomError } from '@coze-arch/bot-error';
|
||||
import { FileBizType } from '@coze-arch/bot-api/developer_api';
|
||||
import { DeveloperApi } from '@coze-arch/bot-api';
|
||||
|
||||
/** 图片上传错误码 */
|
||||
/** image upload error code */
|
||||
export enum ImgUploadErrNo {
|
||||
Success = 0,
|
||||
/** 缺少文件 */
|
||||
/** Missing document */
|
||||
NoFile,
|
||||
/** 上传失败 */
|
||||
/** Upload failed. */
|
||||
UploadFail,
|
||||
/** 上传超时 */
|
||||
/** Upload timed out */
|
||||
UploadTimeout,
|
||||
/** 获取 URL 失败 */
|
||||
/** Failed to get URL */
|
||||
GetUrlFail,
|
||||
/** 校验异常, 但是不明确具体异常 */
|
||||
/** Check exception, but not specific exception */
|
||||
ValidateError,
|
||||
/** 文件尺寸超出限制 */
|
||||
/** File size exceeds limit */
|
||||
MaxSizeError,
|
||||
/** 文件类型不支持 */
|
||||
/** File type not supported */
|
||||
SuffixError,
|
||||
/** 最大宽度限制 */
|
||||
/** Maximum width limit */
|
||||
MaxWidthError,
|
||||
/** 最大高度限制 */
|
||||
/** Maximum height limit */
|
||||
MaxHeightError,
|
||||
/** 最小宽度限制 */
|
||||
/** minimum width limit */
|
||||
MinWidthError,
|
||||
/** 最小高度限制 */
|
||||
/** Minimum height limit */
|
||||
MinHeightError,
|
||||
/** 固定宽高比 */
|
||||
/** Fixed Aspect Ratio */
|
||||
AspectRatioError,
|
||||
}
|
||||
|
||||
export interface ImageRule {
|
||||
/** 文件大小限制, 单位 b, 1M = 1 * 1024 * 1024 */
|
||||
/** File size limit, unit b, 1M = 1 * 1024 * 1024 */
|
||||
maxSize?: number;
|
||||
/** 文件后缀 */
|
||||
/** file suffix */
|
||||
suffix?: string[];
|
||||
/** 最大宽度限制 */
|
||||
/** Maximum width limit */
|
||||
maxWidth?: number;
|
||||
/** 最大高度限制 */
|
||||
/** Maximum height limit */
|
||||
maxHeight?: number;
|
||||
/** 最小宽度限制 */
|
||||
/** minimum width limit */
|
||||
minWidth?: number;
|
||||
/** 最小高度限制 */
|
||||
/** Minimum height limit */
|
||||
minHeight?: number;
|
||||
/** 固定宽高比 */
|
||||
/** Fixed Aspect Ratio */
|
||||
aspectRatio?: number;
|
||||
}
|
||||
|
||||
@@ -82,34 +82,34 @@ type UploadResult =
|
||||
};
|
||||
|
||||
/**
|
||||
* Workflow 图片上传
|
||||
* Workflow image upload
|
||||
*/
|
||||
class ImageUploader {
|
||||
/** 任务 ID, 用于避免 ABA 问题 */
|
||||
/** Task ID to avoid ABA issues */
|
||||
private taskId = 0;
|
||||
/**
|
||||
* 上传模式
|
||||
* - api 直接使用接口上传
|
||||
* - uploader 上传到视频云服务, 走 workflow 服务. !海外版未经过测试
|
||||
* upload mode
|
||||
* - API directly uses the interface to upload
|
||||
* - uploader to Video Cloud as a Service, go workflow service.! Overseas version has not been tested
|
||||
*/
|
||||
mode: 'uploader' | 'api' = 'uploader';
|
||||
/** 校验规则 */
|
||||
/** validation rule */
|
||||
rules?: ImageRule;
|
||||
/** 上传的文件 */
|
||||
/** Uploaded file */
|
||||
file?: File;
|
||||
/** 展示 Url, 添加文件后生成, 用于预览 */
|
||||
/** Show URLs, generated after adding files, for preview */
|
||||
displayUrl?: string;
|
||||
/** 上传状态 */
|
||||
/** Upload Status */
|
||||
isUploading = false;
|
||||
/** 超时时间 */
|
||||
/** timeout */
|
||||
timeout?: number;
|
||||
/** 校验结果 */
|
||||
/** verification result */
|
||||
validateResult?: {
|
||||
isSuccess: boolean;
|
||||
errNo: ImgUploadErrNo;
|
||||
msg?: string;
|
||||
};
|
||||
/** 上传结果 */
|
||||
/** Upload result */
|
||||
uploadResult?: UploadResult;
|
||||
|
||||
constructor(config?: {
|
||||
@@ -122,7 +122,7 @@ class ImageUploader {
|
||||
this.timeout = config?.timeout ?? this.timeout;
|
||||
}
|
||||
|
||||
/** 选择待上传文件 */
|
||||
/** Select the file to upload */
|
||||
async select(file: File) {
|
||||
if (!file) {
|
||||
throw new CustomError('normal_error', '选择文件为空');
|
||||
@@ -140,16 +140,16 @@ class ImageUploader {
|
||||
});
|
||||
}
|
||||
|
||||
/** 上传图片 */
|
||||
/** Upload image */
|
||||
async upload() {
|
||||
// 未选择文件或文件不符合要求
|
||||
// No file was selected or the file does not meet the requirements
|
||||
if (!this.file || !this.validateResult?.isSuccess || this.isUploading) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.isUploading = true;
|
||||
|
||||
// 添加任务 ID,避免 ABA 问题
|
||||
// Add task IDs to avoid ABA issues
|
||||
this.taskId += 1;
|
||||
const currentId = this.taskId;
|
||||
|
||||
@@ -208,7 +208,7 @@ class ImageUploader {
|
||||
if (!uri) {
|
||||
return;
|
||||
}
|
||||
// 获取 url
|
||||
// Get URL
|
||||
const resp = await workflowApi
|
||||
.SignImageURL(
|
||||
{
|
||||
@@ -301,7 +301,7 @@ class ImageUploader {
|
||||
reset() {
|
||||
this.file = undefined;
|
||||
if (this.displayUrl) {
|
||||
// 是内部链接
|
||||
// Is an internal link
|
||||
URL.revokeObjectURL(this.displayUrl);
|
||||
this.displayUrl = undefined;
|
||||
}
|
||||
@@ -319,7 +319,7 @@ class ImageUploader {
|
||||
|
||||
const rules = this.rules || {};
|
||||
|
||||
// 文件尺寸
|
||||
// file size
|
||||
if (rules.maxSize) {
|
||||
if (this.file.size > rules.maxSize) {
|
||||
this.validateResult = {
|
||||
@@ -333,7 +333,7 @@ class ImageUploader {
|
||||
}
|
||||
}
|
||||
|
||||
// 文件后缀
|
||||
// file suffix
|
||||
if (Array.isArray(rules.suffix) && rules.suffix.length > 0) {
|
||||
const fileExtension = getFileExtension(this.file.name);
|
||||
if (!rules.suffix.includes(fileExtension)) {
|
||||
@@ -348,7 +348,7 @@ class ImageUploader {
|
||||
}
|
||||
}
|
||||
|
||||
// 图片尺寸
|
||||
// image size
|
||||
const { width, height } = await getImageSize(this.displayUrl);
|
||||
|
||||
if (!width || !height) {
|
||||
@@ -445,14 +445,14 @@ function getBase64(file: Blob): Promise<string> {
|
||||
});
|
||||
}
|
||||
|
||||
/** 获取文件名后缀 */
|
||||
/** Get filename suffix */
|
||||
function getFileExtension(name: string) {
|
||||
const index = name.lastIndexOf('.');
|
||||
return name.slice(index + 1).toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param url 获取图片宽高
|
||||
* @Param url Get image width and height
|
||||
*/
|
||||
function getImageSize(url: string): Promise<{ width: number; height: number }> {
|
||||
return new Promise((resolve, reject) => {
|
||||
@@ -468,9 +468,9 @@ function getImageSize(url: string): Promise<{ width: number; height: number }> {
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化文件大小
|
||||
* @param bytes 文件大小
|
||||
* @param decimals 小数位数, 默认 2 位
|
||||
* Format file size
|
||||
* @param bytes file size
|
||||
* @Param decimals, default 2 digits
|
||||
* @example
|
||||
* formatBytes(1024); // 1KB
|
||||
* formatBytes('1024'); // 1KB
|
||||
|
||||
@@ -52,7 +52,7 @@ interface ImageUploaderProps {
|
||||
style?: CSSProperties;
|
||||
readonly?: boolean;
|
||||
disabled?: boolean;
|
||||
/** 图片上传限制 */
|
||||
/** image upload restrictions */
|
||||
rules?: ImageRule;
|
||||
value?: { url: string; uri: string } | undefined;
|
||||
validateStatus?: SelectProps['validateStatus'];
|
||||
@@ -61,13 +61,13 @@ interface ImageUploaderProps {
|
||||
}
|
||||
|
||||
interface ImagePopoverWrapperProps {
|
||||
/** 图片地址 */
|
||||
/** Image address */
|
||||
url?: string;
|
||||
maxWidth?: number;
|
||||
maxHeight?: number;
|
||||
minWidth?: number;
|
||||
minHeight?: number;
|
||||
/** 是否支持预览 */
|
||||
/** Whether to support preview */
|
||||
enablePreview?: boolean;
|
||||
children?: React.ReactElement;
|
||||
}
|
||||
@@ -215,7 +215,7 @@ const ImageUploader: FC<ImageUploaderProps> = ({
|
||||
return 'image/*';
|
||||
}, [rules?.suffix]);
|
||||
|
||||
/** 整体区域支持交互 */
|
||||
/** Overall Area Support Interaction */
|
||||
const wrapCanAction = useMemo(
|
||||
() => !uri && !loading && !isError && !disabled && !readonly,
|
||||
[uri, loading, isError, disabled, readonly],
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
/* eslint-disable @coze-arch/max-line-per-function */
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
|
||||
@@ -24,36 +24,36 @@ import { Toast } from '@coze-arch/coze-design';
|
||||
import ImageUploader, { ImgUploadErrNo } from './image-uploader';
|
||||
|
||||
interface UseImageUploaderParams {
|
||||
/** 图片限制条件 */
|
||||
/** image restrictions */
|
||||
rules?: ImageUploader['rules'];
|
||||
/** 上传模式 */
|
||||
/** upload mode */
|
||||
mode?: ImageUploader['mode'];
|
||||
/** 上传配置 */
|
||||
/** upload configuration */
|
||||
timeout?: ImageUploader['timeout'];
|
||||
}
|
||||
|
||||
interface UseImageUploaderReturn {
|
||||
/** 图片标识, 用于提交给服务 */
|
||||
/** Image ID for submission to the service */
|
||||
uri: string;
|
||||
/** 图片展示地址 */
|
||||
/** Picture display address */
|
||||
url: string;
|
||||
/** 文件名 */
|
||||
/** file name */
|
||||
fileName: string;
|
||||
/** 上传中状态 */
|
||||
/** Uploading status */
|
||||
loading: boolean;
|
||||
/** 上传失败状态 */
|
||||
/** Upload failed status */
|
||||
isError: boolean;
|
||||
/** 上传图片 */
|
||||
/** Upload image */
|
||||
uploadImg: (file: File) => Promise<ImageUploader['uploadResult']>;
|
||||
/** 清除已上传图片 */
|
||||
/** Clear uploaded images */
|
||||
clearImg: () => void;
|
||||
/** 上传失败后重试 */
|
||||
/** Retry after upload failure */
|
||||
retryUploadImg: () => Promise<ImageUploader['uploadResult']>;
|
||||
/**
|
||||
* 设置初始状态, 用于回显服务下发的数据
|
||||
* Set the initial state for echoing data sent by the service
|
||||
*
|
||||
* @param val 对应值
|
||||
* @param isMerge 是否 merge 模式, merge 模式仅更新传入字段. 默认 false
|
||||
* @param val corresponding value
|
||||
* @Param isMerge Whether to merge mode, merge mode only updates incoming fields. Default false
|
||||
*/
|
||||
setImgValue: (
|
||||
val: { uri?: string; url?: string; fileName?: string },
|
||||
@@ -61,7 +61,7 @@ interface UseImageUploaderReturn {
|
||||
) => void;
|
||||
}
|
||||
|
||||
/** 缓存文件名 */
|
||||
/** cache filename */
|
||||
const fileNameCache: Record<string, string> = Object.create(null);
|
||||
|
||||
// eslint-disable-next-line max-lines-per-function
|
||||
@@ -102,14 +102,14 @@ export default function useImageUploader(
|
||||
setFileName(targetFileName);
|
||||
}
|
||||
|
||||
// 非 Merge 模式, 未设置的值清空
|
||||
// Non-Merge mode, unset values are cleared
|
||||
if (!isMerge) {
|
||||
setUrl(targetDisplayUrl ?? '');
|
||||
setUri(targetUri ?? '');
|
||||
setFileName(targetFileName ?? '');
|
||||
}
|
||||
|
||||
// 文件名特殊逻辑, 根据 uri 从缓存重映射文件名
|
||||
// Filename special logic, remapping filenames from cache based on URIs
|
||||
if (!targetFileName) {
|
||||
if (targetUri && fileNameCache[targetUri]) {
|
||||
setFileName(fileNameCache[targetUri]);
|
||||
@@ -130,12 +130,12 @@ export default function useImageUploader(
|
||||
const uploadImg = useCallback(
|
||||
async (file: File): Promise<ImageUploader['uploadResult'] | undefined> => {
|
||||
await uploaderRef.current.select(file);
|
||||
// 图片校验不通过
|
||||
// The picture verification failed.
|
||||
if (!uploaderRef.current.validateResult?.isSuccess) {
|
||||
Toast.error(
|
||||
uploaderRef.current.validateResult?.msg || '图片不符合要求',
|
||||
);
|
||||
// @ts-expect-error 此处 validateResult.isSuccess 为 false
|
||||
// @ts-expect-error here validateResult.isSuccess is false
|
||||
return uploaderRef.current.validateResult;
|
||||
}
|
||||
|
||||
@@ -146,10 +146,10 @@ export default function useImageUploader(
|
||||
await uploaderRef.current.upload();
|
||||
setLoading(false);
|
||||
|
||||
// 上传结果
|
||||
// Upload result
|
||||
const { uploadResult } = uploaderRef.current;
|
||||
|
||||
// 无上传结果说明上传取消
|
||||
// No upload result indicates that the upload is cancelled.
|
||||
if (!uploadResult) {
|
||||
return;
|
||||
}
|
||||
@@ -159,7 +159,7 @@ export default function useImageUploader(
|
||||
if (uploadResult.isSuccess) {
|
||||
Toast.success(I18n.t('file_upload_success'));
|
||||
setUri(uploadResult.uri);
|
||||
// FIXME: 合理的设计应该用 uri 进行缓存, 但是 Imageflow 初期只存储了 url, 使用 url 作为临时方案
|
||||
// FIXME: A reasonable design should cache with URIs, but Imageflow initially only stored URLs, using URLs as a temporary solution
|
||||
fileNameCache[uploadResult.url] = `${file.name}`;
|
||||
} else {
|
||||
Toast.error(uploadResult.msg);
|
||||
@@ -172,7 +172,7 @@ export default function useImageUploader(
|
||||
const retryUploadImg = useCallback(async (): Promise<
|
||||
ImageUploader['uploadResult']
|
||||
> => {
|
||||
// 重传前置检查, 有文件且校验通过
|
||||
// Resend pre-check, there is a file and the verification is passed
|
||||
if (
|
||||
!uploaderRef.current?.file ||
|
||||
!uploaderRef.current?.validateResult?.isSuccess
|
||||
@@ -189,7 +189,7 @@ export default function useImageUploader(
|
||||
await uploaderRef.current.upload();
|
||||
setLoading(false);
|
||||
|
||||
// 上传结果
|
||||
// Upload result
|
||||
const uploadResult = uploaderRef.current.uploadResult || {
|
||||
isSuccess: false,
|
||||
errNo: ImgUploadErrNo.UploadFail,
|
||||
|
||||
Reference in New Issue
Block a user