ソースを参照

藏品征集-批量导入附件

shaogen1995 3 ヶ月 前
コミット
353ed82eff

+ 3 - 1
src/components/MyPopconfirm.tsx

@@ -12,6 +12,7 @@ type Props = {
     | '恢复'
     | '导入当前合格数据'
     | '取消关注'
+    | '清空'
   onConfirm: () => void
   Dom?: React.ReactNode
   loc?: 'bottom'
@@ -29,7 +30,8 @@ function MyPopconfirm({ txtK, onConfirm, Dom, loc, disabled }: Props) {
       撤回: ['确定撤回吗?', '确定'],
       恢复: ['确定恢复吗?', '确定'],
       导入当前合格数据: ['确定导入吗?如数据太大可能需要等待', '确定'],
-      取消关注: ['确定取消关注吗?', '确定']
+      取消关注: ['确定取消关注吗?', '确定'],
+      清空: ['确定清空数据嘛?', '确定']
     }
     return Reflect.get(obj, txtK) || ['', '']
   }, [txtK])

+ 4 - 7
src/components/Z3upFiles/index.module.scss

@@ -4,7 +4,6 @@
   height: 100%;
 
   :global {
-
     .Z3files {
       width: 500px;
       // padding-top: 6px;
@@ -15,7 +14,7 @@
         justify-content: space-between;
         align-items: center;
         font-size: 16px;
-        border-bottom: 1px dashed #999;
+        // border-bottom: 1px dashed #999;
         padding-bottom: 5px;
 
         .Z3files1 {
@@ -30,7 +29,7 @@
           width: 120px;
           justify-content: flex-end;
 
-          &>span {
+          & > span {
             cursor: pointer;
           }
 
@@ -50,13 +49,11 @@
         position: relative;
         overflow: hidden;
         opacity: 0;
-        transition: top .2s;
+        transition: top 0.2s;
         color: #ff4d4f;
         top: -10px;
       }
 
-
-
       .noUpThumbAc {
         top: 0;
         opacity: 1;
@@ -69,4 +66,4 @@
       left: 10px;
     }
   }
-}
+}

+ 119 - 0
src/components/ZupFile/index.module.scss

@@ -0,0 +1,119 @@
+.ZupFile {
+  position: fixed;
+  top: 0;
+  left: 0;
+  z-index: 100;
+  width: 100%;
+  height: 100%;
+  border-radius: 10px;
+  background-color: rgba(0, 0, 0, 0.6);
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  padding: 2% 0;
+
+  :global {
+    .ZupFileBox {
+      width: 1200px;
+      height: 100%;
+      background-color: #fff;
+      border-radius: 10px;
+      position: relative;
+      overflow: hidden;
+    }
+    .ZupFilell {
+      padding: 15px 40px;
+      width: 100%;
+      height: 100%;
+      overflow-y: auto;
+
+      .ant-upload-wrapper .ant-upload-drag {
+        position: absolute;
+        left: 2%;
+        top: 50%;
+        transform: translateY(-50%);
+        width: 300px;
+        height: 300px;
+      }
+
+      .ant-upload-drag {
+        height: 160px;
+      }
+
+      .ant-upload-list {
+        position: absolute;
+        left: 350px;
+        width: 800px;
+        height: 680px;
+        overflow-y: auto;
+        padding-right: 100px;
+      }
+
+      .ant-upload-list-item-container {
+        transition: none !important;
+        height: 40px !important;
+        margin-top: 15px;
+      }
+
+      // 删除之后的延迟问题
+      .ant-upload-list-item-container.ant-upload-animate-leave {
+        margin-top: 0px;
+        height: 0px !important;
+        overflow: hidden;
+      }
+
+      .ant-upload-list-item-action {
+        // display: none !important;
+        opacity: 1 !important;
+      }
+
+      .ant-upload-list-item-actions .anticon {
+        color: #ff4d4f !important;
+      }
+
+      // 自定义列表
+      .custom-upload-item {
+        position: relative;
+        .mySelect {
+          position: absolute;
+          top: 50%;
+          left: 50%;
+          transform: translate(-50%, -50%);
+          & > span {
+            color: #ff4d4f;
+            margin-left: 15px;
+          }
+        }
+      }
+
+      // .ant-upload-list-item-name {
+      //   width: 600px;
+      //   transition: none !important;
+      //   flex: none !important;
+      // }
+    }
+
+    .ZupFileBtnX {
+      position: absolute;
+      bottom: 8%;
+      left: 50%;
+      transform: translateX(-50%);
+    }
+  }
+}
+
+.ZupFileMo {
+  :global {
+    .ant-modal-close {
+      display: none;
+    }
+    .ant-modal {
+      width: 600px !important;
+    }
+
+    .ant-modal-body {
+      padding-top: 15px !important;
+      border-top: 1px solid #ccc;
+    }
+  }
+}

