|
@@ -0,0 +1,362 @@
|
|
|
|
+import React, {
|
|
|
|
+ useCallback,
|
|
|
|
+ useEffect,
|
|
|
|
+ useMemo,
|
|
|
|
+ useRef,
|
|
|
|
+ useState,
|
|
|
|
+} from "react";
|
|
|
|
+import styles from "./index.module.scss";
|
|
|
|
+import { forwardRef, useImperativeHandle } from "react";
|
|
|
|
+import { MessageFu } from "@/utils/message";
|
|
|
|
+import { API_upFile } from "@/store/action/layout";
|
|
|
|
+import { fileDomInitialFu } from "@/utils/domShow";
|
|
|
|
+import {
|
|
|
|
+ UploadOutlined,
|
|
|
|
+ EyeOutlined,
|
|
|
|
+ CloseOutlined,
|
|
|
|
+ DownloadOutlined,
|
|
|
|
+} from "@ant-design/icons";
|
|
|
|
+import classNames from "classnames";
|
|
|
|
+import { baseURL } from "@/utils/http";
|
|
|
|
+import store from "@/store";
|
|
|
|
+import MyPopconfirm from "../MyPopconfirm";
|
|
|
|
+import { Button, Input } from "antd";
|
|
|
|
+import ImageLazy from "../ImageLazy";
|
|
|
|
+
|
|
|
|
+export type ZupVideosTxtType = {
|
|
|
|
+ fileName: string;
|
|
|
|
+ filePath: string;
|
|
|
|
+ id: number;
|
|
|
|
+ // type: "video" | "img";
|
|
|
|
+ // parentId: number | null;
|
|
|
|
+ son: { txt: string; thumb: string; thumbId: number };
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+type Props = {
|
|
|
|
+ size: number; //视频大小
|
|
|
|
+ fileNum: number; //数量限制
|
|
|
|
+ dirCode: string; //文件的code码
|
|
|
|
+ myUrl: string; //请求地址
|
|
|
|
+ fileCheck?: boolean; //是否检验
|
|
|
|
+ format?: string[]; //上传格式 默认["video/mp4"]
|
|
|
|
+ formatTxt?: string; //上传提示
|
|
|
|
+ checkTxt?: string;
|
|
|
|
+ upTxt?: string;
|
|
|
|
+ isLook?: boolean; //是不是查看
|
|
|
|
+ fromData?: any;
|
|
|
|
+ ref: any; //当前自己的ref,给父组件调用
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+function ZupVideosTxt(
|
|
|
|
+ {
|
|
|
|
+ size,
|
|
|
|
+ fileNum,
|
|
|
|
+ dirCode,
|
|
|
|
+ myUrl,
|
|
|
|
+ fileCheck = false,
|
|
|
|
+ format = ["video/mp4"],
|
|
|
|
+ formatTxt = ".mp4",
|
|
|
|
+ checkTxt = "请上传视频!",
|
|
|
|
+ upTxt = "",
|
|
|
|
+ isLook = false,
|
|
|
|
+ fromData,
|
|
|
|
+ }: Props,
|
|
|
|
+ ref: any
|
|
|
|
+) {
|
|
|
|
+ const [fileList, setFileList] = useState<ZupVideosTxtType[]>([]);
|
|
|
|
+
|
|
|
|
+ // 区分 一级视频上传 和 二级封面图上传
|
|
|
|
+ const [level, setLevel] = useState<0 | 1 | 2>(0);
|
|
|
|
+
|
|
|
|
+ const levelChangeFu = useCallback((val: 1 | 2) => {
|
|
|
|
+ setLevel(0);
|
|
|
|
+ setTimeout(() => {
|
|
|
|
+ setLevel(val);
|
|
|
|
+ }, 30);
|
|
|
|
+ }, []);
|
|
|
|
+
|
|
|
|
+ useEffect(() => {
|
|
|
|
+ if (level) myInput.current?.click();
|
|
|
|
+ }, [level]);
|
|
|
|
+
|
|
|
|
+ const fIdRef = useRef(0);
|
|
|
|
+
|
|
|
|
+ // 上传
|
|
|
|
+ const handeUpPhoto = useCallback(
|
|
|
|
+ async (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
|
|
+ if (e.target.files) {
|
|
|
|
+ // 拿到files信息
|
|
|
|
+ const filesInfo = e.target.files[0];
|
|
|
|
+ // console.log("-----", filesInfo.type);
|
|
|
|
+
|
|
|
|
+ const formatRes = level === 1 ? format : ["image/jpeg", "image/png"];
|
|
|
|
+ const formatTxtRes = level === 1 ? formatTxt : ".png,.jpg,.jpeg";
|
|
|
|
+ const sizeRes = level === 1 ? size : 1;
|
|
|
|
+
|
|
|
|
+ // 校验格式
|
|
|
|
+ if (!formatRes.includes(filesInfo.type)) {
|
|
|
|
+ e.target.value = "";
|
|
|
|
+ return MessageFu.warning(`只支持${formatTxtRes}格式!`);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 校验大小
|
|
|
|
+ if (filesInfo.size > sizeRes * 1024 * 1024) {
|
|
|
|
+ e.target.value = "";
|
|
|
|
+ return MessageFu.warning(`最大支持${sizeRes}M!`);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 创建FormData对象
|
|
|
|
+ const fd = new FormData();
|
|
|
|
+
|
|
|
|
+ fd.append("type", level === 1 ? "video" : "img");
|
|
|
|
+ fd.append("isDb", "true");
|
|
|
|
+ fd.append("dirCode", dirCode);
|
|
|
|
+ if (level === 2) fd.append("parentId", fIdRef.current + "");
|
|
|
|
+
|
|
|
|
+ fd.append("file", filesInfo);
|
|
|
|
+
|
|
|
|
+ if (fromData) {
|
|
|
|
+ for (const k in fromData) {
|
|
|
|
+ if (fromData[k]) fd.append(k, fromData[k]);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ e.target.value = "";
|
|
|
|
+
|
|
|
|
+ try {
|
|
|
|
+ const res = await API_upFile(fd, myUrl);
|
|
|
|
+ if (res.code === 0) {
|
|
|
|
+ MessageFu.success("上传成功!");
|
|
|
|
+
|
|
|
|
+ const dataRes = res.data;
|
|
|
|
+
|
|
|
|
+ if (level === 1) {
|
|
|
|
+ setFileList([
|
|
|
|
+ ...fileList,
|
|
|
|
+ { ...dataRes, son: { txt: "", thumb: "" } },
|
|
|
|
+ ]);
|
|
|
|
+ } else if (level === 2) {
|
|
|
|
+ setFileList(
|
|
|
|
+ fileList.map((v) => ({
|
|
|
|
+ ...v,
|
|
|
|
+ son:
|
|
|
|
+ v.id === fIdRef.current
|
|
|
|
+ ? {
|
|
|
|
+ txt: v.son.txt,
|
|
|
|
+ thumb: dataRes.filePath,
|
|
|
|
+ thumbId: dataRes.id,
|
|
|
|
+ }
|
|
|
|
+ : v.son,
|
|
|
|
+ }))
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ fileDomInitialFu();
|
|
|
|
+ } catch (error) {
|
|
|
|
+ fileDomInitialFu();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ [dirCode, fileList, format, formatTxt, fromData, level, myUrl, size]
|
|
|
|
+ );
|
|
|
|
+
|
|
|
|
+ const myInput = useRef<HTMLInputElement>(null);
|
|
|
|
+
|
|
|
|
+ // 点击预览
|
|
|
|
+ const lookFileFu = useCallback((url: string, type: "video" | "img") => {
|
|
|
|
+ type === "video"
|
|
|
|
+ ? store.dispatch({
|
|
|
|
+ type: "layout/lookDom",
|
|
|
|
+ payload: { src: url, type: "video" },
|
|
|
|
+ })
|
|
|
|
+ : store.dispatch({
|
|
|
|
+ type: "layout/lookBigImg",
|
|
|
|
+ payload: { url: baseURL + url, show: true },
|
|
|
|
+ });
|
|
|
|
+ }, []);
|
|
|
|
+
|
|
|
|
+ // 上传了视频但是没有填写 采访问题 或者没有上传封面图
|
|
|
|
+ const isOneVideoFlag = useMemo(() => {
|
|
|
|
+ let flag = false;
|
|
|
|
+
|
|
|
|
+ if (fileList.some((v) => !v.son.thumb || !v.son.txt)) flag = true;
|
|
|
|
+
|
|
|
|
+ return flag;
|
|
|
|
+ }, [fileList]);
|
|
|
|
+
|
|
|
|
+ // 让父组件调用的 回显 附件 地址
|
|
|
|
+ const setFileComFileFu = useCallback((valList: ZupVideosTxtType[]) => {
|
|
|
|
+ setFileList(valList);
|
|
|
|
+ }, []);
|
|
|
|
+
|
|
|
|
+ // 让父组件调用的返回 附件 名字和路径
|
|
|
|
+ const fileComFileResFu = useCallback(() => {
|
|
|
|
+ return { fileList, isOneVideoFlag };
|
|
|
|
+ }, [fileList, isOneVideoFlag]);
|
|
|
|
+
|
|
|
|
+ // 可以让父组件调用子组件的方法
|
|
|
|
+ useImperativeHandle(ref, () => ({
|
|
|
|
+ setFileComFileFu,
|
|
|
|
+ fileComFileResFu,
|
|
|
|
+ }));
|
|
|
|
+
|
|
|
|
+ // 采访问题的输入框的改变 | 删除
|
|
|
|
+ const fileSonChangeFu = useCallback(
|
|
|
|
+ (id: number, val: string, key: "txt" | "thumb") => {
|
|
|
|
+ setFileList(
|
|
|
|
+ fileList.map((v) => ({
|
|
|
|
+ ...v,
|
|
|
|
+ son:
|
|
|
|
+ v.id === id
|
|
|
|
+ ? {
|
|
|
|
+ ...v.son,
|
|
|
|
+ [key]: val,
|
|
|
|
+ }
|
|
|
|
+ : v.son,
|
|
|
|
+ }))
|
|
|
|
+ );
|
|
|
|
+ },
|
|
|
|
+ [fileList]
|
|
|
|
+ );
|
|
|
|
+
|
|
|
|
+ return (
|
|
|
|
+ <div className={styles.ZupVideosTxt}>
|
|
|
|
+ <input
|
|
|
|
+ id="upInput"
|
|
|
|
+ type="file"
|
|
|
|
+ accept={level === 1 ? formatTxt : ".png,.jpg,.jpeg"}
|
|
|
|
+ ref={myInput}
|
|
|
|
+ onChange={(e) => handeUpPhoto(e)}
|
|
|
|
+ />
|
|
|
|
+
|
|
|
|
+ <div className="zVmain">
|
|
|
|
+ <div className="file_upIcon">
|
|
|
|
+ <Button
|
|
|
|
+ hidden={fileList.length >= fileNum}
|
|
|
|
+ disabled={isOneVideoFlag}
|
|
|
|
+ icon={<UploadOutlined rev={undefined} />}
|
|
|
|
+ onClick={() => levelChangeFu(1)}
|
|
|
|
+ >
|
|
|
|
+ 上传
|
|
|
|
+ </Button>
|
|
|
|
+ <span className={classNames(isOneVideoFlag ? "ZvUpTit" : "")}>
|
|
|
|
+ 请完整填写采访问题并且上传封面图!
|
|
|
|
+ </span>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <div className="fileBoxRow_r_tit" hidden={fileList.length >= fileNum}>
|
|
|
|
+ 仅支持{formatTxt.replaceAll(".", "")}格式,最大支持{size}M。
|
|
|
|
+ {upTxt}
|
|
|
|
+ <div
|
|
|
|
+ className={classNames(
|
|
|
|
+ "noUpThumb",
|
|
|
|
+ fileList.length <= 0 && fileCheck ? "noUpThumbAc" : ""
|
|
|
|
+ )}
|
|
|
|
+ >
|
|
|
|
+ {checkTxt}
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ {fileList.map((v, i) => (
|
|
|
|
+ <div className="zVRow" key={v.id}>
|
|
|
|
+ <div className="zVR1">
|
|
|
|
+ <div title={v.fileName}>
|
|
|
|
+ <span>{i + 1}. </span>
|
|
|
|
+ {v.fileName}
|
|
|
|
+ </div>
|
|
|
|
+ <EyeOutlined
|
|
|
|
+ onClick={() => lookFileFu(v.filePath, "video")}
|
|
|
|
+ rev={undefined}
|
|
|
|
+ />
|
|
|
|
+ <a
|
|
|
|
+ href={baseURL + v.filePath}
|
|
|
|
+ download
|
|
|
|
+ target="_blank"
|
|
|
|
+ rel="noreferrer"
|
|
|
|
+ >
|
|
|
|
+ <DownloadOutlined rev={undefined} />
|
|
|
|
+ </a>
|
|
|
|
+
|
|
|
|
+ {isLook ? null : (
|
|
|
|
+ <MyPopconfirm
|
|
|
|
+ txtK="删除"
|
|
|
|
+ onConfirm={() =>
|
|
|
|
+ setFileList(fileList.filter((c) => c.id !== v.id))
|
|
|
|
+ }
|
|
|
|
+ Dom={<CloseOutlined rev={undefined} />}
|
|
|
|
+ />
|
|
|
|
+ )}
|
|
|
|
+ </div>
|
|
|
|
+ <div className="zVR2">
|
|
|
|
+ <div
|
|
|
|
+ className={classNames("zVR2_1", v.son.txt ? "" : "zVR2_1Err")}
|
|
|
|
+ >
|
|
|
|
+ <Input
|
|
|
|
+ maxLength={50}
|
|
|
|
+ showCount
|
|
|
|
+ placeholder="请输入采访问题"
|
|
|
|
+ value={v.son.txt}
|
|
|
|
+ onChange={(e) =>
|
|
|
|
+ fileSonChangeFu(
|
|
|
|
+ v.id,
|
|
|
|
+ e.target.value.replace(/\s+/g, ""),
|
|
|
|
+ "txt"
|
|
|
|
+ )
|
|
|
|
+ }
|
|
|
|
+ />
|
|
|
|
+ </div>
|
|
|
|
+ <div
|
|
|
|
+ className={classNames("zVR2_2", v.son.thumb ? "" : "zVR2_2Err")}
|
|
|
|
+ >
|
|
|
|
+ <Button
|
|
|
|
+ hidden={!!v.son.thumb}
|
|
|
|
+ icon={<UploadOutlined rev={undefined} />}
|
|
|
|
+ onClick={() => {
|
|
|
|
+ fIdRef.current = v.id;
|
|
|
|
+ levelChangeFu(2);
|
|
|
|
+ }}
|
|
|
|
+ >
|
|
|
|
+ 上传封面
|
|
|
|
+ </Button>
|
|
|
|
+
|
|
|
|
+ {v.son.thumb ? (
|
|
|
|
+ <div className="zVR2_2Img">
|
|
|
|
+ <ImageLazy
|
|
|
|
+ width={90}
|
|
|
|
+ height={90}
|
|
|
|
+ src={v.son.thumb}
|
|
|
|
+ noLook
|
|
|
|
+ />
|
|
|
|
+ <div className="zVR2_2ImgIcon">
|
|
|
|
+ <EyeOutlined
|
|
|
|
+ onClick={() => lookFileFu(v.son.thumb, "img")}
|
|
|
|
+ rev={undefined}
|
|
|
|
+ />
|
|
|
|
+ <a
|
|
|
|
+ href={baseURL + v.son.thumb}
|
|
|
|
+ download
|
|
|
|
+ target="_blank"
|
|
|
|
+ rel="noreferrer"
|
|
|
|
+ >
|
|
|
|
+ <DownloadOutlined rev={undefined} />
|
|
|
|
+ </a>
|
|
|
|
+
|
|
|
|
+ {isLook ? null : (
|
|
|
|
+ <MyPopconfirm
|
|
|
|
+ txtK="删除"
|
|
|
|
+ onConfirm={() => fileSonChangeFu(v.id, "", "thumb")}
|
|
|
|
+ Dom={<CloseOutlined rev={undefined} />}
|
|
|
|
+ />
|
|
|
|
+ )}
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ ) : null}
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ ))}
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ );
|
|
|
|
+}
|
|
|
|
+export default forwardRef(ZupVideosTxt);
|