Parcourir la source

feat: 凭证中心

lanxin il y a 13 heures
Parent
commit
59d21c1bc3

+ 93 - 129
src/pages/Abench/A4proof/index.tsx

@@ -1,130 +1,83 @@
 import React, { useMemo, useState, useEffect } from 'react'
 import styles from './index.module.scss'
-import { selectObj, getDictFu, resJiLianFu } from '@/utils/dataChange'
 import history from '@/utils/history'
 import { MessageFu } from '@/utils/message'
 import { authorityFu } from '@/utils/authority'
 import TableList from '@/pages/Zother/TableList'
 import { useSelector } from 'react-redux'
 import { RootState } from '@/store'
-import { API_getGoodsList, API_getGoodsListAll } from '@/store/action/Abench/A3flow'
+import { API_getGoodsList, API_download } from '@/store/action/Abench/A4proof'
+import { baseURL } from '@/utils/http'
 import { baseFormData } from '@/pages/Zother/data'
-import { flowCenterTableC } from '@/utils/tableData'
-import { Button, Modal, Radio, Checkbox } from 'antd'
-import { exportExcelFile } from '@/utils/xlsxExport'
+import { voucherCenterTableC } from '@/utils/tableData'
+import { Button, message } from 'antd'
 import tabLeftArr from '@/pages/Layout/data'
-import { GI5tableType } from '@/pages/ZgoodsInfo/data'
 
