shaogen1995 1 tahun lalu
induk
melakukan
577647eafe

+ 16 - 8
src/components/ZRichTexts/index.tsx

@@ -39,9 +39,13 @@ type Props = {
   isLook: boolean; //是否是查看进来
   ref: any; //当前自己的ref,给父组件调用
   myUrl: string; //上传的api地址
+  isOne?: boolean;
 };
 
-function ZRichTexts({ check, dirCode, isLook, myUrl }: Props, ref: any) {
+function ZRichTexts(
+  { check, dirCode, isLook, myUrl, isOne = false }: Props,
+  ref: any
+) {
   const [sectionArr, setSectionArr] = useState<SectionArrType[]>([
     {
       id: Date.now(),
@@ -223,7 +227,7 @@ function ZRichTexts({ check, dirCode, isLook, myUrl }: Props, ref: any) {
   // 章节音频删除
   const delSectionFu = useCallback(
     (index: number) => {
-      console.log("ppppppppp", index);
+      // console.log("ppppppppp", index);
 
       const arr = [...sectionArr];
       arr[index].fileInfo = { fileName: "", filePath: "" };
@@ -283,12 +287,16 @@ function ZRichTexts({ check, dirCode, isLook, myUrl }: Props, ref: any) {
       <div
         className={classNames("formRightZW", isLook ? "formRightZWLook" : "")}
       >
-        <Checkbox
-          checked={isSection}
-          onChange={(e) => setIsSection(e.target.checked)}
-        >
-          按章节发布
-        </Checkbox>
+        {isOne ? (
+          <div></div>
+        ) : (
+          <Checkbox
+            checked={isSection}
+            onChange={(e) => setIsSection(e.target.checked)}
+          >
+            按章节发布
+          </Checkbox>
+        )}
 
         {isSection ? (
           <Button hidden={isLook} type="primary" onClick={addSectionFu}>

+ 3 - 1
src/components/ZupTypes/index.tsx

@@ -49,6 +49,7 @@ type Props = {
   videoTit?: string; //视频上传的提示语
   isTypeShow?: boolean; //默认就选中(只有一个类型的时候)
   isUpName?: boolean; //是否能修改图片名字
+  lastImgTxt?:string
 };
 
 function ZupTypes(
@@ -66,6 +67,7 @@ function ZupTypes(
     videoTit = "",
     isTypeShow = false,
     isUpName = false,
+    lastImgTxt=''
   }: Props,
   ref: any
 ) {
@@ -547,7 +549,7 @@ function ZupTypes(
               <br />
             </>
           ) : null}
-          支持png、jpg的图片格式;最大支持5M;最多支持{imgLength}张。
+          支持png、jpg的图片格式;最大支持5M;最多支持{imgLength}张。{lastImgTxt}
         </div>
       </div>
 

+ 126 - 0
src/pages/A3holding/A3add/index.module.scss

@@ -0,0 +1,126 @@
+.A3add {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  z-index: 12;
+  background-color: #fff;
+  border-radius: 10px;
+  padding: 24px;
+
+  :global {
+    .A3eMain {
+      width: 100%;
+      height: 100%;
+      overflow-y: auto;
+
+
+      .A3fromRow {
+        position: relative;
+        width: 800px;
+        height: 56px;
+
+        // &>div {
+        //   width: 100%;
+        // }
+
+        .A3_1Frow {
+          position: absolute;
+          top: 0px;
+          left: 600px;
+          width: 200px;
+        }
+
+        .A3_4Frow {
+          position: absolute;
+          left: 400px;
+          top: 4px;
+        }
+
+        .A3_6Frow {
+          position: absolute;
+          left: 200px;
+          top: 5px;
+          color: #999;
+          font-size: 12px;
+        }
+
+      }
+
+      .ant-form {
+        width: 800px;
+
+        // .ant-input-affix-wrapper{
+        //   width: 800px;
+        // }
+        .formRow {
+          display: flex;
+
+          .formLeft {
+            position: relative;
+            top: 3px;
+            width: 100px;
+            text-align: right;
+
+            &>span {
+              color: #ff4d4f;
+            }
+          }
+
+          .formRight {
+            width: calc(100% - 100px);
+          }
+
+
+          .formRight5Tit {
+            position: relative;
+            top: -10px;
+            transition: top .2s;
+            margin: 5px 0;
+            color: #ff4d4f;
+            opacity: 0;
+            pointer-events: none;
+          }
+
+          .formRight5TitErr {
+            opacity: 1;
+            top: 0;
+          }
+        }
+
+
+        .A3Ebtn {
+          position: absolute;
+          z-index: 10;
+          left: 1200px;
+          top: 50%;
+          transform: translateY(-50%);
+        }
+      }
+    }
+
+
+    // 从查看进入
+    .A3eMainLook {
+      .ant-picker {
+        pointer-events: none;
+      }
+
+      .ant-checkbox-wrapper {
+        pointer-events: none;
+      }
+
+      .ant-input-number {
+        pointer-events: none;
+      }
+
+      .ant-select {
+        pointer-events: none;
+      }
+      .ant-radio-wrapper{
+        pointer-events: none;
+      }
+    }
+  }
+}

+ 307 - 0
src/pages/A3holding/A3add/index.tsx

@@ -0,0 +1,307 @@
+import React, { useCallback, useEffect, useRef, useState } from "react";
+import styles from "./index.module.scss";
+import { A1EditInfoType } from "@/pages/A1event/data";
+import {
+  Button,
+  DatePicker,
+  Form,
+  FormInstance,
+  Input,
+  InputNumber,
+  Select,
+} from "antd";
+import { A3_APIgetInfo, A3_APIsave } from "@/store/action/A3holding";
+import dayjs from "dayjs";
+import { MessageFu } from "@/utils/message";
+import classNames from "classnames";
+import ZupAudio from "@/components/ZupAudio";
+import ZRichTexts from "@/components/ZRichTexts";
+import ZupTypes from "@/components/ZupTypes";
+import MyPopconfirm from "@/components/MyPopconfirm";
+import TextArea from "antd/es/input/TextArea";
+
+type Props = {
+  editInfo: A1EditInfoType;
+  selectAgeArr: { value: number | string; label: string }[];
+  closeFu: () => void;
+  editTableFu: () => void;
+  addTableFu: () => void;
+};
+
+function A3add({
+  editInfo,
+  selectAgeArr,
+  closeFu,
+  editTableFu,
+  addTableFu,
+}: Props) {
+  const [dirCode, setDirCode] = useState("");
+
+  // 表单的ref
+  const FormBoxRef = useRef<FormInstance>(null);
+
+  // 富文本的ref
+  const ZRichTextRef = useRef<any>(null);
+
+  // 标题的音频
+  const [nameAudio, setNameAudio] = useState({
+    fileName: "",
+    filePath: "",
+  });
+  // 多个图片的ref
+  const ZupFilesRef2 = useRef<any>(null);
+
+  // 编辑/查看 进入页面 获取信息
+  const getInfoFu = useCallback(async (id: number) => {
+    const res = await A3_APIgetInfo(id);
+    if (res.code === 0) {
+      const data = res.data;
+
+      setDirCode(data.dirCode);
+
+      // 展示展馆
+      ZupFilesRef2.current?.setFileComFileFu({
+        type: "img",
+        fileList: data.exhibitionFile || [],
+      });
+
+      // 设置标题的 音频
+      if (data.fileName && data.filePath) {
+        setNameAudio({
+          fileName: data.fileName,
+          filePath: data.filePath,
+        });
+      }
+      // 设置富文本
+      ZRichTextRef.current?.ritxtShowFu(JSON.parse(data.rtf));
+
+      const obj = {
+        ...data,
+        myTime: dayjs(data.datePublish),
+      };
+
+      FormBoxRef.current?.setFieldsValue(obj);
+    }
+  }, []);
+
+  // 附件 是否 已经点击过确定
+  const [fileCheck, setFileCheck] = useState(false);
+
+  // 没有通过校验
+  const onFinishFailed = useCallback(() => {
+    setFileCheck(true);
+  }, []);
+
+  //  通过校验点击确定
+  const onFinish = useCallback(
+    async (values: any) => {
+      setFileCheck(true);
+      // 发布日期
+      const datePublish = dayjs(values.myTime).format("YYYY-MM-DD");
+
+      // 富文本校验不通过
+      const rtf = ZRichTextRef.current?.fatherBtnOkFu() || { flag: true };
+
+      if (rtf.flag) return MessageFu.warning("请输入完整正文!");
+
+      // 展馆的校验
+      const { sonFileIds: exhibitionFileIds } =
+        ZupFilesRef2.current?.fileComFileResFu() || [];
+
+      if (exhibitionFileIds.length <= 0) {
+        return MessageFu.warning("请最少上传一张图片!");
+      }
+
+      const obj = {
+        ...values,
+        id: editInfo.id > 0 ? editInfo.id : null,
+        datePublish,
+        // thumb: coverUrl1.filePath, //待完善
+        rtf: JSON.stringify(rtf.val || ""),
+        fileName: nameAudio.fileName,
+        filePath: nameAudio.filePath,
+        exhibitionFileIds: exhibitionFileIds.join(","),
+        dirCode,
+      };
+      const res = await A3_APIsave(obj);
+
+      if (res.code === 0) {
+        MessageFu.success(`${editInfo.txt}成功!`);
+        editInfo.id > 0 ? editTableFu() : addTableFu();
+        closeFu();
+      }
+    },
+    [addTableFu, closeFu, dirCode, editInfo, editTableFu, nameAudio]
+  );
+
+  useEffect(() => {
+    if (editInfo.id > 0) {
+      getInfoFu(editInfo.id);
+    } else {
+      setDirCode(Date.now() + "");
+      FormBoxRef.current?.setFieldsValue({
+        myTime: dayjs(Date.now()),
+        sort: 999,
+        display: 1,
+      });
+    }
+  }, [editInfo.id, getInfoFu]);
+
+  return (
+    <div className={styles.A3add}>
+      <div
+        className={classNames(
+          "A3eMain",
+          editInfo.txt === "查看" ? "A3eMainLook" : ""
+        )}
+      >
+        <Form
+          ref={FormBoxRef}
+          name="basic"
+          labelCol={{ span: 3 }}
+          onFinish={onFinish}
+          onFinishFailed={onFinishFailed}
+          autoComplete="off"
+          scrollToFirstError
+        >
+          <div className="A3fromRow">
+            <Form.Item
+              label="名称"
+              name="name"
+              rules={[{ required: true, message: "请输入名称!" }]}
+              getValueFromEvent={(e) => e.target.value.replace(/\s+/g, "")}
+            >
+              <Input
+                readOnly={editInfo.txt === "查看"}
+                style={{ width: "500px" }}
+                maxLength={50}
+                showCount
+                placeholder="请输入内容"
+              />
+            </Form.Item>
+            {/* 标题的无障碍音频 */}
+            <div className="A3_1Frow">
+              <ZupAudio
+                fileInfo={nameAudio}
+                upDataFu={(info) => setNameAudio(info)}
+                delFu={() => setNameAudio({ fileName: "", filePath: "" })}
+                dirCode={dirCode}
+                myUrl="cms/collection/upload"
+                isLook={editInfo.txt === "查看"}
+              />
+            </div>
+          </div>
+
+          {/* 图片 */}
+          <div className="formRow">
+            <div className="formLeft">
+              <span>* </span>
+              图片:
+            </div>
+            <div className="formRight">
+              <ZupTypes
+                ref={ZupFilesRef2}
+                selecFlag="图片"
+                fileCheck={fileCheck}
+                dirCode={dirCode}
+                myUrl="cms/collection/upload"
+                isLook={editInfo.txt === "查看"}
+                imgLength={50}
+                isTypeShow={true}
+                lastImgTxt='第一张将作为封面'
+              />
+            </div>
+          </div>
+
+          <Form.Item label="摘要" name="digest">
+            <TextArea
+              readOnly={editInfo.txt === "查看"}
+              placeholder="请输入内容"
+              maxLength={500}
+              showCount
+            />
+          </Form.Item>
+
+          {/* 简介 */}
+          <div className="formRow">
+            <div className="formLeft">
+              <span>* </span>
+              简介:
+            </div>
+            <div className="formRight">
+              <ZRichTexts
+                check={fileCheck}
+                dirCode={dirCode}
+                isLook={editInfo.txt === "查看"}
+                ref={ZRichTextRef}
+                myUrl="cms/collection/upload"
+                isOne={true}
+              />
+            </div>
+          </div>
+
+          <Form.Item
+            label="发布日期"
+            name="myTime"
+            rules={[{ required: true, message: "请选择发布日期!" }]}
+          >
+            <DatePicker />
+          </Form.Item>
+
+          <div className="A3fromRow">
+            <Form.Item
+              label="排序值"
+              name="sort"
+              rules={[{ required: true, message: "请输入排序值!" }]}
+            >
+              <InputNumber
+                min={1}
+                max={999}
+                precision={0}
+                placeholder="请输入"
+              />
+            </Form.Item>
+            <div className="A3_6Frow" hidden={editInfo.txt === "查看"}>
+              请输入1~999的数字。数字越小,排序越靠前。数字相同时,更新发布的内容排在前面
+            </div>
+          </div>
+
+          <Form.Item
+            label="状态"
+            name="display"
+            rules={[{ required: true, message: "请选择状态!" }]}
+          >
+            <Select
+              placeholder="请选择状态"
+              style={{ width: 200 }}
+              options={[
+                { value: 1, label: "发布" },
+                { value: 0, label: "不发布" },
+              ]}
+            />
+          </Form.Item>
+
+          {/* 确定和取消按钮 */}
+          <Form.Item className="A3Ebtn">
+            {editInfo.txt === "查看" ? (
+              <Button onClick={closeFu}>返回</Button>
+            ) : (
+              <>
+                <Button type="primary" htmlType="submit">
+                  提交
+                </Button>
+                <br />
+                <br />
+                <MyPopconfirm txtK="取消" onConfirm={closeFu} />
+              </>
+            )}
+          </Form.Item>
+        </Form>
+      </div>
+    </div>
+  );
+}
+
+const MemoA3add = React.memo(A3add);
+
+export default MemoA3add;

+ 23 - 0
src/pages/A3holding/data.ts

@@ -0,0 +1,23 @@
+export type A3FromDataType = {
+  pageNum: number;
+  pageSize: number;
+  searchKey: string;
+  type: string;
+  dictAgeId: "" | number;
+  display: "" | 0 | 1;
+};
+
+export const A3Selct_1 = [
+  { value: "", label: "全部" },
+  { value: "Bronzes", label: "Bronzes" },
+  { value: "Ceramics", label: "Ceramics" },
+  { value: "Buddhist Statues", label: "Buddhist Statues" },
+  { value: "Jadewares", label: "Jadewares" },
+  { value: "Calligraphies", label: "Calligraphies" },
+  { value: "Paintings", label: "Paintings" },
+  { value: "Gold & Silverwares", label: "Gold & Silverwares" },
+  { value: "Coins & Banknotes", label: "Coins & Banknotes" },
+  { value: "Brocades & Embroideries", label: "Brocades & Embroideries" },
+  { value: "Cultural Supplies", label: "Cultural Supplies" },
+  { value: "Miscellaneous", label: "Miscellaneous" },
+];

+ 25 - 2
src/pages/A3holding/index.module.scss

@@ -1,5 +1,28 @@
 .A3holding{
-  :global{
-    
+  position: relative;
+
+  :global {
+    .A3top {
+      padding: 15px 24px;
+      border-radius: 10px;
+      background-color: #fff;
+      display: flex;
+      justify-content: space-between;
+
+      .A3topLeft {
+        display: flex;
+        &>div {
+          margin-right: 24px;
+        }
+      }
+    }
+
+    .A3tableBox {
+      border-radius: 10px;
+      overflow: hidden;
+      margin-top: 15px;
+      height: calc(100% - 77px);
+      background-color: #fff;
+    }
   }
 }

+ 226 - 5
src/pages/A3holding/index.tsx

@@ -1,12 +1,233 @@
-import React from "react";
+import React, {
+  useCallback,
+  useEffect,
+  useMemo,
+  useRef,
+  useState,
+} from "react";
 import styles from "./index.module.scss";
- function A3holding() {
-  
+import { useDispatch, useSelector } from "react-redux";
+import { A3FromDataType, A3Selct_1 } from "./data";
+import { A3_APIdel, A3_APIgetList } from "@/store/action/A3holding";
+import { RootState } from "@/store";
+import { MessageFu } from "@/utils/message";
+import { A3tableType } from "@/types";
+import { Button, Input, Select } from "antd";
+import MyPopconfirm from "@/components/MyPopconfirm";
+import { A1EditInfoType, A1Selct } from "../A1event/data";
+import MyTable from "@/components/MyTable";
+import { A3tableC } from "@/utils/tableData";
+import { A8_APIgetList } from "@/store/action/A8dict";
+import A3add from "./A3add";
+function A3holding() {
+  const dispatch = useDispatch();
+
+  const [fromData, setFromData] = useState<A3FromDataType>({
+    pageNum: 1,
+    pageSize: 10,
+    searchKey: "",
+    type: "",
+    dictAgeId: "",
+    display: "",
+  });
+  const getListFu = useCallback(() => {
+    dispatch(A3_APIgetList(fromData));
+  }, [dispatch, fromData]);
+
+  useEffect(() => {
+    getListFu();
+  }, [getListFu]);
+
+  const [inputKey, setInputKey] = useState(1);
+
+  // 标题的输入
+  const timeRef = useRef(-1);
+  const fromKeyChangeFu = useCallback(
+    (e: React.ChangeEvent<HTMLInputElement>, key: "searchKey") => {
+      clearTimeout(timeRef.current);
+      timeRef.current = window.setTimeout(() => {
+        setFromData({ ...fromData, [key]: e.target.value, pageNum: 1 });
+      }, 500);
+    },
+    [fromData]
+  );
+
+  // 点击重置
+  const resetSelectFu = useCallback(() => {
+    setInputKey(Date.now());
+    setFromData({
+      pageNum: 1,
+      pageSize: 10,
+      searchKey: "",
+      type: "",
+      dictAgeId: "",
+      display: "",
+    });
+  }, []);
+
+  const tableInfo = useSelector(
+    (state: RootState) => state.A3holding.tableInfo
+  );
+
+  const delTableFu = useCallback(
+    async (id: number) => {
+      const res = await A3_APIdel(id);
+      if (res.code === 0) {
+        MessageFu.success("删除成功!");
+        getListFu();
+      }
+    },
+    [getListFu]
+  );
+
+  const tableLastBtn = useMemo(() => {
+    return [
+      {
+        title: "操作",
+        render: (item: A3tableType) => (
+          <>
+            <Button
+              size="small"
+              type="text"
+              onClick={() => setEditInfo({ id: item.id, txt: "查看" })}
+            >
+              查看
+            </Button>
+            <Button
+              size="small"
+              type="text"
+              onClick={() => setEditInfo({ id: item.id, txt: "编辑" })}
+            >
+              编辑
+            </Button>
+            <MyPopconfirm txtK="删除" onConfirm={() => delTableFu(item.id)} />
+          </>
+        ),
+      },
+    ];
+  }, [delTableFu]);
+
+  //查看、新增、编辑
+  const [editInfo, setEditInfo] = useState<A1EditInfoType>({
+    id: 0,
+    txt: "",
+  });
+
+  useEffect(() => {
+    dispatch(A8_APIgetList());
+  }, [dispatch]);
+
+  const A8tableList = useSelector((state: RootState) => state.A8dict.list);
+
+  const selectAgeArr = useMemo(() => {
+    return [
+      { value: "", label: "全部" },
+      ...A8tableList.map((v) => ({ value: v.id, label: v.name })),
+    ];
+  }, [A8tableList]);
+
   return (
     <div className={styles.A3holding}>
-       <div className="pageTitle">馆藏管理</div>
+      <div className="pageTitle">
+        馆藏管理{editInfo.id ? ` - ${editInfo.txt}` : ""}
+      </div>
+
+      {/* 顶部筛选 */}
+      <div className="A3top">
+        <div className="A3topLeft">
+          <div>
+            <span>名称:</span>
+            <Input
+              key={inputKey}
+              maxLength={50}
+              showCount
+              style={{ width: 300 }}
+              placeholder="请输入关键字,不超过50字"
+              allowClear
+              onChange={(e) => fromKeyChangeFu(e, "searchKey")}
+            />
+          </div>
+
+          <div>
+            <span>类别:</span>
+            <Select
+              placeholder="请选择"
+              style={{ width: 200 }}
+              value={fromData.type}
+              onChange={(e) =>
+                setFromData({ ...fromData, pageNum: 1, type: e })
+              }
+              options={A3Selct_1}
+            />
+          </div>
+
+          <div>
+            <span>年代:</span>
+            <Select
+              placeholder="请选择"
+              style={{ width: 200 }}
+              value={fromData.dictAgeId}
+              onChange={(e) =>
+                setFromData({ ...fromData, pageNum: 1, dictAgeId: e })
+              }
+              options={selectAgeArr}
+            />
+          </div>
+
+          <div>
+            <span>状态:</span>
+            <Select
+              placeholder="请选择"
+              style={{ width: 100 }}
+              value={fromData.display}
+              onChange={(e) =>
+                setFromData({ ...fromData, pageNum: 1, display: e })
+              }
+              options={A1Selct}
+            />
+          </div>
+        </div>
+
+        <div>
+          <Button
+            type="primary"
+            onClick={() => setEditInfo({ id: -1, txt: "新增" })}
+          >
+            新增
+          </Button>
+          &emsp;
+          <Button onClick={resetSelectFu}>重置</Button>
+        </div>
+      </div>
+
+      {/* 表格主体 */}
+      <div className="A3tableBox">
+        <MyTable
+          yHeight={625}
+          list={tableInfo.list}
+          columnsTemp={A3tableC}
+          lastBtn={tableLastBtn}
+          pageNum={fromData.pageNum}
+          pageSize={fromData.pageSize}
+          total={tableInfo.total}
+          onChange={(pageNum, pageSize) =>
+            setFromData({ ...fromData, pageNum, pageSize })
+          }
+        />
+      </div>
+
+      {/* 新增 编辑 查看 */}
+      {editInfo.id ? (
+        <A3add
+          editInfo={editInfo}
+          selectAgeArr={selectAgeArr}
+          closeFu={() => setEditInfo({ id: 0, txt: "" })}
+          editTableFu={() => getListFu()}
+          addTableFu={() => resetSelectFu()}
+        />
+      ) : null}
     </div>
-  )
+  );
 }
 
 const MemoA3holding = React.memo(A3holding);

+ 87 - 3
src/pages/A8dict/index.module.scss

@@ -1,5 +1,89 @@
-.A8dict{
-  :global{
-    
+.A8dict {
+  background-color: #fff;
+  border-radius: 10px;
+
+  :global {
+    .A8top {
+      padding: 15px 24px;
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+
+      &>div {
+        font-size: 18px;
+        font-weight: 700;
+        color: var(--themeColor);
+      }
+    }
+
+    .A8tableBox {
+      border-radius: 10px;
+      overflow: hidden;
+      height: calc(100% - 62px);
+    }
+  }
+}
+
+.A8addMo {
+  :global {
+    .ant-modal-close {
+      display: none;
+    }
+
+    .ant-modal-body {
+      border-top: 1px solid #ccc;
+      padding-top: 15px !important;
+    }
+
+    .A8addRow {
+      display: flex;
+      height: 32px;
+      align-items: center;
+
+      .A8addRow1 {
+        width: 70px;
+        text-align: right;
+
+        &>span {
+          color: #ff4d4f;
+        }
+      }
+
+      .A8addRow2 {
+        width: calc(100% - 70px);
+      }
+
+      .A8addRow2Err {
+        .ant-input-outlined {
+          border-color: #ff4d4f;
+        }
+      }
+    }
+
+    .A8addRowTit0 {
+      padding-left: 70px;
+      color: #999;
+      font-size: 12px;
+    }
+
+    .A8addRowTit {
+      opacity: 0;
+      pointer-events: none;
+      transition: top .2s;
+      padding-left: 70px;
+      color: #ff4d4f;
+      position: relative;
+      top: -10px;
+    }
+
+    .A8addRowTitErr {
+      opacity: 1;
+      top: 0;
+    }
+
+    .A8addBtn {
+      margin-top: 40px;
+      text-align: center;
+    }
   }
 }

+ 224 - 5
src/pages/A8dict/index.tsx

@@ -1,12 +1,231 @@
-import React from "react";
+import React, { useCallback, useEffect, useMemo, useState } from "react";
 import styles from "./index.module.scss";
- function A8dict() {
-  
+import { Button, Input, InputNumber, Modal } from "antd";
+import { useDispatch, useSelector } from "react-redux";
+import { A8_APIdel, A8_APIgetList, A8_APIsave } from "@/store/action/A8dict";
+import { A8tableType } from "@/types";
+import MyPopconfirm from "@/components/MyPopconfirm";
+import { MessageFu } from "@/utils/message";
+import { RootState } from "@/store";
+import MyTable from "@/components/MyTable";
+import { A8tableC } from "@/utils/tableData";
+import classNames from "classnames";
+
+type formDataType = {
+  id: number;
+  name: string;
+  sort: number;
+  type: "dict";
+  display: 1;
+};
+
+const formBase: formDataType = {
+  id: 0,
+  name: "",
+  sort: 999,
+  type: "dict",
+  display: 1,
+};
+
+function A8dict() {
+  const dispatch = useDispatch();
+  const getListFu = useCallback(() => {
+    dispatch(A8_APIgetList());
+  }, [dispatch]);
+
+  useEffect(() => {
+    getListFu();
+  }, [getListFu]);
+
+  const tableList = useSelector((state: RootState) => state.A8dict.list);
+
+  const delTableFu = useCallback(
+    async (id: number) => {
+      const res = await A8_APIdel(id);
+      if (res.code === 0) {
+        MessageFu.success("删除成功!");
+        getListFu();
+      }
+    },
+    [getListFu]
+  );
+
+  const tableLastBtn = useMemo(() => {
+    return [
+      {
+        title: "操作",
+        render: (item: A8tableType) => {
+          return item.id === 30 ? (
+            " - "
+          ) : (
+            <>
+              <Button
+                size="small"
+                type="text"
+                onClick={() =>
+                  setFormData({
+                    id: item.id,
+                    name: item.name,
+                    sort: item.sort,
+                    type: "dict",
+                    display: 1,
+                  })
+                }
+              >
+                编辑
+              </Button>
+              <MyPopconfirm txtK="删除" onConfirm={() => delTableFu(item.id)} />
+            </>
+          );
+        },
+      },
+    ];
+  }, [delTableFu]);
+
+  // 表单数据
+  const [formData, setFormData] = useState<formDataType>(formBase);
+
+  //  是否 已经点击过确定
+  const [fileCheck, setFileCheck] = useState(false);
+
+  const formDataChangeFu = useCallback(
+    (key: "name" | "sort", val: string | number) => {
+      setFormData({ ...formData, [key]: val });
+    },
+    [formData]
+  );
+
+  // 关闭弹窗
+  const btnXFu = useCallback(() => {
+    setFileCheck(false);
+    setFormData(formBase);
+  }, []);
+
+  // 点击确定
+  const btnOkFu = useCallback(async () => {
+    setFileCheck(true);
+    if (!formData.name || !formData.sort) return;
+
+    const res = await A8_APIsave({
+      ...formData,
+      id: formData.id < 0 ? null : formData.id,
+    });
+    if (res.code === 0) {
+      let msg = formData.id > 0 ? "编辑成功!" : "新增成功!";
+      MessageFu.success(msg);
+      getListFu();
+    }
+
+    // 关闭弹窗
+    btnXFu();
+  }, [btnXFu, formData, getListFu]);
+
   return (
     <div className={styles.A8dict}>
-       <div className="pageTitle">字典管理</div>
+      <div className="pageTitle">字典管理</div>
+      <div className="A8top">
+        <div>馆藏年代</div>
+        <Button
+          type="primary"
+          onClick={() => setFormData({ ...formBase, id: -1 })}
+        >
+          新增
+        </Button>
+      </div>
+      <div className="A8tableBox">
+        <MyTable
+          yHeight={690}
+          list={tableList}
+          columnsTemp={A8tableC}
+          lastBtn={tableLastBtn}
+          pagingInfo={false}
+        />
+      </div>
+
+      {formData.id ? (
+        <Modal
+          wrapClassName={styles.A8addMo}
+          open={true}
+          title={formData.id > 0 ? "字典编辑" : "字典新增"}
+          footer={
+            [] // 设置footer为空,去掉 取消 确定默认按钮
+          }
+        >
+          <div className="A8addRow">
+            <div className="A8addRow1">
+              <span>* </span>字典值:
+            </div>
+            <div
+              className={classNames(
+                "A8addRow2",
+                fileCheck && !formData.name ? "A8addRow2Err" : ""
+              )}
+            >
+              <Input
+                placeholder="请输入内容"
+                maxLength={50}
+                showCount
+                value={formData.name}
+                onChange={(e) =>
+                  formDataChangeFu("name", e.target.value.replace(/\s+/g, ""))
+                }
+              />
+            </div>
+          </div>
+
+          <div
+            className={classNames(
+              "A8addRowTit",
+              fileCheck && !formData.name ? "A8addRowTitErr" : ""
+            )}
+          >
+            请输入字典值!
+          </div>
+
+          <div className="A8addRow">
+            <div className="A8addRow1">
+              <span>* </span>排序值:
+            </div>
+            <div
+              className={classNames(
+                "A8addRow2",
+                fileCheck && !formData.sort ? "A8addRow2Err" : ""
+              )}
+            >
+              <InputNumber
+                value={formData.sort}
+                onChange={(e) => formDataChangeFu("sort", e!)}
+                style={{ width: 402 }}
+                min={1}
+                max={999}
+                precision={0}
+                placeholder="请输入1~999的数字"
+              />
+            </div>
+          </div>
+          <div className="A8addRowTit0">
+            数字越小,排序越靠前。数字相同时,更新发布的内容排在前面
+          </div>
+          <div
+            className={classNames(
+              "A8addRowTit",
+              fileCheck && !formData.sort ? "A8addRowTitErr" : ""
+            )}
+          >
+            请输入排序值!
+          </div>
+
+          <div className="A8addBtn">
+            <Button type="primary" onClick={btnOkFu}>
+              提交
+            </Button>
+            &emsp;
+            <MyPopconfirm txtK="取消" onConfirm={btnXFu} />
+          </div>
+        </Modal>
+      ) : null}
     </div>
-  )
+  );
 }
 
 const MemoA8dict = React.memo(A8dict);

+ 54 - 0
src/store/action/A3holding.ts

@@ -0,0 +1,54 @@
+import http from "@/utils/http";
+import { AppDispatch } from "..";
+
+/**
+ *馆藏管理-列表
+ */
+
+export const A3_APIgetList = (data: any): any => {
+  return async (dispatch: AppDispatch) => {
+    const res = await http.post("cms/collection/pageList", data);
+    if (res.code === 0) {
+      const obj = {
+        // 待完善
+        list: res.data.records.map((v: any) => ({
+          ...v,
+          activityTime:
+            v.type === "long"
+              ? ""
+              : v.dateStart + " 至 " + (v.dateEnd ? v.dateEnd : "长期有效"),
+        })),
+        total: res.data.total,
+      };
+      dispatch({ type: "A3/getList", payload: obj });
+    }
+  };
+};
+
+/**
+ * 馆藏管理-删除
+ */
+export const A3_APIdel = (id: number) => {
+  return http.get(`cms/collection/removes/${id}`);
+};
+
+/**
+ * 馆藏管理-获取详情
+ */
+export const A3_APIgetInfo = (id: number) => {
+  return http.get(`cms/collection/detail/${id}`);
+};
+
+/**
+ * 馆藏管理-新增、编辑
+ */
+export const A3_APIsave = (data: any) => {
+  return http.post("cms/collection/save", data);
+};
+
+/**
+ * 馆藏管理-修改 展品 图片的名字
+ */
+export const A3_APIchangeImgName = (data: any) => {
+  return http.post("cms/collection/file/update", data);
+};

+ 37 - 0
src/store/action/A8dict.ts

@@ -0,0 +1,37 @@
+import http from "@/utils/http";
+import { AppDispatch } from "..";
+
+/**
+ *字典-列表
+ */
+
+export const A8_APIgetList = (): any => {
+  return async (dispatch: AppDispatch) => {
+    const res = await http.get("cms/dict/getList?type=dict");
+    if (res.code === 0) {
+      dispatch({
+        type: "A8/getList",
+        payload: res.data.map((v: any) => ({
+          ...v,
+          updateTime: v.id === 30 ? " - " : v.updateTime,
+          creatorName: v.id === 30 ? " - " : v.creatorName,
+          sort: v.id === 30 ? " - " : v.sort,
+        })),
+      });
+    }
+  };
+};
+
+/**
+ * 字典-删除
+ */
+export const A8_APIdel = (id: number) => {
+  return http.get(`cms/dict/removes/${id}`);
+};
+
+/**
+ * 字典-新增、编辑
+ */
+export const A8_APIsave = (data: any) => {
+  return http.post("cms/dict/save", data);
+};

+ 28 - 0
src/store/reducer/A3holding.ts

@@ -0,0 +1,28 @@
+import { A3tableType } from "@/types";
+
+// 初始化状态
+const initState = {
+  // 列表数据
+  tableInfo: {
+    list: [] as A3tableType[],
+    total: 0,
+  },
+};
+
+// 定义 action 类型
+type Props = {
+  type: "A3/getList";
+  payload: { list: A3tableType[]; total: number };
+};
+
+// reducer
+export default function Reducer(state = initState, action: Props) {
+  switch (action.type) {
+    // 获取列表数据
+    case "A3/getList":
+      return { ...state, tableInfo: action.payload };
+
+    default:
+      return state;
+  }
+}

+ 25 - 0
src/store/reducer/A8dict.ts

@@ -0,0 +1,25 @@
+import { A8tableType } from "@/types";
+
+// 初始化状态
+const initState = {
+  // 列表数据
+  list: [] as A8tableType[],
+};
+
+// 定义 action 类型
+type Props = {
+  type: "A8/getList";
+  payload: A8tableType[];
+};
+
+// reducer
+export default function Reducer(state = initState, action: Props) {
+  switch (action.type) {
+    // 获取列表数据
+    case "A8/getList":
+      return { ...state, list: action.payload };
+
+    default:
+      return state;
+  }
+}

+ 4 - 0
src/store/reducer/index.ts

@@ -5,6 +5,8 @@ import { combineReducers } from "redux";
 import A0Layout from "./layout";
 import A1event from "./A1event";
 import A2exhibition from "./A2exhibition";
+import A3holding from "./A3holding";
+import A8dict from "./A8dict";
 import Z1user from "./Z1user";
 import Z2log from "./Z2log";
 
@@ -13,6 +15,8 @@ const rootReducer = combineReducers({
   A0Layout,
   A1event,
   A2exhibition,
+  A3holding,
+  A8dict,
   Z1user,
   Z2log,
 });

+ 23 - 0
src/types/api/A3holding.d.ts

@@ -0,0 +1,23 @@
+export type A3tableType = {
+  author: string;
+  createTime: string;
+  // creatorId?: any;
+  creatorName: string;
+  // datePublish?: any;
+  dictAge: string;
+  dictAgeId: number;
+  digest: string;
+  display: number;
+  fileIds: string;
+  fileName: string;
+  filePath: string;
+  // files?: any;
+  id: number;
+  name: string;
+  rtf: string;
+  size: string;
+  sort: number;
+  thumb: string;
+  type: string;
+  updateTime: string;
+};

+ 7 - 0
src/types/api/A8dict.d.ts

@@ -0,0 +1,7 @@
+export type A8tableType =  {
+	id: number;
+	name: string;
+	rtf: string;
+	sort: number;
+	type: string;
+}

+ 2 - 0
src/types/index.d.ts

@@ -1,5 +1,7 @@
 export * from './api/layot'
 export * from './api/A1event'
 export * from './api/A2exhibition'
+export * from './api/A3holding'
+export * from './api/A8dict'
 export * from './api/Z1user'
 export * from './api/Z2log'

+ 19 - 0
src/utils/tableData.ts

@@ -36,6 +36,25 @@ export const A2tableC = [
   ["txtChange", "状态", "display", { 0: "不发布", 1: "发布" }],
 ];
 
+export const A3tableC = [
+  ["txt", "名称", "name"],
+  ["txt", "类别", "type"],
+  ["txt", "年代", "dictAge"],
+  ["text", "摘要", "digest", 50],
+  ["img", "封面", "thumb"],
+  ["txt", "最近编辑日期", "updateTime"],
+  ["txt", "编辑人", "creatorName"],
+  ["txt", "排序值", "sort"],
+  ["txtChange", "状态", "display", { 0: "不发布", 1: "发布" }],
+];
+
+export const A8tableC = [
+  ["txt", "字典值", "name"],
+  ["txt", "最近编辑日期", "updateTime"],
+  ["txt", "编辑人", "creatorName"],
+  ["txt", "排序值", "sort"],
+];
+
 export const Z1tableC = [
   ["txt", "用户名", "userName"],
   ["txtChange", "角色", "isAdmin", { 1: "管理员", 0: "普通成员" }],