Jelajahi Sumber

feat(开发);

lanxin 2 bulan lalu
induk
melakukan
f1feba6c78
100 mengubah file dengan 11041 tambahan dan 5122 penghapusan
  1. 6352 0
      public/4dage.js
  2. 2 2
      public/index.html
  3. 34 0
      public/model.html
  4. TEMPAT SAMPAH
      src/assets/img/eye.png
  5. TEMPAT SAMPAH
      src/assets/img/loginBac.jpg
  6. TEMPAT SAMPAH
      src/assets/img/loginBac.png
  7. TEMPAT SAMPAH
      src/assets/img/loginPw.png
  8. TEMPAT SAMPAH
      src/assets/img/loginUser.png
  9. TEMPAT SAMPAH
      src/assets/img/logo.png
  10. TEMPAT SAMPAH
      src/assets/img/tag.png
  11. 14 1
      src/assets/styles/base.css
  12. 1 1
      src/assets/styles/base.less
  13. 3 4
      src/components/ImageLazy/index.tsx
  14. 20 26
      src/components/LookDom/index.tsx
  15. 7 0
      src/components/MyTable/index.module.scss
  16. 51 20
      src/components/MyTable/index.tsx
  17. 0 149
      src/components/UpXlsx.tsx
  18. 114 122
      src/components/ZRichText/index.tsx
  19. 32 20
      src/components/ZRichTexts/index.tsx
  20. 20 33
      src/components/ZupOne/index.tsx
  21. 30 16
      src/components/ZupTypes/index.tsx
  22. 1 1
      src/index.tsx
  23. 17 5
      src/pages/A1manage/A1add/index.module.scss
  24. 230 0
      src/pages/A1banner/A1add/index.tsx
  25. 7 0
      src/pages/A1banner/data.ts
  26. 20 0
      src/pages/A1banner/index.module.scss
  27. 140 0
      src/pages/A1banner/index.tsx
  28. 0 94
      src/pages/A1manage/A1Import/index.module.scss
  29. 0 179
      src/pages/A1manage/A1Import/index.tsx
  30. 0 402
      src/pages/A1manage/A1add/index.tsx
  31. 0 225
      src/pages/A1manage/A1ying/A1Yadd.tsx
  32. 0 104
      src/pages/A1manage/A1ying/index.module.scss
  33. 0 176
      src/pages/A1manage/A1ying/index.tsx
  34. 0 19
      src/pages/A1manage/data.ts
  35. 0 271
      src/pages/A1manage/index.tsx
  36. 0 202
      src/pages/A2classify/A2add.tsx
  37. 0 113
      src/pages/A2classify/A2add2.tsx
  38. 0 18
      src/pages/A2classify/data.ts
  39. 0 123
      src/pages/A2classify/index.module.scss
  40. 0 337
      src/pages/A2classify/index.tsx
  41. 65 0
      src/pages/A2introduction/index.module.scss
  42. 114 0
      src/pages/A2introduction/index.tsx
  43. 65 0
      src/pages/A3map/index.module.scss
  44. 114 0
      src/pages/A3map/index.tsx
  45. 0 163
      src/pages/A3recommend/A3add.tsx
  46. 0 7
      src/pages/A3recommend/data.ts
  47. 0 78
      src/pages/A3recommend/index.module.scss
  48. 0 181
      src/pages/A3recommend/index.tsx
  49. 0 76
      src/pages/A4iosUser/A4ip/index.module.scss
  50. 0 158
      src/pages/A4iosUser/A4ip/index.tsx
  51. 0 21
      src/pages/A4iosUser/data.ts
  52. 0 144
      src/pages/A4iosUser/index.tsx
  53. 110 0
      src/pages/A4news/A4add/index.module.scss
  54. 298 0
      src/pages/A4news/A4add/index.tsx
  55. 7 0
      src/pages/A4news/data.ts
  56. 24 0
      src/pages/A4news/index.module.scss
  57. 149 0
      src/pages/A4news/index.tsx
  58. 116 0
      src/pages/A5activity/A5add/index.module.scss
  59. 374 0
      src/pages/A5activity/A5add/index.tsx
  60. 7 0
      src/pages/A5activity/data.ts
  61. 4 10
      src/pages/A5bookAudit/index.module.scss
  62. 149 0
      src/pages/A5activity/index.tsx
  63. 0 125
      src/pages/A5bookAudit/A5look/index.module.scss
  64. 0 318
      src/pages/A5bookAudit/A5look/index.tsx
  65. 0 25
      src/pages/A5bookAudit/data.ts
  66. 0 161
      src/pages/A5bookAudit/index.tsx
  67. 110 0
      src/pages/A6exhibition/A6add/index.module.scss
  68. 279 0
      src/pages/A6exhibition/A6add/index.tsx
  69. 7 0
      src/pages/A6exhibition/data.ts
  70. 10 9
      src/pages/A1manage/index.module.scss
  71. 168 0
      src/pages/A6exhibition/index.tsx
  72. 0 108
      src/pages/A6remarkAudit/A6audit.tsx
  73. 0 79
      src/pages/A6remarkAudit/index.module.scss
  74. 0 121
      src/pages/A6remarkAudit/index.tsx
  75. 19 7
      src/pages/A7notice/A7add/index.module.scss
  76. 333 0
      src/pages/A7collection/A7add/index.tsx
  77. 7 0
      src/pages/A7collection/data.ts
  78. 10 9
      src/pages/A4iosUser/index.module.scss
  79. 168 0
      src/pages/A7collection/index.tsx
  80. 0 182
      src/pages/A7notice/A7add/index.tsx
  81. 0 63
      src/pages/A7notice/A7type/index.module.scss
  82. 0 171
      src/pages/A7notice/A7type/index.tsx
  83. 0 6
      src/pages/A7notice/data.ts
  84. 0 45
      src/pages/A7notice/index.module.scss
  85. 0 192
      src/pages/A7notice/index.tsx
  86. 109 0
      src/pages/B1reserve1/B1look/index.module.scss
  87. 95 0
      src/pages/B1reserve1/B1look/index.tsx
  88. 7 0
      src/pages/B1reserve1/data.ts
  89. 20 0
      src/pages/B1reserve1/index.module.scss
  90. 107 0
      src/pages/B1reserve1/index.tsx
  91. 109 0
      src/pages/B2reserve2/B2look/index.module.scss
  92. 95 0
      src/pages/B2reserve2/B2look/index.tsx
  93. 7 0
      src/pages/B2reserve2/data.ts
  94. 20 0
      src/pages/B2reserve2/index.module.scss
  95. 107 0
      src/pages/B2reserve2/index.tsx
  96. 86 0
      src/pages/C1reserveOpt/C1NoTime.tsx
  97. 96 0
      src/pages/C1reserveOpt/C1edit/index.module.scss
  98. 295 0
      src/pages/C1reserveOpt/C1edit/index.tsx
  99. 86 0
      src/pages/C1reserveOpt/C1xuZhi.tsx
  100. 0 0
      src/pages/C1reserveOpt/data.ts

File diff ditekan karena terlalu besar
+ 6352 - 0
public/4dage.js


+ 2 - 2
public/index.html

@@ -21,7 +21,7 @@
       work correctly both with client-side routing and a non-root public URL.
       Learn how to configure a non-root public URL by running `npm run build`.
     -->
-    <title>刘少奇同志纪念馆数字图书馆-管理后台</title>
+    <title>克拉玛依市博物馆-管理后台</title>
   </head>
   <body>
     <noscript>You need to enable JavaScript to run this app.</noscript>
@@ -40,6 +40,6 @@
 
   <script>
     // 图书影印模块-显示bookId
-    const isBookIdShow = true
+    const isBookIdShow = false
   </script>
 </html>

+ 34 - 0
public/model.html

@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="UTF-8" />
+    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+    <script src="./4dage.js"></script>
+    <title>Document</title>
+    <style>
+      html {
+        overflow: hidden;
+      }
+    </style>
+  </head>
+
+  <body>
+    <div id="ui"></div>
+    <script>
+      let m = getQueryVariable('m')
+
+      // window.autoRotate = true; // 是否自动旋转
+
+      // fdage.embed( number, {
+      fdage.embed(m, {
+        transparentBackground: true,
+        width: 800,
+        height: 600,
+        autoStart: true,
+        fullFrame: true,
+        pagePreset: false
+      })
+    </script>
+  </body>
+</html>

TEMPAT SAMPAH
src/assets/img/eye.png


TEMPAT SAMPAH
src/assets/img/loginBac.jpg


TEMPAT SAMPAH
src/assets/img/loginBac.png


TEMPAT SAMPAH
src/assets/img/loginPw.png


TEMPAT SAMPAH
src/assets/img/loginUser.png


TEMPAT SAMPAH
src/assets/img/logo.png


TEMPAT SAMPAH
src/assets/img/tag.png


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

@@ -8,7 +8,8 @@ html {
   font-size: 14px;
 }
 body {
-  font: 1em/1.4 'Microsoft Yahei', 'PingFang SC', 'Avenir', 'Segoe UI', 'Hiragino Sans GB', 'STHeiti', 'Microsoft Sans Serif', 'WenQuanYi Micro Hei', sans-serif;
+  font: 1em/1.4 'Microsoft Yahei', 'PingFang SC', 'Avenir', 'Segoe UI', 'Hiragino Sans GB',
+    'STHeiti', 'Microsoft Sans Serif', 'WenQuanYi Micro Hei', sans-serif;
   height: 100%;
   color: black;
 }
@@ -101,6 +102,15 @@ textarea {
   display: flex;
   justify-content: center;
 }
+#root .tableSort {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  & > button {
+    border: none;
+    color: var(--themeColor);
+  }
+}
 #root .ant-image {
   display: none;
 }
@@ -180,3 +190,6 @@ textarea {
   max-height: 500px !important;
   overflow-y: auto !important;
 }
+.ant-select-item-option-selected {
+  background-color: rgba(0, 0, 0, 0.04) !important;
+}

+ 1 - 1
src/assets/styles/base.less

@@ -46,7 +46,7 @@ textarea {
 /* 主题色 */
 :root {
   --themeColor: #a89170;
-  --themeColor2: #272727;
+  --themeColor2: #534638;
 }
 
 /* 找不到页面 */

+ 3 - 4
src/components/ImageLazy/index.tsx

@@ -1,6 +1,5 @@
 import React, { useCallback, useState } from 'react'
 import styles from './index.module.scss'
-import { baseURL } from '@/utils/http'
 import imgLoding from '@/assets/img/loading.gif'
 import imgErr from '@/assets/img/IMGerror.png'
 import { EyeOutlined } from '@ant-design/icons'
@@ -29,9 +28,9 @@ function ImageLazy({ width = 100, height = 100, src, srcBig, noLook, offline = f
   const lookBigImg = useCallback(() => {
     store.dispatch({
       type: 'layout/lookBigImg',
-      payload: { url: offline ? src : srcBig ? baseURL + srcBig : baseURL + src, show: true }
+      payload: { url: srcBig ? srcBig : src, show: true }
     })
-  }, [offline, src, srcBig])
+  }, [src, srcBig])
 
   return (
     <div className={styles.ImageLazy} style={{ width: width, height: height }}>
@@ -39,7 +38,7 @@ function ImageLazy({ width = 100, height = 100, src, srcBig, noLook, offline = f
         <Image
           lazy
           onLoad={onLoad}
-          src={src ? (offline ? src : baseURL + src) : ''}
+          src={src}
           placeholder={<img src={imgLoding} alt='' />}
           fallback={<img src={imgErr} alt='' />}
           fit='cover'

+ 20 - 26
src/components/LookDom/index.tsx

@@ -1,41 +1,35 @@
 /* eslint-disable jsx-a11y/iframe-has-title */
-import React from "react";
-import { CloseCircleOutlined } from "@ant-design/icons";
-import styles from "./index.module.scss";
-import { useSelector } from "react-redux";
-import store, { RootState } from "@/store";
-import { baseURL } from "@/utils/http";
+import React from 'react'
+import { CloseCircleOutlined } from '@ant-design/icons'
+import styles from './index.module.scss'
+import { useSelector } from 'react-redux'
+import store, { RootState } from '@/store'
 function LookDom() {
-  const { src, type, flag } = useSelector(
-    (state: RootState) => state.A0Layout.lookDom
-  );
+  const { src, type, flag } = useSelector((state: RootState) => state.A0Layout.lookDom)
   return (
-    <div
-      className={styles.LookDom}
-      style={src ? { opacity: 1, pointerEvents: "auto" } : {}}
-    >
+    <div className={styles.LookDom} style={src ? { opacity: 1, pointerEvents: 'auto' } : {}}>
       {src ? (
         <>
-          {type === "video" ? (
-            <div className="viedoBox">
-              <video autoPlay controls src={flag ? src : baseURL + src}></video>
+          {type === 'video' ? (
+            <div className='viedoBox'>
+              <video autoPlay controls src={src}></video>
             </div>
-          ) : type === "audio" ? (
-            <div className="audioBox">
-              <audio autoPlay controls src={flag ? src : baseURL + src}></audio>
+          ) : type === 'audio' ? (
+            <div className='audioBox'>
+              <audio autoPlay controls src={src}></audio>
             </div>
           ) : (
-            <div className="modelBox">
+            <div className='modelBox'>
               <iframe src={`model.html?m=${src}`}></iframe>
             </div>
           )}
 
           <div
-            className="close"
+            className='close'
             onClick={() =>
               store.dispatch({
-                type: "layout/lookDom",
-                payload: { src: "", type: "", flag: false },
+                type: 'layout/lookDom',
+                payload: { src: '', type: '', flag: false }
               })
             }
           >
@@ -44,9 +38,9 @@ function LookDom() {
         </>
       ) : null}
     </div>
-  );
+  )
 }
 
-const MemoLookDom = React.memo(LookDom);
+const MemoLookDom = React.memo(LookDom)
 
-export default MemoLookDom;
+export default MemoLookDom

+ 7 - 0
src/components/MyTable/index.module.scss

@@ -11,6 +11,13 @@
           a {
             color: var(--themeColor) !important;
           }
+
+          .ant-btn {
+            background-color: transparent;
+            span:hover {
+              color: var(--themeColor) !important;
+            }
+          }
         }
       }
       .tabx {

+ 51 - 20
src/components/MyTable/index.tsx

@@ -1,9 +1,11 @@
 import React, { useCallback, useEffect, useMemo } from 'react'
 import styles from './index.module.scss'
-import { Table } from 'antd'
+import { Table, Button } from 'antd'
 import ImageLazy from '../ImageLazy'
-
+import { A1_moveUp, A1_moveDown } from '../../store/action/A1banner'
+import { useDispatch } from 'react-redux'
 type Props = {
+  myKey?: string //表格的key
   yHeight?: number //设置表格的高度
   list: any //表格数据
   columnsTemp: any[][] //表格展示
@@ -51,8 +53,10 @@ function MyTable({
   classKey = '',
   merge,
   myTitle,
-  isNull = '(空)'
+  isNull = '(空)',
+  myKey
 }: Props) {
+  const dispatch = useDispatch()
   useEffect(() => {
     const dom = document.querySelector(`.MyTable${classKey} .ant-table-body`) as HTMLDivElement
 
@@ -73,34 +77,34 @@ function MyTable({
     (v: any) => {
       /**
        * index:序号
-       * txt:正常数据
+       * txtNormal:正常数据
+       * txt:判断显示不同字段
        * img:图片
        * txtChange:判断显示不同字段
        * text:文字比较多的情况
+       * sort:排序
        */
 
       const obj = {
         index: (_: any, __: any, index: number) => index + 1 + (pageNum - 1) * pageSize,
-        txt: (item: any) =>
-          v[3] && !item[v[2]] ? (
-            <div dangerouslySetInnerHTML={{ __html: v[3] }}></div>
-          ) : (
-            item[v[2]] || isNull
-          ),
-        img: (item: any) =>
-          v[3] && !item[v[2]] ? (
-            <div dangerouslySetInnerHTML={{ __html: v[3] }}></div>
-          ) : (
+        txtNormal: (item: any) => item[v[2]] || isNull,
+        txt: (item: any) => {
+          return item.status === 0 ? item[v[3]] || isNull : item[v[2]] || isNull
+        },
+        img: (item: any) => {
+          console.log(item.status, item[v[2]], v[2], v, 'txt')
+          return (
             <div className='tableImgAuto'>
               <ImageLazy
                 width={60}
                 height={60}
-                srcBig={item.thumbPc}
-                src={item[v[2]] || item.thumb}
-                offline={(item[v[2]] || item.thumb || '').includes('http')}
+                srcBig={item.imgB}
+                src={item.status === 0 ? item[v[3]] || item.imgThB : item[v[2]] || item.imgThB}
+                offline={(item.status === 0 ? item[v[3]] : item[v[2]] || '').includes('http')}
               />
             </div>
-          ),
+          )
+        },
         txtChange: (item: any) => Reflect.get(v[3], item[v[2]]) || v[4] || isNull,
         text: (item: any) => {
           let tempCom: any = item[v[2]] || isNull
@@ -120,12 +124,39 @@ function MyTable({
           }
 
           return tempCom
+        },
+        sort: (item: any, record: any, index: number) => {
+          const isFirst = index === 0
+          const isLast = index === list.length - 1
+          const handlesort = (type: 'up' | 'down') => {
+            if (type === 'up') {
+              dispatch(A1_moveUp(index))
+            } else {
+              dispatch(A1_moveDown(index))
+            }
+          }
+          return (
+            <div className='tableSort'>
+              <Button
+                style={{ display: isFirst ? 'none' : 'block', backgroundColor: 'transparent' }}
+                onClick={() => handlesort('up')}
+              >
+                上移
+              </Button>
+              <Button
+                style={{ display: isLast ? 'none' : 'block', backgroundColor: 'transparent' }}
+                onClick={() => handlesort('down')}
+              >
+                下移
+              </Button>
+            </div>
+          )
         }
       }
 
       return Reflect.get(obj, v[0])
     },
-    [isNull, pageNum, pageSize]
+    [dispatch, isNull, list.length, pageNum, pageSize]
   )
 
   const columns = useMemo(() => {
@@ -150,7 +181,7 @@ function MyTable({
       scroll={{ y: yHeight ? yHeight : '' }}
       dataSource={list}
       columns={[...columns, ...lastBtn]}
-      rowKey='id'
+      rowKey={myKey ? myKey : 'id'}
       pagination={
         pagingInfo
           ? {

+ 0 - 149
src/components/UpXlsx.tsx

@@ -1,149 +0,0 @@
-import { API_upFile } from '@/store/action/layout'
-import { A1tableType } from '@/types'
-import { fileDomInitialFu } from '@/utils/domShow'
-import { MessageFu } from '@/utils/message'
-import { notification } from 'antd'
-import React, { useCallback, useRef } from 'react'
-import { forwardRef, useImperativeHandle } from 'react'
-
-type Props = {
-  url: string
-  xlsxResInfoFu: (arr: A1tableType[]) => void
-  ref: any //当前自己的ref,给父组件调用
-  dirCode: string
-  ISBNArr: string[] //ISBN编号集合,用来过滤表格
-}
-
-function UpXlsx({ url, xlsxResInfoFu, dirCode, ISBNArr }: Props, ref: any) {
-  const [api, contextHolder] = notification.useNotification()
-
-  // 点击上传附件按钮
-  const myInput = useRef<HTMLInputElement>(null)
-
-  // 上传附件的处理函数
-  const handeUpPhoto = useCallback(
-    async (e: React.ChangeEvent<HTMLInputElement>) => {
-      if (e.target.files) {
-        // 拿到files信息
-        const filesInfo = e.target.files[0]
-
-        // 校验格式
-        if (!filesInfo.name.endsWith('.xlsx')) {
-          e.target.value = ''
-          return MessageFu.warning('只支持.xlsx格式!')
-        }
-
-        // 校验大小
-        if (filesInfo.size > 5 * 1024 * 1024) {
-          e.target.value = ''
-          return MessageFu.warning('最大支持5M!')
-        }
-        // 创建FormData对象
-        const fd = new FormData()
-        // 把files添加进FormData对象(‘photo’为后端需要的字段)
-        fd.append('type', 'doc')
-        fd.append('dirCode', dirCode)
-        fd.append('file', filesInfo)
-        fd.append('isDb', 'false')
-
-        e.target.value = ''
-
-        const res = await API_upFile(fd, url)
-
-        try {
-          if (res.code === 0) {
-            MessageFu.success('上传成功!')
-            // const { msg, error } = res.data
-
-            // const errorTit = error && error.length ? JSON.stringify(error) : ''
-
-            // api.info({
-            //   message: msg,
-            //   description: errorTit,
-            //   duration: 0,
-            //   placement: 'topLeft'
-            // })
-
-            const arrTemp: A1tableType[] = res.data || []
-
-            const moreTit: number[] = []
-
-            const arr = arrTemp.filter((item, ind) => {
-              const indRes = ind === arrTemp.findIndex(item2 => item.num === item2.num)
-
-              if (!indRes) moreTit.push(ind)
-              return indRes
-            })
-
-            if (moreTit && moreTit.length) {
-              const moreTitTxt = moreTit.map(v => v + 1)
-
-              api.warning({
-                message: `第${JSON.stringify(moreTitTxt)}行ISBN编号重复,已过滤`,
-                duration: 0,
-                placement: 'bottomLeft'
-              })
-            }
-
-            if (ISBNArr.length + arr.length > 50) {
-              fileDomInitialFu()
-              return MessageFu.warning(
-                `最多支持50条数据,您本次可录入数据条数为${50 - ISBNArr.length}条!`
-              )
-            }
-
-            const temp: string[] = []
-            const arrRes: A1tableType[] = []
-
-            arr.forEach((v: any, i: number) => {
-              v.id = Date.now() + i
-              if (ISBNArr.includes(v.num) && v.num !== '') {
-                temp.push(v.num)
-              } else {
-                arrRes.push(v)
-              }
-            })
-
-            xlsxResInfoFu(arrRes)
-
-            if (temp.length) {
-              api.warning({
-                message: 'ISBN编号' + JSON.stringify(temp) + '重复,已过滤',
-                duration: 0,
-                placement: 'bottomLeft'
-              })
-            }
-          }
-          fileDomInitialFu()
-        } catch (error) {
-          fileDomInitialFu()
-        }
-      }
-    },
-    [api, dirCode, ISBNArr, url, xlsxResInfoFu]
-  )
-
-  const myInputClickFu = useCallback(() => {
-    myInput.current?.click()
-  }, [])
-
-  // 可以让父组件调用子组件的方法
-  useImperativeHandle(ref, () => ({
-    myInputClickFu
-  }))
-
-  return (
-    <>
-      {contextHolder}
-      <input
-        id='upInput'
-        type='file'
-        accept='.xlsx'
-        ref={myInput}
-        onChange={e => handeUpPhoto(e)}
-      />
-    </>
-  )
-}
-
-export default forwardRef(UpXlsx)

+ 114 - 122
src/components/ZRichText/index.tsx

@@ -1,216 +1,208 @@
-import React, {
-  useCallback,
-  useEffect,
-  useMemo,
-  useRef,
-  useState,
-} from "react";
-import styles from "./index.module.scss";
+import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
+import styles from './index.module.scss'
 
 // 引入编辑器组件
 
 // 安装---npm install braft-editor --save --force
 // npm install braft-utils --save --force
-import { ContentUtils } from "braft-utils";
-import BraftEditor from "braft-editor";
+import { ContentUtils } from 'braft-utils'
+import BraftEditor from 'braft-editor'
 // 引入编辑器样式
-import "braft-editor/dist/index.css";
+import 'braft-editor/dist/index.css'
 
-import classNames from "classnames";
-import { MessageFu } from "@/utils/message";
-import { fileDomInitialFu } from "@/utils/domShow";
-import { baseURL } from "@/utils/http";
+import classNames from 'classnames'
+import { MessageFu } from '@/utils/message'
+import { fileDomInitialFu } from '@/utils/domShow'
+import { baseURL } from '@/utils/http'
 
-import { forwardRef, useImperativeHandle } from "react";
-import { API_upFile } from "@/store/action/layout";
+import { forwardRef, useImperativeHandle } from 'react'
+import { API_upFile } from '@/store/action/layout'
 
 type Props = {
-  check: boolean; //表单校验,为fasle表示不校验
-  dirCode: string; //文件的code码
-  isLook: boolean; //是否是查看进来
-  ref: any; //当前自己的ref,给父组件调用
-  myUrl: string; //上传的api地址
-  full?: boolean;
-};
+  check: boolean //表单校验,为fasle表示不校验
+  dirCode: string //文件的code码
+  isLook: boolean //是否是查看进来
+  ref: any //当前自己的ref,给父组件调用
+  myUrl: string //上传的api地址
+  full?: boolean
+}
 
 function ZRichText({ check, dirCode, isLook, myUrl, full }: Props, ref: any) {
   // 添加 上传 图片的dom
   useEffect(() => {
     setTimeout(() => {
-      const dom = document.querySelector(".bf-controlbar")!;
-      const div = document.createElement("div");
-      div.className = "upImgBox";
+      const dom = document.querySelector('.bf-controlbar')!
+      const div = document.createElement('div')
+      div.className = 'upImgBox'
       // div.title = "上传图片";
-      div.innerHTML = "上传图片/视频";
+      div.innerHTML = '上传图片/视频'
       div.onclick = async () => {
-        myInput.current?.click();
-      };
-      dom.appendChild(div);
-    }, 20);
+        myInput.current?.click()
+      }
+      dom.appendChild(div)
+    }, 20)
 
     // 监听 富文本 的 class 变化,在全屏的时候会 富文本会添加上 fullscreen 的类
     // 修复顶部样式冲突问题
 
-    const editorDom = document.querySelector(".bf-container") as HTMLDivElement;
+    const editorDom = document.querySelector('.bf-container') as HTMLDivElement
 
     const observer = new MutationObserver(() => {
       // console.log("change");
-      const dom = document.querySelector(".layoutRightTop") as HTMLDivElement;
+      const dom = document.querySelector('.layoutRightTop') as HTMLDivElement
 
-      if (editorDom.className.includes("fullscreen")) dom.style.zIndex = "-1";
-      else dom.style.zIndex = "100";
-    });
+      if (editorDom.className.includes('fullscreen')) dom.style.zIndex = '-1'
+      else dom.style.zIndex = '100'
+    })
 
     observer.observe(editorDom, {
-      attributes: true,
-    });
+      attributes: true
+    })
 
     // 销毁监听
     return () => {
-      observer.disconnect();
-    };
-  }, []);
+      observer.disconnect()
+    }
+  }, [])
 
   useEffect(() => {
-    const controlbarDom = document.querySelectorAll(".txtBox .bf-controlbar ");
-    const contentDom = document.querySelectorAll(".txtBox .bf-content ");
+    const controlbarDom = document.querySelectorAll('.txtBox .bf-controlbar ')
+    const contentDom = document.querySelectorAll('.txtBox .bf-content ')
     if (controlbarDom) {
       controlbarDom.forEach((v: any) => {
-        v.style.display = isLook ? "none" : "block";
-      });
+        v.style.display = isLook ? 'none' : 'block'
+      })
       contentDom.forEach((v: any) => {
-        v.style.height = isLook ? "100%" : "";
-      });
+        v.style.height = isLook ? '100%' : ''
+      })
     }
-  }, [isLook]);
+  }, [isLook])
 
   // 编辑器文本
   const [editorValue, setEditorValue] = useState(
     // 初始内容
-    BraftEditor.createEditorState("")
-  );
+    BraftEditor.createEditorState('')
+  )
 
   // 判断 富文本是否为空
   const isTxtFlag = useMemo(() => {
-    const txt: string = editorValue.toHTML();
-    if (
-      txt.replaceAll("<p>", "").replaceAll("</p>", "").replaceAll(" ", "") ===
-      ""
-    ) {
-      return true;
-    } else return false;
-  }, [editorValue]);
+    const txt: string = editorValue.toHTML()
+    if (txt.replaceAll('<p>', '').replaceAll('</p>', '').replaceAll(' ', '') === '') {
+      return true
+    } else return false
+  }, [editorValue])
 
-  const myInput = useRef<HTMLInputElement>(null);
+  const myInput = useRef<HTMLInputElement>(null)
 
   // 上传图片
   const handeUpPhoto = useCallback(
     async (e: React.ChangeEvent<HTMLInputElement>) => {
       if (e.target.files) {
         // 拿到files信息
-        const filesInfo = e.target.files[0];
-
-        let type = ["image/jpeg", "image/png", "video/mp4"];
-        let size = 5;
-        let txt = "图片只支持png、jpg和jpeg格式!";
-        let txt2 = "图片最大支持5M!";
-
-        const isVideoFlag = filesInfo.name.endsWith(".mp4");
-
-        // 校验格式
-        if (!type.includes(filesInfo.type)) {
-          e.target.value = "";
-          if (isVideoFlag) {
-            // 上传视频
-            size = 500;
-            txt = "视频只支持mp4格式!";
-            txt2 = "视频最大支持500M!";
-          }
-
-          return MessageFu.warning(txt);
+        const filesInfo = e.target.files[0]
+
+        const isVideo = filesInfo.name.endsWith('.mp4')
+
+        const mediaConfig = isVideo
+          ? {
+              types: ['video/mp4'],
+              maxSize: 500,
+              errorText: '视频只支持mp4格式!',
+              errorSizeText: '视频最大支持500M!',
+              mediaType: 'VIDEO'
+            }
+          : {
+              types: ['image/jpeg', 'image/png'],
+              maxSize: 5,
+              errorText: '图片只支持png、jpg和jpeg格式!',
+              errorSizeText: '图片最大支持5M!',
+              mediaType: 'IMAGE'
+            }
+
+        // 格式校验
+        if (!mediaConfig.types.includes(filesInfo.type)) {
+          e.target.value = ''
+          return MessageFu.warning(mediaConfig.errorText)
         }
-        // 校验大小
-        if (filesInfo.size > size * 1024 * 1024) {
-          e.target.value = "";
-          return MessageFu.warning(txt2);
+
+        // 大小校验
+        if (filesInfo.size > mediaConfig.maxSize) {
+          e.target.value = ''
+          return MessageFu.warning(mediaConfig.errorSizeText)
         }
+
         // 创建FormData对象
-        const fd = new FormData();
+        const fd = new FormData()
         // 把files添加进FormData对象(‘photo’为后端需要的字段)
-        fd.append("type", isVideoFlag ? "video" : "img");
-        fd.append("dirCode", dirCode);
-        fd.append("file", filesInfo);
+        fd.append('type', isVideo ? 'video' : 'img')
+        fd.append('dirCode', dirCode)
+        fd.append('file', filesInfo)
 
-        e.target.value = "";
+        e.target.value = ''
 
         try {
-          const res = await API_upFile(fd, myUrl);
+          const res = await API_upFile(fd, myUrl)
           if (res.code === 0) {
-            MessageFu.success("上传成功!");
+            MessageFu.success('上传成功!')
             // 在光标位置插入图片
             const newTxt = ContentUtils.insertMedias(editorValue, [
               {
-                type: "IMAGE",
-                url: baseURL + res.data.filePath,
-              },
-            ]);
+                type: mediaConfig.mediaType,
+                url: baseURL + res.data.filePath
+              }
+            ])
 
-            setEditorValue(newTxt);
+            setEditorValue(newTxt)
           }
-          fileDomInitialFu();
+          fileDomInitialFu()
         } catch (error) {
-          fileDomInitialFu();
+          fileDomInitialFu()
         }
       }
     },
     [dirCode, editorValue, myUrl]
-  );
+  )
 
   // 让父组件调用的 回显 富文本
   const ritxtShowFu = useCallback((val: string) => {
-    setEditorValue(BraftEditor.createEditorState(val));
-  }, []);
+    setEditorValue(BraftEditor.createEditorState(val))
+  }, [])
 
   // 让父组件调用的返回 富文本信息 和 表单校验 isTxtFlag为ture表示未通过校验
   const fatherBtnOkFu = useCallback(() => {
-    return { val: editorValue.toHTML(), flag: isTxtFlag };
-  }, [editorValue, isTxtFlag]);
+    return { val: editorValue.toHTML(), flag: isTxtFlag }
+  }, [editorValue, isTxtFlag])
 
   // 可以让父组件调用子组件的方法
   useImperativeHandle(ref, () => ({
     ritxtShowFu,
-    fatherBtnOkFu,
-  }));
+    fatherBtnOkFu
+  }))
 
   return (
-    <div className={styles.ZRichText} style={{ width: full ? "100%" : "" }}>
+    <div className={styles.ZRichText} style={{ width: full ? '100%' : '' }}>
       <input
-        id="upInput"
-        type="file"
-        accept=".png,.jpg,.jpeg,.mp4"
+        id='upInput'
+        type='file'
+        accept='.png,.jpg,.jpeg,.mp4'
         ref={myInput}
-        onChange={(e) => handeUpPhoto(e)}
+        onChange={e => handeUpPhoto(e)}
       />
 
-      <div className="txtBox">
+      <div className='txtBox'>
         <BraftEditor
           readOnly={isLook}
-          placeholder="请输入内容"
+          placeholder='请输入内容'
           value={editorValue}
-          onChange={(e) => setEditorValue(e)}
-          imageControls={["remove"]}
+          onChange={e => setEditorValue(e)}
+          imageControls={['remove']}
         />
       </div>
-      <div
-        className={classNames(
-          "noUpThumb",
-          check && isTxtFlag ? "noUpThumbAc" : ""
-        )}
-      >
+      <div className={classNames('noUpThumb', check && isTxtFlag ? 'noUpThumbAc' : '')}>
         请输入正文!
       </div>
     </div>
-  );
+  )
 }
 
-export default forwardRef(ZRichText);
+export default forwardRef(ZRichText)

+ 32 - 20
src/components/ZRichTexts/index.tsx

@@ -13,8 +13,6 @@ import 'braft-editor/dist/index.css'
 import classNames from 'classnames'
 import { MessageFu } from '@/utils/message'
 import { fileDomInitialFu } from '@/utils/domShow'
-import { baseURL } from '@/utils/http'
-
 import { forwardRef, useImperativeHandle } from 'react'
 import { API_upFile } from '@/store/action/layout'
 import ZupAudio, { ZupAudioType } from '../ZupAudio'