-const ExportModal = ({
-  open,
-  availableYears,
-  onConfirm,
-  onCancel
-}: {
-  open: boolean
-  availableYears: (number | string)[]
-  onConfirm: (exportType: number, years: (number | string)[]) => void
-  onCancel: () => void
-}) => {
-  const [exportValue, setExportValue] = useState<number>(1)
-  const [selectedYears, setSelectedYears] = useState<(number | string)[]>([])
-
-  const onExportTypeChange = (e: any) => {
-    setExportValue(e.target.value)
-  }
-
-  return (
-    <Modal
-      title='数据导出'
-      open={open}
-      onOk={() => onConfirm(exportValue, selectedYears)}
-      onCancel={onCancel}
-      okText='导出'
-      cancelText='取消'
-    >
-      <span style={{ marginBottom: 16 }}>导出范围:</span>
-
-      <Radio.Group
-        onChange={onExportTypeChange}
-        value={exportValue}
-        options={[
-          { value: 1, label: '所有年份' },
-          { value: 2, label: '按年份' }
-        ]}
-      />
-
-      {exportValue === 2 && (
-        <div style={{ marginTop: 24 }}>
-          <Checkbox.Group
-            style={{ flexDirection: 'column', gap: '5px' }}
-            options={availableYears.map(year => ({
-              label: `${year}年`,
-              value: year
-            }))}
-            value={selectedYears}
-            onChange={checkedValues => setSelectedYears(checkedValues as (number | string)[])}
-          />
-          <div style={{ opacity: '0.5', marginTop: '10px' }}>上述年份为藏品制档日期所在年份</div>
-        </div>
-      )}
-    </Modal>
-  )
-}
 function A4proof() {
-  const tableInfo = useSelector((state: RootState) => state.A3flow.tableInfo)
-  const [allData, setAllData] = useState([])
-  const [isModalOpen, setIsModalOpen] = useState(false)
-  const [availableYears, setAvailableYears] = useState<any>([])
+  const tableInfo = useSelector((state: RootState) => state.A4proof.tableInfo)
   const [list, setList] = useState<any[]>([])
-  const showModal = async () => {
-    setIsModalOpen(true)
-    const res = await API_getGoodsListAll()
-    setAllData(res.data.records)
-    //获取年份信息
-    const years = Array.from(
-      new Set(
-        res.data.records
-          .map((item: any) => item.createTime?.slice(0, 4))
-          .filter(Boolean) as string[]
-      )
-    ).sort((a, b) => Number(b) - Number(a))
-    setAvailableYears(years)
-  }
-
-  const dataExport = async (exportType: number = 1, years: (number | string)[] = []) => {
-    // 根据导出范围筛选数据:
-    // exportType === 1:所有年份,不做筛选
-    // exportType === 2:按年份,只保留所选年份的数据
-    const filteredData =
-      exportType === 2 && years.length
-        ? allData.filter((item: any) => {
-            if (!item.createTime) return false
-            const yearStr = item.createTime.slice(0, 4)
-            return years.includes(yearStr)
-          })
-        : allData
+  // 跨页参数
+  const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([])
+
+  // 跨页多选
+  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 listData = filteredData.map((item: any) => {
-      let applyTypeText = '(空)'
-      const obj = list.find((v: any) => v.value === item.type)
-      if (obj) applyTypeText = obj.label
-      let applyStatusText = '(空)'
-      const obj2 = selectObj['藏品入库申请状态'].find((v: any) => v.value === item.status)
-      if (obj2) applyStatusText = obj2.label
-      return {
-        申请类型: applyTypeText,
-        申请编号: item.num,
-        发起部门: item.deptName,
-        发起人: item.creatorName,
-        发起日期: item.date,
-        申请状态: applyStatusText
-      }
-    })
-    // console.log(listData)
-    exportExcelFile(listData, [100, 100, 120, 100, 140, 100], '流程中心数据')
-    setIsModalOpen(false)
+  // 下载方法
+  const downloadFn = async (ids: number | number[]) => {
+    const idArr = Array.isArray(ids) ? ids : [ids]
+    if (!idArr.length) return
+
+    const res: any = await API_download(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 downloadSingleFn = (path: string, fileName: string) => {
+  //   const downloadUrl = `${baseURL}${path}`
+  //   const link = document.createElement('a')
+  //   link.href = downloadUrl
+  //   link.download = fileName
+  //   document.body.appendChild(link)
+  //   link.click()
+  //   document.body.removeChild(link)
+  // }
+  // 申请类型
   useEffect(() => {
     const arr: any[] = []
     tabLeftArr.forEach(v1 => {
@@ -140,9 +93,9 @@ function A4proof() {
     return [
       {
         title: '申请类型',
-        render: (item: GI5tableType) => {
+        render: (item: any) => {
           let txt = '(空)'
-          const obj = list.find(v => v.value === item.type)
+          const obj = list.find(v => v.value === item.moduleName)
           if (obj) txt = obj.label
           return txt
         }
@@ -150,16 +103,16 @@ function A4proof() {
     ]
   }, [list])
 
-  const A3topSearch = useMemo(
+  const A4topSearch = useMemo(
     () => [
       {
         type: 'input',
         key: 'searchKey',
-        placeholder: `请输入凭证名称或申请编号`
+        placeholder: `请输入凭证名称或业务编号`
       },
       {
         type: 'select',
-        key: 'type',
+        key: 'moduleName',
         placeholder: '业务类型',
         options: list
       }
@@ -177,15 +130,20 @@ function A4proof() {
   }) => {
     return (
       <>
-        <Button type='primary' onClick={showModal}>
-          数据导出
+        <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>
-        <ExportModal
-          open={isModalOpen}
-          availableYears={availableYears}
-          onConfirm={dataExport}
-          onCancel={() => setIsModalOpen(false)}
-        />
         <Button type='primary' onClick={clickSearch}>
           查询
         </Button>
@@ -220,10 +178,15 @@ function A4proof() {
               size='small'
               type='text'
               onClick={() => {
-                alert('审批')
+                const id = Number(item.id)
+                if (Number.isNaN(id)) {
+                  message.error('当前附件ID异常,无法下载')
+                  return
+                }
+                downloadFn(id)
               }}
             >
-              审批
+              下载
             </Button>
           </>
         )
@@ -240,14 +203,15 @@ function A4proof() {
         getListAPI={API_getGoodsList}
         pageKey='A4proof'
         tableInfo={tableInfo}
-        columnsTemp={flowCenterTableC}
+        columnsTemp={voucherCenterTableC}
         rightBtnWidth={240}
         leftRowWidth={'20%'}
         yHeight={592}
         staBtn={staBtn}
-        searchDom={A3topSearch}
+        searchDom={A4topSearch}
         storyTableListToprr={storyTableListToprr}
         storyTableLastBtn={storyTableLastBtn}
+        rowSelection={rowSelection}
       />
     </div>
   )

+ 55 - 0
src/store/action/Abench/A4proof.ts

@@ -0,0 +1,55 @@
+import http from '@/utils/http'
+import { AppDispatch } from '@/store'
+
+/**
+ * 流程中心-获取详情
+ */
+export const API_getGoodsInfo = (id: number) => {
+  return http.get(`cms/workVoucher/orderDetail/${id}`)
+}
+
+/**
+ * 流程中心-获取分页列表
+ */
+export const API_getGoodsList = (data: any): any => {
+  return async (dispatch: AppDispatch) => {
+    const res = await http.post(`cms/workVoucher/pageList`, data)
+    if (res.code === 0) {
+      const obj = {
+        list: res.data.records,
+        total: res.data.total
+      }
+
+      dispatch({ type: 'A4/getList', payload: obj })
+    }
+  }
+}
+
+/**
+ * 流程中心-获取全部数据
+ */
+export const API_getGoodsListAll = () => {
+  return http.post(`cms/workVoucher/pageList`, {
+    moduleName: '',
+    pageNum: 1,
+    pageSize: 99999,
+    searchKey: ''
+  })
+}
+
+/**
+ * 流程中心-删除附件
+ */
+// export const API_delFiles = (ids: number[]) => {
+//   return http.post(`cms/workVoucher/removes`, ids)
+// }
+
+/**
+ * 通用下载-批量下载
+ */
+export const API_download = (ids: number[], downloadType?: number) => {
+  return http.post(`cms/file/downloadBatch`, {
+    ids,
+    downloadType
+  })
+}

+ 26 - 0
src/store/reducer/Abench/A4proof.ts

@@ -0,0 +1,26 @@
+// 初始化状态
+const initState = {
+  // 列表数据
+  tableInfo: {
+    list: [] as any[],
+    total: 0
+  }
+}
+
+// 定义 action 类型
+type Props = {
+  type: 'A4/getList'
+  payload: { list: any[]; total: number }
+}
+
+// reducer
+export default function Reducer(state = initState, action: Props) {
+  switch (action.type) {
+    // 获取列表数据
+    case 'A4/getList':
+      return { ...state, tableInfo: action.payload }
+
+    default:
+      return state
+  }
+}

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

@@ -4,6 +4,7 @@ import { combineReducers } from 'redux'
 // 导入 登录 模块的 reducer
 import A0Layout from './layout'
 import A3flow from './Abench/A3flow'
+import A4proof from './Abench/A4proof'
 import B1collect from './Benter/B1collect'
 import B2enterGuan from './Benter/B2enterGuan'
 import B3auth from './Benter/B3auth'
@@ -32,6 +33,7 @@ import I8log from './Isystem/I8log'
 const rootReducer = combineReducers({
   A0Layout,
   A3flow,
+  A4proof,
   B1collect,
   B2enterGuan,
   B3auth,

+ 8 - 0
src/utils/tableData.ts

@@ -210,6 +210,14 @@ export const flowCenterTableC = [
   ['select', '申请状态', 'status', selectObj['藏品入库申请状态']]
 ]
 
+// 凭证中心
+export const voucherCenterTableC = [
+  ['txt', '凭证名称', 'fileName'],
+  ['txt', '归档日期', 'createTime'],
+  ['txt', '归档人', 'creatorName'],
+  ['txt', '业务编号', 'joinNum']
+]
+
 // 藏品盘点
 export const checkTableC = [
   ['txt', '盘点日期', 'createTime'],