|
@@ -0,0 +1,385 @@
|
|
|
+import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
|
+import styles from "./index.module.scss";
|
|
|
+
|
|
|
+import { InboxOutlined } from "@ant-design/icons";
|
|
|
+import {
|
|
|
+ Button,
|
|
|
+ message,
|
|
|
+ Modal,
|
|
|
+ Popconfirm,
|
|
|
+ Select,
|
|
|
+ Upload,
|
|
|
+ UploadFile,
|
|
|
+ UploadProps,
|
|
|
+} from "antd";
|
|
|
+
|
|
|
+import { EyeOutlined, DownloadOutlined } from "@ant-design/icons";
|
|
|
+
|
|
|
+import history from "@/utils/history";
|
|
|
+import React from "react";
|
|
|
+import { getTokenFu } from "@/utils/storage";
|
|
|
+import { MessageFu } from "@/utils/message";
|
|
|
+import { A1_APIOupFileIds, A1_APIremoveSure } from "@/store/action/A1Project";
|
|
|
+import { authFilesLookFu, urlChangeFu } from "@/utils/authFilesLook";
|
|
|
+import { useSelector } from "react-redux";
|
|
|
+import { RootState } from "@/store";
|
|
|
+
|
|
|
+const { Dragger } = Upload;
|
|
|
+
|
|
|
+type SelectType = {
|
|
|
+ id: string;
|
|
|
+ value: number | undefined;
|
|
|
+ txt: string;
|
|
|
+ tit: string;
|
|
|
+ fileName: string;
|
|
|
+};
|
|
|
+
|
|
|
+type props = {
|
|
|
+ myUrl: string;
|
|
|
+ upFileFu: () => void;
|
|
|
+ closeFu: () => void;
|
|
|
+};
|
|
|
+
|
|
|
+function A1IupFile({ myUrl, closeFu, upFileFu }: props) {
|
|
|
+ // 从仓库获取 内控文件 属性
|
|
|
+ const typeData = useSelector((state: RootState) => state.A2Dict.A2Tab2Arr);
|
|
|
+
|
|
|
+ const [typeSelect, setTypeSelect] = useState([] as SelectType[]);
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ console.log("pppppppp", typeSelect);
|
|
|
+ }, [typeSelect]);
|
|
|
+
|
|
|
+ // 下拉框改变
|
|
|
+ const selectChangeFu = useCallback(
|
|
|
+ (val: number, id: string) => {
|
|
|
+ const info = typeData.find((v) => v.id === val)!;
|
|
|
+
|
|
|
+ const tit = info.suffix ? info.suffix : "all";
|
|
|
+
|
|
|
+ setTypeSelect(
|
|
|
+ typeSelect.map((v) => ({
|
|
|
+ ...v,
|
|
|
+ value: v.id === id ? val : v.value,
|
|
|
+ txt: v.id === id ? info.description : v.txt,
|
|
|
+ tit: v.id === id ? tit : v.tit,
|
|
|
+ }))
|
|
|
+ );
|
|
|
+ },
|
|
|
+ [typeData, typeSelect]
|
|
|
+ );
|
|
|
+
|
|
|
+ // 校验指定格式
|
|
|
+ const typeGeShiFlag = useCallback((val: string, name: string) => {
|
|
|
+ if (val === "all") return false;
|
|
|
+ else {
|
|
|
+ let flag = true;
|
|
|
+
|
|
|
+ const arr = val.split(",");
|
|
|
+
|
|
|
+ arr.forEach((v) => {
|
|
|
+ if (name.includes("." + v)) flag = false;
|
|
|
+ });
|
|
|
+
|
|
|
+ return flag;
|
|
|
+ }
|
|
|
+ }, []);
|
|
|
+
|
|
|
+ // 确定按钮的格式校验
|
|
|
+ const disBtnOkRes = useMemo(() => {
|
|
|
+ let flag = false;
|
|
|
+ typeSelect.forEach((v) => {
|
|
|
+ if (v.tit !== "all") {
|
|
|
+ const arr = v.tit.split(","); //['pdf','gif']
|
|
|
+
|
|
|
+ const arr2 = v.fileName.split(".");
|
|
|
+
|
|
|
+ const str = arr2[arr2.length - 1]; //66666.pdf =>pdf
|
|
|
+
|
|
|
+ if (arr.every((v2) => v2 !== str)) flag = true;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return flag;
|
|
|
+ }, [typeSelect]);
|
|
|
+
|
|
|
+ const [modal, contextHolder] = Modal.useModal();
|
|
|
+
|
|
|
+ const [fileList, setFileList] = useState<UploadFile[]>([]);
|
|
|
+
|
|
|
+ const timeRef = useRef(-1);
|
|
|
+
|
|
|
+ const FileProps: UploadProps = {
|
|
|
+ name: "file",
|
|
|
+ multiple: true,
|
|
|
+ action: myUrl,
|
|
|
+ headers: {
|
|
|
+ token: getTokenFu(),
|
|
|
+ },
|
|
|
+ // 支持上传文件夹
|
|
|
+ directory: true,
|
|
|
+ fileList,
|
|
|
+ //不要前面的图标
|
|
|
+ // iconRender: () => false,
|
|
|
+ // 文件上传之前 -- 这里不用校验
|
|
|
+ // beforeUpload(file, fileList) {
|
|
|
+ // // console.log("文件上传之前-用于校验", file);
|
|
|
+ // // if (file.fileName.includes("4dage")) {
|
|
|
+ // // // console.log("校验不通过,不上传");
|
|
|
+ // // message.error(`${file.fileName}不符合上传需求`);
|
|
|
+ // // return Upload.LIST_IGNORE;
|
|
|
+ // // }
|
|
|
+ // },
|
|
|
+ onChange(info) {
|
|
|
+ setFileList([...info.fileList]);
|
|
|
+
|
|
|
+ const { status } = info.file;
|
|
|
+ if (status !== "uploading") {
|
|
|
+ // 检查请求状态
|
|
|
+ const response = info.file.response || {};
|
|
|
+
|
|
|
+ if (response.code !== 0) {
|
|
|
+ clearTimeout(timeRef.current);
|
|
|
+
|
|
|
+ timeRef.current = window.setTimeout(() => {
|
|
|
+ setFileList(info.fileList.filter((v) => v.uid !== info.file.uid));
|
|
|
+ }, 100);
|
|
|
+ }
|
|
|
+ if (response.code === 5001 || response.code === 5002) {
|
|
|
+ message.warning("登录失效!");
|
|
|
+ history.push("/login");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // console.log(info.file, info.fileList);
|
|
|
+ }
|
|
|
+ if (status === "done") {
|
|
|
+ // console.log("-----", info);
|
|
|
+
|
|
|
+ setTypeSelect([
|
|
|
+ ...typeSelect,
|
|
|
+ {
|
|
|
+ id: info.file.response.data.id,
|
|
|
+ value: undefined,
|
|
|
+ txt: "",
|
|
|
+ tit: "",
|
|
|
+ fileName: info.file.name,
|
|
|
+ },
|
|
|
+ ]);
|
|
|
+
|
|
|
+ // message.success(`${info.file.fileName} 上传成功.`);
|
|
|
+ } else if (status === "error") {
|
|
|
+ message.error(`${info.file.fileName} 上传失败.`);
|
|
|
+ // 去掉列表中的失败状态文件
|
|
|
+ clearTimeout(timeRef.current);
|
|
|
+
|
|
|
+ timeRef.current = window.setTimeout(() => {
|
|
|
+ setFileList(info.fileList.filter((v) => v.uid !== info.file.uid));
|
|
|
+ }, 100);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // onDrop(e) {
|
|
|
+ // // console.log("拖动文件到上传区域", e.dataTransfer.files);
|
|
|
+ // },
|
|
|
+ // 点击删除
|
|
|
+ async onRemove(info) {
|
|
|
+ const promiseFu = new Promise((resolve: (value: boolean) => void) => {
|
|
|
+ modal.confirm({
|
|
|
+ title: "删除确认",
|
|
|
+ content: "删除后无法恢复,是否删除?",
|
|
|
+ okText: "删除",
|
|
|
+ cancelText: "取消",
|
|
|
+ async onOk() {
|
|
|
+ if (info.percent === 100) {
|
|
|
+ // console.log("-----还没有发请求删除", info);
|
|
|
+ const id = info.response.data.id;
|
|
|
+ // 已经上传完成,发请求删除
|
|
|
+ const res = await A1_APIremoveSure([id + ""]);
|
|
|
+
|
|
|
+ if (res.code === 0) {
|
|
|
+ setTypeSelect(typeSelect.filter((v) => v.id !== id));
|
|
|
+ resolve(true);
|
|
|
+ MessageFu.success("删除成功!");
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ resolve(true);
|
|
|
+ MessageFu.success("删除成功!");
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onCancel() {
|
|
|
+ resolve(false);
|
|
|
+ },
|
|
|
+ });
|
|
|
+ });
|
|
|
+ return await promiseFu;
|
|
|
+ },
|
|
|
+ };
|
|
|
+
|
|
|
+ // 点击确定
|
|
|
+ const btnOkFu = useCallback(async () => {
|
|
|
+ if (fileList.some((v) => v.percent !== 100))
|
|
|
+ return message.warning("有文件未上传完成.");
|
|
|
+
|
|
|
+ // 拿到 id集合
|
|
|
+
|
|
|
+ const ids: number[] = [];
|
|
|
+
|
|
|
+ fileList.forEach((v) => {
|
|
|
+ ids.push(v.response.data.id);
|
|
|
+ });
|
|
|
+
|
|
|
+ const res = await A1_APIOupFileIds(ids.join(","));
|
|
|
+
|
|
|
+ if (res.code === 0) {
|
|
|
+ MessageFu.success("保存成功!");
|
|
|
+ upFileFu();
|
|
|
+ closeFu();
|
|
|
+ }
|
|
|
+ }, [closeFu, fileList, upFileFu]);
|
|
|
+
|
|
|
+ return (
|
|
|
+ <Modal
|
|
|
+ wrapClassName={styles.A1IupFile}
|
|
|
+ destroyOnClose
|
|
|
+ open={true}
|
|
|
+ title="内控文件上传"
|
|
|
+ footer={
|
|
|
+ [] // 设置footer为空,去掉 取消 确定默认按钮
|
|
|
+ }
|
|
|
+ >
|
|
|
+ <div className="A1OMain">
|
|
|
+ <Dragger {...FileProps}>
|
|
|
+ <p className="ant-upload-drag-icon">
|
|
|
+ <InboxOutlined rev={undefined} />
|
|
|
+ </p>
|
|
|
+ <br />
|
|
|
+ <p className="ant-upload-text">
|
|
|
+ 点击上传整个文件夹,或拖动多个文件至此上传
|
|
|
+ </p>
|
|
|
+ </Dragger>
|
|
|
+ {/* 自定义 预览 下载 删除 */}
|
|
|
+ <div className="myIncoBox">
|
|
|
+ {fileList.map((v, i) => (
|
|
|
+ <div className="myIncoRow" key={v.uid}>
|
|
|
+ {v.percent === 100 && v.response && v.response.data ? (
|
|
|
+ <>
|
|
|
+ {authFilesLookFu(v.response.data.fileName) ? (
|
|
|
+ <>
|
|
|
+ {/* // 1.预览(fileName里面有常用的,浏览器能识别的 图片 音频 视频 模型) */}
|
|
|
+ <div title="预览文件">
|
|
|
+ <EyeOutlined
|
|
|
+ rev={undefined}
|
|
|
+ onClick={() =>
|
|
|
+ authFilesLookFu(
|
|
|
+ v.response.data.fileName,
|
|
|
+ v.response.data.filePath
|
|
|
+ )
|
|
|
+ }
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </>
|
|
|
+ ) : null}
|
|
|
+ {/* // 2.下载 */}
|
|
|
+ <div
|
|
|
+ title="下载文件"
|
|
|
+ onClick={() =>
|
|
|
+ urlChangeFu(
|
|
|
+ v.response.data.filePath,
|
|
|
+ true,
|
|
|
+ undefined,
|
|
|
+ v.response.data.fileName
|
|
|
+ )
|
|
|
+ }
|
|
|
+ >
|
|
|
+ <DownloadOutlined rev={undefined} />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {/* 下拉框 */}
|
|
|
+ <div className="A1IUselect">
|
|
|
+ <Select
|
|
|
+ style={{ width: 200 }}
|
|
|
+ placeholder="请选择"
|
|
|
+ value={typeSelect[i] ? typeSelect[i].value : undefined}
|
|
|
+ onChange={(e) => selectChangeFu(e, typeSelect[i].id)}
|
|
|
+ options={typeData.map((v) => ({
|
|
|
+ value: v.id,
|
|
|
+ label: v.name,
|
|
|
+ }))}
|
|
|
+ />
|
|
|
+
|
|
|
+ {/* 没选择的时候的提示 */}
|
|
|
+ <div className="A1IUselectTit">
|
|
|
+ {typeSelect[i] && typeSelect[i].value ? (
|
|
|
+ <div className="A1IUselectTit2">
|
|
|
+ <div title={typeSelect[i].txt}>
|
|
|
+ {typeSelect[i].txt}
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {typeGeShiFlag(
|
|
|
+ typeSelect[i].tit,
|
|
|
+ typeSelect[i].fileName
|
|
|
+ ) ? (
|
|
|
+ <div
|
|
|
+ className="A1IUselectTit2Tit"
|
|
|
+ title={`该文件类型只支持 ${typeSelect[i].tit}`}
|
|
|
+ >
|
|
|
+  该文件类型只支持 {typeSelect[i].tit} 格式
|
|
|
+ </div>
|
|
|
+ ) : null}
|
|
|
+
|
|
|
+ {/* {typeSelect[i].tit !== "all" &&
|
|
|
+ typeSelect[i].fileName.includes(typeSelect[i].tit) ? (
|
|
|
+
|
|
|
+ ) : (
|
|
|
+ ""
|
|
|
+ )} */}
|
|
|
+ </div>
|
|
|
+ ) : (
|
|
|
+ <div className="A1IUselectTit1">请选择文件类型</div>
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </>
|
|
|
+ ) : (
|
|
|
+ ""
|
|
|
+ )}
|
|
|
+
|
|
|
+ {/* 3.前面的序号 */}
|
|
|
+ {/* <div className="mySortQ" hidden={fileList.length <= 1}>
|
|
|
+ {i + 1}.
|
|
|
+ </div> */}
|
|
|
+ </div>
|
|
|
+ ))}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div className="A1OUpBtn">
|
|
|
+ <Popconfirm
|
|
|
+ title="放弃编辑后,信息将不会保存!"
|
|
|
+ okText="放弃"
|
|
|
+ cancelText="取消"
|
|
|
+ onConfirm={closeFu}
|
|
|
+ okButtonProps={{ loading: false }}
|
|
|
+ >
|
|
|
+ <Button>取消</Button>
|
|
|
+ </Popconfirm>
|
|
|
+  
|
|
|
+ <Button
|
|
|
+ type="primary"
|
|
|
+ onClick={btnOkFu}
|
|
|
+ disabled={
|
|
|
+ fileList.length <= 0 ||
|
|
|
+ typeSelect.some((v) => !v.value) ||
|
|
|
+ disBtnOkRes
|
|
|
+ }
|
|
|
+ >
|
|
|
+ 确定
|
|
|
+ </Button>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {contextHolder}
|
|
|
+ </Modal>
|
|
|
+ );
|
|
|
+}
|
|
|
+
|
|
|
+const MemoA1IupFile = React.memo(A1IupFile);
|
|
|
+export default MemoA1IupFile;
|