+ 232 - 0
src/components/ZupFile/index.tsx

@@ -0,0 +1,232 @@
+import React, { useCallback, useMemo, useState } from 'react'
+import { Upload, Button, UploadProps, Select } from 'antd'
+import { InboxOutlined } from '@ant-design/icons'
+import { MessageFu } from '@/utils/message'
+import styles from './index.module.scss'
+import { B1Xtype } from '@/pages/B_enterTibet/B1collect/data'
+import { baseURL } from '@/utils/http'
+import { fileTypeRes } from '@/store/action/layout'
+import { getTokenFu } from '@/utils/storage'
+import history from '@/utils/history'
+import modal from 'antd/es/modal'
+import { API_C2dels } from '@/store/action/C2files'
+import MyPopconfirm from '../MyPopconfirm'
+
+const { Dragger } = Upload
+
+type Props = {
+  tableList: B1Xtype[]
+  moduleId: number
+  isShow: boolean
+  closeFu: () => void
+  succFu: (obj: any) => void
+}
+
+function ZupFile({ tableList, moduleId, isShow, closeFu, succFu }: Props) {
+  // 附件列表
+  const [fileList, setFileList] = useState<any[]>([])
+
+  // const timeRef = useRef(-1)
+
+  const FileProps: UploadProps = {
+    name: 'file',
+    // 支持上传文件夹
+    directory: true,
+    multiple: true,
+    action: baseURL + 'cms/orderCollect/upload',
+    headers: {
+      token: getTokenFu()
+    },
+    // 上传的额外参数
+    data: file => ({
+      dirCode: 'collectUpFiles',
+      isDb: 'true',
+      type: fileTypeRes(file.name),
+      moduleId,
+      isCompress: 'true'
+    }),
+    fileList,
+    onChange(info: any) {
+      setFileList([...info.fileList])
+
+      const { status } = info.file
+
+      // 检查请求状态
+      const response = info.file.response || {}
+
+      if (status !== 'uploading') {
+        if (response.code !== 0) {
+          setFileList(info.fileList.filter((v: any) => v.uid !== info.file.uid))
+          MessageFu.error(`${info.file.name} 上传失败;${response.msg}`)
+        }
+        if (response.code === 5001 || response.code === 5002) {
+          MessageFu.warning('登录失效!')
+          history.push('/login')
+          return false
+        }
+
+        // console.log(info.file, info.fileList);
+      }
+      if (status === 'done' && response.code === 0) {
+        // console.log("-----", info);
+        setFileList(
+          info.fileList.map((v: any) => ({
+            ...v,
+            mySelect:
+              info.file.uid === v.uid
+                ? {
+                    id: info.file.response.data.id,
+                    goodsId: undefined,
+                    name: info.file.name
+                  }
+                : v.mySelect
+          }))
+        )
+      } else if (status === 'error') {
+        MessageFu.error(`${info.file.name} 上传失败.`)
+        // 去掉列表中的失败状态文件
+        setFileList(info.fileList.filter((v: any) => v.uid !== info.file.uid))
+      }
+    },
+    // 自定义列表
+    itemRender: (originNode, file: any) => {
+      const obj = file.mySelect || { goodsId: undefined }
+
+      return (
+        <span className='custom-upload-item'>
+          {originNode}
+
+          {file.status === 'done' ? (
+            <span className='mySelect'>
+              <Select
+                getPopupContainer={() => document.querySelector('#A1OMain')!}
+                style={{ width: 200 }}
+                placeholder='请选择'
+                value={obj.goodsId}
+                onChange={e => selectChangeFu(e, file.uid, file.mySelect.id)}
+                options={tableList.map(v => ({
+                  value: v.id,
+                  label: v.name
+                }))}
+              />
+              <span>请选择藏品</span>
+            </span>
+          ) : null}
+        </span>
+      )
+    },
+    // onDrop(e) {
+    //   // console.log("拖动文件到上传区域", e.dataTransfer.files);
+    // },
+    // 点击删除
+    async onRemove(info) {
+      const promiseFu = new Promise((resolve: (value: boolean) => void) => {
+        modal.confirm({
+          title: '删除确认',
+          content: '删除后无法恢复,是否删除?',
+          okText: '删除',
+          cancelText: '取消',
+          async onOk() {
+            if (info.percent === 100) {
+              // console.log("-----还没有发请求删除", info);
+              const id = info.response.data.id
+              // 已经上传完成,发请求删除
+              const res = await API_C2dels([id])
+
+              if (res.code === 0) {
+                MessageFu.success('删除成功!')
+                resolve(true)
+              }
+            } else {
+              resolve(true)
+              MessageFu.success('删除成功!')
+            }
+          },
+          onCancel() {
+            resolve(false)
+          }
+        })
+      })
+      return await promiseFu
+    }
+  }
+
+  // 下拉框改变
+  const selectChangeFu = useCallback(
+    (val: number, uid: string, id: number) => {
+      setFileList(
+        fileList.map(v => ({
+          ...v,
+          mySelect:
+            v.uid === uid
+              ? {
+                  ...v.mySelect,
+                  goodsId: v.mySelect.id === id ? val : v.mySelect.goodsId
+                }
+              : v.mySelect
+        }))
+      )
+    },
+    [fileList]
+  )
+
+  // 需要提交的数据
+  const arrRes = useMemo(() => {
+    return fileList.map((v: any) => v.mySelect || { goodsId: undefined })
+  }, [fileList])
+
+  // 点击提交
+  const btnOk = useCallback(async () => {
+    const obj: any = {}
+    arrRes.forEach(v => {
+      if (obj[v.goodsId]) obj[v.goodsId].push(v.id)
+      else obj[v.goodsId] = [v.id]
+    })
+
+    succFu(obj)
+    setFileList([])
+    closeFu()
+  }, [arrRes, closeFu, succFu])
+
+  return (
+    <div className={styles.ZupFile} hidden={!isShow}>
+      <div className='ZupFileBox' id='A1OMain'>
+        <div className='ZupFilell'>
+          {/* 文件夹上传区域(支持拖拽) */}
+          <Dragger {...FileProps}>
+            <p className='ant-upload-drag-icon'>
+              <InboxOutlined />
+            </p>
+            <p className='ant-upload-text'>点击或拖拽文件夹到此区域上传</p>
+            <p className='ant-upload-hint'>支持上传整个文件夹及子目录文件</p>
+          </Dragger>
+        </div>
+      </div>
+
+      {/* 关闭按钮 */}
+      <div className='ZupFileBtnX'>
+        <Button
+          type='primary'
+          onClick={btnOk}
+          disabled={fileList.length === 0 || arrRes.some(v => !v.goodsId)}
+        >
+          提交
+        </Button>
+        &emsp;
+        <Button onClick={closeFu}>关闭</Button>
+        {fileList.length ? (
+          <>
+            &emsp;
+            <MyPopconfirm
+              txtK='清空'
+              onConfirm={() => setFileList([])}
+              Dom={<Button danger>清空数据</Button>}
+            />
+          </>
+        ) : null}
+      </div>
+    </div>
+  )
+}
+
+export default ZupFile

