123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687 |
- /*
- * @Author: code4eat awesomedema@gmail.com
- * @Date: 2023-01-04 14:12:31
- * @LastEditors: code4eat awesomedema@gmail.com
- * @LastEditTime: 2024-11-15 14:31:22
- * @FilePath: /BudgetManaSystem/src/pages/budgetMana/oneBatch/index.tsx
- * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
- */
- import { ActionType, ProColumns, ProFormText } from '@ant-design/pro-components';
- import { Space, Dropdown, MenuProps, DatePicker } from 'antd';
- import { useEffect, useRef, useState } from 'react';
- import { getData, getRedirReportData, getSearchRowsReq } from './service';
- import './style.less';
- import { createFromIconfontCN, DownOutlined } from '@ant-design/icons';
- import exportTableToExcel from '@/utils/tableToExcel';
- import 'moment/locale/zh-cn';
- import locale from 'antd/es/date-picker/locale/zh_CN';
- import moment from 'moment';
- import { formatMoneyNumber } from '@/utils/format';
- import KCIMPagecontainer from '@/components/KCIMPageContainer';
- import { KCIMTable } from '@/components/KCIMTable';
- import { getStringWidth } from '@/utils/tooljs';
- import ExportProgressModal from './ExportProgressModal';
- import { getParamsDataBySysId } from '@/services/getDic';
- import { useModel, useParams } from '@umijs/max';
- const IconFont = createFromIconfontCN({
- scriptUrl: '',
- });
- interface Searchable {
- [key: string]: string;
- }
- let searchKeys: any[] = [];
- let totalTableData: any[] = [];
- let dataSource: any[] = [];
- let tableDataSearchKeywords: undefined | string = undefined;
- let currentPage = 0;
- let maxFetchCount = 0;
- let prevParams: any = null;
- function multiAttributeSearchOptimized(dataArray: any[], keys: any[], keywords: any[]) {
- // 确保关键词为非空数组
- if (!Array.isArray(keywords) || keywords.length === 0) {
- return dataArray;
- }
- const lowerCaseKeywords = keywords.map(kw => kw.toLowerCase());
- return dataArray.filter((item: { [x: string]: any; }) => {
- // 对每一项数据进行指定属性的搜索
- return keys.some((key: string | number) => {
- const value = item[key];
- // 确保属性存在且为字符串类型
- if (typeof value === 'string') {
- // 遍历每一个关键词,判断是否存在匹配
- return lowerCaseKeywords.some(keyword => value.toLowerCase().includes(keyword));
- }
- return false;
- });
- });
- }
- const ReportExport = ({ reportCode, propsParams, tableScrollH }: { reportCode: string, propsParams: any, tableScrollH: number }) => {
- const { reportCode: urlReportCode } = reportCode ? { reportCode } : useParams();
- const [tableColumn, set_tableColumn] = useState<ProColumns[] | any[]>([]);
- const [tableScrollX, set_tableScrollX] = useState<number>(1000);
- const { initialState, setInitialState } = useModel('@@initialState');
- const [currentComputeDate, set_currentComputeDate] = useState<string | undefined>(propsParams ? propsParams.compute_date : (initialState ? initialState.computeDate : undefined));
- const [breadCrumbList, set_breadCrumbList] = useState<any[]>([]);
- const [tableDataFilterParams, set_tableDataFilterParams] = useState<any | undefined>(propsParams ? { parameter: propsParams } : undefined);
- const tableRef = useRef<ActionType>();
- const [loading, set_loading] = useState(true);
- const [tableH, set_tableH] = useState(tableScrollH ? tableScrollH : 0);
- const [step, set_step] = useState(0);
- const [reportName, set_reportName] = useState('');
- const [pageSize, set_pageSize] = useState(20);
- const [openProcessModal, set_openProcessModal] = useState(false);
- const [searchRows, set_searchRows] = useState<any[]>([]);
- const [tableData, set_tableData] = useState<any[]>([]);
- const [searchType, set_searchType] = useState(0);
- const [pagination, set_pagination] = useState<any>(null);
- const reportJumphandle = (reportData: any) => {
- set_loading(true);
- set_searchRows([]);
- let parameter: { [key: string]: any } = {};
- const { redirectParameter = undefined } = reportData;
- const _step = step + 1;
- if (redirectParameter) {
- const tempArr = redirectParameter.split('|');
- tempArr.forEach((element: string) => {
- parameter[`${element}`] = reportData[`${element}`]
- });
- }
- set_breadCrumbList(
- [...breadCrumbList,
- {
- index: _step,
- name: reportData[`report_name`] || reportData[`redirectReportName`],
- params: {
- reportCode: reportData.redirectReportCode,
- parameter: {
- ...parameter
- }
- }
- }
- ]
- );
- set_step(_step);
- getSearchRows(reportData.redirectReportCode, parameter);
- totalTableData = [];
- currentPage = 0;
- dataSource = [];
- }
- const getSearchRows = async (code: string, others?: any) => {
- const resp = await getSearchRowsReq(code);
- if (resp) {
- const rows = resp.reportIndex ? resp.reportIndex : [];
- set_searchType(resp.indexType);
- set_searchRows(rows);
- const searchObject = rows.reduce((acc: { [x: string]: any; }, curr: { columnIndex: string | number; value: any; }) => {
- acc[curr.columnIndex] = '';
- return acc;
- }, {});
- set_tableDataFilterParams({ ...tableDataFilterParams, reportCode: code, parameter: { ...others, compute_date: currentComputeDate, ...searchObject, ...(reportCode ? tableDataFilterParams?.parameter : {}) } });
- }
- }
- const getTableData = async (params: any) => {
- if (!openProcessModal) {
- set_loading(true);
- }
-
- if (!params.reportCode || (JSON.stringify(prevParams) === JSON.stringify(params))) {
- // 参数相同,不执行请求
- return;
- }
- const { systemId } = JSON.parse(localStorage.getItem('currentSelectedTab') as string)
- const paramsData = await getParamsDataBySysId(systemId, '1806523783696224256');
- const pageSize = paramsData.value ? Number(paramsData.value) : 100;
- set_pageSize(pageSize);
- const { parameter = {}, current, reportCode } = params;
- searchKeys = [];
- let resp: any = undefined;
- if (step != 0) {
- //报表跳转
- resp = await getRedirReportData(
- { pageSize, current },
- reportCode,
- { ...parameter, compute_date: currentComputeDate, }
- );
- }
- if (step == 0) {
- //首次获取表格数据
- resp = await getData(
- { pageSize, current },
- urlReportCode as string,
- { ...parameter, compute_date: currentComputeDate, }
- );
- }
- if (resp) {
- prevParams = params;
- const { title, data: assignmentData, reportName, current, totalCount, totalPage, pageSize } = resp;
- set_reportName(reportName);
- let scrollX = 0;
- const columns: ProColumns[] = title.map((item: any, index: number) => {
- if (item.search) {
- searchKeys.push({ name: item.name, key: item.columnName });
- }
- const wid = (item.name.length * 17) > 100 ? (item.name.length * 17) : 100;
- scrollX = scrollX + wid;
- return {
- title: item.name,
- dataIndex: `${item.columnName}`,
- key: `${item.columnName}`,
- width: wid,
- ellipsis: true,
- fixed: item.freeze ? true : false,
- hideInTable: item.hide,
- align: (item.dataType == 3 || item.dataType == 2) ? 'right' : 'left',
- sorter: item.sortStatus ? (a: any, b: any) => {
- if (item.dataType == 3) {
- //数值
- return b[`${item.columnName}`] - (a[`${item.columnName}`]);
- } else {
- return b[`${item.columnName}`]?.localeCompare(a[`${item.columnName}`]);
- }
- } : undefined,
- renderText: (_: string | number, record: any) => {
- if (item.redirect) {
- if (item.redirectData && item.redirectData.length > 1) {
- const items: MenuProps['items'] = [
- ...(item.redirectData.map((a: any, index: number) => ({
- key: index,
- label: (
- <a onClick={() => reportJumphandle({ ...item, ...record, ...a })}>
- {a.redirectReportName}
- </a>
- ),
- })))
- ];
- return <Dropdown menu={{ items }}>
- <a onClick={(e) => e.preventDefault()}>
- <Space>
- {(item.dataType && item.dataType == 3 && _) && formatMoneyNumber(Number(Number(_).toFixed(item.decimalPlace ? item.decimalPlace : 2)))}
- {(item.dataType && item.dataType == 2 && _ && typeof _ == 'number') && `${(_ * 100).toFixed(item.decimalPlace ? item.decimalPlace : 2)}%`}
- {(item.dataType != 2 && item.dataType != 3) && _}
- <DownOutlined />
- </Space>
- </a>
- </Dropdown>
- } else {
- return <a className='active' onClick={() => reportJumphandle({ ...item.redirectData[0], ...record })}>
- {(item.dataType && item.dataType == 3 && _) && formatMoneyNumber(Number(Number(_).toFixed(item.decimalPlace ? item.decimalPlace : 2)))}
- {(item.dataType && item.dataType == 2 && _ && typeof _ == 'number') && `${(_ * 100).toFixed(item.decimalPlace ? item.decimalPlace : 2)}%`}
- {(item.dataType != 2 && item.dataType != 3) && _}
- </a>
- }
- }
- return <span >
- {(item.dataType && item.dataType == 3 && _) && formatMoneyNumber(Number(Number(_).toFixed(item.decimalPlace ? item.decimalPlace : 2)))}
- {(item.dataType && item.dataType == 2 && _ && typeof _ == 'number') && `${(_ * 100).toFixed(item.decimalPlace ? item.decimalPlace : 2)}%`}
- {(item.dataType != 2 && item.dataType != 3) && _}
- </span>
- }
- }
- });
- set_tableColumn([...columns]);
- set_tableScrollX(scrollX);
- const data = assignmentData.map((item: any) => {
- let rowData: { [key: string]: any } = {};
- item.forEach((b: any) => {
- const needTitle = title.filter((a: any) => a.code == b.code);
- if (needTitle.length > 0) {
- rowData[`${needTitle[0].columnName}`] = b.value
- }
- });
- return { ...item, ...rowData, id: Math.random(), columns }
- });
- const exportdata = assignmentData.map((item: any) => {
- let rowData: { [key: string]: any } = {};
- item.forEach((b: any) => {
- const needTitle = title.filter((a: any) => a.code == b.code);
- if (needTitle.length > 0) {
- if (needTitle[0].dataType == 2 && typeof b.value == 'number') {
- rowData[`${needTitle[0].columnName}`] = `${(b.value * 100).toFixed(needTitle[0].decimalPlace ? needTitle[0].decimalPlace : 2)}%`
- } else {
- rowData[`${needTitle[0].columnName}`] = b.value
- }
- }
- });
- return { ...item, ...rowData, id: Math.random(), columns }
- });
- if (openProcessModal) {
- totalTableData = [...totalTableData, ...exportdata];
- return {
- currentCount: totalTableData.length,
- totalCount,
- totalPage
- }
- }
- if (!openProcessModal) {
- set_tableData(data);
- dataSource = data;
- set_pagination({
- current,
- total: totalCount,
- pageSize: pageSize,
- totalPage: totalPage,
- })
- }
- } else {
- prevParams = undefined;
- if (!openProcessModal) {
- set_tableData([]);
- dataSource = [];
- set_pagination(false)
- }
- }
- if (!openProcessModal) {
- set_loading(false);
- }
- return openProcessModal ? { currentCount: 0, totalCount: 0 } : []
- }
- const handleResize = (e: any) => {
- const wH = e.target.innerHeight;
- const tableHeight = wH - 290;
- if (!reportCode) {
- set_tableH(tableHeight);
- }
- }
- function doResize() {
- setTimeout(() => {
- const ev: any = new Event('resize');
- window.dispatchEvent(ev);
- }, 0)
- }
- const exportHandle = () => {
- // set_openProcessModal(true);
- let headers: { [key: string]: any } = {};
- let data: any[] = [];
- tableColumn.forEach(a => {
- if (a.hideInTable != 1) {
- headers[`${a.dataIndex}`] = a.title;
- }
- });
- totalTableData.forEach(b => {
- let _temp: { [key: string]: any } = {};
- Object.keys(headers).forEach(key => {
- _temp[`${key}`] = b[`${key}`]
- });
- data.push(_temp);
- });
- //console.log({tableColumn,headers,tableData,data});
- const excelTableData = [
- ...data
- ];
- const _columns = tableColumn.filter(a => a.hideInTable != 1);
- exportTableToExcel(excelTableData, _columns as any[], reportName);
- currentPage = 0;
- maxFetchCount = 0;
- totalTableData = [];
- // tableRef.current?.reload();
- }
- const fetchExportData = async () => {
- currentPage = currentPage + 1;
- const resp: any = await getTableData({ ...tableDataFilterParams, current: currentPage });
- if (resp) {
- const { currentCount = 0, totalCount = 0, totalPage } = resp;
- maxFetchCount = totalPage;
- return { currentCount, totalCount };
- } else {
- return { currentCount: 0, totalCount: 0 };
- }
- };
- const handleCompletion = () => {
- set_openProcessModal(false);
- exportHandle();
- }
- //面包屑跳转
- const switchHandle = (data: any) => {
- set_loading(true);
- set_step(data.index);
- const _breadCrumbList = breadCrumbList.filter((a: any) => a.index <= data.index);
- set_breadCrumbList([..._breadCrumbList]);
- getSearchRows(data.params.reportCode);
- }
- const handleSearchChange = (e: any, node: any, index: number) => {
- const { value } = e.target;
- // 更新搜索内容
- set_searchRows((prevSearchRows) => {
- const updatedSearchRows = [...prevSearchRows];
- updatedSearchRows[index] = { ...updatedSearchRows[index], value };
- return updatedSearchRows;
- });
- };
- const handleReset = () => {
- set_searchRows((prevSearchRows) => {
- const newObj = prevSearchRows.map((row) => ({ ...row, value: '' }))
- const searchObject = newObj.reduce((acc, curr) => {
- acc[curr.columnIndex] = curr.value ? curr.value : '';
- return acc;
- }, {});
- set_tableDataFilterParams({ ...tableDataFilterParams, parameter: { ...( tableDataFilterParams.parameter), ...searchObject } });
- return newObj
- }
- );
- };
- const tableDataSearchHandle = () => {
- const searchObject = searchRows.reduce((acc, curr) => {
- acc[curr.columnIndex] = curr.value ? curr.value : '';
- return acc;
- }, {});
- set_tableDataFilterParams({
- ...tableDataFilterParams,
- parameter: { ...(tableDataFilterParams.parameter), ...searchObject }
- });
- }
- const tableDataColumnSearchHandle = () => {
- if (tableDataSearchKeywords) {
- // 确保 searchKeys 不为空
- if (searchKeys.length === 0) {
- set_tableData(dataSource);
- return;
- }
- const keys = searchKeys.map(a => a.key);
- const result = multiAttributeSearchOptimized(tableData, keys, [tableDataSearchKeywords as string]);
- set_tableData(result);
- } else {
- // 恢复到初始数据
- set_tableData(dataSource);
- }
- };
- useEffect(() => {
- // 在这里处理路由参数变化的逻辑
- set_loading(true);
- set_tableDataFilterParams(undefined);
- set_breadCrumbList([{
- name: '首页',
- index: 0,
- params: { reportCode: urlReportCode, parameter: { ...(reportCode ? tableDataFilterParams?.parameter : {}), compute_date: currentComputeDate } }
- }]);
- urlReportCode && getSearchRows(urlReportCode);
- }, [urlReportCode]);
- useEffect(() => {
- if (currentComputeDate) {
- const searchObject = searchRows.reduce((acc: { [x: string]: any; }, curr: { columnIndex: string | number; value: any; }) => {
- acc[curr.columnIndex] = '';
- return acc;
- }, {});
- set_tableDataFilterParams({ ...tableDataFilterParams, parameter: { ...(reportCode ? tableDataFilterParams?.parameter : {}), compute_date: currentComputeDate,...searchObject } });
- }
- }, [currentComputeDate]);
- useEffect(() => {
- if (tableDataFilterParams) {
- getTableData(tableDataFilterParams);
- }
- }, [tableDataFilterParams]);
- useEffect(() => {
- window.addEventListener('resize', (e) => handleResize(e)) //监听窗口大小改变
- doResize();
- return () => {
- window.removeEventListener('resize', (e) => handleResize(e))
- }
- }, [])
- return (
- <KCIMPagecontainer className='ReportTemplate' title={false} style={reportCode ? { border: 'none' } : {}}>
- <ExportProgressModal
- visible={openProcessModal}
- onCancel={() => set_openProcessModal(false)}
- fetchData={fetchExportData}
- onCompletion={handleCompletion}
- />
- {
- breadCrumbList.length > 1 && <div className='breadcrumb'>
- {
- breadCrumbList.map((item: any, index: number) => {
- return (
- <>
- <span className={index != step ? 'tab' : 'tab actived'} key={index} onClick={() => { index != step && switchHandle(item) }}>{item.name}</span>{index == breadCrumbList.length - 1 ? '' : <span style={{ color: '#7A8599' }}> / </span>}
- </>
- )
- })
- }
- </div>
- }
- <div className='contentWrap' style={reportCode ? { padding: 0 } : {}}>
- <div className='toolbar'>
- {(currentComputeDate && !reportCode) && (<div className='search'>
- <span>核算年月:</span>
- <DatePicker
- disabled={breadCrumbList.length>1}
- onChange={(data, dateString) => {
- set_currentComputeDate(dateString);
- setInitialState((s: any) => ({ ...s, computeDate: dateString }))
- }}
- allowClear={false}
- picker='month'
- locale={locale}
- autoComplete="off"
- value={moment(currentComputeDate, 'YYYY-MM')}
- format='YYYY-MM' placeholder="请选择核算年月" />
- <div style={{ display: (searchType == 1 && searchKeys.length > 0) ? 'flex' : 'none', flexDirection: 'row', alignItems: 'center', marginLeft: 16 }}>
- <span style={{ whiteSpace: 'nowrap' }}>检索:</span>
- <ProFormText
- noStyle
- // style={{width:(searchKeys.length)*20}}
- width={((searchKeys.length) * 100) > 675 ? 675 : (searchKeys.length) * 100}
- placeholder={searchKeys.reduce((prev, cur) => `${prev.length > 0 ? prev + '/' : prev}${cur.name}`, '')}
- fieldProps={{
- suffix:
- < IconFont type="iconsousuo" style={{ color: '#99A6BF' }} onClick={() => tableDataColumnSearchHandle()} />
- ,
- onChange: (e) => {
- if (e.target.value) {
- tableDataSearchKeywords = e.target.value
- } else {
- tableDataSearchKeywords = undefined;
- tableDataColumnSearchHandle();
- }
- },
- onPressEnter: (e) => tableDataColumnSearchHandle()
- }}
- />
- </div>
- <div style={{ display: (searchRows && searchRows.length > 0) ? 'flex' : 'none', flexDirection: 'row', alignItems: 'center', marginLeft: 8 }}>
- {/* <span style={{ whiteSpace: 'nowrap' }}>检索:</span> */}
- {
- (searchRows ? searchRows : []).map((node, index) => {
- return (
- <ProFormText
- key={index}
- noStyle
- width={150}
- // allowClear={false}
- style={{ marginRight: 8 }}
- placeholder={`${node.tips}`}
- fieldProps={{
- style: { marginRight: 8 },
- value: node.value,
- // suffix:
- // < IconFont type="iconsousuo" style={{ color: '#99A6BF' }}
- // />
- // ,
- onChange: (e) => {
- handleSearchChange(e, node, index)
- },
- }}
- />
- )
- })
- }
- </div>
- </div>)}
- {!reportCode && <div style={{ display: 'flex', flexDirection: 'row', alignItems: 'center' }}>
- {searchType == 2 && <div className='searchBtn' onClick={() => handleReset()}>重置</div>}
- {searchType == 2 && <div className='searchBtn' onClick={() => tableDataSearchHandle()}>查询</div>}
- <div className='export' onClick={() => set_openProcessModal(true)}>导出</div>
- </div>}
- </div>
- <div className='ReportTemplateContent' style={reportCode ? { paddingTop: 0 } : {}}>
- {/* {(currentComputeDate&&(searchType == 0||searchType == 2) ) && <KCIMTable actionRef={tableRef} rowKey='id' columns={tableColumn as ProColumns[]}
- params={tableDataFilterParams}
- scroll={{ x: tableScrollX, y: tableH }}
- loading
- pagination={{ pageSizeOptions: [10, 20, 50, 100, 1000], showSizeChanger: true, pageSize }}
- request={(params, sort, filter) => getTableData(params)}
- />} */}
- {(currentComputeDate) && <KCIMTable actionRef={tableRef} rowKey='id' columns={tableColumn as ProColumns[]}
- // params={tableDataFilterParams}
- loading={loading}
- scroll={{ x: tableScrollX, y: tableH }}
- dataSource={tableData}
- pagination={searchType == 1 ? { pageSizeOptions: [10, 20, 50, 100, 1000], showSizeChanger: true, pageSize } : {
- ...pagination,
- onChange(page, pageSize) {
- getTableData({ ...tableDataFilterParams, current: page, pageSize });
- },
- }}
- />}
- </div>
- </div>
- </KCIMPagecontainer>
- )
- }
- export default ReportExport
|