相关参考

  1. import { useState, useEffect } from "react";
  2. import { Modal, Button, message } from "antd";
  3. import { LoadingOutlined, PaperClipOutlined } from "@ant-design/icons";
  4. import { UploadFile } from "../components";
  5. import * as PartnerAction from "../api/request/partner";
  6. import "@css/components/upload-partner.less";
  7. export default ({ fetchList }: any) => {
  8. const [visible, setVisible] = useState<boolean>(false);
  9. const [btnLoading, setBtnLoading] = useState<boolean>(false);
  10. const [uploadDisabled, setUploadDisabled] = useState<boolean>(true);
  11. const [uploadFileInfo, setUploadFileInfo] = useState<any>({});
  12. // 确认上传
  13. const onFinish = async () => {
  14. try {
  15. const formData = new FormData();
  16. formData.append("file", uploadFileInfo.file);
  17. setBtnLoading(true);
  18. const { success }: any = await PartnerAction.uploadFile(formData);
  19. setBtnLoading(false);
  20. if (!success) return;
  21. await fetchList();
  22. setVisible(false);
  23. message.success("导入成功");
  24. onUploadFileChange({
  25. status: "none",
  26. });
  27. } catch (error) {
  28. console.log(error);
  29. }
  30. };
  31. // 【X】关闭按钮
  32. const onModalClose = (): void => {
  33. if (btnLoading) return;
  34. setUploadDisabled(true);
  35. setVisible(false);
  36. setUploadFileInfo({
  37. status: "none",
  38. });
  39. };
  40. const onUploadFileChange = (item: any) => {
  41. setUploadFileInfo(item);
  42. };
  43. useEffect(() => {
  44. if (
  45. uploadFileInfo.status === "none" ||
  46. uploadFileInfo.status === "progress"
  47. ) {
  48. setUploadDisabled(true);
  49. }
  50. if (uploadFileInfo.status === "done") {
  51. setUploadDisabled(false);
  52. }
  53. }, [uploadFileInfo]);
  54. return (
  55. <>
  56. <Button onClick={() => setVisible(true)}>文件上传</Button>
  57. <Modal
  58. title="文件上传"
  59. centered
  60. visible={visible}
  61. maskClosable={false}
  62. keyboard={false}
  63. onCancel={onModalClose}
  64. okButtonProps={{ disabled: uploadDisabled, loading: btnLoading }}
  65. cancelButtonProps={{ disabled: uploadDisabled }}
  66. onOk={onFinish}
  67. >
  68. <UploadFile
  69. uploadDisabled={btnLoading}
  70. uploadData={uploadFileInfo}
  71. onUploadFileChange={onUploadFileChange}
  72. />
  73. <>
  74. {uploadFileInfo.status === "none" ? (
  75. <span className="file_prefix">支持扩展名:.xls .xlsx</span>
  76. ) : (
  77. <p className="upload_file">
  78. {uploadFileInfo.status === "progress" && (
  79. <LoadingOutlined className="upload_icon" />
  80. )}
  81. {uploadFileInfo.status === "done" && (
  82. <PaperClipOutlined className="upload_icon" />
  83. )}
  84. {(uploadFileInfo.status === "done" ||
  85. uploadFileInfo.status === "progress") &&
  86. `${uploadFileInfo?.file?.name}`}
  87. </p>
  88. )}
  89. </>
  90. </Modal>
  91. </>
  92. );
  93. };
  1. import { useState, useEffect, useRef } from "react";
  2. import { UploadOutlined } from "@ant-design/icons";
  3. import { Button, message } from "antd";
  4. import { beforeUploadFile } from "../utils";
  5. import "@css/components/upload-file.less";
  6. export default ({ uploadDisabled = false, onUploadFileChange }: any) => {
  7. const uploadFileRef = useRef<any>({});
  8. const [disabled, setDisabled] = useState<boolean>(uploadDisabled);
  9. const [fileData, setFileData] = useState<any>({
  10. status: "none",
  11. });
  12. const onUploadFile = (e: any) => {
  13. const file = e.target.files[0];
  14. if (!beforeUploadFile(file)) return;
  15. const fileReader: any = new FileReader();
  16. fileReader.onload = () => {
  17. const data = {
  18. ...fileData,
  19. file,
  20. status: "done",
  21. };
  22. setFileData(data);
  23. setDisabled(false);
  24. onUploadFileChange(data);
  25. };
  26. fileReader.onerror = () => {
  27. message.error("文件失败,请重新上传:", fileReader.error);
  28. onUploadFileChange({
  29. status: "none",
  30. });
  31. setDisabled(false);
  32. };
  33. fileReader.onprogress = () => {
  34. setFileData({
  35. status: "progress",
  36. });
  37. onUploadFileChange({
  38. status: "progress",
  39. });
  40. setDisabled(true);
  41. };
  42. fileReader.readAsArrayBuffer(file);
  43. };
  44. const onUploadClick = () => {
  45. uploadFileRef.current.click();
  46. };
  47. // 重置input的value为空
  48. /**
  49. * faq:使用input[type=file] 实现文件上传功能,通过onchange事件触发js代码,这个时候第一次上传是完全没问题的,当你第二次上传文件时,如果是不同于上一次上传文件的话是可以正常上传的,不过如果你选择的还是上一个文件,也就是两次上传的文件重复了,那么就会上传失败。
  50. * input是通过onchange事件来触发js代码的,由于两次文件是重复的,所以这个时候onchange事件是没有触发到的。
  51. * how:读取文件后,记得把input的value重新设置为空即e.target.value=''
  52. */
  53. const onResetInputValue = (e: any) => {
  54. (e.target as HTMLInputElement).value = "";
  55. };
  56. useEffect(() => {
  57. onUploadFileChange({
  58. status: "none",
  59. });
  60. }, []);
  61. return (
  62. <>
  63. <div className="upload_container">
  64. <Button disabled={disabled} onClick={onUploadClick}>
  65. <UploadOutlined />
  66. 选择文件
  67. </Button>
  68. <input
  69. ref={uploadFileRef}
  70. type="file"
  71. onClick={(e) => onResetInputValue(e)}
  72. className="upload_input"
  73. onChange={onUploadFile}
  74. />
  75. </div>
  76. </>
  77. );
  78. };
  1. export const EXCEL_SUFFIX_REG = /(xls|xlsx)(\?.*)?/;
  2. // 文件上传校验
  3. export const beforeUploadFile = (file: any): boolean | undefined => {
  4. const temp = file?.name?.split(".");
  5. const suffix = temp[temp.length - 1].toLowerCase();
  6. if (!EXCEL_SUFFIX_REG.test(suffix)) {
  7. message.warning("仅支持导入.xls .xlsx扩展名文件");
  8. return false;
  9. }
  10. return true;
  11. };