shaogen1995 2 năm trước cách đây
mục cha
commit
e630ae0427

+ 3 - 3
houtai/src/assets/styles/base.css

@@ -43,9 +43,6 @@ textarea {
   --themeColor: #f0d99c;
   --themeColor2: #93886e;
 }
-a {
-  color: var(--themeColor);
-}
 /* 找不到页面 */
 .noFindPage {
   opacity: 0;
@@ -72,6 +69,9 @@ a {
   /* antd图片预览组件 */
   /* antd表格居中 */
 }
+#root a {
+  color: var(--themeColor2);
+}
 #root .ant-btn-text {
   color: #99b8dd;
 }

+ 4 - 4
houtai/src/assets/styles/base.less

@@ -53,9 +53,7 @@ textarea {
   --themeColor2: #93886e;
 }
 
-a {
-  color: var(--themeColor);
-}
+
 
 
 
@@ -84,6 +82,9 @@ a {
   overflow: auto;
   overflow-y: overlay;
 
+  a {
+    color: var(--themeColor2);
+  }
 
   /* 普通文字按钮的颜色 */
   .ant-btn-text {
@@ -195,7 +196,6 @@ a {
   color: var(--themeColor2);
 }
 
-
 #upInput {
   display: none;
 }

+ 176 - 0
houtai/src/pages/B2Goods/GoodsAdd/index.module.scss

@@ -0,0 +1,176 @@
+.GoodsAdd {
+  width: 100%;
+  height: 100%;
+  overflow-y: auto;
+  overflow-y: overlay;
+  border-radius: 10px;
+  background-color: #fff;
+  padding: 20px 0;
+
+  :global {
+    .main {
+      width: 800px;
+      padding-left: 5px;
+
+      .myformBox0{
+        margin-top: -20px;
+      }
+
+      .myformBox {
+        .ant-btn-default{
+          width: 100px;
+        }
+        display: flex;
+        margin-bottom: 20px;
+
+        .label {
+          width: 100px;
+          text-align: right;
+
+          &>span {
+            position: relative;
+            top: 2px;
+            color: #ff4d4f;
+          }
+        }
+
+      }
+
+      .myformBox2 {
+        align-items: center;
+        height: 32px;
+
+        .label {
+          height: 32px;
+          line-height: 32px;
+        }
+
+        .fileTit {
+          margin-left: 20px;
+          font-size: 14px;
+          color: rgb(126, 124, 124);
+        }
+
+        .fileInfo {
+          height: 32px;
+          line-height: 32px;
+          display: flex;
+          font-size: 16px;
+
+          .clearCover{
+            margin-left: 20px;
+            cursor: pointer;
+            font-size: 18px;
+          }
+   
+        }
+
+
+      }
+
+      .myformBox3 {
+        margin-top: 20px;
+
+        .upImgBox {
+          display: flex;
+          flex-wrap: wrap;
+
+          &>div {
+            margin: 0 15px 15px 0;
+          }
+
+          .fileBoxRow_r_img {
+            position: relative;
+
+            .clearCover {
+              right: -10px;
+              top: -10px;
+              transform: translate(0, 0);
+              background-color: rgba(0, 0, 0, .8);
+              width: 20px;
+              height: 20px;
+              border-radius: 50%;
+              font-size: 16px;
+              color: #fff;
+            }
+          }
+        }
+
+        .fileTit {
+          font-size: 14px;
+          color: rgb(126, 124, 124);
+        }
+      }
+
+      .fileBoxRow_r {
+        position: relative;
+
+        .fileBoxRow_up {
+          color: #a6a6a6;
+          border-radius: 3px;
+          cursor: pointer;
+          font-size: 30px;
+          width: 100px;
+          height: 100px;
+          border: 1px dashed #797979;
+          display: flex;
+          justify-content: center;
+          align-items: center;
+
+
+        }
+
+        .fileBoxRow_r_img {
+          width: 100px;
+          height: 100px;
+          position: relative;
+
+          .clearCover {
+            cursor: pointer;
+            z-index: 10;
+            position: absolute;
+            width: 50px;
+            height: 50px;
+            top: 50%;
+            transform: translateY(-50%);
+            right: -50px;
+            display: flex;
+            justify-content: center;
+            align-items: center;
+            font-size: 24px;
+          }
+        }
+
+        .fileBoxRow_r_tit {
+          height: 46px;
+          margin-top: 5px;
+          font-size: 14px;
+          color: rgb(126, 124, 124);
+
+
+        }
+      }
+
+      .noUpThumb {
+        position: relative;
+        overflow: hidden;
+        opacity: 0;
+        transition: top .2s;
+        color: #ff4d4f;
+        top: -10px;
+      }
+
+      .noUpThumb2 {
+        margin-top: -10px;
+        position: relative;
+        padding-left: 100px;
+        margin-bottom: 12px;
+      }
+
+      .noUpThumbAc {
+        top:0;
+        opacity: 1;
+      }
+    }
+  }
+}

+ 737 - 0
houtai/src/pages/B2Goods/GoodsAdd/index.tsx

@@ -0,0 +1,737 @@
+import { RootState } from "@/store";
+import { Button, Checkbox, Form, Input, Popconfirm, Select } from "antd";
+import React, {
+  useCallback,
+  useEffect,
+  useMemo,
+  useRef,
+  useState,
+} from "react";
+import { useDispatch, useSelector } from "react-redux";
+import TextArea from "antd/es/input/TextArea";
+import styles from "./index.module.scss";
+import { MessageFu } from "@/utils/message";
+import ImageLazy from "@/components/ImageLazy";
+import classNames from "classnames";
+import {
+  PlusOutlined,
+  CloseCircleOutlined,
+  UploadOutlined,
+  CloseOutlined,
+  PlayCircleOutlined,
+} from "@ant-design/icons";
+import { goodsUploadAPI } from "@/store/action/B2Goods";
+import { baseURL } from "@/utils/http";
+
+type Props = {
+  id: number;
+  closeMoalFu: () => void;
+  upListFu: () => void;
+};
+
+// 上传附件的进度条
+const UpAsyncLodingDom: any = document.querySelector("#UpAsyncLoding");
+const progressDom: any = document.querySelector("#progress");
+
+function GoodsAdd({ id, closeMoalFu, upListFu }: Props) {
+  const dispatch = useDispatch();
+
+  // 表单的ref
+  const FormBoxRef = useRef<any>({});
+
+  // 文件的dirCode码
+  const [dirCode, setDirCode] = useState("");
+
+  const getInfoInAPIFu = useCallback(async (id: number) => {
+    // const res = await getUserInfoByIdAPI(id);
+    // FormBoxRef.current.setFieldsValue(res.data);
+    console.log("是编辑,在这里发请求拿数据");
+    // setDirCode(data.dirCode!);
+  }, []);
+
+  useEffect(() => {
+    if (id > 0) getInfoInAPIFu(id);
+    else {
+      setDirCode(Date.now() + "");
+      FormBoxRef.current.setFieldsValue({ topic: 3, display: 1 ,aaaaa:0});
+    }
+  }, [getInfoInAPIFu, id]);
+
+  // 从仓库获取下拉列表数据
+  const dictList = useSelector((state: RootState) => state.loginStore.dictList);
+
+  // 上传封面图的ref
+  const [coverCheck, setCoverCheck] = useState(false);
+  const [cover, setCover] = useState("");
+  const myInput = useRef<HTMLInputElement>(null);
+
+  // 上传封面图
+  const handeUpPhoto = useCallback(
+    async (e: React.ChangeEvent<HTMLInputElement>) => {
+      if (e.target.files) {
+        // 拿到files信息
+        const filesInfo = e.target.files[0];
+        // 校验格式
+        const type = ["image/jpeg", "image/png"];
+        if (!type.includes(filesInfo.type)) {
+          e.target.value = "";
+          return MessageFu.warning("只支持jpg、png格式!");
+        }
+        // 校验大小
+        if (filesInfo.size > 20 * 1024 * 1024) {
+          e.target.value = "";
+          return MessageFu.warning("最大支持20M!");
+        }
+        // 创建FormData对象
+        const fd = new FormData();
+        // 把files添加进FormData对象(‘photo’为后端需要的字段)
+        fd.append("type", "thumb");
+        fd.append("dirCode", dirCode);
+        fd.append("file", filesInfo);
+
+        e.target.value = "";
+
+        const res: any = await goodsUploadAPI(fd);
+        if (res.code === 0) {
+          MessageFu.success("上传成功!");
+          setCover(res.data.filePath);
+        }
+        UpAsyncLodingDom.style.opacity = 0;
+        progressDom.style.width = "0%";
+      }
+    },
+    [dirCode]
+  );
+
+  // 选中附件类型
+  const [typeCheck, setTypeCheck] = useState<any>([]);
+  const [typeOk, setTypeOk] = useState(false);
+
+  const typeCheckArr = useMemo(() => {
+    return [
+      { label: "模型", value: "model" },
+      { label: "图片", value: "img" },
+      { label: "音频", value: "audio" },
+      { label: "视频", value: "video" },
+    ];
+  }, []);
+
+  type FileListType = {
+    fileName?: string;
+    filePath?: string;
+    id?: number;
+  };
+
+  // 上传附件的信息
+  const [fileList, setFileList] = useState({
+    model: {} as FileListType,
+    img: [] as FileListType[],
+    audio: {} as FileListType,
+    video: {} as FileListType,
+  });
+
+  // 附件信息的校验
+
+  const fileCheckFu = useMemo(() => {
+    let flag = false;
+    if (typeCheck.length === 0) flag = true;
+    if (typeCheck.includes("model") && !fileList.model.id) flag = true;
+    if (typeCheck.includes("img") && fileList.img.length === 0) flag = true;
+    if (typeCheck.includes("audio") && !fileList.audio.id) flag = true;
+    if (typeCheck.includes("video") && !fileList.video.id) flag = true;
+    return flag;
+  }, [fileList, typeCheck]);
+
+  // 点击上传附件按钮
+  const myInput2 = useRef<HTMLInputElement>(null);
+
+  const [fileOneType, setFileOneType] = useState("");
+
+  useEffect(() => {
+    if (fileOneType) myInput2.current?.click();
+  }, [fileOneType]);
+
+  const upFileFu = useCallback((type: string) => {
+    setFileOneType("");
+    window.setTimeout(() => {
+      setFileOneType(type);
+    }, 100);
+  }, []);
+
+  // 上传附件的处理函数
+  const handeUpPhoto2 = useCallback(
+    (e: React.ChangeEvent<HTMLInputElement>) => {
+      if (e.target.files) {
+        // 拿到files信息
+        const filesInfo = e.target.files[0];
+
+        let anType = ["image/jpeg", "image/png", "image/gif"];
+        let anTit1 = "只支持png、jpg、gif和jpeg格式!";
+        let anTit2 = "最大支持20M!";
+        let anSize = 20 * 1024 * 1024;
+
+        if (fileOneType === "audio") {
+          anType = ["audio/mpeg"];
+          anTit1 = "只支持mp3格式!";
+          anTit2 = "最大支持10M!";
+          anSize = 10 * 1024 * 1024;
+        } else if (fileOneType === "video") {
+          anType = ["video/mp4"];
+          anTit1 = "只支持mp4格式!";
+          anTit2 = "最大支持500M!";
+          anSize = 500 * 1024 * 1024;
+        } else if (fileOneType === "model") {
+          anType = [""];
+          anTit1 = "只支持4dage格式!";
+          anTit2 = "最大支持500M!";
+          anSize = 500 * 1024 * 1024;
+        }
+
+        // 校验格式
+        if (fileOneType !== "model") {
+          if (!anType.includes(filesInfo.type)) {
+            e.target.value = "";
+            return MessageFu.warning(anTit1);
+          }
+        } else {
+          if (!filesInfo.name.includes(".4dage")) {
+            e.target.value = "";
+            return MessageFu.warning(anTit1);
+          }
+        }
+
+        // 校验大小
+        if (filesInfo.size > anSize) {
+          e.target.value = "";
+          return MessageFu.warning(anTit2);
+        }
+        // 创建FormData对象
+        const fd = new FormData();
+        // 把files添加进FormData对象(‘photo’为后端需要的字段)
+        fd.append("type", fileOneType);
+        fd.append("file", filesInfo);
+
+        e.target.value = "";
+
+        // const res: any = await goodsUploadAPI(fd);
+        // if (res.code === 0) {
+        // MessageFu.success("上传成功!");
+        // if (fileOneType === "img")
+        //   setFileList({ ...fileList, img: [res.data, ...fileList.img] });
+        // else setFileList({ ...fileList, [fileOneType]: res.data });
+
+        // }
+        UpAsyncLodingDom.style.opacity = 0;
+        progressDom.style.width = "0%";
+      }
+    },
+    [fileOneType]
+  );
+
+  // 附件图片的拖动
+  const [dragImg, setDragImg] = useState<any>(null);
+
+  const handleDragOver = useCallback(
+    (e: React.DragEvent<HTMLDivElement>, item: FileListType) => {
+      e.dataTransfer.dropEffect = "move";
+    },
+    []
+  );
+
+  const handleDragEnter = useCallback(
+    (e: React.DragEvent<HTMLDivElement>, item: FileListType) => {
+      e.dataTransfer.effectAllowed = "move";
+      if (item === dragImg) return;
+      const newItems = [...fileList.img]; //拷贝一份数据进行交换操作。
+      const src = newItems.indexOf(dragImg); //获取数组下标
+      const dst = newItems.indexOf(item);
+      newItems.splice(dst, 0, ...newItems.splice(src, 1)); //交换位置
+      setFileList({ ...fileList, img: newItems });
+    },
+    [dragImg, fileList]
+  );
+
+  // 删除某一张图片
+  const delImgListFu = useCallback(
+    (id: number) => {
+      const newItems = fileList.img.filter((v) => v.id !== id);
+      setFileList({ ...fileList, img: newItems });
+    },
+    [fileList]
+  );
+
+  // 没有通过校验
+  const onFinishFailed = useCallback(() => {
+    setCoverCheck(true);
+    setTypeOk(true);
+    return MessageFu.warning("有表单不符号规则!");
+  }, []);
+
+  // 通过校验点击确定
+  const onFinish = useCallback(() => {
+    console.log("通过校验,点击确定");
+    setCoverCheck(true);
+    setTypeOk(true);
+    if (typeCheck.length === 0) return MessageFu.warning("有表单不符号规则!");;
+    if (cover === "") return MessageFu.warning("有表单不符号规则!");;
+  }, [cover, typeCheck.length]);
+
+  return (
+    <div className={styles.GoodsAdd}>
+      <div className="main">
+        <Form
+          ref={FormBoxRef}
+          name="basic"
+          labelCol={{ span: 3 }}
+          onFinish={onFinish}
+          onFinishFailed={onFinishFailed}
+          autoComplete="off"
+        >
+          <Form.Item
+            label="名称"
+            name="name"
+            rules={[{ required: true, message: "请输名称!" }]}
+            getValueFromEvent={(e) => e.target.value.replace(/\s+/g, "")}
+          >
+            <Input maxLength={25} showCount placeholder="请输入内容" />
+          </Form.Item>
+
+          <Form.Item
+            label="登记编号"
+            name="num"
+            getValueFromEvent={(e) => e.target.value.replace(/\s+/g, "")}
+          >
+            <Input maxLength={25} showCount placeholder="请输入内容" />
+          </Form.Item>
+
+          <Form.Item
+            label="类别"
+            name="dictTexture"
+            rules={[{ required: true, message: "请选择类别!" }]}
+          >
+            <Select
+              placeholder="请选择"
+              style={{ width: 400 }}
+              options={dictList["texture"].slice(1)}
+            />
+          </Form.Item>
+
+          <Form.Item
+            label="年代"
+            name="dictAge"
+            rules={[{ required: true, message: "请选择年代!" }]}
+          >
+            <Select
+              placeholder="请选择"
+              style={{ width: 400 }}
+              options={dictList["age"].slice(1)}
+            />
+          </Form.Item>
+
+          <Form.Item
+            label="级别"
+            name="dictLevel"
+            rules={[{ required: true, message: "请选择级别!" }]}
+          >
+            <Select
+              placeholder="请选择"
+              style={{ width: 400 }}
+              options={dictList["level"].slice(1)}
+            />
+          </Form.Item>
+
+          <Form.Item
+            label="来源"
+            name="dictSource"
+            rules={[{ required: true, message: "请选择来源!" }]}
+          >
+            <Select
+              placeholder="请选择"
+              style={{ width: 400 }}
+              options={dictList["source"].slice(1)}
+            />
+          </Form.Item>
+
+          <Form.Item
+            label="万物墙主题"
+            name="topic"
+            rules={[{ required: true, message: "请选择万物墙主题!" }]}
+          >
+            <Select
+              placeholder="请选择"
+              style={{ width: 400 }}
+              options={[
+                { value: 1, label: "战争" },
+                { value: 2, label: "生活" },
+                { value: 3, label: "不展示" },
+              ]}
+            />
+          </Form.Item>
+
+          <Form.Item
+            label="简介"
+            name="description"
+            getValueFromEvent={(e) => e.target.value.trim()}
+          >
+            <TextArea
+              rows={4}
+              placeholder="请输入内容"
+              showCount
+              maxLength={200}
+            />
+          </Form.Item>
+
+          {/* -----上传封面图片 */}
+          <div className="myformBox myformBox0">
+            <input
+              id="upInput"
+              type="file"
+              accept=".png,.jpg,.jpeg"
+              ref={myInput}
+              onChange={(e) => handeUpPhoto(e)}
+            />
+            <input
+              id="upInput2"
+              type="file"
+              accept={
+                fileOneType === "img"
+                  ? ".gif,.png,.jpg,.jpeg"
+                  : fileOneType === "audio"
+                  ? ".mp3"
+                  : fileOneType === "model"
+                  ? ".4dage"
+                  : ".mp4"
+              }
+              ref={myInput2}
+              onChange={(e) => handeUpPhoto2(e)}
+            />
+            <div className="label">
+              <span>*</span> 封面图:
+            </div>
+            <div className="fileBoxRow_r">
+              <div
+                hidden={cover !== ""}
+                className="fileBoxRow_up"
+                onClick={() => myInput.current?.click()}
+              >
+                <PlusOutlined />
+              </div>
+              <div className="fileBoxRow_r_img" hidden={cover === ""}>
+                {cover ? (
+                  <ImageLazy width={100} height={100} src={cover} />
+                ) : null}
+
+                <Popconfirm
+                  title="删除后无法恢复,是否删除?"
+                  okText="删除"
+                  cancelText="取消"
+                  onConfirm={() => setCover("")}
+                >
+                  <div className="clearCover">
+                    <CloseCircleOutlined />
+                  </div>
+                </Popconfirm>
+              </div>
+              <div className="fileBoxRow_r_tit">
+                支持png、jpg和jpeg的图片格式;最大支持20M。
+                <br />
+                <div
+                  className={classNames(
+                    "noUpThumb",
+                    !cover && coverCheck ? "noUpThumbAc" : ""
+                  )}
+                >
+                  请上传封面图!
+                </div>
+              </div>
+            </div>
+          </div>
+
+          {/* 选中文件类型和上传附件 */}
+          <div className="myformBox">
+            <div className="label">
+              <span>*</span> 文件类型:
+            </div>
+            <div className="myformBoxR">
+              <Checkbox.Group
+                options={typeCheckArr}
+                value={typeCheck}
+                onChange={(e) => setTypeCheck(e)}
+                // onChange={(e) => console.log(e)}
+              />
+            </div>
+          </div>
+
+          {/* -----------模型上传 */}
+          <div
+            className="myformBox myformBox2"
+            hidden={!typeCheck.includes("model")}
+          >
+            <div className="label">
+              <span>*</span> 模型:
+            </div>
+            {fileList.model.id ? (
+              <div className="fileInfo">
+                <a
+                  href={baseURL + fileList.model.filePath}
+                  download
+                  target="_blank"
+                  className="upSuccTxt"
+                  rel="noreferrer"
+                >
+                  {fileList.model.fileName}
+                </a>
+
+                <Popconfirm
+                  title="删除后无法恢复,是否删除?"
+                  okText="删除"
+                  cancelText="取消"
+                  onConfirm={() => setFileList({ ...fileList, model: {} })}
+                >
+                  <div className="clearCover">
+                    <CloseCircleOutlined />
+                  </div>
+                </Popconfirm>
+              </div>
+            ) : (
+              <>
+                <Button
+                  onClick={() => upFileFu("model")}
+                  icon={<UploadOutlined />}
+                >
+                  上传
+                </Button>
+
+                <div className="fileTit">
+                  仅支持4dage格式的模型文件,大小不能超过500M。
+                </div>
+              </>
+            )}
+          </div>
+
+          {/* -----------图片上传 */}
+          <div
+            className="myformBox myformBox3"
+            hidden={!typeCheck.includes("img")}
+          >
+            <div className="label">
+              <span>*</span> 图片:
+            </div>
+            <>
+              <div className="fileBoxRow_r">
+                <div className="upImgBox">
+                  <div
+                    hidden={!!fileList.img.length && fileList.img.length >= 9}
+                    className="fileBoxRow_up"
+                    onClick={() => upFileFu("img")}
+                  >
+                    <PlusOutlined />
+                  </div>
+                  {fileList.img.map((v) => (
+                    <div
+                      className="fileBoxRow_r_img"
+                      key={v.id}
+                      draggable="true"
+                      onDragStart={() => setDragImg(v)}
+                      onDragOver={(e) => handleDragOver(e, v)}
+                      onDragEnter={(e) => handleDragEnter(e, v)}
+                      onDragEnd={() => setDragImg(null)}
+                    >
+                      {v.filePath ? (
+                        <ImageLazy
+                          noLook={dragImg ? true : false}
+                          width={100}
+                          height={100}
+                          src={v.filePath}
+                        />
+                      ) : null}
+
+                      <Popconfirm
+                        title="删除后无法恢复,是否删除?"
+                        okText="删除"
+                        cancelText="取消"
+                        onConfirm={() => delImgListFu(v.id!)}
+                      >
+                        <div className="clearCover">
+                          <CloseOutlined />
+                        </div>
+                      </Popconfirm>
+                    </div>
+                  ))}
+                </div>
+                <div className="fileTit">
+                  {fileList.img.length && fileList.img.length >= 2 ? (
+                    <>
+                      按住鼠标可拖动图片调整顺序。
+                      <br />
+                    </>
+                  ) : null}
+                  支持png、jpg、gif和jpeg的图片格式;最大支持20M;最多支持9张。
+                </div>
+              </div>
+            </>
+          </div>
+
+          {/* -----------音频上传 */}
+          <div
+            className="myformBox myformBox2"
+            hidden={!typeCheck.includes("audio")}
+          >
+            <div className="label">
+              <span>*</span> 音频:
+            </div>
+            {fileList.audio.id ? (
+              <div className="fileInfo">
+                <a
+                  href={baseURL + fileList.audio.filePath}
+                  download
+                  target="_blank"
+                  className="upSuccTxt"
+                  rel="noreferrer"
+                >
+                  {fileList.audio.fileName}
+                </a>
+
+                <Popconfirm
+                  title="删除后无法恢复,是否删除?"
+                  okText="删除"
+                  cancelText="取消"
+                  onConfirm={() => setFileList({ ...fileList, audio: {} })}
+                >
+                  <div className="clearCover">
+                    <CloseCircleOutlined />
+                  </div>
+                </Popconfirm>
+              </div>
+            ) : (
+              <>
+                <Button
+                  onClick={() => upFileFu("audio")}
+                  icon={<UploadOutlined />}
+                >
+                  上传
+                </Button>
+
+                <div className="fileTit">
+                  仅支持MP3格式的音频文件,大小不得超过10MB。
+                </div>
+              </>
+            )}
+          </div>
+
+          {/* -----------视频上传 */}
+          <div
+            className="myformBox myformBox2"
+            hidden={!typeCheck.includes("video")}
+          >
+            <div className="label">
+              <span>*</span> 视频:
+            </div>
+            {fileList.video.id ? (
+              <div className="fileInfo">
+                <div className="upSuccTxt">{fileList.video.filePath}</div>
+                <div
+                  className="clearCover"
+                  hidden={!fileList.video.filePath}
+                  onClick={() =>
+                    dispatch({
+                      type: "login/lookVideo",
+                      payload: fileList.video.filePath,
+                    })
+                  }
+                >
+                  <PlayCircleOutlined />
+                </div>
+
+                <Popconfirm
+                  title="删除后无法恢复,是否删除?"
+                  okText="删除"
+                  cancelText="取消"
+                  onConfirm={() => setFileList({ ...fileList, video: {} })}
+                >
+                  <div className="clearCover">
+                    <CloseCircleOutlined />
+                  </div>
+                </Popconfirm>
+              </div>
+            ) : (
+              <>
+                <Button
+                  onClick={() => upFileFu("video")}
+                  icon={<UploadOutlined />}
+                >
+                  上传
+                </Button>
+
+                <div className="fileTit">
+                  仅支持MP4格式的视频文件,大小不得超过500MB。
+                </div>
+              </>
+            )}
+          </div>
+
+          <div
+            className={classNames(
+              "noUpThumb noUpThumb2",
+              fileCheckFu && typeOk ? "noUpThumbAc" : ""
+            )}
+          >
+            请至少选择一个文件类型,并上传对应附件!
+          </div>
+
+
+          <Form.Item
+            label="展示状态"
+            name="display"
+            rules={[{ required: true, message: "请选择展示状态!" }]}
+          >
+            <Select
+              placeholder="请选择"
+              style={{ width: 400 }}
+              options={[
+                { value: 1, label: "展示" },
+                { value: 0, label: "不展示" },
+              ]}
+            />
+          </Form.Item>
+
+          <Form.Item
+            label="弹幕留言"
+            name="aaaaa"
+            rules={[{ required: true, message: "请选择弹幕留言!" }]}
+          >
+            <Select
+              placeholder="请选择"
+              style={{ width: 400 }}
+              options={[
+                { value: 1, label: "开启" },
+                { value: 0, label: "关闭" },
+              ]}
+            />
+          </Form.Item>
+
+          {/* 确定和取消按钮 */}
+          <br />
+          <Form.Item wrapperCol={{ offset: 9, span: 16 }}>
+            <Button type="primary" htmlType="submit">
+              提交
+            </Button>
+            &emsp;
+            <Popconfirm
+              title="放弃编辑后,信息将不会保存!"
+              okText="放弃"
+              cancelText="取消"
+              onConfirm={closeMoalFu}
+            >
+              <Button>取消</Button>
+            </Popconfirm>
+          </Form.Item>
+        </Form>
+      </div>
+    </div>
+  );
+}
+
+const MemoGoodsAdd = React.memo(GoodsAdd);
+
+export default MemoGoodsAdd;

+ 11 - 0
houtai/src/pages/B2Goods/GoodsBarrage/index.css

@@ -0,0 +1,11 @@
+.GoodsBarrage .ant-modal-close {
+  display: none;
+}
+.GoodsBarrage .main {
+  border-top: 1px solid #999999;
+  padding-top: 15px;
+  width: 100%;
+}
+.GoodsBarrage .button {
+  text-align: center;
+}

+ 14 - 0
houtai/src/pages/B2Goods/GoodsBarrage/index.less

@@ -0,0 +1,14 @@
+.GoodsBarrage {
+  .ant-modal-close {
+    display: none;
+  }
+
+  .main {
+    border-top: 1px solid #999999;
+    padding-top: 15px;
+    width: 100%;
+  }
+  .button{
+    text-align: center;
+  }
+}

+ 50 - 0
houtai/src/pages/B2Goods/GoodsBarrage/index.tsx

@@ -0,0 +1,50 @@
+import { Button, Modal, Popconfirm, Radio } from "antd";
+import React, { useState } from "react";
+import "./index.css";
+
+type Props = {
+  closeMoalFu: () => void;
+};
+
+function GoodsBarrage({ closeMoalFu }: Props) {
+  const [value, setValue] = useState(1);
+
+  return (
+    <Modal
+      wrapClassName="GoodsBarrage"
+      destroyOnClose
+      open={true}
+      title="弹幕开关批量设置"
+      footer={
+        [] // 设置footer为空,去掉 取消 确定默认按钮
+      }
+    >
+      <div className="main">
+        <div className="row">
+          <span>当前状态:</span>
+          <Radio.Group onChange={(e) => setValue(e.target.value)} value={value}>
+            <Radio value={1}>开启</Radio>
+            <Radio value={2}>关闭</Radio>
+          </Radio.Group>
+        </div>
+        <br />
+        <div className="button">
+          <Button type="primary">提交</Button>
+          &emsp;
+          <Popconfirm
+            title="放弃编辑后,信息将不会保存!"
+            okText="放弃"
+            cancelText="取消"
+            onConfirm={closeMoalFu}
+          >
+            <Button>取消</Button>
+          </Popconfirm>
+        </div>
+      </div>
+    </Modal>
+  );
+}
+
+const MemoGoodsBarrage = React.memo(GoodsBarrage);
+
+export default MemoGoodsBarrage;

+ 30 - 17
houtai/src/pages/B2Goods/index.tsx

@@ -27,6 +27,8 @@ import { useDispatch, useSelector } from "react-redux";
 import styles from "./index.module.scss";
 import ExportJsonExcel from "js-export-excel";
 import ImageLazy from "@/components/ImageLazy";
+import GoodsBarrage from "./GoodsBarrage";
+import GoodsAdd from "./GoodsAdd";
 
 const { RangePicker } = DatePicker;
 function Goods() {
@@ -239,11 +241,6 @@ function Goods() {
     [getList]
   );
 
-  // 点击编辑
-  const openEditPageFu = useCallback((id: number) => {
-    console.log("点击了编辑", id);
-  }, []);
-
   // 点击删除
   const delTableFu = useCallback(
     async (id: number) => {
@@ -270,7 +267,7 @@ function Goods() {
       },
       {
         title: "登记编号",
-        render:(item:any)=>(item.num?item.num:'(空)')
+        render: (item: any) => (item.num ? item.num : "(空)"),
       },
       {
         title: "类别",
@@ -338,11 +335,7 @@ function Goods() {
         title: "操作",
         render: (item: any) => (
           <>
-            <Button
-              size="small"
-              type="text"
-              onClick={() => openEditPageFu(item.id!)}
-            >
+            <Button size="small" type="text" onClick={() => setAddId(item.id!)}>
               编辑
             </Button>
             <Popconfirm
@@ -359,13 +352,19 @@ function Goods() {
         ),
       },
     ];
-  }, [delTableFu, isEnabledClickFu, openEditPageFu]);
+  }, [delTableFu, isEnabledClickFu]);
+
+  // 弹幕设置的弹窗
+  const [barrage, setBarrage] = useState(false);
+
+  // 新增或者编辑的弹窗
+  const [addId, setAddId] = useState(-1);
 
   return (
     <div className={styles.Goods}>
-      <div className="pageTitlt">馆藏管理</div>
+      <div className="pageTitlt">{addId===0?'馆藏管理':addId>0?'编辑馆藏':'新增馆藏'}</div>
       {/* 搜索信息 */}
-      <div className="searchBox">
+      <div className="searchBox" hidden={addId!==0}>
         <div className="searchRow">
           <span>名称:</span>
           <Input
@@ -504,12 +503,14 @@ function Goods() {
         <div className="searchRow">
           <Button onClick={resetSelectFu}>重置</Button>&emsp;
           <Button onClick={deriveFu}>批量导出</Button>&emsp;
-          <Button>弹幕设置</Button>&emsp;
-          <Button type="primary">新增</Button>
+          <Button onClick={() => setBarrage(true)}>弹幕设置</Button>&emsp;
+          <Button type="primary" onClick={() => setAddId(-1)}>
+            新增
+          </Button>
         </div>
       </div>
       {/* 表格主体 */}
-      <div className="tableBox">
+      <div className="tableBox" hidden={addId!==0}>
         <Table
           scroll={{ y: 560 }}
           dataSource={tableInfo.list}
@@ -526,6 +527,18 @@ function Goods() {
           }}
         />
       </div>
+
+      {/* 弹幕设置 */}
+      {barrage ? <GoodsBarrage closeMoalFu={() => setBarrage(false)} /> : null}
+
+      {/* 新增和编辑的弹窗 */}
+      {addId !== 0 ? (
+        <GoodsAdd
+          id={addId}
+          closeMoalFu={() => setAddId(0)}
+          upListFu={resetSelectFu}
+        />
+      ) : null}
     </div>
   );
 }

