shaogen1995 hace 2 años
padre
commit
697525fea3

+ 14 - 0
src/assets/styles/base.css

@@ -69,6 +69,20 @@ textarea {
   /* antd图片预览组件 */
   /* antd表格居中 */
 }
+#root .iconHoverTit {
+  display: flex;
+  align-items: center;
+}
+#root .iconHoverTit .iconHoverTitTxt {
+  background-color: var(--themeColor);
+  color: #fff;
+  width: 16px;
+  height: 16px;
+  line-height: 16px;
+  text-align: center;
+  font-size: 12px;
+  border-radius: 50%;
+}
 #root .ant-btn-text {
   color: var(--themeColor);
 }

+ 16 - 0
src/assets/styles/base.less

@@ -82,6 +82,22 @@ textarea {
   overflow: auto;
   overflow-y: overlay;
 
+  // ?的提示
+  .iconHoverTit{
+    display: flex;
+    align-items: center;
+    .iconHoverTitTxt{
+      background-color: var(--themeColor);
+      color: #fff;
+      width: 16px;
+      height: 16px;
+      line-height: 16px;
+      text-align: center;
+      font-size: 12px;
+      border-radius: 50%;
+    }
+  }
+
   // a {
   //   color: var(--themeColor);
   // }

+ 6 - 0
src/components/Z1upImgs/index.module.scss

@@ -102,5 +102,11 @@
         opacity: 1;
       }
     }
+
+    .lookNone{
+      position: relative;
+      top: -10px;
+      left: 10px;
+    }
   }
 }

+ 5 - 1
src/components/Z1upImgs/index.tsx

@@ -185,7 +185,7 @@ function Z1upImgs(
               />
               <a
                 href={baseURL + v.filePath}
-                download
+                download={v.fileName}
                 target="_blank"
                 rel="noreferrer"
               >
@@ -215,6 +215,10 @@ function Z1upImgs(
           请上传图片!
         </div>
       </div>
+
+      {isLook && fileList.length <= 0 ? (
+        <div className="lookNone">(空)</div>
+      ) : null}
     </div>
   );
 }

+ 6 - 0
src/components/Z2upVideos/index.module.scss

@@ -88,5 +88,11 @@
         opacity: 1;
       }
     }
+
+    .lookNone {
+      position: relative;
+      top: -6px;
+      left: 10px;
+    }
   }
 }

+ 5 - 2
src/components/Z2upVideos/index.tsx

