Explorar o código

Merge branch 'master' of http://192.168.0.115:3000/shaogen1995/qingDao_goods into master

shaogen1995 hai 2 días
pai
achega
b46a52ac00

+ 214 - 31
src/pages/Cledger/C1ledger/C1Import/index.tsx

@@ -1,25 +1,133 @@
-import React, { useMemo, useState } from 'react'
+import React, { useMemo, useRef, useState } from 'react'
 import styles from './index.module.scss'
 import styles from './index.module.scss'
-import { selectObj, getDictFu } from '@/utils/dataChange'
-import { openLink } from '@/utils/history'
 import TableList from '@/pages/Zother/TableList'
 import TableList from '@/pages/Zother/TableList'
 import { useSelector } from 'react-redux'
 import { useSelector } from 'react-redux'
 import { RootState } from '@/store'
 import { RootState } from '@/store'
-import { API_getGoodsList } from '@/store/action/Cledger/C1ledger'
-import { baseFormData } from '@/pages/Zother/data'
+import {
+  API_getImportExcelList,
+  API_getImportZipList,
+  API_uploadImportExcel,
+  API_uploadImportZip,
+  API_getImportResult,
+  API_deleteImportResult,
+  API_getImportExcelResult,
+  API_deleteImportExcelResult
+} from '@/store/action/Cledger/C1ledger'
 import { importDataTableC } from '@/utils/tableData'
 import { importDataTableC } from '@/utils/tableData'
 import { Button, Radio } from 'antd'
 import { Button, Radio } from 'antd'