+ 53 - 1
src/pages/B_enterTibet/B1collect/B1edit/index.tsx

@@ -17,7 +17,8 @@ import {
   B1_APIsaveApply,
   B1_APIsaveAudit,
   B1_APIsaveCreate,
-  B1_APIsaveDraft
+  B1_APIsaveDraft,
+  B1X_APIgoodsIdTofileId
 } from '@/store/action/B1collect'
 import dayjs from 'dayjs'
 import { EXbtnFu } from '@/utils/EXBtn'
@@ -27,6 +28,7 @@ import { B1Xtype } from '../data'
 import ZupFileTable from '@/components/ZupFileTable'
 import { FourTableType, TypeinfoXLSX } from '../type'
 import B1upXLSX from './B1upXLSX'
+import ZupFile from '@/components/ZupFile'
 
 function B1edit() {
   const { key, id } = useParams<any>()
@@ -285,6 +287,9 @@ function B1edit() {
     err: []
   })
 
+  // 批量上传页面
+  const [upFile, setUpFile] = useState(false)
+
   return (
     <div className={styles.B1edit}>
       <div className='pageTitle'>藏品征集-{Reflect.get(pageTitTxtObj, key)}</div>
@@ -368,6 +373,10 @@ function B1edit() {
                     upSuccFu={(succ, err) => setInfoXLSX({ show: true, succ, err })}
                     clickSuccFu={arr => setClueArr([...arr, ...clueArr])}
                   />
+
+                  <Button onClick={() => setUpFile(true)} disabled={clueArr.length === 0}>
+                    批量上传附件
+                  </Button>
                   <Button type='primary' onClick={() => setAddInfo({ id: -1 } as B1Xtype)}>
                     新增
                   </Button>
@@ -454,6 +463,49 @@ function B1edit() {
           }}
         />
       ) : null}
