123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626 |
- /*
- * @Author: code4eat awesomedema@gmail.com
- * @Date: 2023-01-04 14:12:31
- * @LastEditors: code4eat awesomedema@gmail.com
- * @LastEditTime: 2024-09-06 11:13:27
- * @FilePath: /BudgetManaSystem/src/pages/budgetMana/oneBatch/index.tsx
- * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
- */
- import BMSPagecontainer from '@/components/BMSPageContainer'
- import { BMSTable } from '@/components/BMSTable';
- import { getComputeDate } from '@/pages/Home/service';
- import { ActionType, ProColumns } from '@ant-design/pro-components';
- import { message, Modal, Popover, Table, Tabs, Tooltip } from 'antd';
- import { useEffect, useRef, useState } from 'react';
- import { caculate, checkRequest, getCheckType, getCurrentCheckStatus, getCurrentZhileiCheckStatus, getData, getZhileiList } from './service';
- import './style.less';
- import { create, all, number } from 'mathjs'
- import * as XLSX from 'xlsx';
- import exportTableToMultiExcel from '@/utils/tableToMultiHeaderExcel';
- import { getJiezhuanStatus } from '../monthlySet/service';
- import { formatMoneyNumber } from '@/utils/format';
- import { createFromIconfontCN } from '@ant-design/icons';
- const IconFont = createFromIconfontCN({
- scriptUrl: '',
- });
- const config = {
- number: 'number',
- precision: 14
- }
- const math = create(all, config as any);
- type JsonStructure = {
- code: string;
- name: string;
- expand?: number;
- childTitle?: JsonStructure[];
- };
- type Column = {
- title: string | JSX.Element;
- dataIndex: string;
- key: string;
- ellipsis: boolean;
- width: number;
- renderText?: any,
- children?: Column[];
- };
- let checkStatusArr: number[] = []
- const OneBatch = () => {
- const [tableColumn, set_tableColumn] = useState<ProColumns[] | any[]>([]);
- const [columnsForExcel, set_columnsForExcel] = useState<ProColumns[] | any[]>([]);
- const [tableData, set_tableData] = useState<any[]>([]);
- const [currentComputeDate, set_currentComputeDate] = useState<string | undefined>();
- const [currentTabKey, set_currentTabKey] = useState('1');
- const [tabs, set_Tabs] = useState<{
- name: any; value: string
- }[]>([]);
- const [tableDataFilterParams, set_tableDataFilterParams] = useState<any | undefined>({ reportCode: undefined });
- const [auditType, set_auditType] = useState('0');
- const [ifShowTip, set_ifShowTip] = useState(false);
- const tableRef = useRef<ActionType>();
- const [tableH, set_tableH] = useState(0);
- const [reportTitle, set_reportTitle] = useState('');
- const [checkType, set_checkType] = useState<string | undefined>(undefined); // 一次分配审核模式,1职类一起审核 2职类分开审核
- const [disAccount, set_disAccount] = useState(false);
- const [ifBanAllAction, set_ifBanAllAction] = useState(true); //是否掩藏所有操作
- const onTabChange = (activeKey: string) => {
- set_currentTabKey(activeKey);
- set_tableDataFilterParams({
- ...tableDataFilterParams,
- reportCode: activeKey
- });
- }
- const [expandedkeys, set_expandedkeys] = useState<string[]>([]);
- const convertToColumnsFunc = (json: JsonStructure[], ifRender?: boolean, level: number = 1): Column[] => {
- return json.map((item) => {
- let column: Column = {
- title: item.name,
- dataIndex: `key-${item.code}`,
- key: `key-${item.code}`,
- ellipsis: true,
- width: 200,
- renderText(text: any) {
- function formatMoney(num: number) {
- if (typeof num !== 'number' || isNaN(num)) {
- return '-';
- }
- return new Intl.NumberFormat('en-US', { minimumFractionDigits: 0, maximumSignificantDigits: 10 }).format(num);
- }
- return formatMoney(text)
- }
- };
- const isExpanded = expandedkeys.includes(item.code);
- if (item.expand === 1 && item.childTitle && item.childTitle.length > 0) {
- column.title = ifRender ? (
- <div style={{ display: 'flex', flexDirection: 'row', justifyContent: 'center', alignContent: 'center' }}>
- <span style={{ display: 'inline-block', maxWidth: '80%', minWidth: 140, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{item.name}</span>
- <div className='expandIcon' onClick={() => {
- if (isExpanded) {
- let _expandedkeys = [...expandedkeys];
- _expandedkeys.splice(expandedkeys.findIndex(a => a == item.code), 1);
- set_expandedkeys([..._expandedkeys]);
- } else {
- set_expandedkeys([...expandedkeys, item.code]);
- }
- }}>
- {isExpanded ? '-' : '+'}
- </div>
- </div>
- ) : item.name;
- if (isExpanded) {
- column.children = convertToColumnsFunc(item.childTitle, ifRender, level + 1);
- }
- }
- return column;
- });
- }
- useEffect(() => {
- tableRef.current?.reload();
- }, [expandedkeys])
- const getTableData = async (params: any, sort: any, filter: any) => {
- const { reportCode = 1 } = params;
- const resp: any = await getData(
- currentComputeDate as string,
- reportCode
- );
- if (resp) {
- const { title, assignmentData, reportName } = resp;
- const columns = convertToColumnsFunc(title, true);
- const columnsForExcel = convertToColumnsFunc(title, false);
- set_tableColumn([
- {
- title: '核算单元代码',
- dataIndex: 'unitCode',
- key: 'unitCode',
- width: 140,
- fixed: 'left',
- ellipsis: true,
- sorter: (a, b) => {
- return b.unitCode.localeCompare(a.unitCode)
- },
- },
- {
- title: '核算单元',
- dataIndex: 'unitName',
- key: 'unitName',
- width: 140,
- fixed: 'left',
- ellipsis: true,
- sorter: (a, b) => {
- return b.unitName.localeCompare(a.unitName)
- },
- },
- ...columns, {
- title: '总奖金',
- dataIndex: 'totalScore',
- key: 'totalScore',
- width: 140,
- fixed: 'right',
- ellipsis: true,
- renderText(text, record, index, action) {
- return formatMoneyNumber(text)
- },
- }]);
- set_columnsForExcel([
- {
- title: '核算单元代码',
- dataIndex: 'unitCode',
- key: 'unitCode',
- width: 140,
- fixed: 'left',
- ellipsis: true,
- sorter: (a, b) => {
- return b.unitCode.localeCompare(a.unitCode)
- },
- },
- {
- title: '核算单元',
- dataIndex: 'unitName',
- key: 'unitName',
- width: 140,
- fixed: 'left',
- ellipsis: true,
- sorter: (a, b) => {
- return b.unitName.localeCompare(a.unitName)
- },
- },
- ...columnsForExcel, {
- title: '总奖金',
- dataIndex: 'totalScore',
- key: 'totalScore',
- width: 140,
- fixed: 'right',
- ellipsis: true,
- renderText(text, record, index, action) {
- return formatMoneyNumber(text)
- },
- }]);
- // set_tableColumn([...mockColumns]);
- // set_columnsForExcel([...mockColumns]);
- const data = assignmentData.map((item: any) => {
- let rowData: { [key: string]: any } = {};
- for (let index = 0; index < item.value.length; index++) {
- for (const key in item.value[index]) {
- if (key != 'code') {
- rowData[`key-${item.value[index].code}`] = item.value[index].value
- }
- }
- }
- return { ...item, ...rowData, id: item.id, columns }
- });
- set_tableData(data);
- set_reportTitle(reportName);
- return {
- data,
- success: true
- }
- }
- return []
- }
- const checkHandle = async (type: string) => {
- if (!checkType) return;
- const resp = await checkRequest({
- computeDate: currentComputeDate as string,
- auditType: type == '0' ? '1' : '0', //审核类型 1审核 0取消审核
- reportCode: checkType == '2' ? currentTabKey : undefined
- }, checkType);
- if (resp) {
- if (type == '0') {
- message.success('审核提交成功!');
- set_auditType('1');
- }
- if (type == '1') {
- message.success('取消审核提交成功!');
- set_auditType('0');
- }
- }
- return resp;
- }
- const getCurrentComputeDate = async () => {
- const resp = await getComputeDate();
- set_currentComputeDate(resp);
- }
- const getTabList = async () => {
- const resp = await getZhileiList();
- if (resp) {
- set_Tabs(resp.list);
- }
- }
- const confirmCaculateHandle = async () => {
- const resp = await caculate(currentComputeDate as string);
- if (resp) {
- tableRef.current?.reload();
- }
- }
- const getCheckStatus = async (computeDate: string, code?: string) => {
- if (checkType == '1') {
- const resp = await getCurrentCheckStatus(computeDate);
- if (resp) {
- set_auditType('1'); //0 未审核 1 已审核
- } else {
- set_auditType('0');
- }
- }
- if (checkType == '2') {
- const resp = await getCurrentZhileiCheckStatus(computeDate, code ? code : currentTabKey);
- if (resp) {
- set_auditType('1'); //0 未审核 1 已审核
- } else {
- set_auditType('0');
- }
- }
- }
- const generateFunc = () => {
- Modal.confirm({
- title: '注意',
- okText: '确定',
- cancelText: '',
- closable: true,
- content: '计算会覆盖原有数据,确定要继续计算操作?',
- onOk: () => confirmCaculateHandle()
- })
- }
- const exportHandle = async (flag: number) => {
- if (!flag) {
- exportTableToMultiExcel([{ data: tableData, columns: columnsForExcel, sheetName: reportTitle }], `${reportTitle}.xlsx`, true);
- } else {
- const sheetsData = [];
- for (const tab of tabs) {
- const resp: any = await getData(currentComputeDate as string, Number(tab.value));
- if (resp) {
- const { title, assignmentData } = resp;
- const columnsForExcel = convertToColumnsFunc(title, false);
- const columns = [
- {
- title: '核算单元代码',
- dataIndex: 'unitCode',
- key: 'unitCode',
- width: 140,
- fixed: 'left',
- ellipsis: true,
- sorter: (a: { unitCode: any; }, b: { unitCode: string; }) => {
- return b.unitCode.localeCompare(a.unitCode)
- },
- },
- {
- title: '核算单元',
- dataIndex: 'unitName',
- key: 'unitName',
- width: 140,
- fixed: 'left',
- ellipsis: true,
- sorter: (a: { unitName: any; }, b: { unitName: string; }) => {
- return b.unitName.localeCompare(a.unitName)
- },
- },
- ...columnsForExcel, {
- title: '总奖金',
- dataIndex: 'totalScore',
- key: 'totalScore',
- width: 140,
- fixed: 'right',
- ellipsis: true,
- renderText(text: number, record: any, index: any, action: any) {
- return formatMoneyNumber(text)
- },
- }];
- const data = assignmentData.map((item: any) => {
- let rowData: { [key: string]: any } = {};
- for (let index = 0; index < item.value.length; index++) {
- for (const key in item.value[index]) {
- if (key !== 'code') {
- rowData[`key-${item.value[index].code}`] = item.value[index].value;
- }
- }
- }
- return { ...item, ...rowData, id: item.id, columns };
- });
- sheetsData.push({ data, columns, sheetName: tab.name });
- }
- }
- exportTableToMultiExcel(sheetsData, `一次分配报表数据.xlsx`, true);
- }
- }
- const handleResize = (e: any) => {
- const wH = e.target.innerHeight;
- const tableHeight = wH - 290;
- set_tableH(tableHeight);
- }
- const getCheckTypeHandle = async () => {
- const resp = await getCheckType();
- if (resp && resp.list.length > 0) {
- set_checkType(resp.list[0].value);
- }
- }
- function doResize() {
- setTimeout(() => {
- const ev: any = new Event('resize');
- window.dispatchEvent(ev);
- }, 0)
- }
- useEffect(() => {
- if (tabs.length > 0) {
- set_currentTabKey(tabs[0].value);
- }
- }, [tabs]);
- useEffect(() => {
- if (currentComputeDate && checkType == '2') {
- getCheckStatus(currentComputeDate as string);
- }
- }, [currentTabKey]);
- useEffect(() => {
- if (checkType == '2') {
- checkStatusArr = [];
- tabs.forEach(async (item) => {
- const resp = await getCurrentZhileiCheckStatus(currentComputeDate as string, item.value);
- checkStatusArr.push(resp);
- if (checkStatusArr.length == tabs.length) {
- const total = [...checkStatusArr].reduce((prev, cur) => prev + cur, 0);
- total > 0 ? set_disAccount(true) : set_disAccount(false)
- }
- })
- }
- }, [auditType]);
- const getJiezhuanStatusHandle = async () => {
- const resp = await getJiezhuanStatus(currentComputeDate as string);
- if (resp == 2) {
- set_ifBanAllAction(true);
- } else {
- set_ifBanAllAction(false);
- }
- }
- useEffect(() => {
- if (currentComputeDate && checkType) {
- getCheckStatus(currentComputeDate);
- getJiezhuanStatusHandle();
- }
- }, [currentComputeDate, checkType]);
- useEffect(() => {
- getCurrentComputeDate();
- window.addEventListener('resize', (e) => handleResize(e)) //监听窗口大小改变
- doResize();
- getTabList();
- getCheckTypeHandle();
- return () => {
- window.removeEventListener('resize', (e) => handleResize(e))
- }
- }, [])
- return (
- <BMSPagecontainer className='OneBatch' title={`核算年月:${currentComputeDate}`}>
- <div className='btnGroup'>
- {
- !ifBanAllAction && (
- <Popover open={ifShowTip} content={'当前处于审核中,无法操作!'} >
- <div style={{ display: 'flex', flexDirection: 'row', alignItems: 'center' }}>
- <div className={(auditType == '0' && !disAccount) ? 'caculateBtn' : 'caculateBtn disabled'}
- onMouseEnter={() => auditType == '0' ? set_ifShowTip(false) : set_ifShowTip(true)}
- onMouseLeave={() => set_ifShowTip(false)}
- onClick={() => (auditType == '0' && !disAccount) ? generateFunc() : () => { }}>计算</div>
- <div className={auditType == '0' ? 'caculateBtn' : 'caculateBtn disabled'}
- style={{ marginRight: 8 }}
- onMouseEnter={() => auditType == '0' ? set_ifShowTip(false) : set_ifShowTip(true)}
- onMouseLeave={() => set_ifShowTip(false)}
- onClick={() => auditType == '0' ? exportHandle(1) : () => { }}>
- 导出全部
- <Tooltip title="将所有职类的数据导出到一个excel文件并分sheet页放置">
- <IconFont type="iconshuoming" style={{ fontSize: 16, paddingLeft: 10 }} />
- </Tooltip>
- </div>
- <div className={auditType == '0' ? 'caculateBtn' : 'caculateBtn disabled'}
- onMouseEnter={() => auditType == '0' ? set_ifShowTip(false) : set_ifShowTip(true)}
- onMouseLeave={() => set_ifShowTip(false)}
- onClick={() => auditType == '0' ? exportHandle(0) : () => { }}>
- 导出当前
- <Tooltip title={tabs.length>0?`将${(tabs.filter((a)=>a.value == currentTabKey))[0].name}的数据导出到excel文件`:''}>
- <IconFont type="iconshuoming" style={{ fontSize: 16, paddingLeft: 10 }} />
- </Tooltip>
- </div>
- </div>
- </Popover>
- )
- }
- {!ifBanAllAction && <div className='checkBtn' onClick={() => checkHandle(`${auditType}`)}>{auditType == '0' ? '审核' : '取消审核'}</div>}
- </div>
- <div className='content'>
- <Tabs
- defaultActiveKey='1'
- onChange={onTabChange}
- items={[
- ...tabs.map(a => ({ label: a.name, key: a.value }))
- ]}
- />
- <div className='tabContent'>
- {currentComputeDate && <BMSTable actionRef={tableRef} rowKey='unitCode' bordered pagination={false} columns={tableColumn as ProColumns[]}
- params={tableDataFilterParams}
- scroll={{ x: 140 * tableColumn.length, y: tableH }}
- request={(params, sort, filter) => getTableData(params, sort, filter)}
- summary={(pageData) => {
- const Caculate = ({ colData }: { colData: any }) => {
- const { dataIndex, children } = colData;
- if (children) {
- return children.map((child: any, index: number) => (
- <Caculate key={index} colData={child} />
- ));
- }
- const total = pageData.reduce((prev, cur) => {
- //return prev + cur[`${dataIndex}`]
- if (typeof cur[`${dataIndex}`] == 'number') {
- return math.add(prev, cur[`${dataIndex}`] as number);
- }
- }, 0);
- return dataIndex == "unitName" ? <div style={{ textAlign: 'left' }}>合计</div> : (
- //<span>{typeof total == 'number'?math.format(total, {precision: 14}) : '合计'}</span>
- <span style={{ textAlign: 'left' }}>{typeof total == 'number' ? Number(total.toFixed(4)) : '-'}</span>
- )
- }
- const renderSummaryRow = (columns: any[]): React.ReactNode[] => {
- return columns.map((colData, index) => {
- if (colData.children) {
- return renderSummaryRow(colData.children);
- } else {
- return (
- <Table.Summary.Cell key={index} index={index} align='center' rowSpan={1}>
- <Caculate colData={colData} />
- </Table.Summary.Cell>
- );
- }
- });
- };
- return (
- <Table.Summary fixed>
- <Table.Summary.Row>
- {renderSummaryRow(tableColumn)}
- </Table.Summary.Row>
- </Table.Summary>
- );
- }}
- />}
- </div>
- </div>
- </BMSPagecontainer>
- )
- }
- export default OneBatch
|