Browse Source

藏品附件

lanxin 1 tuần trước cách đây
mục cha
commit
ceccca0ec1

+ 5 - 1
src/components/MyTable/index.tsx

@@ -26,6 +26,8 @@ type Props = {
   // 设置宽度
   widthSet?: any
   rowKey?: string
+  // antd Table rowSelection 配置,支持跨页多选等
+  rowSelection?: any
 }
 
 // 表格内容定制化
@@ -60,7 +62,8 @@ function MyTable({
   myTitle,
   isNull = '(空)',
   widthSet,
-  rowKey
+  rowKey,
+  rowSelection
 }: Props) {
   useEffect(() => {
     const dom = document.querySelector(`.MyTable${classKey} .ant-table-body`) as HTMLDivElement
@@ -182,6 +185,7 @@ function MyTable({
       dataSource={list}
       columns={[...staBtn, ...columns, ...lastBtn]}
       rowKey={rowKey ? rowKey : 'id'}
+      rowSelection={rowSelection}
       pagination={
         pagingInfo
           ? {

+ 3 - 0
src/pages/Cledger/C4file/C4edit/index.module.scss

@@ -0,0 +1,3 @@
+// .B1edit {
+//   // :global {}
+// }

+ 40 - 0
src/pages/Cledger/C4file/C4edit/index.tsx

@@ -0,0 +1,40 @@
+import React from 'react'
+import styles from './index.module.scss'
+import EditTop from '@/pages/Zother/EditTop'
+import EditBtn from '@/pages/Zother/EditBtn'
+import { InfoProvider } from '@/pages/Zother/InfoContext'
+import { rowArrTemp } from '@/pages/Zother/data'
+import { B1API_obj } from '@/store/action/Benter/B1collect'
+import SonClueList from '@/pages/Zother/SonClueList'
+
+const rowArr = rowArrTemp('征集')
+
+function B1edit() {
+  return (
+    <InfoProvider>
+      <div className={styles.B1edit} id='editBox'>
+        <div className='editMain'>
+          {/* 顶部 */}
+          <EditTop
+            pageTxt='藏品征集'
+            rowArr={rowArr}
+            APIobj={B1API_obj}
+            fileUpInfo={{ myUrl: 'cms/order/collect/upload', dirCode: 'collect' }}
+          />
+
+          {/* 线索清单 */}
+          <SonClueList
+            fileUpInfo={{ myUrl: 'cms/order/collect/son/upload', dirCode: 'collectClues' }}
+          />
+
+          {/* 底部按钮 */}
+          <EditBtn path='/collect' APIobj={B1API_obj} checkListTxt='请添加线索' />
+        </div>
+      </div>
+    </InfoProvider>
+  )
+}
+
+const MemoB1edit = React.memo(B1edit)
+
+export default MemoB1edit

+ 4 - 4
src/pages/Cledger/C4file/index.module.scss

@@ -1,4 +1,4 @@
-.C4file {
-  :global {
-  }
-}
+// .C4file {
+//   :global {
+//   }
+// }

+ 252 - 2
src/pages/Cledger/C4file/index.tsx

@@ -1,9 +1,259 @@
-import React from 'react'
+import React, { useMemo, useState } from 'react'
 import styles from './index.module.scss'
+import { useSelector } from 'react-redux'
+import { RootState } from '@/store'
+import { openLink } from '@/utils/history'
+import TableList from '@/pages/Zother/TableList'
+import { API_getFileList, API_downloadFiles, API_getFileLog } from '@/store/action/Cledger/C4file'
+import { goodsFileTableC } from '@/utils/tableData'
+import { Button, message, Modal, Table } from 'antd'
+import { baseURL } from '@/utils/http'
+
+const C4search = [
+  {
+    type: 'input',
+    key: 'searchKey',
+    placeholder: `搜索附件名称、藏品登记号、藏品名称`
+  }
+]
+
+const C4baseFormData = {
+  pageSize: 10,
+  pageNum: 1,
+  searchKey: '',
+  type: ''
+}
+
 function C4file() {
+  // 从仓库拿数据
+  const tableInfo = useSelector((state: RootState) => state.C4file.tableInfo)
+  const [fileType, setFileType] = useState<string>('')
+  const currentTypeValue = fileType
+  // 跨页参数
+  const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([])
+  // 下载记录参数
+  const [isShowDownloadLog, setIsShowDownloadLog] = useState(false)
+  const [downloadLogData, setDownloadLogData] = useState<any[]>([])
+  // 额外参数
+  const extraParams = useMemo(
+    () => ({
+      type: currentTypeValue
+    }),
+    [currentTypeValue]
+  )
+
+  // 跨页多选
+  const rowSelection = useMemo(
+    () => ({
+      selectedRowKeys,
+      // 这里不直接用 onChange 的 keys 覆盖,避免翻页时丢失其他页勾选
+      onChange: () => {},
+      // 单行勾选/取消
+      onSelect: (record: any, selected: boolean) => {
+        const id = record.id as React.Key
+        setSelectedRowKeys(prev => {
+          if (selected) {
+            if (prev.includes(id)) return prev
+            return [...prev, id]
+          } else {
+            return prev.filter(k => k !== id)
+          }
+        })
+      },
+      // 全选/全不选当前页
+      onSelectAll: (selected: boolean, _selectedRows: any[], changeRows: any[]) => {
+        const changeIds = changeRows.map(r => r.id as React.Key)
+        setSelectedRowKeys(prev => {
+          if (selected) {
+            const set = new Set<React.Key>(prev)
+            changeIds.forEach(id => set.add(id))
+            return Array.from(set)
+          } else {
+            return prev.filter(k => !changeIds.includes(k))
+          }
+        })
+      },
+      preserveSelectedRowKeys: true
+    }),
+    [selectedRowKeys]
+  )
+
+  // 下载方法
+  const downloadFn = async (ids: number | number[]) => {
+    const idArr = Array.isArray(ids) ? ids : [ids]
+    if (!idArr.length) return
+
+    const res: any = await API_downloadFiles(idArr)
+    if (res && res.code === 0 && res.data) {
+      const path = res.data as string
+      const fullUrl = path.startsWith('http') ? path : `${baseURL}${path}`
+      window.open(fullUrl)
+    }
+  }
+  // 查看下载记录
+  const downloadLogFn = async (id: number) => {
+    const res: any = await API_getFileLog(id)
+    if (res && res.code === 0 && res.data) {
+      setDownloadLogData(res.data)
+      setIsShowDownloadLog(true)
+      console.log(res.data)
+    }
+  }
+  // 故事管理/藏品总账定制右侧内容
+  const storyTableListToprr = ({
+    clickSearch,
+    resetSelectFu
+  }: {
+    clickSearch: () => void
+    resetSelectFu: () => void
+  }) => {
+    const toggleType = (key: string) => {
+      setFileType(prev => (prev === key ? '' : key))
+    }
+
+    const handleReset = () => {
+      setFileType('')
+      setSelectedRowKeys([])
+      resetSelectFu()
+    }
+
+    return (
+      <>
+        <Button type={fileType === '' ? 'primary' : 'default'} onClick={() => setFileType('')}>
+          全部
+        </Button>
+        <Button type={fileType === 'img' ? 'primary' : 'default'} onClick={() => toggleType('img')}>
+          图像
+        </Button>
+        <Button
+          type={fileType === 'model' ? 'primary' : 'default'}
+          onClick={() => toggleType('model')}
+        >
+          3D
+        </Button>
+        <Button
+          type={fileType === 'audio' ? 'primary' : 'default'}
+          onClick={() => toggleType('audio')}
+        >
+          音频
+        </Button>
+        <Button
+          type={fileType === 'video' ? 'primary' : 'default'}
+          onClick={() => toggleType('video')}
+        >
+          视频
+        </Button>
+        <Button type={fileType === 'doc' ? 'primary' : 'default'} onClick={() => toggleType('doc')}>
+          文档
+        </Button>
+        <Button
+          type={fileType === 'other' ? 'primary' : 'default'}
+          onClick={() => toggleType('other')}
+        >
+          其他
+        </Button>
+        &nbsp;
+        <Button
+          type='primary'
+          onClick={() => {
+            const ids = selectedRowKeys.map(key => Number(key)).filter(id => !Number.isNaN(id))
+            if (ids.length === 0) {
+              message.warning('请先选择要下载的附件')
+              return
+            }
+
+            downloadFn(ids)
+          }}
+        >
+          批量下载
+        </Button>
+        <Button type='primary' onClick={clickSearch}>
+          查询
+        </Button>
+        <Button onClick={handleReset}>重置</Button>
+      </>
+    )
+  }
+
+  // 故事管理/藏品总账定制右侧操作按钮
+  const storyTableLastBtn = useMemo(() => {
+    return [
+      {
+        title: '操作',
+        render: (item: any) => (
+          <>
+            <Button size='small' type='text' onClick={() => openLink(`/goodsLook/${item.id}`)}>
+              查看藏品
+            </Button>
+            <Button
+              size='small'
+              type='text'
+              onClick={() => {
+                const id = Number(item.id)
+                if (Number.isNaN(id)) {
+                  message.error('当前附件ID异常,无法下载')
+                  return
+                }
+                downloadFn(id)
+              }}
+            >
+              下载
+            </Button>
+            <Button size='small' type='text' onClick={() => downloadLogFn(item.id)}>
+              下载记录
+            </Button>
+          </>
+        )
+      }
+    ]
+  }, [])
+
   return (
-    <div className={styles.C4file}>
+    <div className={styles.B1collect}>
       <div className='pageTitle'>藏品附件</div>
+
+      <TableList
+        baseFormData={C4baseFormData}
+        getListAPI={API_getFileList}
+        pageKey='file'
+        tableInfo={tableInfo}
+        columnsTemp={goodsFileTableC}
+        yHeight={585}
+        rightBtnWidth={700}
+        leftRowWidth={'50%'}
+        searchDom={C4search}
+        storyTableListToprr={storyTableListToprr}
+        storyTableLastBtn={storyTableLastBtn}
+        extraParams={extraParams}
+        rowSelection={rowSelection}
+      />
+      <Modal
+        title='下载记录'
+        open={isShowDownloadLog}
+        onCancel={() => setIsShowDownloadLog(false)}
+        footer={null}
+      >
+        <Table
+          rowKey='id'
+          columns={[
+            {
+              title: '下载人员',
+              dataIndex: 'creatorName',
+              key: 'creatorName'
+            },
+            {
+              title: '下载时间',
+              dataIndex: 'createTime',
+              key: 'createTime'
+            }
+          ]}
+          dataSource={downloadLogData}
+          pagination={{
+            pageSize: 3,
+            position: ['bottomCenter']
+          }}
+        />
+      </Modal>
     </div>
   )
 }

+ 14 - 3
src/pages/Zother/TableList/index.tsx

@@ -32,6 +32,10 @@ type Props = {
   storyTableListToprr?: (props: any) => React.ReactNode
   // 故事管理/藏品总账定制操作栏
   storyTableLastBtn?: any
+  // 额外查询参数(不会影响顶部表单状态),在发请求时合并
+  extraParams?: any
+  // antd Table rowSelection 配置(例如跨页多选)
+  rowSelection?: any
 }
 
 const TableList = forwardRef<any, Props>(function TableList(props, ref) {
@@ -46,7 +50,9 @@ const TableList = forwardRef<any, Props>(function TableList(props, ref) {
     rightBtnWidth = 250,
     leftRowWidth = '25%',
     storyTableLastBtn,
-    storyTableListToprr
+    storyTableListToprr,
+    extraParams,
+    rowSelection
   } = props
   const dispatch = useDispatch()
 
@@ -86,8 +92,12 @@ const TableList = forwardRef<any, Props>(function TableList(props, ref) {
 
   // 封装发送请求的函数
   const getListFu = useCallback(() => {
-    dispatch(getListAPI(formDataRef.current))
-  }, [dispatch, getListAPI])
+    const params = {
+      ...formDataRef.current,
+      ...(extraParams || {})
+    }
+    dispatch(getListAPI(params))
+  }, [dispatch, getListAPI, extraParams])
 
   useEffect(() => {
     getListFu()
@@ -228,6 +238,7 @@ const TableList = forwardRef<any, Props>(function TableList(props, ref) {
           pageSize={formData.pageSize}
           total={tableInfo.total}
           onChange={(pageNum, pageSize) => paginationChange(pageNum, pageSize)}
+          rowSelection={rowSelection}
         />
       </div>
     </>

+ 32 - 0
src/store/action/Cledger/C4file.ts

@@ -1,4 +1,5 @@
 import http from '@/utils/http'
+import { AppDispatch } from '@/store'
 
 /**
  * 藏品附件 -根据附件id拿列表
@@ -6,3 +7,34 @@ import http from '@/utils/http'
 export const API_getFileListByIds = (ids: string[]) => {
   return http.post('cms/file/getList', ids)
 }
+
+/**
+ * 藏品附件 -获取藏品附件列表
+ */
+export const API_getFileList = (data: any): any => {
+  return async (dispatch: AppDispatch) => {
+    const res = await http.post(`cms/good/file/page`, data)
+    if (res.code === 0) {
+      const obj = {
+        list: res.data.records,
+        total: res.data.total
+      }
+
+      dispatch({ type: 'C4/getList', payload: obj })
+    }
+  }
+}
+
+/**
+ * 藏品附件 -下载记录
+ */
+export const API_getFileLog = (fileId: number) => {
+  return http.get(`cms/good/file/log/${fileId}`)
+}
+
+/**
+ * 藏品附件 -根据附件id批量下载附件
+ */
+export const API_downloadFiles = (ids: number[]) => {
+  return http.post('cms/good/file/downloadBatchZip', ids)
+}

+ 44 - 0
src/store/reducer/Cledger/C4file.ts

@@ -0,0 +1,44 @@
+export type C4tableType = {
+  createTime: string
+  creatorId: number
+  creatorName: string
+  fileName: string
+  filePath: string
+  fileSize: string
+  id: number
+  joinName: string
+  joinNum: string
+  moduleId: number
+  moduleName: string
+  parentId: number
+  thumb: string
+  type: string
+  updateTime: string
+}
+
+// 初始化状态
+const initState = {
+  // 列表数据
+  tableInfo: {
+    list: [] as C4tableType[],
+    total: 0
+  }
+}
+
+// 定义 action 类型
+type Props = {
+  type: 'C4/getList'
+  payload: { list: C4tableType[]; total: number }
+}
+
+// reducer
+export default function Reducer(state = initState, action: Props) {
+  switch (action.type) {
+    // 获取列表数据
+    case 'C4/getList':
+      return { ...state, tableInfo: action.payload }
+
+    default:
+      return state
+  }
+}

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

@@ -8,6 +8,7 @@ import B2enterGuan from './Benter/B2enterGuan'
 import B3auth from './Benter/B3auth'
 import B4enterCang from './Benter/B4enterCang'
 import C1ledger from './Cledger/C1ledger'
+import C4file from './Cledger/C4file'
 import D1register from './Dmanage/D1register'
 import D3writeOff from './Dmanage/D3writeOff'
 import E1tag from './Eculture/E1tag'
@@ -30,6 +31,7 @@ const rootReducer = combineReducers({
   B3auth,
   B4enterCang,
   C1ledger,
+  C4file,
   D1register,
   D3writeOff,
   E1tag,

+ 8 - 0
src/utils/dataChange.ts

@@ -132,6 +132,14 @@ export const selectObj = {
     { value: '采集', label: '采集' },
     { value: '拣选', label: '拣选' },
     { value: '其他', label: '其他' }
+  ],
+  附件类型: [
+    { value: 'img', label: '图像' },
+    { value: 'model', label: '3D' },
+    { value: 'audio', label: '音频' },
+    { value: 'video', label: '视频' },
+    { value: 'doc', label: '文档' },
+    { value: 'other', label: '其他' }
   ]
 }
 

+ 12 - 0
src/utils/tableData.ts

@@ -142,3 +142,15 @@ export const warehouseSetTableC = [
   ['txt', '库房负责人', 'managerUser'],
   ['txt', '库房说明', 'description']
 ]
+
+//藏品附件
+export const goodsFileTableC = [
+  ['select', '附件类型', 'type', selectObj['附件类型']],
+  ['img', '缩略图', 'thumb'],
+  ['txt', '附件名称', 'fileName'],
+  ['txt', '藏品登记号', 'joinNum'],
+  ['txt', '藏品名称', 'joinName'],
+  ['dateRes', '上传日期', 'createTime'],
+  ['txtC', '上传人', 'creatorName'],
+  ['txt', '文件大小', 'fileSize']
+]