@@ -37,10 +35,11 @@ type Props = {
   myUrl: string //上传的api地址
   isOne?: boolean //只显示单个富文本
   upAudioBtnNone?: boolean //是否能上传无障碍音频
+  video?: boolean //是否能上传视频
 }
 
 function ZRichTexts(
-  { check, dirCode, isLook, myUrl, isOne = false, upAudioBtnNone = false }: Props,
+  { check, dirCode, isLook, myUrl, isOne = false, upAudioBtnNone = false, video = false }: Props,
   ref: any
 ) {
   const [sectionArr, setSectionArr] = useState<SectionArrType[]>([
@@ -91,27 +90,40 @@ function ZRichTexts(
         // 拿到files信息
         const filesInfo = e.target.files[0]
 
-        let type = ['image/jpeg', 'image/png']
-        let size = 5
-        let txt = '图片只支持png、jpg和jpeg格式!'
-        let txt2 = '图片最大支持5M!'
-
-        // 校验格式
-        if (!type.includes(filesInfo.type)) {
+        const isVideo = filesInfo.name.endsWith('.mp4')
+
+        const mediaConfig = isVideo
+          ? {
+              types: ['video/mp4'],
+              maxSize: 500,
+              errorText: '视频只支持mp4格式!',
+              errorSizeText: '视频最大支持500M!',
+              mediaType: 'VIDEO'
+            }
+          : {
+              types: ['image/jpeg', 'image/png'],
+              maxSize: 5,
+              errorText: '图片只支持png、jpg和jpeg格式!',
+              errorSizeText: '图片最大支持5M!',
+              mediaType: 'IMAGE'
+            }
+
+        // 格式校验
+        if (!mediaConfig.types.includes(filesInfo.type)) {
           e.target.value = ''
-          return MessageFu.warning(txt)
+          return MessageFu.warning(mediaConfig.errorText)
         }
 
-        // 校验大小
-        if (filesInfo.size > size * 1024 * 1024) {
+        // 大小校验
+        if (filesInfo.size > mediaConfig.maxSize * 1024 * 1024) {
           e.target.value = ''
-          return MessageFu.warning(txt2)
+          return MessageFu.warning(mediaConfig.errorSizeText)
         }
 
         // 创建FormData对象
         const fd = new FormData()
         // 把files添加进FormData对象(‘photo’为后端需要的字段)
-        fd.append('type', 'img')
+        fd.append('type', isVideo ? 'video' : 'img')
         fd.append('dirCode', dirCode)
         fd.append('file', filesInfo)
 
@@ -121,11 +133,11 @@ function ZRichTexts(
           const res = await API_upFile(fd, myUrl)
           if (res.code === 0) {
             MessageFu.success('上传成功!')
-            // 在光标位置插入图片
+            // 在光标位置插入图片/视频
             const newTxt = ContentUtils.insertMedias(sectionArr[nowIndexRef.current].txt, [
               {
-                type: 'IMAGE',
-                url: baseURL + res.data.filePath
+                type: mediaConfig.mediaType,
+                url: res.data.url
               }
             ])
             const arr = [...sectionArr]
@@ -255,7 +267,7 @@ function ZRichTexts(
       <input
         id='upInput'
         type='file'
-        accept='.png,.jpg,.jpeg'
+        accept='.png,.jpg,.jpeg,.mp4'
         ref={myInput}
         onChange={e => handeUpPhoto(e)}
       />
@@ -293,7 +305,7 @@ function ZRichTexts(
                   myInput.current?.click()
                 }}
               >
-                上传图片
+                上传图片/视频
               </Button>
             </div>
           </div>

+ 20 - 33
src/components/ZupOne/index.tsx

@@ -9,7 +9,6 @@ import {
   UploadOutlined
 } from '@ant-design/icons'
 import store from '@/store'
-import { baseURL } from '@/utils/http'
 import classNames from 'classnames'
 import { Button } from 'antd'
 import { MessageFu } from '@/utils/message'
@@ -55,8 +54,8 @@ function ZupOne(
 ) {
   const [fileUrl, setFileUrl] = useState({
     fileName: '',
-    filePath: '',
-    thumb: '' //压缩图
+    url: '',
+    thUrl: '' //压缩图
   })
 
   const myInput = useRef<HTMLInputElement>(null)
@@ -133,7 +132,7 @@ function ZupOne(
 
   // 让父组件调用的 回显 附件 地址
   const setFileComFileFu = useCallback(
-    (valObj: { fileName: string; filePath: string; thumb: string }) => {
+    (valObj: { fileName: string; url: string; thUrl: string }) => {
       setFileUrl(valObj)
     },
     []
@@ -160,16 +159,18 @@ function ZupOne(
     return accept
   }, [myType])
 
+  console.log(fileUrl, 'fileUrl')
+
   // 点击 预览(除了图片)
   const lookFileNoImgFu = useCallback(
     (type: MyTypeType) => {
       if (type === 'pdf' || type === 'thumb') {
         // 新窗口打开
-        window.open(baseURL + fileUrl.filePath)
+        window.open(fileUrl.url)
       } else if (type !== 'epub') {
         store.dispatch({
           type: 'layout/lookDom',
-          payload: { src: fileUrl.filePath, type }
+          payload: { src: fileUrl.url, type }
         })
       }
 
@@ -177,7 +178,7 @@ function ZupOne(
       // } else {
       // }
     },
-    [fileUrl.filePath]
+    [fileUrl.url]
   )
 
   return (
@@ -191,7 +192,7 @@ function ZupOne(
       />
       {myType === 'thumb' ? (
         <div
-          hidden={fileUrl.filePath !== ''}
+          hidden={fileUrl.url !== ''}
           className='file_upIcon'
           onClick={() => myInput.current?.click()}
         >
@@ -199,7 +200,7 @@ function ZupOne(
         </div>
       ) : (
         <Button
-          hidden={fileUrl.filePath !== ''}
+          hidden={fileUrl.url !== ''}
           onClick={() => myInput.current?.click()}
           icon={<UploadOutlined rev={undefined} />}
         >
@@ -209,22 +210,16 @@ function ZupOne(
 
       {/* 为图片的情况-------------- */}
       {myType === 'thumb' ? (
-        <div className='file_img' hidden={fileUrl.filePath === ''}>
+        <div className='file_img' hidden={fileUrl.url === ''}>
           {fileUrl ? (
-            <ImageLazy
-              width={100}
-              height={100}
-              srcBig={fileUrl.filePath}
-              src={fileUrl.thumb}
-              noLook
-            />
+            <ImageLazy width={100} height={100} srcBig={fileUrl.url} src={fileUrl.thUrl} noLook />
           ) : null}
 
           {/* 删除 */}
           <div className='file_closeBox' hidden={isLook}>
             <MyPopconfirm
               txtK='删除'
-              onConfirm={() => setFileUrl({ fileName: '', filePath: '', thumb: '' })}
+              onConfirm={() => setFileUrl({ fileName: '', url: '', thUrl: '' })}
               Dom={<CloseOutlined rev={undefined} />}
             />
           </div>
@@ -235,35 +230,29 @@ function ZupOne(
               onClick={() =>
                 store.dispatch({
                   type: 'layout/lookBigImg',
-                  payload: { url: baseURL + fileUrl.filePath, show: true }
+                  payload: { url: fileUrl.url, show: true }
                 })
               }
               rev={undefined}
             />
-            <a href={baseURL + fileUrl.filePath} download target='_blank' rel='noreferrer'>
+            <a href={fileUrl.url} download target='_blank' rel='noreferrer'>
               <DownloadOutlined rev={undefined} />
             </a>
           </div>
         </div>
-      ) : fileUrl.filePath ? (
+      ) : fileUrl.url ? (
         <div className='fileInfo'>
           <div className='upSuccTxt'>{fileUrl.fileName}</div>
           {/* 视频预览 */}
           <div
             className='clearCover'
-            hidden={!fileUrl.filePath || myType === 'epub'}
+            hidden={!fileUrl.url || myType === 'epub'}
             onClick={() => lookFileNoImgFu(myType)}
           >
             <EyeOutlined rev={undefined} />
           </div>
           {/* 视频下载 */}
-          <a
-            href={baseURL + fileUrl.filePath}
-            download
-            target='_blank'
-            className='clearCover'
-            rel='noreferrer'
-          >
+          <a href={fileUrl.url} download target='_blank' className='clearCover' rel='noreferrer'>
             <DownloadOutlined rev={undefined} />
           </a>
           {/* 视频删除 */}
@@ -271,7 +260,7 @@ function ZupOne(
           {isLook ? null : (
             <MyPopconfirm
               txtK='删除'
-              onConfirm={() => setFileUrl({ fileName: '', filePath: '', thumb: '' })}
+              onConfirm={() => setFileUrl({ fileName: '', url: '', thUrl: '' })}
               Dom={<CloseOutlined className='clearCover' rev={undefined} />}
             />
           )}
@@ -281,9 +270,7 @@ function ZupOne(
       <div className='fileBoxRow_r_tit' hidden={isLook}>
         格式要求:支持{formatTxt}格式;最大支持{size}M。{upTxt}
         <br />
-        <div
-          className={classNames('noUpThumb', !fileUrl.filePath && fileCheck ? 'noUpThumbAc' : '')}
-        >
+        <div className={classNames('noUpThumb', !fileUrl.url && fileCheck ? 'noUpThumbAc' : '')}>
           {checkTxt}
         </div>
       </div>

+ 30 - 16
src/components/ZupTypes/index.tsx

@@ -2,7 +2,6 @@ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
 import styles from './index.module.scss'
 import { Button, Checkbox, Input, Modal } from 'antd'
 import { forwardRef, useImperativeHandle } from 'react'
-import { baseURL } from '@/utils/http'
 import {
   PlusOutlined,
   CloseCircleOutlined,
@@ -197,13 +196,34 @@ function ZupTypes(
         try {
           if (res.code === 0) {
             MessageFu.success('上传成功!')
+
             if (fileOneType === 'img')
               setFileList({
                 ...fileList,
-                img: [...fileList.img, { ...res.data, imgName: '未命名' }]
+                img: [
+                  ...fileList.img,
+                  {
+                    fileName: res.data.filename,
+                    filePath: res.data.url,
+                    id: res.data.id,
+                    type: 'img',
+                    imgName: '未命名'
+                  }
+                ]
+              })
+            else
+              setFileList({
+                ...fileList,
+                [fileOneType]: {
+                  fileName: res.data.filename,
+                  filePath: res.data.url,
+                  id: res.data.id,
+                  type: fileOneType,
+                  imgName: '未命名'
+                }
               })
-            else setFileList({ ...fileList, [fileOneType]: res.data })
           }
+          console.log(fileList)
           fileDomInitialFu()
         } catch (error) {
           fileDomInitialFu()
@@ -274,7 +294,7 @@ function ZupTypes(
               </div>
 
               <a
-                href={baseURL + fileList[type].filePath}
+                href={fileList[type].filePath}
                 download
                 target='_blank'
                 className='ZTbox2Down'
@@ -313,10 +333,11 @@ function ZupTypes(
 
   // ------------让父组件调用的 回显
   const setFileComFileFu = useCallback((info: any) => {
-    if (info.type) setTypeCheck(info.type.split(','))
+    if (info.type) setTypeCheck(info.type)
 
     if (info.fileList && info.fileList.length) {
       const data: FileListType[] = info.fileList
+      console.log('-xsxxas', data)
       const obj = {
         model: {} as FileListType,
         img: [] as FileListType[],
@@ -355,17 +376,10 @@ function ZupTypes(
       sonType: typeCheck,
       sonFileIds: fileIds,
       sonIsOk: fileCheckFu,
+      fileList,
       coverUrl
     }
-  }, [
-    fileCheckFu,
-    fileList.audio.id,
-    fileList.img,
-    fileList.model.id,
-    fileList.video.id,
-    oneIsCover,
-    typeCheck
-  ])
+  }, [fileCheckFu, fileList, oneIsCover, typeCheck])
 
   // 可以让父组件调用子组件的方法
   useImperativeHandle(ref, () => ({
@@ -491,14 +505,14 @@ function ZupTypes(
                       store.dispatch({
                         type: 'layout/lookBigImg',
                         payload: {
-                          url: baseURL + v.filePath,
+                          url: v.filePath,
                           show: true
                         }
                       })
                     }
                     rev={undefined}
                   />
-                  <a href={baseURL + v.filePath} download target='_blank' rel='noreferrer'>
+                  <a href={v.filePath} download target='_blank' rel='noreferrer'>
                     <DownloadOutlined rev={undefined} />
                   </a>
                 </div>

+ 1 - 1
src/index.tsx

@@ -22,7 +22,7 @@ root.render(
     locale={locale}
     theme={{
       token: {
-        colorPrimary: ' #A89170'
+        colorPrimary: ' #534638'
       }
     }}
   >

+ 17 - 5
src/pages/A1manage/A1add/index.module.scss

@@ -12,7 +12,7 @@
   :global {
     .A1aMain {
       width: 100%;
-      height: 100%;
+      height: calc(100% - 80px);
       overflow-y: auto;
 
       textarea {
@@ -34,6 +34,9 @@
 
       .ant-form {
         width: 800px;
+        display: flex;
+        flex-direction: column;
+        gap: 30px;
 
         // .ant-input-affix-wrapper{
         //   width: 800px;
@@ -58,11 +61,20 @@
         }
 
         .A1abtn {
-          position: absolute;
+          display: flex;
+          align-items: center;
+          width: 100%;
+          height: 80px;
+          position: fixed;
+          bottom: 0;
+          background: #fff;
           z-index: 10;
-          left: 1200px;
-          top: 50%;
-          transform: translateY(-50%);
+
+          .A1abtnBox {
+            display: flex;
+            gap: 20px;
+            padding-left: 100px;
+          }
         }
       }
     }

+ 230 - 0
src/pages/A1banner/A1add/index.tsx

@@ -0,0 +1,230 @@
+import React, { useCallback, useEffect, useRef, useState } from 'react'
+import styles from './index.module.scss'
+import classNames from 'classnames'
+import { A1EditInfoType } from '../data'
+import { Button, Form, FormInstance, Input, DatePicker } from 'antd'
+import { A1_APIgetInfo, A1_APIadd, A1_APIedit } from '@/store/action/A1banner'
+import { MessageFu } from '@/utils/message'
+import ZupOne from '@/components/ZupOne'
+import { A1AddType, A1tbType } from '@/types'
+import MyPopconfirm from '@/components/MyPopconfirm'
+import dayjs from 'dayjs'
+
+type Props = {
+  editInfo: A1EditInfoType
+  closeFu: () => void
+  addTableFu: () => void
+  editTableFu: () => void
+}
+
+function A1add({ editInfo, closeFu, addTableFu, editTableFu }: Props) {
+  // 表单的ref
+  const FormBoxRef = useRef<FormInstance>(null)
+
+  // 封面图的ref
+  const ZupThumbRef = useRef<any>(null)
+
+  // 回显数据的方法调用
+  const dataShow = useCallback((info: A1tbType) => {
+    let editObj = null
+    if (info.status === 0) {
+      editObj = {
+        ...info,
+        title: info.titleB,
+        url: info.urlB,
+        publish: info.publishB,
+        img: info.imgB,
+        imgTh: info.imgThB
+      }
+    } else {
+      editObj = { ...info }
+    }
+    FormBoxRef.current?.setFieldsValue({ ...editObj, publish: dayjs(editObj.publish) })
+
+    // 设置封面图
+    ZupThumbRef.current?.setFileComFileFu({
+      fileName: '',
+      thUrl: editObj.imgTh,
+      url: editObj.img
+    })
+  }, [])
+
+  // 编辑 进入页面 获取信息
+  const getInfoFu = useCallback(
+    async (id: number) => {
+      if (editInfo.info) dataShow(editInfo.info)
+      else {
+        const res = await A1_APIgetInfo(id)
+        if (res.code === 0) {
+          dataShow(res.data)
+        }
+      }
+    },
+    [dataShow, editInfo.info]
+  )
+
+  // 附件 是否 已经点击过确定
+  const [fileCheck, setFileCheck] = useState(false)
+
+  // 编辑填入数据
+  useEffect(() => {
+    if (editInfo.id > 0) {
+      getInfoFu(editInfo.id)
+    }
+  }, [editInfo.id, getInfoFu])
+
+  // 没有通过校验
+  const onFinishFailed = useCallback(() => {
+    setFileCheck(true)
+  }, [])
+
+  //  通过校验点击确定
+  const onFinish = useCallback(
+    async (values: any) => {
+      setFileCheck(true)
+
+      const coverUrl = ZupThumbRef.current?.fileComFileResFu()
+      // 没有传 封面图
+      if (!coverUrl.url) return MessageFu.warning('请上传封面图!')
+
+      // 发布
+      const obj1: A1AddType = {
+        ...values,
+        img: coverUrl.url,
+        imgB: '',
+        imgTh: coverUrl.thUrl,
+        imgThB: '',
+        publishB: '',
+        status: 1,
+        titleB: '',
+        urlB: ''
+      }
+
+      // 预发布
+      const obj2: A1AddType = {
+        img: '',
+        imgB: coverUrl.url,
+        imgTh: '',
+        imgThB: coverUrl.thUrl,
+        publish: '',
+        publishB: values.publish,
+        status: 0,
+        title: '',
+        titleB: values.title,
+        url: '',
+        urlB: values.url
+      }
+
+      let res: any
+      if (btnRef.current === '1') {
+        res =
+          editInfo.txt === '新增'
+            ? await A1_APIadd(obj1)
+            : await A1_APIedit({ ...obj1, carouselId: editInfo.id })
+      } else {
+        res =
+          editInfo.txt === '新增'
+            ? await A1_APIadd(obj2)
+            : await A1_APIedit({ ...obj2, carouselId: editInfo.id })
+      }
+
+      if (res.code === 0) {
+        MessageFu.success(`${editInfo.txt}成功!`)
+        editInfo.id > 0 ? editTableFu() : addTableFu()
+        closeFu()
+      }
+    },
+    [addTableFu, closeFu, editInfo.id, editInfo.txt, editTableFu]
+  )
+
+  const formOkBtnRef = useRef<any>(null)
+
+  const btnRef = useRef('')
+
+  return (
+    <div className={styles.A1add}>
+      <div className={classNames('A1aMain')}>
+        <Form
+          ref={FormBoxRef}
+          name='basic'
+          labelCol={{ span: 3 }}
+          onFinish={onFinish}
+          onFinishFailed={onFinishFailed}
+          autoComplete='off'
+          scrollToFirstError
+        >
+          <Form.Item
+            label='标题'
+            name='title'
+            rules={[{ required: true, message: '请输入标题!' }]}
+          >
+            <Input placeholder='请输入内容,不超过30个字' maxLength={30} showCount />
+          </Form.Item>
+
+          <Form.Item label='发布日期' name='publish'>
+            <DatePicker allowClear placeholder='请选择日期' style={{ width: 200 }} />
+          </Form.Item>
+
+          {/* 封面 */}
+          <div className='formRow'>
+            <div className='formLeft'>
+              <span>* </span>
+              封面:
+            </div>
+            <div className='formRight'>
+              <ZupOne
+                ref={ZupThumbRef}
+                fileCheck={fileCheck}
+                size={5}
+                dirCode={'A1banner'}
+                myUrl='museum/upload/uploadImg'
+                format={['image/jpeg', 'image/png']}
+                formatTxt='png、jpg和jpeg'
+                checkTxt='请上传封面图!'
+                upTxt='最多1张'
+                myType='thumb'
+              />
+            </div>
+          </div>
+
+          <div className='A1fromRow'>
+            <Form.Item label='链接' name='url' rules={[{ required: true, message: '请输入链接!' }]}>
+              <Input placeholder='请输入' />
+            </Form.Item>
+          </div>
+
+          {/* 确定和取消按钮 */}
+          <Form.Item className='A1abtn'>
+            <div className='A1abtnBox'>
+              <Button
+                type='primary'
+                htmlType='submit'
+                onClick={() => {
+                  btnRef.current = '1'
+                  formOkBtnRef.current?.click()
+                }}
+              >
+                发布
+              </Button>
+              <Button
+                type='primary'
+                htmlType='submit'
+                onClick={() => {
+                  btnRef.current = '0'
+                  formOkBtnRef.current?.click()
+                }}
+              >
+                预发布
+              </Button>
+              <MyPopconfirm txtK='取消' onConfirm={closeFu} />
+            </div>
+          </Form.Item>
+        </Form>
+      </div>
+    </div>
+  )
+}
+
+const MemoA1add = React.memo(A1add)
+
+export default MemoA1add

+ 7 - 0
src/pages/A1banner/data.ts

@@ -0,0 +1,7 @@
+import { A1tbType } from '@/types'
+
+export type A1EditInfoType = {
+  id: number
+  txt: '新增' | '编辑' | ''
+  info?: A1tbType
+}

+ 20 - 0
src/pages/A1banner/index.module.scss

@@ -0,0 +1,20 @@
+.A1banner {
+  position: relative;
+  :global {
+    .A1top {
+      border-radius: 10px;
+      background-color: #fff;
+      padding: 15px 24px;
+      display: flex;
+      justify-content: right;
+      gap: 20px;
+    }
+    .A1tableBox {
+      border-radius: 10px;
+      overflow: hidden;
+      margin-top: 15px;
+      height: calc(100% - 77px);
+      background-color: #fff;
+    }
+  }
+}

+ 140 - 0
src/pages/A1banner/index.tsx

@@ -0,0 +1,140 @@
+import React, { useCallback, useEffect, useMemo, useState } from 'react'
+import styles from './index.module.scss'
+import { Button } from 'antd'
+import { useDispatch, useSelector } from 'react-redux'
+import { A1EditInfoType } from './data'
+import { A1_APIdel, A1_APIgetList, A1_APIpublish } from '@/store/action/A1banner'
+import { RootState } from '@/store'
+import { MessageFu } from '@/utils/message'
+import { A1tbType } from '@/types'
+import MyPopconfirm from '@/components/MyPopconfirm'
+import MyTable from '@/components/MyTable'
+import { A1tableC } from '@/utils/tableData'
+import A1add from './A1add'
+
+const pageDataBase = {
+  pageNum: 1,
+  pageSize: 10
+}
+
+function A1banner() {
+  const dispatch = useDispatch()
+
+  const [pageData, setPageData] = useState(pageDataBase)
+
+  const getListFu = useCallback(() => {
+    // status: -1 全部 0 未发布 1 已发布
+    dispatch(A1_APIgetList({ ...pageData, status: -1 }))
+  }, [dispatch, pageData])
+
+  useEffect(() => {
+    getListFu()
+  }, [getListFu])
+
+  // 点击重置
+  const resetSelectFu = useCallback(() => {
+    setPageData({ ...pageDataBase })
+  }, [])
+
+  const tableInfo = useSelector((state: RootState) => state.A1banner.tableInfo)
+
+  const delTableFu = useCallback(
+    async (id: number) => {
+      const res = await A1_APIdel(id)
+      if (res.code === 0) {
+        MessageFu.success('删除成功!')
+        getListFu()
+      }
+    },
+    [getListFu]
+  )
+
+  const publishFu = useCallback(
+    async (id: number) => {
+      const res = await A1_APIpublish(id)
+      if (res.code === 0) {
+        MessageFu.success('发布成功!')
+        getListFu()
+      }
+    },
+    [getListFu]
+  )
+
+  const tableLastBtn = useMemo(() => {
+    return [
+      {
+        title: '操作',
+        render: (item: A1tbType) => (
+          <>
+            {item.status === 0 && (
+              <Button size='small' type='text'>
+                预览
+              </Button>
+            )}
+            <Button
+              size='small'
+              type='text'
+              onClick={() => setEditInfo({ id: item.carouselId, txt: '编辑' })}
+            >
+              编辑
+            </Button>
+            {item.status === 0 && (
+              <Button size='small' type='text' onClick={() => publishFu(item.carouselId)}>
+                发布
+              </Button>
+            )}
+            <MyPopconfirm txtK='删除' onConfirm={() => delTableFu(item.carouselId)} />
+          </>
+        )
+      }
+    ]
+  }, [delTableFu, publishFu])
+
+  //新增、编辑
+  const [editInfo, setEditInfo] = useState<A1EditInfoType>({
+    id: 0,
+    txt: ''
+  })
+
+  return (
+    <div className={styles.A1banner}>
+      <div className='pageTitle'>首页轮播图 {editInfo.id ? ` - ${editInfo.txt}` : ''}</div>
+
+      {/* 顶部筛选 */}
+      <div className='A1top'>
+        <Button type='primary' onClick={() => setEditInfo({ id: -1, txt: '新增' })}>
+          新增
+        </Button>
+      </div>
+
+      {/* 表格主体 */}
+      <div className='A1tableBox'>
+        <MyTable
+          myKey='carouselId'
+          yHeight={625}
+          list={tableInfo.list}
+          columnsTemp={A1tableC}
+          lastBtn={tableLastBtn}
+          pageNum={pageData.pageNum}
+          pageSize={pageData.pageSize}
+          total={tableInfo.total}
+          onChange={(pageNum, pageSize) => setPageData({ ...pageData, pageNum, pageSize })}
+        />
+      </div>
+
+      {/* 新增 / 编辑 */}
+      {editInfo.id ? (
+        <A1add
+          editInfo={editInfo}
+          closeFu={() => setEditInfo({ id: 0, txt: '新增' })}
+          addTableFu={resetSelectFu}
+          editTableFu={getListFu}
+        ></A1add>
+      ) : null}
+    </div>
+  )
+}
+
+const MemoA1banner = React.memo(A1banner)
+
+export default MemoA1banner

+ 0 - 94
src/pages/A1manage/A1Import/index.module.scss

@@ -1,94 +0,0 @@
-.A1Import {
-  position: absolute;
-  top: 0;
-  left: 0;
-  width: 100%;
-  height: 100%;
-  z-index: 10;
-  background-color: #ecedf1;
-
-  :global {
-    .A1top {
-      .anticon-arrow-left {
-        cursor: pointer;
-        font-size: 30px;
-        margin-right: 24px;
-      }
-      h1 {
-        line-height: 30px;
-        font-size: 16px;
-      }
-      & > div {
-        display: flex;
-        align-items: center;
-        .A1iInco {
-          width: 24px;
-          height: 24px;
-          border-radius: 50%;
-          cursor: pointer;
-          display: flex;
-          justify-content: center;
-          align-items: center;
-          border: 1px solid #ccc;
-        }
-      }
-    }
-    .A1tableBox {
-      position: relative;
-      // height: calc(100% - 180px);
-      .ant-table-tbody .ant-table-cell {
-        padding: 4px !important;
-      }
-      .A1Ibtn {
-        position: absolute;
-        bottom: 10px;
-        left: 50%;
-        transform: translateX(-50%);
-        & > span {
-          width: 500px;
-          position: absolute;
-          top: -8px;
-          left: 80px;
-          opacity: 0;
-          pointer-events: none;
-          transition: all 0.3s;
-          color: #ff4d4d;
-        }
-        .A1IbtnTit {
-          top: 8px;
-          opacity: 1;
-        }
-      }
-    }
-
-    .A1Iedit {
-      position: absolute;
-      top: 0;
-      left: 0;
-      z-index: 10;
-      width: 100%;
-      height: 100%;
-      background-color: rgba(0, 0, 0, 0.6);
-      border-radius: 10px;
-      padding: 50px 100px;
-      & > div {
-        width: 100%;
-        height: 100%;
-        position: relative;
-      }
-    }
-  }
-}
-
-.A1Imo {
-  :global {
-    .ant-modal-body {
-      padding-top: 20px !important;
-      border-top: 1px solid #ccc;
-    }
-    .A1ImoRow {
-      margin-bottom: 20px;
-      font-size: 16px;
-    }
-  }
-}

+ 0 - 179
src/pages/A1manage/A1Import/index.tsx

@@ -1,179 +0,0 @@
-import React, { useCallback, useMemo, useRef, useState } from 'react'
-import styles from './index.module.scss'
-import { ArrowLeftOutlined, QuestionOutlined } from '@ant-design/icons'
-import MyPopconfirm from '@/components/MyPopconfirm'
-import { Button, Modal } from 'antd'
-import MyTable from '@/components/MyTable'
-import { A1tableType, A2tableType, A2TreeType } from '@/types'
-import { A1tableCimp } from '@/utils/tableData'
-import UpXlsx from '@/components/UpXlsx'
-import { baseURL } from '@/utils/http'
-import classNames from 'classnames'
-import A1add from '../A1add'
-import { A1_APIimport } from '@/store/action/A1manage'
-import { MessageFu } from '@/utils/message'
-
-type Props = {
-  closeFu: () => void
-  addTableFu: () => void
-  storageArr: A2TreeType[]
-  exhibitTypeArr: A2tableType[]
-}
-
-function A1Import({ closeFu, addTableFu, storageArr, exhibitTypeArr }: Props) {
-  const [list, setList] = useState<A1tableType[]>([])
-
-  const [tit, setTit] = useState(false)
-
-  const tableLastBtn = useMemo(() => {
-    return [
-      {
-        title: '操作',
-        render: (item: A1tableType) => (
-          <>
-            <Button size='small' type='text' onClick={() => setEditInfo(item)}>
-              编辑
-            </Button>
-
-            <MyPopconfirm
-              txtK='删除'
-              onConfirm={() => setList(list.filter(v => v.id !== item.id))}
-            />
-          </>
-        )
-      }
-    ]
-  }, [list])
-
-  // 编辑
-  const [editInfo, setEditInfo] = useState({} as A1tableType)
-
-  // 上传xlsx 的ref
-  const upXlsxRef = useRef<any>(null)
-
-  // 信息录入不完整的消息提示
-  const titShow = useMemo(() => {
-    return list.some(v => !v.thumb || !v.storageId || !v.exhibitTypeId || !v.filePath)
-  }, [list])
-
-  // 编辑完返回的信息
-  const editFu = useCallback(
-    (info: A1tableType) => {
-      const index = list.findIndex(v => v.id === info.id)
-      const arr = [...list]
-      arr[index] = info
-      setList(arr)
-    },
-    [list]
-  )
-
-  // 点击导入
-  const impFu = useCallback(async () => {
-    const res = await A1_APIimport(list.map(v => ({ ...v, id: null })))
-    if (res.code === 0) {
-      MessageFu.success('导入成功!')
-      addTableFu()
-      closeFu()
-    }
-
-    // else if(res.code===-2){
-    //   MessageFu.warning()
-    // }
-  }, [addTableFu, closeFu, list])
-
-  return (
-    <div className={styles.A1Import}>
-      <div className='A1top'>
-        <div>
-          <ArrowLeftOutlined onClick={closeFu} />
-          <h1>图书批量导入</h1>
-        </div>
-        <div>
-          关于导入规则&nbsp;
-          <span className='A1iInco' onClick={() => setTit(true)}>
-            <QuestionOutlined />
-          </span>
-          &emsp;
-          <MyPopconfirm txtK='清空' onConfirm={() => setList([])} Dom={<Button>清空</Button>} />
-          &emsp;
-          <a href={baseURL + '/baseData/tp_book.xlsx'} download>
-            <Button>下载模板</Button>
-          </a>
-          &emsp;
-          <UpXlsx
-            url='cms/book/upload/excel'
-            ref={upXlsxRef}
-            xlsxResInfoFu={arr => setList([...arr, ...list])}
-            dirCode='cameraXlsx'
-            ISBNArr={list.map(v => v.num)}
-          />
-          {/* 上传xlsx */}
-          <Button type='primary' onClick={() => upXlsxRef.current?.myInputClickFu()}>
-            上传
-          </Button>
-        </div>
-      </div>
-
-      {/* 表格主体 */}
-      <div className='A1tableBox'>
-        <MyTable
-          classKey='A1Itable'
-          yHeight={610}
-          list={list}
-          columnsTemp={A1tableCimp}
-          lastBtn={tableLastBtn}
-          pagingInfo={false}
-        />
-
-        {/* 底部导入按钮 */}
-        <div className='A1Ibtn'>
-          <Button disabled={list.length === 0 || titShow} type='primary' onClick={impFu}>
-            导入
-          </Button>
-          <span className={classNames(list.length && titShow ? 'A1IbtnTit' : '')}>
-            请先完善代填入字段
-          </span>
-        </div>
-      </div>
-
-      {/* 复用编辑 */}
-      {editInfo.id ? (
-        <div className='A1Iedit'>
-          <div>
-            <A1add
-              editInfo={{ id: editInfo.id, txt: '编辑', info: editInfo }}
-              closeFu={() => setEditInfo({} as A1tableType)}
-              addTableFu={() => {}}
-              editTableFu={() => {}}
-              storageArr={storageArr}
-              exhibitTypeArr={exhibitTypeArr}
-              isImportFu={info => editFu(info)}
-              ISBNArr={list.filter(v => v.id !== editInfo.id).map(v => v.num)}
-            />
-          </div>
-        </div>
-      ) : null}
-
-      {/* 导入规则 */}
-      <Modal
-        wrapClassName={styles.A1Imo}
-        open={tit}
-        title='导入规则'
-        onCancel={() => setTit(false)}
-        footer={
-          [] // 设置footer为空,去掉 取消 确定默认按钮
-        }
-      >
-        <div className='A1ImoRow'>1:下载模板</div>
-        <div className='A1ImoRow'>2:在模板中填入内容,注意必填项和填入要求</div>
-        <div className='A1ImoRow'>3:上传已填写的模板文件</div>
-        <div className='A1ImoRow'>4:在当前列表中,完善图书信息,包括上传封面,附件等</div>
-        <div className='A1ImoRow'>5:导入内容</div>
-      </Modal>
-    </div>
-  )
-}
-
-const MemoA1Import = React.memo(A1Import)
-
-export default MemoA1Import

+ 0 - 402
src/pages/A1manage/A1add/index.tsx

@@ -1,402 +0,0 @@
-import React, { useCallback, useEffect, useRef, useState } from 'react'
-import styles from './index.module.scss'
-import classNames from 'classnames'
-import { A1EditInfoType } from '../data'
-import { Button, Cascader, Form, FormInstance, Input, InputNumber, Select } from 'antd'
-import { A1_APIgetInfo, A1_APIsave } from '@/store/action/A1manage'
-import { MessageFu } from '@/utils/message'
-import ZupOne from '@/components/ZupOne'
-import TextArea from 'antd/es/input/TextArea'
-import dayjs from 'dayjs'
-import { A1tableType, A2tableType, A2TreeType } from '@/types'
-import MyPopconfirm from '@/components/MyPopconfirm'
-import { A5_APIgetInfo } from '@/store/action/A5bookAudit'
-import { treeResIdFu } from '@/pages/A2classify/data'
-
-type Props = {
-  editInfo: A1EditInfoType
-  closeFu: () => void
-  addTableFu: () => void
-  editTableFu: () => void
-  storageArr: A2TreeType[]
-  exhibitTypeArr: A2tableType[]
-  isAudit?: boolean //从图书审核页面进来
-  isImportFu?: (info: A1tableType) => void // 从批量导入里面进来
-  ISBNArr?: string[] //ISBN编号集合,用来判断当前填写的ISBN是否已经存在了(外层表格中)
-}
-
-function A1add({
-  editInfo,
-  closeFu,
-  addTableFu,
-  editTableFu,
-  storageArr,
-  exhibitTypeArr,
-  isAudit,
-  isImportFu,
-  ISBNArr
-}: Props) {
-  // 表单的ref
-  const FormBoxRef = useRef<FormInstance>(null)
-
-  // 封面图的ref
-  const ZupThumbRef = useRef<any>(null)
-
-  // txt的ref
-  const ZupTxtRef = useRef<any>(null)
-
-  // 回显数据的方法调用
-  const dataShow = useCallback((info: A1tableType) => {
-    let storageIds: any[] = []
-    if (info.ancestor) storageIds = info.ancestor.split(',').map((v: string) => Number(v))
-
-    if (info.storageId) storageIds.push(Number(info.storageId))
-
-    const obj = {
-      ...info,
-      storageIds,
-      exhibitTypeId: info.exhibitTypeId ? Number(info.exhibitTypeId) : null,
-      year: info.year ? info.year : null
-    }
-
-    FormBoxRef.current?.setFieldsValue(obj)
-
-    // 设置封面图
-    ZupThumbRef.current?.setFileComFileFu({
-      fileName: '',
-      thumb: info.thumb,
-      filePath: info.thumbPc
-    })
-
-    // 设置附件
-    ZupTxtRef.current?.setFileComFileFu({
-      fileName: info.fileName,
-      filePath: info.filePath
-    })
-  }, [])
-
-  // 编辑/查看 进入页面 获取信息
-  const getInfoFu = useCallback(
-    async (id: number) => {
-      if (isImportFu && editInfo.info) dataShow(editInfo.info)
-      else {
-        const res = isAudit ? await A5_APIgetInfo(id) : await A1_APIgetInfo(id)
-        if (res.code === 0) {
-          dataShow(res.data)
-        }
-      }
-    },
-    [dataShow, editInfo.info, isAudit, isImportFu]
-  )
-
-  // 附件 是否 已经点击过确定
-  const [fileCheck, setFileCheck] = useState(false)
-
-  useEffect(() => {
-    if (editInfo.id > 0) {
-      getInfoFu(editInfo.id)
-    } else {
-      FormBoxRef.current?.setFieldsValue({
-        sort: 999,
-        year: dayjs().get('year')
-      })
-    }
-  }, [editInfo.id, getInfoFu])
-
-  // 没有通过校验
-  const onFinishFailed = useCallback(() => {
-    setFileCheck(true)
-  }, [])
-
-  //  通过校验点击确定
-  const onFinish = useCallback(
-    async (values: any) => {
-      setFileCheck(true)
-
-      const coverUrl1 = ZupThumbRef.current?.fileComFileResFu()
-      // 没有传 封面图
-      if (!coverUrl1.filePath) return MessageFu.warning('请上传封面图!')
-
-      let fileName = ''
-      let filePath = ''
-      // txt附件
-      const ZupTxtRefObj = ZupTxtRef.current?.fileComFileResFu()
-      fileName = ZupTxtRefObj.fileName
-      filePath = ZupTxtRefObj.filePath
-      if (!filePath) return MessageFu.warning('请上传epub附件!')
-
-      if (ISBNArr && ISBNArr.includes(values.num) && values.num !== '')
-        return MessageFu.warning(`ISBN编号 ${values.num} 重复!`)
-
-      let storageId: null | number = null
-
-      if (values.storageIds && values.storageIds.length) {
-        storageId = values.storageIds[values.storageIds.length - 1]
-      }
-
-      const obj = {
-        ...values,
-        id: isAudit ? null : editInfo.id > 0 ? editInfo.id : null,
-        thumb: coverUrl1.thumb,
-        thumbPc: coverUrl1.filePath,
-        storageId,
-        fileName,
-        filePath
-      }
-
-      // if (obj) {
-      //   console.log(123, obj);
-      //   return;
-      // }
-
-      if (isImportFu && editInfo.info) {
-        const info = editInfo.info
-
-        // 多级筛选的 映射字段回显
-        let ancestor = ''
-        let storageName = ''
-
-        const storageArrAc = treeResIdFu(storageArr, storageId!)
-        if (storageArrAc) {
-          ancestor = storageArrAc.ancestor
-          storageName = storageArrAc.name
-        }
-
-        // 下拉框 映射字段回显
-        let exhibitTypeName = ''
-
-        const exhibitTypeArrAc = exhibitTypeArr.find(v => v.id === values.exhibitTypeId)
-
-        if (exhibitTypeArrAc) exhibitTypeName = exhibitTypeArrAc.name
-        const ImpObj = {
-          ...obj,
-          id: info.id,
-          ancestor,
-          storageName,
-          exhibitTypeName
-        }
-
-        isImportFu(ImpObj)
-        MessageFu.success('编辑成功!')
-        closeFu()
-      } else {
-        const res = await A1_APIsave(obj)
-
-        if (res.code === 0) {
-          MessageFu.success(isAudit ? '创建成功!' : `${editInfo.txt}成功!`)
-          editInfo.id > 0 ? editTableFu() : addTableFu()
-          closeFu()
-        }
-      }
-    },
-    [
-      ISBNArr,
-      addTableFu,
-      closeFu,
-      editInfo.id,
-      editInfo.info,
-      editInfo.txt,
-      editTableFu,
-      exhibitTypeArr,
-      isAudit,
-      isImportFu,
-      storageArr
-    ]
-  )
-
-  // 年份
-  const [ageSelect, setAgeSelect] = useState<{ value: string; label: string }[]>([])
-
-  useEffect(() => {
-    const arr: { value: string; label: string }[] = []
-    const nowYear = dayjs().get('year')
-    const num = nowYear - 1900
-    for (let i = 0; i <= num; i++) {
-      const temp = nowYear - i + ''
-      arr.push({
-        value: temp,
-        label: temp
-      })
-    }
-
-    setAgeSelect(arr)
-  }, [])
-
-  return (
-    <div className={styles.A1add}>
-      <div className={classNames('A1aMain', editInfo.txt === '查看' ? 'A1aMainLook' : '')}>
-        <Form
-          ref={FormBoxRef}
-          name='basic'
-          labelCol={{ span: 3 }}
-          onFinish={onFinish}
-          onFinishFailed={onFinishFailed}
-          autoComplete='off'
-          scrollToFirstError
-        >
-          <Form.Item label='书名' name='name' rules={[{ required: true, message: '请输入书名!' }]}>
-            <Input
-              readOnly={editInfo.txt === '查看'}
-              placeholder='请输入内容'
-              maxLength={50}
-              showCount
-            />
-          </Form.Item>
-
-          <Form.Item label='简介' name='description'>
-            <TextArea
-              readOnly={editInfo.txt === '查看'}
-              maxLength={200}
-              showCount
-              placeholder='请输入内容'
-            />
-          </Form.Item>
-
-          <Form.Item label='作者' name='author'>
-            <Input
-              readOnly={editInfo.txt === '查看'}
-              placeholder='请输入内容'
-              maxLength={20}
-              showCount
-            />
-          </Form.Item>
-
-          <Form.Item label='出版社' name='press'>
-            <Input
-              readOnly={editInfo.txt === '查看'}
-              placeholder='请输入内容'
-              maxLength={20}
-              showCount
-            />
-          </Form.Item>
-
-          <Form.Item label='出版年份' name='year'>
-            <Select
-              allowClear
-              placeholder='请选择年份'
-              style={{ width: 200 }}
-              options={ageSelect}
-            />
-          </Form.Item>
-
-          {/* 封面 */}
-          <div className='formRow'>
-            <div className='formLeft'>
-              <span>* </span>
-              封面:
-            </div>
-            <div className='formRight'>
-              <ZupOne
-                ref={ZupThumbRef}
-                isLook={editInfo.txt === '查看'}
-                fileCheck={fileCheck}
-                size={5}
-                dirCode={'A1manage'}
-                myUrl='cms/book/upload'
-                format={['image/jpeg', 'image/png']}
-                formatTxt='png、jpg和jpeg'
-                checkTxt='请上传封面图!'
-                upTxt='最多1张'
-                myType='thumb'
-              />
-            </div>
-          </div>
-          {editInfo.txt === '查看' ? <br /> : null}
-
-          <Form.Item
-            label='中图法分类'
-            name='storageIds'
-            rules={[{ required: true, message: '请选择中图法分类!' }]}
-          >
-            <Cascader
-              allowClear={false}
-              changeOnSelect
-              style={{ width: 300 }}
-              options={storageArr}
-              fieldNames={{ label: 'name', value: 'id', children: 'children' }}
-              placeholder='请选择'
-            />
-          </Form.Item>
-
-          <Form.Item
-            label='展示分类'
-            name='exhibitTypeId'
-            rules={[{ required: true, message: '请选择展示分类!' }]}
-          >
-            <Select
-              placeholder='请选择'
-              style={{ width: 200 }}
-              fieldNames={{ label: 'name', value: 'id' }}
-              options={exhibitTypeArr}
-            />
-          </Form.Item>
-
-          <Form.Item label='ISBN编号' name='num'>
-            <Input
-              readOnly={editInfo.txt === '查看'}
-              placeholder='请输入内容'
-              maxLength={20}
-              showCount
-            />
-          </Form.Item>
-          {/* 附件 */}
-          <div className='formRow'>
-            <div className='formLeft'>
-              <span>* </span>
-              附件:
-            </div>
-            <div className='formRight'>
-              <ZupOne
-                ref={ZupTxtRef}
-                isLook={editInfo.txt === '查看'}
-                fileCheck={fileCheck}
-                size={500}
-                dirCode='A1manage'
-                myUrl='cms/book/upload'
-                format={['']}
-                formatTxt='epub'
-                checkTxt='请上传epub附件!'
-                upTxt='最多1个'
-                myType='epub'
-              />
-            </div>
-          </div>
-          {editInfo.txt === '查看' ? <br /> : null}
-
-          <div className='A1fromRow'>
-            <Form.Item
-              label='排序值'
-              name='sort'
-              rules={[{ required: true, message: '请输入排序值!' }]}
-            >
-              <InputNumber min={1} max={999} precision={0} placeholder='请输入' />
-            </Form.Item>
-            <div className='A1_6Frow' hidden={editInfo.txt === '查看'}>
-              请输入1~999的数字。数字越小,排序越靠前。数字相同时,更新发布的内容排在前面
-            </div>
-          </div>
-
-          {/* 确定和取消按钮 */}
-          <Form.Item className='A1abtn'>
-            {editInfo.txt === '查看' ? (
-              <Button onClick={closeFu}>返回</Button>
-            ) : (
-              <>
-                <Button type='primary' htmlType='submit'>
-                  提交
-                </Button>
-                <br />
-                <br />
-                <MyPopconfirm txtK='取消' onConfirm={closeFu} />
-              </>
-            )}
-          </Form.Item>
-        </Form>
-      </div>
-    </div>
-  )
-}
-
-const MemoA1add = React.memo(A1add)
-
-export default MemoA1add

+ 0 - 225
src/pages/A1manage/A1ying/A1Yadd.tsx

@@ -1,225 +0,0 @@
-import React, { useCallback, useEffect, useRef, useState } from 'react'
-import styles from './index.module.scss'
-import { Button, Form, FormInstance, Input, InputNumber, Modal } from 'antd'
-import { A1_APIgetInfoById, A1_APIsaveById } from '@/store/action/A1manage'
-import { MessageFu } from '@/utils/message'
-import ZupOne from '@/components/ZupOne'
-import MyPopconfirm from '@/components/MyPopconfirm'
-import TextArea from 'antd/es/input/TextArea'
-
-type Props = {
-  type: 'img' | 'video'
-  id: number
-  bookId: number
-  closeFu: () => void
-  addTableFu: () => void
-  editTableFu: () => void
-}
-
-function A1Yadd({ type, id, closeFu, addTableFu, editTableFu, bookId }: Props) {
-  // 表单的ref
-  const FormBoxRef = useRef<FormInstance>(null)
-
-  // 封面图的ref
-  const ZupThumbRef = useRef<any>(null)
-
-  // 附件的ref
-  const ZupFileRef = useRef<any>(null)
-
-  // 编辑/查看 进入页面 获取信息
-  const getInfoFu = useCallback(async (id: number) => {
-    const res = await A1_APIgetInfoById(id)
-    if (res.code === 0) {
-      const data = res.data
-      FormBoxRef.current?.setFieldsValue(data)
-
-      // 设置封面图
-      ZupThumbRef.current?.setFileComFileFu({
-        fileName: '',
-        thumb: data.thumb,
-        filePath: data.thumbPc
-      })
-
-      // 设置附件
-      ZupFileRef.current?.setFileComFileFu({
-        fileName: data.fileName,
-        filePath: data.filePath
-      })
-    }
-  }, [])
-
-  // 附件 是否 已经点击过确定
-  const [fileCheck, setFileCheck] = useState(false)
-
-  useEffect(() => {
-    if (id > 0) {
-      getInfoFu(id)
-    } else {
-      FormBoxRef.current?.setFieldsValue({
-        sort: 999
-      })
-    }
-  }, [id, getInfoFu])
-
-  // 没有通过校验
-  const onFinishFailed = useCallback(() => {
-    setFileCheck(true)
-  }, [])
-
-  //  通过校验点击确定
-  const onFinish = useCallback(
-    async (values: any) => {
-      setFileCheck(true)
-
-      const coverUrl1 = ZupThumbRef.current?.fileComFileResFu()
-      // 没有传 封面图
-      if (!coverUrl1.filePath)
-        return MessageFu.warning(`请上传!${type === 'img' ? '图片' : '封面图'}!`)
-
-      let fileName = ''
-      let filePath = ''
-      // 附件
-      if (type === 'video') {
-        const ZupTxtRefObj = ZupFileRef.current?.fileComFileResFu()
-        fileName = ZupTxtRefObj.fileName
-        filePath = ZupTxtRefObj.filePath
-        if (!filePath) return MessageFu.warning('请上传附件!')
-      }
-
-      const obj = {
-        ...values,
-        id: id > 0 ? id : null,
-        thumb: coverUrl1.thumb,
-        thumbPc: coverUrl1.filePath,
-        fileName,
-        filePath,
-        type,
-        bookId
-      }
-
-      // if (obj) {
-      //   console.log(123, obj)
-      //   return
-      // }
-
-      const res = await A1_APIsaveById(obj)
-
-      if (res.code === 0) {
-        MessageFu.success(`${id > 0 ? '编辑' : '新增'}成功!`)
-        id > 0 ? editTableFu() : addTableFu()
-        closeFu()
-      }
-    },
-    [addTableFu, bookId, closeFu, editTableFu, id, type]
-  )
-
-  return (
-    <Modal
-      wrapClassName={styles.A1Yadd}
-      open={true}
-      title={id > 0 ? '编辑' : '新增'}
-      footer={
-        [] // 设置footer为空,去掉 取消 确定默认按钮
-      }
-    >
-      <div className='A1Ymain'>
-        <Form
-          ref={FormBoxRef}
-          name='basic'
-          labelCol={{ span: 2 }}
-          onFinish={onFinish}
-          onFinishFailed={onFinishFailed}
-          autoComplete='off'
-          scrollToFirstError
-        >
-          {type === 'video' ? (
-            <Form.Item
-              label='标题'
-              name='name'
-              rules={[{ required: true, message: '请输入标题!' }]}
-            >
-              <Input placeholder='请输入内容' maxLength={20} showCount />
-            </Form.Item>
-          ) : null}
-
-          {/* 封面 */}
-          <div className='formRow'>
-            <div className='formLeft'>
-              <span>* </span>
-              {type === 'img' ? '图片' : '封面'}:
-            </div>
-            <div className='formRight'>
-              <ZupOne
-                ref={ZupThumbRef}
-                fileCheck={fileCheck}
-                size={5}
-                dirCode={'A1manageY'}
-                myUrl='cms/video/upload'
-                format={['image/jpeg', 'image/png']}
-                formatTxt='png、jpg和jpeg'
-                checkTxt={`请上传${type === 'img' ? '图片' : '封面图'}!`}
-                upTxt='最多1张'
-                myType='thumb'
-              />
-            </div>
-          </div>
-
-          <Form.Item label={type === 'img' ? '正文' : '简介'} name='description'>
-            <TextArea maxLength={type === 'img' ? 1000 : 200} showCount placeholder='请输入内容' />
-          </Form.Item>
-
-          {/* 附件 */}
-          {type === 'video' ? (
-            <div className='formRow'>
-              <div className='formLeft'>
-                <span>* </span>
-                附件:
-              </div>
-              <div className='formRight'>
-                <ZupOne
-                  ref={ZupFileRef}
-                  fileCheck={fileCheck}
-                  size={2000}
-                  dirCode='A1manageY'
-                  myUrl='cms/video/upload'
-                  format={['video/mp4']}
-                  formatTxt='video'
-                  checkTxt='请上传video附件!'
-                  upTxt='最多1个'
-                  myType='video'
-                />
-              </div>
-            </div>
-          ) : null}
-
-          <div className='A1fromRow'>
-            <Form.Item
-              label='排序值'
-              name='sort'
-              rules={[{ required: true, message: '请输入排序值!' }]}
-            >
-              <InputNumber min={1} max={999} precision={0} placeholder='请输入' />
-            </Form.Item>
-            <div className='A1_6Frow'>
-              请输入1~999的数字。数字越小,排序越靠前。数字相同时,更新发布的内容排在前面
-            </div>
-          </div>
-
-          {/* 确定和取消按钮 */}
-          <Form.Item className='A1Ybtn'>
-            <Button type='primary' htmlType='submit'>
-              提交
-            </Button>
-            <br />
-            <br />
-            <MyPopconfirm txtK='取消' onConfirm={closeFu} />
-          </Form.Item>
-        </Form>
-      </div>
-    </Modal>
-  )
-}
-
-const MemoA1Yadd = React.memo(A1Yadd)
-
-export default MemoA1Yadd

+ 0 - 104
src/pages/A1manage/A1ying/index.module.scss

@@ -1,104 +0,0 @@
-.A1ying {
-  position: absolute;
-  top: 0;
-  left: 0;
-  width: 100%;
-  height: 100%;
-  z-index: 12;
-  background-color: #fff;
-  border-radius: 10px;
-  :global {
-    .A1Ytop {
-      border-radius: 10px;
-      background-color: #fff;
-      padding: 15px 24px;
-      display: flex;
-      justify-content: space-between;
-      .A1YtopRow {
-        display: flex;
-        align-items: center;
-        .anticon-arrow-left {
-          cursor: pointer;
-          font-size: 30px;
-          margin-right: 24px;
-        }
-        .A1YtopBack {
-          color: var(--themeColor);
-          font-size: 18px;
-          font-weight: 700;
-          margin-right: 24px;
-        }
-      }
-    }
-  }
-}
-
-// 新增 、编辑弹窗
-.A1Yadd {
-  :global {
-    .ant-modal-close {
-      display: none;
-    }
-    .ant-modal {
-      width: 1000px !important;
-    }
-    .ant-modal-body {
-      border-top: 1px solid #ccc;
-      padding-top: 15px !important;
-    }
-
-    .A1Ymain {
-      width: 100%;
-      height: 100%;
-      overflow-y: auto;
-      position: relative;
-
-      textarea {
-        min-height: 150px !important;
-      }
-
-      .A1fromRow {
-        position: relative;
-        width: 800px;
-
-        .A1_6Frow {
-          position: absolute;
-          left: 180px;
-          top: 5px;
-          color: #999;
-          font-size: 12px;
-        }
-      }
-
-      .ant-form {
-        width: 800px;
-        .formRow {
-          display: flex;
-
-          .formLeft {
-            position: relative;
-            top: 3px;
-            width: 67px;
-            text-align: right;
-
-            & > span {
-              color: #ff4d4f;
-            }
-          }
-
-          .formRight {
-            width: calc(100% - 67px);
-          }
-        }
-
-        .A1Ybtn {
-          position: absolute;
-          z-index: 10;
-          right: 20px;
-          top: 50%;
-          transform: translateY(-50%);
-        }
-      }
-    }
-  }
-}

+ 0 - 176
src/pages/A1manage/A1ying/index.tsx

@@ -1,176 +0,0 @@
-import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
-import styles from './index.module.scss'
-import { A1_APIdelById, A1_APIgetListById } from '@/store/action/A1manage'
-import { ArrowLeftOutlined } from '@ant-design/icons'
-import { Button, Input } from 'antd'
-import MyTable from '@/components/MyTable'
-import { A1YType } from '@/types'
-import MyPopconfirm from '@/components/MyPopconfirm'
-import { MessageFu } from '@/utils/message'
-import { A2tableY1, A2tableY2 } from '@/utils/tableData'
-import A1Yadd from './A1Yadd'
-
-type FromDataType = {
-  searchKey: string
-  pageNum: number
-  pageSize: number
-  bookId: number
-  type: 'img' | 'video'
-}
-
-type Props = {
-  bookId: number
-  type: 'img' | 'video'
-  name: string
-  closeFu: () => void
-}
-
-function A1ying({ bookId, type, closeFu, name }: Props) {
-  const [fromData, setFromData] = useState({} as FromDataType)
-
-  useEffect(() => {
-    setFromData({
-      searchKey: '',
-      pageNum: 1,
-      pageSize: 10,
-      bookId,
-      type
-    })
-  }, [bookId, type])
-
-  const getListFu = useCallback(async () => {
-    if (fromData.bookId) {
-      const res = await A1_APIgetListById(fromData)
-
-      if (res.code === 0) {
-        const obj = {
-          list: res.data.records,
-          total: res.data.total
-        }
-        setTableInfo(obj)
-      }
-    }
-  }, [fromData])
-
-  useEffect(() => {
-    getListFu()
-  }, [getListFu])
-
-  // 输入框的输入
-  const [inputKey, setInputKey] = useState(1)
-  const timeRef = useRef(-1)
-  const txtChangeFu = useCallback(
-    (e: React.ChangeEvent<HTMLInputElement>, key: 'searchKey') => {
-      clearTimeout(timeRef.current)
-      timeRef.current = window.setTimeout(() => {
-        setFromData({ ...fromData, [key]: e.target.value.replaceAll("'", ''), pageNum: 1 })
-      }, 500)
-    },
-    [fromData]
-  )
-
-  // 点击重置
-  const resetSelectFu = useCallback(() => {
-    setInputKey(Date.now())
-    setFromData({
-      searchKey: '',
-      pageNum: 1,
-      pageSize: 10,
-      bookId,
-      type
-    })
-  }, [bookId, type])
-
-  // 表格数据
-  const [tableInfo, setTableInfo] = useState({
-    list: [] as A1YType[],
-    total: 0
-  })
-
-  const delTableFu = useCallback(
-    async (id: number) => {
-      const res = await A1_APIdelById(id)
-      if (res.code === 0) {
-        MessageFu.success('删除成功!')
-        getListFu()
-      }
-    },
-    [getListFu]
-  )
-
-  const tableLastBtn = useMemo(() => {
-    return [
-      {
-        title: '操作',
-        render: (item: A1YType) => (
-          <>
-            <Button size='small' type='text' onClick={() => setAddId(item.id)}>
-              编辑
-            </Button>
-            <MyPopconfirm txtK='删除' onConfirm={() => delTableFu(item.id)} />
-          </>
-        )
-      }
-    ]
-  }, [delTableFu])
-
-  // 新增和编辑
-  const [addId, setAddId] = useState(0)
-
-  return (
-    <div className={styles.A1ying}>
-      <div className='A1Ytop'>
-        <div className='A1YtopRow'>
-          <ArrowLeftOutlined onClick={closeFu} />
-          <div className='A1YtopBack'>
-            {name} - {type === 'img' ? '影印资料' : '视频资料'}
-          </div>
-          <span>搜索:</span>
-          <Input
-            key={inputKey}
-            maxLength={20}
-            style={{ width: 300 }}
-            placeholder={type === 'img' ? '请输入正文' : '请输入标题或简介'}
-            allowClear
-            onChange={e => txtChangeFu(e, 'searchKey')}
-          />
-        </div>
-        <div className='A1YtopRow'>
-          <Button onClick={resetSelectFu}>重置</Button>&emsp;
-          <Button type='primary' onClick={() => setAddId(-1)}>
-            新增
-          </Button>
-        </div>
-      </div>
-
-      <div className='A1tableBox'>
-        <MyTable
-          classKey='A1y'
-          yHeight={625}
-          list={tableInfo.list}
-          columnsTemp={type === 'img' ? A2tableY1 : A2tableY2}
-          lastBtn={tableLastBtn}
-          pageNum={fromData.pageNum}
-          pageSize={fromData.pageSize}
-          total={tableInfo.total}
-          onChange={(pageNum, pageSize) => setFromData({ ...fromData, pageNum, pageSize })}
-        />
-      </div>
-
-      {addId ? (
-        <A1Yadd
-          type={type}
-          bookId={bookId}
-          id={addId}
-          closeFu={() => setAddId(0)}
-          addTableFu={resetSelectFu}
-          editTableFu={getListFu}
-        />
-      ) : null}
-    </div>
-  )
-}
-
-const MemoA1ying = React.memo(A1ying)
-
-export default MemoA1ying

+ 0 - 19
src/pages/A1manage/data.ts

@@ -1,19 +0,0 @@
-import { A1tableType } from '@/types'
-
-export type A1FromDataType = {
-  searchKey: string
-  num: string
-
-  storageArr: number[] | undefined
-  storageId: number | null
-  exhibitTypeId: number | null
-
-  pageNum: number
-  pageSize: number
-}
-
-export type A1EditInfoType = {
-  id: number
-  txt: '新增' | '编辑' | '查看' | ''
-  info?: A1tableType
-}

+ 0 - 271
src/pages/A1manage/index.tsx

@@ -1,271 +0,0 @@
-import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
-import styles from './index.module.scss'
-import { Button, Cascader, Input, Select } from 'antd'
-import { useDispatch, useSelector } from 'react-redux'
-import { A1EditInfoType, A1FromDataType } from './data'
-import { A1_APIdel, A1_APIgetList } from '@/store/action/A1manage'
-import { RootState } from '@/store'
-import { MessageFu } from '@/utils/message'
-import { A1tableType } from '@/types'
-import MyPopconfirm from '@/components/MyPopconfirm'
-import { A2_APIgetList1, A2_APIgetList2 } from '@/store/action/A2classify'
-import MyTable from '@/components/MyTable'
-import { A1tableC } from '@/utils/tableData'
-import A1add from './A1add'
-import A1ying from './A1ying'
-import A1Import from './A1Import'
-
-const fromDataBase: A1FromDataType = {
-  searchKey: '',
-  num: '',
-
-  storageArr: undefined,
-  storageId: null,
-  exhibitTypeId: null,
-  pageNum: 1,
-  pageSize: 10
-}
-
-function A1manage() {
-  const dispatch = useDispatch()
-
-  // 获取中图法分类 和 展示分类
-
-  useEffect(() => {
-    dispatch(A2_APIgetList1())
-    dispatch(A2_APIgetList2({ pageNum: 1, pageSize: 9999, searchKey: '' }))
-  }, [dispatch])
-
-  const { treeData: storageArr, tableInfo: exhibitTypeObj } = useSelector(
-    (state: RootState) => state.A2classify
-  )
-
-  const [fromData, setFromData] = useState(fromDataBase)
-
-  const getListFu = useCallback(() => {
-    const obj: A1FromDataType = {
-      ...fromData,
-      storageId: null
-    }
-    if (fromData.storageArr && fromData.storageArr.length)
-      obj.storageId = fromData.storageArr[fromData.storageArr.length - 1]
-
-    dispatch(A1_APIgetList(obj))
-  }, [dispatch, fromData])
-
-  useEffect(() => {
-    getListFu()
-  }, [getListFu])
-
-  const [inputKey, setInputKey] = useState(1)
-
-  // 输入框的输入
-  const timeRef = useRef(-1)
-  const txtChangeFu = useCallback(
-    (e: React.ChangeEvent<HTMLInputElement>, key: 'searchKey' | 'num') => {
-      clearTimeout(timeRef.current)
-      timeRef.current = window.setTimeout(() => {
-        setFromData({ ...fromData, [key]: e.target.value.replaceAll("'", ''), pageNum: 1 })
-      }, 500)
-    },
-    [fromData]
-  )
-
-  // 点击重置
-  const resetSelectFu = useCallback(() => {
-    setInputKey(Date.now())
-    setFromData({ ...fromDataBase })
-  }, [])
-
-  const tableInfo = useSelector((state: RootState) => state.A1manage.tableInfo)
-
-  const delTableFu = useCallback(
-    async (id: number) => {
-      const res = await A1_APIdel(id)
-      if (res.code === 0) {
-        MessageFu.success('删除成功!')
-        getListFu()
-      }
-    },
-    [getListFu]
-  )
-
-  const tableLastBtn = useMemo(() => {
-    return [
-      {
-        title: '操作',
-        render: (item: A1tableType) => (
-          <>
-            <Button
-              size='small'
-              type='text'
-              onClick={() => setEditInfo({ id: item.id, txt: '查看' })}
-            >
-              查看
-            </Button>
-            <Button
-              size='small'
-              type='text'
-              onClick={() => setEditInfo({ id: item.id, txt: '编辑' })}
-            >
-              编辑
-            </Button>
-            <Button
-              size='small'
-              type='text'
-              onClick={() => setBookYing({ bookId: item.id, type: 'img', name: item.name })}
-            >
-              影印
-            </Button>
-            <Button
-              size='small'
-              type='text'
-              onClick={() => setBookYing({ bookId: item.id, type: 'video', name: item.name })}
-            >
-              视频
-            </Button>
-
-            <MyPopconfirm txtK='删除' onConfirm={() => delTableFu(item.id)} />
-          </>
-        )
-      }
-    ]
-  }, [delTableFu])
-
-  //查看、新增、编辑
-  const [editInfo, setEditInfo] = useState<A1EditInfoType>({
-    id: 0,
-    txt: ''
-  })
-
-  // 影印和视频
-  const [bookYing, setBookYing] = useState<{ bookId: number; type: 'img' | 'video'; name: string }>(
-    {
-      bookId: 0,
-      type: 'img',
-      name: ''
-    }
-  )
-
-  // 批量导入
-  const [imp, setImp] = useState(false)
-
-  return (
-    <div className={styles.A1manage}>
-      <div className='pageTitle'>图书管理 {editInfo.id ? ` - ${editInfo.txt}` : ''}</div>
-
-      {/* 顶部筛选 */}
-      <div className='A1top'>
-        <div>
-          <div className='A1TopRow'>
-            <span>搜索:</span>
-            <Input
-              key={inputKey}
-              maxLength={20}
-              style={{ width: 192 }}
-              placeholder='请输入书名/作者/出版社'
-              allowClear
-              onChange={e => txtChangeFu(e, 'searchKey')}
-            />
-            &nbsp;
-            <Input
-              key={inputKey + 1}
-              maxLength={20}
-              style={{ width: 192 }}
-              placeholder='请输入完整ISBN编号'
-              allowClear
-              onChange={e => txtChangeFu(e, 'num')}
-            />
-          </div>
-
-          <div className='A1TopRow'>
-            <span>中图法分类:</span>
-            <Cascader
-              changeOnSelect
-              style={{ width: 250 }}
-              options={storageArr}
-              fieldNames={{ label: 'name', value: 'id', children: 'children' }}
-              value={fromData.storageArr}
-              placeholder='全部'
-              onChange={e =>
-                setFromData({
-                  ...fromData,
-                  storageArr: e as number[]
-                })
-              }
-            />
-          </div>
-          <div className='A1TopRow'>
-            <span>展示分类:</span>
-            <Select
-              allowClear
-              placeholder='全部'
-              style={{ width: 180 }}
-              value={fromData.exhibitTypeId}
-              fieldNames={{ label: 'name', value: 'id' }}
-              onChange={e => setFromData({ ...fromData, pageNum: 1, exhibitTypeId: e })}
-              options={exhibitTypeObj.list}
-            />
-          </div>
-        </div>
-        <div>
-          <Button onClick={() => setImp(true)}>批量导入</Button>&emsp;
-          <Button onClick={resetSelectFu}>重置</Button>&emsp;
-          <Button type='primary' onClick={() => setEditInfo({ id: -1, txt: '新增' })}>
-            新增
-          </Button>
-        </div>
-      </div>
-
-      {/* 表格主体 */}
-      <div className='A1tableBox'>
-        <MyTable
-          yHeight={625}
-          list={tableInfo.list}
-          columnsTemp={A1tableC}
-          lastBtn={tableLastBtn}
-          pageNum={fromData.pageNum}
-          pageSize={fromData.pageSize}
-          total={tableInfo.total}
-          onChange={(pageNum, pageSize) => setFromData({ ...fromData, pageNum, pageSize })}
-        />
-      </div>
-
-      {/* 新增 / 编辑 / 查看 */}
-      {editInfo.id ? (
-        <A1add
-          editInfo={editInfo}
-          closeFu={() => setEditInfo({ id: 0, txt: '新增' })}
-          addTableFu={resetSelectFu}
-          editTableFu={getListFu}
-          storageArr={storageArr}
-          exhibitTypeArr={exhibitTypeObj.list}
-        ></A1add>
-      ) : null}
-
-      {/* 影印和视频 */}
-      {bookYing.bookId ? (
-        <A1ying
-          bookId={bookYing.bookId}
-          type={bookYing.type}
-          name={bookYing.name}
-          closeFu={() => setBookYing({ bookId: 0, type: 'img', name: '' })}
-        />
-      ) : null}
-
-      {/* 批量导入 */}
-      {imp ? (
-        <A1Import
-          storageArr={storageArr}
-          exhibitTypeArr={exhibitTypeObj.list}
-          closeFu={() => setImp(false)}
-          addTableFu={resetSelectFu}
-        />
-      ) : null}
-    </div>
-  )
-}
-
-const MemoA1manage = React.memo(A1manage)
-
-export default MemoA1manage

+ 0 - 202
src/pages/A2classify/A2add.tsx

@@ -1,202 +0,0 @@
-import React, { useCallback, useEffect, useRef, useState } from 'react'
-import styles from './index.module.scss'
-import { Button, Cascader, Form, FormInstance, Input, InputNumber, Modal } from 'antd'
-import MyPopconfirm from '@/components/MyPopconfirm'
-import { useSelector } from 'react-redux'
-import { RootState } from '@/store'
-import { A2_APIgetInfo1, A2_APIsave1 } from '@/store/action/A2classify'
-import { MessageFu } from '@/utils/message'
-import { A2TreeType } from '@/types'
-
-export type A2AddInfoType = {
-  id: number
-  txt: '新增' | '编辑'
-  acInfo: A2TreeType
-}
-
-type Props = {
-  addInfo: A2AddInfoType
-  addFu: () => void
-  closeFu: () => void
-}
-
-function A2add({ addInfo, addFu, closeFu }: Props) {
-  const treeData = useSelector((state: RootState) => state.A2classify.treeData)
-
-  // 级联选择器改变的时候 筛选当前级联的 信息出来
-  const [acCardInfo, setAcCardInfo] = useState({} as A2TreeType)
-  const [parentIdArr, setParentIdArr] = useState<number[] | null>(null)
-
-  // useEffect(() => {
-  //   console.log(acCardInfo, parentIdArr)
-  // }, [acCardInfo, parentIdArr])
-
-  useEffect(() => {
-    setAcCardInfo(addInfo.acInfo)
-
-    let ids: number[] | null = addInfo.acInfo.id ? [addInfo.acInfo.id] : null
-    if (addInfo.acInfo.ancestor)
-      ids = [...addInfo.acInfo.ancestor.split(',').map(v => Number(v)), addInfo.acInfo.id]
-
-    const idsRes = ids
-    if (ids && ids.length >= 1 && addInfo.txt === '编辑') {
-      ids.pop()
-    }
-
-    setParentIdArr(idsRes)
-  }, [addInfo.acInfo, addInfo.txt])
-
-  const cardChange = useCallback((aa: any, bb: any) => {
-    setParentIdArr(aa)
-
-    if (bb && bb.length) setAcCardInfo(bb[bb.length - 1])
-    else setAcCardInfo({} as A2TreeType)
-  }, [])
-
-  const getInfoFu = useCallback(async (id: number) => {
-    const res = await A2_APIgetInfo1(id)
-    if (res.code === 0) {
-      FormBoxRef.current?.setFieldsValue({
-        ...res.data
-      })
-    }
-  }, [])
-  useEffect(() => {
-    if (addInfo.txt === '编辑') getInfoFu(addInfo.id)
-    else {
-      FormBoxRef.current?.setFieldsValue({
-        sort: 999
-      })
-    }
-  }, [addInfo.id, addInfo.txt, getInfoFu])
-
-  // 设置表单初始数据(区分编辑和新增)
-  const FormBoxRef = useRef<FormInstance>(null)
-
-  // 没有通过校验
-  const onFinishFailed = useCallback(() => {
-    // return MessageFu.warning("有表单不符号规则!");
-  }, [])
-
-  // 通过校验点击确定
-  const onFinish = useCallback(
-    async (values: any) => {
-      let ancestor = ''
-      let parentId: number | null = null
-
-      if (parentIdArr && parentIdArr.length >= 5 && addInfo.txt === '新增')
-        return MessageFu.warning('最多支持五级!')
-
-      if (acCardInfo) parentId = addInfo.txt === '编辑' ? acCardInfo.parentId : acCardInfo.id
-      if (parentIdArr && parentId) ancestor = parentIdArr.filter(v => v !== addInfo.id).join(',')
-
-      let level = 1
-      if (parentIdArr) {
-        level = addInfo.txt === '新增' ? acCardInfo.level + 1 : acCardInfo.level
-      }
-      const obj = {
-        ...values,
-        id: addInfo.id > 0 ? addInfo.id : null,
-        ancestor,
-        level,
-        parentId
-      }
-      // console.log(123, obj)
-      // if (1 + 1 === 2) {
-      //   return
-      // }
-
-      const res = await A2_APIsave1(obj)
-
-      if (res.code === 0) {
-        MessageFu.success(addInfo.txt + '成功!')
-        addFu()
-        closeFu()
-      }
-    },
-    [acCardInfo, addFu, addInfo.id, addInfo.txt, closeFu, parentIdArr]
-  )
-  return (
-    <Modal
-      wrapClassName={styles.A2add}
-      open={true}
-      title={`${addInfo.txt} - 中图法分类`}
-      footer={
-        [] // 设置footer为空,去掉 取消 确定默认按钮
-      }
-    >
-      <div className='A2aMain'>
-        <Form
-          scrollToFirstError={true}
-          ref={FormBoxRef}
-          name='basic'
-          labelCol={{ span: 3 }}
-          onFinish={onFinish}
-          onFinishFailed={onFinishFailed}
-          autoComplete='off'
-        >
-          <div className='fromRow'>
-            <div className='fromRowll'>父级分类:</div>
-            <div className='fromRowrr'>
-              <Cascader
-                style={{ width: 658 }}
-                disabled={addInfo.txt === '编辑'}
-                changeOnSelect
-                fieldNames={{ label: 'name', value: 'id', children: 'children' }}
-                options={treeData}
-                placeholder={addInfo.txt === '编辑' ? '空' : '请选择'}
-                value={parentIdArr ? [...parentIdArr] : []}
-                onChange={cardChange}
-              />
-            </div>
-          </div>
-
-          <Form.Item
-            label='分类编号'
-            name='num'
-            rules={[{ required: true, message: '请输入分类编号!' }]}
-            getValueFromEvent={e => e.target.value.replace(/\s+/g, '')}
-          >
-            <Input maxLength={20} showCount placeholder='请输入内容' />
-          </Form.Item>
-
-          <Form.Item
-            label='分类名称'
-            name='name'
-            rules={[{ required: true, message: '请输入分类名称!' }]}
-            getValueFromEvent={e => e.target.value.replace(/\s+/g, '')}
-          >
-            <Input maxLength={20} showCount placeholder='请输入内容' />
-          </Form.Item>
-
-          <div className='fromRow2'>
-            <Form.Item
-              label='排序值'
-              name='sort'
-              rules={[{ required: true, message: '请输入排序值!' }]}
-            >
-              <InputNumber min={1} max={999} precision={0} placeholder='请输入' />
-            </Form.Item>
-            <div className='fromRowTit'>
-              请输入1~999的数字。数字越小,排序越靠前。数字相同时,更新发布的内容排在前面
-            </div>
-          </div>
-
-          {/* 确定和取消按钮 */}
-          <br />
-          <Form.Item wrapperCol={{ offset: 9, span: 16 }}>
-            <Button type='primary' htmlType='submit'>
-              提交
-            </Button>
-            &emsp;
-            <MyPopconfirm txtK='取消' onConfirm={closeFu} />
-          </Form.Item>
-        </Form>
-      </div>
-    </Modal>
-  )
-}
-
-const MemoA2add = React.memo(A2add)
-
-export default MemoA2add

+ 0 - 113
src/pages/A2classify/A2add2.tsx

@@ -1,113 +0,0 @@
-import React, { useCallback, useEffect, useRef } from 'react'
-import styles from './index.module.scss'
-import { Button, Form, FormInstance, Input, InputNumber, Modal } from 'antd'
-import MyPopconfirm from '@/components/MyPopconfirm'
-import { A2_APIgetInfo2, A2_APIsave2 } from '@/store/action/A2classify'
-import { MessageFu } from '@/utils/message'
-
-type Props = {
-  tab2Id: number
-  addFu: (flag: boolean) => void
-  closeFu: () => void
-}
-
-function A2add2({ tab2Id, addFu, closeFu }: Props) {
-  // 设置表单初始数据(区分编辑和新增)
-  const FormBoxRef = useRef<FormInstance>(null)
-
-  const getInfoFu = useCallback(async (id: number) => {
-    const res = await A2_APIgetInfo2(id)
-    if (res.code === 0) {
-      FormBoxRef.current?.setFieldsValue({
-        ...res.data
-      })
-    }
-  }, [])
-  useEffect(() => {
-    if (tab2Id > 0) getInfoFu(tab2Id)
-    else {
-      FormBoxRef.current?.setFieldsValue({
-        sort: 999
-      })
-    }
-  }, [getInfoFu, tab2Id])
-
-  // 没有通过校验
-  const onFinishFailed = useCallback(() => {
-    // return MessageFu.warning("有表单不符号规则!");
-  }, [])
-
-  // 通过校验点击确定
-  const onFinish = useCallback(
-    async (values: any) => {
-      const res = await A2_APIsave2({
-        ...values,
-        id: tab2Id > 0 ? tab2Id : null
-      })
-      if (res.code === 0) {
-        MessageFu.success(tab2Id > 0 ? '编辑成功!' : '新增成功!')
-        addFu(tab2Id > 0 ? true : false)
-        closeFu()
-      }
-    },
-    [addFu, closeFu, tab2Id]
-  )
-  return (
-    <Modal
-      wrapClassName={styles.A2add}
-      open={true}
-      title={`${tab2Id > 0 ? '编辑' : '新增'} - 展示分类`}
-      footer={
-        [] // 设置footer为空,去掉 取消 确定默认按钮
-      }
-    >
-      <div className='A2aMain'>
-        <Form
-          scrollToFirstError={true}
-          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={20} showCount placeholder='请输入内容' />
-          </Form.Item>
-
-          <div className='fromRow2'>
-            <Form.Item
-              label='排序值'
-              name='sort'
-              rules={[{ required: true, message: '请输入排序值!' }]}
-            >
-              <InputNumber min={1} max={999} precision={0} placeholder='请输入' />
-            </Form.Item>
-            <div className='fromRowTit'>
-              请输入1~999的数字。数字越小,排序越靠前。数字相同时,更新发布的内容排在前面
-            </div>
-          </div>
-
-          {/* 确定和取消按钮 */}
-          <br />
-          <Form.Item wrapperCol={{ offset: 9, span: 16 }}>
-            <Button type='primary' htmlType='submit'>
-              提交
-            </Button>
-            &emsp;
-            <MyPopconfirm txtK='取消' onConfirm={closeFu} />
-          </Form.Item>
-        </Form>
-      </div>
-    </Modal>
-  )
-}
-
-const MemoA2add2 = React.memo(A2add2)
-
-export default MemoA2add2

+ 0 - 18
src/pages/A2classify/data.ts

@@ -1,18 +0,0 @@
-export const treeResIdFu = (list: any, id: number) => {
-  // 每次进来使用find遍历一次
-  let res = list.find((item: any) => item.id === id)
-
-  if (res) {
-    return res
-  } else {
-    for (let i = 0; i < list.length; i++) {
-      if (list[i].children instanceof Array && list[i].children.length > 0) {
-        res = treeResIdFu(list[i].children, id)
-
-        if (res) return res
-      }
-    }
-
-    return null
-  }
-}

+ 0 - 123
src/pages/A2classify/index.module.scss

@@ -1,123 +0,0 @@
-.A2classify {
-  background-color: #fff;
-  border-radius: 10px;
-  padding: 20px 24px;
-  position: relative;
-  :global {
-    .A2top {
-      display: flex;
-      justify-content: space-between;
-      height: 40px;
-      align-items: center;
-      .A2top1 {
-        display: flex;
-        align-items: center;
-      }
-    }
-    .A2main {
-      margin-top: 15px;
-      height: calc(100% - 50px);
-      & > div {
-        height: 100%;
-      }
-      .A2Null {
-        width: 100%;
-        height: 300px;
-        font-size: 24px;
-        display: flex;
-        justify-content: center;
-        align-items: center;
-      }
-      .A2m1 {
-        display: flex;
-        justify-content: space-between;
-        .A2m1ll {
-          width: 40%;
-          background-color: #e8e8e8;
-          padding: 20px;
-          overflow-y: auto;
-          .site-tree-search-value {
-            color: red;
-            font-weight: 700;
-          }
-          .ant-tree {
-            min-height: 100%;
-            padding: 10px;
-          }
-        }
-        .A2m1rr {
-          width: calc(60% - 24px);
-          border: 1px solid #ccc;
-          padding: 20px;
-          .A2mr1 {
-            font-weight: 700;
-            color: var(--themeColor);
-            font-size: 24px;
-          }
-          .A2mr2 {
-            margin: 20px 0 40px;
-          }
-
-          .A2mr3 {
-            display: flex;
-            font-size: 20px;
-            margin-bottom: 30px;
-            .A2mr3ll {
-              width: 100px;
-              text-align: right;
-              font-weight: 700;
-            }
-            .A2mr3rr {
-              width: calc(100% - 100px);
-            }
-          }
-        }
-      }
-    }
-  }
-}
-
-// 新增弹窗页面
-.A2add {
-  :global {
-    .ant-modal-close {
-      display: none;
-    }
-
-    .ant-modal {
-      width: 800px !important;
-    }
-
-    .ant-modal-body {
-      border-top: 1px solid #ccc;
-    }
-
-    .A2aMain {
-      padding-top: 15px;
-      .fromRow2 {
-        position: relative;
-
-        .fromRowTit {
-          position: absolute;
-          left: 200px;
-          top: 5px;
-          color: #999;
-          font-size: 12px;
-        }
-      }
-      .fromRow {
-        display: flex;
-        align-items: center;
-        margin-bottom: 24px;
-        .fromRowll {
-          width: 94px;
-          text-align: right;
-          position: relative;
-        }
-        .fromRowrr {
-          width: calc(100% - 94px);
-        }
-      }
-    }
-  }
-}

+ 0 - 337
src/pages/A2classify/index.tsx

@@ -1,337 +0,0 @@
-import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
-import styles from './index.module.scss'
-import { Button, Input, Tree, TreeDataNode } from 'antd'
-import { treeResIdFu } from './data'
-import { useDispatch, useSelector } from 'react-redux'
-import { RootState } from '@/store'
-import { A2_APIdel1, A2_APIdel2, A2_APIgetList1, A2_APIgetList2 } from '@/store/action/A2classify'
-import MyPopconfirm from '@/components/MyPopconfirm'
-import { MessageFu } from '@/utils/message'
-import A2add, { A2AddInfoType } from './A2add'
-import { A2tableType, A2TreeType } from '@/types'
-import MyTable from '@/components/MyTable'
-import { A2tableC } from '@/utils/tableData'
-import A2add2 from './A2add2'
-
-export type TopLeftArrType = '中图法分类' | '展示分类'
-
-const topLeftArr: TopLeftArrType[] = ['中图法分类', '展示分类']
-
-function A2classify() {
-  const { treeData: treeDataTemp, treeFlag } = useSelector((state: RootState) => state.A2classify)
-  const dispatch = useDispatch()
-
-  const [topType, setTopType] = useState<TopLeftArrType>('中图法分类')
-
-  const getList1 = useCallback(() => {
-    dispatch(A2_APIgetList1())
-  }, [dispatch])
-
-  const getList2 = useCallback(
-    async (val: string) => {
-      dispatch(A2_APIgetList2({ pageNum: 1, pageSize: 9999, searchKey: val }))
-    },
-    [dispatch]
-  )
-
-  useEffect(() => {
-    getList1()
-  }, [getList1])
-
-  // 点击重置
-  const resetSelectFu = useCallback(
-    (flag?: boolean) => {
-      setValue('')
-      if (topType === '展示分类') getList2('')
-      if (flag) getList1()
-    },
-    [getList1, getList2, topType]
-  )
-
-  // 顶部切换tab
-  const cutTop = useCallback(
-    (item: TopLeftArrType) => {
-      setValue('')
-      setTopType(item)
-      item === '中图法分类' ? getList1() : getList2('')
-    },
-    [getList1, getList2]
-  )
-
-  const [value, setValue] = useState('')
-
-  const time = useRef(-1)
-  const valueChange = useCallback(
-    (val: string) => {
-      setValue(val)
-      clearInterval(time.current)
-      time.current = window.setTimeout(() => {
-        if (topType === '展示分类') getList2(val)
-        // topType === '中图法分类' ? getList1(val) : getList2(val)
-      }, 500)
-    },
-    [getList2, topType]
-  )
-
-  // 有关树------------------------
-  const tab1Flag = useRef(true)
-  useEffect(() => {
-    if (treeDataTemp && treeDataTemp.length && tab1Flag.current) {
-      tab1Flag.current = false
-      setAcShu(treeDataTemp[0].id as number)
-    }
-  }, [treeDataTemp])
-
-  // 当前选中的树节点ID
-  const [acShu, setAcShu] = useState(0)
-
-  // 点击树节点
-  const onSelect = (id: any) => {
-    if (id[0]) setAcShu(id[0])
-  }
-
-  // 搜索高亮
-  const treeData = useMemo(() => {
-    const loop = (dataTemp: any[]): TreeDataNode[] => {
-      const data = dataTemp || []
-
-      return data.map(item => {
-        const strTitle = ((item.num ? item.num + ' ' : '') + item.name) as string
-
-        const index = strTitle.indexOf(value)
-
-        const beforeStr = strTitle.substring(0, index)
-        const afterStr = strTitle.slice(index + value.length)
-        const title =
-          index > -1 ? (
-            <span key={item.id}>
-              {beforeStr}
-              <span className='site-tree-search-value'>{value}</span>
-              {afterStr}
-            </span>
-          ) : (
-            <span key={item.id}>{strTitle}</span>
-          )
-        if (item.children) {
-          return { title, key: item.id, children: loop(item.children) }
-        }
-        return {
-          title,
-          key: item.id
-        }
-      })
-    }
-
-    return loop(treeDataTemp)
-  }, [treeDataTemp, value])
-
-  // 右侧信息
-  const rightData = useMemo(() => {
-    let obj = {} as A2TreeType
-
-    obj = treeResIdFu(treeDataTemp, acShu)
-
-    return obj || {}
-  }, [acShu, treeDataTemp])
-
-  // 点击删除
-  const delTree = useCallback(
-    async (id: number) => {
-      const res = await A2_APIdel1(id)
-      if (res.code === 0) {
-        MessageFu.success('删除成功!')
-        tab1Flag.current = true
-        getList1()
-      }
-    },
-    [getList1]
-  )
-
-  // 点击新增和编辑
-  const [addInfo, setAddInfo] = useState({} as A2AddInfoType)
-
-  const addSonFu = useCallback(
-    (id: number) => {
-      setAddInfo({
-        id,
-        txt: id > 0 ? '编辑' : '新增',
-        acInfo: rightData
-      })
-    },
-    [rightData]
-  )
-
-  // -----------------展示分类
-  const tableInfo = useSelector((state: RootState) => state.A2classify.tableInfo)
-
-  const delTableFu = useCallback(
-    async (id: number) => {
-      const res = await A2_APIdel2(id)
-      if (res.code === 0) {
-        MessageFu.success('删除成功!')
-        getList2(value)
-      }
-    },
-    [getList2, value]
-  )
-  const tableLastBtn = useMemo(() => {
-    return [
-      {
-        title: '操作',
-        render: (item: A2tableType) => (
-          <>
-            <Button size='small' type='text' onClick={() => setTab2Id(item.id)}>
-              编辑
-            </Button>
-            <MyPopconfirm txtK='删除' onConfirm={() => delTableFu(item.id)} />
-          </>
-        )
-      }
-    ]
-  }, [delTableFu])
-
-  // tab新增/编辑
-  const [tab2Id, setTab2Id] = useState(0)
-
-  return (
-    <div className={styles.A2classify}>
-      <div className='pageTitle'>图书分类</div>
-      {/* 顶部 */}
-      <div className='A2top'>
-        <div className='A2top1'>
-          {topLeftArr.map(item => (
-            <Button
-              onClick={() => cutTop(item)}
-              key={item}
-              type={topType === item ? 'primary' : 'default'}
-            >
-              {item}
-            </Button>
-          ))}
-        </div>
-        <div className='A2top1'>
-          <Input
-            style={{ width: 240 }}
-            placeholder={topType === '中图法分类' ? '请输入分类名称/编号' : '请输入标题'}
-            value={value}
-            onChange={e => valueChange(e.target.value)}
-          />
-          &emsp;
-          <Button onClick={() => resetSelectFu()}>重置</Button>&emsp;
-          <Button
-            type='primary'
-            onClick={() =>
-              topType === '展示分类'
-                ? setTab2Id(-1)
-                : setAddInfo({ id: -1, txt: '新增', acInfo: rightData })
-            }
-          >
-            新增
-          </Button>
-        </div>
-      </div>
-
-      {/* 主体 */}
-      <div className='A2main'>
-        <div className='A2m1' hidden={topType !== '中图法分类'}>
-          <div className='A2m1ll'>
-            {treeDataTemp && treeDataTemp.length ? (
-              <Tree
-                // 默认全部展开
-                defaultExpandAll={true}
-                // 数据
-                treeData={treeData}
-                // 自定义字段
-                // fieldNames={{ title: 'title', key: 'key', children: 'children' }}
-                // 选中
-                selectedKeys={[acShu]}
-                // 点击
-                onSelect={onSelect}
-              />
-            ) : treeFlag ? (
-              <div className='A2Null'>暂无数据</div>
-            ) : null}
-          </div>
-          <div className='A2m1rr'>
-            <div className='A2mr1'>分类详情</div>
-
-            {rightData.id ? (
-              <>
-                <div className='A2mr2'>
-                  <Button type='text' onClick={() => addSonFu(rightData.id)}>
-                    编辑
-                  </Button>
-                  &emsp;
-                  <MyPopconfirm txtK='删除' onConfirm={() => delTree(rightData.id)} />
-                </div>
-
-                <div className='A2mr3'>
-                  <div className='A2mr3ll'>分类编号:</div>
-                  <div className='A2mr3rr'>{rightData.num}</div>
-                </div>
-
-                <div className='A2mr3'>
-                  <div className='A2mr3ll'>分类名称:</div>
-                  <div className='A2mr3rr'>{rightData.name}</div>
-                </div>
-
-                <div className='A2mr3'>
-                  <div className='A2mr3ll'>层级:</div>
-                  <div className='A2mr3rr'>{rightData.level}</div>
-                </div>
-
-                <div className='A2mr3'>
-                  <div className='A2mr3ll'>排序值:</div>
-                  <div className='A2mr3rr'>{rightData.sort}</div>
-                </div>
-
-                <div className='A2mr3'>
-                  <div className='A2mr3ll'>编辑时间:</div>
-                  <div className='A2mr3rr'>{rightData.updateTime}</div>
-                </div>
-
-                <div className='A2mr3'>
-                  <div className='A2mr3ll'>编辑人:</div>
-                  <div className='A2mr3rr'>{rightData.creatorName}</div>
-                </div>
-              </>
-            ) : treeFlag ? (
-              <div className='A2Null'>暂无数据</div>
-            ) : null}
-          </div>
-        </div>
-        <div className='A2m2' hidden={topType !== '展示分类'}>
-          <MyTable
-            yHeight={678}
-            list={tableInfo.list}
-            columnsTemp={A2tableC}
-            lastBtn={tableLastBtn}
-            pagingInfo={false}
-          />
-        </div>
-      </div>
-
-      {/* 新增/编辑页面 中图法分类 */}
-      {addInfo.id ? (
-        <A2add
-          addInfo={addInfo}
-          addFu={() => resetSelectFu(true)}
-          closeFu={() => setAddInfo({} as A2AddInfoType)}
-        />
-      ) : null}
-
-      {/* 新增/编辑 展示分类 */}
-      {tab2Id ? (
-        <A2add2
-          tab2Id={tab2Id}
-          addFu={flag => (flag ? getList2(value) : resetSelectFu())}
-          closeFu={() => setTab2Id(0)}
-        />
-      ) : null}
-    </div>
-  )
-}
-
-const MemoA2classify = React.memo(A2classify)
-
-export default MemoA2classify

+ 65 - 0
src/pages/A2introduction/index.module.scss

@@ -0,0 +1,65 @@
+.A2introduction {
+  width: 100%;
+  height: 100%;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  :global {
+    .A2containerBox {
+      border-radius: 10px;
+      overflow: hidden;
+      margin-top: 15px;
+      height: 100%;
+      width: 100%;
+      background-color: #fff;
+      .introduction {
+        font-size: 20px;
+        font-weight: bold;
+        padding: 20px 45px;
+        color: var(--themeColor);
+      }
+      .introBox {
+        display: flex;
+        padding-top: 40px;
+        height: 100%;
+        .introLeft {
+          width: 165px;
+          display: flex;
+          font-size: 16px;
+          color: var(--themeColor2);
+          padding: 10px 45px;
+          flex-direction: column;
+          gap: 10px;
+        }
+        .introRight {
+          padding: 10px 0;
+          padding-bottom: 100px;
+          width: 1000px;
+          height: 800px;
+          overflow: auto;
+          &::-webkit-scrollbar {
+            display: none;
+          }
+          font-size: 16px;
+          line-height: 24px;
+          & > img {
+            width: 100%;
+            padding: 10px 0;
+            object-fit: contain;
+          }
+        }
+      }
+
+      .btnBox {
+        display: flex;
+        padding: 20px 165px;
+        gap: 20px;
+        position: absolute;
+        bottom: 0;
+        left: 0;
+        width: 100%;
+        background-color: #fff;
+      }
+    }
+  }
+}

+ 114 - 0
src/pages/A2introduction/index.tsx

@@ -0,0 +1,114 @@
+import React, { useEffect, useRef, useState } from 'react'
+import { Button, message } from 'antd'
+import styles from './index.module.scss'
+import ZRichTexts from '@/components/ZRichTexts'
+import { A2_APIaddOrEdit, A2_APIgetInfo } from '@/store/action/A2introduction'
+import { A2AddType, A2editType } from '@/types/api/A2introduction'
+import { SectionArrType } from '@/components/ZRichTexts'
+const A2introduction = () => {
+  const [isEdit, setIsEdit] = useState(false)
+  const [data, setData] = useState<any>({})
+  const ZRichTextRef = useRef<any>(null)
+
+  const getInfo = async () => {
+    const res = await A2_APIgetInfo(1)
+    if (res.data) {
+      const arr: SectionArrType[] = [
+        {
+          id: res.data.carouselId,
+          name: '克博简介',
+          txt: res.data.context,
+          fileInfo: { fileName: '', filePath: '' }
+        }
+      ]
+      setData(res.data)
+      ZRichTextRef.current?.ritxtShowFu({ txtArr: arr })
+    }
+  }
+
+  useEffect(() => {
+    getInfo()
+  }, [])
+
+  const editFu = () => {
+    setIsEdit(true)
+    getInfo()
+  }
+
+  const publishFu = () => {
+    const obj = ZRichTextRef.current?.fatherBtnOkFu()
+    console.log(obj, 'obj')
+    const addObj: A2AddType = {
+      context: obj.val.txtArr[0].txt,
+      type: 1
+    }
+    const editObj: A2editType = {
+      carouselId: data.carouselId,
+      context: obj.val.txtArr[0].txt,
+      type: 1
+    }
+    const params = data.carouselId ? editObj : addObj
+    // 添加与修改是同一个接口,区别在于是否传入carouselId
+    if (!obj.flag) {
+      A2_APIaddOrEdit(params).then((res: any) => {
+        if (res.code === 0) {
+          message.success('发布成功')
+          setIsEdit(false)
+          getInfo()
+        }
+      })
+    }
+  }
+
+  return (
+    <div className={styles.A2introduction}>
+      <div className='pageTitle'>克博简介</div>
+      <div className='A2containerBox'>
+        <div className='introduction'>克博简介</div>
+        {!isEdit ? (
+          <div className='introBox'>
+            <div className='introLeft'>
+              <div>简介:</div>
+              <Button type='primary' onClick={editFu}>
+                修改
+              </Button>
+            </div>
+            <div
+              className='introRight'
+              dangerouslySetInnerHTML={{ __html: data.context || '暂无内容' }}
+            ></div>
+          </div>
+        ) : (
+          <>
+            <div className='introBox'>
+              <div className='introLeft'>
+                <div>简介:</div>
+              </div>
+              <div className='introRight'>
+                <ZRichTexts
+                  check={true}
+                  dirCode={'A2introduction'}
+                  isLook={false}
+                  ref={ZRichTextRef}
+                  myUrl='museum/upload/upload'
+                  isOne={true}
+                  upAudioBtnNone={true}
+                />
+              </div>
+            </div>
+            <div className='btnBox'>
+              <Button type='primary' onClick={publishFu}>
+                发布
+              </Button>
+              <Button onClick={() => setIsEdit(false)}>取消</Button>
+            </div>
+          </>
+        )}
+      </div>
+    </div>
+  )
+}
+
+const MemoA2introduction = React.memo(A2introduction)
+
+export default MemoA2introduction

+ 65 - 0
src/pages/A3map/index.module.scss

@@ -0,0 +1,65 @@
+.A3map {
+  width: 100%;
+  height: 100%;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  :global {
+    .A3containerBox {
+      border-radius: 10px;
+      overflow: hidden;
+      margin-top: 15px;
+      height: 100%;
+      width: 100%;
+      background-color: #fff;
+      .introduction {
+        font-size: 20px;
+        font-weight: bold;
+        padding: 20px 45px;
+        color: var(--themeColor);
+      }
+      .introBox {
+        display: flex;
+        padding-top: 40px;
+        height: 100%;
+        .introLeft {
+          width: 165px;
+          display: flex;
+          font-size: 16px;
+          color: var(--themeColor2);
+          padding: 10px 45px;
+          flex-direction: column;
+          gap: 10px;
+        }
+        .introRight {
+          padding: 10px 0;
+          padding-bottom: 100px;
+          width: 1000px;
+          height: 800px;
+          overflow: auto;
+          &::-webkit-scrollbar {
+            display: none;
+          }
+          font-size: 16px;
+          line-height: 24px;
+          & > img {
+            width: 100%;
+            padding: 10px 0;
+            object-fit: contain;
+          }
+        }
+      }
+
+      .btnBox {
+        display: flex;
+        padding: 20px 165px;
+        gap: 20px;
+        position: absolute;
+        bottom: 0;
+        left: 0;
+        width: 100%;
+        background-color: #fff;
+      }
+    }
+  }
+}

+ 114 - 0
src/pages/A3map/index.tsx

@@ -0,0 +1,114 @@
+import React, { useEffect, useRef, useState } from 'react'
+import { Button, message } from 'antd'
+import styles from './index.module.scss'
+import ZRichTexts from '@/components/ZRichTexts'
+import { A2_APIaddOrEdit, A2_APIgetInfo } from '@/store/action/A2introduction'
+import { A2AddType, A2editType } from '@/types/api/A2introduction'
+import { SectionArrType } from '@/components/ZRichTexts'
+const A3map = () => {
+  const [isEdit, setIsEdit] = useState(false)
+  const [data, setData] = useState<any>({})
+  const ZRichTextRef = useRef<any>(null)
+
+  const getInfo = async () => {
+    const res = await A2_APIgetInfo(2)
+    if (res.data) {
+      const arr: SectionArrType[] = [
+        {
+          id: res.data.carouselId,
+          name: '克博地图',
+          txt: res.data.context,
+          fileInfo: { fileName: '', filePath: '' }
+        }
+      ]
+      setData(res.data)
+      ZRichTextRef.current?.ritxtShowFu({ txtArr: arr })
+    }
+  }
+
+  useEffect(() => {
+    getInfo()
+  }, [])
+
+  const editFu = () => {
+    setIsEdit(true)
+    getInfo()
+  }
+
+  const publishFu = () => {
+    const obj = ZRichTextRef.current?.fatherBtnOkFu()
+    console.log(obj, 'obj')
+    const addObj: A2AddType = {
+      context: obj.val.txtArr[0].txt,
+      type: 2
+    }
+    const editObj: A2editType = {
+      carouselId: data.carouselId,
+      context: obj.val.txtArr[0].txt,
+      type: 2
+    }
+    const params = data.carouselId ? editObj : addObj
+    // 添加与修改是同一个接口,区别在于是否传入carouselId
+    if (!obj.flag) {
+      A2_APIaddOrEdit(params).then((res: any) => {
+        if (res.code === 0) {
+          message.success('发布成功')
+          setIsEdit(false)
+          getInfo()
+        }
+      })
+    }
+  }
+
+  return (
+    <div className={styles.A3map}>
+      <div className='pageTitle'>克博地图</div>
+      <div className='A3containerBox'>
+        <div className='introduction'>克博地图</div>
+        {!isEdit ? (
+          <div className='introBox'>
+            <div className='introLeft'>
+              <div>简介:</div>
+              <Button type='primary' onClick={editFu}>
+                修改
+              </Button>
+            </div>
+            <div
+              className='introRight'
+              dangerouslySetInnerHTML={{ __html: data.context || '暂无内容' }}
+            ></div>
+          </div>
+        ) : (
+          <>
+            <div className='introBox'>
+              <div className='introLeft'>
+                <div>简介:</div>
+              </div>
+              <div className='introRight'>
+                <ZRichTexts
+                  check={true}
+                  dirCode={'A2introduction'}
+                  isLook={false}
+                  ref={ZRichTextRef}
+                  myUrl='museum/upload/upload'
+                  isOne={true}
+                  upAudioBtnNone={true}
+                />
+              </div>
+            </div>
+            <div className='btnBox'>
+              <Button type='primary' onClick={publishFu}>
+                发布
+              </Button>
+              <Button onClick={() => setIsEdit(false)}>取消</Button>
+            </div>
+          </>
+        )}
+      </div>
+    </div>
+  )
+}
+
+const MemoA3map = React.memo(A3map)
+
+export default MemoA3map

+ 0 - 163
src/pages/A3recommend/A3add.tsx

@@ -1,163 +0,0 @@
-import React, { useCallback, useEffect, useState } from 'react'
-import styles from './index.module.scss'
-import { Button, InputNumber, Modal, Select } from 'antd'
-import MyPopconfirm from '@/components/MyPopconfirm'
-import { A1_APIgetSelect, A3_APIgetInfo, A3_APIsave } from '@/store/action/A3recommend'
-import { MessageFu } from '@/utils/message'
-
-type Props = {
-  type: 'index' | 'rank'
-  id: number
-  closeFu: () => void
-  addTableFu: () => void
-}
-
-function A3add({ type, id, closeFu, addTableFu }: Props) {
-  const getSelect = useCallback(async () => {
-    const res = await A1_APIgetSelect()
-    if (res.code === 0) {
-      setSelectArr(res.data.records.map((v: any) => ({ value: v.id, name: v.name, num: v.num })))
-    }
-  }, [])
-
-  useEffect(() => {
-    getSelect()
-  }, [getSelect])
-
-  const getInfo = useCallback(async (id: number) => {
-    const res = await A3_APIgetInfo(id)
-    if (res.code === 0) {
-      setName(res.data.bookId)
-      if (res.data.num) setNum(res.data.bookId)
-
-      setSort(res.data.sort)
-    }
-  }, [])
-
-  useEffect(() => {
-    if (id > 0) getInfo(id)
-  }, [getInfo, id])
-
-  const [selectArr, setSelectArr] = useState<{ value: number; name: string; num: string }[]>([])
-
-  const [name, setName] = useState<number | null>(null)
-  const [num, setNum] = useState<number | null>(null)
-
-  const [sort, setSort] = useState<number>(999)
-
-  const onChange = useCallback(
-    (value: number) => {
-      setName(value)
-
-      const obj = selectArr.find(v => v.value === value)!
-
-      if (obj.num) setNum(value)
-      else setNum(null)
-    },
-    [selectArr]
-  )
-
-  // 拿来占位,不然会报错
-  const onSearch = useCallback((value: string) => {
-    // console.log(`search ${value}`)
-  }, [])
-
-  const btnOk = useCallback(async () => {
-    if (!Number(name)) return MessageFu.warning('请输入书名!')
-    if (!sort) return MessageFu.warning('请输入排序值!')
-
-    const obj = {
-      id: id > 0 ? id : null,
-      type,
-      bookId: Number(name),
-      sort
-    }
-
-    const res = await A3_APIsave(obj)
-    if (res.code === 0) {
-      MessageFu.success(id > 0 ? '编辑成功!' : '新增成功!')
-      addTableFu()
-      closeFu()
-    }
-  }, [addTableFu, closeFu, id, name, sort, type])
-
-  return (
-    <Modal
-      wrapClassName={styles.A3add}
-      open={true}
-      title={id > 0 ? '编辑' : '新增'}
-      footer={
-        [] // 设置footer为空,去掉 取消 确定默认按钮
-      }
-    >
-      <div className='formRow'>
-        <div className='formLeft'>
-          <span>*</span>书名:
-        </div>
-        <div className='formRight'>
-          <Select
-            showSearch
-            value={name}
-            maxLength={20}
-            placeholder={'请输入内容模糊搜索'}
-            style={{ width: 400 }}
-            onChange={onChange}
-            onSearch={onSearch}
-            fieldNames={{ label: 'name', value: 'value' }}
-            optionFilterProp='name'
-            options={selectArr}
-          />
-        </div>
-      </div>
-
-      <div className='formRow'>
-        <div className='formLeft'>ISBN编号:</div>
-        <div className='formRight'>
-          <Select
-            showSearch
-            value={num}
-            maxLength={20}
-            placeholder={'请输入内容模糊搜索'}
-            style={{ width: 400 }}
-            onChange={onChange}
-            onSearch={onSearch}
-            fieldNames={{ label: 'num', value: 'value' }}
-            optionFilterProp='num'
-            options={selectArr.filter(v => v.num)}
-          />
-        </div>
-      </div>
-
-      <div className='formRow'>
-        <div className='formLeft'>
-          <span>*</span>排序值:
-        </div>
-        <div className='formRight'>
-          <InputNumber
-            value={sort}
-            onChange={e => setSort(e ? e : 1)}
-            min={1}
-            max={999}
-            precision={0}
-            placeholder='请输入'
-          />
-          <div className='formRightTit'>
-            请输入1~999的数字。数字越小,排序越靠前。数字相同时,更新发布的内容排在前面
-          </div>
-        </div>
-      </div>
-
-      <div className='A3abtn'>
-        <Button type='primary' onClick={btnOk}>
-          提交
-        </Button>
-        &emsp;
-        <MyPopconfirm txtK='取消' onConfirm={closeFu} />
-      </div>
-    </Modal>
-  )
-}
-
-const MemoA3add = React.memo(A3add)
-
-export default MemoA3add

+ 0 - 7
src/pages/A3recommend/data.ts

@@ -1,7 +0,0 @@
-export type A3FromDataType = {
-  type: 'index' | 'rank'
-  searchKey: string
-  num: string
-  pageNum: number
-  pageSize: number
-}

+ 0 - 78
src/pages/A3recommend/index.module.scss

@@ -1,78 +0,0 @@
-.A3recommend {
-  position: relative;
-  :global {
-    .A3top {
-      border-radius: 10px;
-      background-color: #fff;
-      padding: 15px 24px;
-      display: flex;
-      justify-content: space-between;
-      & > div {
-        display: flex;
-        .A3TopRow {
-          display: flex;
-          align-items: center;
-          margin-right: 20px;
-          .ant-select-selection-placeholder {
-            color: black;
-          }
-        }
-      }
-    }
-    .A3tableBox {
-      border-radius: 10px;
-      overflow: hidden;
-      margin-top: 15px;
-      height: calc(100% - 77px);
-      background-color: #fff;
-    }
-  }
-}
-
-// 新增 、编辑弹窗
-.A3add {
-  :global {
-    .ant-modal-close {
-      display: none;
-    }
-    .ant-modal {
-      width: 800px !important;
-    }
-    .ant-modal-body {
-      border-top: 1px solid #ccc;
-      padding-top: 15px !important;
-    }
-
-    .formRow {
-      display: flex;
-      align-items: center;
-      margin-bottom: 24px;
-
-      .formLeft {
-        width: 80px;
-        text-align: right;
-
-        & > span {
-          color: #ff4d4f;
-        }
-      }
-
-      .formRight {
-        width: calc(100% - 80px);
-        position: relative;
-        .formRightTit {
-          position: absolute;
-          left: 110px;
-          top: 5px;
-          color: #999;
-          font-size: 12px;
-        }
-      }
-    }
-
-    .A3abtn {
-      text-align: center;
-      margin-top: 30px;
-    }
-  }
-}

+ 0 - 181
src/pages/A3recommend/index.tsx

@@ -1,181 +0,0 @@
-import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
-import styles from './index.module.scss'
-import { Button, Input } from 'antd'
-import { useDispatch, useSelector } from 'react-redux'
-import { A3FromDataType } from './data'
-import { A3_APIdel, A3_APIgetList } from '@/store/action/A3recommend'
-import { RootState } from '@/store'
-import { MessageFu } from '@/utils/message'
-import { A3tableType } from '@/types'
-import MyPopconfirm from '@/components/MyPopconfirm'
-import MyTable from '@/components/MyTable'
-import { A3tableC } from '@/utils/tableData'
-import A3add from './A3add'
-
-const fromDataBase: A3FromDataType = {
-  type: 'index',
-  searchKey: '',
-  num: '',
-  pageNum: 1,
-  pageSize: 9999
-}
-
-const topTypeArr: { name: string; key: 'index' | 'rank' }[] = [
-  {
-    name: '首页推荐',
-    key: 'index'
-  },
-  {
-    name: '排行榜推荐',
-    key: 'rank'
-  }
-]
-
-function A3recommend() {
-  const dispatch = useDispatch()
-
-  const [fromData, setFromData] = useState(fromDataBase)
-
-  const getListFu = useCallback(() => {
-    dispatch(A3_APIgetList(fromData))
-  }, [dispatch, fromData])
-
-  useEffect(() => {
-    getListFu()
-  }, [getListFu])
-
-  const [inputKey, setInputKey] = useState(1)
-
-  // 输入框的输入
-  const timeRef = useRef(-1)
-  const txtChangeFu = useCallback(
-    (e: React.ChangeEvent<HTMLInputElement>, key: 'searchKey' | 'num') => {
-      clearTimeout(timeRef.current)
-      timeRef.current = window.setTimeout(() => {
-        setFromData({ ...fromData, [key]: e.target.value.replaceAll("'", ''), pageNum: 1 })
-      }, 500)
-    },
-    [fromData]
-  )
-
-  // 点击重置
-  const resetSelectFu = useCallback(() => {
-    setInputKey(Date.now())
-    setFromData({ ...fromDataBase, type: fromData.type })
-  }, [fromData.type])
-
-  const tableList = useSelector((state: RootState) => state.A3recommend.tableList)
-
-  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={() => setEditId(item.id)}>
-              编辑
-            </Button>
-
-            <MyPopconfirm txtK='删除' onConfirm={() => delTableFu(item.id)} />
-          </>
-        )
-      }
-    ]
-  }, [delTableFu])
-
-  // 点击编辑和新增
-  const [editId, setEditId] = useState(0)
-
-  return (
-    <div className={styles.A3recommend}>
-      <div className='pageTitle'>图书推荐</div>
-      {/* 顶部筛选 */}
-      <div className='A3top'>
-        <div>
-          <div className='A3TopRow'>
-            {topTypeArr.map(v => (
-              <Button
-                type={v.key === fromData.type ? 'primary' : 'default'}
-                key={v.key}
-                onClick={() => setFromData({ ...fromData, type: v.key, pageNum: 1 })}
-              >
-                {v.name}
-              </Button>
-            ))}
-          </div>
-
-          <div className='A3TopRow'>
-            <span>搜索:</span>
-            <Input
-              key={inputKey}
-              maxLength={20}
-              style={{ width: 192 }}
-              placeholder='请输入书名/作者/出版社'
-              allowClear
-              onChange={e => txtChangeFu(e, 'searchKey')}
-            />
-            &nbsp;
-            <Input
-              key={inputKey + 1}
-              maxLength={20}
-              style={{ width: 192 }}
-              placeholder='请输入完整ISBN编号'
-              allowClear
-              onChange={e => txtChangeFu(e, 'num')}
-            />
-          </div>
-        </div>
-        <div>
-          <Button onClick={resetSelectFu}>重置</Button>&emsp;
-          <Button
-            type='primary'
-            onClick={() => {
-              if (fromData.type === 'index' && tableList.length >= 50)
-                return MessageFu.warning('最多支持50本!')
-              if (fromData.type === 'rank' && tableList.length >= 10)
-                return MessageFu.warning('最多支持10本!')
-              setEditId(-1)
-            }}
-          >
-            新增
-          </Button>
-        </div>
-      </div>
-
-      {/* 表格主体 */}
-      <div className='A3tableBox'>
-        <MyTable
-          yHeight={678}
-          list={tableList}
-          columnsTemp={A3tableC}
-          lastBtn={tableLastBtn}
-          pagingInfo={false}
-        />
-      </div>
-
-      {editId ? (
-        <A3add
-          id={editId}
-          type={fromData.type}
-          closeFu={() => setEditId(0)}
-          addTableFu={resetSelectFu}
-        />
-      ) : null}
-    </div>
-  )
-}
-
-const MemoA3recommend = React.memo(A3recommend)
-
-export default MemoA3recommend

+ 0 - 76
src/pages/A4iosUser/A4ip/index.module.scss

@@ -1,76 +0,0 @@
-.A4ip {
-  position: absolute;
-  top: 0;
-  left: 0;
-  width: 100%;
-  height: 100%;
-  background-color: rgba(0, 0, 0, 0.6);
-  border-radius: 10px;
-  padding: 50px 100px;
-  :global {
-    .A4iBox {
-      width: 100%;
-      height: 100%;
-      border-radius: 10px;
-      background-color: #fff;
-      padding: 20px;
-      .A4iTop {
-        display: flex;
-        align-items: center;
-        justify-content: space-between;
-        & > div {
-          display: flex;
-          align-items: center;
-        }
-      }
-      .ant-table-wrapper {
-        margin-top: 20px;
-        .ant-table-cell {
-          padding: 6px;
-        }
-      }
-    }
-  }
-}
-
-// 新增 /编辑
-.A4ipAdd {
-  :global {
-    .ant-modal-close {
-      display: none;
-    }
-    .ant-modal {
-      width: 800px !important;
-      top: 30%;
-    }
-    .ant-modal-body {
-      border-top: 1px solid #ccc;
-      padding-top: 15px !important;
-    }
-
-    .formRow {
-      display: flex;
-      align-items: center;
-      margin-bottom: 24px;
-
-      .formLeft {
-        width: 80px;
-        text-align: right;
-
-        & > span {
-          color: #ff4d4f;
-        }
-      }
-
-      .formRight {
-        width: calc(100% - 80px);
-        position: relative;
-      }
-    }
-
-    .A4ibtn {
-      text-align: center;
-      margin-top: 50px;
-    }
-  }
-}

+ 0 - 158
src/pages/A4iosUser/A4ip/index.tsx

@@ -1,158 +0,0 @@
-import React, { useCallback, useEffect, useMemo, useState } from 'react'
-import styles from './index.module.scss'
-import { Button, Input, Modal } from 'antd'
-import { A4_APIipDel, A4_APIipList, A4_APIipSave } from '@/store/action/A4iosUser'
-import { useDispatch, useSelector } from 'react-redux'
-import { RootState } from '@/store'
-import MyTable from '@/components/MyTable'
-import { MessageFu } from '@/utils/message'
-import { A4IpType } from '@/types'
-import MyPopconfirm from '@/components/MyPopconfirm'
-
-type Props = {
-  closeFu: () => void
-}
-
-function A4ip({ closeFu }: Props) {
-  const dispatch = useDispatch()
-
-  const getListFu = useCallback(async () => {
-    dispatch(A4_APIipList())
-  }, [dispatch])
-
-  useEffect(() => {
-    getListFu()
-  }, [getListFu])
-
-  const ipList = useSelector((state: RootState) => state.A4iosUser.ipList)
-
-  const delTableFu = useCallback(
-    async (id: number) => {
-      const res = await A4_APIipDel(id)
-      if (res.code === 0) {
-        MessageFu.success('删除成功!')
-        getListFu()
-      }
-    },
-    [getListFu]
-  )
-
-  const [opId, setOpId] = useState(0)
-  const [ip, setIp] = useState('')
-
-  const tableLastBtn = useMemo(() => {
-    return [
-      {
-        title: '操作',
-        render: (item: A4IpType) => (
-          <>
-            <Button
-              size='small'
-              type='text'
-              onClick={() => {
-                setOpId(item.id)
-                setIp(item.ip)
-              }}
-            >
-              编辑
-            </Button>
-
-            <MyPopconfirm txtK='删除' onConfirm={() => delTableFu(item.id)} />
-          </>
-        )
-      }
-    ]
-  }, [delTableFu])
-
-  const btnOk = useCallback(async () => {
-    if (ip === '') return MessageFu.warning('请输入IP地址!')
-
-    const res = await A4_APIipSave({
-      id: opId > 0 ? opId : null,
-      ip
-    })
-
-    if (res.code === 0) {
-      MessageFu.success(opId > 0 ? '编辑成功!' : '新增成功!')
-      setOpId(0)
-      setIp('')
-      getListFu()
-    }
-  }, [getListFu, ip, opId])
-
-  return (
-    <div className={styles.A4ip}>
-      <div className='A4iBox'>
-        <div className='A4iTop'>
-          <h1>IP黑名单</h1>
-          <div>
-            <Button
-              type='primary'
-              onClick={() => {
-                setOpId(-1)
-                setIp('')
-              }}
-            >
-              新增
-            </Button>
-            &emsp; <Button onClick={closeFu}>关闭</Button>
-          </div>
-        </div>
-
-        <MyTable
-          classKey='A4ipTable'
-          yHeight={595}
-          list={ipList}
-          columnsTemp={[['txt', 'IP地址', 'ip']]}
-          lastBtn={tableLastBtn}
-          pagingInfo={false}
-        />
-      </div>
-
-      {opId ? (
-        <Modal
-          wrapClassName={styles.A4ipAdd}
-          open={true}
-          title={opId > 0 ? '编辑' : '新增'}
-          footer={
-            [] // 设置footer为空,去掉 取消 确定默认按钮
-          }
-        >
-          <br />
-          <div className='formRow'>
-            <div className='formLeft'>
-              <span>*</span>IP地址:
-            </div>
-            <div className='formRight'>
-              <Input
-                placeholder='请输入内容'
-                maxLength={20}
-                showCount
-                value={ip}
-                onChange={e => setIp(e.target.value.replace(/[^\d.]/g, ''))}
-              />
-            </div>
-          </div>
-
-          <div className='A4ibtn'>
-            <Button type='primary' onClick={btnOk}>
-              提交
-            </Button>
-            &emsp;
-            <MyPopconfirm
-              txtK='取消'
-              onConfirm={() => {
-                setOpId(0)
-                setIp('')
-              }}
-            />
-          </div>
-        </Modal>
-      ) : null}
-    </div>
-  )
-}
-
-const MemoA4ip = React.memo(A4ip)
-
-export default MemoA4ip

+ 0 - 21
src/pages/A4iosUser/data.ts

@@ -1,21 +0,0 @@
-export type A4FromDataType = {
-  searchKey: string
-  pageNum: number
-  pageSize: number
-  isEnabled: 0 | 1 | ''
-}
-
-export const A4selArr1 = [
-  {
-    value: '',
-    label: '全部'
-  },
-  {
-    value: 0,
-    label: '禁用'
-  },
-  {
-    value: 1,
-    label: '启用'
-  }
-]

+ 0 - 144
src/pages/A4iosUser/index.tsx

@@ -1,144 +0,0 @@
-import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
-import styles from './index.module.scss'
-import { Button, Input, Select, Switch } from 'antd'
-import { A4FromDataType, A4selArr1 } from './data'
-import { useDispatch, useSelector } from 'react-redux'
-import { A4_APIgetList, A4_APIisEnabled } from '@/store/action/A4iosUser'
-import { RootState } from '@/store'
-import { A4tableType } from '@/types'
-import MyTable from '@/components/MyTable'
-import { A4tableC } from '@/utils/tableData'
-import { MessageFu } from '@/utils/message'
-import A4ip from './A4ip'
-
-const fromDataBase: A4FromDataType = {
-  searchKey: '',
-  pageNum: 1,
-  pageSize: 10,
-  isEnabled: ''
-}
-
-function A4iosUser() {
-  const dispatch = useDispatch()
-
-  const [fromData, setFromData] = useState(fromDataBase)
-
-  const getListFu = useCallback(() => {
-    dispatch(A4_APIgetList(fromData))
-  }, [dispatch, fromData])
-
-  useEffect(() => {
-    getListFu()
-  }, [getListFu])
-
-  const [inputKey, setInputKey] = useState(1)
-
-  // 输入框的输入
-  const timeRef = useRef(-1)
-  const txtChangeFu = useCallback(
-    (e: React.ChangeEvent<HTMLInputElement>, key: 'searchKey') => {
-      clearTimeout(timeRef.current)
-      timeRef.current = window.setTimeout(() => {
-        setFromData({ ...fromData, [key]: e.target.value.replaceAll("'", ''), pageNum: 1 })
-      }, 500)
-    },
-    [fromData]
-  )
-
-  // 点击重置
-  const resetSelectFu = useCallback(() => {
-    setInputKey(Date.now())
-    setFromData({ ...fromDataBase })
-  }, [])
-
-  const tableInfo = useSelector((state: RootState) => state.A4iosUser.tableInfo)
-
-  // 用户状态切换
-  const cutIsEnabled = useCallback(
-    async (id: number, val: 0 | 1) => {
-      const res = await A4_APIisEnabled(id, val ? 0 : 1)
-      if (res.code === 0) {
-        MessageFu.success('操作成功!')
-        getListFu()
-      }
-    },
-    [getListFu]
-  )
-
-  const tableLastBtn = useMemo(() => {
-    return [
-      {
-        title: '用户状态',
-        render: (item: A4tableType) => (
-          <Switch
-            checked={!!item.isEnabled}
-            onChange={() => cutIsEnabled(item.id, item.isEnabled)}
-            checkedChildren='启用'
-            unCheckedChildren='禁用'
-          />
-        )
-      }
-    ]
-  }, [cutIsEnabled])
-
-  const [ipShow, setIpShow] = useState(false)
-
-  return (
-    <div className={styles.A4iosUser}>
-      <div className='pageTitle'>平台用户</div>
-
-      {/* 顶部筛选 */}
-      <div className='A4top'>
-        <div>
-          <div className='A4TopRow'>
-            <span>搜索:</span>
-            <Input
-              key={inputKey}
-              maxLength={20}
-              style={{ width: 192 }}
-              placeholder='请输入用户昵称'
-              allowClear
-              onChange={e => txtChangeFu(e, 'searchKey')}
-            />
-          </div>
-
-          <div className='A4TopRow'>
-            <span>用户状态:</span>
-            <Select
-              style={{ width: 180 }}
-              value={fromData.isEnabled}
-              onChange={e => setFromData({ ...fromData, pageNum: 1, isEnabled: e })}
-              options={A4selArr1}
-            />
-          </div>
-        </div>
-        <div>
-          <Button onClick={resetSelectFu}>重置</Button>&emsp;
-          <Button type='primary' onClick={() => setIpShow(true)}>
-            IP黑名单
-          </Button>
-        </div>
-      </div>
-
-      {/* 表格主体 */}
-      <div className='A4tableBox'>
-        <MyTable
-          yHeight={625}
-          list={tableInfo.list}
-          columnsTemp={A4tableC}
-          lastBtn={tableLastBtn}
-          pageNum={fromData.pageNum}
-          pageSize={fromData.pageSize}
-          total={tableInfo.total}
-          onChange={(pageNum, pageSize) => setFromData({ ...fromData, pageNum, pageSize })}
-        />
-      </div>
-
-      {ipShow ? <A4ip closeFu={() => setIpShow(false)} /> : null}
-    </div>
-  )
-}
-
-const MemoA4iosUser = React.memo(A4iosUser)
-
-export default MemoA4iosUser

+ 110 - 0
src/pages/A4news/A4add/index.module.scss

@@ -0,0 +1,110 @@
+.A4add {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  z-index: 12;
+  background-color: #fff;
+  border-radius: 10px;
+  padding: 24px;
+
+  :global {
+    .A4aMain {
+      width: 100%;
+      height: calc(100% - 80px);
+      overflow-y: auto;
+
+      textarea {
+        min-height: 75px !important;
+      }
+
+      .A4fromRow {
+        position: relative;
+        width: 800px;
+
+        .A4_6Frow {
+          position: absolute;
+          left: 200px;
+          top: 5px;
+          color: #999;
+          font-size: 12px;
+        }
+      }
+
+      .ant-form {
+        width: 800px;
+        display: flex;
+        flex-direction: column;
+        gap: 30px;
+
+        // .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);
+          }
+        }
+
+        .A4abtn {
+          display: flex;
+          align-items: center;
+          width: 100%;
+          height: 80px;
+          position: fixed;
+          bottom: 0;
+          background: #fff;
+          z-index: 10;
+
+          .A4abtnBox {
+            display: flex;
+            gap: 20px;
+            padding-left: 100px;
+          }
+        }
+      }
+    }
+
+    // 从查看进入
+    .A4aMainLook {
+      // 左边的 label 也不让选中
+      label {
+        pointer-events: none;
+      }
+
+      .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;
+      }
+    }
+  }
+}

+ 298 - 0
src/pages/A4news/A4add/index.tsx

@@ -0,0 +1,298 @@
+import React, { useCallback, useEffect, useRef, useState } from 'react'
+import styles from './index.module.scss'
+import classNames from 'classnames'
+import { A1EditInfoType } from '../data'
+import { Button, Form, FormInstance, Input, DatePicker } from 'antd'
+import TextArea from 'antd/es/input/TextArea'
+import { A4_APIgetInfo, A4_APIadd, A4_APIedit } from '@/store/action/A4news'
+import { MessageFu } from '@/utils/message'
+import ZupOne from '@/components/ZupOne'
+import MyPopconfirm from '@/components/MyPopconfirm'
+import dayjs from 'dayjs'
+import ZRichTexts from '@/components/ZRichTexts'
+import { A4AddType, A4tableType } from '@/types/api/A4news'
+
+type Props = {
+  editInfo: A1EditInfoType
+  closeFu: () => void
+  addTableFu: () => void
+  editTableFu: () => void
+}
+
+function A4add({ editInfo, closeFu, addTableFu, editTableFu }: Props) {
+  // 表单的ref
+  const FormBoxRef = useRef<FormInstance>(null)
+
+  // 封面图的ref
+  const ZupThumbRef1 = useRef<any>(null)
+  const ZupThumbRef2 = useRef<any>(null)
+  // 正文的ref
+  const ZRichTextRef = useRef<any>(null)
+
+  // 回显数据的方法调用
+  const dataShow = useCallback((info: A4tableType) => {
+    let editObj = null
+    if (info.status === 0) {
+      editObj = {
+        ...info,
+        title: info.titleB,
+        publish: info.publishB,
+        remark: info.remarkB,
+        context: info.contextB,
+        indexImg: info.indexImgB,
+        indexImgTh: info.indexImgThB,
+        infoImg: info.infoImgB,
+        infoImgTh: info.infoImgThB
+      }
+    } else {
+      editObj = { ...info }
+    }
+    console.log('-xsxxas', editObj)
+    FormBoxRef.current?.setFieldsValue({ ...editObj, publish: dayjs(editObj.publish) })
+
+    // 设置封面图
+    ZupThumbRef1.current?.setFileComFileFu({
+      fileName: '',
+      thUrl: editObj.indexImgTh,
+      url: editObj.indexImg
+    })
+    ZupThumbRef2.current?.setFileComFileFu({
+      fileName: '',
+      thUrl: editObj.infoImgTh,
+      url: editObj.infoImg
+    })
+
+    // 设置正文
+    ZRichTextRef.current?.ritxtShowFu({
+      txtArr: [
+        {
+          id: editObj.informationId,
+          name: '正文',
+          txt: editObj.context,
+          fileInfo: { fileName: '', filePath: '' }
+        }
+      ]
+    })
+  }, [])
+
+  // 编辑 进入页面 获取信息
+  const getInfoFu = useCallback(
+    async (id: number) => {
+      if (editInfo.info) dataShow(editInfo.info)
+      else {
+        const res = await A4_APIgetInfo(id)
+        if (res.code === 0) {
+          dataShow(res.data)
+        }
+      }
+    },
+    [dataShow, editInfo.info]
+  )
+
+  // 附件 是否 已经点击过确定
+  const [fileCheck, setFileCheck] = useState(false)
+
+  // 编辑填入数据
+  useEffect(() => {
+    if (editInfo.id > 0) {
+      getInfoFu(editInfo.id)
+    }
+  }, [editInfo.id, getInfoFu])
+
+  // 没有通过校验
+  const onFinishFailed = useCallback(() => {
+    setFileCheck(true)
+  }, [])
+
+  //  通过校验点击确定
+  const onFinish = useCallback(
+    async (values: any) => {
+      setFileCheck(true)
+
+      const coverUrl1 = ZupThumbRef1.current?.fileComFileResFu()
+      const coverUrl2 = ZupThumbRef2.current?.fileComFileResFu()
+      const context = ZRichTextRef.current?.fatherBtnOkFu()
+      // 没有传 封面图
+      if (!coverUrl1.url) return MessageFu.warning('请上传首页封面图!')
+      if (!coverUrl2.url) return MessageFu.warning('请上传详情封面图!')
+      if (!context.val.txtArr[0].txt) return MessageFu.warning('请输入正文!')
+
+      // 发布
+      const obj1: A4AddType = {
+        ...values,
+        indexImg: coverUrl1.url,
+        indexImgTh: coverUrl1.thUrl,
+        infoImg: coverUrl2.url,
+        infoImgTh: coverUrl2.thUrl,
+        context: context.val.txtArr[0].txt,
+        publishB: '',
+        status: 1,
+        titleB: '',
+        urlB: ''
+      }
+
+      // 预发布
+      const obj2: A4AddType = {
+        indexImg: '',
+        indexImgB: coverUrl1.url,
+        indexImgTh: '',
+        indexImgThB: coverUrl1.thUrl,
+        infoImg: '',
+        infoImgB: coverUrl2.url,
+        infoImgTh: '',
+        infoImgThB: coverUrl2.thUrl,
+        publish: '',
+        publishB: values.publish,
+        status: 0,
+        title: '',
+        titleB: values.title,
+        remark: '',
+        remarkB: values.remark,
+        context: '',
+        contextB: context.val.txtArr[0].txt
+      }
+
+      let res: any
+      if (btnRef.current === '1') {
+        res =
+          editInfo.txt === '新增'
+            ? await A4_APIadd(obj1)
+            : await A4_APIedit({ ...obj1, informationId: editInfo.id })
+      } else {
+        res =
+          editInfo.txt === '新增'
+            ? await A4_APIadd(obj2)
+            : await A4_APIedit({ ...obj2, informationId: editInfo.id })
+      }
+
+      if (res.code === 0) {
+        MessageFu.success(`${editInfo.txt}成功!`)
+        editInfo.id > 0 ? editTableFu() : addTableFu()
+        closeFu()
+      }
+    },
+    [addTableFu, closeFu, editInfo.id, editInfo.txt, editTableFu]
+  )
+
+  const formOkBtnRef = useRef<any>(null)
+
+  const btnRef = useRef('')
+
+  return (
+    <div className={styles.A4add}>
+      <div className={classNames('A4aMain')}>
+        <Form
+          ref={FormBoxRef}
+          name='basic'
+          labelCol={{ span: 3 }}
+          onFinish={onFinish}
+          onFinishFailed={onFinishFailed}
+          autoComplete='off'
+          scrollToFirstError
+        >
+          <Form.Item
+            label='标题'
+            name='title'
+            rules={[{ required: true, message: '请输入标题!' }]}
+          >
+            <Input placeholder='请输入内容,不超过30个字' maxLength={30} showCount />
+          </Form.Item>
+
+          <Form.Item label='发表日期' name='publish'>
+            <DatePicker allowClear placeholder='请选择日期' style={{ width: 200 }} />
+          </Form.Item>
+
+          <Form.Item label='摘要' name='remark'>
+            <TextArea maxLength={200} showCount placeholder='请输入内容,不超过200个字' />
+          </Form.Item>
+
+          <Form.Item label='正文' name='context'>
+            <ZRichTexts
+              check={true}
+              dirCode={'A4news'}
+              isLook={false}
+              ref={ZRichTextRef}
+              myUrl='museum/upload/upload'
+              isOne={true}
+              upAudioBtnNone={true}
+            />
+          </Form.Item>
+
+          {/* 封面 */}
+          <div className='formRow'>
+            <div className='formLeft'>
+              <span>* </span>
+              首页封面:
+            </div>
+            <div className='formRight'>
+              <ZupOne
+                ref={ZupThumbRef1}
+                fileCheck={fileCheck}
+                size={5}
+                dirCode={'A1banner'}
+                myUrl='museum/upload/uploadImg'
+                format={['image/jpeg', 'image/png']}
+                formatTxt='png、jpg和jpeg'
+                checkTxt='请上传封面图!'
+                upTxt='最多1张'
+                myType='thumb'
+              />
+            </div>
+          </div>
+
+          <div className='formRow'>
+            <div className='formLeft'>
+              <span>* </span>
+              详情封面:
+            </div>
+            <div className='formRight'>
+              <ZupOne
+                ref={ZupThumbRef2}
+                fileCheck={fileCheck}
+                size={5}
+                dirCode={'A1banner'}
+                myUrl='museum/upload/uploadImg'
+                format={['image/jpeg', 'image/png']}
+                formatTxt='png、jpg和jpeg'
+                checkTxt='请上传封面图!'
+                upTxt='最多1张'
+                myType='thumb'
+              />
+            </div>
+          </div>
+
+          {/* 确定和取消按钮 */}
+          <Form.Item className='A4abtn'>
+            <div className='A4abtnBox'>
+              <Button
+                type='primary'
+                htmlType='submit'
+                onClick={() => {
+                  btnRef.current = '1'
+                  formOkBtnRef.current?.click()
+                }}
+              >
+                发布
+              </Button>
+              <Button
+                type='primary'
+                htmlType='submit'
+                onClick={() => {
+                  btnRef.current = '0'
+                  formOkBtnRef.current?.click()
+                }}
+              >
+                预发布
+              </Button>
+              <MyPopconfirm txtK='取消' onConfirm={closeFu} />
+            </div>
+          </Form.Item>
+        </Form>
+      </div>
+    </div>
+  )
+}
+
+const MemoA4add = React.memo(A4add)
+
+export default MemoA4add

+ 7 - 0
src/pages/A4news/data.ts

@@ -0,0 +1,7 @@
+import { A4tableType } from '@/types/api/A4news'
+
+export type A1EditInfoType = {
+  id: number
+  txt: '新增' | '编辑' | ''
+  info?: A4tableType
+}

+ 24 - 0
src/pages/A4news/index.module.scss

@@ -0,0 +1,24 @@
+.A4news {
+  position: relative;
+  :global {
+    .A4top {
+      border-radius: 10px;
+      background-color: #fff;
+      padding: 15px 24px;
+      display: flex;
+      justify-content: space-between;
+      gap: 20px;
+      .A4topLeft {
+        display: flex;
+        gap: 20px;
+      }
+    }
+    .A4tableBox {
+      border-radius: 10px;
+      overflow: hidden;
+      margin-top: 15px;
+      height: calc(100% - 77px);
+      background-color: #fff;
+    }
+  }
+}

+ 149 - 0
src/pages/A4news/index.tsx

@@ -0,0 +1,149 @@
+import React, { useCallback, useEffect, useMemo, useState } from 'react'
+import styles from './index.module.scss'
+import { Button, Input } from 'antd'
+import { useDispatch, useSelector } from 'react-redux'
+import { A1EditInfoType } from './data'
+import { A4_APIdel, A4_APIgetList, A4_APIpublish } from '@/store/action/A4news'
+import { RootState } from '@/store'
+import { MessageFu } from '@/utils/message'
+import { A4tableType } from '@/types/api/A4news'
+import MyPopconfirm from '@/components/MyPopconfirm'
+import MyTable from '@/components/MyTable'
+import { A4tableC } from '@/utils/tableData'
+import A4add from './A4add'
+
+const pageDataBase = {
+  pageNum: 1,
+  pageSize: 10
+}
+
+function A4news() {
+  const dispatch = useDispatch()
+
+  const [pageData, setPageData] = useState(pageDataBase)
+  const [title, setTitle] = useState('')
+  const getListFu = useCallback(
+    (title?: string) => {
+      // status: -1 全部 0 未发布 1 已发布
+      dispatch(A4_APIgetList({ ...pageData, status: -1, title }))
+    },
+    [dispatch, pageData]
+  )
+
+  useEffect(() => {
+    getListFu()
+  }, [getListFu])
+
+  // 点击重置
+  const resetSelectFu = useCallback(() => {
+    setPageData({ ...pageDataBase })
+  }, [])
+
+  const tableInfo = useSelector((state: RootState) => state.A4news.tableInfo)
+
+  const delTableFu = useCallback(
+    async (id: number) => {
+      const res = await A4_APIdel(id)
+      if (res.code === 0) {
+        MessageFu.success('删除成功!')
+        getListFu()
+      }
+    },
+    [getListFu]
+  )
+
+  const publishFu = useCallback(
+    async (id: number) => {
+      const res = await A4_APIpublish(id)
+      if (res.code === 0) {
+        MessageFu.success('发布成功!')
+        getListFu()
+      }
+    },
+    [getListFu]
+  )
+
+  const tableLastBtn = useMemo(() => {
+    return [
+      {
+        title: '操作',
+        render: (item: A4tableType) => (
+          <>
+            {item.status === 0 && (
+              <Button size='small' type='text'>
+                预览
+              </Button>
+            )}
+            <Button
+              size='small'
+              type='text'
+              onClick={() => setEditInfo({ id: item.informationId, txt: '编辑' })}
+            >
+              编辑
+            </Button>
+            {item.status === 0 && (
+              <Button size='small' type='text' onClick={() => publishFu(item.informationId)}>
+                发布
+              </Button>
+            )}
+            <MyPopconfirm txtK='删除' onConfirm={() => delTableFu(item.informationId)} />
+          </>
+        )
+      }
+    ]
+  }, [delTableFu, publishFu])
+
+  //新增、编辑
+  const [editInfo, setEditInfo] = useState<A1EditInfoType>({
+    id: 0,
+    txt: ''
+  })
+
+  return (
+    <div className={styles.A4news}>
+      <div className='pageTitle'>克博资讯 {editInfo.id ? ` - ${editInfo.txt}` : ''}</div>
+
+      {/* 顶部筛选 */}
+      <div className='A4top'>
+        <div className='A4topLeft'>
+          <Input placeholder='请输入标题' onChange={e => setTitle(e.target.value)} />
+          <Button type='primary' onClick={() => getListFu(title)}>
+            搜索
+          </Button>
+        </div>
+        <Button type='primary' onClick={() => setEditInfo({ id: -1, txt: '新增' })}>
+          新增
+        </Button>
+      </div>
+
+      {/* 表格主体 */}
+      <div className='A4tableBox'>
+        <MyTable
+          myKey='carouselId'
+          yHeight={625}
+          list={tableInfo.list}
+          columnsTemp={A4tableC}
+          lastBtn={tableLastBtn}
+          pageNum={pageData.pageNum}
+          pageSize={pageData.pageSize}
+          total={tableInfo.total}
+          onChange={(pageNum, pageSize) => setPageData({ ...pageData, pageNum, pageSize })}
+        />
+      </div>
+
+      {/* 新增 / 编辑 */}
+      {editInfo.id ? (
+        <A4add
+          editInfo={editInfo}
+          closeFu={() => setEditInfo({ id: 0, txt: '新增' })}
+          addTableFu={resetSelectFu}
+          editTableFu={getListFu}
+        />
+      ) : null}
+    </div>
+  )
+}
+
+const MemoA4news = React.memo(A4news)
+
+export default MemoA4news

+ 116 - 0
src/pages/A5activity/A5add/index.module.scss

@@ -0,0 +1,116 @@
+.A5add {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  z-index: 12;
+  background-color: #fff;
+  border-radius: 10px;
+  padding: 24px;
+
+  :global {
+    .A5aMain {
+      width: 100%;
+      height: calc(100% - 80px);
+      overflow-y: auto;
+
+      textarea {
+        min-height: 75px !important;
+      }
+
+      .A5fromRow {
+        position: relative;
+        width: 800px;
+
+        .A5_6Frow {
+          position: absolute;
+          left: 200px;
+          top: 5px;
+          color: #999;
+          font-size: 12px;
+        }
+      }
+
+      .ant-form {
+        width: 800px;
+        display: flex;
+        flex-direction: column;
+        gap: 30px;
+
+        // .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);
+          }
+        }
+
+        .reserveBox {
+          display: flex;
+          flex-direction: column;
+          gap: 10px;
+        }
+
+        .A5abtn {
+          display: flex;
+          align-items: center;
+          width: 100%;
+          height: 80px;
+          position: fixed;
+          bottom: 0;
+          background: #fff;
+          z-index: 10;
+
+          .A5abtnBox {
+            display: flex;
+            gap: 20px;
+            padding-left: 100px;
+          }
+        }
+      }
+    }
+
+    // 从查看进入
+    .A5aMainLook {
+      // 左边的 label 也不让选中
+      label {
+        pointer-events: none;
+      }
+
+      .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;
+      }
+    }
+  }
+}

+ 374 - 0
src/pages/A5activity/A5add/index.tsx

@@ -0,0 +1,374 @@
+import React, { useCallback, useEffect, useRef, useState } from 'react'
+import styles from './index.module.scss'
+import classNames from 'classnames'
+import { A1EditInfoType } from '../data'
+import {
+  Button,
+  Form,
+  FormInstance,
+  Input,
+  DatePicker,
+  Select,
+  InputNumber,
+  TimePicker
+} from 'antd'
+import TextArea from 'antd/es/input/TextArea'
+import { A5_APIgetInfo, A5_APIadd, A5_APIedit } from '@/store/action/A5activity'
+import { MessageFu } from '@/utils/message'
+import ZupOne from '@/components/ZupOne'
+import MyPopconfirm from '@/components/MyPopconfirm'
+import dayjs from 'dayjs'
+import ZRichTexts from '@/components/ZRichTexts'
+import { A5AddType, A5tableType } from '@/types/api/A5activity'
+
+type Props = {
+  editInfo: A1EditInfoType
+  closeFu: () => void
+  addTableFu: () => void
+  editTableFu: () => void
+}
+
+function A5add({ editInfo, closeFu, addTableFu, editTableFu }: Props) {
+  // 表单的ref
+  const FormBoxRef = useRef<FormInstance>(null)
+
+  // 封面图的ref
+  const ZupThumbRef1 = useRef<any>(null)
+  const ZupThumbRef2 = useRef<any>(null)
+  // 正文的ref
+  const ZRichTextRef = useRef<any>(null)
+
+  // 回显数据的方法调用
+  const dataShow = useCallback((info: A5tableType) => {
+    let editObj = null
+    if (info.status === 0) {
+      editObj = {
+        ...info,
+        title: info.titleB,
+        publish: info.publishB,
+        remark: info.remarkB,
+        context: info.contextB,
+        indexImg: info.indexImgB,
+        indexImgTh: info.indexImgThB,
+        infoImg: info.infoImgB,
+        infoImgTh: info.infoImgThB
+      }
+    } else {
+      editObj = { ...info }
+    }
+    console.log('-xsxxas', editObj)
+    FormBoxRef.current?.setFieldsValue({
+      ...editObj,
+      publish: dayjs(editObj.publish),
+      date: editObj.subscribe === 1 ? [dayjs(editObj.startTime), dayjs(editObj.endTime)] : [],
+      time:
+        editObj.subscribe === 1
+          ? [dayjs(editObj.time.split('-')[0], 'HH:mm'), dayjs(editObj.time.split('-')[1], 'HH:mm')]
+          : []
+    })
+
+    // 设置封面图
+    ZupThumbRef1.current?.setFileComFileFu({
+      fileName: '',
+      thUrl: editObj.indexImgTh,
+      url: editObj.indexImg
+    })
+    ZupThumbRef2.current?.setFileComFileFu({
+      fileName: '',
+      thUrl: editObj.infoImgTh,
+      url: editObj.infoImg
+    })
+
+    // 设置正文
+    ZRichTextRef.current?.ritxtShowFu({
+      txtArr: [
+        {
+          id: editObj.activityId,
+          name: '正文',
+          txt: editObj.context,
+          fileInfo: { fileName: '', filePath: '' }
+        }
+      ]
+    })
+  }, [])
+
+  // 编辑 进入页面 获取信息
+  const getInfoFu = useCallback(
+    async (id: number) => {
+      if (editInfo.info) dataShow(editInfo.info)
+      else {
+        const res = await A5_APIgetInfo(id)
+        if (res.code === 0) {
+          dataShow(res.data)
+          setIsReserve(res.data.subscribe || 0)
+        }
+      }
+    },
+    [dataShow, editInfo.info]
+  )
+
+  // 附件 是否 已经点击过确定
+  const [fileCheck, setFileCheck] = useState(false)
+
+  // 编辑填入数据
+  useEffect(() => {
+    if (editInfo.id > 0) {
+      getInfoFu(editInfo.id)
+    }
+  }, [editInfo.id, getInfoFu])
+
+  // 没有通过校验
+  const onFinishFailed = useCallback(() => {
+    setFileCheck(true)
+  }, [])
+
+  //  通过校验点击确定
+  const onFinish = useCallback(
+    async (values: any) => {
+      setFileCheck(true)
+
+      const coverUrl1 = ZupThumbRef1.current?.fileComFileResFu()
+      const coverUrl2 = ZupThumbRef2.current?.fileComFileResFu()
+      const context = ZRichTextRef.current?.fatherBtnOkFu()
+      // 没有传 封面图
+      if (!coverUrl1.url) return MessageFu.warning('请上传首页封面图!')
+      if (!coverUrl2.url) return MessageFu.warning('请上传详情封面图!')
+      if (!context.val.txtArr[0].txt) return MessageFu.warning('请输入正文!')
+
+      // 发布
+      const obj1: A5AddType = {
+        ...values,
+        indexImg: coverUrl1.url,
+        indexImgTh: coverUrl1.thUrl,
+        infoImg: coverUrl2.url,
+        infoImgTh: coverUrl2.thUrl,
+        context: context.val.txtArr[0].txt,
+        publishB: '',
+        status: 1,
+        titleB: '',
+        urlB: '',
+        startTime: values?.date?.[0]?.format('YYYY-MM-DD') || '',
+        endTime: values?.date?.[1]?.format('YYYY-MM-DD') || '',
+        personCount: values?.personCount || 0,
+        time: values?.time?.map((item: any) => item.format('HH:mm')).join('-') || '',
+        guide: values?.guide || ''
+      }
+
+      // 预发布
+      const obj2: A5AddType = {
+        indexImg: '',
+        indexImgB: coverUrl1.url,
+        indexImgTh: '',
+        indexImgThB: coverUrl1.thUrl,
+        infoImg: '',
+        infoImgB: coverUrl2.url,
+        infoImgTh: '',
+        infoImgThB: coverUrl2.thUrl,
+        publish: '',
+        publishB: values.publish,
+        status: 0,
+        subscribe: values.subscribe,
+        title: '',
+        titleB: values.title,
+        remark: '',
+        remarkB: values.remark,
+        context: '',
+        contextB: context.val.txtArr[0].txt,
+        startTime: values?.date?.[0]?.format('YYYY-MM-DD') || '',
+        endTime: values?.date?.[1]?.format('YYYY-MM-DD') || '',
+        personCount: values?.personCount || 0,
+        time: values?.time?.map((item: any) => item.format('HH:mm')).join('-') || '',
+        guide: values?.guide || ''
+      }
+
+      let res: any
+      if (btnRef.current === '1') {
+        res =
+          editInfo.txt === '新增'
+            ? await A5_APIadd(obj1)
+            : await A5_APIedit({ ...obj1, activityId: editInfo.id })
+      } else {
+        res =
+          editInfo.txt === '新增'
+            ? await A5_APIadd(obj2)
+            : await A5_APIedit({ ...obj2, activityId: editInfo.id })
+      }
+
+      if (res.code === 0) {
+        MessageFu.success(`${editInfo.txt}成功!`)
+        editInfo.id > 0 ? editTableFu() : addTableFu()
+        closeFu()
+      }
+    },
+    [addTableFu, closeFu, editInfo.id, editInfo.txt, editTableFu]
+  )
+
+  const formOkBtnRef = useRef<any>(null)
+
+  const btnRef = useRef('')
+
+  const [isReserve, setIsReserve] = useState(0)
+
+  return (
+    <div className={styles.A5add}>
+      <div className={classNames('A5aMain')}>
+        <Form
+          ref={FormBoxRef}
+          name='basic'
+          labelCol={{ span: 3 }}
+          onFinish={onFinish}
+          onFinishFailed={onFinishFailed}
+          autoComplete='off'
+          scrollToFirstError
+        >
+          <Form.Item
+            label='标题'
+            name='title'
+            rules={[{ required: true, message: '请输入标题!' }]}
+          >
+            <Input placeholder='请输入内容,不超过30个字' maxLength={30} showCount />
+          </Form.Item>
+
+          <Form.Item label='发表日期' name='publish'>
+            <DatePicker allowClear placeholder='请选择日期' style={{ width: 200 }} />
+          </Form.Item>
+
+          <Form.Item label='摘要' name='remark'>
+            <TextArea maxLength={200} showCount placeholder='请输入内容,不超过200个字' />
+          </Form.Item>
+
+          <Form.Item label='正文' name='context'>
+            <ZRichTexts
+              check={true}
+              dirCode={'A4news'}
+              isLook={false}
+              ref={ZRichTextRef}
+              myUrl='museum/upload/upload'
+              isOne={true}
+              upAudioBtnNone={true}
+            />
+          </Form.Item>
+
+          {/* 封面 */}
+          <div className='formRow'>
+            <div className='formLeft'>
+              <span>* </span>
+              首页封面:
+            </div>
+            <div className='formRight'>
+              <ZupOne
+                ref={ZupThumbRef1}
+                fileCheck={fileCheck}
+                size={5}
+                dirCode={'A5'}
+                myUrl='museum/upload/uploadImg'
+                format={['image/jpeg', 'image/png']}
+                formatTxt='png、jpg和jpeg'
+                checkTxt='请上传封面图!'
+                upTxt='最多1张'
+                myType='thumb'
+              />
+            </div>
+          </div>
+
+          <div className='formRow'>
+            <div className='formLeft'>
+              <span>* </span>
+              详情封面:
+            </div>
+            <div className='formRight'>
+              <ZupOne
+                ref={ZupThumbRef2}
+                fileCheck={fileCheck}
+                size={5}
+                dirCode={'A5'}
+                myUrl='museum/upload/uploadImg'
+                format={['image/jpeg', 'image/png']}
+                formatTxt='png、jpg和jpeg'
+                checkTxt='请上传封面图!'
+                upTxt='最多1张'
+                myType='thumb'
+              />
+            </div>
+          </div>
+
+          <Form.Item label='需要预约' name='subscribe'>
+            <Select
+              onChange={val => {
+                setIsReserve(val)
+              }}
+              options={[
+                { label: '是', value: 1 },
+                { label: '否', value: 0 }
+              ]}
+            />
+          </Form.Item>
+
+          {isReserve === 1 && (
+            <div className='reserveBox'>
+              <Form.Item
+                label='活动日期'
+                name='date'
+                rules={[{ required: !!isReserve, message: '请选择活动日期' }]}
+              >
+                <DatePicker.RangePicker />
+              </Form.Item>
+              <Form.Item
+                label='可预约人数'
+                name='personCount'
+                rules={[{ required: !!isReserve, message: '请输入可预约人数' }]}
+              >
+                <InputNumber min={0} max={1000000} />
+              </Form.Item>
+              <Form.Item
+                label='活动时间段'
+                name='time'
+                rules={[{ required: !!isReserve, message: '请选择活动时间段' }]}
+              >
+                <TimePicker.RangePicker />
+              </Form.Item>
+              <Form.Item
+                label='活动须知'
+                name='guide'
+                rules={[{ required: !!isReserve, message: '请输入活动须知' }]}
+              >
+                <TextArea maxLength={200} showCount placeholder='请输入内容,不超过200个字' />
+              </Form.Item>
+            </div>
+          )}
+
+          {/* 确定和取消按钮 */}
+          <Form.Item className='A5abtn'>
+            <div className='A5abtnBox'>
+              <Button
+                type='primary'
+                htmlType='submit'
+                onClick={() => {
+                  btnRef.current = '1'
+                  formOkBtnRef.current?.click()
+                }}
+              >
+                发布
+              </Button>
+              <Button
+                type='primary'
+                htmlType='submit'
+                onClick={() => {
+                  btnRef.current = '0'
+                  formOkBtnRef.current?.click()
+                }}
+              >
+                预发布
+              </Button>
+              <MyPopconfirm txtK='取消' onConfirm={closeFu} />
+            </div>
+          </Form.Item>
+        </Form>
+      </div>
+    </div>
+  )
+}
+
+const MemoA5add = React.memo(A5add)
+
+export default MemoA5add

+ 7 - 0
src/pages/A5activity/data.ts

@@ -0,0 +1,7 @@
+import { A5tableType } from '@/types/api/A5activity'
+
+export type A1EditInfoType = {
+  id: number
+  txt: '新增' | '编辑' | '查看' | ''
+  info?: A5tableType
+}

+ 4 - 10
src/pages/A5bookAudit/index.module.scss

@@ -1,4 +1,4 @@
-.A5bookAudit {
+.A5activity {
   position: relative;
   :global {
     .A5top {
@@ -7,16 +7,10 @@
       padding: 15px 24px;
       display: flex;
       justify-content: space-between;
-      & > div {
+      gap: 20px;
+      .A5topLeft {
         display: flex;
-        .A5TopRow {
-          display: flex;
-          align-items: center;
-          margin-right: 20px;
-          .ant-select-selection-placeholder {
-            color: black;
-          }
-        }
+        gap: 20px;
       }
     }
     .A5tableBox {

+ 149 - 0
src/pages/A5activity/index.tsx

@@ -0,0 +1,149 @@
+import React, { useCallback, useEffect, useMemo, useState } from 'react'
+import styles from './index.module.scss'
+import { Button, Input } from 'antd'
+import { useDispatch, useSelector } from 'react-redux'
+import { A1EditInfoType } from './data'
+import { A5_APIdel, A5_APIgetList, A5_APIpublish } from '@/store/action/A5activity'
+import { RootState } from '@/store'
+import { MessageFu } from '@/utils/message'
+import { A5tableType } from '@/types/api/A5activity'
+import MyPopconfirm from '@/components/MyPopconfirm'
+import MyTable from '@/components/MyTable'
+import { A4tableC } from '@/utils/tableData'
+import A5add from './A5add'
+
+const pageDataBase = {
+  pageNum: 1,
+  pageSize: 10
+}
+
+function A5activity() {
+  const dispatch = useDispatch()
+
+  const [pageData, setPageData] = useState(pageDataBase)
+  const [title, setTitle] = useState('')
+  const getListFu = useCallback(
+    (title?: string) => {
+      // status: -1 全部 0 未发布 1 已发布
+      dispatch(A5_APIgetList({ ...pageData, status: -1, title }))
+    },
+    [dispatch, pageData]
+  )
+
+  useEffect(() => {
+    getListFu()
+  }, [getListFu])
+
+  // 点击重置
+  const resetSelectFu = useCallback(() => {
+    setPageData({ ...pageDataBase })
+  }, [])
+
+  const tableInfo = useSelector((state: RootState) => state.A5activity.tableInfo)
+
+  const delTableFu = useCallback(
+    async (id: number) => {
+      const res = await A5_APIdel(id)
+      if (res.code === 0) {
+        MessageFu.success('删除成功!')
+        getListFu()
+      }
+    },
+    [getListFu]
+  )
+
+  const publishFu = useCallback(
+    async (id: number) => {
+      const res = await A5_APIpublish(id)
+      if (res.code === 0) {
+        MessageFu.success('发布成功!')
+        getListFu()
+      }
+    },
+    [getListFu]
+  )
+
+  const tableLastBtn = useMemo(() => {
+    return [
+      {
+        title: '操作',
+        render: (item: A5tableType) => (
+          <>
+            {item.status === 0 && (
+              <Button size='small' type='text'>
+                预览
+              </Button>
+            )}
+            <Button
+              size='small'
+              type='text'
+              onClick={() => setEditInfo({ id: item.activityId, txt: '编辑' })}
+            >
+              编辑
+            </Button>
+            {item.status === 0 && (
+              <Button size='small' type='text' onClick={() => publishFu(item.activityId)}>
+                发布
+              </Button>
+            )}
+            <MyPopconfirm txtK='删除' onConfirm={() => delTableFu(item.activityId)} />
+          </>
+        )
+      }
+    ]
+  }, [delTableFu, publishFu])
+
+  //新增、编辑
+  const [editInfo, setEditInfo] = useState<A1EditInfoType>({
+    id: 0,
+    txt: ''
+  })
+
+  return (
+    <div className={styles.A5activity}>
+      <div className='pageTitle'>活动列表 {editInfo.id ? ` - ${editInfo.txt}` : ''}</div>
+
+      {/* 顶部筛选 */}
+      <div className='A5top'>
+        <div className='A5topLeft'>
+          <Input placeholder='请输入标题' onChange={e => setTitle(e.target.value)} />
+          <Button type='primary' onClick={() => getListFu(title)}>
+            搜索
+          </Button>
+        </div>
+        <Button type='primary' onClick={() => setEditInfo({ id: -1, txt: '新增' })}>
+          新增
+        </Button>
+      </div>
+
+      {/* 表格主体 */}
+      <div className='A5tableBox'>
+        <MyTable
+          myKey='activityId'
+          yHeight={625}
+          list={tableInfo.list}
+          columnsTemp={A4tableC}
+          lastBtn={tableLastBtn}
+          pageNum={pageData.pageNum}
+          pageSize={pageData.pageSize}
+          total={tableInfo.total}
+          onChange={(pageNum, pageSize) => setPageData({ ...pageData, pageNum, pageSize })}
+        />
+      </div>
+
+      {/* 新增 / 编辑 */}
+      {editInfo.id ? (
+        <A5add
+          editInfo={editInfo}
+          closeFu={() => setEditInfo({ id: 0, txt: '新增' })}
+          addTableFu={resetSelectFu}
+          editTableFu={getListFu}
+        />
+      ) : null}
+    </div>
+  )
+}
+
+const MemoA5activity = React.memo(A5activity)
+
+export default MemoA5activity

+ 0 - 125
src/pages/A5bookAudit/A5look/index.module.scss

@@ -1,125 +0,0 @@
-.A5look {
-  position: absolute;
-  top: 0;
-  left: 0;
-  width: 100%;
-  height: 100%;
-  background-color: #fff;
-  border-radius: 10px;
-  padding: 24px;
-  :global {
-    .A5lMain {
-      padding-right: 400px;
-      width: 100%;
-      height: 100%;
-      overflow: auto;
-    }
-
-    .A5lBtn {
-      font-size: 16px;
-      position: absolute;
-      right: 200px;
-      top: 50%;
-      transform: translateY(-50%);
-      text-align: center;
-    }
-
-    .A5lRow {
-      display: flex;
-      margin-bottom: 20px;
-      font-size: 16px;
-      .A5lLeft {
-        font-weight: 700;
-        width: 120px;
-        text-align: right;
-      }
-      .A5lLeft2 {
-        position: relative;
-        top: 6px;
-      }
-      .A5lRight {
-        width: calc(100% - 120px);
-        .ant-select {
-          pointer-events: none;
-          .ant-select-selector {
-            font-size: 16px;
-            border: none;
-            padding: 0;
-          }
-          .ant-select-arrow {
-            display: none;
-          }
-        }
-      }
-    }
-    .A5lRow2 {
-      margin-bottom: 15px;
-    }
-
-    .A5Ladd {
-      position: absolute;
-      top: 0;
-      left: 0;
-      width: 100%;
-      height: 100%;
-      z-index: 10;
-      padding: 50px 100px;
-      background-color: rgba(0, 0, 0, 0.6);
-      border-radius: 10px;
-      & > div {
-        width: 100%;
-        height: 100%;
-        position: relative;
-      }
-    }
-  }
-}
-
-// 审核
-.A5lAduit {
-  :global {
-    .ant-modal-close {
-      display: none;
-    }
-    .ant-modal {
-      width: 800px !important;
-      // top: 30%;
-    }
-    .ant-modal-body {
-      border-top: 1px solid #ccc;
-      padding-top: 15px !important;
-    }
-
-    .formRow {
-      display: flex;
-      // align-items: center;
-      margin-bottom: 24px;
-
-      .formLeft {
-        width: 80px;
-        text-align: right;
-
-        & > span {
-          color: #ff4d4f;
-        }
-      }
-      .formLeft2 {
-        position: relative;
-        top: 4px;
-      }
-
-      .formRight {
-        width: calc(100% - 80px);
-        position: relative;
-        .ant-btn {
-          margin-right: 15px;
-        }
-      }
-    }
-
-    .A5lAduitBtn {
-      text-align: center;
-      margin-top: 50px;
-    }
-  }
-}

+ 0 - 318
src/pages/A5bookAudit/A5look/index.tsx

@@ -1,318 +0,0 @@
-import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
-import styles from './index.module.scss'
-import { A5tableType } from '@/types'
-import ZupOne from '@/components/ZupOne'
-import { Button, Cascader, Input, Modal } from 'antd'
-import { A2_APIgetList1, A2_APIgetList2 } from '@/store/action/A2classify'
-import { useDispatch, useSelector } from 'react-redux'
-import { RootState } from '@/store'
-import { A5selArr1 } from '../data'
-import MyPopconfirm from '@/components/MyPopconfirm'
-import { A5_APIaudit, A5_APIgetInfo } from '@/store/action/A5bookAudit'
-import { MessageFu } from '@/utils/message'
-import A1add from '@/pages/A1manage/A1add'
-const { TextArea } = Input
-
-type Props = {
-  info: A5tableType
-  closeFuOne: () => void
-  editTableFu: () => void
-}
-
-function A5look({ info, closeFuOne, editTableFu }: Props) {
-  const dispatch = useDispatch()
-  // 占位ref
-  const imgRef = useRef<any>(null)
-  const ZupTxtRef = useRef<any>(null)
-
-  // 获取中图法分类 和 展示分类
-  useEffect(() => {
-    dispatch(A2_APIgetList1())
-    dispatch(A2_APIgetList2({ pageNum: 1, pageSize: 9999, searchKey: '' }))
-  }, [dispatch])
-
-  const { treeData: storageArr, tableInfo: exhibitTypeObj } = useSelector(
-    (state: RootState) => state.A2classify
-  )
-
-  const [storageIds, setStorageIds] = useState<any>([])
-
-  // 审核状态外面页面
-  const [auditStatus, setAuditStatus] = useState<'' | 0 | 1 | 2>('')
-
-  const auditStatusTxt = useMemo(() => {
-    let txt = ''
-    let obj = A5selArr1.find(v => v.value === auditStatus)
-    if (obj) txt = obj.label
-    return txt
-  }, [auditStatus])
-
-  // 审核状态-里面
-  const [auditStatus2, setAuditStatus2] = useState<'' | 0 | 1 | 2>('')
-
-  // 审核人
-  const [auditBy, setAuditBy] = useState('')
-
-  // 审核时间
-  const [auditTime, setAuditTime] = useState('')
-
-  // 审核备注
-  const [auditDesc, setAuditDesc] = useState('')
-
-  useEffect(() => {
-    // 设置封面图
-    imgRef.current?.setFileComFileFu({
-      fileName: '',
-      filePath: info.thumb
-    })
-
-    // 设置附件
-    ZupTxtRef.current?.setFileComFileFu({
-      fileName: info.fileName,
-      filePath: info.filePath
-    })
-
-    let storageIds: number[] = []
-    if (info.ancestor) storageIds = info.ancestor.split(',').map((v: string) => Number(v))
-    storageIds.push(Number(info.storageId))
-
-    setStorageIds(storageIds)
-
-    // 设置审核状态
-    setAuditStatus(info.auditStatus)
-
-    setAuditBy(info.creatorName)
-    setAuditTime(info.auditTime)
-    setAuditDesc(info.auditDesc)
-  }, [info])
-
-  // 审核页面
-  const [aduitShow, setAduitShow] = useState(false)
-
-  useEffect(() => {
-    if (aduitShow) setAuditStatus2(auditStatus)
-    else setAuditStatus2('')
-  }, [aduitShow, auditStatus, info.auditStatus])
-
-  // 审核点击确定
-  const btnOk = useCallback(async () => {
-    const obj = {
-      id: info.id,
-      auditDesc,
-      auditStatus: auditStatus2
-    }
-    const res = await A5_APIaudit(obj)
-    if (res.code === 0) {
-      MessageFu.success('审核成功!')
-      const res2 = await A5_APIgetInfo(info.id)
-      if (res2.code === 0) {
-        const data: A5tableType = res2.data
-
-        setAuditStatus(data.auditStatus)
-        setAuditBy(data.creatorName)
-        setAuditTime(data.auditTime)
-        setAuditDesc(data.auditDesc)
-        setAduitShow(false)
-
-        editTableFu()
-      }
-    }
-  }, [auditDesc, auditStatus2, editTableFu, info.id])
-
-  // 点击创建图书
-  const [creatorShow, setCreatorShow] = useState(false)
-
-  return (
-    <div className={styles.A5look}>
-      <div className='A5lMain'>
-        <div className='A5lRow'>
-          <div className='A5lLeft'>书名:</div>
-          <div className='A5lRight'>{info.name || '(空)'}</div>
-        </div>
-        <div className='A5lRow'>
-          <div className='A5lLeft'>简介:</div>
-          <div className='A5lRight'>{info.description || '(空)'}</div>
-        </div>
-        <div className='A5lRow'>
-          <div className='A5lLeft'>作者:</div>
-          <div className='A5lRight'>{info.author || '(空)'}</div>
-        </div>
-        <div className='A5lRow'>
-          <div className='A5lLeft'>出版社:</div>
-          <div className='A5lRight'>{info.press || '(空)'}</div>
-        </div>
-        <div className='A5lRow A5lRow2'>
-          <div className='A5lLeft'>出版年份:</div>
-          <div className='A5lRight'>{info.year || '(空)'}</div>
-        </div>
-        <div className='A5lRow'>
-          <div className='A5lLeft A5lLeft2'>封面:</div>
-          <div className='A5lRight'>
-            <ZupOne
-              ref={imgRef}
-              isLook={true}
-              fileCheck={false}
-              size={5}
-              dirCode={'A1manage'}
-              myUrl='cms/book/upload'
-              format={['image/jpeg', 'image/png']}
-              formatTxt='png、jpg和jpeg'
-              checkTxt='请上传封面图!'
-              upTxt='最多1张'
-              myType='thumb'
-            />
-          </div>
-        </div>
-        <div className='A5lRow'>
-          <div className='A5lLeft A5lLeft2'>中图法分类:</div>
-          <div className='A5lRight'>
-            <Cascader
-              allowClear={false}
-              changeOnSelect
-              style={{ width: 300 }}
-              options={storageArr}
-              fieldNames={{ label: 'name', value: 'id', children: 'children' }}
-              placeholder='请选择'
-              value={storageIds}
-            />
-          </div>
-        </div>
-        <div className='A5lRow'>
-          <div className='A5lLeft'>展示分类:</div>
-          <div className='A5lRight'>{info.exhibitTypeName || '(空)'}</div>
-        </div>
-        <div className='A5lRow'>
-          <div className='A5lLeft'>ISBN编号:</div>
-          <div className='A5lRight'>{info.num || '(空)'}</div>
-        </div>
-        <div className='A5lRow'>
-          <div className='A5lLeft'>附件:</div>
-          <div className='A5lRight'>
-            <ZupOne
-              ref={ZupTxtRef}
-              isLook={true}
-              fileCheck={false}
-              size={30}
-              dirCode='A1manage'
-              myUrl='cms/book/upload'
-              format={['']}
-              formatTxt='epub'
-              checkTxt='请上传epub附件!'
-              upTxt='最多1个'
-              myType='epub'
-            />
-          </div>
-        </div>
-        <div className='A5lRow'>
-          <div className='A5lLeft'>提交人:</div>
-          <div className='A5lRight'>{info.wxUserName || '(空)'}</div>
-        </div>
-        <div className='A5lRow'>
-          <div className='A5lLeft'>提交时间:</div>
-          <div className='A5lRight'>{info.createTime || '(空)'}</div>
-        </div>
-      </div>
-
-      {/* 右侧按钮 */}
-      <div className='A5lBtn'>
-        审核状态:{auditStatusTxt}
-        <br /> <br />
-        <Button type='primary' onClick={() => setAduitShow(true)}>
-          审核
-        </Button>
-        <br /> <br />
-        <Button type='primary' onClick={() => setCreatorShow(true)}>
-          创建图书
-        </Button>
-        <br /> <br />
-        <Button onClick={closeFuOne}>返回</Button>
-      </div>
-
-      {/* 审核出来的页面 */}
-      {aduitShow ? (
-        <Modal
-          wrapClassName={styles.A5lAduit}
-          open={true}
-          title='审核'
-          footer={
-            [] // 设置footer为空,去掉 取消 确定默认按钮
-          }
-        >
-          <div className='formRow'>
-            <div className='formLeft formLeft2'>审核状态:</div>
-            <div className='formRight'>
-              {A5selArr1.filter(v => v.label !== '全部').map(v => (
-                <Button
-                  onClick={() => setAuditStatus2(v.value as 0)}
-                  type={v.value === auditStatus2 ? 'primary' : 'default'}
-                  key={v.value}
-                >
-                  {v.label}
-                </Button>
-              ))}
-            </div>
-          </div>
-
-          <div className='formRow'>
-            <div className='formLeft'>
-              <span></span>审核人:
-            </div>
-            <div className='formRight'>{auditBy || '(空)'}</div>
-          </div>
-
-          <div className='formRow'>
-            <div className='formLeft'>
-              <span></span>审核时间:
-            </div>
-            <div className='formRight'>{auditTime || '(空)'}</div>
-          </div>
-
-          <div className='formRow'>
-            <div className='formLeft'>
-              <span></span>审核备注:
-            </div>
-            <div className='formRight'>
-              <TextArea
-                value={auditDesc}
-                onChange={e => setAuditDesc(e.target.value)}
-                rows={6}
-                placeholder='请输入内容'
-                maxLength={200}
-                showCount
-              />
-            </div>
-          </div>
-
-          <div className='A5lAduitBtn'>
-            <Button type='primary' onClick={btnOk}>
-              提交
-            </Button>
-            &emsp;
-            <MyPopconfirm txtK='取消' onConfirm={() => setAduitShow(false)} />
-          </div>
-        </Modal>
-      ) : null}
-
-      {/* 点击创建图书 */}
-      {creatorShow ? (
-        <div className='A5Ladd'>
-          <div>
-            <A1add
-              editInfo={{ id: info.id, txt: '编辑' }}
-              closeFu={() => setCreatorShow(false)}
-              addTableFu={() => {}}
-              editTableFu={() => {}}
-              storageArr={storageArr}
-              exhibitTypeArr={exhibitTypeObj.list}
-              isAudit={true}
-            />
-          </div>
-        </div>
-      ) : null}
-    </div>
-  )
-}
-
-const MemoA5look = React.memo(A5look)
-
-export default MemoA5look

+ 0 - 25
src/pages/A5bookAudit/data.ts

@@ -1,25 +0,0 @@
-export type A5FromDataType = {
-  auditStatus: '' | 0 | 1 | 2
-  searchKey: string
-  num: string
-  pageNum: number
-  pageSize: number
-}
-export const A5selArr1 = [
-  {
-    value: '',
-    label: '全部'
-  },
-  {
-    value: 0,
-    label: '待审核'
-  },
-  {
-    value: 1,
-    label: '审核通过'
-  },
-  {
-    value: 2,
-    label: '审核驳回'
-  }
-]

+ 0 - 161
src/pages/A5bookAudit/index.tsx

@@ -1,161 +0,0 @@
-import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
-import styles from './index.module.scss'
-import { A5FromDataType, A5selArr1 } from './data'
-import { useDispatch, useSelector } from 'react-redux'
-import { A5_APIdel, A5_APIgetList } from '@/store/action/A5bookAudit'
-import { RootState } from '@/store'
-import { MessageFu } from '@/utils/message'
-import { A5tableType } from '@/types'
-import { Button, Input, Select } from 'antd'
-import MyPopconfirm from '@/components/MyPopconfirm'
-import MyTable from '@/components/MyTable'
-import { A5tableC } from '@/utils/tableData'
-import A5look from './A5look'
-
-const fromDataBase: A5FromDataType = {
-  auditStatus: '',
-  searchKey: '',
-  num: '',
-  pageNum: 1,
-  pageSize: 10
-}
-
-function A5bookAudit() {
-  const dispatch = useDispatch()
-
-  const [fromData, setFromData] = useState(fromDataBase)
-
-  const getListFu = useCallback(() => {
-    dispatch(A5_APIgetList(fromData))
-  }, [dispatch, fromData])
-
-  useEffect(() => {
-    getListFu()
-  }, [getListFu])
-
-  const [inputKey, setInputKey] = useState(1)
-
-  // 输入框的输入
-  const timeRef = useRef(-1)
-  const txtChangeFu = useCallback(
-    (e: React.ChangeEvent<HTMLInputElement>, key: 'searchKey' | 'num') => {
-      clearTimeout(timeRef.current)
-      timeRef.current = window.setTimeout(() => {
-        setFromData({ ...fromData, [key]: e.target.value.replaceAll("'", ''), pageNum: 1 })
-      }, 500)
-    },
-    [fromData]
-  )
-
-  // 点击重置
-  const resetSelectFu = useCallback(() => {
-    setInputKey(Date.now())
-    setFromData({ ...fromDataBase })
-  }, [])
-
-  const tableInfo = useSelector((state: RootState) => state.A5bookAudit.tableInfo)
-
-  const delTableFu = useCallback(
-    async (id: number) => {
-      const res = await A5_APIdel(id)
-      if (res.code === 0) {
-        MessageFu.success('删除成功!')
-        getListFu()
-      }
-    },
-    [getListFu]
-  )
-
-  const tableLastBtn = useMemo(() => {
-    return [
-      {
-        title: '操作',
-        render: (item: A5tableType) => (
-          <>
-            <Button size='small' type='text' onClick={() => setLookInfo(item)}>
-              查看
-            </Button>
-
-            <MyPopconfirm txtK='删除' onConfirm={() => delTableFu(item.id)} />
-          </>
-        )
-      }
-    ]
-  }, [delTableFu])
-
-  // 点击查看
-  const [lookInfo, setLookInfo] = useState({} as A5tableType)
-
-  return (
-    <div className={styles.A5bookAudit}>
-      <div className='pageTitle'>图书审核{lookInfo.id ? ' - 查看' : ''}</div>
-
-      {/* 顶部筛选 */}
-      <div className='A5top'>
-        <div>
-          <div className='A5TopRow'>
-            <span>搜索:</span>
-            <Input
-              key={inputKey}
-              maxLength={20}
-              style={{ width: 200 }}
-              placeholder='请输入书名/作者/出版社'
-              allowClear
-              onChange={e => txtChangeFu(e, 'searchKey')}
-            />
-            &nbsp;
-            <Input
-              key={inputKey + 1}
-              maxLength={20}
-              style={{ width: 200 }}
-              placeholder='请输入完整ISBN编号'
-              allowClear
-              onChange={e => txtChangeFu(e, 'num')}
-            />
-          </div>
-
-          <div className='A5TopRow'>
-            <span>审核状态:</span>
-            <Select
-              placeholder='全部'
-              style={{ width: 180 }}
-              value={fromData.auditStatus}
-              onChange={e => setFromData({ ...fromData, pageNum: 1, auditStatus: e })}
-              options={A5selArr1}
-            />
-          </div>
-        </div>
-        <div>
-          <Button onClick={resetSelectFu}>重置</Button>&emsp;
-        </div>
-      </div>
-
-      {/* 表格主体 */}
-      <div className='A5tableBox'>
-        <MyTable
-          yHeight={625}
-          list={tableInfo.list}
-          columnsTemp={A5tableC}
-          lastBtn={tableLastBtn}
-          pageNum={fromData.pageNum}
-          pageSize={fromData.pageSize}
-          total={tableInfo.total}
-          onChange={(pageNum, pageSize) => setFromData({ ...fromData, pageNum, pageSize })}
-        />
-      </div>
-
-      {/* 点击查看 */}
-      {lookInfo.id ? (
-        <A5look
-          info={lookInfo}
-          closeFuOne={() => setLookInfo({} as A5tableType)}
-          editTableFu={getListFu}
-        />
-      ) : null}
-    </div>
-  )
-}
-
-const MemoA5bookAudit = React.memo(A5bookAudit)
-
-export default MemoA5bookAudit

+ 110 - 0
src/pages/A6exhibition/A6add/index.module.scss

@@ -0,0 +1,110 @@
+.A6add {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  z-index: 12;
+  background-color: #fff;
+  border-radius: 10px;
+  padding: 24px;
+
+  :global {
+    .A6aMain {
+      width: 100%;
+      height: calc(100% - 80px);
+      overflow-y: auto;
+
+      textarea {
+        min-height: 75px !important;
+      }
+
+      .A6fromRow {
+        position: relative;
+        width: 800px;
+
+        .A6_6Frow {
+          position: absolute;
+          left: 200px;
+          top: 5px;
+          color: #999;
+          font-size: 12px;
+        }
+      }
+
+      .ant-form {
+        width: 800px;
+        display: flex;
+        flex-direction: column;
+        gap: 30px;
+
+        // .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);
+          }
+        }
+
+        .A6abtn {
+          display: flex;
+          align-items: center;
+          width: 100%;
+          height: 80px;
+          position: fixed;
+          bottom: 0;
+          background: #fff;
+          z-index: 10;
+
+          .A6abtnBox {
+            display: flex;
+            gap: 20px;
+            padding-left: 100px;
+          }
+        }
+      }
+    }
+
+    // 从查看进入
+    .A6aMainLook {
+      // 左边的 label 也不让选中
+      label {
+        pointer-events: none;
+      }
+
+      .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;
+      }
+    }
+  }
+}

+ 279 - 0
src/pages/A6exhibition/A6add/index.tsx

@@ -0,0 +1,279 @@
+import React, { useCallback, useEffect, useRef, useState } from 'react'
+import styles from './index.module.scss'
+import classNames from 'classnames'
+import { A1EditInfoType } from '../data'
+import { Button, Form, FormInstance, Input, DatePicker, Select } from 'antd'
+import TextArea from 'antd/es/input/TextArea'
+import { A6_APIgetInfo, A6_APIadd, A6_APIedit } from '@/store/action/A6exhibition'
+import { MessageFu } from '@/utils/message'
+import ZupOne from '@/components/ZupOne'
+import MyPopconfirm from '@/components/MyPopconfirm'
+import dayjs from 'dayjs'
+import ZRichTexts from '@/components/ZRichTexts'
+import { A6AddType, A6tableType } from '@/types/api/A6exhibition'
+
+type Props = {
+  editInfo: A1EditInfoType
+  closeFu: () => void
+  addTableFu: () => void
+  editTableFu: () => void
+}
+
+function A6add({ editInfo, closeFu, addTableFu, editTableFu }: Props) {
+  // 表单的ref
+  const FormBoxRef = useRef<FormInstance>(null)
+
+  // 封面图的ref
+  const ZupThumbRef1 = useRef<any>(null)
+  // 正文的ref
+  const ZRichTextRef = useRef<any>(null)
+
+  // 回显数据的方法调用
+  const dataShow = useCallback((info: A6tableType) => {
+    let editObj = null
+    if (info.status === 0) {
+      editObj = {
+        ...info,
+        title: info.titleB,
+        publish: info.publishB,
+        remark: info.remarkB,
+        context: info.contextB,
+        img: info.imgB,
+        imgTh: info.imgThB,
+        webSite: info.webSiteB
+      }
+    } else {
+      editObj = { ...info }
+    }
+    console.log('-xsxxas', editObj)
+    FormBoxRef.current?.setFieldsValue({ ...editObj, publish: dayjs(editObj.publish) })
+
+    // 设置封面图
+    ZupThumbRef1.current?.setFileComFileFu({
+      fileName: '',
+      thUrl: editObj.imgTh,
+      url: editObj.img
+    })
+
+    // 设置正文
+    ZRichTextRef.current?.ritxtShowFu({
+      txtArr: [
+        {
+          id: editObj.exhibitId,
+          name: '正文',
+          txt: editObj.context,
+          fileInfo: { fileName: '', filePath: '' }
+        }
+      ]
+    })
+  }, [])
+
+  // 编辑 进入页面 获取信息
+  const getInfoFu = useCallback(
+    async (id: number) => {
+      if (editInfo.info) dataShow(editInfo.info)
+      else {
+        const res = await A6_APIgetInfo(id)
+        if (res.code === 0) {
+          dataShow(res.data)
+        }
+      }
+    },
+    [dataShow, editInfo.info]
+  )
+
+  // 附件 是否 已经点击过确定
+  const [fileCheck, setFileCheck] = useState(false)
+
+  // 编辑填入数据
+  useEffect(() => {
+    if (editInfo.id > 0) {
+      getInfoFu(editInfo.id)
+    }
+  }, [editInfo.id, getInfoFu])
+
+  // 没有通过校验
+  const onFinishFailed = useCallback(() => {
+    setFileCheck(true)
+  }, [])
+
+  //  通过校验点击确定
+  const onFinish = useCallback(
+    async (values: any) => {
+      setFileCheck(true)
+
+      const coverUrl1 = ZupThumbRef1.current?.fileComFileResFu()
+      const context = ZRichTextRef.current?.fatherBtnOkFu()
+      // 没有传 封面图
+      if (!coverUrl1.url) return MessageFu.warning('请上传首页封面图!')
+      if (!context.val.txtArr[0].txt) return MessageFu.warning('请输入正文!')
+
+      // 发布
+      const obj1: A6AddType = {
+        ...values,
+        img: coverUrl1.url,
+        imgTh: coverUrl1.thUrl,
+        context: context.val.txtArr[0].txt,
+        publishB: '',
+        status: 1,
+        titleB: '',
+        webSiteB: ''
+      }
+
+      // 预发布
+      const obj2: A6AddType = {
+        img: '',
+        imgB: coverUrl1.url,
+        imgTh: '',
+        imgThB: coverUrl1.thUrl,
+        publish: '',
+        publishB: values.publish,
+        status: 0,
+        type: values.type,
+        title: '',
+        titleB: values.title,
+        remark: '',
+        remarkB: values.remark,
+        context: '',
+        contextB: context.val.txtArr[0].txt,
+        webSiteB: values.webSite,
+        webSite: ''
+      }
+
+      let res: any
+      if (btnRef.current === '1') {
+        res =
+          editInfo.txt === '新增'
+            ? await A6_APIadd(obj1)
+            : await A6_APIedit({ ...obj1, exhibitId: editInfo.id })
+      } else {
+        res =
+          editInfo.txt === '新增'
+            ? await A6_APIadd(obj2)
+            : await A6_APIedit({ ...obj2, exhibitId: editInfo.id })
+      }
+
+      if (res.code === 0) {
+        MessageFu.success(`${editInfo.txt}成功!`)
+        editInfo.id > 0 ? editTableFu() : addTableFu()
+        closeFu()
+      }
+    },
+    [addTableFu, closeFu, editInfo.id, editInfo.txt, editTableFu]
+  )
+
+  const formOkBtnRef = useRef<any>(null)
+
+  const btnRef = useRef('')
+
+  return (
+    <div className={styles.A6add}>
+      <div className={classNames('A6aMain')}>
+        <Form
+          ref={FormBoxRef}
+          name='basic'
+          labelCol={{ span: 3 }}
+          onFinish={onFinish}
+          onFinishFailed={onFinishFailed}
+          autoComplete='off'
+          scrollToFirstError
+        >
+          <Form.Item
+            label='标题'
+            name='title'
+            rules={[{ required: true, message: '请输入标题!' }]}
+          >
+            <Input placeholder='请输入内容,不超过30个字' maxLength={30} showCount />
+          </Form.Item>
+
+          <Form.Item label='展览类型' name='type'>
+            <Select
+              placeholder='请选择展览类型'
+              options={[
+                { label: '室内展览', value: 1 },
+                { label: '室外展览', value: 2 }
+              ]}
+            />
+          </Form.Item>
+
+          <Form.Item label='发表日期' name='publish'>
+            <DatePicker allowClear placeholder='请选择日期' style={{ width: 200 }} />
+          </Form.Item>
+
+          <Form.Item label='摘要' name='remark'>
+            <TextArea maxLength={200} showCount placeholder='请输入内容,不超过200个字' />
+          </Form.Item>
+
+          <Form.Item label='正文' name='context'>
+            <ZRichTexts
+              check={true}
+              dirCode={'A4news'}
+              isLook={false}
+              ref={ZRichTextRef}
+              myUrl='museum/upload/upload'
+              isOne={true}
+              upAudioBtnNone={true}
+            />
+          </Form.Item>
+
+          <Form.Item label='虚拟展厅' name='webSite'>
+            <Input placeholder='请输入链接' />
+          </Form.Item>
+
+          {/* 封面 */}
+          <div className='formRow'>
+            <div className='formLeft'>
+              <span>* </span>
+              封面:
+            </div>
+            <div className='formRight'>
+              <ZupOne
+                ref={ZupThumbRef1}
+                fileCheck={fileCheck}
+                size={5}
+                dirCode={'A1banner'}
+                myUrl='museum/upload/uploadImg'
+                format={['image/jpeg', 'image/png']}
+                formatTxt='png、jpg和jpeg'
+                checkTxt='请上传封面图!'
+                upTxt='最多1张'
+                myType='thumb'
+              />
+            </div>
+          </div>
+
+          {/* 确定和取消按钮 */}
+          <Form.Item className='A6abtn'>
+            <div className='A6abtnBox'>
+              <Button
+                type='primary'
+                htmlType='submit'
+                onClick={() => {
+                  btnRef.current = '1'
+                  formOkBtnRef.current?.click()
+                }}
+              >
+                发布
+              </Button>
+              <Button
+                type='primary'
+                htmlType='submit'
+                onClick={() => {
+                  btnRef.current = '0'
+                  formOkBtnRef.current?.click()
+                }}
+              >
+                预发布
+              </Button>
+              <MyPopconfirm txtK='取消' onConfirm={closeFu} />
+            </div>
+          </Form.Item>
+        </Form>
+      </div>
+    </div>
+  )
+}
+
+const MemoA6add = React.memo(A6add)
+
+export default MemoA6add

+ 7 - 0
src/pages/A6exhibition/data.ts

@@ -0,0 +1,7 @@
+import { A6tableType } from '@/types/api/A6exhibition'
+
+export type A1EditInfoType = {
+  id: number
+  txt: '新增' | '编辑' | '查看' | ''
+  info?: A6tableType
+}

+ 10 - 9
src/pages/A1manage/index.module.scss

@@ -1,25 +1,26 @@
-.A1manage {
+.A6exhibition {
   position: relative;
   :global {
-    .A1top {
+    .A6top {
       border-radius: 10px;
       background-color: #fff;
       padding: 15px 24px;
       display: flex;
       justify-content: space-between;
-      & > div {
+      gap: 20px;
+      .A6topLeft {
         display: flex;
-        .A1TopRow {
+        gap: 20px;
+        .rowItem {
+          margin-left: 20px;
+          width: 200px;
           display: flex;
           align-items: center;
-          margin-right: 20px;
-          .ant-select-selection-placeholder {
-            color: black;
-          }
+          gap: 10px;
         }
       }
     }
-    .A1tableBox {
+    .A6tableBox {
       border-radius: 10px;
       overflow: hidden;
       margin-top: 15px;

+ 168 - 0
src/pages/A6exhibition/index.tsx

@@ -0,0 +1,168 @@
+import React, { useCallback, useEffect, useMemo, useState } from 'react'
+import styles from './index.module.scss'
+import { Button, Input, Select } from 'antd'
+import { useDispatch, useSelector } from 'react-redux'
+import { A1EditInfoType } from './data'
+import { A6_APIdel, A6_APIgetList, A6_APIpublish } from '@/store/action/A6exhibition'
+import { RootState } from '@/store'
+import { MessageFu } from '@/utils/message'
+import { A6tableType } from '@/types/api/A6exhibition'
+import MyPopconfirm from '@/components/MyPopconfirm'
+import MyTable from '@/components/MyTable'
+import { A6tableC } from '@/utils/tableData'
+import A6add from './A6add'
+
+const pageDataBase = {
+  pageNum: 1,
+  pageSize: 10
+}
+
+function A6exhibition() {
+  const dispatch = useDispatch()
+
+  const [pageData, setPageData] = useState(pageDataBase)
+  const [title, setTitle] = useState('')
+  const [type, setType] = useState(0)
+  const getListFu = useCallback(
+    (title?: string) => {
+      // status: -1 全部 0 未发布 1 已发布
+      dispatch(A6_APIgetList({ ...pageData, status: -1, title, type }))
+    },
+    [dispatch, pageData, type]
+  )
+
+  useEffect(() => {
+    getListFu()
+  }, [getListFu])
+
+  // 点击重置
+  const resetSelectFu = useCallback(() => {
+    setPageData({ ...pageDataBase })
+  }, [])
+
+  const tableInfo = useSelector((state: RootState) => state.A6exhibition.tableInfo)
+
+  const delTableFu = useCallback(
+    async (id: number) => {
+      const res = await A6_APIdel(id)
+      if (res.code === 0) {
+        MessageFu.success('删除成功!')
+        getListFu()
+      }
+    },
+    [getListFu]
+  )
+
+  const publishFu = useCallback(
+    async (id: number) => {
+      const res = await A6_APIpublish(id)
+      if (res.code === 0) {
+        MessageFu.success('发布成功!')
+        getListFu()
+      }
+    },
+    [getListFu]
+  )
+
+  const tableLastBtn = useMemo(() => {
+    return [
+      {
+        title: '操作',
+        render: (item: A6tableType) => (
+          <>
+            {item.status === 0 && (
+              <Button size='small' type='text'>
+                预览
+              </Button>
+            )}
+            <Button
+              size='small'
+              type='text'
+              onClick={() => setEditInfo({ id: item.exhibitId, txt: '编辑' })}
+            >
+              编辑
+            </Button>
+            {item.status === 0 && (
+              <Button size='small' type='text' onClick={() => publishFu(item.exhibitId)}>
+                发布
+              </Button>
+            )}
+            <MyPopconfirm txtK='删除' onConfirm={() => delTableFu(item.exhibitId)} />
+          </>
+        )
+      }
+    ]
+  }, [delTableFu, publishFu])
+
+  //新增、编辑
+  const [editInfo, setEditInfo] = useState<A1EditInfoType>({
+    id: 0,
+    txt: ''
+  })
+
+  return (
+    <div className={styles.A6exhibition}>
+      <div className='pageTitle'>展览列表 {editInfo.id ? ` - ${editInfo.txt}` : ''}</div>
+
+      {/* 顶部筛选 */}
+      <div className='A6top'>
+        <div className='A6topLeft'>
+          <Input
+            style={{ width: 200 }}
+            placeholder='请输入标题'
+            onChange={e => setTitle(e.target.value)}
+          />
+
+          <Button type='primary' onClick={() => getListFu(title)}>
+            搜索
+          </Button>
+          <div className='rowItem'>
+            展览类型:
+            <Select
+              style={{ width: 120 }}
+              defaultValue={0}
+              options={[
+                { label: '全部', value: 0 },
+                { label: '室内', value: 1 },
+                { label: '室外', value: 2 }
+              ]}
+              onChange={value => setType(value)}
+            />
+          </div>
+        </div>
+        <Button type='primary' onClick={() => setEditInfo({ id: -1, txt: '新增' })}>
+          新增
+        </Button>
+      </div>
+
+      {/* 表格主体 */}
+      <div className='A6tableBox'>
+        <MyTable
+          myKey='exhibitId'
+          yHeight={625}
+          list={tableInfo.list}
+          columnsTemp={A6tableC}
+          lastBtn={tableLastBtn}
+          pageNum={pageData.pageNum}
+          pageSize={pageData.pageSize}
+          total={tableInfo.total}
+          onChange={(pageNum, pageSize) => setPageData({ ...pageData, pageNum, pageSize })}
+        />
+      </div>
+
+      {/* 新增 / 编辑 */}
+      {editInfo.id ? (
+        <A6add
+          editInfo={editInfo}
+          closeFu={() => setEditInfo({ id: 0, txt: '新增' })}
+          addTableFu={resetSelectFu}
+          editTableFu={getListFu}
+        />
+      ) : null}
+    </div>
+  )
+}
+
+const MemoA6exhibition = React.memo(A6exhibition)
+
+export default MemoA6exhibition

+ 0 - 108
src/pages/A6remarkAudit/A6audit.tsx

@@ -1,108 +0,0 @@
-import React, { useCallback, useEffect, useState } from 'react'
-import styles from './index.module.scss'
-import { Button, Modal } from 'antd'
-import { A5selArr1 } from '../A5bookAudit/data'
-import MyPopconfirm from '@/components/MyPopconfirm'
-import { A6tableType } from '@/types'
-import { A6_APIaudit, A6_APIgetInfo } from '@/store/action/A6remarkAudit'
-import { MessageFu } from '@/utils/message'
-
-type Props = {
-  id: number
-  closeFu: () => void
-  editTableFu: () => void
-}
-
-function A6audit({ id, closeFu, editTableFu }: Props) {
-  const [auditStatus, setAuditStatus] = useState<null | 0 | 1 | 2>(null)
-
-  const [info, setInfo] = useState({} as A6tableType)
-
-  const getInfo = useCallback(async (id: number) => {
-    const res = await A6_APIgetInfo(id)
-    if (res.code === 0) {
-      setInfo(res.data)
-      setAuditStatus(res.data.auditStatus)
-    }
-  }, [])
-
-  useEffect(() => {
-    getInfo(id)
-  }, [getInfo, id])
-
-  const btnOk = useCallback(async () => {
-    const obj = {
-      id,
-      auditStatus
-    }
-    const res = await A6_APIaudit(obj)
-
-    if (res.code === 0) {
-      MessageFu.success('审核成功!')
-      closeFu()
-      editTableFu()
-    }
-  }, [auditStatus, closeFu, editTableFu, id])
-
-  return (
-    <Modal
-      wrapClassName={styles.A6audit}
-      open={true}
-      title='审核'
-      footer={
-        [] // 设置footer为空,去掉 取消 确定默认按钮
-      }
-    >
-      <div className='formRow'>
-        <div className='formLeft'>书名:</div>
-        <div className='formRight'>{info.bookName || '(空)'}</div>
-      </div>
-
-      <div className='formRow'>
-        <div className='formLeft'>评论内容:</div>
-        <div className='formRight'>{info.content || '(空)'}</div>
-      </div>
-
-      <div className='formRow'>
-        <div className='formLeft formLeft2'>审核状态:</div>
-        <div className='formRight'>
-          {A5selArr1.filter(v => v.label !== '全部').map(v => (
-            <Button
-              onClick={() => setAuditStatus(v.value as 0)}
-              type={v.value === auditStatus ? 'primary' : 'default'}
-              key={v.value}
-            >
-              {v.label}
-            </Button>
-          ))}
-        </div>
-      </div>
-
-      <div className='formRow'>
-        <div className='formLeft'>
-          <span></span>审核人:
-        </div>
-        <div className='formRight'>{info.creatorName || '(空)'}</div>
-      </div>
-
-      <div className='formRow'>
-        <div className='formLeft'>
-          <span></span>审核时间:
-        </div>
-        <div className='formRight'>{info.auditTime || '(空)'}</div>
-      </div>
-
-      <div className='A6aBtn'>
-        <Button type='primary' onClick={btnOk}>
-          提交
-        </Button>
-        &emsp;
-        <MyPopconfirm txtK='取消' onConfirm={closeFu} />
-      </div>
-    </Modal>
-  )
-}
-
-const MemoA6audit = React.memo(A6audit)
-
-export default MemoA6audit

+ 0 - 79
src/pages/A6remarkAudit/index.module.scss

@@ -1,79 +0,0 @@
-.A6remarkAudit {
-  position: relative;
-  :global {
-    .A6top {
-      border-radius: 10px;
-      background-color: #fff;
-      padding: 15px 24px;
-      display: flex;
-      justify-content: space-between;
-      & > div {
-        display: flex;
-        .A6TopRow {
-          display: flex;
-          align-items: center;
-          margin-right: 20px;
-          .ant-select-selection-placeholder {
-            color: black;
-          }
-        }
-      }
-    }
-    .A6tableBox {
-      border-radius: 10px;
-      overflow: hidden;
-      margin-top: 15px;
-      height: calc(100% - 77px);
-      background-color: #fff;
-    }
-  }
-}
-
-// 审核
-.A6audit {
-  :global {
-    .ant-modal-close {
-      display: none;
-    }
-    .ant-modal {
-      width: 800px !important;
-      // top: 30%;
-    }
-    .ant-modal-body {
-      border-top: 1px solid #ccc;
-      padding-top: 15px !important;
-    }
-
-    .formRow {
-      display: flex;
-      // align-items: center;
-      margin-bottom: 24px;
-
-      .formLeft {
-        width: 80px;
-        text-align: right;
-
-        & > span {
-          color: #ff4d4f;
-        }
-      }
-      .formLeft2 {
-        position: relative;
-        top: 4px;
-      }
-
-      .formRight {
-        width: calc(100% - 80px);
-        position: relative;
-        .ant-btn {
-          margin-right: 15px;
-        }
-      }
-    }
-
-    .A6aBtn {
-      text-align: center;
-      margin-top: 50px;
-    }
-  }
-}

+ 0 - 121
src/pages/A6remarkAudit/index.tsx

@@ -1,121 +0,0 @@
-import React, { useCallback, useEffect, useMemo, useState } from 'react'
-import styles from './index.module.scss'
-import { A5FromDataType, A5selArr1 } from '../A5bookAudit/data'
-import { useDispatch, useSelector } from 'react-redux'
-import { A6_APIdel, A6_APIgetList } from '@/store/action/A6remarkAudit'
-import { RootState } from '@/store'
-import { MessageFu } from '@/utils/message'
-import { A6tableType } from '@/types'
-import { Button, Select } from 'antd'
-import MyPopconfirm from '@/components/MyPopconfirm'
-import MyTable from '@/components/MyTable'
-import { A6tableC } from '@/utils/tableData'
-import A6audit from './A6audit'
-
-type A6FromDataType = Omit<A5FromDataType, 'searchKey' | 'num'>
-
-const fromDataBase: A6FromDataType = {
-  auditStatus: '',
-  pageNum: 1,
-  pageSize: 10
-}
-
-function A6remarkAudit() {
-  const dispatch = useDispatch()
-
-  const [fromData, setFromData] = useState(fromDataBase)
-
-  const getListFu = useCallback(() => {
-    dispatch(A6_APIgetList(fromData))
-  }, [dispatch, fromData])
-
-  useEffect(() => {
-    getListFu()
-  }, [getListFu])
-
-  // 点击重置
-  const resetSelectFu = useCallback(() => {
-    setFromData({ ...fromDataBase })
-  }, [])
-
-  const tableInfo = useSelector((state: RootState) => state.A6remarkAudit.tableInfo)
-
-  const delTableFu = useCallback(
-    async (id: number) => {
-      const res = await A6_APIdel(id)
-      if (res.code === 0) {
-        MessageFu.success('删除成功!')
-        getListFu()
-      }
-    },
-    [getListFu]
-  )
-
-  const tableLastBtn = useMemo(() => {
-    return [
-      {
-        title: '操作',
-        render: (item: A6tableType) => (
-          <>
-            <Button size='small' type='text' onClick={() => setAuditId(item.id)}>
-              审核
-            </Button>
-
-            <MyPopconfirm txtK='删除' onConfirm={() => delTableFu(item.id)} />
-          </>
-        )
-      }
-    ]
-  }, [delTableFu])
-
-  // 审核弹窗id
-  const [auditId, setAuditId] = useState(0)
-
-  return (
-    <div className={styles.A6remarkAudit}>
-      <div className='pageTitle'>评论审核</div>
-
-      {/* 顶部筛选 */}
-      <div className='A6top'>
-        <div>
-          <div className='A6TopRow'>
-            <span>审核状态:</span>
-            <Select
-              placeholder='全部'
-              style={{ width: 180 }}
-              value={fromData.auditStatus}
-              onChange={e => setFromData({ ...fromData, pageNum: 1, auditStatus: e })}
-              options={A5selArr1}
-            />
-          </div>
-        </div>
-        <div>
-          <Button onClick={resetSelectFu}>重置</Button>&emsp;
-        </div>
-      </div>
-
-      {/* 表格主体 */}
-      <div className='A6tableBox'>
-        <MyTable
-          yHeight={625}
-          list={tableInfo.list}
-          columnsTemp={A6tableC}
-          lastBtn={tableLastBtn}
-          pageNum={fromData.pageNum}
-          pageSize={fromData.pageSize}
-          total={tableInfo.total}
-          onChange={(pageNum, pageSize) => setFromData({ ...fromData, pageNum, pageSize })}
-        />
-      </div>
-
-      {/* 点击审核 */}
-      {auditId ? (
-        <A6audit id={auditId} closeFu={() => setAuditId(0)} editTableFu={getListFu} />
-      ) : null}
-    </div>
-  )
-}
-
-const MemoA6remarkAudit = React.memo(A6remarkAudit)
-
-export default MemoA6remarkAudit

+ 19 - 7
src/pages/A7notice/A7add/index.module.scss

@@ -12,18 +12,18 @@
   :global {
     .A7aMain {
       width: 100%;
-      height: 100%;
+      height: calc(100% - 80px);
       overflow-y: auto;
 
       textarea {
         min-height: 75px !important;
       }
 
-      .A1fromRow {
+      .A7fromRow {
         position: relative;
         width: 800px;
 
-        .A1_6Frow {
+        .A7_6Frow {
           position: absolute;
           left: 200px;
           top: 5px;
@@ -34,6 +34,9 @@
 
       .ant-form {
         width: 800px;
+        display: flex;
+        flex-direction: column;
+        gap: 30px;
 
         // .ant-input-affix-wrapper{
         //   width: 800px;
@@ -58,11 +61,20 @@
         }
 
         .A7abtn {
-          position: absolute;
+          display: flex;
+          align-items: center;
+          width: 100%;
+          height: 80px;
+          position: fixed;
+          bottom: 0;
+          background: #fff;
           z-index: 10;
-          left: 1200px;
-          top: 50%;
-          transform: translateY(-50%);
+
+          .A7abtnBox {
+            display: flex;
+            gap: 20px;
+            padding-left: 100px;
+          }
         }
       }
     }

+ 333 - 0
src/pages/A7collection/A7add/index.tsx

@@ -0,0 +1,333 @@
+import React, { useCallback, useEffect, useRef, useState } from 'react'
+import styles from './index.module.scss'
+import classNames from 'classnames'
+import { A1EditInfoType } from '../data'
+import { Button, Form, FormInstance, Input, DatePicker, Select } from 'antd'
+import TextArea from 'antd/es/input/TextArea'
+import { A7_APIgetInfo, A7_APIadd, A7_APIedit } from '@/store/action/A7collection'
+import { MessageFu } from '@/utils/message'
+import ZupOne from '@/components/ZupOne'
+import MyPopconfirm from '@/components/MyPopconfirm'
+import dayjs from 'dayjs'
+import { A7AddType, A7tableType } from '@/types/api/A7collection'
+import ZupTypes from '@/components/ZupTypes'
+
+type Props = {
+  editInfo: A1EditInfoType
+  closeFu: () => void
+  addTableFu: () => void
+  editTableFu: () => void
+}
+
+function A7add({ editInfo, closeFu, addTableFu, editTableFu }: Props) {
+  // 表单的ref
+  const FormBoxRef = useRef<FormInstance>(null)
+
+  // 封面图的ref
+  const ZupThumbRef1 = useRef<any>(null)
+
+  // 附件的ref
+  const ZupTypesRef = useRef<any>(null)
+
+  // 回显数据的方法调用
+  const dataShow = useCallback((info: A7tableType) => {
+    let editObj = null
+    if (info.status === 0) {
+      editObj = {
+        ...info,
+        title: info.titleB,
+        type: info.typeB,
+        era: info.eraB,
+        texture: info.textureB,
+        size: info.sizeB,
+        publish: info.publishB,
+        remark: info.remarkB,
+        img: info.imgB,
+        imgTh: info.imgThB,
+        typeModel: info.typeModelB,
+        typeImage: info.typeImageB,
+        typeAudio: info.typeAudioB,
+        typeVideo: info.typeVideoB,
+        modelFile: info.modelFileB,
+        imageFiles: info.imageFilesB,
+        videoFile: info.videoFileB,
+        audioFile: info.audioFileB,
+        webSite: info.webSiteB
+      }
+    } else {
+      editObj = { ...info }
+    }
+    console.log('-xsxxas', editObj)
+    FormBoxRef.current?.setFieldsValue({ ...editObj, publish: dayjs(editObj.publish) })
+
+    // 设置封面图
+    ZupThumbRef1.current?.setFileComFileFu({
+      fileName: '',
+      thUrl: editObj.imgTh,
+      url: editObj.img
+    })
+
+    // 设置附件
+    const imgFileList = editObj.typeImage
+      ? editObj.imageFiles.map((v: any) => ({
+          fileName: v.split('/').pop(),
+          filePath: v,
+          id: v,
+          type: 'img'
+        }))
+      : []
+    ZupTypesRef.current?.setFileComFileFu({
+      fileList: [
+        ...imgFileList,
+        editObj.typeModel && {
+          fileName: editObj.modelFile.split('/').pop(),
+          filePath: editObj.modelFile,
+          id: editObj.modelFile,
+          type: 'model'
+        },
+        editObj.typeAudio && {
+          fileName: editObj.audioFile.split('/').pop(),
+          filePath: editObj.audioFile,
+          id: editObj.audioFile,
+          type: 'audio'
+        },
+        editObj.typeVideo && {
+          fileName: editObj.videoFile.split('/').pop(),
+          filePath: editObj.videoFile,
+          id: editObj.videoFile,
+          type: 'video'
+        }
+      ],
+      type: [
+        editObj.typeImage && 'img',
+        editObj.typeModel && 'model',
+        editObj.typeAudio && 'audio',
+        editObj.typeVideo && 'video'
+      ]
+    })
+  }, [])
+
+  // 编辑 进入页面 获取信息
+  const getInfoFu = useCallback(
+    async (id: number) => {
+      if (editInfo.info) dataShow(editInfo.info)
+      else {
+        const res = await A7_APIgetInfo(id)
+        if (res.code === 0) {
+          dataShow(res.data)
+        }
+      }
+    },
+    [dataShow, editInfo.info]
+  )
+
+  // 附件 是否 已经点击过确定
+  const [fileCheck, setFileCheck] = useState(false)
+
+  // 编辑填入数据
+  useEffect(() => {
+    if (editInfo.id > 0) {
+      getInfoFu(editInfo.id)
+    }
+  }, [editInfo.id, getInfoFu])
+
+  // 没有通过校验
+  const onFinishFailed = useCallback(() => {
+    setFileCheck(true)
+  }, [])
+
+  //  通过校验点击确定
+  const onFinish = useCallback(
+    async (values: any) => {
+      setFileCheck(true)
+
+      const coverUrl1 = ZupThumbRef1.current?.fileComFileResFu()
+      const { fileList, sonType } = ZupTypesRef.current?.fileComFileResFu()
+      console.log('-xsxxas', fileList)
+      // 没有传 封面图
+      if (!coverUrl1.url) return MessageFu.warning('请上传首页封面图!')
+      if (sonType.length === 0) return MessageFu.warning('请上传附件!')
+
+      // 发布
+      const obj1: A7AddType = {
+        ...values,
+        img: coverUrl1.url,
+        imgTh: coverUrl1.thUrl,
+        status: 1,
+        modelFile: fileList.model.filePath || '',
+        imageFiles: fileList.img.map((v: any) => v.filePath) || [],
+        videoFile: fileList.video.filePath || '',
+        audioFile: fileList.audio.filePath || '',
+        typeModel: sonType.includes('model') || false,
+        typeImage: sonType.includes('img') || false,
+        typeAudio: sonType.includes('audio') || false,
+        typeVideo: sonType.includes('video') || false
+      }
+
+      // 预发布
+      const obj2: A7AddType = {
+        ...values,
+        audioFileB: fileList.audio.filePath || '',
+        eraB: values.era,
+        imageFilesB: fileList.img.map((v: any) => v.filePath) || [],
+        imgB: coverUrl1.url,
+        imgThB: coverUrl1.thUrl,
+        modelFileB: fileList.model.filePath || '',
+        publishB: values.publish,
+        remarkB: values.remark,
+        sizeB: values.size,
+        status: 0,
+        textureB: values.texture,
+        titleB: values.title,
+        typeAudioB: sonType.includes('audio') || false,
+        typeB: values.type,
+        typeImageB: sonType.includes('img') || false,
+        typeModelB: sonType.includes('model') || false,
+        typeVideoB: sonType.includes('video') || false,
+        videoFileB: fileList.video.filePath || '',
+        webSiteB: ''
+      }
+
+      let res: any
+      if (btnRef.current === '1') {
+        res =
+          editInfo.txt === '新增'
+            ? await A7_APIadd(obj1)
+            : await A7_APIedit({ ...obj1, artifactId: editInfo.id })
+      } else {
+        res =
+          editInfo.txt === '新增'
+            ? await A7_APIadd(obj2)
+            : await A7_APIedit({ ...obj2, artifactId: editInfo.id })
+      }
+
+      if (res.code === 0) {
+        MessageFu.success(`${editInfo.txt}成功!`)
+        editInfo.id > 0 ? editTableFu() : addTableFu()
+        closeFu()
+      }
+    },
+    [addTableFu, closeFu, editInfo.id, editInfo.txt, editTableFu]
+  )
+
+  const formOkBtnRef = useRef<any>(null)
+
+  const btnRef = useRef('')
+
+  return (
+    <div className={styles.A7add}>
+      <div className={classNames('A7aMain')}>
+        <Form
+          ref={FormBoxRef}
+          name='basic'
+          labelCol={{ span: 3 }}
+          onFinish={onFinish}
+          onFinishFailed={onFinishFailed}
+          autoComplete='off'
+          scrollToFirstError
+        >
+          <Form.Item
+            label='标题'
+            name='title'
+            rules={[{ required: true, message: '请输入标题!' }]}
+          >
+            <Input placeholder='请输入内容,不超过30个字' maxLength={30} showCount />
+          </Form.Item>
+
+          <Form.Item label='类别' name='type'>
+            <Select
+              options={[
+                { label: '平面纸质类', value: 1 },
+                { label: '棉麻丝绸类', value: 2 },
+                { label: '专业器物类', value: 3 }
+              ]}
+            />
+          </Form.Item>
+
+          <Form.Item label='年代' name='era'>
+            <Input placeholder='请输入内容,最多10字' maxLength={10} showCount />
+          </Form.Item>
+
+          <Form.Item label='质地' name='texture'>
+            <Input placeholder='请输入内容,最多10字' maxLength={10} showCount />
+          </Form.Item>
+
+          <Form.Item label='尺寸' name='size'>
+            <Input placeholder='请输入内容,最多10字' maxLength={10} showCount />
+          </Form.Item>
+
+          <Form.Item label='简介' name='remark'>
+            <TextArea maxLength={200} showCount placeholder='请输入内容,不超过200个字' />
+          </Form.Item>
+
+          {/* 封面 */}
+          <div className='formRow'>
+            <div className='formLeft'>
+              <span>* </span>
+              封面图:
+            </div>
+            <div className='formRight'>
+              <ZupOne
+                ref={ZupThumbRef1}
+                fileCheck={fileCheck}
+                size={5}
+                dirCode={'A7collection'}
+                myUrl='museum/upload/uploadImg'
+                format={['image/jpeg', 'image/png']}
+                formatTxt='png、jpg和jpeg'
+                checkTxt='请上传封面图!'
+                upTxt='最多1张'
+                myType='thumb'
+              />
+            </div>
+          </div>
+
+          <Form.Item label='* 文件类型' name='file'>
+            <ZupTypes
+              ref={ZupTypesRef}
+              selecFlag='模型/图片/音频/视频'
+              fileCheck={fileCheck}
+              dirCode='A7collection'
+              myUrl='museum/upload/upload'
+            />
+          </Form.Item>
+
+          <Form.Item label='* 发表日期' name='publish'>
+            <DatePicker allowClear placeholder='请选择日期' style={{ width: 200 }} />
+          </Form.Item>
+
+          {/* 确定和取消按钮 */}
+          <Form.Item className='A7abtn'>
+            <div className='A7abtnBox'>
+              <Button
+                type='primary'
+                htmlType='submit'
+                onClick={() => {
+                  btnRef.current = '1'
+                  formOkBtnRef.current?.click()
+                }}
+              >
+                发布
+              </Button>
+              <Button
+                type='primary'
+                htmlType='submit'
+                onClick={() => {
+                  btnRef.current = '0'
+                  formOkBtnRef.current?.click()
+                }}
+              >
+                预发布
+              </Button>
+              <MyPopconfirm txtK='取消' onConfirm={closeFu} />
+            </div>
+          </Form.Item>
+        </Form>
+      </div>
+    </div>
+  )
+}
+
+const MemoA7add = React.memo(A7add)
+
+export default MemoA7add

+ 7 - 0
src/pages/A7collection/data.ts

@@ -0,0 +1,7 @@
+import { A7tableType } from '@/types/api/A7collection'
+
+export type A1EditInfoType = {
+  id: number
+  txt: '新增' | '编辑' | '查看' | ''
+  info?: A7tableType
+}

+ 10 - 9
src/pages/A4iosUser/index.module.scss

@@ -1,25 +1,26 @@
-.A4iosUser {
+.A7collection {
   position: relative;
   :global {
-    .A4top {
+    .A7top {
       border-radius: 10px;
       background-color: #fff;
       padding: 15px 24px;
       display: flex;
       justify-content: space-between;
-      & > div {
+      gap: 20px;
+      .A7topLeft {
         display: flex;
-        .A4TopRow {
+        gap: 20px;
+        .rowItem {
+          margin-left: 20px;
+          width: 200px;
           display: flex;
           align-items: center;
-          margin-right: 20px;
-          .ant-select-selection-placeholder {
-            color: black;
-          }
+          gap: 10px;
         }
       }
     }
-    .A4tableBox {
+    .A7tableBox {
       border-radius: 10px;
       overflow: hidden;
       margin-top: 15px;

+ 168 - 0
src/pages/A7collection/index.tsx

@@ -0,0 +1,168 @@
+import React, { useCallback, useEffect, useMemo, useState } from 'react'
+import styles from './index.module.scss'
+import { Button, Input, Select } from 'antd'
+import { useDispatch, useSelector } from 'react-redux'
+import { A1EditInfoType } from './data'
+import { A7_APIdel, A7_APIgetList, A7_APIpublish } from '@/store/action/A7collection'
+import { RootState } from '@/store'
+import { MessageFu } from '@/utils/message'
+import { A7tableType } from '@/types/api/A7collection'
+import MyPopconfirm from '@/components/MyPopconfirm'
+import MyTable from '@/components/MyTable'
+import { A7tableC } from '@/utils/tableData'
+import A7add from './A7add'
+
+const pageDataBase = {
+  pageNum: 1,
+  pageSize: 10
+}
+
+function A7collection() {
+  const dispatch = useDispatch()
+
+  const [pageData, setPageData] = useState(pageDataBase)
+  const [title, setTitle] = useState('')
+  const [type, setType] = useState(0)
+  const getListFu = useCallback(
+    (title?: string) => {
+      // status: -1 全部 0 未发布 1 已发布
+      dispatch(A7_APIgetList({ ...pageData, status: -1, title, type }))
+    },
+    [dispatch, pageData, type]
+  )
+
+  useEffect(() => {
+    getListFu()
+  }, [getListFu])
+
+  // 点击重置
+  const resetSelectFu = useCallback(() => {
+    setPageData({ ...pageDataBase })
+  }, [])
+
+  const tableInfo = useSelector((state: RootState) => state.A7collection.tableInfo)
+
+  const delTableFu = useCallback(
+    async (id: number) => {
+      const res = await A7_APIdel(id)
+      if (res.code === 0) {
+        MessageFu.success('删除成功!')
+        getListFu()
+      }
+    },
+    [getListFu]
+  )
+
+  const publishFu = useCallback(
+    async (id: number) => {
+      const res = await A7_APIpublish(id)
+      if (res.code === 0) {
+        MessageFu.success('发布成功!')
+        getListFu()
+      }
+    },
+    [getListFu]
+  )
+
+  const tableLastBtn = useMemo(() => {
+    return [
+      {
+        title: '操作',
+        render: (item: A7tableType) => (
+          <>
+            {item.status === 0 && (
+              <Button size='small' type='text'>
+                预览
+              </Button>
+            )}
+            <Button
+              size='small'
+              type='text'
+              onClick={() => setEditInfo({ id: item.artifactId, txt: '编辑' })}
+            >
+              编辑
+            </Button>
+            {item.status === 0 && (
+              <Button size='small' type='text' onClick={() => publishFu(item.artifactId)}>
+                发布
+              </Button>
+            )}
+            <MyPopconfirm txtK='删除' onConfirm={() => delTableFu(item.artifactId)} />
+          </>
+        )
+      }
+    ]
+  }, [delTableFu, publishFu])
+
+  //新增、编辑
+  const [editInfo, setEditInfo] = useState<A1EditInfoType>({
+    id: 0,
+    txt: ''
+  })
+
+  return (
+    <div className={styles.A7collection}>
+      <div className='pageTitle'>克博典藏 {editInfo.id ? ` - ${editInfo.txt}` : ''}</div>
+
+      {/* 顶部筛选 */}
+      <div className='A7top'>
+        <div className='A7topLeft'>
+          <Input
+            style={{ width: 200 }}
+            placeholder='请输入标题'
+            onChange={e => setTitle(e.target.value)}
+          />
+          <Button type='primary' onClick={() => getListFu(title)}>
+            搜索
+          </Button>
+          <div className='rowItem'>
+            类别:
+            <Select
+              style={{ width: 120 }}
+              defaultValue={0}
+              options={[
+                { label: '全部', value: 0 },
+                { label: '平面纸质类', value: 1 },
+                { label: '棉麻丝绸类', value: 2 },
+                { label: '专业器物类', value: 3 }
+              ]}
+              onChange={value => setType(value)}
+            />
+          </div>
+        </div>
+        <Button type='primary' onClick={() => setEditInfo({ id: -1, txt: '新增' })}>
+          新增
+        </Button>
+      </div>
+
+      {/* 表格主体 */}
+      <div className='A7tableBox'>
+        <MyTable
+          myKey='artifactId'
+          yHeight={625}
+          list={tableInfo.list}
+          columnsTemp={A7tableC}
+          lastBtn={tableLastBtn}
+          pageNum={pageData.pageNum}
+          pageSize={pageData.pageSize}
+          total={tableInfo.total}
+          onChange={(pageNum, pageSize) => setPageData({ ...pageData, pageNum, pageSize })}
+        />
+      </div>
+
+      {/* 新增 / 编辑 */}
+      {editInfo.id ? (
+        <A7add
+          editInfo={editInfo}
+          closeFu={() => setEditInfo({ id: 0, txt: '新增' })}
+          addTableFu={resetSelectFu}
+          editTableFu={getListFu}
+        />
+      ) : null}
+    </div>
+  )
+}
+
+const MemoA7collection = React.memo(A7collection)
+
+export default MemoA7collection

+ 0 - 182
src/pages/A7notice/A7add/index.tsx

@@ -1,182 +0,0 @@
-import React, { useCallback, useEffect, useRef, useState } from 'react'
-import styles from './index.module.scss'
-import { A1EditInfoType } from '@/pages/A1manage/data'
-import { Button, Form, FormInstance, Input, InputNumber, Select } from 'antd'
-import classNames from 'classnames'
-import { A7_APIgetInfo, A7_APIsave } from '@/store/action/A7notice'
-import { MessageFu } from '@/utils/message'
-import { useSelector } from 'react-redux'
-import { RootState } from '@/store'
-import MyPopconfirm from '@/components/MyPopconfirm'
-import ZRichTexts from '@/components/ZRichTexts'
-
-type Props = {
-  editInfo: A1EditInfoType
-  closeFu: () => void
-  addTableFu: () => void
-  editTableFu: () => void
-}
-
-function A7add({ editInfo, closeFu, addTableFu, editTableFu }: Props) {
-  const { typeList } = useSelector((state: RootState) => state.A7notice)
-
-  // 表单的ref
-  const FormBoxRef = useRef<FormInstance>(null)
-
-  // 富文本的ref
-  const ZRichTextRef = useRef<any>(null)
-
-  // 编辑/查看 进入页面 获取信息
-  const getInfoFu = useCallback(async (id: number) => {
-    const res = await A7_APIgetInfo(id)
-    if (res.code === 0) {
-      const data = res.data
-
-      // 设置富文本
-      ZRichTextRef.current?.ritxtShowFu(JSON.parse(data.description || '{}'))
-
-      FormBoxRef.current?.setFieldsValue(data)
-    }
-  }, [])
-
-  useEffect(() => {
-    if (editInfo.id > 0) {
-      getInfoFu(editInfo.id)
-    } else {
-      FormBoxRef.current?.setFieldsValue({
-        sort: 999
-      })
-    }
-  }, [editInfo.id, getInfoFu])
-
-  // 附件 是否 已经点击过确定
-  const [fileCheck, setFileCheck] = useState(false)
-
-  // 没有通过校验
-  const onFinishFailed = useCallback(() => {
-    setFileCheck(true)
-  }, [])
-
-  //  通过校验点击确定
-  const onFinish = useCallback(
-    async (values: any) => {
-      setFileCheck(true)
-
-      // 富文本校验不通过
-      const rtf = ZRichTextRef.current?.fatherBtnOkFu() || { flag: true }
-
-      if (rtf.flag) return MessageFu.warning('请输入完整正文!')
-
-      const obj = {
-        ...values,
-        id: editInfo.id > 0 ? editInfo.id : null,
-        description: JSON.stringify(rtf.val || '')
-      }
-
-      // if (obj) {
-      //   console.log(123, obj);
-      //   return;
-      // }
-
-      const res = await A7_APIsave(obj)
-
-      if (res.code === 0) {
-        MessageFu.success(`${editInfo.txt}成功!`)
-        editInfo.id > 0 ? editTableFu() : addTableFu()
-        closeFu()
-      }
-    },
-    [addTableFu, closeFu, editInfo.id, editInfo.txt, editTableFu]
-  )
-
-  return (
-    <div className={styles.A7add}>
-      <div className={classNames('A7aMain', editInfo.txt === '查看' ? 'A7aMainLook' : '')}>
-        <Form
-          ref={FormBoxRef}
-          name='basic'
-          labelCol={{ span: 3 }}
-          onFinish={onFinish}
-          onFinishFailed={onFinishFailed}
-          autoComplete='off'
-          scrollToFirstError
-        >
-          <Form.Item label='标题' name='name' rules={[{ required: true, message: '请输入标题!' }]}>
-            <Input
-              readOnly={editInfo.txt === '查看'}
-              placeholder='请输入内容'
-              maxLength={20}
-              showCount
-            />
-          </Form.Item>
-
-          <Form.Item
-            label='公告类型'
-            name='dictId'
-            rules={[{ required: true, message: '请选择公告类型!' }]}
-          >
-            <Select
-              placeholder='请选择'
-              fieldNames={{ label: 'name', value: 'id' }}
-              style={{ width: 200 }}
-              options={typeList}
-            />
-          </Form.Item>
-
-          {/* 封面 */}
-          <div className='formRow'>
-            <div className='formLeft'>
-              <span>* </span>
-              正文:
-            </div>
-            <div className='formRight'>
-              <ZRichTexts
-                check={fileCheck}
-                dirCode={'A7notice'}
-                isLook={editInfo.txt === '查看'}
-                ref={ZRichTextRef}
-                myUrl='cms/notice/upload'
-                isOne={true}
-                upAudioBtnNone={true}
-              />
-            </div>
-          </div>
-          {/* {editInfo.txt === '查看' ? <br /> : null} */}
-
-          <div className='A1fromRow'>
-            <Form.Item
-              label='排序值'
-              name='sort'
-              rules={[{ required: true, message: '请输入排序值!' }]}
-            >
-              <InputNumber min={1} max={999} precision={0} placeholder='请输入' />
-            </Form.Item>
-            <div className='A1_6Frow' hidden={editInfo.txt === '查看'}>
-              请输入1~999的数字。数字越小,排序越靠前。数字相同时,更新发布的内容排在前面
-            </div>
-          </div>
-
-          {/* 确定和取消按钮 */}
-          <Form.Item className='A7abtn'>
-            {editInfo.txt === '查看' ? (
-              <Button onClick={closeFu}>返回</Button>
-            ) : (
-              <>
-                <Button type='primary' htmlType='submit'>
-                  提交
-                </Button>
-                <br />
-                <br />
-                <MyPopconfirm txtK='取消' onConfirm={closeFu} />
-              </>
-            )}
-          </Form.Item>
-        </Form>
-      </div>
-    </div>
-  )
-}
-
-const MemoA7add = React.memo(A7add)
-
-export default MemoA7add

+ 0 - 63
src/pages/A7notice/A7type/index.module.scss

@@ -1,63 +0,0 @@
-.A7type {
-  width: 100%;
-  height: 100%;
-  padding: 24px;
-  background-color: #fff;
-  border-radius: 10px;
-
-  :global {
-    .A7tTitle {
-      display: flex;
-      justify-content: space-between;
-    }
-    .A7tTable {
-      border-radius: 10px;
-      overflow: hidden;
-      margin-top: 15px;
-      height: calc(100% - 77px);
-    }
-  }
-}
-
-// 新增 、编辑弹窗
-.A7tAdd {
-  :global {
-    .ant-modal-close {
-      display: none;
-    }
-    .ant-modal {
-      width: 800px !important;
-      top: 30%;
-    }
-    .ant-modal-body {
-      border-top: 1px solid #ccc;
-      padding-top: 15px !important;
-    }
-
-    .A7tMain {
-      width: 100%;
-      height: 100%;
-      overflow-y: auto;
-      position: relative;
-
-      .A7tFromRow {
-        position: relative;
-
-        .A7tFrowTit {
-          position: absolute;
-          left: 180px;
-          top: 5px;
-          color: #999;
-          font-size: 12px;
-        }
-      }
-
-      .ant-form {
-        .A7tBtn {
-          text-align: center;
-          margin-top: 30px;
-        }
-      }
-    }
-  }
-}

+ 0 - 171
src/pages/A7notice/A7type/index.tsx

@@ -1,171 +0,0 @@
-import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
-import styles from './index.module.scss'
-import { Button, Form, FormInstance, Input, InputNumber, Modal } from 'antd'
-import { useDispatch, useSelector } from 'react-redux'
-import { RootState } from '@/store'
-import { A7_APIdel2, A7_APIgetList2, A7_APIsave2 } from '@/store/action/A7notice'
-import MyTable from '@/components/MyTable'
-import { MessageFu } from '@/utils/message'
-import { A7tableType, A7typeType } from '@/types'
-import MyPopconfirm from '@/components/MyPopconfirm'
-import { A7tableCtype } from '@/utils/tableData'
-
-type Props = {
-  closeFu: () => void
-}
-
-function A7type({ closeFu }: Props) {
-  const dispatch = useDispatch()
-
-  useEffect(() => {
-    dispatch(A7_APIgetList2())
-  }, [dispatch])
-
-  const { typeList } = useSelector((state: RootState) => state.A7notice)
-
-  const delTableFu = useCallback(
-    async (id: number) => {
-      const res = await A7_APIdel2(id)
-      if (res.code === 0) {
-        MessageFu.success('删除成功!')
-        dispatch(A7_APIgetList2())
-      }
-    },
-    [dispatch]
-  )
-
-  const tableLastBtn = useMemo(() => {
-    return [
-      {
-        title: '操作',
-        render: (item: A7typeType) =>
-          item.id === 5 ? (
-            ' - '
-          ) : (
-            <>
-              <Button size='small' type='text' onClick={() => setEditInfo(item)}>
-                编辑
-              </Button>
-              <MyPopconfirm txtK='删除' onConfirm={() => delTableFu(item.id)} />
-            </>
-          )
-      }
-    ]
-  }, [delTableFu])
-
-  // 新增和编辑
-  const [editInfo, setEditInfo] = useState({} as A7typeType)
-
-  useEffect(() => {
-    FormBoxRef.current?.setFieldsValue(editInfo)
-  }, [editInfo])
-
-  // 表单的ref
-  const FormBoxRef = useRef<FormInstance>(null)
-
-  // 没有通过校验
-  const onFinishFailed = useCallback(() => {}, [])
-
-  //  通过校验点击确定
-  const onFinish = useCallback(
-    async (values: any) => {
-      const res = await A7_APIsave2({
-        id: editInfo.id > 0 ? editInfo.id : null,
-        name: values.name,
-        sort: values.sort,
-        type: 'notice',
-        display: 1
-      })
-      if (res.code === 0) {
-        MessageFu.success(editInfo.id > 0 ? '编辑成功!' : '新增成功!')
-        setEditInfo({} as A7typeType)
-        dispatch(A7_APIgetList2())
-      }
-    },
-    [dispatch, editInfo.id]
-  )
-
-  return (
-    <div className={styles.A7type}>
-      <div className='A7tTitle'>
-        <h1>公告类型</h1>
-        <div>
-          <Button type='primary' onClick={() => setEditInfo({ id: -1, name: '', sort: 999 })}>
-            新增
-          </Button>
-          &emsp;
-          <Button onClick={closeFu}>关闭</Button>
-        </div>
-      </div>
-
-      <div className='A7tTable'>
-        <MyTable
-          classKey='A7tTable'
-          yHeight={580}
-          list={typeList}
-          columnsTemp={A7tableCtype}
-          lastBtn={tableLastBtn}
-          pagingInfo={false}
-        />
-      </div>
-
-      {/* 新增/编辑 */}
-      {editInfo.id ? (
-        <Modal
-          wrapClassName={styles.A7tAdd}
-          open={true}
-          title={editInfo.id > 0 ? '编辑' : '新增'}
-          footer={
-            [] // 设置footer为空,去掉 取消 确定默认按钮
-          }
-        >
-          <div className='A7tMain'>
-            <Form
-              ref={FormBoxRef}
-              name='basic'
-              labelCol={{ span: 2 }}
-              onFinish={onFinish}
-              onFinishFailed={onFinishFailed}
-              autoComplete='off'
-              scrollToFirstError
-            >
-              <Form.Item
-                label='标题'
-                name='name'
-                rules={[{ required: true, message: '请输入标题!' }]}
-              >
-                <Input placeholder='请输入内容' maxLength={20} showCount />
-              </Form.Item>
-
-              <div className='A7tFromRow'>
-                <Form.Item
-                  label='排序值'
-                  name='sort'
-                  rules={[{ required: true, message: '请输入排序值!' }]}
-                >
-                  <InputNumber min={1} max={999} precision={0} placeholder='请输入' />
-                </Form.Item>
-                <div className='A7tFrowTit'>
-                  请输入1~999的数字。数字越小,排序越靠前。数字相同时,更新发布的内容排在前面
-                </div>
-              </div>
-
-              {/* 确定和取消按钮 */}
-              <Form.Item className='A7tBtn'>
-                <Button type='primary' htmlType='submit'>
-                  提交
-                </Button>
-                &emsp;
-                <MyPopconfirm txtK='取消' onConfirm={() => setEditInfo({} as A7tableType)} />
-              </Form.Item>
-            </Form>
-          </div>
-        </Modal>
-      ) : null}
-    </div>
-  )
-}
-
-const MemoA7type = React.memo(A7type)
-
-export default MemoA7type

+ 0 - 6
src/pages/A7notice/data.ts

@@ -1,6 +0,0 @@
-export type A7FromDataType = {
-  searchKey: string
-  dictId: number | null
-  pageNum: number
-  pageSize: number
-}

+ 0 - 45
src/pages/A7notice/index.module.scss

@@ -1,45 +0,0 @@
-.A7notice {
-  position: relative;
-  :global {
-    .A7top {
-      border-radius: 10px;
-      background-color: #fff;
-      padding: 15px 24px;
-      display: flex;
-      justify-content: space-between;
-      & > div {
-        display: flex;
-        .A7TopRow {
-          display: flex;
-          align-items: center;
-          margin-right: 20px;
-          .ant-select-selection-placeholder {
-            color: black;
-          }
-        }
-      }
-    }
-    .A7tableBox {
-      border-radius: 10px;
-      overflow: hidden;
-      margin-top: 15px;
-      height: calc(100% - 77px);
-      background-color: #fff;
-    }
-
-    .A7type {
-      position: absolute;
-      top: 0;
-      left: 0;
-      width: 100%;
-      height: 100%;
-      border-radius: 10px;
-      padding: 50px 100px;
-      background-color: rgba(0, 0, 0, 0.6);
-      & > div {
-        width: 100%;
-        height: 100%;
-      }
-    }
-  }
-}

+ 0 - 192
src/pages/A7notice/index.tsx

@@ -1,192 +0,0 @@
-import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
-import styles from './index.module.scss'
-import { A7FromDataType } from './data'
-import { useDispatch, useSelector } from 'react-redux'
-import { A7_APIdel, A7_APIgetList, A7_APIgetList2 } from '@/store/action/A7notice'
-import { RootState } from '@/store'
-import { MessageFu } from '@/utils/message'
-import { A7tableType } from '@/types'
-import { Button, Input, Select } from 'antd'
-import MyPopconfirm from '@/components/MyPopconfirm'
-import { A1EditInfoType } from '../A1manage/data'
-import MyTable from '@/components/MyTable'
-import { A7tableC } from '@/utils/tableData'
-import A7type from './A7type'
-import A7add from './A7add'
-
-const fromDataBase: A7FromDataType = {
-  dictId: null,
-  searchKey: '',
-  pageNum: 1,
-  pageSize: 10
-}
-
-function A7notice() {
-  const dispatch = useDispatch()
-
-  useEffect(() => {
-    dispatch(A7_APIgetList2())
-  }, [dispatch])
-
-  const [fromData, setFromData] = useState(fromDataBase)
-
-  const getListFu = useCallback(() => {
-    dispatch(A7_APIgetList(fromData))
-  }, [dispatch, fromData])
-
-  useEffect(() => {
-    getListFu()
-  }, [getListFu])
-
-  const [inputKey, setInputKey] = useState(1)
-
-  // 输入框的输入
-  const timeRef = useRef(-1)
-  const txtChangeFu = useCallback(
-    (e: React.ChangeEvent<HTMLInputElement>, key: 'searchKey') => {
-      clearTimeout(timeRef.current)
-      timeRef.current = window.setTimeout(() => {
-        setFromData({ ...fromData, [key]: e.target.value.replaceAll("'", ''), pageNum: 1 })
-      }, 500)
-    },
-    [fromData]
-  )
-
-  // 点击重置
-  const resetSelectFu = useCallback(() => {
-    setInputKey(Date.now())
-    setFromData({ ...fromDataBase })
-  }, [])
-
-  const { tableInfo, typeList } = useSelector((state: RootState) => state.A7notice)
-
-  const delTableFu = useCallback(
-    async (id: number) => {
-      const res = await A7_APIdel(id)
-      if (res.code === 0) {
-        MessageFu.success('删除成功!')
-        getListFu()
-      }
-    },
-    [getListFu]
-  )
-
-  const tableLastBtn = useMemo(() => {
-    return [
-      {
-        title: '操作',
-        render: (item: A7tableType) => (
-          <>
-            <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: ''
-  })
-
-  // 公告类型显示隐藏
-  const [typeShow, setTypeShow] = useState(false)
-
-  return (
-    <div className={styles.A7notice}>
-      <div className='pageTitle'>公告管理 {editInfo.id ? ` - ${editInfo.txt}` : ''}</div>
-
-      {/* 顶部筛选 */}
-      <div className='A7top'>
-        <div>
-          <div className='A7TopRow'>
-            <span>搜索:</span>
-            <Input
-              key={inputKey}
-              maxLength={20}
-              style={{ width: 200 }}
-              placeholder='请输入公告标题'
-              allowClear
-              onChange={e => txtChangeFu(e, 'searchKey')}
-            />
-          </div>
-
-          <div className='A7TopRow'>
-            <span>展示分类:</span>
-            <Select
-              allowClear
-              placeholder='全部'
-              style={{ width: 200 }}
-              value={fromData.dictId}
-              fieldNames={{ label: 'name', value: 'id' }}
-              onChange={e => setFromData({ ...fromData, pageNum: 1, dictId: e })}
-              options={typeList}
-            />
-          </div>
-        </div>
-        <div>
-          <Button onClick={resetSelectFu}>重置</Button>&emsp;
-          <Button type='primary' onClick={() => setTypeShow(true)}>
-            公告类型
-          </Button>
-          &emsp;
-          <Button type='primary' onClick={() => setEditInfo({ id: -1, txt: '新增' })}>
-            新增
-          </Button>
-        </div>
-      </div>
-
-      {/* 表格主体 */}
-      <div className='A7tableBox'>
-        <MyTable
-          yHeight={625}
-          list={tableInfo.list}
-          columnsTemp={A7tableC}
-          lastBtn={tableLastBtn}
-          pageNum={fromData.pageNum}
-          pageSize={fromData.pageSize}
-          total={tableInfo.total}
-          onChange={(pageNum, pageSize) => setFromData({ ...fromData, pageNum, pageSize })}
-        />
-      </div>
-
-      {/* 公告类型 */}
-      {typeShow ? (
-        <div className='A7type'>
-          <div>
-            <A7type closeFu={() => setTypeShow(false)} />
-          </div>
-        </div>
-      ) : null}
-
-      {/* 新增/编辑 */}
-      {editInfo.id ? (
-        <A7add
-          editInfo={editInfo}
-          closeFu={() => setEditInfo({ id: 0, txt: '新增' })}
-          addTableFu={resetSelectFu}
-          editTableFu={getListFu}
-        />
-      ) : null}
-    </div>
-  )
-}
-
-const MemoA7notice = React.memo(A7notice)
-
-export default MemoA7notice

+ 109 - 0
src/pages/B1reserve1/B1look/index.module.scss

@@ -0,0 +1,109 @@
+.B1add {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  z-index: 12;
+  background-color: #fff;
+  border-radius: 10px;
+  padding: 24px;
+
+  :global {
+    .B1aMain {
+      width: 100%;
+      height: calc(100% - 80px);
+      overflow-y: auto;
+
+      textarea {
+        min-height: 75px !important;
+      }
+
+      .B1fromRow {
+        position: relative;
+        width: 800px;
+
+        .B1_6Frow {
+          position: absolute;
+          left: 200px;
+          top: 5px;
+          color: #999;
+          font-size: 12px;
+        }
+      }
+
+      .ant-form {
+        width: 800px;
+        display: flex;
+        flex-direction: column;
+
+        // .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);
+          }
+        }
+
+        .B1abtn {
+          display: flex;
+          align-items: center;
+          width: 100%;
+          height: 80px;
+          position: fixed;
+          bottom: 0;
+          background: #fff;
+          z-index: 10;
+
+          .B1abtnBox {
+            display: flex;
+            gap: 20px;
+            padding-left: 100px;
+          }
+        }
+      }
+    }
+
+    // 从查看进入
+    .B1aMainLook {
+      // 左边的 label 也不让选中
+      label {
+        pointer-events: none;
+      }
+
+      .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;
+      }
+    }
+  }
+}

+ 95 - 0
src/pages/B1reserve1/B1look/index.tsx

@@ -0,0 +1,95 @@
+import React, { useCallback, useEffect, useRef } from 'react'
+import styles from './index.module.scss'
+import classNames from 'classnames'
+import { B1EditInfoType } from '../data'
+import { Button, Form, FormInstance, Divider } from 'antd'
+import { B_APIgetInfo } from '@/store/action/Breserve'
+import { B1tableType } from '@/types'
+import dayjs from 'dayjs'
+
+type Props = {
+  editInfo: B1EditInfoType
+  closeFu: () => void
+  addTableFu: () => void
+  editTableFu: () => void
+}
+
+function B1add({ editInfo, closeFu, addTableFu, editTableFu }: Props) {
+  // 表单的ref
+  const FormBoxRef = useRef<FormInstance>(null)
+
+  // 回显数据的方法调用
+  const dataShow = useCallback((info: B1tableType) => {
+    FormBoxRef.current?.setFieldsValue(info)
+  }, [])
+
+  // 查询数据
+  const getInfoFu = useCallback(
+    async (id: number) => {
+      if (editInfo.info) dataShow(editInfo.info)
+      else {
+        const res = await B_APIgetInfo(id)
+        if (res.code === 0) {
+          dataShow(res.data)
+        }
+      }
+    },
+    [dataShow, editInfo.info]
+  )
+
+  // 查询填入数据
+  useEffect(() => {
+    if (editInfo.id > 0) {
+      getInfoFu(editInfo.id)
+    }
+  }, [editInfo.id, getInfoFu])
+
+  return (
+    <div className={styles.B1add}>
+      <div className={classNames('B1aMain')}>
+        <Form
+          ref={FormBoxRef}
+          name='basic'
+          labelCol={{ span: 3 }}
+          autoComplete='off'
+          scrollToFirstError
+        >
+          <Form.Item
+            label='申请时间'
+            name='createTime'
+            rules={[{ required: true, message: '请输入标题!' }]}
+          >
+            {dayjs().format('YYYY-MM-DD HH:mm:ss')}
+          </Form.Item>
+
+          <Form.Item label='预约日期' name='reserveDate'>
+            {dayjs().format('YYYY-MM-DD')}
+          </Form.Item>
+
+          <Form.Item label='预约时段' name='reserveTime'>
+            10:00-12:00
+          </Form.Item>
+
+          <Form.Item label='预约人数' name='reserveNum'>
+            100
+          </Form.Item>
+
+          <Divider />
+
+          {/* 确定和取消按钮 */}
+          <Form.Item className='B1abtn'>
+            <div className='B1abtnBox'>
+              <Button type='primary' onClick={closeFu}>
+                返回
+              </Button>
+            </div>
+          </Form.Item>
+        </Form>
+      </div>
+    </div>
+  )
+}
+
+const MemoB1add = React.memo(B1add)
+
+export default MemoB1add

+ 7 - 0
src/pages/B1reserve1/data.ts

@@ -0,0 +1,7 @@
+import { B1tableType } from '@/types'
+
+export type B1EditInfoType = {
+  id: number
+  txt: '查看' | '导出' | ''
+  info?: B1tableType
+}

+ 20 - 0
src/pages/B1reserve1/index.module.scss

@@ -0,0 +1,20 @@
+.B1reserve1 {
+  position: relative;
+  :global {
+    .B1top {
+      border-radius: 10px;
+      background-color: #fff;
+      padding: 15px 24px;
+      display: flex;
+      justify-content: right;
+      gap: 20px;
+    }
+    .B1tableBox {
+      border-radius: 10px;
+      overflow: hidden;
+      margin-top: 15px;
+      height: calc(100% - 77px);
+      background-color: #fff;
+    }
+  }
+}

+ 107 - 0
src/pages/B1reserve1/index.tsx

@@ -0,0 +1,107 @@
+import React, { useCallback, useEffect, useMemo, useState } from 'react'
+import styles from './index.module.scss'
+import { Button } from 'antd'
+import { useDispatch, useSelector } from 'react-redux'
+import { B1EditInfoType } from './data'
+import { B_APIgetList, B_APIdel } from '@/store/action/Breserve'
+import { RootState } from '@/store'
+import { B1tableType } from '@/types'
+import MyPopconfirm from '@/components/MyPopconfirm'
+import MyTable from '@/components/MyTable'
+import { B1tableC } from '@/utils/tableData'
+import B1look from './B1look'
+
+const pageDataBase = {
+  pageNum: 1,
+  pageSize: 10
+}
+
+function B1reserve1() {
+  const dispatch = useDispatch()
+
+  const [pageData, setPageData] = useState(pageDataBase)
+
+  const getListFu = useCallback(() => {
+    // status: -1 全部 0 未发布 1 已发布
+    dispatch(B_APIgetList({ ...pageData, type: 1 }))
+  }, [dispatch, pageData])
+
+  useEffect(() => {
+    getListFu()
+  }, [getListFu])
+
+  // 点击重置
+  const resetSelectFu = useCallback(() => {
+    setPageData({ ...pageDataBase })
+  }, [])
+
+  const tableInfo = useSelector((state: RootState) => state.Breserve.tableInfo)
+
+  const tableLastBtn = useMemo(() => {
+    return [
+      {
+        title: '操作',
+        render: (item: B1tableType) => (
+          <>
+            <Button
+              size='small'
+              type='text'
+              onClick={() => setEditInfo({ id: item.id, txt: '查看' })}
+            >
+              查看
+            </Button>
+            <MyPopconfirm txtK='删除' onConfirm={() => B_APIdel(item.id)} />
+          </>
+        )
+      }
+    ]
+  }, [])
+
+  //查看
+  const [editInfo, setEditInfo] = useState<B1EditInfoType>({
+    id: 0,
+    txt: ''
+  })
+
+  return (
+    <div className={styles.B1reserve1}>
+      <div className='pageTitle'>展馆预约记录</div>
+
+      {/* 顶部筛选 */}
+      <div className='B1top'>
+        <Button type='primary' onClick={() => setEditInfo({ id: -1, txt: '导出' })}>
+          导出
+        </Button>
+      </div>
+
+      {/* 表格主体 */}
+      <div className='B1tableBox'>
+        <MyTable
+          myKey='id'
+          yHeight={625}
+          list={tableInfo.list}
+          columnsTemp={B1tableC}
+          lastBtn={tableLastBtn}
+          pageNum={pageData.pageNum}
+          pageSize={pageData.pageSize}
+          total={tableInfo.total}
+          onChange={(pageNum, pageSize) => setPageData({ ...pageData, pageNum, pageSize })}
+        />
+      </div>
+
+      {/* 导出 */}
+      {editInfo.id ? (
+        <B1look
+          editInfo={editInfo}
+          closeFu={() => setEditInfo({ id: 0, txt: '导出' })}
+          addTableFu={resetSelectFu}
+          editTableFu={getListFu}
+        />
+      ) : null}
+    </div>
+  )
+}
+
+const MemoB1reserve1 = React.memo(B1reserve1)
+
+export default MemoB1reserve1

+ 109 - 0
src/pages/B2reserve2/B2look/index.module.scss

@@ -0,0 +1,109 @@
+.B2look {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  z-index: 12;
+  background-color: #fff;
+  border-radius: 10px;
+  padding: 24px;
+
+  :global {
+    .B2Main {
+      width: 100%;
+      height: calc(100% - 80px);
+      overflow-y: auto;
+
+      textarea {
+        min-height: 75px !important;
+      }
+
+      .B2fromRow {
+        position: relative;
+        width: 800px;
+
+        .B2_6Frow {
+          position: absolute;
+          left: 200px;
+          top: 5px;
+          color: #999;
+          font-size: 12px;
+        }
+      }
+
+      .ant-form {
+        width: 800px;
+        display: flex;
+        flex-direction: column;
+
+        // .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);
+          }
+        }
+
+        .B2btn {
+          display: flex;
+          align-items: center;
+          width: 100%;
+          height: 80px;
+          position: fixed;
+          bottom: 0;
+          background: #fff;
+          z-index: 10;
+
+          .B2btnBox {
+            display: flex;
+            gap: 20px;
+            padding-left: 100px;
+          }
+        }
+      }
+    }
+
+    // 从查看进入
+    .B2MainLook {
+      // 左边的 label 也不让选中
+      label {
+        pointer-events: none;
+      }
+
+      .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;
+      }
+    }
+  }
+}

+ 95 - 0
src/pages/B2reserve2/B2look/index.tsx

@@ -0,0 +1,95 @@
+import React, { useCallback, useEffect, useRef } from 'react'
+import styles from './index.module.scss'
+import classNames from 'classnames'
+import { B2EditInfoType } from '../data'
+import { Button, Form, FormInstance, Divider } from 'antd'
+import { B_APIgetInfo } from '@/store/action/Breserve'
+import { B2tableType } from '@/types'
+import dayjs from 'dayjs'
+
+type Props = {
+  editInfo: B2EditInfoType
+  closeFu: () => void
+  addTableFu: () => void
+  editTableFu: () => void
+}
+
+function B2look({ editInfo, closeFu, addTableFu, editTableFu }: Props) {
+  // 表单的ref
+  const FormBoxRef = useRef<FormInstance>(null)
+
+  // 回显数据的方法调用
+  const dataShow = useCallback((info: B2tableType) => {
+    FormBoxRef.current?.setFieldsValue(info)
+  }, [])
+
+  // 查询数据
+  const getInfoFu = useCallback(
+    async (id: number) => {
+      if (editInfo.info) dataShow(editInfo.info)
+      else {
+        const res = await B_APIgetInfo(id)
+        if (res.code === 0) {
+          dataShow(res.data)
+        }
+      }
+    },
+    [dataShow, editInfo.info]
+  )
+
+  // 查询填入数据
+  useEffect(() => {
+    if (editInfo.id > 0) {
+      getInfoFu(editInfo.id)
+    }
+  }, [editInfo.id, getInfoFu])
+
+  return (
+    <div className={styles.B2look}>
+      <div className={classNames('B2Main')}>
+        <Form
+          ref={FormBoxRef}
+          name='basic'
+          labelCol={{ span: 3 }}
+          autoComplete='off'
+          scrollToFirstError
+        >
+          <Form.Item
+            label='申请时间'
+            name='createTime'
+            rules={[{ required: true, message: '请输入标题!' }]}
+          >
+            {dayjs().format('YYYY-MM-DD HH:mm:ss')}
+          </Form.Item>
+
+          <Form.Item label='预约日期' name='reserveDate'>
+            {dayjs().format('YYYY-MM-DD')}
+          </Form.Item>
+
+          <Form.Item label='预约时段' name='reserveTime'>
+            10:00-12:00
+          </Form.Item>
+
+          <Form.Item label='预约人数' name='reserveNum'>
+            100
+          </Form.Item>
+
+          <Divider />
+
+          {/* 确定和取消按钮 */}
+          <Form.Item className='B2btn'>
+            <div className='B2btnBox'>
+              <Button type='primary' onClick={closeFu}>
+                返回
+              </Button>
+            </div>
+          </Form.Item>
+        </Form>
+      </div>
+    </div>
+  )
+}
+
+const MemoB2look = React.memo(B2look)
+
+export default MemoB2look

+ 7 - 0
src/pages/B2reserve2/data.ts

@@ -0,0 +1,7 @@
+import { B2tableType } from '@/types'
+
+export type B2EditInfoType = {
+  id: number
+  txt: '查看' | '导出' | ''
+  info?: B2tableType
+}

+ 20 - 0
src/pages/B2reserve2/index.module.scss

@@ -0,0 +1,20 @@
+.B2reserve2 {
+  position: relative;
+  :global {
+    .B2top {
+      border-radius: 10px;
+      background-color: #fff;
+      padding: 15px 24px;
+      display: flex;
+      justify-content: right;
+      gap: 20px;
+    }
+    .B2tableBox {
+      border-radius: 10px;
+      overflow: hidden;
+      margin-top: 15px;
+      height: calc(100% - 77px);
+      background-color: #fff;
+    }
+  }
+}

+ 107 - 0
src/pages/B2reserve2/index.tsx

@@ -0,0 +1,107 @@
+import React, { useCallback, useEffect, useMemo, useState } from 'react'
+import styles from './index.module.scss'
+import { Button } from 'antd'
+import { useDispatch, useSelector } from 'react-redux'
+import { B2EditInfoType } from './data'
+import { B_APIgetList, B_APIdel } from '@/store/action/Breserve'
+import { RootState } from '@/store'
+import { B2tableType } from '@/types'
+import MyPopconfirm from '@/components/MyPopconfirm'
+import MyTable from '@/components/MyTable'
+import { B2tableC } from '@/utils/tableData'
+import B2look from './B2look'
+
+const pageDataBase = {
+  pageNum: 1,
+  pageSize: 10
+}
+
+function B2reserve2() {
+  const dispatch = useDispatch()
+
+  const [pageData, setPageData] = useState(pageDataBase)
+
+  const getListFu = useCallback(() => {
+    // status: -1 全部 0 未发布 1 已发布
+    dispatch(B_APIgetList({ ...pageData, type: 2 }))
+  }, [dispatch, pageData])
+
+  useEffect(() => {
+    getListFu()
+  }, [getListFu])
+
+  // 点击重置
+  const resetSelectFu = useCallback(() => {
+    setPageData({ ...pageDataBase })
+  }, [])
+
+  const tableInfo = useSelector((state: RootState) => state.Breserve.tableInfo)
+
+  const tableLastBtn = useMemo(() => {
+    return [
+      {
+        title: '操作',
+        render: (item: B2tableType) => (
+          <>
+            <Button
+              size='small'
+              type='text'
+              onClick={() => setEditInfo({ id: item.id, txt: '查看' })}
+            >
+              查看
+            </Button>
+            <MyPopconfirm txtK='删除' onConfirm={() => B_APIdel(item.id)} />
+          </>
+        )
+      }
+    ]
+  }, [])
+
+  //查看
+  const [editInfo, setEditInfo] = useState<B2EditInfoType>({
+    id: 0,
+    txt: ''
+  })
+
+  return (
+    <div className={styles.B2reserve2}>
+      <div className='pageTitle'>展馆预约记录</div>
+
+      {/* 顶部筛选 */}
+      <div className='B2top'>
+        <Button type='primary' onClick={() => setEditInfo({ id: -1, txt: '导出' })}>
+          导出
+        </Button>
+      </div>
+
+      {/* 表格主体 */}
+      <div className='B2tableBox'>
+        <MyTable
+          myKey='id'
+          yHeight={625}
+          list={tableInfo.list}
+          columnsTemp={B2tableC}
+          lastBtn={tableLastBtn}
+          pageNum={pageData.pageNum}
+          pageSize={pageData.pageSize}
+          total={tableInfo.total}
+          onChange={(pageNum, pageSize) => setPageData({ ...pageData, pageNum, pageSize })}
+        />
+      </div>
+
+      {/* 导出 */}
+      {editInfo.id ? (
+        <B2look
+          editInfo={editInfo}
+          closeFu={() => setEditInfo({ id: 0, txt: '导出' })}
+          addTableFu={resetSelectFu}
+          editTableFu={getListFu}
+        />
+      ) : null}
+    </div>
+  )
+}
+
+const MemoB2reserve2 = React.memo(B2reserve2)
+
+export default MemoB2reserve2

+ 86 - 0
src/pages/C1reserveOpt/C1NoTime.tsx

@@ -0,0 +1,86 @@
+import React, { useCallback, useState } from 'react'
+import styles from './index.module.scss'
+import { Button, DatePicker, Modal } from 'antd'
+import MyPopconfirm from '@/components/MyPopconfirm'
+import dayjs from 'dayjs'
+import { MessageFu } from '@/utils/message'
+
+type Props = {
+  closeFu: () => void
+  editFu: (val: string[]) => void
+  baseTime: string
+  num: 20 | 50
+}
+
+function C1NoTime({ baseTime, closeFu, editFu, num }: Props) {
+  console.log(baseTime)
+  const baseTimeArr = baseTime
+    ? baseTime
+        .split(',')
+        .map(v => v.replaceAll('年', '-').replaceAll('月', '-').replaceAll('日', ''))
+    : []
+  const [value, setValue] = useState<string[]>(baseTimeArr)
+
+  const onChange = useCallback(
+    (date: any, dateString: string[] | string) => {
+      if (dateString.length) {
+        console.log(dateString)
+        let arr = dateString as string[]
+        if (arr.length > num) {
+          arr = arr.filter((c, i) => i < num)
+          MessageFu.warning(`最多${num}个日期,已过滤超出日期`)
+        }
+        console.log(arr)
+        setValue(arr.map(v => v.replaceAll('年', '-').replaceAll('月', '-').replaceAll('日', '')))
+      } else setValue([])
+    },
+    [num]
+  )
+
+  // const disabledDate = useCallback((time: any) => {
+  //   return dayjs().year() !== time.year()
+  // }, [])
+
+  // const [checkTime, setCheckTime] = useState(dayjs())
+
+  return (
+    <Modal
+      wrapClassName={styles.C1Notime}
+      open={true}
+      title='不可预约日期'
+      footer={
+        [] // 设置footer为空,去掉 取消 确定默认按钮
+      }
+    >
+      <div className='C1NoTit'>请选择日期,最多{num}个</div>
+      <DatePicker
+        multiple
+        onChange={onChange}
+        maxTagCount='responsive'
+        value={value ? value.map(v => dayjs(v)) : []}
+        size='large'
+        allowClear={false}
+        format='YYYY年MM月DD日'
+        // disabledDate={disabledDate}
+        // needConfirm={true}
+        // pickerValue={checkTime}
+        // onPanelChange={a => {
+        //   // 只能选择今年的月份
+        //   if (dayjs(a).year() === dayjs().year()) setCheckTime(a)
+        // }}
+      />
+
+      <div className='C1Nbtn'>
+        <MyPopconfirm txtK='取消' onConfirm={closeFu} />
+        &emsp;
+        <Button type='primary' onClick={() => editFu(value)}>
+          提交
+        </Button>
+      </div>
+    </Modal>
+  )
+}
+
+const MemoC1NoTime = React.memo(C1NoTime)
+
+export default MemoC1NoTime

+ 96 - 0
src/pages/C1reserveOpt/C1edit/index.module.scss

@@ -0,0 +1,96 @@
+.C1edit {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  background-color: #fff;
+  border-radius: 10px;
+  padding: 24px;
+  display: flex;
+
+  :global {
+    .C1ell {
+      width: 100px;
+      margin-right: 20px;
+    }
+
+    .C1err {
+      width: calc(100% - 260px);
+
+      .C1ett1 {
+        position: relative;
+
+        .anticon-delete {
+          position: absolute;
+          top: 50%;
+          transform: translateY(-50%);
+          left: -90px;
+          cursor: pointer;
+          font-size: 18px;
+          &:hover {
+            color: var(--themeColor);
+          }
+        }
+      }
+
+      .C1ett {
+        display: inline-block;
+        width: 100%;
+        text-align: center;
+        cursor: pointer;
+        text-decoration: underline;
+        &:hover {
+          color: var(--themeColor);
+        }
+      }
+    }
+
+    .C1eBtn {
+      display: flex;
+      align-items: center;
+      width: 100%;
+      height: 80px;
+      position: fixed;
+      bottom: 0;
+      background: #fff;
+      z-index: 10;
+
+      .C1eBtnBox {
+        display: flex;
+        gap: 20px;
+        padding-left: 100px;
+      }
+    }
+  }
+}
+
+// 时段选择
+.C1eMBox {
+  :global {
+    .ant-modal-close {
+      display: none;
+    }
+
+    .ant-modal {
+      width: 500px !important;
+    }
+
+    .ant-modal-body {
+      border-top: 1px solid #ccc;
+    }
+
+    .C1eMmain {
+      padding-top: 15px;
+      text-align: center;
+      .C1eMmainTit {
+        margin-top: 10px;
+      }
+    }
+
+    .C1eMbtn {
+      margin-top: 24px;
+      text-align: center;
+    }
+  }
+}

+ 295 - 0
src/pages/C1reserveOpt/C1edit/index.tsx

@@ -0,0 +1,295 @@
+import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
+import styles from './index.module.scss'
+import { Button, Input, Modal, Table, TimePicker } from 'antd'
+import dayjs from 'dayjs'
+import { DeleteOutlined } from '@ant-design/icons'
+import MyPopconfirm from '@/components/MyPopconfirm'
+import { MessageFu } from '@/utils/message'
+import { C1eTableDataKeyType, C1tableType } from '@/types'
+import { C1eTableData } from '../data'
+import { C1_APIdel, C1_APIsave } from '@/store/action/C1reserveOpt'
+
+type TimeType = {
+  id: string
+  show: boolean
+  value: string[] | null
+  txt: '新增' | '编辑'
+}
+
+type NumType = {
+  id: string
+  show: boolean
+  value: number
+  title: string
+  key: C1eTableDataKeyType
+}
+
+type Props = {
+  list: C1tableType[]
+  closeFu: () => void
+  editTableFu: () => void
+}
+
+function C1edit({ list, closeFu, editTableFu }: Props) {
+  // 表格数据
+  const [listRes, setListRes] = useState<C1tableType[]>([])
+
+  useEffect(() => {
+    setListRes(
+      list.map(v => ({
+        ...v,
+        id: v.id + ''
+      }))
+    )
+  }, [list])
+
+  // 1---------时段
+  const [time, setTime] = useState({} as TimeType)
+
+  // 1---------时段点击确定
+  const timeBtnOk = useCallback(async () => {
+    if (time.txt === '新增') {
+      setListRes([
+        ...listRes,
+        {
+          id: time.id,
+          time: time.value!.join('-'),
+          monday: 100,
+          tuesday: 100,
+          wednesday: 100,
+          thursday: 100,
+          friday: 100,
+          saturday: 100,
+          sunday: 100
+        }
+      ])
+    } else {
+      setListRes(
+        listRes.map(v => ({
+          ...v,
+          time: v.id === time.id ? time.value!.join('-') : v.time
+        }))
+      )
+    }
+
+    MessageFu.success(time.txt + '时段成功!')
+
+    setTime({} as TimeType)
+  }, [listRes, time])
+
+  // 1---------时间段改变
+  const timeChangeFu = useCallback(
+    (value: string[]) => {
+      const valueRes = value[0] && value[1] ? value : null
+      setTime({ ...time, value: valueRes })
+    },
+    [time]
+  )
+
+  // 从后台拿的数据,id里面没有’新‘。删除的时候需要记录下来。最后点击提交的时候一起删除
+  const delIds = useRef<string[]>([])
+
+  // 表格
+  const columns = useMemo(() => {
+    const arr: any = [
+      {
+        title: '时段',
+        render: (item: C1tableType) => (
+          <div className='C1ett1'>
+            <MyPopconfirm
+              txtK='删除'
+              onConfirm={() => {
+                if (listRes.length <= 1) return MessageFu.warning('至少需要一个时段!')
+                setListRes(listRes.filter(v => v.id !== item.id))
+                if (!item.id.includes('新')) {
+                  delIds.current.push(item.id)
+                }
+              }}
+              Dom={<DeleteOutlined />}
+            />
+
+            <span
+              className='C1ett'
+              onClick={() =>
+                setTime({
+                  show: true,
+                  value: item.time.split('-'),
+                  txt: '编辑',
+                  id: item.id
+                })
+              }
+            >
+              {item.time}
+            </span>
+          </div>
+        )
+      }
+    ]
+
+    C1eTableData.forEach(v => {
+      arr.push({
+        title: v.title,
+        render: (item: C1tableType) => (
+          <span
+            className='C1ett'
+            onClick={() =>
+              setNum({
+                id: item.id,
+                show: true,
+                value: Reflect.get(item, v.key),
+                title: `${item.time} / ${v.title}`,
+                key: v.key
+              })
+            }
+          >
+            {Reflect.get(item, v.key)}
+          </span>
+        )
+      })
+    })
+    return arr
+  }, [listRes])
+
+  // 2---------星期的数字
+  const [num, setNum] = useState({} as NumType)
+
+  const inputChange = useCallback(
+    (val: React.ChangeEvent<HTMLInputElement>) => {
+      let txt = val.target.value.replace(/^(0+)|[^\d]+/g, '')
+      let txtNum = Number(txt)
+      txtNum = txtNum > 9999 ? 9999 : txtNum
+      setNum({ ...num, value: txtNum })
+    },
+    [num]
+  )
+
+  // 2---------提交
+  const numBtnOk = useCallback(() => {
+    setListRes(
+      listRes.map(v => ({
+        ...v,
+        [num.key]: v.id === num.id ? Number(num.value) : Reflect.get(v, num.key)
+      }))
+    )
+    MessageFu.success('编辑可预约人数成功!')
+    setNum({} as NumType)
+  }, [listRes, num])
+
+  // 最后点击提交
+  const btnLastOk = useCallback(async () => {
+    if (delIds.current.length) delIds.current.forEach(v => C1_APIdel(v))
+
+    const arr = listRes.map(v => ({
+      monday: v.monday,
+      tuesday: v.tuesday,
+      wednesday: v.wednesday,
+      thursday: v.thursday,
+      friday: v.friday,
+      saturday: v.saturday,
+      sunday: v.sunday,
+      time: v.time,
+      id: v.id.includes('新') ? null : Number(v.id)
+    }))
+    const res = await C1_APIsave(arr)
+    if (res.code === 0) {
+      MessageFu.success('编辑成功!')
+      editTableFu()
+      closeFu()
+    }
+  }, [closeFu, editTableFu, listRes])
+
+  return (
+    <div className={styles.C1edit}>
+      <div className='C1ell'>
+        <Button
+          type='primary'
+          onClick={() => {
+            if (listRes.length >= 10) return MessageFu.warning('最多10个时段!')
+            setTime({
+              show: true,
+              value: null,
+              txt: '新增',
+              id: Date.now() + '新'
+            })
+          }}
+        >
+          新增时段
+        </Button>
+      </div>
+      <div className='C1err'>
+        <Table
+          rowKey='id'
+          size='middle'
+          columns={columns}
+          dataSource={listRes}
+          pagination={false}
+        />
+      </div>
+
+      <div className='C1eBtn'>
+        <div className='C1eBtnBox'>
+          <Button type='primary' onClick={btnLastOk}>
+            提交
+          </Button>
+          <MyPopconfirm txtK='取消' onConfirm={closeFu} />
+        </div>
+      </div>
+
+      {/* 时间选择 */}
+      <Modal
+        wrapClassName={styles.C1eMBox}
+        open={time.show}
+        title={`${time.txt}时段`}
+        footer={
+          [] // 设置footer为空,去掉 取消 确定默认按钮
+        }
+      >
+        <div className='C1eMmain'>
+          <TimePicker.RangePicker
+            format='HH:mm'
+            value={
+              time.value ? [dayjs(time.value[0], 'HH:mm'), dayjs(time.value[1], 'HH:mm')] : null
+            }
+            onChange={(_, value) => timeChangeFu(value)}
+          />
+        </div>
+        <div className='C1eMbtn'>
+          <Button onClick={() => setTime({} as TimeType)}>取消</Button>&emsp;
+          <Button type='primary' disabled={!time.value} onClick={timeBtnOk}>
+            提交
+          </Button>
+        </div>
+      </Modal>
+
+      {/* 星期的数字改变 */}
+      <Modal
+        wrapClassName={styles.C1eMBox}
+        open={num.show}
+        title={`${num.title} / 可预约人数`}
+        footer={
+          [] // 设置footer为空,去掉 取消 确定默认按钮
+        }
+      >
+        <div className='C1eMmain'>
+          <Input
+            style={{ width: 208 }}
+            // placeholder="请输入0~9999整数"
+            value={num.value}
+            onChange={e => inputChange(e)}
+          />
+          <div className='C1eMmainTit'>&nbsp;&nbsp;为0时,则该时段不可预约(闭馆)</div>
+        </div>
+        <div className='C1eMbtn'>
+          <Button onClick={() => setNum({} as NumType)}>取消</Button>&emsp;
+          <Button type='primary' onClick={numBtnOk}>
+            提交
+          </Button>
+        </div>
+      </Modal>
+    </div>
+  )
+}
+
+const MemoC1edit = React.memo(C1edit)
+
+export default MemoC1edit

+ 86 - 0
src/pages/C1reserveOpt/C1xuZhi.tsx

@@ -0,0 +1,86 @@
+import React, { useCallback, useEffect, useRef } from 'react'
+import styles from './index.module.scss'
+import { Button, Modal } from 'antd'
+import MyPopconfirm from '@/components/MyPopconfirm'
+import ZRichTexts from '@/components/ZRichTexts'
+import { C1_APIgetbk, C1_APIsavebk } from '@/store/action/C1reserveOpt'
+import { MessageFu } from '@/utils/message'
+
+type Props = {
+  closeFu: () => void
+}
+
+function C1xuZhi({ closeFu }: Props) {
+  // 富文本的ref
+  const ZRichTextRef = useRef<any>(null)
+
+  // 获取设置
+  const getEMfu = useCallback(async () => {
+    const res = await C1_APIgetbk({ type: 'notice' })
+    if (res.code === 0) {
+      // 设置富文本
+      ZRichTextRef.current?.ritxtShowFu({
+        txtArr: [
+          {
+            id: 0,
+            name: '正文',
+            txt: res.data?.rtf || '',
+            fileInfo: { fileName: '', filePath: '' }
+          }
+        ]
+      })
+    }
+  }, [])
+
+  useEffect(() => {
+    getEMfu()
+  }, [getEMfu])
+
+  // 点击提交
+  const btnOk = useCallback(async () => {
+    // 富文本校验不通过
+    const rtf = ZRichTextRef.current?.fatherBtnOkFu() || { flag: true }
+
+    const res = await C1_APIsavebk({ type: 'notice', rtf: rtf.val.txtArr[0].txt || '' })
+
+    if (res.code === 0) {
+      MessageFu.success(`设置预约须知成功!`)
+      closeFu()
+    }
+  }, [closeFu])
+
+  return (
+    <Modal
+      wrapClassName={styles.C1xuZhi}
+      open={true}
+      title={'预约须知'}
+      footer={
+        [] // 设置footer为空,去掉 取消 确定默认按钮
+      }
+    >
+      <div className='formRow'>
+        <ZRichTexts
+          check={false}
+          dirCode={'C1xuZhiText'}
+          isLook={false}
+          ref={ZRichTextRef}
+          myUrl='museum/upload/upload'
+          isOne={true}
+          upAudioBtnNone={true}
+        />
+      </div>
+
+      <div className='C1Xbtn'>
+        <MyPopconfirm txtK='取消' onConfirm={closeFu} />
+        &emsp;
+        <Button type='primary' onClick={btnOk}>
+          提交
+        </Button>
+      </div>
+    </Modal>
+  )
+}
+
+const MemoC1xuZhi = React.memo(C1xuZhi)
+
+export default MemoC1xuZhi

+ 0 - 0
src/pages/C1reserveOpt/data.ts


Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini