Appearance
AntDesign
antdesign 组件库常用开发技巧
图片上传
下面是图片上传组件的定义,使用 antdesign 的Upload组件进行二次封装。你需要阅读代码注释,进行相应的修改以符合你的项目需求。
下面是组件的具体代码,何俊已经加上了注释,理解阅读应该是没有问题的
import { useValidateStore } from '@/store/useValidateStore'
import classNames from 'classnames'
import { FieldValidateError } from './FieldValidateError'
import { IFieldComponent } from './types'
import { IUploadProps, UploadImage } from '../upload/UploadImage'
import { FormApi, ReactFormApi } from '@tanstack/react-form'
interface IProps extends Omit<IFieldComponent, 'children'>, IUploadProps {
form: FormApi<any, any> & ReactFormApi<any, any>
action?: string
name: string
}
export function FieldUploadImage({ form, name, className, action, onSuccess, ...props }: IProps) {
const removeError = useValidateStore((s) => s.removeError)
return (
<form.Field
name={name}
children={(field) => (
<div className={classNames({ 'flex flex-col gap-1': props.label })}>
{props.label && <div className='text-sm '>{props.label}</div>}
<div onClick={() => removeError(name)}>
<UploadImage
defaultImage={field.state.value}
action={action ?? '/upload/image'}
fieldName={name}
onSuccess={({ url }) => {
if (onSuccess) onSuccess(url)
else form.setFieldValue(name, url)
}}
className={className}
/>
<FieldValidateError errors={field.state.meta.errors} name={name} />
</div>
</div>
)}
/>
)
}
文件上传
下面使用 antdesign 封装文件上传组件,用于处理 mp4等文件的上传处理。
组件除了可以使用 antdesign 的 props 外,增加了以下props
props | 说明 |
---|---|
children | 组件的显示 html |
onSuccess | 上传成功的处理函数 |
fieldName | 后台接收的文件post 数据的 name 字段 |
下面是组件的具体代码,何俊已经加上了注释,理解阅读应该是没有问题的
import { useAxios } from '@/hooks/useAxios'
import { UploadOutlined } from '@ant-design/icons'
import type { UploadProps } from 'antd'
import { Button, message, Progress, Upload } from 'antd'
import { UploadChangeParam } from 'antd/es/upload'
import { UploadFile as UploadFileType } from 'antd/lib'
import classNames from 'classnames'
import qs from 'qs'
import React, { useState } from 'react'
//在原有 antdesign upload 组件基础上进行props类型封装
export interface UploadFileProps extends UploadProps {
children: React.ReactNode
onSuccess: (res: Record<string, any>) => void
fieldName: string
}
//上传文件
export const UploadFile: React.FC<UploadFileProps> = ({ children, onSuccess, fieldName, ...props }) => {
//进度条
const [percent, setPercent] = useState(0)
//显示进度条
const [showProgress, setShowProgress] = useState(false)
//axios 实例用于自定义上传
const { axiosInstance } = useAxios()
//自定义上传处理
async function customRequest(options: any) {
const { action, onSuccess, file } = options
//生成提交的 form 表单
const form = new FormData()
form.append('file', file)
try {
//fieldName会以请求参数的形式传递,方便后台根据字段名获取文件
const response = await axiosInstance.post<Record<string, string>>(
action + `?` + qs.stringify({ field: fieldName }),
form,
)
onSuccess(response.data)
} catch (error) {
setShowProgress(false)
}
}
//上传完成时的处理函数
function handleUpload(info: UploadChangeParam<UploadFileType<any>>) {
//上传中
if (info.file.status == 'uploading') {
//设置进度条显示
setShowProgress(true)
//设置上传进度
setPercent(info.file.percent!)
}
//上传成功完成
if (info.file.status == 'done') {
//设置进度条隐藏
setShowProgress(false)
//进度设置为0
setPercent(0)
//上传成功的回调处理
onSuccess(info.file.response)
}
//上传失败
if (info.file.status == 'error') {
setShowProgress(false)
const error = info.file.response.message
message.error(error || '上传失败')
}
}
return (
<Upload {...props} customRequest={customRequest} onChange={handleUpload}>
<div className='flex justify-start items-end gap-3'>
{children || <Button icon={<UploadOutlined />}>选择文件</Button>}
<Progress percent={percent} className={classNames('w-[500px] opacity-0', { '!opacity-100': showProgress })} />
</div>
</Upload>
)
}