shaogen1995 2 hours ago
parent
commit
33e585c5fd

+ 8 - 0
src/components/Z3upFiles/data.ts

@@ -1,6 +1,14 @@
 import store from '@/store'
 import { baseURL } from '@/utils/http'
 
+export type FileListType = {
+  id: number
+  fileName: string
+  filePath: string
+  thumb: string
+  type: 'img' | 'video' | 'doc'
+}
+
 // 查看 权限 图片 /视频 、音频
 export const authFilesLookFu = (name: string, url: string) => {
   let flag = false

+ 116 - 57
src/components/Z3upFiles/index.module.scss

@@ -1,84 +1,143 @@
-// ----------
 .Z3upFiles {
-  a {
-    color: black;
-  }
-
-  .Z3files {
-    .Z3filesRow {
+  :global {
+    a {
+      color: black;
+    }
+    .Z3files {
       display: flex;
-      align-items: center;
-      padding: 8px 12px;
-      border: 1px solid #d9d9d9;
-      border-radius: 6px;
-      margin-bottom: 8px;
-      background: #fff;
-      transition: all 0.3s;
-
-      &:hover {
-        border-color: #40a9ff;
-        box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
-      }
+      flex-wrap: wrap;
 
-      &.dragging {
-        opacity: 0.5;
-        background: #f0f0f0;
-      }
+      .ZTbox1ImgRow {
+        // content-visibility:auto;
+        margin: 15px 20px 10px 0;
+        width: 100px;
+        height: 125px;
+        position: relative;
+        cursor: move;
+        position: relative;
 
-      &.dragOverlay {
-        box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
-        transform: rotate(5deg);
-      }
+        // 第一张作为封面
+        .ZTbox1ImgRowCover {
+          font-size: 12px;
+          line-height: 22px;
+          position: absolute;
+          left: 0;
+          top: 0;
+          width: 100%;
+          height: 24px;
+          background-color: rgba(0, 0, 0, 0.8);
+          color: #fff;
+          text-align: center;
+          pointer-events: none;
+        }
 
-      .dragHandle {
-        cursor: grab;
-        margin-right: 12px;
-        color: #999;
-        padding: 4px;
+        .ZTbox1ImgRowIcon {
+          width: 100%;
+          background-color: rgba(0, 0, 0, 0.6);
+          color: #fff;
+          display: flex;
+          justify-content: space-around;
+          font-size: 16px;
 
-        &:active {
-          cursor: grabbing;
+          a {
+            color: #fff !important;
+          }
         }
 
-        &:hover {
-          color: #40a9ff;
+        .ZTbox1ImgRowX {
+          cursor: pointer;
+          position: absolute;
+          right: -10px;
+          top: -10px;
+          z-index: 99;
+          background-color: rgba(0, 0, 0, 0.8);
+          width: 20px;
+          height: 20px;
+          border-radius: 50%;
+          font-size: 16px;
+          color: #fff;
+          display: flex;
+          justify-content: center;
+          align-items: center;
         }
       }
 
-      .Z3files1 {
-        flex: 1;
-        overflow: hidden;
-        text-overflow: ellipsis;
-        white-space: nowrap;
-      }
-
-      .Z3files2 {
+      .Z3filesRow {
+        width: 100%;
         display: flex;
         align-items: center;
+        padding: 0px 12px;
+        border: 1px solid #d9d9d9;
+        border-radius: 6px;
+        margin: 2px;
+        background: #fff;
+        transition: all 0.3s;
 
-        .anticon {
-          cursor: pointer;
-          color: #666;
+        &:hover {
+          border-color: #40a9ff;
+          box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+        }
+
+        &.dragging {
+          opacity: 0.5;
+          background: #f0f0f0;
+        }
+
+        &.dragOverlay {
+          box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
+          transform: rotate(5deg);
+        }
+
+        .dragHandle {
+          cursor: grab;
+          margin-right: 12px;
+          color: #999;
+          padding: 4px;
+
+          &:active {
+            cursor: grabbing;
+          }
 
           &:hover {
             color: #40a9ff;
           }
         }
+
+        .Z3files1 {
+          flex: 1;
+          overflow: hidden;
+          text-overflow: ellipsis;
+          white-space: nowrap;
+        }
+
+        .Z3files2 {
+          display: flex;
+          align-items: center;
+
+          .anticon {
+            cursor: pointer;
+            color: #666;
+
+            &:hover {
+              color: #40a9ff;
+            }
+          }
+        }
       }
     }
-  }
 
-  .fileTit {
-    margin-top: 12px;
-    color: #666;
-    font-size: 12px;
+    .fileTit {
+      margin-top: 5px;
+      color: #666;
+      font-size: 12px;
 
-    .noUpThumb {
-      display: none;
+      .noUpThumb {
+        display: none;
 
-      &.noUpThumbAc {
-        display: block;
-        color: #ff4d4f;
+        &.noUpThumbAc {
+          display: block;
+          color: #ff4d4f;
+        }
       }
     }
   }

+ 220 - 131
src/components/Z3upFiles/index.tsx

@@ -1,9 +1,8 @@
-import React, { useCallback, useRef, useState } from 'react'
+import React, { useCallback, useMemo, useRef, useState } from 'react'
 import styles from './index.module.scss'
 import { API_upFile } from '@/store/action/layout'
 import { MessageFu } from '@/utils/message'
 import { fileDomInitialFu } from '@/utils/domShow'
-import { forwardRef, useImperativeHandle } from 'react'
 import { Button, Popconfirm } from 'antd'
 import {
   UploadOutlined,
@@ -14,7 +13,7 @@ import {
 } from '@ant-design/icons'
 import classNames from 'classnames'
 import { baseURL } from '@/utils/http'
-import { authFilesLookFu } from './data'
+import { authFilesLookFu, FileListType } from './data'
 import { DndContext, DragEndEvent, DragOverlay, DragStartEvent, closestCenter } from '@dnd-kit/core'
 import {
   SortableContext,
@@ -23,118 +22,76 @@ import {
   arrayMove
 } from '@dnd-kit/sortable'
 import { CSS } from '@dnd-kit/utilities'
-import { FileImgListType } from '@/pages/Layout/data'
+import { useInfo } from '@/pages/Zother/InfoContext'
+import { Typetable } from '@/pages/Zother/data'
+import { fileTypeRes } from '@/utils'
+import ImageLazy from '../ImageLazy'
+import store from '@/store'
+import MyPopconfirm from '../MyPopconfirm'
+
+// 可排序的文件项组件
+interface SortableFileItemProps {
+  file: FileListType
+  onDelete: (id: number) => void
+  isLook: boolean
+  index: number
+}
 
 type Props = {
   isLook: boolean // 是否是查看
-  ref: any // 当前自己的ref,给父组件调用
   fileCheck: boolean
   dirCode: string // 文件的code码
   myUrl: string
   fromData?: any
-  accept?: string
-  // result:成果 | list:清单
-  type?: string
   tips?: string
   // 文件大小
   size?: number
   // 最大文件数量
   maxCount?: number
+  // 订单id
+  moduleId: number
+  oneIsCover?: boolean //是否将第一张作为封面
 }
 
-// 可排序的文件项组件
-interface SortableFileItemProps {
-  file: FileImgListType
-  onDelete: (id: number) => void
-  isLook: boolean
-  index: number
-}
+function Z3upFiles({
+  isLook,
+  fileCheck,
+  dirCode,
+  myUrl,
+  fromData,
+  tips = '单个附件不得超过500M',
+  size = 500,
+  moduleId,
+  maxCount = 999,
+  oneIsCover
+}: Props) {
+  const { info, setInfoFu } = useInfo()
 
-const SortableFileItem = ({ file, onDelete, isLook, index }: SortableFileItemProps) => {
-  const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({
-    id: file.id
-  })
+  const fileList = useMemo(() => {
+    return info.files || []
+  }, [info.files])
 
-  const style = {
-    transform: CSS.Transform.toString(transform),
-    transition,
-    opacity: isDragging ? 0.5 : 1
-  }
+  const setFileList = useCallback(
+    (newFiles: FileListType[] | ((prev: FileListType[]) => FileListType[])) => {
+      setInfoFu((prevInfo: Typetable) => {
+        const currentFiles = prevInfo.files || []
+        const updatedFiles = typeof newFiles === 'function' ? newFiles(currentFiles) : newFiles
 
-  return (
-    <div
-      ref={setNodeRef}
-      style={style}
-      className={classNames(styles.Z3filesRow, { [styles.dragging]: isDragging })}
-    >
-      {!isLook && (
-        <div className={styles.dragHandle} {...attributes} {...listeners}>
-          <MenuOutlined rev={undefined} />
-        </div>
-      )}
-      <div className={styles.Z3files1} title={file.fileName}>
-        {file.fileName}
-      </div>
-      <div className={styles.Z3files2}>
-        {authFilesLookFu(file.fileName, '') ? (
-          <>
-            <EyeOutlined
-              rev={undefined}
-              title='查看'
-              onClick={() => authFilesLookFu(file.fileName, file.filePath)}
-            />
-            &emsp;
-          </>
-        ) : null}
-        <a
-          title='下载'
-          href={baseURL + file.filePath}
-          download={file.fileName}
-          target='_blank'
-          rel='noreferrer'
-        >
-          <DownloadOutlined rev={undefined} />
-        </a>
-        &emsp;
-        {!isLook && (
-          <Popconfirm
-            title='删除后无法恢复,是否删除?'
-            okText='删除'
-            cancelText='取消'
-            onConfirm={() => onDelete(file.id)}
-            okButtonProps={{ loading: false }}
-          >
-            <CloseOutlined rev={undefined} title='删除' />
-          </Popconfirm>
-        )}
-      </div>
-    </div>
+        // 明确指定返回类型
+        const updatedInfo: Typetable = {
+          ...prevInfo,
+          files: updatedFiles
+        }
+
+        return updatedInfo
+      })
+    },
+    [setInfoFu]
   )
-}
 
-function Z3upFiles(
-  {
-    isLook,
-    type = 'doc',
-    fileCheck,
-    dirCode,
-    myUrl,
-    fromData,
-    accept = '.zip',
-    tips = '单个附件不得超过500M',
-    size
-  }: Props,
-  ref: any
-) {
-  const [fileList, setFileList] = useState<FileImgListType[]>([])
   const [activeId, setActiveId] = useState<number | null>(null)
   const myInput = useRef<HTMLInputElement>(null)
 
-  // 给父组件调用 回显
-  const showList = useCallback((list: FileImgListType[]) => {
-    setFileList(list)
-  }, [])
-
   // 上传多个文件
   const handeUpPhoto = useCallback(
     async (e: React.ChangeEvent<HTMLInputElement>) => {
@@ -142,6 +99,11 @@ function Z3upFiles(
 
       const files = Array.from(e.target.files)
 
+      if (files.length + fileList.length > maxCount)
+        return MessageFu.warning(
+          `最多可上传${maxCount}个文件,当前选中${files.length}个文件,还可上传${maxCount - fileList.length}个文件`
+        )
+
       // 逐个上传文件
       for (const file of files) {
         // 校验大小
@@ -149,13 +111,14 @@ function Z3upFiles(
           MessageFu.warning(`文件"${file.name}"超过${size}M限制!`)
           continue
         }
-
+        const typeRes = fileTypeRes(file.name)
         // 创建FormData对象
         const fd = new FormData()
-        fd.append('type', type)
+        fd.append('type', typeRes)
         fd.append('dirCode', dirCode)
         fd.append('isCompress', 'true')
         fd.append('isDb', 'true')
+        fd.append('moduleId', moduleId + '')
         fd.append('file', file)
 
         if (fromData) {
@@ -182,7 +145,7 @@ function Z3upFiles(
         }
       }
     },
-    [dirCode, fromData, myUrl, size, type]
+    [dirCode, fileList.length, fromData, maxCount, moduleId, myUrl, setFileList, size]
   )
 
   // 拖拽开始
@@ -191,38 +154,164 @@ function Z3upFiles(
   }, [])
 
   // 拖拽结束
-  const handleDragEnd = useCallback((event: DragEndEvent) => {
-    const { active, over } = event
-    setActiveId(null)
+  const handleDragEnd = useCallback(
+    (event: DragEndEvent) => {
+      const { active, over } = event
+      setActiveId(null)
 
-    if (over && active.id !== over.id) {
-      setFileList(items => {
-        const oldIndex = items.findIndex(item => item.id === active.id)
-        const newIndex = items.findIndex(item => item.id === over.id)
+      if (over && active.id !== over.id) {
+        setFileList(items => {
+          const oldIndex = items.findIndex(item => item.id === active.id)
+          const newIndex = items.findIndex(item => item.id === over.id)
 
-        return arrayMove(items, oldIndex, newIndex)
-      })
-    }
-  }, [])
+          return arrayMove(items, oldIndex, newIndex)
+        })
+      }
+    },
+    [setFileList]
+  )
 
   // 列表删除某一个文件
-  const delImgListFu = useCallback((id: number) => {
-    setFileList(prev => prev.filter(v => v.id !== id))
-  }, [])
-
-  // 让父组件调用,拿到附件信息
-  const filesRes = useCallback(() => {
-    return fileList || []
-  }, [fileList])
+  const delImgListFu = useCallback(
+    (id: number) => {
+      setFileList(prev => prev.filter(v => v.id !== id))
+    },
+    [setFileList]
+  )
 
   // 获取当前拖拽的文件
   const activeFile = activeId ? fileList.find(file => file.id === activeId) : null
 
-  // 可以让父组件调用子组件的方法
-  useImperativeHandle(ref, () => ({
-    filesRes,
-    showList
-  }))
+  // 附件图片的拖动
+  const [dragImg, setDragImg] = useState<any>(null)
+
+  const handleDragOver = useCallback(
+    (e: React.DragEvent<HTMLDivElement>, item: FileListType) => {
+      if (isLook) return
+      e.dataTransfer.dropEffect = 'move'
+    },
+    [isLook]
+  )
+
+  const handleDragEnter = useCallback(
+    (e: React.DragEvent<HTMLDivElement>, item: FileListType) => {
+      if (isLook) return
+
+      e.dataTransfer.effectAllowed = 'move'
+      if (item === dragImg) return
+      const newItems = [...fileList] //拷贝一份数据进行交换操作。
+      const src = newItems.indexOf(dragImg) //获取数组下标
+      const dst = newItems.indexOf(item)
+      newItems.splice(dst, 0, ...newItems.splice(src, 1)) //交换位置
+      setFileList({ ...newItems })
+    },
+    [dragImg, fileList, isLook, setFileList]
+  )
+
+  // 详情子函数--------------------
+  const SortableFileItem = ({ file, onDelete, isLook, index }: SortableFileItemProps) => {
+    const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({
+      id: file.id
+    })
+
+    const style = {
+      transform: CSS.Transform.toString(transform),
+      transition,
+      opacity: isDragging ? 0.5 : 1
+    }
+    if (file.type === 'img') {
+      return (
+        <div
+          className='ZTbox1ImgRow'
+          draggable='true'
+          onDragStart={() => setDragImg(file)}
+          onDragOver={e => handleDragOver(e, file)}
+          onDragEnter={e => handleDragEnter(e, file)}
+          onDragEnd={() => setDragImg(null)}
+        >
+          {file.thumb || file.filePath ? (
+            <ImageLazy noLook={true} width={100} height={100} src={file.thumb || file.filePath} />
+          ) : null}
+
+          {oneIsCover && index === 0 ? <div className='ZTbox1ImgRowCover'>封面</div> : null}
+
+          <div className='ZTbox1ImgRowIcon'>
+            <EyeOutlined
+              onClick={() =>
+                store.dispatch({
+                  type: 'layout/lookBigImg',
+                  payload: {
+                    url: baseURL + file.filePath,
+                    show: true
+                  }
+                })
+              }
+              rev={undefined}
+            />
+            <a href={baseURL + file.filePath} download target='_blank' rel='noreferrer'>
+              <DownloadOutlined rev={undefined} />
+            </a>
+          </div>
+
+          <MyPopconfirm
+            txtK='删除'
+            onConfirm={() => delImgListFu(file.id)}
+            Dom={<CloseOutlined className='ZTbox1ImgRowX' rev={undefined} />}
+          />
+        </div>
+      )
+    } else {
+      return (
+        <div
+          ref={setNodeRef}
+          style={style}
+          className={classNames('Z3filesRow', isDragging ? 'dragging' : '')}
+        >
+          {!isLook && (
+            <div className='dragHandle' {...attributes} {...listeners}>
+              <MenuOutlined rev={undefined} />
+            </div>
+          )}
+          <div className='Z3files1' title={file.fileName}>
+            {file.fileName}
+          </div>
+          <div className='Z3files2'>
+            {authFilesLookFu(file.fileName, '') ? (
+              <>
+                <EyeOutlined
+                  rev={undefined}
+                  title='查看'
+                  onClick={() => authFilesLookFu(file.fileName, file.filePath)}
+                />
+                &emsp;
+              </>
+            ) : null}
+            <a
+              title='下载'
+              href={baseURL + file.filePath}
+              download={file.fileName}
+              target='_blank'
+              rel='noreferrer'
+            >
+              <DownloadOutlined rev={undefined} />
+            </a>
+            &emsp;
+            {!isLook && (
+              <Popconfirm
+                title='删除后无法恢复,是否删除?'
+                okText='删除'
+                cancelText='取消'
+                onConfirm={() => onDelete(file.id)}
+                okButtonProps={{ loading: false }}
+              >
+                <CloseOutlined rev={undefined} title='删除' />
+              </Popconfirm>
+            )}
+          </div>
+        </div>
+      )
+    }
+  }
 
   return (
     <div className={styles.Z3upFiles}>
@@ -233,7 +322,7 @@ function Z3upFiles(
         onChange={handeUpPhoto}
         multiple // 支持多选
       />
-      <div className={styles.Z3Btn}>
+      <div className='Z3Btn'>
         {!isLook && (
           <Button
             onClick={() => myInput.current?.click()}
@@ -243,7 +332,7 @@ function Z3upFiles(
           </Button>
         )}
 
-        <div className={styles.Z3files} style={{ marginTop: isLook ? '0' : '16px' }}>
+        <div className='Z3files'>
           <DndContext
             collisionDetection={closestCenter}
             onDragStart={handleDragStart}
@@ -262,26 +351,26 @@ function Z3upFiles(
             </SortableContext>
             <DragOverlay>
               {activeFile ? (
-                <div className={classNames(styles.Z3filesRow, styles.dragOverlay)}>
-                  <div className={styles.dragHandle}>
+                <div className={classNames('Z3filesRow', 'dragOverlay')}>
+                  <div className='dragHandle'>
                     <MenuOutlined rev={undefined} />
                   </div>
-                  <div className={styles.Z3files1} title={activeFile.fileName}>
+                  <div className='Z3files1' title={activeFile.fileName}>
                     {activeFile.fileName}
                   </div>
-                  <div className={styles.Z3files2}>{/* 拖拽时隐藏操作按钮 */}</div>
+                  <div className='Z3files2'>{/* 拖拽时隐藏操作按钮 */}</div>
                 </div>
               ) : null}
             </DragOverlay>
           </DndContext>
         </div>
 
-        <div className={styles.fileTit} hidden={isLook}>
-          {tips};支持按住Ctrl键选择多个文件;拖动附件左侧图标可调整顺序
+        <div className='fileTit' hidden={isLook}>
+          {tips};支持按住Ctrl键选择多个文件;按住鼠标拖动图片/拖动附件左侧图标 可调整顺序
           <div
             className={classNames(
-              styles.noUpThumb,
-              fileList.length <= 0 && fileCheck ? styles.noUpThumbAc : ''
+              'noUpThumb',
+              fileList.length <= 0 && fileCheck ? 'noUpThumbAc' : ''
             )}
           >
             请上传文件!
@@ -295,4 +384,4 @@ function Z3upFiles(
   )
 }
 
-export default forwardRef(Z3upFiles)
+export default Z3upFiles

+ 0 - 82
src/components/ZRichText/index.module.scss

@@ -1,82 +0,0 @@
-.ZRichText {
-  width: 1000px;
-  height: 100%;
-
-  :global {
-    .txtBox {
-      width: 100%;
-      height: 100%;
-      border: 1px solid #ccc;
-
-      a{
-        color: #fff !important;
-      }
-
-      // 隐藏媒体功能
-      .control-item.media {
-        display: none;
-      }
-
-      .bf-container {
-        height:100%;
-      }
-
-      .bf-content {
-        height: calc(100% - 92px);
-        padding-bottom: 0px;
-      }
-
-
-
-      .bf-controlbar {
-        position: relative;
-
-        .upImgBox {
-          position: absolute;
-          bottom: 13px;
-          right: 15px;
-          cursor: pointer;
-          color: var(--themeColor);
-          // display: none;
-        }
-
-        .upImgBoxNo {
-          display: none;
-        }
-
-      }
-    }
-
-    .noUpThumb {
-      position: relative;
-      overflow: hidden;
-      opacity: 0;
-      transition: top .2s;
-      color: #ff4d4f;
-      top: -10px;
-    }
-
-    .noUpThumbAc {
-      top: 0;
-      opacity: 1;
-    }
-
-    .bf-media .bf-image {
-      float: initial !important;
-      display: block;
-      margin: 10px auto;
-      text-align: center;
-
-      // 不让拖动放大缩小图片(会报错)
-      .bf-csize-icon {
-        display: none !important;
-      }
-
-      img {
-        max-width: 500px;
-        max-height: 300px;
-      }
-    }
-
-  }
-}

+ 0 - 216
src/components/ZRichText/index.tsx

@@ -1,216 +0,0 @@
-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 "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";
-
-type Props = {
-  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";
-      // div.title = "上传图片";
-      div.innerHTML = "上传图片/视频";
-      div.onclick = async () => {
-        myInput.current?.click();
-      };
-      dom.appendChild(div);
-    }, 20);
-
-    // 监听 富文本 的 class 变化,在全屏的时候会 富文本会添加上 fullscreen 的类
-    // 修复顶部样式冲突问题
-
-    const editorDom = document.querySelector(".bf-container") as HTMLDivElement;
-
-    const observer = new MutationObserver(() => {
-      // console.log("change");
-      const dom = document.querySelector(".layoutRightTop") as HTMLDivElement;
-
-      if (editorDom.className.includes("fullscreen")) dom.style.zIndex = "-1";
-      else dom.style.zIndex = "100";
-    });
-
-    observer.observe(editorDom, {
-      attributes: true,
-    });
-
-    // 销毁监听
-    return () => {
-      observer.disconnect();
-    };
-  }, []);
-
-  useEffect(() => {
-    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";
-      });
-      contentDom.forEach((v: any) => {
-        v.style.height = isLook ? "100%" : "";
-      });
-    }
-  }, [isLook]);
-
-  // 编辑器文本
-  const [editorValue, setEditorValue] = useState(
-    // 初始内容
-    BraftEditor.createEditorState("")
-  );
-
-  // 判断 富文本是否为空
-  const isTxtFlag = useMemo(() => {
-    const txt: string = editorValue.toHTML();
-    if (
-      txt.replaceAll("<p>", "").replaceAll("</p>", "").replaceAll(" ", "") ===
-      ""
-    ) {
-      return true;
-    } else return false;
-  }, [editorValue]);
-
-  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);
-        }
-        // 校验大小
-        if (filesInfo.size > size * 1024 * 1024) {
-          e.target.value = "";
-          return MessageFu.warning(txt2);
-        }
-        // 创建FormData对象
-        const fd = new FormData();
-        // 把files添加进FormData对象(‘photo’为后端需要的字段)
-        fd.append("type", isVideoFlag ? "video" : "img");
-        fd.append("dirCode", dirCode);
-        fd.append("file", filesInfo);
-
-        e.target.value = "";
-
-        try {
-          const res = await API_upFile(fd, myUrl);
-          if (res.code === 0) {
-            MessageFu.success("上传成功!");
-            // 在光标位置插入图片
-            const newTxt = ContentUtils.insertMedias(editorValue, [
-              {
-                type: "IMAGE",
-                url: baseURL + res.data.filePath,
-              },
-            ]);
-
-            setEditorValue(newTxt);
-          }
-          fileDomInitialFu();
-        } catch (error) {
-          fileDomInitialFu();
-        }
-      }
-    },
-    [dirCode, editorValue, myUrl]
-  );
-
-  // 让父组件调用的 回显 富文本
-  const ritxtShowFu = useCallback((val: string) => {
-    setEditorValue(BraftEditor.createEditorState(val));
-  }, []);
-
-  // 让父组件调用的返回 富文本信息 和 表单校验 isTxtFlag为ture表示未通过校验
-  const fatherBtnOkFu = useCallback(() => {
-    return { val: editorValue.toHTML(), flag: isTxtFlag };
-  }, [editorValue, isTxtFlag]);
-
-  // 可以让父组件调用子组件的方法
-  useImperativeHandle(ref, () => ({
-    ritxtShowFu,
-    fatherBtnOkFu,
-  }));
-
-  return (
-    <div className={styles.ZRichText} style={{ width: full ? "100%" : "" }}>
-      <input
-        id="upInput"
-        type="file"
-        accept=".png,.jpg,.jpeg,.mp4"
-        ref={myInput}
-        onChange={(e) => handeUpPhoto(e)}
-      />
-
-      <div className="txtBox">
-        <BraftEditor
-          readOnly={isLook}
-          placeholder="请输入内容"
-          value={editorValue}
-          onChange={(e) => setEditorValue(e)}
-          imageControls={["remove"]}
-        />
-      </div>
-      <div
-        className={classNames(
-          "noUpThumb",
-          check && isTxtFlag ? "noUpThumbAc" : ""
-        )}
-      >
-        请输入正文!
-      </div>
-    </div>
-  );
-}
-
-export default forwardRef(ZRichText);

+ 0 - 195
src/components/ZRichTexts/index.module.scss

@@ -1,195 +0,0 @@
-.ZRichTexts {
-  width: 1000px;
-
-  :global {
-    // 正文
-    .formRightZW {
-      width: 700px;
-      top: -3px;
-      position: relative;
-      display: flex;
-      align-items: center;
-      justify-content: space-between;
-      height: 32px;
-
-      .formRightZWRR {
-        display: flex;
-      }
-    }
-
-    // 从查看进来
-    .formRightZWLook {
-      .ant-checkbox-wrapper {
-        pointer-events: none;
-      }
-    }
-
-    .txtBox {
-      width: 100%;
-      position: relative;
-
-      a {
-        color: #fff !important;
-      }
-
-      // 隐藏媒体功能
-      .control-item.media {
-        display: none;
-      }
-
-      button {
-        &:nth-of-type(7) {
-          display: none !important;
-        }
-        &:nth-of-type(8) {
-          display: none !important;
-        }
-        &:nth-of-type(18) {
-          display: none !important;
-        }
-        &:nth-of-type(19) {
-          display: none !important;
-        }
-      }
-
-      .bf-container {
-        height: 100%;
-      }
-
-      .bf-content {
-        height: 300px;
-        padding-bottom: 0px;
-      }
-
-      .bf-controlbar {
-        position: relative;
-
-        .upImgBox {
-          position: absolute;
-          bottom: 13px;
-          right: 15px;
-          cursor: pointer;
-          color: var(--themeColor);
-          // display: none;
-        }
-
-        .upImgBoxNo {
-          display: none;
-        }
-      }
-
-      .zztxtRow {
-        margin-bottom: 20px;
-        border: 1px solid #ccc;
-
-        .zztxtRow1 {
-          padding: 0 20px;
-          height: 40px;
-          display: flex;
-          align-items: center;
-          justify-content: space-between;
-          background-color: #e8e8e8;
-
-          .zztxtRow1_1 {
-            display: flex;
-            align-items: center;
-
-            .zztxtRow1_1_1 {
-              font-weight: 700;
-              font-size: 16px;
-              margin-right: 20px;
-            }
-
-            .zztxtRow1_1_2 {
-              display: flex;
-              align-items: center;
-              width: 580px;
-              height: 32px;
-            }
-          }
-        }
-
-        .zztxtRow1_2 {
-          display: flex;
-          align-items: center;
-
-          .anticon {
-            cursor: pointer;
-            font-size: 18px;
-          }
-
-          .zztxtRow1_2Icon {
-            position: relative;
-            top: 2px;
-          }
-
-          .zztxtRow1_2IconNo {
-            pointer-events: none;
-            opacity: 0.2;
-          }
-        }
-      }
-
-      .zztxtRowErr {
-        border-color: #ff4d4f;
-      }
-    }
-
-    // 从查看进来
-    .txtBoxLook {
-      .button-remove {
-        display: none !important;
-      }
-      .bf-controlbar {
-        pointer-events: auto !important;
-        display: flex;
-        justify-content: flex-end;
-        button {
-          display: none;
-          &:last-child {
-            display: inline-block;
-          }
-        }
-        div {
-          display: none;
-        }
-        .separator-line {
-          display: none;
-        }
-      }
-    }
-
-    .noUpThumb {
-      position: relative;
-      overflow: hidden;
-      opacity: 0;
-      transition: top 0.2s;
-      color: #ff4d4f;
-      top: -20px;
-    }
-
-    .noUpThumbAc {
-      top: -10px;
-      opacity: 1;
-    }
-
-    .bf-media .bf-image {
-      float: initial !important;
-      display: block;
-      margin: 0px auto;
-      text-align: center;
-
-      // 不让拖动放大缩小图片(会报错)
-      .bf-csize-icon {
-        display: none !important;
-      }
-
-      img {
-        max-width: 500px;
-        max-height: 300px;
-      }
-    }
-
-    // .bf-video-wrap
-  }
-}

+ 0 - 414
src/components/ZRichTexts/index.tsx

@@ -1,414 +0,0 @@
-import React, { useCallback, 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 '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'
-import { Button, Checkbox, Input } from 'antd'
-import { ArrowDownOutlined, DeleteOutlined, ArrowUpOutlined } from '@ant-design/icons'
-import MyPopconfirm from '../MyPopconfirm'
-
-export type SectionArrType = {
-  id: number
-  name: string
-  txt: any
-  fileInfo: ZupAudioType
-}
-
-type Props = {
-  check: boolean //表单校验,为fasle表示不校验
-  dirCode: string //文件的code码
-  isLook: boolean //是否是查看进来
-  ref: any //当前自己的ref,给父组件调用
-  myUrl: string //上传的api地址
-  isOne?: boolean //只显示单个富文本
-  upAudioBtnNone?: boolean //是否能上传无障碍音频
-}
-
-function ZRichTexts(
-  { check, dirCode, isLook, myUrl, isOne = false, upAudioBtnNone = false }: Props,
-  ref: any
-) {
-  const [sectionArr, setSectionArr] = useState<SectionArrType[]>([
-    {
-      id: Date.now(),
-      name: '',
-      txt: BraftEditor.createEditorState(''),
-      fileInfo: { fileName: '', filePath: '' }
-    }
-  ])
-
-  // 是否按章节发布
-  const [isSection, setIsSection] = useState(false)
-
-  // 当前上传 图片 视频的索引
-  const nowIndexRef = useRef(0)
-
-  // 判断 富文本是否为空
-  const isTxtFlag = useMemo(() => {
-    let flag = false
-
-    // 不是按章节发布,检查第一个富文本
-    if (!isSection) {
-      const txt = sectionArr[0].txt.toText()
-      const txtHtml = sectionArr[0].txt.toHTML()
-      const txtRes = txt.replaceAll('\n', '').replaceAll(' ', '')
-      if (!txtRes && !txtHtml.includes('class="media-wrap')) flag = true
-    } else {
-      // 按章节发布  检查 所有的 标题 和富文本
-      sectionArr.forEach(v => {
-        if (!v.name) flag = true
-        const txt = v.txt.toText()
-        const txtHtml = sectionArr[0].txt.toHTML()
-        const txtRes = txt.replaceAll('\n', '').replaceAll(' ', '')
-        if (!txtRes && !txtHtml.includes('class="media-wrap')) flag = true
-      })
-    }
-
-    return flag
-  }, [isSection, sectionArr])
-
-  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') || filesInfo.name.endsWith('.MP4')
-
-        if (isVideoFlag) {
-          // 上传视频
-          size = 500
-          txt = '视频只支持mp4格式!'
-          txt2 = '视频最大支持500M!'
-        }
-
-        // 校验格式
-        if (!type.includes(filesInfo.type)) {
-          e.target.value = ''
-          return MessageFu.warning(txt)
-        }
-
-        // 校验大小
-        if (filesInfo.size > size * 1024 * 1024) {
-          e.target.value = ''
-          return MessageFu.warning(txt2)
-        }
-
-        // 创建FormData对象
-        const fd = new FormData()
-        // 把files添加进FormData对象(‘photo’为后端需要的字段)
-        fd.append('type', isVideoFlag ? 'video' : 'img')
-        fd.append('dirCode', dirCode)
-        fd.append('file', filesInfo)
-
-        e.target.value = ''
-
-        try {
-          const res = await API_upFile(fd, myUrl)
-          if (res.code === 0) {
-            MessageFu.success('上传成功!')
-            // 在光标位置插入图片
-            const newTxt = ContentUtils.insertMedias(sectionArr[nowIndexRef.current].txt, [
-              {
-                type: isVideoFlag ? 'VIDEO' : 'IMAGE',
-                url: baseURL + res.data.filePath
-              }
-            ])
-            const arr = [...sectionArr]
-            arr[nowIndexRef.current].txt = newTxt
-            setSectionArr(arr)
-          }
-          fileDomInitialFu()
-        } catch (error) {
-          fileDomInitialFu()
-        }
-      }
-    },
-    [dirCode, myUrl, sectionArr]
-  )
-
-  // 让父组件调用的 回显 富文本
-  const ritxtShowFu = useCallback((val: any) => {
-    if (val) {
-      setIsSection(val.isSection || false)
-      if (val.txtArr) {
-        const arr = val.txtArr.map((v: any) => ({
-          ...v,
-          txt: BraftEditor.createEditorState(v.txt)
-        }))
-        setSectionArr(arr)
-      }
-    }
-  }, [])
-
-  // 让父组件调用的返回 富文本信息 和 表单校验 isTxtFlag为ture表示未通过校验
-  const fatherBtnOkFu = useCallback(() => {
-    const arr: any[] = []
-
-    sectionArr.forEach((v, i) => {
-      arr.push({
-        ...v,
-        txt: v.txt.toHTML()
-      })
-    })
-
-    const obj = {
-      isSection: isSection, //是否按章节发布
-      txtArr: arr
-    }
-
-    return { val: obj, flag: isTxtFlag }
-  }, [isSection, isTxtFlag, sectionArr])
-
-  // 可以让父组件调用子组件的方法
-  useImperativeHandle(ref, () => ({
-    ritxtShowFu,
-    fatherBtnOkFu
-  }))
-
-  // 点击新增章节
-  const addSectionFu = useCallback(() => {
-    if (sectionArr.length >= 20) return MessageFu.warning('最多存在20个章节')
-    setSectionArr([
-      ...sectionArr,
-      {
-        id: Date.now(),
-        name: '',
-        txt: BraftEditor.createEditorState(''),
-        fileInfo: { fileName: '', filePath: '' }
-      }
-    ])
-  }, [sectionArr])
-
-  // 章节音频上传成功
-  const upSectionFu = useCallback(
-    (info: ZupAudioType, index: number) => {
-      const arr = [...sectionArr]
-      arr[index].fileInfo = info
-      setSectionArr(arr)
-    },
-    [sectionArr]
-  )
-
-  // 章节音频删除
-  const delSectionFu = useCallback(
-    (index: number) => {
-      // console.log("ppppppppp", index);
-
-      const arr = [...sectionArr]
-      arr[index].fileInfo = { fileName: '', filePath: '' }
-      setSectionArr(arr)
-    },
-    [sectionArr]
-  )
-
-  // 整个章节的删除
-  const delSectionAllFu = useCallback(
-    (id: number) => {
-      setSectionArr(sectionArr.filter(v => v.id !== id))
-    },
-    [sectionArr]
-  )
-
-  // 整个章节的位移
-  const moveSectionFu = useCallback(
-    (index: number, num: number) => {
-      const arr = [...sectionArr]
-      const temp = arr[index]
-      arr[index] = arr[index + num]
-      arr[index + num] = temp
-      setSectionArr(arr)
-    },
-    [sectionArr]
-  )
-
-  // 单个富文本是否输入完整
-  const isOneTxtFlag = useCallback(
-    (name: string, txt: any) => {
-      let flag = false
-      if (!name && isSection) flag = true
-      const txt2 = txt.toText()
-      const txtHtml = txt.toHTML()
-      const txtRes = txt2.replaceAll('\n', '').replaceAll(' ', '')
-      if (!txtRes && !txtHtml.includes('class="media-wrap')) flag = true
-      return flag
-    },
-    [isSection]
-  )
-
-  return (
-    <div className={styles.ZRichTexts}>
-      <input
-        id='upInput'
-        type='file'
-        accept='.png,.jpg,.jpeg,.mp4'
-        ref={myInput}
-        onChange={e => handeUpPhoto(e)}
-      />
-
-      <div className={classNames('formRightZW', isLook ? 'formRightZWLook' : '')}>
-        {isOne ? (
-          <div></div>
-        ) : (
-          <Checkbox checked={isSection} onChange={e => setIsSection(e.target.checked)}>
-            按章节发布
-          </Checkbox>
-        )}
-
-        {isSection ? (
-          <Button hidden={isLook} type='primary' onClick={addSectionFu}>
-            新增章节
-          </Button>
-        ) : (
-          <div className='formRightZWRR'>
-            {upAudioBtnNone ? null : (
-              <ZupAudio
-                fileInfo={sectionArr[0].fileInfo}
-                upDataFu={info => upSectionFu(info, 0)}
-                delFu={() => delSectionFu(0)}
-                dirCode={dirCode}
-                myUrl={myUrl}
-                isLook={isLook}
-              />
-            )}
-
-            <div hidden={isLook} style={{ marginLeft: 20 }}>
-              <Button
-                onClick={() => {
-                  nowIndexRef.current = 0
-                  myInput.current?.click()
-                }}
-              >
-                上传图片/视频
-              </Button>
-            </div>
-          </div>
-        )}
-      </div>
-
-      <div className={classNames('txtBox', isLook ? 'txtBoxLook' : '')}>
-        {sectionArr.map((item, index) => (
-          <div
-            className={classNames(
-              'zztxtRow',
-              isOneTxtFlag(item.name, item.txt) && check ? 'zztxtRowErr' : ''
-            )}
-            key={item.id}
-            hidden={!isSection && index > 0}
-          >
-            {/* 顶部 */}
-            <div className='zztxtRow1' hidden={!isSection && index === 0}>
-              <div className='zztxtRow1_1'>
-                <div className='zztxtRow1_1_1'>章节 {index + 1}</div>
-                <div className='zztxtRow1_1_2'>
-                  标题:
-                  <Input
-                    readOnly={isLook}
-                    value={item.name}
-                    placeholder='请输入内容'
-                    maxLength={100}
-                    showCount
-                    style={{ width: 400 }}
-                    onChange={e => {
-                      const arr = [...sectionArr]
-                      // arr[index].name = e.target.value.replace(/\s+/g, '')
-                      arr[index].name = e.target.value
-                      setSectionArr(arr)
-                    }}
-                  />
-                  &emsp;
-                  <Button
-                    hidden={isLook}
-                    onClick={() => {
-                      nowIndexRef.current = index
-                      myInput.current?.click()
-                    }}
-                  >
-                    上传图片/视频
-                  </Button>
-                </div>
-              </div>
-              <div className='zztxtRow1_2'>
-                <ZupAudio
-                  fileInfo={item.fileInfo}
-                  upDataFu={info => upSectionFu(info, index)}
-                  delFu={() => delSectionFu(index)}
-                  dirCode={dirCode}
-                  myUrl={myUrl}
-                  isLook={isLook}
-                />
-                &emsp;
-                <div
-                  hidden={isLook}
-                  className={classNames('zztxtRow1_2Icon', index === 0 ? 'zztxtRow1_2IconNo' : '')}
-                  onClick={() => moveSectionFu(index, -1)}
-                >
-                  <ArrowUpOutlined title='上移' />
-                </div>
-                &emsp;
-                <div
-                  hidden={isLook}
-                  className={classNames(
-                    'zztxtRow1_2Icon',
-                    index === sectionArr.length - 1 ? 'zztxtRow1_2IconNo' : ''
-                  )}
-                  onClick={() => moveSectionFu(index, 1)}
-                >
-                  <ArrowDownOutlined title='下移' />
-                </div>
-                &emsp;
-                {isLook || sectionArr.length <= 1 ? null : (
-                  <MyPopconfirm
-                    txtK='删除'
-                    onConfirm={() => delSectionAllFu(item.id)}
-                    Dom={<DeleteOutlined title='删除' className='ZTbox2X' />}
-                  />
-                )}
-              </div>
-            </div>
-            {/* 主体 */}
-            <BraftEditor
-              readOnly={isLook}
-              placeholder='请输入内容'
-              value={item.txt}
-              onChange={e => {
-                const arr = [...sectionArr]
-                arr[index].txt = e
-                setSectionArr(arr)
-              }}
-              imageControls={['remove']}
-            />
-          </div>
-        ))}
-      </div>
-      <div className={classNames('noUpThumb', check && isTxtFlag ? 'noUpThumbAc' : '')}>
-        {`请完整输入${isSection ? '标题/' : ''}正文!`}
-      </div>
-    </div>
-  )
-}
-
-export default forwardRef(ZRichTexts)

+ 0 - 63
src/components/ZupAudio/index.module.scss

@@ -1,63 +0,0 @@
-// 上传无障碍音频的样式
-.ZupAudio {
-  margin-left: 20px;
-  width: 180px;
-  height: 32px;
-  // position: relative;
-  // top: -4px;
-  border: 1px solid #ccc;
-  border-radius: 16px;
-  background-color: #fff;
-
-  :global {
-
-    .ZupAudio1 {
-      cursor: pointer;
-
-      display: flex;
-      justify-content: center;
-
-      .anticon-upload {
-        font-size: 20px;
-      }
-
-      .ZupAudio1_1 {
-        line-height: 15px;
-        color: #aaa5cb;
-        margin-left: 10px;
-
-        &>p {
-          &:nth-of-type(2) {
-            font-size: 10px;
-            // color: red;
-            opacity: .7;
-          }
-        }
-      }
-    }
-
-    .ZupAudio2 {
-      padding: 0 10px;
-      height: 100%;
-      display: flex;
-      align-items: center;
-
-      .anticon {
-        font-size: 18px;
-        cursor: pointer;
-
-      }
-
-      &>div {
-        height: 100%;
-        line-height: 30px;
-        width: calc(100% - 35px);
-        overflow: hidden;
-        text-overflow: ellipsis;
-        white-space: nowrap;
-      }
-    }
-
-
-  }
-}

+ 0 - 122
src/components/ZupAudio/index.tsx

@@ -1,122 +0,0 @@
-import React, { useCallback, useRef } from 'react'
-import styles from './index.module.scss'
-import { MessageFu } from '@/utils/message'
-import { API_upFile } from '@/store/action/layout'
-import { fileDomInitialFu } from '@/utils/domShow'
-import { UploadOutlined, DeleteOutlined, EyeOutlined } from '@ant-design/icons'
-import store from '@/store'
-import MyPopconfirm from '../MyPopconfirm'
-
-export type ZupAudioType = {
-  fileName: string
-  filePath: string
-}
-
-type Props = {
-  fileInfo: ZupAudioType
-  upDataFu: (info: ZupAudioType) => void
-  delFu: () => void
-  dirCode: string
-  myUrl: string
-  size?: number
-  isLook?: boolean
-}
-
-function ZupAudio({ size = 10, isLook = false, fileInfo, upDataFu, delFu, dirCode, myUrl }: Props) {
-  // 上传 无障碍音频的 点击
-  const handeUpAudio = useCallback(
-    async (e: React.ChangeEvent<HTMLInputElement>) => {
-      if (e.target.files) {
-        // 拿到files信息
-        const filesInfo = e.target.files[0]
-        // console.log("-----", filesInfo);
-
-        // 校验格式
-        const type = ['audio/mpeg']
-        if (!type.includes(filesInfo.type)) {
-          e.target.value = ''
-          return MessageFu.warning(`只支持.mp3格式!`)
-        }
-
-        // 校验大小
-        if (filesInfo.size > size * 1024 * 1024) {
-          e.target.value = ''
-          return MessageFu.warning(`最大支持${size}M!`)
-        }
-        // 创建FormData对象
-        const fd = new FormData()
-
-        fd.append('type', 'audio')
-        fd.append('dirCode', dirCode)
-        fd.append('file', filesInfo)
-        e.target.value = ''
-
-        try {
-          const res = await API_upFile(fd, myUrl)
-          if (res.code === 0) {
-            MessageFu.success('上传成功!')
-            // console.log(res);
-            upDataFu(res.data)
-          }
-          fileDomInitialFu()
-        } catch (error) {
-          fileDomInitialFu()
-        }
-      }
-    },
-    [dirCode, myUrl, size, upDataFu]
-  )
-
-  // 上传附件的ref
-  const myInput = useRef<HTMLInputElement>(null)
-
-  return (
-    <div className={styles.ZupAudio} id='upInputAudioBox' hidden={isLook && !fileInfo.filePath}>
-      {/* 上传无障碍音频 */}
-      <input
-        id='upInputAudio'
-        type='file'
-        accept='.mp3'
-        onChange={e => handeUpAudio(e)}
-        ref={myInput}
-      />
-      {fileInfo.filePath ? (
-        <div className='ZupAudio2'>
-          <div title={fileInfo.fileName}>{fileInfo.fileName}</div>
-          <EyeOutlined
-            title='预览'
-            onClick={() =>
-              store.dispatch({
-                type: 'layout/lookDom',
-                payload: { src: fileInfo.filePath, type: 'audio' }
-              })
-            }
-          />
-
-          {isLook ? null : (
-            <>
-              &nbsp;
-              <MyPopconfirm
-                txtK='删除'
-                onConfirm={delFu}
-                Dom={<DeleteOutlined title='删除' className='ZTbox2X' rev={undefined} />}
-              />
-            </>
-          )}
-        </div>
-      ) : (
-        <div className='ZupAudio1' onClick={() => myInput.current?.click()}>
-          <UploadOutlined />
-          <div className='ZupAudio1_1'>
-            <p>上传无障碍音频</p>
-            <p>支持{size}MB以下mp3格式</p>
-          </div>
-        </div>
-      )}
-    </div>
-  )
-}
-
-const MemoZupAudio = React.memo(ZupAudio)
-
-export default MemoZupAudio

+ 0 - 101
src/components/ZupOne/index.module.scss

@@ -1,101 +0,0 @@
-.ZupOne {
-  width: 100%;
-  height: 100%;
-  position: relative;
-
-  :global {
-
-    .file_upIcon {
-      color: #a6a6a6;
-      border-radius: 3px;
-      cursor: pointer;
-      font-size: 30px;
-      width: 100px;
-      height: 100px;
-      border: 1px dashed #797979;
-      display: flex;
-      justify-content: center;
-      align-items: center;
-
-
-    }
-
-    .file_img {
-      width: 100px;
-      height: 126px;
-      position: relative;
-      margin-top: 10px;
-
-      .file_closeBox {
-        position: absolute;
-        right: -10px;
-        top: -10px;
-        z-index: 99;
-        background-color: rgba(0, 0, 0, 0.8);
-        width: 20px;
-        height: 20px;
-        border-radius: 50%;
-        font-size: 16px;
-        color: #fff;
-        display: flex;
-        justify-content: center;
-        align-items: center;
-      }
-
-
-
-      .file_lookBox {
-        width: 100%;
-        background-color: rgba(0, 0, 0, .6);
-        color: #fff;
-        display: flex;
-        justify-content: space-around;
-
-        &>a {
-          color: #fff !important;
-        }
-
-        font-size: 16px;
-      }
-    }
-
-    .fileInfo {
-      display: flex;
-      align-items: center;
-      font-size: 16px;
-
-      .clearCover {
-        margin-left: 20px;
-        cursor: pointer;
-        font-size: 16px;
-      }
-
-      &>a {
-        color: black;
-      }
-    }
-
-    .fileBoxRow_r_tit {
-      height: 46px;
-      margin-top: 5px;
-      font-size: 14px;
-      color: rgb(126, 124, 124);
-
-
-    }
-
-    .noUpThumb {
-      position: relative;
-      overflow: hidden;
-      opacity: 0;
-      transition: top .2s;
-      color: #ff4d4f;
-      top: -10px;
-    }
-
-    .noUpThumbAc {
-      top: 0;
-      opacity: 1;
-    }
-  }
-}

+ 0 - 286
src/components/ZupOne/index.tsx

@@ -1,286 +0,0 @@
-import React, { useCallback, useMemo, useRef, useState } from 'react'
-import styles from './index.module.scss'
-import ImageLazy from '@/components/ImageLazy'
-import {
-  PlusOutlined,
-  EyeOutlined,
-  CloseOutlined,
-  DownloadOutlined,
-  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'
-import { fileDomInitialFu } from '@/utils/domShow'
-import { API_upFile } from '@/store/action/layout'
-import { forwardRef, useImperativeHandle } from 'react'
-import MyPopconfirm from '../MyPopconfirm'
-
-type MyTypeType = 'thumb' | 'video' | 'audio' | 'model' | 'pdf'
-
-// 这个组件 只处理 上传 一张图片或者 视频 音频 模型 pdf 的情况
-
-type Props = {
-  fileCheck: boolean //有没有点击过确定
-  size: number //上传附件大小(M)
-  dirCode: string //文件的code码
-  myUrl: string //请求地址
-  format: string[] //上传格式 ["image/jpeg", "image/png"] ["video/mp4"] ,application/pdf
-  formatTxt: string //上传图片提示
-  checkTxt: string
-  upTxt: string
-  myType: MyTypeType
-  isLook?: boolean //是不是查看
-  fromData?: any
-  ref: any //当前自己的ref,给父组件调用
-}
-
-function ZupOne(
-  {
-    fileCheck,
-    size,
-    dirCode,
-    myUrl,
-    format,
-    formatTxt,
-    checkTxt,
-    upTxt,
-    myType,
-    isLook = false,
-    fromData
-  }: Props,
-  ref: any
-) {
-  const [fileUrl, setFileUrl] = useState({
-    fileName: '',
-    filePath: '',
-    thumb: ''
-  })
-
-  const myInput = useRef<HTMLInputElement>(null)
-
-  // 上传封面图
-  const handeUpPhoto = useCallback(
-    async (e: React.ChangeEvent<HTMLInputElement>) => {
-      if (e.target.files) {
-        // 拿到files信息
-        const filesInfo = e.target.files[0]
-        // console.log("-----", filesInfo.type);
-
-        // 校验格式
-        const type = format
-
-        if (myType === 'pdf') {
-          if (!filesInfo.type.includes('pdf')) {
-            e.target.value = ''
-            return MessageFu.warning(`只支持${formatTxt}格式!`)
-          }
-        } else {
-          if (!type.includes(filesInfo.type)) {
-            e.target.value = ''
-            return MessageFu.warning(`只支持${formatTxt}格式!`)
-          }
-        }
-
-        // 校验大小
-        if (filesInfo.size > size * 1024 * 1024) {
-          e.target.value = ''
-          return MessageFu.warning(`最大支持${size}M!`)
-        }
-        // 创建FormData对象
-        const fd = new FormData()
-        // 把files添加进FormData对象(‘photo’为后端需要的字段)
-        let myTypeRes: string = myType
-        if (['pdf'].includes(myTypeRes)) myTypeRes = 'doc'
-        fd.append('type', myTypeRes)
-        fd.append('dirCode', dirCode)
-        fd.append('file', filesInfo)
-
-        if (myType === 'thumb') {
-          // 开启压缩图片
-          fd.append('isCompress', 'true')
-        }
-
-        if (fromData) {
-          for (const k in fromData) {
-            if (fromData[k]) fd.append(k, fromData[k])
-          }
-        }
-
-        e.target.value = ''
-
-        try {
-          const res = await API_upFile(fd, myUrl)
-          if (res.code === 0) {
-            MessageFu.success('上传成功!')
-            setFileUrl(res.data)
-          }
-          fileDomInitialFu()
-        } catch (error) {
-          fileDomInitialFu()
-        }
-      }
-    },
-    [dirCode, format, formatTxt, fromData, myType, myUrl, size]
-  )
-
-  // 让父组件调用的 回显 附件 地址
-  const setFileComFileFu = useCallback(
-    (valObj: { fileName: string; filePath: string; thumb: string }) => {
-      setFileUrl(valObj)
-    },
-    []
-  )
-
-  // 让父组件调用的返回 附件 名字和路径
-  const fileComFileResFu = useCallback(() => {
-    return fileUrl
-  }, [fileUrl])
-
-  // 可以让父组件调用子组件的方法
-  useImperativeHandle(ref, () => ({
-    setFileComFileFu,
-    fileComFileResFu
-  }))
-
-  const acceptRes = useMemo(() => {
-    let accept = '.png,.jpg,.jpeg'
-    if (myType === 'video') accept = '.mp4'
-    else if (myType === 'audio') accept = '.mp3'
-    else if (myType === 'model') accept = '.4dage'
-    else if (myType === 'pdf') accept = '.pdf'
-    return accept
-  }, [myType])
-
-  // 点击 预览(除了图片)
-  const lookFileNoImgFu = useCallback(
-    (type: MyTypeType) => {
-      if (type === 'pdf' || type === 'thumb') {
-        // 新窗口打开
-        window.open(baseURL + fileUrl.filePath)
-      } else {
-        store.dispatch({
-          type: 'layout/lookDom',
-          payload: { src: fileUrl.filePath, type }
-        })
-      }
-
-      // if (type === "pdf") {
-      // } else {
-      // }
-    },
-    [fileUrl.filePath]
-  )
-
-  return (
-    <div className={styles.ZupOne}>
-      <input
-        id='upInput'
-        type='file'
-        accept={acceptRes}
-        ref={myInput}
-        onChange={e => handeUpPhoto(e)}
-      />
-      {myType === 'thumb' ? (
-        <div
-          hidden={fileUrl.filePath !== ''}
-          className='file_upIcon'
-          onClick={() => myInput.current?.click()}
-        >
-          <PlusOutlined rev={undefined} />
-        </div>
-      ) : (
-        <Button
-          hidden={fileUrl.filePath !== ''}
-          onClick={() => myInput.current?.click()}
-          icon={<UploadOutlined rev={undefined} />}
-        >
-          上传
-        </Button>
-      )}
-
-      {/* 为图片的情况-------------- */}
-      {myType === 'thumb' ? (
-        <div className='file_img' hidden={fileUrl.filePath === ''}>
-          {fileUrl ? (
-            <ImageLazy
-              width={100}
-              height={100}
-              src={fileUrl.thumb || fileUrl.filePath}
-              srcBig={fileUrl.filePath || fileUrl.thumb || ''}
-              noLook
-            />
-          ) : null}
-
-          {/* 删除 */}
-          <div className='file_closeBox' hidden={isLook}>
-            <MyPopconfirm
-              txtK='删除'
-              onConfirm={() => setFileUrl({ fileName: '', filePath: '', thumb: '' })}
-              Dom={<CloseOutlined rev={undefined} />}
-            />
-          </div>
-
-          {/* 预览 下载 */}
-          <div className='file_lookBox'>
-            <EyeOutlined
-              onClick={() =>
-                store.dispatch({
-                  type: 'layout/lookBigImg',
-                  payload: { url: baseURL + fileUrl.filePath, show: true }
-                })
-              }
-              rev={undefined}
-            />
-            <a href={baseURL + fileUrl.filePath} download target='_blank' rel='noreferrer'>
-              <DownloadOutlined rev={undefined} />
-            </a>
-          </div>
-        </div>
-      ) : fileUrl.filePath ? (
-        <div className='fileInfo'>
-          <div className='upSuccTxt'>{fileUrl.fileName}</div>
-          {/* 视频预览 */}
-          <div
-            className='clearCover'
-            hidden={!fileUrl.filePath}
-            onClick={() => lookFileNoImgFu(myType)}
-          >
-            <EyeOutlined rev={undefined} />
-          </div>
-          {/* 视频下载 */}
-          <a
-            href={baseURL + fileUrl.filePath}
-            download
-            target='_blank'
-            className='clearCover'
-            rel='noreferrer'
-          >
-            <DownloadOutlined rev={undefined} />
-          </a>
-          {/* 视频删除 */}
-
-          <MyPopconfirm
-            txtK='删除'
-            onConfirm={() => setFileUrl({ fileName: '', filePath: '', thumb: '' })}
-            Dom={<CloseOutlined className='clearCover' rev={undefined} />}
-          />
-        </div>
-      ) : null}
-
-      <div className='fileBoxRow_r_tit' hidden={isLook}>
-        格式要求:支持{formatTxt}格式;最大支持{size}M。{upTxt}
-        <br />
-        <div
-          className={classNames('noUpThumb', !fileUrl.filePath && fileCheck ? 'noUpThumbAc' : '')}
-        >
-          {checkTxt}
-        </div>
-      </div>
-    </div>
-  )
-}
-
-export default forwardRef(ZupOne)

+ 0 - 215
src/components/ZupTypes/index.module.scss

@@ -1,215 +0,0 @@
-.ZupTypes {
-  padding-top: 3px;
-
-  :global {
-    .ZTboxTit {
-      margin-left: 10px;
-      font-size: 14px;
-      color: rgb(126, 124, 124);
-      position: relative;
-      top: 4px;
-    }
-
-    .ZTbox {
-      margin-top: 20px;
-      display: flex;
-
-      .ZTbox1 {
-        position: relative;
-        top: 3px;
-        width: 60px;
-
-        & > span {
-          color: #ff4d4f;
-        }
-      }
-
-      .ZTbox2 {
-        width: calc(100% - 60px);
-        margin-left: 5px;
-        display: flex;
-        font-size: 16px;
-        align-items: center;
-
-        .ZTbox2Look {
-          margin-left: 20px;
-          cursor: pointer;
-        }
-
-        .ZTbox2Down {
-          margin-left: 15px;
-          color: black;
-        }
-
-        .ZTbox2X {
-          cursor: pointer;
-          margin-left: 15px;
-        }
-      }
-    }
-
-    // 图片
-    .ZTboxImgMain {
-      margin-top: 20px;
-
-      .ZTboxImgBox {
-        display: flex;
-
-        .ZTbox1 {
-          position: relative;
-          top: 3px;
-          width: 60px;
-
-          & > span {
-            color: #ff4d4f;
-          }
-        }
-
-        .ZTbox1Img {
-          width: calc(100% - 60px);
-          display: flex;
-          flex-wrap: wrap;
-
-          .ZTbox1ImgIcon {
-            margin-right: 20px;
-            color: #a6a6a6;
-            border-radius: 3px;
-            cursor: pointer;
-            font-size: 30px;
-            width: 100px;
-            height: 100px;
-            border: 1px dashed #797979;
-            display: flex;
-            justify-content: center;
-            align-items: center;
-          }
-
-          .ZTbox1ImgRow {
-            // content-visibility:auto;
-            margin-right: 20px;
-            width: 100px;
-            height: 125px;
-            position: relative;
-            margin-bottom: 20px;
-            cursor: move;
-            position: relative;
-
-            // 第一张作为封面
-            .ZTbox1ImgRowCover {
-              font-size: 12px;
-              line-height: 22px;
-              position: absolute;
-              left: 0;
-              top: 0;
-              width: 100%;
-              height: 24px;
-              background-color: rgba(0, 0, 0, 0.8);
-              color: #fff;
-              text-align: center;
-              pointer-events: none;
-            }
-
-            // 修改图片名字
-            .ZTbox1ImgRowName {
-              font-size: 12px;
-              line-height: 22px;
-              position: absolute;
-              left: 0;
-              bottom: 25px;
-              width: 100%;
-              cursor: pointer;
-              height: 24px;
-              padding: 0 3px;
-              background-color: rgba(0, 0, 0, 0.8);
-              color: #fff;
-              text-align: center;
-              overflow: hidden;
-              text-overflow: ellipsis;
-              white-space: nowrap;
-
-              &:hover {
-                color: var(--themeColor);
-              }
-            }
-
-            .ZTbox1ImgRowIcon {
-              width: 100%;
-              background-color: rgba(0, 0, 0, 0.6);
-              color: #fff;
-              display: flex;
-              justify-content: space-around;
-              font-size: 16px;
-
-              a {
-                color: #fff !important;
-              }
-            }
-
-            .ZTbox1ImgRowX {
-              cursor: pointer;
-              position: absolute;
-              right: -10px;
-              top: -10px;
-              z-index: 99;
-              background-color: rgba(0, 0, 0, 0.8);
-              width: 20px;
-              height: 20px;
-              border-radius: 50%;
-              font-size: 16px;
-              color: #fff;
-              display: flex;
-              justify-content: center;
-              align-items: center;
-            }
-          }
-        }
-      }
-    }
-
-    .ZcheckTxt {
-      position: relative;
-      overflow: hidden;
-      opacity: 0;
-      transition: top 0.2s;
-      color: #ff4d4f;
-      top: -10px;
-    }
-
-    .ZcheckTxtAc {
-      top: 2px;
-      opacity: 1;
-    }
-  }
-}
-
-// 查看情况
-.ZupTypesLook {
-  :global {
-    .ZTbox1ImgRowName {
-      cursor: default !important;
-      color: #fff !important;
-    }
-
-    .ZTbox1ImgRow {
-      cursor: default !important;
-    }
-
-    .ZTbox1ImgRowX {
-      display: none !important;
-    }
-  }
-}
-
-// 修改图片名字的弹窗
-.ZupTypesMo {
-  :global {
-    .ant-modal-close {
-      display: none;
-    }
-
-    .ZupTypesMoBtn {
-      margin-top: 24px;
-      text-align: center;
-    }
-  }
-}

+ 0 - 627
src/components/ZupTypes/index.tsx

@@ -1,627 +0,0 @@
-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,
-  UploadOutlined,
-  CloseOutlined,
-  DownloadOutlined,
-  EyeOutlined
-} from '@ant-design/icons'
-import { MessageFu } from '@/utils/message'
-import { API_upFile } from '@/store/action/layout'
-import { fileDomInitialFu } from '@/utils/domShow'
-import store from '@/store'
-import ImageLazy from '../ImageLazy'
-import classNames from 'classnames'
-import MyPopconfirm from '../MyPopconfirm'
-// import { A2_APIchangeImgName } from "@/store/action/A2exhibition";
-
-export type FileListType = {
-  fileName: string
-  thumb?: string
-  filePath: string
-  id: number
-  type: 'model' | 'img' | 'audio' | 'video'
-  imgName: string
-}
-
-type Props = {
-  ref: any //当前自己的ref,给父组件调用
-  selecFlag: string //筛选的字符串 模型/图片/音频/视频
-  fileCheck: boolean //有没有点击过确定
-  dirCode: string //文件的code码
-  myUrl: string //请求地址
-  isLook?: boolean //是不是查看
-  modelSize?: number //模型文件大小限制
-  imgSize?: number //图片大小限制
-  imgLength?: number //图片数量限制
-  audioSize?: number //音频大小限制
-  videoSize?: number //视频大小限制
-  videoTit?: string //视频上传的提示语
-  isTypeShow?: boolean //默认就选中(只有一个类型的时候)
-  isUpName?: boolean //是否能修改图片名字
-  lastImgTxt?: string //加载最后面的上传提示
-  oneIsCover?: boolean //是否将第一张作为封面
-  multipleImg?: boolean // 新增参数:是否支持多张图片同时上传
-}
-
-function ZupTypes(
-  {
-    selecFlag,
-    fileCheck,
-    dirCode,
-    myUrl,
-    isLook = false,
-    modelSize = 500,
-    imgSize = 5,
-    imgLength = 9,
-    audioSize = 10,
-    videoSize = 500,
-    videoTit = '',
-    isTypeShow = false,
-    isUpName = false,
-    lastImgTxt = '',
-    oneIsCover = false,
-    multipleImg = false
-  }: Props,
-  ref: any
-) {
-  // 筛选
-  const [typeCheck, setTypeCheck] = useState<string[]>([])
-
-  // 筛选数组
-  const typeCheckArr = useMemo(() => {
-    const arr = [
-      { label: '模型', value: 'model' },
-      { label: '图片', value: 'img' },
-      { label: '音频', value: 'audio' },
-      { label: '视频', value: 'video' }
-    ]
-
-    const arrRes = arr.filter(v => selecFlag.includes(v.label))
-    if (arrRes.length <= 1 && isTypeShow) {
-      setTypeCheck([arrRes[0].value])
-      // 默认就选中(只有一个类型的时候)
-    }
-
-    return arrRes
-  }, [isTypeShow, selecFlag])
-
-  // 上传附件的信息
-  const [fileList, setFileList] = useState({
-    model: {} as FileListType,
-    img: [] as FileListType[],
-    audio: {} as FileListType,
-    video: {} as FileListType
-  })
-
-  // 附件信息的校验,不满足返回 true
-  const fileCheckFu = useMemo(() => {
-    let flag = false
-    if (typeCheck.length === 0) flag = true
-    if (typeCheck.includes('model') && !fileList.model.id) flag = true
-    if (typeCheck.includes('img') && fileList.img.length === 0) flag = true
-    if (typeCheck.includes('audio') && !fileList.audio.id) flag = true
-    if (typeCheck.includes('video') && !fileList.video.id) flag = true
-    return flag
-  }, [fileList, typeCheck])
-
-  // 点击上传附件按钮
-  const myInput = useRef<HTMLInputElement>(null)
-
-  const [fileOneType, setFileOneType] = useState('')
-
-  useEffect(() => {
-    if (fileOneType) myInput.current?.click()
-  }, [fileOneType])
-
-  const upFileFu = useCallback((type: string) => {
-    setFileOneType('')
-    window.setTimeout(() => {
-      setFileOneType(type)
-    }, 100)
-  }, [])
-
-  // 上传附件的处理函数
-  const handeUpPhoto2 = useCallback(
-    async (e: React.ChangeEvent<HTMLInputElement>) => {
-      if (!e.target.files || e.target.files.length === 0) return
-
-      // 新增:多选模式下获取所有文件 [2,6](@ref)
-      let files =
-        multipleImg && fileOneType === 'img' ? Array.from(e.target.files) : [e.target.files[0]]
-
-      // 新增:检查图片数量限制 [4](@ref)
-      if (fileOneType === 'img' && multipleImg) {
-        const remainingSlots = imgLength - fileList.img.length
-        if (files.length > remainingSlots) {
-          MessageFu.warning(`最多还能上传${remainingSlots}张图片`)
-          files = files.slice(0, remainingSlots)
-        }
-      }
-
-      // 批量处理文件 [4](@ref)
-      for (const file of files) {
-        // 原有的校验逻辑(格式、大小等)保持不变...
-        let anType = ['image/jpeg', 'image/png']
-        let anTit1 = '只支持png、jpg格式!'
-        let anTit2 = `最大支持${imgSize}M!`
-        let anSize = imgSize * 1024 * 1024
-
-        if (fileOneType === 'audio') {
-          anType = ['audio/mpeg']
-          anTit1 = '只支持mp3格式!'
-          anTit2 = `最大支持${audioSize}M!`
-          anSize = audioSize * 1024 * 1024
-        } else if (fileOneType === 'video') {
-          anType = ['video/mp4']
-          anTit1 = '只支持mp4格式!'
-          anTit2 = `最大支持${videoSize}M!`
-          anSize = videoSize * 1024 * 1024
-        } else if (fileOneType === 'model') {
-          anType = ['']
-          anTit1 = '只支持4dage格式!'
-          anTit2 = `最大支持${modelSize}M!`
-          anSize = modelSize * 1024 * 1024
-        }
-
-        // 校验格式
-        if (fileOneType !== 'model') {
-          if (!anType.includes(file.type)) {
-            e.target.value = ''
-            return MessageFu.warning(anTit1)
-          }
-        } else {
-          if (!file.name.includes('.4dage')) {
-            e.target.value = ''
-            return MessageFu.warning(anTit1)
-          }
-        }
-
-        // 校验大小
-        if (file.size > anSize) {
-          e.target.value = ''
-          return MessageFu.warning(anTit2)
-        }
-        // 创建FormData
-        const fd = new FormData()
-        fd.append('type', fileOneType)
-        fd.append('dirCode', dirCode)
-        fd.append('isDb', 'true')
-        //初始图片 fileName为:未命名
-        if (isUpName) {
-          fd.append('isDefaultName', 'false')
-        }
-
-        fd.append('file', file)
-
-        if (fileOneType === 'img' && file.size > 1 * 1024 * 1024) {
-          // 开启压缩图片
-          fd.append('isCompress', 'true')
-        }
-
-        e.target.value = ''
-
-        try {
-          const res = await API_upFile(fd, myUrl)
-          if (res.code === 0) {
-            MessageFu.success(
-              `上传成功${files.length > 1 ? `(${files.indexOf(file) + 1}/${files.length})` : ''}`
-            )
-
-            // 更新状态
-            if (fileOneType === 'img') {
-              setFileList(prev => ({
-                ...prev,
-                img: [...prev.img, { ...res.data, imgName: '未命名' }]
-              }))
-            } else {
-              setFileList(prev => ({ ...prev, [fileOneType]: res.data }))
-            }
-            fileDomInitialFu()
-          }
-        } catch (error) {
-          // 错误处理
-          fileDomInitialFu()
-        }
-      }
-    },
-    [
-      audioSize,
-      dirCode,
-      fileList.img.length,
-      fileOneType,
-      imgLength,
-      imgSize,
-      isUpName,
-      modelSize,
-      multipleImg,
-      myUrl,
-      videoSize
-    ]
-  )
-
-  // 附件图片的拖动
-  const [dragImg, setDragImg] = useState<any>(null)
-
-  const handleDragOver = useCallback(
-    (e: React.DragEvent<HTMLDivElement>, item: FileListType) => {
-      if (isLook) return
-      e.dataTransfer.dropEffect = 'move'
-    },
-    [isLook]
-  )
-
-  const handleDragEnter = useCallback(
-    (e: React.DragEvent<HTMLDivElement>, item: FileListType) => {
-      if (isLook) return
-
-      e.dataTransfer.effectAllowed = 'move'
-      if (item === dragImg) return
-      const newItems = [...fileList.img] //拷贝一份数据进行交换操作。
-      const src = newItems.indexOf(dragImg) //获取数组下标
-      const dst = newItems.indexOf(item)
-      newItems.splice(dst, 0, ...newItems.splice(src, 1)) //交换位置
-      setFileList({ ...fileList, img: newItems })
-    },
-    [dragImg, fileList, isLook]
-  )
-
-  // 删除某一张图片
-  const delImgListFu = useCallback(
-    (id: number) => {
-      const newItems = fileList.img.filter(v => v.id !== id)
-      setFileList({ ...fileList, img: newItems })
-    },
-    [fileList]
-  )
-
-  // 模型 音频 视频 的 dom
-  const resOneDivDom = useCallback(
-    (type: 'model' | 'audio' | 'video') => {
-      const dom = (
-        <div className='ZTbox' hidden={!typeCheck.includes(type)}>
-          <div className='ZTbox1'>
-            <span> </span>
-            {type === 'model' ? '模型' : type === 'audio' ? '音频' : '视频'}:
-          </div>
-          {fileList[type].id ? (
-            <div className='ZTbox2'>
-              <div className='ZTbox2Name'>{fileList[type].fileName}</div>
-
-              <div
-                className='ZTbox2Look'
-                onClick={() =>
-                  store.dispatch({
-                    type: 'layout/lookDom',
-                    payload: { src: fileList[type].filePath, type }
-                  })
-                }
-              >
-                <EyeOutlined rev={undefined} />
-              </div>
-
-              <a
-                href={baseURL + fileList[type].filePath}
-                download
-                target='_blank'
-                className='ZTbox2Down'
-                rel='noreferrer'
-              >
-                <DownloadOutlined rev={undefined} />
-              </a>
-
-              <MyPopconfirm
-                txtK='删除'
-                onConfirm={() => setFileList({ ...fileList, [type]: {} as FileListType })}
-                Dom={<CloseCircleOutlined className='ZTbox2X' rev={undefined} />}
-              />
-            </div>
-          ) : (
-            <>
-              <Button onClick={() => upFileFu(type)} icon={<UploadOutlined rev={undefined} />}>
-                上传
-              </Button>
-
-              <div className='ZTboxTit'>
-                {type === 'model'
-                  ? `仅支持4dage格式的模型文件,大小不能超过${modelSize}M。`
-                  : type === 'audio'
-                  ? `仅支持mp3格式的音频文件,大小不得超过${audioSize}MB。`
-                  : `仅支持mp4格式的视频文件,大小不得超过${videoSize}MB。${videoTit}`}
-              </div>
-            </>
-          )}
-        </div>
-      )
-      return dom
-    },
-    [audioSize, fileList, modelSize, typeCheck, upFileFu, videoSize, videoTit]
-  )
-
-  // ------------让父组件调用的 回显
-  const setFileComFileFu = useCallback((info: any) => {
-    if (info.type) setTypeCheck(info.type.split(','))
-
-    if (info.fileList && info.fileList.length) {
-      const data: FileListType[] = info.fileList
-      const obj = {
-        model: {} as FileListType,
-        img: [] as FileListType[],
-        audio: {} as FileListType,
-        video: {} as FileListType
-      }
-
-      data.forEach(v => {
-        if (v.type === 'img') {
-          obj.img.push({ ...v, imgName: v.fileName })
-        } else obj[v.type!] = v
-      })
-      setFileList(obj)
-    }
-  }, [])
-
-  // --------------让父组件调用的返回 附件 信息
-  const fileComFileResFu = useCallback(() => {
-    let coverUrl = ''
-    let coverUrlBig = ''
-    const fileIds = []
-    if (fileList.model.id && typeCheck.includes('model')) fileIds.push(fileList.model.id)
-    if (fileList.audio.id && typeCheck.includes('audio')) fileIds.push(fileList.audio.id)
-    if (fileList.video.id && typeCheck.includes('video')) fileIds.push(fileList.video.id)
-    if (typeCheck.includes('img')) {
-      fileList.img.forEach((v, i) => {
-        if (v.id) {
-          fileIds.push(v.id)
-          if (oneIsCover && i === 0) {
-            // 返回 第一张图的url 作为封面
-            coverUrl = v.thumb || v.filePath
-            coverUrlBig = v.filePath || v.thumb!
-          }
-        }
-      })
-    }
-    return {
-      sonType: typeCheck,
-      sonFileIds: fileIds,
-      sonIsOk: fileCheckFu,
-      coverUrl,
-      coverUrlBig
-    }
-  }, [
-    fileCheckFu,
-    fileList.audio.id,
-    fileList.img,
-    fileList.model.id,
-    fileList.video.id,
-    oneIsCover,
-    typeCheck
-  ])
-
-  // 可以让父组件调用子组件的方法
-  useImperativeHandle(ref, () => ({
-    setFileComFileFu,
-    fileComFileResFu
-  }))
-
-  // 修改图片名称
-  const [isNameChange, setIsNameChange] = useState({
-    id: 0,
-    oldName: '',
-    newName: ''
-  })
-
-  // 关闭弹窗
-  const isNameChangeXFu = useCallback(() => {
-    setIsNameChange({ id: 0, oldName: '', newName: '' })
-  }, [])
-
-  // 点击图片名字-出来弹窗
-  const isNameChangeFu = useCallback(
-    (item: FileListType) => {
-      if (isLook) return
-      setIsNameChange({ id: item.id, oldName: item.imgName, newName: '' })
-    },
-    [isLook]
-  )
-
-  // 修改完这点击 确定修改
-  // const isNameChangeOkFu = useCallback(async () => {
-  //   if (!isNameChange.newName) return MessageFu.warning("图片名不能为空!");
-
-  //   const res = await A2_APIchangeImgName({
-  //     id: isNameChange.id,
-  //     fileName: isNameChange.newName,
-  //   });
-
-  //   if (res.code === 0) {
-  //     MessageFu.success("修改图片名成功!");
-  //     setFileList({
-  //       ...fileList,
-  //       img: fileList.img.map((v) => ({
-  //         ...v,
-  //         imgName: v.id === isNameChange.id ? isNameChange.newName : v.imgName,
-  //       })),
-  //     });
-  //     isNameChangeXFu();
-  //   }
-  // }, [fileList, isNameChange.id, isNameChange.newName, isNameChangeXFu]);
-  //
-
-  return (
-    <div className={classNames(styles.ZupTypes, isLook ? styles.ZupTypesLook : '')}>
-      <input
-        id='upInput'
-        type='file'
-        accept={
-          fileOneType === 'img'
-            ? '.png,.jpg,.jpeg'
-            : fileOneType === 'audio'
-            ? '.mp3'
-            : fileOneType === 'model'
-            ? '.4dage'
-            : '.mp4'
-        }
-        ref={myInput}
-        onChange={e => handeUpPhoto2(e)}
-        multiple={fileOneType === 'img' && multipleImg}
-      />
-      <div hidden={isTypeShow}>
-        <Checkbox.Group
-          options={typeCheckArr}
-          value={typeCheck}
-          onChange={e => setTypeCheck(e as string[])}
-        />
-      </div>
-
-      {/* -----------模型 */}
-      {resOneDivDom('model')}
-
-      {/* -----------图片 */}
-      <div className='ZTboxImgMain' hidden={!typeCheck.includes('img')}>
-        <div className='ZTboxImgBox'>
-          <div className='ZTbox1' hidden={isTypeShow}>
-            <span> </span> 图片:
-          </div>
-
-          <div className='ZTbox1Img' style={{ width: isTypeShow ? '100%' : '' }}>
-            <div
-              hidden={(!!fileList.img.length && fileList.img.length >= imgLength) || isLook}
-              className='ZTbox1ImgIcon'
-              onClick={() => upFileFu('img')}
-            >
-              <PlusOutlined rev={undefined} />
-            </div>
-            {fileList.img.map((v, i) => (
-              <div
-                className='ZTbox1ImgRow'
-                key={v.id}
-                draggable='true'
-                onDragStart={() => setDragImg(v)}
-                onDragOver={e => handleDragOver(e, v)}
-                onDragEnter={e => handleDragEnter(e, v)}
-                onDragEnd={() => setDragImg(null)}
-              >
-                {v.thumb || v.filePath ? (
-                  <ImageLazy noLook={true} width={100} height={100} src={v.thumb || v.filePath} />
-                ) : null}
-
-                {oneIsCover && i === 0 ? <div className='ZTbox1ImgRowCover'>封面</div> : null}
-
-                {/* 修改图片名字 */}
-                {isUpName ? (
-                  <div
-                    title={v.imgName}
-                    className='ZTbox1ImgRowName'
-                    onClick={() => isNameChangeFu(v)}
-                  >
-                    {v.imgName}
-                  </div>
-                ) : null}
-
-                <div className='ZTbox1ImgRowIcon'>
-                  <EyeOutlined
-                    onClick={() =>
-                      store.dispatch({
-                        type: 'layout/lookBigImg',
-                        payload: {
-                          url: baseURL + v.filePath,
-                          show: true
-                        }
-                      })
-                    }
-                    rev={undefined}
-                  />
-                  <a href={baseURL + v.filePath} download target='_blank' rel='noreferrer'>
-                    <DownloadOutlined rev={undefined} />
-                  </a>
-                </div>
-
-                <MyPopconfirm
-                  txtK='删除'
-                  onConfirm={() => delImgListFu(v.id!)}
-                  Dom={<CloseOutlined className='ZTbox1ImgRowX' rev={undefined} />}
-                />
-              </div>
-            ))}
-          </div>
-        </div>
-
-        <div className='ZTboxTit' hidden={isLook}>
-          {fileList.img.length && fileList.img.length >= 2 ? (
-            <>
-              按住鼠标可拖动图片调整顺序。
-              <br />
-            </>
-          ) : null}
-          {oneIsCover ? '第一张为封面图;' : ''} 支持png、jpg的图片格式;最大支持{imgSize}
-          M;最多支持{imgLength}张。{multipleImg ? '按住Ctrl可一次性选择多张图片上传' : ''}
-          {lastImgTxt}
-        </div>
-      </div>
-
-      {/* -----------音频 */}
-      {resOneDivDom('audio')}
-
-      {/* -----------视频 */}
-      {resOneDivDom('video')}
-
-      {/* 最后的提示 */}
-      <div className={classNames('ZcheckTxt', fileCheck && fileCheckFu ? 'ZcheckTxtAc' : '')}>
-        请最少上传一张图片!
-      </div>
-
-      {/* 点击修改名字出来的弹窗 */}
-      {isNameChange.id ? (
-        <Modal
-          wrapClassName={styles.ZupTypesMo}
-          open={true}
-          title='修改展品图片名称'
-          footer={
-            [] // 设置footer为空,去掉 取消 确定默认按钮
-          }
-        >
-          <br />
-          <div className='ZupTypesMoRow'>
-            <strong>当前名:</strong>
-            {isNameChange.oldName}
-          </div>
-          <div className='ZupTypesMoRow'>
-            <br />
-            <strong>修改为:</strong>
-            <Input
-              style={{ width: 400 }}
-              placeholder='请输入图片名'
-              maxLength={50}
-              showCount
-              value={isNameChange.newName}
-              onChange={e => {
-                setIsNameChange({
-                  ...isNameChange,
-                  newName: e.target.value.replace(/\s+/g, '')
-                })
-              }}
-            />
-          </div>
-
-          <div className='ZupTypesMoBtn'>
-            <Button onClick={isNameChangeXFu}>取消</Button>
-            &emsp;
-            <Button
-              type='primary'
-              //  onClick={isNameChangeOkFu}
-            >
-              修改
-            </Button>
-          </div>
-        </Modal>
-      ) : null}
-    </div>
-  )
-}
-
-export default forwardRef(ZupTypes)

+ 0 - 95
src/components/ZupVideos/index.module.scss

@@ -1,95 +0,0 @@
-.ZupVideos {
-  width: 100%;
-
-  :global {
-    .zVmain {
-      width: 100%;
-      display: flex;
-      flex-wrap: wrap;
-
-      .file_upIcon {
-        color: #a6a6a6;
-        border-radius: 3px;
-        cursor: pointer;
-        font-size: 30px;
-        width: 100px;
-        height: 100px;
-        border: 1px dashed #797979;
-        display: flex;
-        justify-content: center;
-        align-items: center;
-        margin-right: 20px;
-      }
-
-      .zVRow {
-        margin-right: 20px;
-        margin-bottom: 10px;
-
-        .zVRow1 {
-          display: flex;
-          position: relative;
-
-          .zVRow1V {
-            width: 100px;
-            height: 100px;
-            border-radius: 3px;
-
-            video {
-              width: 100%;
-              height: 100%;
-              object-fit: cover;
-            }
-          }
-
-          .zVRow1I {
-            position: absolute;
-            top: 0;
-            right: 0px;
-            height: 100%;
-            display: flex;
-            flex-direction: column;
-            justify-content: space-around;
-            align-items: center;
-            background-color: rgba(0, 0, 0, 0.6);
-            color: #fff;
-            padding: 0 5px;
-            a {
-              color: #fff !important;
-            }
-          }
-        }
-
-        .zVRow2 {
-          margin-top: 3px;
-          font-size: 14px;
-          text-align: center;
-          width: 100px;
-          overflow: hidden;
-          text-overflow: ellipsis;
-          white-space: nowrap;
-        }
-      }
-    }
-
-    .fileBoxRow_r_tit {
-      height: 46px;
-      margin-top: 5px;
-      font-size: 14px;
-      color: rgb(126, 124, 124);
-    }
-
-    .noUpThumb {
-      position: relative;
-      overflow: hidden;
-      opacity: 0;
-      transition: top 0.2s;
-      color: #ff4d4f;
-      top: -10px;
-    }
-
-    .noUpThumbAc {
-      top: 0;
-      opacity: 1;
-    }
-  }
-}

+ 0 - 193
src/components/ZupVideos/index.tsx

@@ -1,193 +0,0 @@
-import React, { useCallback, useRef, useState } from 'react'
-import styles from './index.module.scss'
-import { forwardRef, useImperativeHandle } from 'react'
-import { FileListType } from '../ZupTypes'
-import { MessageFu } from '@/utils/message'
-import { API_upFile } from '@/store/action/layout'
-import { fileDomInitialFu } from '@/utils/domShow'
-import { PlusOutlined, EyeOutlined, CloseOutlined, DownloadOutlined } from '@ant-design/icons'
-import classNames from 'classnames'
-import { baseURL } from '@/utils/http'
-import store from '@/store'
-import MyPopconfirm from '../MyPopconfirm'
-
-type Props = {
-  size: number //视频大小
-  fileNum: number //数量限制
-  dirCode: string //文件的code码
-  myUrl: string //请求地址
-  fileCheck?: boolean //是否检验
-  typeArr?: string[] //上传格式 ['mp4','mov','avi','wmv']
-  checkTxt?: string
-  upTxt?: string
-  isLook?: boolean //是不是查看
-  fromData?: any
-  ref: any //当前自己的ref,给父组件调用
-}
-
-function ZupVideos(
-  {
-    size,
-    fileNum,
-    dirCode,
-    myUrl,
-    fileCheck = false,
-    typeArr = ['mp4', 'mov', 'avi', 'wmv'],
-    checkTxt = '请上传视频!',
-    upTxt = '',
-    isLook = false,
-    fromData
-  }: Props,
-  ref: any
-) {
-  const [fileList, setFileList] = useState<FileListType[]>([])
-
-  // 上传
-  const handeUpPhoto = useCallback(
-    async (e: React.ChangeEvent<HTMLInputElement>) => {
-      if (e.target.files) {
-        // 拿到files信息
-        const filesInfo = e.target.files[0]
-        // console.log('-----', filesInfo.name)
-
-        const fileNameArr = filesInfo.name.split('.')
-        const fileNameLast = fileNameArr[fileNameArr.length - 1]
-
-        // 校验格式
-        if (!typeArr.includes(fileNameLast.toLowerCase())) {
-          e.target.value = ''
-          return MessageFu.warning(`只支持${typeArr.join('/')}格式`)
-        }
-
-        // 校验大小
-        if (filesInfo.size > size * 1024 * 1024) {
-          e.target.value = ''
-          return MessageFu.warning(`最大支持${size}M!`)
-        }
-        // 创建FormData对象
-        const fd = new FormData()
-
-        fd.append('type', 'video')
-        fd.append('isDb', 'true')
-        fd.append('dirCode', dirCode)
-        fd.append('file', filesInfo)
-
-        if (fromData) {
-          for (const k in fromData) {
-            if (fromData[k]) fd.append(k, fromData[k])
-          }
-        }
-
-        e.target.value = ''
-
-        try {
-          const res = await API_upFile(fd, myUrl)
-          if (res.code === 0) {
-            MessageFu.success('上传成功!')
-            setFileList([...fileList, res.data])
-            // console.log(res);
-          }
-          fileDomInitialFu()
-        } catch (error) {
-          fileDomInitialFu()
-        }
-      }
-    },
-    [dirCode, fileList, fromData, myUrl, size, typeArr]
-  )
-
-  // 让父组件调用的 回显 附件 地址
-  const setFileComFileFu = useCallback((valList: FileListType[]) => {
-    setFileList(valList)
-  }, [])
-
-  // 让父组件调用的返回 附件 名字和路径
-  const fileComFileResFu = useCallback(() => {
-    return fileList
-  }, [fileList])
-
-  // 可以让父组件调用子组件的方法
-  useImperativeHandle(ref, () => ({
-    setFileComFileFu,
-    fileComFileResFu
-  }))
-
-  const myInput = useRef<HTMLInputElement>(null)
-
-  // 点击预览
-  const lookFileFu = useCallback((file: string) => {
-    store.dispatch({
-      type: 'layout/lookDom',
-      payload: { src: file, type: 'video' }
-    })
-  }, [])
-
-  return (
-    <div className={styles.ZupVideos}>
-      <input
-        id='upInput'
-        type='file'
-        accept={typeArr.map(v => `.${v}`).join(',')}
-        ref={myInput}
-        onChange={e => handeUpPhoto(e)}
-      />
-
-      <div hidden={!(isLook && fileList.length <= 0)}>(空)</div>
-
-      <div className='zVmain'>
-        <div
-          hidden={fileList.length >= fileNum || isLook}
-          className='file_upIcon'
-          onClick={() => myInput.current?.click()}
-        >
-          <PlusOutlined />
-        </div>
-
-        {fileList.map(v => (
-          <div className='zVRow' key={v.id}>
-            <div className='zVRow1'>
-              <div className='zVRow1V' title={v.fileName}>
-                <video src={baseURL + v.filePath}></video>
-              </div>
-              <div className='zVRow1I'>
-                {/* 视频预览 */}
-                <EyeOutlined onClick={() => lookFileFu(v.filePath)} />
-                {/* 视频下载 */}
-                <a href={baseURL + v.filePath} download target='_blank' rel='noreferrer'>
-                  <DownloadOutlined />
-                </a>
-                {/* 视频删除 */}
-
-                {isLook ? null : (
-                  <MyPopconfirm
-                    txtK='删除'
-                    onConfirm={() => setFileList(fileList.filter(c => c.id !== v.id))}
-                    Dom={<CloseOutlined />}
-                  />
-                )}
-              </div>
-            </div>
-            <div className='zVRow2' title={v.fileName}>
-              {v.fileName}
-            </div>
-          </div>
-        ))}
-      </div>
-
-      <div className='fileBoxRow_r_tit' hidden={isLook}>
-        格式要求:支持{typeArr.join('/')}格式,最大支持{size}M{upTxt}
-        <br />
-        <div
-          className={classNames(
-            'noUpThumb',
-            fileList.length <= 0 && fileCheck ? 'noUpThumbAc' : ''
-          )}
-        >
-          {checkTxt}
-        </div>
-      </div>
-    </div>
-  )
-}
-
-export default forwardRef(ZupVideos)

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

@@ -23,13 +23,6 @@ export type RouterType = {
   son: RouterTypeRow[]
 }[]
 
-export type FileImgListType = {
-  id: number
-  fileName: string
-  filePath: string
-  type: 'img' | 'video' | 'doc'
-}
-
 const tabLeftArr: RouterType = [
   {
     id: 1,

+ 10 - 1
src/pages/Zother/EditTop/index.tsx

@@ -7,6 +7,7 @@ import { Button, Cascader, DatePicker, Input } from 'antd'
 import classNames from 'classnames'
 import TextArea from 'antd/es/input/TextArea'
 import { useInfo } from '../InfoContext'
+import Z3upFiles from '@/components/Z3upFiles'
 
 const pageKeyTxtObj = {
   1: '新增',
@@ -163,7 +164,15 @@ function EditTop({ rowArr, pageTxt, APIobj }: Props) {
             {/* 附件 */}
             <div className='Edtop1row Edtop1rowFull'>
               <div className='Edtop1ll'>附件:</div>
-              <div className='Edtop1rr'></div>
+              <div className='Edtop1rr'>
+                <Z3upFiles
+                  moduleId={info.id}
+                  isLook={['3', '4'].includes(key)}
+                  fileCheck={false}
+                  dirCode='register'
+                  myUrl='cms/order/register/upload'
+                />
+              </div>
             </div>
           </div>
         </>

+ 11 - 4
src/pages/Zother/InfoContext.tsx

@@ -3,7 +3,7 @@ import { Typetable } from './data'
 
 type InfoContextValue = {
   info: Typetable
-  setInfoFu: (info: Typetable) => void
+  setInfoFu: (info: Typetable | ((prevInfo: Typetable) => Typetable)) => void
 }
 
 type Props = {
@@ -15,9 +15,16 @@ const InfoContext = createContext<InfoContextValue | undefined>(undefined)
 export function InfoProvider({ children }: Props) {
   const [info, setInfo] = useState({} as Typetable)
 
-  const setInfoFu = useCallback((newInfo: Typetable) => {
-    setInfo(newInfo)
-  }, [])
+  const setInfoFu = useCallback(
+    (newInfoOrUpdater: Typetable | ((prevInfo: Typetable) => Typetable)) => {
+      if (typeof newInfoOrUpdater === 'function') {
+        setInfo(newInfoOrUpdater)
+      } else {
+        setInfo(newInfoOrUpdater)
+      }
+    },
+    []
+  )
 
   const value = useMemo(() => ({ info, setInfoFu }), [info, setInfoFu])
 

+ 2 - 1
src/pages/Zother/data.ts

@@ -1,4 +1,5 @@
 // 通用的一些 数据 和类型
+import { FileListType } from '@/components/Z3upFiles/data'
 import { getDictFu, selectObj } from '@/utils/dataChange'
 
 // 列表字段
@@ -135,7 +136,7 @@ export type Typetable = {
   date: string
   dictIdApply?: any
   fileIds?: any
-  files: any[]
+  files: FileListType[]
   goodIds: string
   id: number
   nodeProcessId: number

+ 27 - 0
src/utils/index.ts

@@ -0,0 +1,27 @@
+// 上传文件自动归类
+type FileObjType = {
+  [key: string]: string[]
+}
+export const fileImgArr = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'tiff', 'webp', 'svg', 'psd', 'ai']
+export const fileVideoArr = ['mp4', 'mov', 'avi', 'mkv', 'flv', 'wmv', 'mpeg', 'webm']
+
+const fileObj: FileObjType = {
+  img: fileImgArr,
+  video: fileVideoArr,
+  model: ['4dage', 'obj', 'stl', 'fbx', 'gltf', '3ds', 'blend', 'dae', 'step'],
+  audio: ['mp3', 'wav', 'flac', 'aac', 'ogg', 'm4a'],
+  doc: ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'csv', 'md', 'html']
+  // 'other':[]
+}
+
+export const fileTypeRes = (fileName: string) => {
+  const txtArr = fileName.split('.')
+  const txt = txtArr[txtArr.length - 1]
+
+  let type = 'other'
+
+  for (const k in fileObj) {
+    if (fileObj[k].includes(txt.toLowerCase())) type = k
+  }
+  return type
+}