+
+      {/* 批量上传 */}
+      <ZupFile
+        tableList={clueArr}
+        moduleId={topInfo.id}
+        isShow={upFile}
+        closeFu={() => setUpFile(false)}
+        succFu={async obj => {
+          // 得到的格式是
+          // {
+          //   藏品id:[附件id,附件id]
+          // }
+
+          const oldTableArr = [...clueArr]
+
+          // 附件id和藏品id绑定
+          const arr: any = []
+
+          oldTableArr.forEach(v1 => {
+            // 拿之前的附件id
+            const txt = v1.fileIds || ''
+            // 转数组
+            let txtArr = txt.split(',')
+            if (obj[v1.id]) {
+              // 合并
+              txtArr = [...txtArr, ...obj[v1.id]]
+              // 去重
+              txtArr = Array.from(new Set(txtArr))
+              v1.fileIds = txtArr.filter(v => v).join(',')
+
+              // 绑定
+              if (v1.fileIds) arr.push({ id: v1.id, fileIds: v1.fileIds })
+            }
+          })
+
+          const res = await B1X_APIgoodsIdTofileId(arr)
+
+          if (res.code === 0) {
+            MessageFu.success('提交成功')
+            setClueArr(oldTableArr)
+          }
+        }}
+      />
     </div>
   )
 }

+ 7 - 0
src/store/action/B1collect.ts

@@ -97,3 +97,10 @@ export const B1X_APIgetInfo = (id: number) => {
 export const B1X_APIadds = (data: any) => {
   return http.post('cms/orderCollect/collect/batch/add', data)
 }
+
+/**
+ * 藏品征集-批量上传附件id和藏品id绑定
+ */
+export const B1X_APIgoodsIdTofileId = (data: any) => {
+  return http.post('cms/orderCollect/collect/binding/file', data)
+}