@@ -125,7 +125,7 @@ function Z2upVideos(
         onChange={(e) => handeUpPhoto(e)}
       />
       <div className="Z2Btn">
-        {fileList.length < max ? (
+        {fileList.length < max && !isLook ? (
           <Button
             onClick={() => myInput.current?.click()}
             icon={<UploadOutlined />}
@@ -170,7 +170,7 @@ function Z2upVideos(
                 />
                 <a
                   href={baseURL + v.filePath}
-                  download
+                  download={v.fileName}
                   target="_blank"
                   rel="noreferrer"
                 >
@@ -199,6 +199,9 @@ function Z2upVideos(
           </div>
         </div>
       </div>
+      {isLook && fileList.length <= 0 ? (
+        <div className="lookNone">(空)</div>
+      ) : null}
     </div>
   );
 }

+ 9 - 1
src/components/Z3upFiles/index.module.scss

@@ -25,11 +25,13 @@
         .Z3files2 {
           display: flex;
           width: 120px;
+          justify-content: flex-end;
 
           &>span {
             cursor: pointer;
           }
-          a{
+
+          a {
             color: black;
           }
         }
@@ -57,5 +59,11 @@
         opacity: 1;
       }
     }
+
+    .lookNone {
+      position: relative;
+      top: 4px;
+      left: 10px;
+    }
   }
 }

+ 5 - 2
src/components/Z3upFiles/index.tsx

@@ -99,7 +99,7 @@ function Z3upFiles(
         onChange={(e) => handeUpPhoto(e)}
       />
       <div className="Z3Btn">
-        {fileList.length < max ? (
+        {fileList.length < max && !isLook ? (
           <Button
             onClick={() => myInput.current?.click()}
             icon={<UploadOutlined />}
@@ -127,7 +127,7 @@ function Z3upFiles(
                 <a
                   title="下载"
                   href={baseURL + v.filePath}
-                  download
+                  download={v.fileName}
                   target="_blank"
                   rel="noreferrer"
                 >
@@ -160,6 +160,9 @@ function Z3upFiles(
           </div>
         </div>
       </div>
+      {isLook && fileList.length <= 0 ? (
+        <div className="lookNone">(空)</div>
+      ) : null}
     </div>
   );
 }

+ 102 - 4
src/pages/A1Project/A1Add/index.module.scss

@@ -16,7 +16,7 @@
       overflow-y: auto;
       padding: 20px 20px 20px 0px;
 
-      .ant-form-item-label{
+      .ant-form-item-label {
         width: 120px !important;
       }
 
@@ -56,18 +56,25 @@
 
         .e_rowR {
           width: calc(100% - 130px);
+          .lookNoneOne{
+            position: relative;
+            left: 10px;
+            top: 4px;
+          }
 
           .erLinkTop {
-            .ant-btn{
+            .ant-btn {
               width: 82px;
             }
+
             .e_rowRtit {
               font-size: 14px;
               color: rgb(126, 124, 124);
             }
           }
-          .erLinkMain{
-            .erLinkRow{
+
+          .erLinkMain {
+            .erLinkRow {
               margin-top: 15px;
             }
           }
@@ -78,6 +85,97 @@
       }
     }
 
+    // 查看的情况
+    .A1AddMainLook {
+      height: 100%;
+
+      .ant-row {
+        pointer-events: none;
+      }
+
+      .ant-form-item-control-input {
+        pointer-events: none;
+
+        .ant-input-affix-wrapper {
+          border: transparent;
+
+          .ant-input-show-count-suffix {
+            opacity: 0;
+          }
+        }
+
+        .ant-select-selector {
+          border: transparent;
+        }
+
+        .ant-select-arrow {
+          opacity: 0;
+        }
+
+        .ant-input {
+          border: transparent;
+        }
+
+        .ant-input-data-count {
+          opacity: 0;
+        }
+
+      }
+
+      .ant-checkbox-group {
+        pointer-events: none;
+      }
+
+      .myformBox3 .upImgBox .fileImgListBox>div {
+        margin: 0px 20px 15px 0;
+        cursor: default;
+      }
+
+      .closeLook {
+        .ant-form-item-control-input {
+          pointer-events: auto;
+        }
+      }
+
+      textarea {
+        min-height: 40px !important;
+      }
+
+      textarea,
+      input {
+        &::-webkit-input-placeholder {
+          color: black;
+        }
+
+        &:-moz-placeholder {
+          color: black;
+        }
+
+        &::-moz-placeholder {
+          color: black;
+        }
+
+        &:-ms-input-placeholder {
+          color: black;
+        }
+      }
+
+      // 下拉框 placeholder 字体颜色
+      .ant-select-selection-placeholder {
+        color: black;
+      }
+
+      .e_row {
+        margin-bottom: 24px;
+
+        .e_rowRLook {
+          padding-left: 12px;
+        }
+
+      }
+    }
+
+
 
   }
 }

+ 73 - 27
src/pages/A1Project/A1Add/index.tsx

@@ -1,4 +1,4 @@
-import React, { useCallback, useRef, useState } from "react";
+import React, { useCallback, useEffect, useRef, useState } from "react";
 import styles from "./index.module.scss";
 import {
   Button,
@@ -18,6 +18,7 @@ import Z1upImgs from "@/components/Z1upImgs";
 import Z2upVideos from "@/components/Z2upVideos";
 import { MessageFu } from "@/utils/message";
 import Z3upFiles from "@/components/Z3upFiles";
+import classNames from "classnames";
 
 const { RangePicker } = DatePicker;
 
@@ -41,9 +42,18 @@ type LinkType = {
 type Props = {
   pageType: { txt: string; id: number };
   closeFu: () => void;
+  addFu: () => void;
+  editFu: () => void;
 };
 
-function A1Add({ pageType, closeFu }: Props) {
+function A1Add({ pageType, closeFu, addFu, editFu }: Props) {
+
+
+  useEffect(()=>{
+    console.log('进来编辑和新增项目的页面~~~~~~~');
+    
+  },[])
+
   // 表单的ref
   const FormBoxRef = useRef<FormInstance>(null);
 
@@ -115,8 +125,17 @@ function A1Add({ pageType, closeFu }: Props) {
       // 项目成功
       const filesRes = filesRef.current.filesIdRes();
       console.log("获取项目成果文件", filesRes);
+
+      if (pageType.txt === "add") {
+        MessageFu.success("新增成功!");
+        addFu();
+      } else if (pageType.txt === "edit") {
+        MessageFu.success("编辑成功!");
+        editFu();
+      }
+      closeFu();
     },
-    [linkArr]
+    [addFu, closeFu, editFu, linkArr, pageType.txt]
   );
 
   // 项目成功的 ref
@@ -124,7 +143,12 @@ function A1Add({ pageType, closeFu }: Props) {
 
   return (
     <div className={styles.A1Add}>
-      <div className="A1AddMain">
+      <div
+        className={classNames(
+          "A1AddMain",
+          pageType.txt === "look" ? "A1AddMainLook" : ""
+        )}
+      >
         <Form
           scrollToFirstError={true}
           ref={FormBoxRef}
@@ -167,7 +191,7 @@ function A1Add({ pageType, closeFu }: Props) {
               style={{ width: 600 }}
               maxLength={30}
               showCount
-              placeholder="请输入内容"
+              placeholder={pageType.txt === "look" ? "(空)" : "请输入内容"}
             />
           </Form.Item>
 
@@ -175,7 +199,7 @@ function A1Add({ pageType, closeFu }: Props) {
             <Cascader
               style={{ width: 300 }}
               options={mapDataAll}
-              placeholder="请选择省/市"
+              placeholder={pageType.txt === "look" ? "(空)" : "请选择省/市"}
             />
           </Form.Item>
 
@@ -191,28 +215,47 @@ function A1Add({ pageType, closeFu }: Props) {
             />
           </Form.Item>
 
-          <Form.Item label="项目日期" name="ffff">
-            <RangePicker style={{ width: 300 }} />
-          </Form.Item>
+          {pageType.txt === "look" ? (
+            <div className="e_row">
+              <div className="e_rowL">
+                <span> </span>项目日期:
+              </div>
+              <div className="e_rowR e_rowRLook">日期日期日期日期</div>
+            </div>
+          ) : (
+            <Form.Item label="项目日期" name="ffff">
+              <RangePicker style={{ width: 300 }} />
+            </Form.Item>
+          )}
 
           <Form.Item label="项目简介" name="gggg">
             <TextArea
               style={{ width: 600 }}
               autoSize
-              placeholder="请输入内容"
+              placeholder={pageType.txt === "look" ? "(空)" : "请输入内容"}
               showCount
               maxLength={500}
             />
           </Form.Item>
 
-          <Form.Item label="项目金额" name="hhhh">
-            <InputNumber
-              style={{ width: 300 }}
-              addonAfter="¥"
-              maxLength={10}
-              placeholder="请输入数字,最多10位"
-            />
-          </Form.Item>
+          {pageType.txt === "look" ? (
+            <div className="e_row">
+              <div className="e_rowL">
+                <span> </span>项目金额:
+              </div>
+              <div className="e_rowR e_rowRLook">1000000 ¥</div>
+            </div>
+          ) : (
+            <Form.Item label="项目金额" name="hhhh">
+              <InputNumber
+                style={{ width: 300 }}
+                addonAfter="¥"
+                maxLength={10}
+                placeholder="请输入数字,最多10位"
+              />
+            </Form.Item>
+          )}
+
           <div className="e_row">
             <div className="e_rowL">
               <span> </span>项目图片:
@@ -253,12 +296,17 @@ function A1Add({ pageType, closeFu }: Props) {
               <span> </span>项目链接:
             </div>
             <div className="e_rowR">
-              <div className="erLinkTop">
-                <Button onClick={addLinkFu} disabled={linkArr.length >= 10}>
-                  新&emsp;增
-                </Button>
-                <span className="e_rowRtit">&emsp;最多支持10条链接</span>
-              </div>
+              {pageType.txt === "look" && linkArr.length <= 0 ? (
+                <div className="lookNoneOne">(空)</div>
+              ) : (
+                <div className="erLinkTop">
+                  <Button onClick={addLinkFu} disabled={linkArr.length >= 10}>
+                    新&emsp;增
+                  </Button>
+                  <span className="e_rowRtit">&emsp;最多支持10条链接</span>
+                </div>
+              )}
+
               <div className="erLinkMain">
                 {linkArr.map((v) => (
                   <div className="erLinkRow" key={v.id}>
@@ -319,9 +367,7 @@ function A1Add({ pageType, closeFu }: Props) {
 
           {/* 确定和取消按钮 */}
           <div className="A1AddBtn">
-            {pageType.txt === "look" ? (
-              <Button onClick={closeFu}>关 闭</Button>
-            ) : (
+            {pageType.txt === "look" ? null : ( // <Button onClick={closeFu}>关 闭</Button>
               <>
                 <Button type="primary" htmlType="submit">
                   保存

+ 61 - 0
src/pages/A1Project/A1Down/index.module.scss

@@ -0,0 +1,61 @@
+.A1Down {
+  :global {
+    .ant-modal-close {
+      display: none;
+    }
+
+    .ant-modal {
+      width: 800px !important;
+    }
+
+    .A1DownMain {
+      width: 100%;
+
+      &>h3 {
+        margin-top: 10px;
+        margin-bottom: 10px;
+      }
+
+      .A1DownMainC {
+        margin-top: 10px;
+        border-top: 1px solid #999999;
+
+        max-height: 600px;
+        overflow-y: auto;
+
+        display: flex;
+        flex-wrap: wrap;
+
+        .A1DownMainCRow {
+          width: 50%;
+          overflow: hidden;
+
+          .ant-checkbox-wrapper {
+            width: 100%;
+            margin-top: 10px;
+
+            span {
+              display: block;
+
+              &:nth-of-type(2) {
+                width: calc(100% - 20px);
+                overflow: hidden;
+                text-overflow: ellipsis;
+                white-space: nowrap;
+
+              }
+            }
+          }
+        }
+
+      }
+
+      .A1DownBtn {
+        width: 100%;
+        display: flex;
+        justify-content: space-between;
+        margin-top: 30px;
+      }
+    }
+  }
+}

+ 117 - 0
src/pages/A1Project/A1Down/index.tsx

@@ -0,0 +1,117 @@
+import React, { useCallback, useEffect, useState } from "react";
+import styles from "./index.module.scss";
+import { Button, Checkbox, Modal } from "antd";
+
+const defaultCheckedList = [
+  { id: 1, label: "Apple", done: false },
+  { id: 2, label: "Pear", done: false },
+  { id: 3, label: "Orange", done: false },
+];
+
+type Props = {
+  id: number;
+  closeFu: () => void;
+};
+
+function A1Down({ id, closeFu }: Props) {
+  const [checkedList, setCheckedList] = useState(defaultCheckedList);
+
+  // 全选的状态
+  const [indeterminate, setIndeterminate] = useState(false);
+  const [checkAll, setCheckAll] = useState(false);
+
+  const onCheckAllChange = useCallback(
+    (val: boolean) => {
+      const newArr = checkedList.map((v) => ({
+        ...v,
+        done: val,
+      }));
+
+      setCheckedList(newArr);
+      setCheckAll(val);
+    },
+    [checkedList]
+  );
+
+  const onChange = useCallback(
+    (val: boolean, id: number) => {
+      setCheckedList(
+        checkedList.map((v) => ({
+          ...v,
+          done: v.id === id ? val : v.done,
+        }))
+      );
+    },
+    [checkedList]
+  );
+
+  useEffect(() => {
+    const newArr = checkedList.filter((v) => v.done);
+
+    setIndeterminate(!!newArr.length && newArr.length < checkedList.length);
+    setCheckAll(newArr.length === checkedList.length);
+  }, [checkedList]);
+
+  // 点击提交
+  const btnOkFu = useCallback(() => {
+    console.log("-------", checkedList);
+  }, [checkedList]);
+
+  return (
+    <Modal
+      wrapClassName={styles.A1Down}
+      destroyOnClose
+      open={true}
+      title="xxx项目"
+      footer={
+        [] // 设置footer为空,去掉 取消 确定默认按钮
+      }
+    >
+      <div className="A1DownMain">
+        <h3>请选择下载的项目文件类型</h3>
+        <Checkbox
+          indeterminate={indeterminate}
+          onChange={(e) => onCheckAllChange(e.target.checked)}
+          checked={checkAll}
+        >
+          全选
+        </Checkbox>
+
+        <div className="A1DownMainC">
+          {checkedList.map((v) => (
+            <div className="A1DownMainCRow" key={v.id} title={v.label}>
+              <Checkbox
+                onChange={(e) => onChange(e.target.checked, v.id)}
+                checked={v.done}
+              >
+                {v.label}
+              </Checkbox>
+            </div>
+          ))}
+        </div>
+
+        <div className="A1DownBtn">
+          <div className="A1DownBtn1">
+            <Button>保存设置</Button>
+          </div>
+
+          <div className="A1DownBtn2">
+            <Button onClick={closeFu}>取消</Button>
+            &emsp;
+            <Button
+              type="primary"
+              onClick={btnOkFu}
+              disabled={checkedList.length < 1}
+            >
+              提交
+            </Button>
+          </div>
+        </div>
+      </div>
+    </Modal>
+  );
+}
+
+const MemoA1Down = React.memo(A1Down);
+
+export default MemoA1Down;

+ 73 - 0
src/pages/A1Project/A1Look/index.module.scss

@@ -0,0 +1,73 @@
+.A1Look {
+  position: absolute;
+  top: 0;
+  left: 0;
+  z-index: 10;
+  width: 100%;
+  height: 100%;
+  background-color: #fff;
+  border-radius: 10px;
+  padding: 10px 30px 20px;
+
+  :global {
+    .A1LookTitle {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      padding-right: 30px;
+
+      &>h3 {
+        font-size: 24px;
+      }
+    }
+
+    .A1LookTab {
+      position: relative;
+      z-index: 30;
+      margin-top: 10px;
+      border-bottom: 1px solid #ccc;
+      display: flex;
+      padding-bottom: 6px;
+
+      .A1LookTabRow {
+        margin-right: 40px;
+        cursor: pointer;
+        font-size: 16px;
+
+        &:hover {
+          color: var(--themeColor);
+        }
+      }
+
+      .A1LookTabRowAc {
+        pointer-events: none;
+        color: var(--themeColor);
+        position: relative;
+
+        &::before {
+          content: '';
+          position: absolute;
+          bottom: -8px;
+          left: 0;
+          z-index: 10;
+          width: 100%;
+          height: 4px;
+          background-color: var(--themeColor);
+        }
+      }
+    }
+
+    .A1LookMain{
+      position: relative;
+      width: 100%;
+      height: calc(100% - 55px);
+      .A1lrBtn{
+        position: absolute;
+        top: 20px;
+        right: 30px;
+        z-index: 30;
+      }
+    }
+
+  }
+}

+ 98 - 0
src/pages/A1Project/A1Look/index.tsx

@@ -0,0 +1,98 @@
+import React, { useCallback, useEffect, useState } from "react";
+import styles from "./index.module.scss";
+import { Button } from "antd";
+import classNames from "classnames";
+
+const A1Add = React.lazy(() => import("../A1Add"));
+const A1Outer = React.lazy(() => import("../A1Outer"));
+
+const A1Tab = [
+  { id: 1, name: "项目介绍" },
+  { id: 2, name: "项目文件" },
+  { id: 3, name: "内控文件" },
+  { id: 4, name: "项目成员" },
+];
+
+type Props = {
+  pageType: { txt: string; id: number };
+  closeFu: () => void;
+  tabType: boolean;
+};
+
+function A1Look({ pageType, closeFu, tabType }: Props) {
+  const [sonPageType, setSonPageType] = useState(pageType);
+
+  const [topType, setTopType] = useState(1);
+
+  useEffect(() => {
+    if (tabType) setTopType(3);
+  }, [tabType]);
+
+  useEffect(() => {
+    if (topType === 1) {
+      setSonPageType({ txt: "look", id: pageType.id });
+    }
+  }, [pageType.id, topType]);
+
+  // 项目介绍 点取消的时候 更新key,重新渲染
+  const [tab1Key, setTab1Key] = useState(-1);
+
+  // 从 项目介绍 点击 取消
+  const tab1CloseFu = useCallback(() => {
+    setTab1Key(Date.now());
+    setSonPageType({ txt: "look", id: pageType.id });
+  }, [pageType.id]);
+
+  return (
+    <div className={styles.A1Look}>
+      <div className="A1LookTitle">
+        <h3>XXXXXXX 项目</h3>
+        <Button onClick={closeFu}>返 回</Button>
+      </div>
+      <div className="A1LookTab">
+        {A1Tab.map((v) => (
+          <div
+            onClick={() => setTopType(v.id)}
+            className={classNames(
+              "A1LookTabRow",
+              topType === v.id ? "A1LookTabRowAc" : ""
+            )}
+            key={v.id}
+          >
+            {v.name}
+          </div>
+        ))}
+      </div>
+      <div className="A1LookMain">
+        {topType === 1 && sonPageType.txt === "look" ? (
+          <div className="A1lrBtn">
+            <Button
+              type="primary"
+              onClick={() => setSonPageType({ txt: "edit", id: pageType.id })}
+            >
+              编辑
+            </Button>
+          </div>
+        ) : null}
+
+        {topType === 1 ? (
+          <A1Add
+            key={tab1Key}
+            pageType={sonPageType}
+            closeFu={tab1CloseFu}
+            addFu={() => {}}
+            editFu={() => {
+              console.log("编辑成功");
+            }}
+          />
+        ) : topType === 2 ? (
+          <A1Outer id={pageType.id} />
+        ) : null}
+      </div>
+    </div>
+  );
+}
+
+const MemoA1Look = React.memo(A1Look);
+
+export default MemoA1Look;

+ 75 - 0
src/pages/A1Project/A1Outer/A1OMove/index.module.scss

@@ -0,0 +1,75 @@
+.A1OMove {
+  :global {
+    .ant-modal-close {
+      display: none;
+    }
+
+    .ant-modal {
+      width: 800px !important;
+    }
+
+    .A1OMMain {
+      width: 100%;
+      border-top: 1px solid #999999;
+
+      .A1OMTit {
+        font-size: 16px;
+        margin: 20px 0 10px;
+
+      }
+
+      .A1OMxie {
+        font-size: 14px;
+        border-bottom: 1px solid #ccc;
+        padding-bottom: 6px;
+        padding-left: 6px;
+
+        &>span {
+          cursor: pointer;
+
+          &:hover {
+            text-decoration: underline
+          }
+
+          &:last-child {
+            cursor: default;
+
+            &:hover {
+              text-decoration: none
+            }
+          }
+        }
+      }
+
+      .A1OMArr {
+        max-height: 500px;
+        overflow-y: auto;
+
+        .A1OMArrRow {
+
+          padding: 6px;
+          border-bottom: 1px solid #ccc;
+          font-size: 18px;
+
+
+        }
+
+        .A1OMArrRowAc {
+          cursor: pointer;
+          color: var(--themeColor);
+
+          &:hover {
+            text-decoration: underline
+          }
+        }
+      }
+
+      .A1OMBtn {
+        width: 100%;
+        display: flex;
+        justify-content: center;
+        margin-top: 30px;
+      }
+    }
+  }
+}

+ 173 - 0
src/pages/A1Project/A1Outer/A1OMove/index.tsx

@@ -0,0 +1,173 @@
+import React, { useCallback, useEffect, useState } from "react";
+import styles from "./index.module.scss";
+import { Button, Modal, Popconfirm } from "antd";
+import { leftTabArr } from "..";
+import classNames from "classnames";
+import { MessageFu } from "@/utils/message";
+
+const towTableArr = [
+  {
+    id: 2,
+    name: "asdasd",
+    type: "文件夹",
+  },
+  {
+    id: 22,
+    name: "sadsssscxxxx",
+    type: "文件",
+  },
+];
+
+type Props = {
+  mId: { id: number; name: string };
+  id1: { id: number; name: string };
+  id2: { id: number; name: string };
+  closeFu: () => void;
+};
+
+function A1OMove({ mId, id1, id2, closeFu }: Props) {
+  // 一级id
+  const [tab1, setTab1] = useState({ id: 0, name: "" });
+
+  // 二级id
+  const [tab2, setTab2] = useState({ id: 0, name: "" });
+
+  // 表格数据
+  const [tableInfo, setTableInfo] = useState(leftTabArr);
+
+  // 封装发送请求的函数
+  const getListFu = useCallback((id: number) => {
+    console.log("文件移动发送请求", id);
+
+    // setTableInfo();
+  }, []);
+
+  // 选中文件夹
+  const cutFileFu = useCallback(
+    (id: number, name: string, type?: string) => {
+      if (type === "文件夹") {
+        if (tab1.id) {
+          // 第二级
+
+          setTab2({ id, name });
+        } else {
+          // 第一级
+          setTab1({ id, name });
+          setTab2({ id: 0, name: "" });
+
+          // 后面调试接口的时候 删掉
+          setTimeout(() => {
+            setTableInfo(towTableArr);
+          }, 200);
+        }
+      }
+    },
+    [tab1.id]
+  );
+
+  useEffect(() => {
+    if (tab1.id) getListFu(tab1.id);
+  }, [getListFu, tab1]);
+
+  useEffect(() => {
+    if (tab2.id) getListFu(tab2.id);
+  }, [getListFu, tab2.id]);
+
+  // 面包屑的根目录
+  const mianB1Fu = useCallback(() => {
+    setTableInfo(leftTabArr);
+    setTab1({ id: 0, name: "" });
+    setTab2({ id: 0, name: "" });
+  }, []);
+
+  const mianB2Fu = useCallback(() => {
+    if (tab2.id) {
+      setTab1({ id: tab1.id, name: tab1.name });
+
+      setTab2({ id: 0, name: "" });
+    }
+  }, [tab1.id, tab1.name, tab2.id]);
+
+  // 点击移动
+  const btnOkFu = useCallback(() => {
+    if (tab2.id) {
+      // 进入到了二级
+      if (tab2.id === id2.id) return MessageFu.warning("不能和之前的位置一样!");
+    } else if (tab1.id) {
+      // 一级
+      if (tab1.id === id1.id) return MessageFu.warning("不能和之前的位置一样!");
+    }
+  }, [id1.id, id2.id, tab1.id, tab2.id]);
+
+  return (
+    <Modal
+      wrapClassName={styles.A1OMove}
+      destroyOnClose
+      open={true}
+      title="移动文件"
+      footer={
+        [] // 设置footer为空,去掉 取消 确定默认按钮
+      }
+    >
+      <div className="A1OMMain">
+        <div className="A1OMTit">
+          当前文件位置:{id1.name} {id2.id ? <>/ {id2.name}</> : null} /{" "}
+          {mId.name}
+        </div>
+
+        <div className="A1OMxie">
+          <span onClick={mianB1Fu}>根目录</span>
+
+          {tab1.id ? (
+            <>
+              {">"} <span onClick={mianB2Fu}>{tab1.name}</span>
+            </>
+          ) : null}
+          {tab2.id ? (
+            <>
+              <span>
+                {" "}
+                {">"} {tab2.name}
+              </span>
+            </>
+          ) : null}
+        </div>
+
+        <div className="A1OMArr">
+          {tableInfo.map((v) => (
+            <div
+              className={classNames(
+                "A1OMArrRow",
+                v.type === "文件夹" ? "A1OMArrRowAc" : ""
+              )}
+              key={v.id}
+              onClick={() => cutFileFu(v.id, v.name, v.type)}
+            >
+              {v.name}
+            </div>
+          ))}
+        </div>
+
+        <div className="A1OMBtn">
+          <Popconfirm
+            title="放弃编辑后,信息将不会保存!"
+            okText="放弃"
+            cancelText="取消"
+            onConfirm={closeFu}
+            okButtonProps={{ loading: false }}
+          >
+            <Button>取消</Button>
+          </Popconfirm>
+          &emsp;
+          <Button type="primary" onClick={btnOkFu} disabled={!tab1.id}>
+            移动至此
+          </Button>
+        </div>
+      </div>
+    </Modal>
+  );
+}
+
+const MemoA1OMove = React.memo(A1OMove);
+
+export default MemoA1OMove;

+ 30 - 0
src/pages/A1Project/A1Outer/A1ORenFile/index.module.scss

@@ -0,0 +1,30 @@
+.A1ORenFile {
+  :global {
+    .ant-modal-close {
+      display: none;
+    }
+
+    .ant-modal {
+      width: 800px !important;
+    }
+
+    .A1ORMain {
+      width: 100%;
+      border-top: 1px solid #999999;
+
+      .A1ORMainInput {
+        padding-top: 20px;
+        .A1ORMainInputTit{
+          margin-bottom: 20px;
+        }
+      }
+
+      .A1ORBtn2 {
+        width: 100%;
+        display: flex;
+        justify-content: center;
+        margin-top: 30px;
+      }
+    }
+  }
+}

+ 100 - 0
src/pages/A1Project/A1Outer/A1ORenFile/index.tsx

@@ -0,0 +1,100 @@
+import React, { useCallback, useEffect, useMemo, useState } from "react";
+import styles from "./index.module.scss";
+import { Button, Input, Modal, Popconfirm } from "antd";
+import { MessageFu } from "@/utils/message";
+
+type Props = {
+  closeFu: () => void;
+  fileInfo: {
+    id: number;
+    fileName: string;
+    type: string;
+  };
+};
+
+function A1ORenFile({ closeFu, fileInfo }: Props) {
+  const [value, setValue] = useState("");
+
+  useEffect(() => {
+    if (fileInfo.id > 0 && fileInfo.type === "文件") {
+      const arr = fileInfo.fileName.split(".");
+      const val = "." + arr[arr.length - 1];
+      const val2 = fileInfo.fileName.replace(val, "");
+      setValue(val2);
+    } else setValue(fileInfo.fileName);
+  }, [fileInfo]);
+
+  const onChangeFu = useCallback((val: string) => {
+    setValue(val.replace(/\s+/g, ""));
+  }, []);
+
+  const isFileType = useMemo(() => {
+    let val = "";
+    if (fileInfo.type === "文件" && fileInfo.fileName) {
+      const arr = fileInfo.fileName.split(".");
+      val = arr[arr.length - 1];
+    }
+    return val;
+  }, [fileInfo]);
+
+  // 点击确定
+  const btnOkFu = useCallback(() => {
+    if (!value) return MessageFu.warning("名称不能为空!");
+
+    console.log("--------点击确定", value);
+  }, [value]);
+
+  return (
+    <Modal
+      wrapClassName={styles.A1ORenFile}
+      destroyOnClose
+      open={true}
+      title={
+        fileInfo.id === -1
+          ? "新建文件夹"
+          : fileInfo.type === "文件夹"
+          ? "文件夹重命名"
+          : "文件重命名"
+      }
+      footer={
+        [] // 设置footer为空,去掉 取消 确定默认按钮
+      }
+    >
+      <div className="A1ORMain">
+        <div className="A1ORMainInput">
+          {isFileType ? (
+            <div className="A1ORMainInputTit">文件后缀:.{isFileType}</div>
+          ) : null}
+
+          <Input
+            value={value}
+            onChange={(e) => onChangeFu(e.target.value)}
+            maxLength={30}
+            showCount
+            placeholder="请输入名称"
+          />
+        </div>
+
+        <div className="A1ORBtn2">
+          <Popconfirm
+            title="放弃编辑后,信息将不会保存!"
+            okText="放弃"
+            cancelText="取消"
+            onConfirm={closeFu}
+            okButtonProps={{ loading: false }}
+          >
+            <Button>取消</Button>
+          </Popconfirm>
+          &emsp;
+          <Button type="primary" onClick={btnOkFu}>
+            确定
+          </Button>
+        </div>
+      </div>
+    </Modal>
+  );
+}
+
+const MemoA1ORenFile = React.memo(A1ORenFile);
+
+export default MemoA1ORenFile;

+ 89 - 0
src/pages/A1Project/A1Outer/index.module.scss

@@ -0,0 +1,89 @@
+.A1Outer {
+  width: 100%;
+  height: 100%;
+  padding-top: 15px;
+
+  :global {
+    .A1Otop {
+      display: flex;
+      justify-content: space-between;
+
+      .A1Otop1 {
+        .A1OnowLoc {
+          padding: 0 5px;
+          margin-top: 15px;
+          font-size: 16px;
+        }
+      }
+    }
+
+    .A1OtableBox {
+      margin-top: 15px;
+      border-radius: 10px;
+      height: calc(100% - 43px);
+      overflow: hidden;
+      display: flex;
+
+      .A1OtableBox1 {
+        width: 150px;
+        background-color: #e8e8e8;
+
+        .A1OtableBox1_1 {
+          height: 60px;
+          background-color: var(--themeColor);
+          line-height: 60px;
+          text-align: center;
+          font-weight: 700;
+          font-size: 20px;
+          color: #fff;
+        }
+
+
+        .A1OtableBox1_2 {
+          margin-top: 15px;
+          height: 40px;
+          line-height: 40px;
+          text-align: center;
+          font-size: 16px;
+          border-radius: 6px;
+          cursor: pointer;
+
+          &:hover {
+            background-color: var(--themeColor);
+            color: #fff;
+          }
+        }
+
+        .A1OtableBox1_2Ac {
+          background-color: var(--themeColor);
+          color: #fff;
+        }
+      }
+
+      .A1OtableBox2 {
+        width: calc(100% - 150px);
+
+        .A1OfilesTable {
+          cursor: pointer;
+          color: var(--themeColor);
+
+          &:hover {
+            text-decoration: underline
+          }
+        }
+
+        .ant-table-body {
+          height: 560px;
+          overflow-y: auto !important;
+
+          .ant-table-row {
+            .ant-table-cell {
+              padding: 10px 8px;
+            }
+          }
+        }
+      }
+
+    }
+  }
+}

+ 399 - 0
src/pages/A1Project/A1Outer/index.tsx

@@ -0,0 +1,399 @@
+import React, {
+  useCallback,
+  useEffect,
+  useMemo,
+  useRef,
+  useState,
+} from "react";
+import styles from "./index.module.scss";
+import { Button, Input, Popconfirm, Table } from "antd";
+import classNames from "classnames";
+import { baseURL } from "@/utils/http";
+import filesLookFu from "@/utils/filesLook";
+import A1ORenFile from "./A1ORenFile";
+import A1OMove from "./A1OMove";
+
+export const leftTabArr:{
+  id: number;
+  type?: string;
+  name: string;
+}[] = [
+  { id: 1, type: "文件夹", name: "重要文档-已盖章" },
+  { id: 2, type: "文件夹", name: "重要文档-未盖章" },
+  { id: 3, type: "文件夹", name: "其他过程文件" },
+];
+
+const towTableArr = [
+  {
+    id: 2,
+    b: "第二级",
+    fileName: "899845646.pdf",
+    type: "文件",
+  },
+  {
+    id: 22,
+    b: "第二级2222",
+    fileName: "899845646杀杀杀.pdf",
+    type: "文件",
+  },
+];
+
+type Props = {
+  id: number;
+};
+
+function A1Outer({ id }: Props) {
+  const [fromData, setFromData] = useState({
+    id: 1,
+    aaaa: "",
+    pageNum: 1,
+    pageSize: 10,
+  });
+
+  // 文件名的输入
+  const aaaaTime = useRef(-1);
+  const aaaaChange = useCallback(
+    (e: React.ChangeEvent<HTMLInputElement>) => {
+      clearTimeout(aaaaTime.current);
+      aaaaTime.current = window.setTimeout(() => {
+        setFromData({
+          ...fromData,
+          aaaa: e.target.value,
+          pageNum: 1,
+        });
+      }, 500);
+    },
+    [fromData]
+  );
+
+  // 封装发送请求的函数
+  const getListFu = useCallback(() => {
+    console.log("tab2发送请求", fromData);
+
+    // 清空选中
+    setSelectedRowKeys([]);
+
+    setTableInfo({
+      list: [
+        {
+          id: 11,
+          c: "2020-02-02 12:34:56",
+          type: "文件夹",
+          fileName: "一个文件夹",
+          filePath: "xxx",
+        },
+        {
+          id: 2,
+          b: "阿三大苏打阿三大苏打",
+          fileName: "899845646.pdf",
+          type: "文件",
+        },
+      ],
+      total: 200,
+    });
+  }, [fromData]);
+
+  useEffect(() => {
+    getListFu();
+  }, [getListFu]);
+
+  // 一级的高亮
+  const [tab1, setTab1] = useState(leftTabArr[0]);
+
+  // 二级的选择
+  const [tab2, setTab2] = useState({ id: 0, name: "" });
+
+  // 一级的切换
+  const cutTab1Fu = useCallback(
+    (id: number, name: string) => {
+      setTab2({ id: 0, name: "" });
+      setTab1({ id, name });
+
+      if (id !== fromData.id) setFromData({ ...fromData, id, pageNum: 1 });
+    },
+    [fromData]
+  );
+
+  // 点击表格里面的删除
+  const delById = useCallback((id: number) => {
+    console.log("---点击删除");
+  }, []);
+
+  // 点击表格里面的 文件夹 的下载
+  const downFilesFu = useCallback((id: number) => {
+    console.log("ssss,点击文件夹的下载");
+  }, []);
+
+  // 点击表格里面的 文件夹 进入 2级
+  const toTowFilesFu = useCallback(
+    (id: number, type: string, name: string) => {
+      if (type === "文件夹") {
+        setTab2({ id, name });
+        setFromData({ ...fromData, id, pageNum: 1 });
+
+        // 后面调试接口的时候 删掉
+        setTimeout(() => {
+          setTableInfo({ list: towTableArr, total: 200 });
+        }, 200);
+      }
+    },
+    [fromData]
+  );
+
+  // 表格数据
+  const [tableInfo, setTableInfo] = useState({
+    list: [
+      {
+        id: 11,
+        c: "2020-02-02 12:34:56",
+        type: "文件夹",
+        fileName: "一个文件夹",
+        filePath: "xxx",
+      },
+      {
+        id: 2,
+        b: "阿三大苏打阿三大苏打",
+        fileName: "899845646.pdf",
+        type: "文件",
+      },
+    ],
+    total: 2,
+  });
+
+  const columns = useMemo(() => {
+    return [
+      {
+        title: "文件名",
+        render: (item: any) =>
+          item.fileName.length >= 30 ? (
+            <span style={{ cursor: "pointer" }} title={item.fileName}>
+              <span
+                onClick={() => toTowFilesFu(item.id, item.type, item.fileName)}
+                className={classNames(
+                  item.type === "文件夹" ? "A1OfilesTable" : ""
+                )}
+              >
+                {item.fileName.substring(0, 30) + "..."}
+              </span>
+            </span>
+          ) : (
+            <span
+              onClick={() => toTowFilesFu(item.id, item.type, item.fileName)}
+              className={classNames(
+                item.type === "文件夹" ? "A1OfilesTable" : ""
+              )}
+            >
+              {item.fileName}
+            </span>
+          ),
+      },
+      {
+        title: "创建用户",
+        dataIndex: "b",
+      },
+      {
+        title: "创建时间",
+        dataIndex: "c",
+      },
+      {
+        title: "操作",
+        render: (item: any) => (
+          <>
+            {filesLookFu(item.fileName) ? (
+              <Button
+                size="small"
+                type="text"
+                onClick={() => filesLookFu(item.fileName, item.filePath)}
+              >
+                查看
+              </Button>
+            ) : null}
+
+            {item.type === "文件夹" ? (
+              <Button
+                size="small"
+                type="text"
+                onClick={() => downFilesFu(item.id)}
+              >
+                下载
+              </Button>
+            ) : (
+              <a
+                href={baseURL + item.filePath}
+                download={item.fileName}
+                target="_blank"
+                rel="noreferrer"
+              >
+                <Button size="small" type="text">
+                  下载
+                </Button>
+              </a>
+            )}
+
+            <Button
+              size="small"
+              type="text"
+              onClick={() =>
+                setRenFile({
+                  id: item.id,
+                  fileName: item.fileName,
+                  type: item.type,
+                })
+              }
+            >
+              重命名
+            </Button>
+            {item.type === "文件夹" ? null : (
+              <Button
+                size="small"
+                type="text"
+                onClick={() => setMoveId({ id: item.id, name: item.fileName })}
+              >
+                移动
+              </Button>
+            )}
+
+            <Popconfirm
+              title="删除后无法恢复,是否删除?"
+              okText="删除"
+              cancelText="取消"
+              onConfirm={() => delById(item.id)}
+              okButtonProps={{ loading: false }}
+            >
+              <Button size="small" type="text" danger>
+                删除
+              </Button>
+            </Popconfirm>
+          </>
+        ),
+      },
+    ];
+  }, [delById, downFilesFu, toTowFilesFu]);
+
+  // 页码变化
+  const paginationChange = useCallback(
+    () => (pageNum: number, pageSize: number) => {
+      setFromData({ ...fromData, pageNum, pageSize });
+    },
+    [fromData]
+  );
+
+  // 关于表格的多选
+  const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
+
+  // 新建文件夹或者 重命名
+  const [renFile, setRenFile] = useState({
+    id: 0,
+    fileName: "",
+    type: "",
+  });
+
+  // 点击移动之后出来的数据
+  const [moveId, setMoveId] = useState({ id: 0, name: "" });
+
+  return (
+    <div className={styles.A1Outer}>
+      <div className="A1Otop">
+        <div className="A1Otop1">
+          <span>文件名:</span>
+          <Input
+            maxLength={30}
+            style={{ width: 300 }}
+            placeholder="请输入文件名称,最多30字"
+            allowClear
+            onChange={(e) => aaaaChange(e)}
+          />
+          &emsp;&emsp;
+          <span className="A1OnowLoc">
+            <span>当前位置:{tab1.name}</span>
+            {tab2.id ? <> / {tab2.name}</> : null}
+          </span>
+        </div>
+        <div className="A1Otop2">
+          {tab2.id ? null : (
+            <>
+              <Button
+                type="primary"
+                onClick={() =>
+                  setRenFile({ id: -1, fileName: "", type: "文件夹" })
+                }
+              >
+                新建文件夹
+              </Button>
+              &emsp;
+            </>
+          )}
+          <Button type="primary" disabled={selectedRowKeys.length <= 0}>
+            批量下载
+          </Button>
+          &emsp;
+          <Button type="primary">批量上传</Button>&emsp;
+        </div>
+      </div>
+      {/* 表格主体 */}
+      <div className="A1OtableBox">
+        <div className="A1OtableBox1">
+          <div className="A1OtableBox1_1">目录</div>
+          {leftTabArr.map((v) => (
+            <div
+              onClick={() => cutTab1Fu(v.id, v.name)}
+              className={classNames(
+                "A1OtableBox1_2",
+                tab1.id === v.id ? "A1OtableBox1_2Ac" : ""
+              )}
+              key={v.id}
+            >
+              {v.name}
+            </div>
+          ))}
+        </div>
+        <div className="A1OtableBox2">
+          <Table
+            rowSelection={{
+              type: "checkbox",
+              selectedRowKeys,
+              onChange: (selectedRowKeys: React.Key[]) => {
+                console.log("选中的ids", selectedRowKeys);
+                setSelectedRowKeys(selectedRowKeys);
+              },
+            }}
+            scroll={{ y: 560 }}
+            dataSource={tableInfo.list}
+            columns={columns}
+            rowKey="id"
+            pagination={{
+              showQuickJumper: true,
+              position: ["bottomCenter"],
+              showSizeChanger: true,
+              current: fromData.pageNum,
+              pageSize: fromData.pageSize,
+              total: tableInfo.total,
+              onChange: paginationChange(),
+            }}
+          />
+        </div>
+      </div>
+      {/* 点击 新建 文件夹 或者 重命名 */}
+      {renFile.id ? (
+        <A1ORenFile
+          closeFu={() => setRenFile({ id: 0, fileName: "", type: "" })}
+          fileInfo={renFile}
+        />
+      ) : null}
+
+      {/* 点击移动 */}
+      {moveId.id ? (
+        <A1OMove
+          mId={moveId}
+          id1={tab1}
+          id2={tab2}
+          closeFu={() => setMoveId({ id: 0, name: "" })}
+        />
+      ) : null}
+    </div>
+  );
+}
+
+const MemoA1Outer = React.memo(A1Outer);
+
+export default MemoA1Outer;

+ 4 - 0
src/pages/A1Project/index.module.scss

@@ -1,5 +1,6 @@
 .A1Project {
   position: relative;
+
   :global {
     .A1top {
       border-radius: 10px;
@@ -45,5 +46,8 @@
         }
       }
     }
+
   }
+
+
 }

+ 68 - 12
src/pages/A1Project/index.tsx

@@ -6,11 +6,13 @@ import React, {
   useState,
 } from "react";
 import styles from "./index.module.scss";
-import { Button, Input, Select, Table } from "antd";
+import { Button, Input, Popconfirm, Select, Table, Tooltip } from "antd";
 import { useSelector } from "react-redux";
 import { RootState } from "@/store";
 import { A1TableType } from "@/types";
 import A1Add from "./A1Add";
+import A1Down from "./A1Down";
+import A1Look from "./A1Look";
 
 const bbbbArr = [
   {
@@ -206,6 +208,15 @@ function A1Project() {
     [fromData]
   );
 
+  // 点击删除
+  const delById = useCallback((id: number) => {}, []);
+
+  // 点击下载
+  const [downId, setDownId] = useState(0);
+
+  // 点击审批
+  const lookTabType = useRef(false);
+
   const columns = useMemo(() => {
     const arr: any = [
       {
@@ -253,8 +264,15 @@ function A1Project() {
           dataIndex: "a",
         },
         {
-          width: 150,
-          title: "待审批/通过/驳回",
+          width: 164,
+          title: (
+            <Tooltip title="该项目内控文件的审批状态和数量">
+              <div className="iconHoverTit">
+                待审批/通过/驳回&nbsp;
+                <div className="iconHoverTitTxt">?</div>
+              </div>
+            </Tooltip>
+          ),
           dataIndex: "a",
         }
       );
@@ -264,27 +282,49 @@ function A1Project() {
       title: "操作",
       render: (item: A1TableType) => (
         <>
-          <Button size="small" type="text">
+          <Button
+            size="small"
+            type="text"
+            onClick={() => {
+              lookTabType.current = false;
+              setPageType({ txt: "look", id: item.id });
+            }}
+          >
             查看
           </Button>
           {topType === "inner" ? (
-            <Button size="small" type="text">
+            <Button
+              size="small"
+              type="text"
+              onClick={() => {
+                lookTabType.current = true;
+                setPageType({ txt: "look", id: item.id });
+              }}
+            >
               审批
             </Button>
           ) : null}
 
-          <Button size="small" type="text">
+          <Button size="small" type="text" onClick={() => setDownId(item.id)}>
             下载
           </Button>
-          <Button size="small" type="text">
-            删除
-          </Button>
+          <Popconfirm
+            title="删除后无法恢复,是否删除?"
+            okText="删除"
+            cancelText="取消"
+            onConfirm={() => delById(item.id)}
+            okButtonProps={{ loading: false }}
+          >
+            <Button size="small" type="text" danger>
+              删除
+            </Button>
+          </Popconfirm>
         </>
       ),
     });
 
     return arr;
-  }, [topType]);
+  }, [delById, topType]);
 
   // 新增和查看
   const [pageType, setPageType] = useState({ txt: "", id: 0 });
@@ -292,7 +332,12 @@ function A1Project() {
   return (
     <div className={styles.A1Project}>
       <div className="pageTitle">
-        项目管理{pageType.txt === "add" ? " > 新增项目" : null}
+        项目管理
+        {pageType.txt === "add"
+          ? " > 新增项目"
+          : pageType.txt === "look"
+          ? " > 查看项目"
+          : null}
       </div>
 
       {/* 顶部筛选 */}
@@ -318,7 +363,7 @@ function A1Project() {
             <span>项目编号/项目名称/建设单位:</span>
             <Input
               key={inputKey}
-              maxLength={30}
+              maxLength={20}
               style={{ width: 200 }}
               placeholder="请输入内容,最多20字"
               allowClear
@@ -453,8 +498,19 @@ function A1Project() {
         <A1Add
           pageType={pageType}
           closeFu={() => setPageType({ txt: "", id: 0 })}
+          addFu={() => resetSelectFu()}
+          editFu={() => A1getListFu()}
+        />
+      ) : pageType.txt === "look" ? (
+        <A1Look
+          pageType={pageType}
+          closeFu={() => setPageType({ txt: "", id: 0 })}
+          tabType={lookTabType.current}
         />
       ) : null}
+
+      {/* 下载 */}
+      {downId ? <A1Down id={downId} closeFu={() => setDownId(0)} /> : null}
     </div>
   );
 }

+ 1 - 0
src/types/declaration.d.ts

@@ -3,5 +3,6 @@ declare module "*.scss";
 declare module "*.png";
 declare module "*.jpg";
 declare module "*.gif";
+declare module "*.svg";
 declare module "js-export-excel";
 declare module 'braft-utils';