index.tsx 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. import { LoadingOutlined, PlusOutlined, UploadOutlined } from '@ant-design/icons';
  2. import SystemConst from '@/utils/const';
  3. import Token from '@/utils/token';
  4. import type { ReactNode } from 'react';
  5. import { useState } from 'react';
  6. import { connect } from '@formily/react';
  7. import { Input, Upload } from 'antd';
  8. import type { UploadChangeParam } from 'antd/lib/upload/interface';
  9. import type { UploadListType } from 'antd/es/upload/interface';
  10. import './index.less';
  11. interface Props {
  12. value: string;
  13. onChange: (value: string | FileProperty | any) => void;
  14. type?: 'file' | 'image';
  15. placeholder: string;
  16. display?: string;
  17. beforeUpload: any;
  18. }
  19. type FileProperty = {
  20. url: string;
  21. size: number;
  22. };
  23. const FUpload = connect((props: Props) => {
  24. const [url, setUrl] = useState<string | FileProperty>(props?.value);
  25. const [loading, setLoading] = useState<boolean>(false);
  26. const handleChange = (info: UploadChangeParam) => {
  27. if (info.file.status === 'uploading') {
  28. setLoading(false);
  29. }
  30. if (info.file.status === 'done') {
  31. info.file.url = info.file.response?.result;
  32. setLoading(false);
  33. const f = {
  34. size: info.file.size || 0,
  35. url: info.file.response?.result,
  36. name: info.file.name,
  37. };
  38. setUrl(f);
  39. props.onChange(f);
  40. }
  41. };
  42. const map = new Map<
  43. string,
  44. {
  45. node: ReactNode;
  46. type: UploadListType;
  47. }
  48. >();
  49. map.set('image', {
  50. node: (
  51. <>
  52. {url ? (
  53. <img src={url as string} alt="avatar" style={{ width: '100%' }} />
  54. ) : (
  55. <div>
  56. {loading ? <LoadingOutlined /> : <PlusOutlined />}
  57. <div style={{ marginTop: 8 }}>选择图片</div>
  58. </div>
  59. )}
  60. </>
  61. ),
  62. type: 'picture-card',
  63. });
  64. map.set('file', {
  65. node: (
  66. <>
  67. <Input
  68. placeholder={props.placeholder}
  69. // 如果display 有值的话,显示display 的值
  70. value={url && (url as FileProperty)[props?.display || 'url']}
  71. onChange={(value) => {
  72. setUrl({
  73. [props?.display || 'url']: value.target.value,
  74. } as any);
  75. props.onChange({ [props?.display || '_a']: value.target.value, url: null, size: null });
  76. }}
  77. onClick={(e) => {
  78. e.preventDefault();
  79. e.stopPropagation();
  80. }}
  81. addonAfter={<UploadOutlined />}
  82. />
  83. </>
  84. ),
  85. type: 'text',
  86. });
  87. return (
  88. <Upload
  89. beforeUpload={props.beforeUpload}
  90. listType={map.get(props.type || 'image')?.type}
  91. action={`/${SystemConst.API_BASE}/file/static`}
  92. headers={{
  93. 'X-Access-Token': Token.get(),
  94. }}
  95. onChange={handleChange}
  96. showUploadList={false}
  97. >
  98. {map.get(props.type || 'image')?.node}
  99. </Upload>
  100. );
  101. });
  102. export default FUpload;