+ 79 - 74
houtai/src/pages/Login/index.module.scss

@@ -20,112 +20,117 @@
       padding-top: 60px;
       text-align: center;
       backdrop-filter: blur(10px);
-      .logo{
+
+      .logo {
         margin: 0 auto;
         width: 375px;
         height: 233px;
         background-image: url('../../assets/img/logo.png');
         background-size: 100% 100%;
       }
-       
 
-        .inputBox {
-          width: 100%;
 
-          input::-webkit-input-placeholder {
-            /* WebKit browsers */
-            color: rgba(255,255,255,.5);
-          }
+      .inputBox {
+        width: 100%;
 
-          input:-moz-placeholder {
-            /* Mozilla Firefox 4 to 18 */
-            color: rgba(255,255,255,.5);
-          }
+        input::-webkit-input-placeholder {
+          /* WebKit browsers */
+          color: rgba(255, 255, 255, .5);
+        }
 
-          input::-moz-placeholder {
-            /* Mozilla Firefox 19+ */
-            color: rgba(255,255,255,.5);
-          }
+        input:-moz-placeholder {
+          /* Mozilla Firefox 4 to 18 */
+          color: rgba(255, 255, 255, .5);
+        }
 
-          input:-ms-input-placeholder {
-            /* Internet Explorer 10+ */
-            color: rgba(255,255,255,.5);
-          }
+        input::-moz-placeholder {
+          /* Mozilla Firefox 19+ */
+          color: rgba(255, 255, 255, .5);
+        }
 
+        input:-ms-input-placeholder {
+          /* Internet Explorer 10+ */
+          color: rgba(255, 255, 255, .5);
+        }
 
-          .inputBoxRow {
-            width: 370px;
-            margin: 50px auto;
 
-            .ant-input-suffix .ant-input-password-icon {
-              color: var(--themeColor);
-              font-size: 22px;
-            }
+        .inputBoxRow {
+          width: 370px;
+          margin: 50px auto;
+
+          .ant-input-suffix .ant-input-password-icon {
+            color: var(--themeColor);
+            font-size: 22px;
           }
+        }
 
-          .ant-input-prefix {
-            margin-right: 10px;
+        .ant-input-prefix {
+          margin-right: 10px;
 
-            .anticon {
-              padding-right: 10px;
-              width: 36px;
-              height: 36px;
+          .anticon {
+            padding-right: 10px;
+            width: 36px;
+            height: 36px;
 
-              svg {
-                width: 100%;
-                height: 100%;
-              }
+            svg {
+              width: 100%;
+              height: 100%;
             }
           }
+        }
 
-          .ant-input {
-            font-size: 18px;
-            width: 45%;
-            height: 60px;
-            line-height: 60px;
-            background-clip: content-box;
-          }
+        .ant-input {
+          font-size: 18px;
+          width: 45%;
+          height: 60px;
+          line-height: 60px;
+          background-clip: content-box;
+        }
 
-          input:-webkit-autofill {
-            background-image: none;
-            -webkit-box-shadow: 0 0 0px 1000px transparent inset !important; //填充阴影,可以用来遮住背景色
-            background-color: transparent;
-            transition: background-color 50000s ease-in-out 0s; //背景色透明  生效时长  过渡效果  启用时延迟的时间
+        input:-webkit-autofill {
+          font-size: 18px !important;
+          -webkit-text-fill-color: #fff !important;
+          background-image: none;
+          -webkit-box-shadow: 0 0 0px 1000px transparent inset !important; //填充阴影,可以用来遮住背景色
+          background-color: transparent;
+          transition: background-color 50000s ease-in-out 0s; //背景色透明  生效时长  过渡效果  启用时延迟的时间
 
-          }
+        }
 
-          .ant-input-affix-wrapper {
+        .ant-input-affix-wrapper {
+          background-color: transparent;
+          padding: 0 11px;
+          width: 100%;
+          height: 60px;
+          border: none;
+          border-bottom: 1px solid var(--themeColor);
+          border-radius: 0;
+          color: var(--themeColor);
+
+          .ant-input {
             background-color: transparent;
-            padding: 0 11px;
             width: 100%;
             height: 60px;
-            border: none;
-            border-bottom: 1px solid var(--themeColor);
-            border-radius: 0;
-            color: var(--themeColor);
-            .ant-input {
-              background-color: transparent;
-              width: 100%;
-              height: 60px;
-              color: #fff;
-            }
-          }
-          .ant-input-affix-wrapper-focused{
-            box-shadow:none
+            color: #fff;
           }
         }
 
-        .loginBtn {
+        .ant-input-affix-wrapper-focused {
+          box-shadow: none
+        }
+      }
+
+      .loginBtn {
 
-          .ant-btn {
-            color: black;
-            background-color: #f0d99c;
-            border-radius: 25px;
-            font-size: 24px;
-            width: 375px;
-            height: 50px;
-          }
+        .ant-btn {
+          color: black;
+          background-color: #f0d99c;
+          border-radius: 25px;
+          font-size: 24px;
+          width: 375px;
+          height: 50px;
         }
+      }
 
     }
   }

+ 20 - 0
houtai/src/store/action/B2Goods.ts

@@ -34,4 +34,24 @@ export const goodsDisplayAPI = (id: number, display: number) => {
  */
 export const goodsRemoveAPI = (id: number) => {
   return http.get(`cms/goods/remove/${id}`);
+};
+
+// 上传附件的进度条
+const UpAsyncLodingDom: any = document.querySelector("#UpAsyncLoding");
+const progressDom: any = document.querySelector("#progress");
+
+/**
+ * 上传封面图和附件
+ */
+export const goodsUploadAPI = (data: any) => {
+  UpAsyncLodingDom.style.opacity = 1;
+
+  return http.post("cms/goods/upload", data, {
+    timeout:50000,
+    // 显示进度条
+    onUploadProgress: (e: any) => {
+      const complete = (e.loaded / e.total) * 100 || 0;
+      progressDom.style.width = complete + "%";
+    },
+  });
 };