+import { MessageFu } from '@/utils/message'
+import { baseURL } from '@/utils/http'
+import C1ImportRes from '../C1ImportRes'
+import C1ImportZipRes from '../C1importZipRes'
 
 
-const C1baseFormData = {
-  ...baseFormData,
-  typeDictId: '',
-  ageDictId: '',
-  textureDictId: ''
+const C1ImportBaseFormData = {
+  pageNum: 1,
+  pageSize: 10,
+  searchKey: '',
+  type: ''
 }
 }
 
 
 function C1Import({ onClose }: { onClose: () => void }) {
 function C1Import({ onClose }: { onClose: () => void }) {
-  const tableInfo = useSelector((state: RootState) => state.C1ledger.tableInfo)
+  const importExcelTableInfo = useSelector(
+    (state: RootState) => state.C1ledger.importExcelTableInfo
+  )
+  const importZipTableInfo = useSelector((state: RootState) => state.C1ledger.importZipTableInfo)
   const [isImportData, setIsImportData] = useState(true)
   const [isImportData, setIsImportData] = useState(true)
+  // 是否查看模式(查看历史记录)
+  const [isLook, setIsLook] = useState(false)
+  const fileInputRef = useRef<HTMLInputElement>(null)
+  const clickSearchRef = useRef<() => void>(() => {})
+  const [uploadData, setUploadData] = useState<{
+    visible: boolean
+    result: any | null
+    errorMsg?: string
+  }>({ visible: false, result: null })
+  // 选择文件并上传--导入数据(excel
+  const handleUploadExcel = async (e: React.ChangeEvent<HTMLInputElement>) => {
+    const file = e.target.files?.[0]
+    if (!file) return
+    const ext = file.name.split('.').pop()?.toLowerCase()
+    if (!['xlsx'].includes(ext || '')) {
+      MessageFu.warning('请选择 Excel 文件(.xlsx 或 .xls)')
+      e.target.value = ''
+      return
+    }
+    const formData = new FormData()
+    formData.append('file', file)
+    formData.append('type', 'doc')
+    formData.append('dirCode', 'importExcel')
+    try {
+      const res: any = await API_uploadImportExcel(formData)
+      e.target.value = ''
+      if (res?.code === 0) {
+        const data = res.data || {}
+        setIsLook(false)
+        setUploadData({
+          visible: true,
+          result: data
+        })
+        MessageFu.success('上传校验完成')
+        clickSearchRef.current?.()
+      } else {
+        setUploadData({
+          visible: false,
+          result: null,
+          errorMsg: res?.msg || '上传失败'
+        })
+      }
+    } catch (err: any) {
+      e.target.value = ''
+      setUploadData({
+        visible: false,
+        result: null,
+        errorMsg: err?.response?.data?.msg || err?.message || '上传失败'
+      })
+    }
+  }
+
+  // 选择文件并上传--导入图片(zip/rar)
+  const handleUploadZip = async (e: React.ChangeEvent<HTMLInputElement>) => {
+    const file = e.target.files?.[0]
+    if (!file) return
+    const ext = file.name.split('.').pop()?.toLowerCase()
+    if (!['zip', 'rar'].includes(ext || '')) {
+      MessageFu.warning('请选择 zip/rar 文件(.zip 或 .rar)')
+      e.target.value = ''
+      return
+    }
+    const formData = new FormData()
+    formData.append('file', file)
+    formData.append('type', 'other')
+    formData.append('dirCode', 'importZip')
+    try {
+      const res: any = await API_uploadImportZip(formData as any)
+      e.target.value = ''
+      if (res?.code === 0) {
+        const data = res.data || {}
+        setIsLook(false)
+        setUploadData({
+          visible: true,
+          result: data
+        })
+        MessageFu.success('上传校验完成')
+        clickSearchRef.current?.()
+      } else {
+        setUploadData({
+          visible: false,
+          result: null,
+          errorMsg: res?.msg || '上传失败'
+        })
+      }
+    } catch (err: any) {
+      e.target.value = ''
+      setUploadData({
+        visible: false,
+        result: null,
+        errorMsg: err?.response?.data?.msg || err?.message || '上传失败'
+      })
+    }
+  }
+
   // 故事管理/藏品总账定制右侧内容
   // 故事管理/藏品总账定制右侧内容
   const storyTableListToprr = ({
   const storyTableListToprr = ({
     clickSearch,
     clickSearch,
@@ -28,6 +136,7 @@ function C1Import({ onClose }: { onClose: () => void }) {
     clickSearch: () => void
     clickSearch: () => void
     resetSelectFu: () => void
     resetSelectFu: () => void
   }) => {
   }) => {
+    clickSearchRef.current = resetSelectFu
     return (
     return (
       <>
       <>
         <div className='TableListToprrBox'>
         <div className='TableListToprrBox'>
@@ -50,17 +159,27 @@ function C1Import({ onClose }: { onClose: () => void }) {
           </Radio.Group>
           </Radio.Group>
         </div>
         </div>
         <div className='TableListToprrBox'>
         <div className='TableListToprrBox'>
+          <input
+            ref={fileInputRef}
+            type='file'
+            accept={isImportData ? '.xlsx' : '.zip,.rar'}
+            style={{ display: 'none' }}
+            onChange={isImportData ? handleUploadExcel : handleUploadZip}
+          />
           {isImportData ? (
           {isImportData ? (
             <>
             <>
-              <Button type='primary' onClick={() => alert('下载模块')}>
-                下载模块
+              <Button
+                type='primary'
+                onClick={() => window.open(`${baseURL}/baseData/ZP_TEMP.xlsx`)}
+              >
+                下载模板
               </Button>
               </Button>
-              <Button type='primary' onClick={() => alert('上传藏品数据')}>
+              <Button type='primary' onClick={() => fileInputRef.current?.click()}>
                 上传藏品数据
                 上传藏品数据
               </Button>
               </Button>
             </>
             </>
           ) : (
           ) : (
-            <Button type='primary' onClick={() => alert('上传压缩包(ZIP,RAR格式)')}>
+            <Button type='primary' onClick={() => fileInputRef.current?.click()}>
               上传压缩包(ZIP,RAR格式)
               上传压缩包(ZIP,RAR格式)
             </Button>
             </Button>
           )}
           )}
@@ -71,38 +190,102 @@ function C1Import({ onClose }: { onClose: () => void }) {
 
 
   // 故事管理/藏品总账定制右侧操作按钮
   // 故事管理/藏品总账定制右侧操作按钮
   const storyTableLastBtn = useMemo(() => {
   const storyTableLastBtn = useMemo(() => {
+    // 点击查看导入结果
+    const handleGetImportResult = (item: any) => {
+      if (isImportData) {
+        API_getImportExcelResult(item.id).then((res: any) => {
+          setIsLook(true)
+          setUploadData({
+            visible: true,
+            result: {
+              excel: res.data,
+              fileName: item.fileName,
+              pcsSuccess: item.pcsSuccess,
+              pcsError: item.pcsError
+            }
+          })
+        })
+      } else {
+        API_getImportResult(item.id).then((res: any) => {
+          setIsLook(true)
+          setUploadData({
+            visible: true,
+            result: {
+              img: res.data,
+              fileName: item.fileName,
+              pcsSuccess: item.pcsSuccess,
+              pcsError: item.pcsError
+            }
+          })
+        })
+      }
+    }
+
+    // 点击删除导入结果
+    const handleDeleteImportResult = (item: any) => {
+      if (isImportData) {
+        API_deleteImportExcelResult(item.id).then(() => {
+          MessageFu.success('删除成功')
+          clickSearchRef.current?.()
+        })
+      } else {
+        API_deleteImportResult(item.id).then(() => {
+          MessageFu.success('删除成功')
+          clickSearchRef.current?.()
+        })
+      }
+    }
     return [
     return [
       {
       {
         title: '操作',
         title: '操作',
         render: (item: any) => (
         render: (item: any) => (
           <>
           <>
-            <Button size='small' type='text' onClick={() => alert('查看')}>
+            <Button size='small' type='text' onClick={() => handleGetImportResult(item)}>
               查看
               查看
             </Button>
             </Button>
-            <Button size='small' type='text' onClick={() => alert('删除记录')}>
+            <Button size='small' type='text' onClick={() => handleDeleteImportResult(item)}>
               删除记录
               删除记录
             </Button>
             </Button>
           </>
           </>
         )
         )
       }
       }
     ]
     ]
-  }, [])
+  }, [isImportData])
 
 
   return (
   return (
     <div className={styles.C1Import}>
     <div className={styles.C1Import}>
-      <TableList
-        baseFormData={C1baseFormData}
-        getListAPI={API_getGoodsList}
-        pageKey='ledger'
-        tableInfo={tableInfo}
-        columnsTemp={importDataTableC}
-        rightBtnWidth={'100%'}
-        leftRowWidth={'20%'}
-        yHeight={592}
-        searchDom={[]}
-        storyTableListToprr={storyTableListToprr}
-        storyTableLastBtn={storyTableLastBtn}
-      />
+      {uploadData.visible ? (
+        isImportData ? (
+          <C1ImportRes
+            onClose={() => setUploadData({ visible: false, result: null })}
+            tableInfo={uploadData.result}
+            uploadFu={handleUploadExcel}
+            isLook={isLook}
+          />
+        ) : (
+          <C1ImportZipRes
+            onClose={() => setUploadData({ visible: false, result: null })}
+            tableInfo={uploadData.result}
+            uploadFu={handleUploadZip}
+            isLook={isLook}
+          />
+        )
+      ) : (
+        <TableList
+          key={isImportData ? 'importExcel' : 'importZip'}
+          baseFormData={C1ImportBaseFormData}
+          getListAPI={isImportData ? API_getImportExcelList : API_getImportZipList}
+          pageKey={isImportData ? 'importExcel' : 'importZip'}
+          tableInfo={isImportData ? importExcelTableInfo : importZipTableInfo}
+          columnsTemp={importDataTableC}
+          rightBtnWidth={'100%'}
+          leftRowWidth={'20%'}
+          yHeight={592}
+          searchDom={[]}
+          storyTableListToprr={storyTableListToprr}
+          storyTableLastBtn={storyTableLastBtn}
+        />
+      )}
     </div>
     </div>
   )
   )
 }
 }

+ 68 - 0
src/pages/Cledger/C1ledger/C1ImportRes/index.module.scss

@@ -0,0 +1,68 @@
+// .B1collect {
+//   :global {
+//   }
+// }
+.TableListTopInfo {
+  width: 100%;
+  display: flex;
+  align-items: center;
+  gap: 20px;
+  margin: 15px 15px 5px;
+  .i1 {
+    color: var(--txtColor);
+  }
+}
+
+.TableListTop {
+  border-radius: 10px;
+  padding: 15px 15px 5px;
+  background-color: var(--boxBcaColor);
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  :global {
+    .TableListTopll {
+      display: flex;
+      flex-wrap: wrap;
+
+      & > div {
+        padding-right: 10px;
+        margin-bottom: 10px;
+        & > div {
+          width: 100%;
+        }
+        & > input {
+          width: 100%;
+        }
+      }
+    }
+    .TableListToprr {
+      display: flex;
+      flex-wrap: wrap;
+
+      justify-content: space-between;
+      .ant-btn {
+        margin-bottom: 10px;
+      }
+    }
+  }
+}
+
+.TableListTable {
+  border-radius: 10px;
+  overflow: hidden;
+  margin-top: 15px;
+  height: calc(100% - 77px);
+  background-color: var(--boxBcaColor);
+}
+
+.TableListBottom {
+  width: 100%;
+  display: flex;
+  justify-content: center;
+  gap: 10px;
+  margin-top: 15px;
+  padding: 15px;
+  background-color: var(--boxBcaColor);
+  border-radius: 10px;
+}

+ 203 - 0
src/pages/Cledger/C1ledger/C1ImportRes/index.tsx

@@ -0,0 +1,203 @@
+import React, { useState, useEffect, useRef, useMemo } from 'react'
+import styles from './index.module.scss'
+import { importDataTableCheckC } from '@/utils/tableData'
+import { selectObj } from '@/utils/dataChange'
+import MyTable from '@/components/MyTable'
+import { Input, Select, Button } from 'antd'
+import { API_addImportExcel, API_addImportExcelRecord } from '@/store/action/Cledger/C1ledger'
+import { MessageFu } from '@/utils/message'
+
+type Props = {
+  onClose: () => void
+  tableInfo: any
+  uploadFu: (e: React.ChangeEvent<HTMLInputElement>) => void
+  isLook?: boolean // 是否查看模式
+}
+
+function C1ImportRes({ onClose, tableInfo, uploadFu, isLook = false }: Props) {
+  const staBtn = [
+    {
+      title: '行数',
+      render: (_: any, __: any, index: number) => index + 1
+    }
+  ]
+  const lastBtn = [
+    {
+      title: '失败原因',
+      render: (_: any, record: any) => {
+        const isFail = record.importIsTrue === 0 || record.importIsTrue === 0
+        const errArr = record.EError ?? record.eerror ?? []
+        if (!isFail) return ''
+        return Array.isArray(errArr) ? (
+          <span style={{ whiteSpace: 'pre-line' }}>{errArr.join('\n')}</span>
+        ) : (
+          errArr
+        )
+      }
+    }
+  ]
+  const successCount = useMemo(() => {
+    return (
+      tableInfo.pcsSuccess ?? tableInfo.excel.filter((item: any) => item.importIsTrue === 1).length
+    )
+  }, [tableInfo.excel, tableInfo.pcsSuccess])
+  const errorCount = useMemo(() => {
+    return (
+      tableInfo.pcsError ?? tableInfo.excel.filter((item: any) => item.importIsTrue === 0).length
+    )
+  }, [tableInfo.excel, tableInfo.pcsError])
+  const [tableInfoData, setTableInfoData] = useState(
+    (tableInfo.excel ?? []).map((item: any, i: number) => ({ ...item, _rowKey: `row-${i}` }))
+  )
+  const [searchKey, setSearchKey] = useState('')
+  const [checkResult, setCheckResult] = useState()
+  const [importLoading, setImportLoading] = useState(false)
+  const fileInputRef = useRef<HTMLInputElement>(null)
+  // 条件搜索(保留 _rowKey 用于表格 key)
+  useEffect(() => {
+    const filtered = (tableInfo.excel ?? [])
+      .map((item: any, i: number) => ({ ...item, _rowKey: `row-${i}` }))
+      .filter((item: any) => {
+        const matchesSearch =
+          !searchKey || item.num.includes(searchKey) || item.name.includes(searchKey)
+        const matchesCheck =
+          checkResult === undefined ||
+          item.importIsTrue === checkResult ||
+          checkResult === item.importIsTrue
+        return matchesSearch && matchesCheck
+      })
+    setTableInfoData(filtered)
+  }, [tableInfo.excel, searchKey, checkResult])
+
+  // 重新上传
+  const reUploadFu = () => {
+    fileInputRef.current?.click()
+    setSearchKey('')
+    setCheckResult(undefined)
+  }
+
+  // 导入校验成功的数据
+  const importSuccessFu = async () => {
+    const successData = tableInfo.excel.filter((item: any) => item.importIsTrue === 1)
+    if (successData.length === 0) {
+      MessageFu.warning('没有校验成功的数据可导入')
+      return
+    }
+    setImportLoading(true)
+    try {
+      // 1. 先添加记录
+      const recordRes: any = await API_addImportExcelRecord({
+        fileName: tableInfo.fileName,
+        filePath: tableInfo.filePath,
+        pcsError: errorCount,
+        pcsSuccess: successCount,
+        pcsTotal: tableInfo.excel.length,
+        type: 'zip'
+      } as any)
+      if (recordRes?.code !== 0) {
+        MessageFu.error(recordRes?.msg || '添加记录失败')
+        return
+      } else {
+        // 2. 再导入数据
+        const importId = recordRes.data.id
+        const res: any = await API_addImportExcel(
+          successData.map((item: any) => ({
+            ...item,
+            importId,
+            importError: item.importIsTrue === 0 ? 1 : 0
+          })) as any
+        )
+        if (res?.code === 0) {
+          MessageFu.success('导入成功')
+          onClose()
+        } else {
+          MessageFu.error(res?.msg || '导入失败')
+        }
+      }
+    } catch (err: any) {
+      MessageFu.error(err?.response?.data?.msg || err?.message || '导入失败')
+    } finally {
+      setImportLoading(false)
+    }
+  }
+
+  const columnsTemp = useMemo(() => {
+    const base = importDataTableCheckC
+    return isLook
+      ? [...base.slice(0, -1), ['txtChange', '校验结果', 'importError', { 1: '失败', 0: '成功' }]]
+      : base
+  }, [isLook])
+
+  return (
+    <div className={styles.C1ImportRes}>
+      <div className={styles.TableListTopInfo}>
+        <h2>{tableInfo.fileName}</h2>
+        <div className='i1'>导入数据条数: {tableInfo.excel.length}</div>
+        <div className='i1'>校验成功条数: {successCount}</div>
+        <div className='i1'>校验失败条数: {errorCount}</div>
+      </div>
+      <div className={styles.TableListTop}>
+        <div
+          className='TableListTopll'
+          style={{
+            width: `100%`
+          }}
+        >
+          <div style={{ width: '20%' }}>
+            <Input
+              placeholder='搜索藏品登记号、藏品名称,不超过30个字'
+              maxLength={30}
+              value={searchKey}
+              onChange={e => setSearchKey(e.target.value)}
+            />
+          </div>
+          <div style={{ width: '20%' }}>
+            <Select
+              allowClear={true}
+              placeholder='校验结果'
+              value={checkResult}
+              onChange={e => setCheckResult(e)}
+              options={selectObj['校验结果']}
+            />
+          </div>
+        </div>
+      </div>
+      <div className={`${styles.TableListTable} table-list-table`}>
+        <MyTable
+          rowKey='_rowKey'
+          list={tableInfoData}
+          columnsTemp={columnsTemp}
+          yHeight={500}
+          staBtn={staBtn}
+          lastBtn={lastBtn}
+        />
+      </div>
+      <div className={styles.TableListBottom}>
+        {!isLook ? (
+          <>
+            <input
+              ref={fileInputRef}
+              type='file'
+              accept='.xlsx'
+              style={{ display: 'none' }}
+              onChange={uploadFu}
+            />
+            <Button type='primary' onClick={reUploadFu}>
+              重新上传表格
+            </Button>
+            <Button type='primary' loading={importLoading} onClick={importSuccessFu}>
+              导入校验成功的数据
+            </Button>
+            <Button onClick={() => onClose()}>取消导入</Button>
+          </>
+        ) : (
+          <Button onClick={() => onClose()}>返回</Button>
+        )}
+      </div>
+    </div>
+  )
+}
+
+const MemoC1ImportRes = React.memo(C1ImportRes)
+
+export default MemoC1ImportRes

+ 68 - 0
src/pages/Cledger/C1ledger/C1importZipRes/index.module.scss

@@ -0,0 +1,68 @@
+// .B1collect {
+//   :global {
+//   }
+// }
+.TableListTopInfo {
+  width: 100%;
+  display: flex;
+  align-items: center;
+  gap: 20px;
+  margin: 15px 15px 5px;
+  .i1 {
+    color: var(--txtColor);
+  }
+}
+
+.TableListTop {
+  border-radius: 10px;
+  padding: 15px 15px 5px;
+  background-color: var(--boxBcaColor);
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  :global {
+    .TableListTopll {
+      display: flex;
+      flex-wrap: wrap;
+
+      & > div {
+        padding-right: 10px;
+        margin-bottom: 10px;
+        & > div {
+          width: 100%;
+        }
+        & > input {
+          width: 100%;
+        }
+      }
+    }
+    .TableListToprr {
+      display: flex;
+      flex-wrap: wrap;
+
+      justify-content: space-between;
+      .ant-btn {
+        margin-bottom: 10px;
+      }
+    }
+  }
+}
+
+.TableListTable {
+  border-radius: 10px;
+  overflow: hidden;
+  margin-top: 15px;
+  height: calc(100% - 77px);
+  background-color: var(--boxBcaColor);
+}
+
+.TableListBottom {
+  width: 100%;
+  display: flex;
+  justify-content: center;
+  gap: 10px;
+  margin-top: 15px;
+  padding: 15px;
+  background-color: var(--boxBcaColor);
+  border-radius: 10px;
+}

+ 170 - 0
src/pages/Cledger/C1ledger/C1importZipRes/index.tsx

@@ -0,0 +1,170 @@
+import React, { useState, useEffect, useRef, useMemo } from 'react'
+import styles from './index.module.scss'
+import { importZipDataTableCheckC } from '@/utils/tableData'
+import { selectObj } from '@/utils/dataChange'
+import MyTable from '@/components/MyTable'
+import { Input, Select, Button } from 'antd'
+import { API_addImportZip, API_addImportZipRecord } from '@/store/action/Cledger/C1ledger'
+import { MessageFu } from '@/utils/message'
+
+type Props = {
+  onClose: () => void
+  tableInfo: any
+  uploadFu: (e: React.ChangeEvent<HTMLInputElement>) => void
+  isLook?: boolean // 是否查看模式
+}
+
+function C1ImportZipRes({ onClose, tableInfo, uploadFu, isLook = false }: Props) {
+  console.log('tableInfo', tableInfo)
+  const successCount = useMemo(() => {
+    return tableInfo.pcsSuccess ?? tableInfo.img.filter((item: any) => item.isTrue === 1).length
+  }, [tableInfo.img, tableInfo.pcsSuccess])
+  const errorCount = useMemo(() => {
+    return tableInfo.pcsError ?? tableInfo.img.filter((item: any) => item.isTrue === 0).length
+  }, [tableInfo.img, tableInfo.pcsError])
+  const [tableInfoData, setTableInfoData] = useState(tableInfo.img)
+  const [searchKey, setSearchKey] = useState('')
+  const [checkResult, setCheckResult] = useState()
+  const [importLoading, setImportLoading] = useState(false)
+  const fileInputRef = useRef<HTMLInputElement>(null)
+
+  // 条件搜索
+  useEffect(() => {
+    const filtered = tableInfo.img.filter((item: any) => {
+      const matchesSearch =
+        !searchKey || item.num.includes(searchKey) || item.name.includes(searchKey)
+      const matchesCheck = checkResult === undefined || item.isTrue === checkResult
+      return matchesSearch && matchesCheck
+    })
+    setTableInfoData(filtered)
+  }, [tableInfo.img, searchKey, checkResult])
+
+  // 重新上传
+  const reUploadFu = () => {
+    fileInputRef.current?.click()
+    setSearchKey('')
+    setCheckResult(undefined)
+  }
+
+  // 导入校验成功的数据:先添加记录,再导入数据
+  const importSuccessFu = async () => {
+    const successData = tableInfo.img.filter((item: any) => item.isTrue === 1)
+    if (successData.length === 0) {
+      MessageFu.warning('没有校验成功的数据可导入')
+      return
+    }
+    setImportLoading(true)
+    try {
+      // 1. 先添加记录
+      const recordRes: any = await API_addImportZipRecord({
+        fileName: tableInfo.fileName,
+        filePath: tableInfo.filePath,
+        pcsError: errorCount,
+        pcsSuccess: successCount,
+        pcsTotal: tableInfo.img.length,
+        type: 'zip'
+      } as any)
+      if (recordRes?.code !== 0) {
+        MessageFu.error(recordRes?.msg || '添加记录失败')
+        return
+      } else {
+        // 2. 再导入数据
+        const importId = recordRes.data.id
+        const payload = successData.map((item: any) => ({
+          description: item.description ?? item.desc ?? '',
+          effect: item.effect ?? '',
+          fileName: item.fileName ?? '',
+          filePath: item.filePath ?? '',
+          id: item.id ?? 0,
+          importError: 0,
+          importId: importId,
+          isTrue: item.isTrue,
+          num: item.num ?? '',
+          type: item.type
+        }))
+        const res: any = await API_addImportZip(payload as any)
+        if (res?.code === 0) {
+          MessageFu.success('导入成功')
+          onClose()
+        } else {
+          MessageFu.error(res?.msg || '导入失败')
+        }
+      }
+    } catch (err: any) {
+      MessageFu.error(err?.response?.data?.msg || err?.message || '导入失败')
+    } finally {
+      setImportLoading(false)
+    }
+  }
+
+  return (
+    <div className={styles.C1ImportRes}>
+      <div className={styles.TableListTopInfo}>
+        <h2>{tableInfo.fileName}</h2>
+        <div className='i1'>导入数据条数: {tableInfo.img.length}</div>
+        <div className='i1'>校验成功条数: {successCount}</div>
+        <div className='i1'>校验失败条数: {errorCount}</div>
+      </div>
+      <div className={styles.TableListTop}>
+        <div
+          className='TableListTopll'
+          style={{
+            width: `100%`
+          }}
+        >
+          <div style={{ width: '20%' }}>
+            <Input
+              placeholder='搜索藏品登记号、藏品名称,不超过30个字'
+              maxLength={30}
+              value={searchKey}
+              onChange={e => setSearchKey(e.target.value)}
+            />
+          </div>
+          <div style={{ width: '20%' }}>
+            <Select
+              allowClear={true}
+              placeholder='校验结果'
+              value={checkResult}
+              onChange={e => setCheckResult(e)}
+              options={selectObj['校验结果']}
+            />
+          </div>
+        </div>
+      </div>
+      <div className={`${styles.TableListTable} table-list-table`}>
+        <MyTable
+          rowKey='fileName'
+          list={tableInfoData}
+          columnsTemp={importZipDataTableCheckC}
+          yHeight={500}
+        />
+      </div>
+      <div className={styles.TableListBottom}>
+        {!isLook ? (
+          <>
+            <input
+              ref={fileInputRef}
+              type='file'
+              accept='.zip,.rar'
+              style={{ display: 'none' }}
+              onChange={uploadFu}
+            />
+            <Button type='primary' onClick={reUploadFu}>
+              重新上传压缩包
+            </Button>
+            <Button type='primary' loading={importLoading} onClick={importSuccessFu}>
+              导入校验成功的数据
+            </Button>
+            <Button onClick={() => onClose()}>取消导入</Button>
+          </>
+        ) : (
+          <Button onClick={() => onClose()}>返回</Button>
+        )}
+      </div>
+    </div>
+  )
+}
+
+const MemoC1ImportZipRes = React.memo(C1ImportZipRes)
+
+export default MemoC1ImportZipRes

+ 1 - 1
src/pages/Cledger/C1ledger/index.tsx

@@ -300,7 +300,7 @@ function C1ledger() {
             </Button>
             </Button>
           </Dropdown>
           </Dropdown>
         ) : null}
         ) : null}
-        <Button type='primary' onClick={() => console.log(123)}>
+        <Button type='primary' onClick={() => setIsImportOpen(true)}>
           数据导入
           数据导入
         </Button>
         </Button>
         <Button type='primary' onClick={showModal}>
         <Button type='primary' onClick={showModal}>

+ 134 - 0
src/store/action/Cledger/C1ledger.ts

@@ -1,6 +1,36 @@
 import http from '@/utils/http'
 import http from '@/utils/http'
 import { AppDispatch } from '@/store'
 import { AppDispatch } from '@/store'
+import { Typetable } from '@/pages/Zother/data'
+interface uploadExcelReq {
+  file: any
+  type: string
+  dirCode?: string
+  isCompress?: boolean
+  moduleId?: number
+  usage?: string
+}
 
 
+interface ImportZipReq {
+  description?: string
+  effect?: any
+  fileName?: string
+  filePath?: string
+  id?: number
+  importError?: string
+  importId?: number
+  isTrue?: boolean
+  num?: number
+  type?: string
+}
+
+interface ImportRecordReq {
+  fileName: string
+  filePath: string
+  pcsError: number
+  pcsSuccess: number
+  pcsTotal: number
+  type: string
+}
 /**
 /**
  * 藏品总账-获取藏品详情
  * 藏品总账-获取藏品详情
  */
  */
@@ -52,6 +82,110 @@ export const API_getGoodsLists = (data: any): any => {
 }
 }
 
 
 /**
 /**
+ * 藏品总账-导入数据分页
+ */
+export const API_getImportExcelList = (data: any): any => {
+  return async (dispatch: AppDispatch) => {
+    const res = await http.post(`cms/importExcel/pageList`, { ...data, type: 'excel' })
+    if (res.code === 0) {
+      const obj = {
+        list: res.data.records,
+        total: res.data.total
+      }
+
+      dispatch({ type: 'C1/getImportExcelList', payload: obj })
+    }
+  }
+}
+
+/**
+ * 藏品总账-导入图片分页
+ */
+export const API_getImportZipList = (data: any): any => {
+  return async (dispatch: AppDispatch) => {
+    const res = await http.post(`cms/importZip/pageList`, { ...data, type: 'zip' })
+    if (res.code === 0) {
+      const obj = {
+        list: res.data.records,
+        total: res.data.total
+      }
+
+      dispatch({ type: 'C1/getImportZipList', payload: obj })
+    }
+  }
+}
+
+/**
+ * 藏品总账-导入数据上传附件excel(FormData 格式,用于文件上传+校验)
+ */
+export const API_uploadImportExcel = (formData: FormData): any => {
+  return http.post(`cms/importExcel/uploadExcel`, formData)
+}
+
+/**
+ * 藏品总账-导入图片上传附件excel zip/rar
+ */
+export const API_uploadImportZip = (data: uploadExcelReq): any => {
+  return http.post(`cms/importZip/uploadZip`, data)
+}
+
+/**
+ * 藏品总账-导入数据-导入校验的数据
+ */
+export const API_addImportExcel = (data: Typetable): any => {
+  return http.post(`cms/importExcel/addRow`, data)
+}
+
+/**
+ * 藏品总账-导入图片-导入解压后的图片信息
+ */
+export const API_addImportZip = (data: ImportZipReq): any => {
+  return http.post(`cms/importZip/addZipData`, data)
+}
+
+/**
+ * 藏品总账-导入数据-新增导入上传附件记录
+ */
+export const API_addImportExcelRecord = (data: ImportRecordReq): any => {
+  return http.post(`cms/importExcel/add`, data)
+}
+
+/**
+ * 藏品总账-导入图片-新增导入上传附件记录
+ */
+export const API_addImportZipRecord = (data: ImportRecordReq): any => {
+  return http.post(`cms/importZip/add`, data)
+}
+
+/**
+ * 藏品总账-导入数据-查看导入结果
+ */
+export const API_getImportExcelResult = (id: number): any => {
+  return http.get(`cms/importExcel/detail/${id}`)
+}
+
+/**
+ * 藏品总账-导入数据-删除导入结果
+ */
+export const API_deleteImportExcelResult = (id: number): any => {
+  return http.get(`cms/importExcel/remove/${id}`)
+}
+
+/**
+ * 藏品总账-导入图片-查看导入结果
+ */
+export const API_getImportResult = (id: number): any => {
+  return http.get(`cms/importZip/detail/${id}`)
+}
+
+/**
+ * 藏品总账-导入图片-删除导入结果
+ */
+export const API_deleteImportResult = (id: number): any => {
+  return http.get(`cms/importZip/remove/${id}`)
+}
+
+/**
  * 藏品-附件-根据藏品Id查询
  * 藏品-附件-根据藏品Id查询
  */
  */
 type GetGoodsByGoodIdReq = {
 type GetGoodsByGoodIdReq = {

+ 29 - 5
src/store/reducer/Cledger/C1ledger.ts

@@ -6,14 +6,33 @@ const initState = {
   tableInfo: {
   tableInfo: {
     list: [] as Typetable[],
     list: [] as Typetable[],
     total: 0
     total: 0
+  },
+  // 导入数据分页数据
+  importExcelTableInfo: {
+    list: [] as Typetable[],
+    total: 0
+  },
+  // 导入图片分页数据
+  importZipTableInfo: {
+    list: [] as Typetable[],
+    total: 0
   }
   }
 }
 }
 
 
 // 定义 action 类型
 // 定义 action 类型
-type Props = {
-  type: 'C1/getList'
-  payload: { list: Typetable[]; total: number }
-}
+type Props =
+  | {
+      type: 'C1/getList'
+      payload: { list: Typetable[]; total: number }
+    }
+  | {
+      type: 'C1/getImportExcelList'
+      payload: { list: Typetable[]; total: number }
+    }
+  | {
+      type: 'C1/getImportZipList'
+      payload: { list: Typetable[]; total: number }
+    }
 
 
 // reducer
 // reducer
 export default function Reducer(state = initState, action: Props) {
 export default function Reducer(state = initState, action: Props) {
@@ -21,7 +40,12 @@ export default function Reducer(state = initState, action: Props) {
     // 获取列表数据
     // 获取列表数据
     case 'C1/getList':
     case 'C1/getList':
       return { ...state, tableInfo: action.payload }
       return { ...state, tableInfo: action.payload }
-
+    // 获取导入数据分页数据
+    case 'C1/getImportExcelList':
+      return { ...state, importExcelTableInfo: action.payload }
+    // 获取导入图片分页数据
+    case 'C1/getImportZipList':
+      return { ...state, importZipTableInfo: action.payload }
     default:
     default:
       return state
       return state
   }
   }

+ 4 - 0
src/utils/dataChange.tsx

@@ -164,6 +164,10 @@ export const selectObj = {
     { value: 'SG', label: '事故登记' },
     { value: 'SG', label: '事故登记' },
     { value: 'XZ', label: '现状登记' },
     { value: 'XZ', label: '现状登记' },
     { value: 'XF', label: '修复登记' }
     { value: 'XF', label: '修复登记' }
+  ],
+  校验结果: [
+    { value: 1, label: '成功' },
+    { value: 0, label: '失败' }
   ]
   ]
 }
 }
 
 

+ 18 - 7
src/utils/tableData.ts

@@ -151,7 +151,7 @@ export const goodsFileTableC = [
   ['txt', '藏品登记号', 'joinNum'],
   ['txt', '藏品登记号', 'joinNum'],
   ['txt', '藏品名称', 'joinName'],
   ['txt', '藏品名称', 'joinName'],
   ['dateRes', '上传日期', 'createTime'],
   ['dateRes', '上传日期', 'createTime'],
-  ['txtC', '上传人', 'creatorName'],
+  ['txt', '上传人', 'creatorName'],
   ['sizeNum', '文件大小(mb)', 'fileSize', 1024]
   ['sizeNum', '文件大小(mb)', 'fileSize', 1024]
 ]
 ]
 
 
@@ -236,13 +236,24 @@ export const checkTableC = [
 
 
 // 导入藏品数据/图片
 // 导入藏品数据/图片
 export const importDataTableC = [
 export const importDataTableC = [
-  ['txt', '文件名称', 'name'],
-  ['txt', '导入数据', 'thumb'],
-  ['txt', '成功数据', 'joinNum'],
-  ['txt', '失败数据', 'joinName'],
+  ['txt', '文件名称', 'fileName'],
+  ['txt', '导入数据', 'pcsTotal'],
+  ['txt', '成功数据', 'pcsSuccess'],
+  ['txt', '失败数据', 'pcsError'],
   ['dateRes', '导入日期', 'createTime'],
   ['dateRes', '导入日期', 'createTime'],
-  ['txt', '导入用户', 'creatorName'],
-  ['txt', '导入结果', 'fileSize']
+  ['txt', '导入用户', 'creatorName']
+]
+
+// 导入藏品数据校验
+export const importDataTableCheckC = [
+  ['txt', '藏品登记号', 'num'],
+  ['txt', '藏品名称', 'name'],
+  ['txtChange', '校验结果', 'importIsTrue', { 0: '失败', 1: '成功' }]
+]
+// 导入藏品图片校验
+export const importZipDataTableCheckC = [
+  ['txt', '图片名称', 'fileName'],
+  ['txtChange', '校验结果', 'isTrue', { 0: '失败', 1: '成功' }]
 ]
 ]
 
 
 // 资源使用
 // 资源使用