/* * @Author: code4eat awesomedema@gmail.com * @Date: 2022-12-16 09:42:52 * @LastEditors: code4eat awesomedema@gmail.com * @LastEditTime: 2023-09-25 13:57:31 * @FilePath: /BudgetManaSystem/src/pages/budgetMana/monthlySet/index.tsx * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE */ import BMSPagecontainer from '@/components/BMSPageContainer'; import { useEffect, useRef, useState } from 'react'; import './style.less'; import { TreeProps, Input, Modal, message, Popover, Table, Switch, Tooltip, DatePicker, ConfigProvider } from 'antd'; import { DataNode } from 'antd/es/tree'; import expandedIcon from '../../../../static/treenode_open.png'; import closeIcon from '../../../../static/treenode_collapse.png'; import { BMSTable } from '@/components/BMSTable'; import { ActionType, ProColumns, ProFormDatePicker, ProFormDigit, ProFormInstance, ProFormSelect } from '@ant-design/pro-components'; import { createFromIconfontCN } from '@ant-design/icons'; import { autoComputedReq, checkCurrentRequest, checkRequest, commitRequest, getCurrentCheckStatusReq, getCurrentCommitStatusReq, getCurrentUnitCheckStatusReq, getSecondaryDistriComputeTableData, getTreeData, getTreeDataRespType, save } from './service'; import { getComputeDate } from '@/pages/Home/service'; import React from 'react'; import DirectoryTree from 'antd/es/tree/DirectoryTree'; import { getDeepestTreeData } from '@/utils/tooljs'; import { getCurrentCheckStatus } from '@/services/auth'; import { useLocation } from '@umijs/max'; import { useAccess } from '@umijs/max'; import { getParamsData } from '@/pages/setting/baseSetting/paramsMana/service'; import 'moment/locale/zh-cn'; import locale from 'antd/es/date-picker/locale/zh_CN'; import moment from 'moment'; import { getJiezhuanStatus } from '@/pages/budgetMana/monthlySet/service'; import { formatMoneyNumber } from '@/utils/format'; const SearchIcon = createFromIconfontCN({ scriptUrl: '', }); export type TableListItem = { key: number; name: string; }; const SecondaryDitriComputed: React.FC = () => { const location = useLocation(); const access = useAccess(); const userFunctionInThispage = access.whatCanIDoInThisPage(location.pathname); const [ifCheckPage, set_ifCheckPage] = useState(false); //是否为二次分配审核页面 const [treeData, set_treeData] = useState([]); const [treeDataDefault, set_treeDataDefault] = useState([]); const [tableColumn, set_tableColumn] = useState([]); const [currentSelectedTreeNode, set_currentSelectedTreeNode] = useState(); const [currentComputeDate, set_currentComputeDate] = useState(); const [ifShowTip, set_ifShowTip] = useState(false); const [commitStatus, set_commitStatus] = useState('0'); //提交状态 const [empFilterParams, set_empFilterParams] = useState(undefined); const [expandedKeys, setExpandedKeys] = useState([]); const [searchValue, setSearchValue] = useState(''); const [autoExpandParent, setAutoExpandParent] = useState(true); const [ifEditMode, set_ifEditMode] = useState(false); const [auditType, set_auditType] = useState('0'); //审核状态 const [currentUnitAuditType, set_currentUnitAuditType] = useState('0'); //当前单元审核状态 const tableRef = useRef(); const [needSaveData, set_needSaveData] = useState(undefined); const [inputsRefKeys, set_inputsRefKeys] = useState([]); const inputsRef = useRef<{ [key: string]: any }>({}); const [pageData, set_pageData] = useState({ total: 0, completedTotal: 0, leftTotal: 0 }); const [dataSource, set_dataSource] = useState([]); const [currentInputRefKeys, set_currentInputRefKeys] = useState(undefined); const [tableH, set_tableH] = useState(0); const [currentTreeDataFilter, set_currentTreeDataFilter] = useState({ name: '全部单元', code: 0 }); const [treeFilterVisible, set_treeFilterVisible] = useState(false); const [ifBanAllAction, set_ifBanAllAction] = useState(true); //是否掩藏所有操作 const column: ProColumns[] = [ // { // title: '工号', // width:120, // fixed: 'left', // dataIndex: 'account', // }, { title: '姓名', width: 140, fixed: 'left', dataIndex: 'name', renderText(text, record, index, action) { return `${record.name}(${record.account})` }, }, ]; const onSelect: TreeProps['onSelect'] = (selectedKeys, info: any) => { // console.log('selected', selectedKeys, info); if (!ifEditMode) { //编辑时,需要先保存后切换 const { node } = info; if (!node.child) { set_currentSelectedTreeNode(node); } } else { Modal.confirm({ title: '提示', content: '当前存在编辑未保存,请先保存!', okText: '确定', cancelText: '取消', }) } }; const getCurrentComputeDate = async () => { const resp = await getComputeDate(); set_currentComputeDate(resp); } const getCheckStatus = async (computeDate: string) => { const resp = await getCurrentCheckStatusReq(computeDate); set_auditType(`${resp}`); //0 未审核 1 已审核 } const getCurrentUnitCheckStatus = async () => { if (currentSelectedTreeNode) { const resp = await getCurrentUnitCheckStatusReq(currentComputeDate as string, currentSelectedTreeNode.code); set_currentUnitAuditType(`${resp}`); //0 未审核 1 已审核 } } const getCurrentCommitStatus = async () => { if (currentSelectedTreeNode) { const resp = await getCurrentCommitStatusReq({ computeDate: currentComputeDate as string, unitCode: currentSelectedTreeNode.code }); set_commitStatus(`${resp}`); } } const gennerateColumns = (data: { title: any; userList: any; }, inputsRefKeys?: string[]) => { const { title } = data; const _columns = title.map((item: any, index: number) => { return { title: item.name, dataIndex: `${item.code}`, width: 160, renderText: (_: any, record: any) => { if (ifEditMode) { let _val = _; return { inputsRef.current[`${record.account}-${item.code}`] = ref; //console.log({ref}); }, onBlur: () => { const updatedUserList = needSaveData.userList.map((a: any) => { if (a.account == record.account) { const arr = a.itemValue.map((b: any) => { if (b.code == item.code) { return { ...b, value: _val ? _val : 0 } //value有为undefined的可能 } else { return b } }); return { ...a, itemValue: arr } } else { return a } }); set_needSaveData({ ...needSaveData, userList: updatedUserList }) }, onChange(value) { _val = value ? value : 0; }, onPressEnter: (event: any) => { if (event.code === 'Enter') { event.preventDefault(); const value = event.target.value ? Number(event.target.value) : 0; const updatedUserList = needSaveData.userList.map((a: any) => { if (a.account == record.account) { const arr = a.itemValue.map((b: any) => { if (b.code == item.code) { return { ...b, value: value ? value : 0 } //value有为undefined的可能 } else { return b } }); return { ...a, itemValue: arr } } else { return a } }); set_needSaveData({ ...needSaveData, userList: updatedUserList }); const index = inputsRefKeys ? inputsRefKeys.findIndex(a => a == `${record.account}-${item.code}`) : -1; //console.log({index,input:inputsRef.current,inputsRefKeys}); const nextInput = inputsRefKeys ? inputsRef.current[inputsRefKeys[index + 1]] : null; if (nextInput) { inputsRefKeys && set_currentInputRefKeys(inputsRefKeys[index + 1]); nextInput.focus(); } } }, onFocus: () => set_currentInputRefKeys(`${record.account}-${item.code}`), defaultValue: _, }} width={120} /> } else { return {formatMoneyNumber(_)} } }, } }); set_tableColumn([...column, ..._columns, { title: '总奖金', dataIndex: 'totalScore', width: 120, fixed: 'right', renderText(text, record, index, action) { return formatMoneyNumber(text); }, }, ]); } const getTableData = async (params: any) => { if (currentSelectedTreeNode && currentComputeDate) { const resp = await getSecondaryDistriComputeTableData({ computeDate: currentComputeDate, unitCode: currentSelectedTreeNode.code, ...params, }); if (resp) { set_needSaveData(resp); //buildTableData(resp); } } return [] } const buildTableData = (resp: any, inputsRefKeys?: string[]) => { const { title, userList } = resp; const _columns = gennerateColumns(resp, inputsRefKeys); const data = userList.map((item: any) => { let total = 0; let rowData: { [key: string]: any } = {}; item.itemValue.forEach((b: any) => { const needTitle = title.filter((a: any) => a.code == b.code); if (needTitle.length > 0) { rowData[`${needTitle[0].code}`] = b.value } total = total + b.value; }); return { ...item, ...rowData, id: Math.random(), _columns, totalScore: Number(total.toFixed(2)) } }); const compeltedTotal = data.reduce((prev: any, cur: any) => prev + cur.totalScore, 0); const leftTotal = resp.totalBonus - compeltedTotal; set_pageData({ ...pageData, total: resp.totalBonus?resp.totalBonus.toFixed(2):0, completedTotal: compeltedTotal.toFixed(2), leftTotal: Number(leftTotal.toFixed(2)) }); set_dataSource(data); } const commitBtnhandle = async (type?: number) => { //console.log({type}); /** * type 1 单个 2 全部 * 提交界面不需要type */ const handle = async (ifCheckCommit: string) => { if (type == 1) { //审核单个 const resp = await checkCurrentRequest({ computeDate: currentComputeDate as string, auditType: currentUnitAuditType == '1' ? '0' : '1', //1 审核 0 取消审核 unitCode: currentSelectedTreeNode.code, type: ifCheckCommit }); if (resp) { message.success('操作成功!'); getTreeReqFunc(currentComputeDate as string, ifCheckPage ? '1' : '0'); getCurrentUnitCheckStatus(); } } if (type == 2) { const resp = await checkRequest({ computeDate: currentComputeDate as string, auditType: auditType == '1' ? '0' : '1', //1 审核 0 取消审核 type: ifCheckCommit }); if (resp) { message.success('操作成功!'); getTreeReqFunc(currentComputeDate as string, ifCheckPage ? '1' : '0'); getCheckStatus(currentComputeDate as string); } } } if (ifCheckPage && type) { const checkCondition = await getParamsData({ pageSize: 500 }); if (checkCondition) { const needParamsVal = checkCondition.list.filter(a => a.code == '1664510428258115584'); //判断未提交是否可以审核 if (needParamsVal.length > 0) { if (needParamsVal[0].value == '0') { handle(needParamsVal[0].value); } else { handle(needParamsVal[0].value); } } } } else { if (commitStatus == '1') { Modal.confirm({ title: '注意', okText: '确定', cancelText: '取消', content: `${commitStatus == '1' ? '取消提交' : '提交'}当前选择的核算单元的数据?`, onOk: async () => { const resp = await commitRequest({ computeDate: currentComputeDate as string, unitCode: currentSelectedTreeNode.code, type: commitStatus == '1' ? '0' : '1', //1 提交 0 取消 }); if (resp) { message.success('提交成功!'); getTreeReqFunc(currentComputeDate as string, ifCheckPage ? '1' : '0'); getCurrentCommitStatus(); } } }) } else { if(pageData.leftTotal != 0){ Modal.confirm({ title: '提交时需有单元的剩余分配金额必须是0', okText: '确定', cancelText: '取消', }) }else { Modal.confirm({ title: '注意', okText: '确定', cancelText: '取消', content: `${commitStatus == '1' ? '取消提交' : '提交'}当前选择的核算单元的数据?`, onOk: async () => { const resp = await commitRequest({ computeDate: currentComputeDate as string, unitCode: currentSelectedTreeNode.code, type: commitStatus == '1' ? '0' : '1', //1 提交 0 取消 }); if (resp) { message.success('提交成功!'); getTreeReqFunc(currentComputeDate as string, ifCheckPage ? '1' : '0'); getCurrentCommitStatus(); } } }) } } } } const dataList: any[] = []; const getParentKey = (key: React.Key, tree: any[]): React.Key => { let parentKey: React.Key; for (let i = 0; i < tree.length; i++) { const node = tree[i]; if (node.child) { if (node.child.some((item: { code: React.Key; }) => item.code === key)) { parentKey = node.code; } else if (getParentKey(key, node.child)) { parentKey = getParentKey(key, node.child); } } } return parentKey!; }; const onTreeSearchKeyChange = (e: React.ChangeEvent) => { const { value } = e.target; const newExpandedKeys = dataList .map((item) => { if (item.name.indexOf(value) > -1) { return getParentKey(item.code, treeData); } return null; }); const b = newExpandedKeys.filter((item, i, self) => item && self.indexOf(item) === i); setExpandedKeys(newExpandedKeys as React.Key[]); setSearchValue(value); setAutoExpandParent(true); } //左侧树结构筛选 const changeTreeDataFilter = (obj: any) => { set_currentTreeDataFilter(obj); set_treeFilterVisible(false); interface Node { map: boolean; child?: Node[]; } function filterNodes(node: Node): Node | null { if (node.map === (obj.code == 1 ? false : true) && (!node.child || node.child.length === 0)) { return node; // 如果节点map为false并且是叶子节点,返回该节点 } if (Array.isArray(node.child)) { // 对每个子节点递归执行此过程 let child = node.child.map(filterNodes).filter((n): n is Node => n !== null); if (child.length > 0) { // 如果有任何子节点的map属性为false,返回包含这些子节点的新节点 return { ...node, child: child }; } } // 如果节点map为true,或者所有子节点的map都为true,返回null return null; } if (obj.code == 0) { set_treeData(treeDataDefault); } else { const result = treeDataDefault.map(a => { return filterNodes(a); }); set_treeData(result.filter(b => b != null) as any); } } const onExpand = (newExpandedKeys: React.Key[]) => { setExpandedKeys(newExpandedKeys); setAutoExpandParent(false); }; const generateList = (data: getTreeDataRespType[]) => { for (let i = 0; i < data.length; i++) { const node = data[i]; const { code, name } = node; dataList.push({ code: code, name: name }); if (node.child) { generateList(node.child); } } }; generateList(treeData as any); const getTreeReqFunc = async (computeDate: string, type: string) => { const resp = await getTreeData(computeDate, type); if(resp){ set_treeDataDefault(resp); } } const handleResize = (e: any) => { const wH = e.target.innerHeight; const tableHeight = wH - 290; set_tableH(tableHeight); } function doResize() { setTimeout(() => { const ev: any = new Event('resize'); window.dispatchEvent(ev); }, 0) } const autoComputed =async () => { const resp = await autoComputedReq({computeDate:currentComputeDate as string,unitCode:currentSelectedTreeNode.code}); if(resp){ message.success('操作成功!'); getTableData({}); } } const computeHandle = () => { Modal.confirm({ title: '注意', content: '重新计算会覆盖原有数据,确定要继续计算操作?', onOk(...args) { autoComputed(); }, }) } const saveHandle = async () => { const resp = await save(needSaveData); if (resp) { message.success('操作成功!'); set_ifEditMode(false); } } const getJiezhuanStatusHandle = async () => { const resp = await getJiezhuanStatus(currentComputeDate as string); if (resp == 2) { set_ifBanAllAction(true); } else { set_ifBanAllAction(false); } } useEffect(() => { if (currentComputeDate) { getTreeReqFunc(currentComputeDate, ifCheckPage ? '1' : '0'); getCheckStatus(currentComputeDate); getJiezhuanStatusHandle(); } }, [currentComputeDate]); useEffect(() => { //tableRef.current?.reload(); if (currentComputeDate && currentSelectedTreeNode) { if (!ifCheckPage) { getCurrentCommitStatus(); } if (ifCheckPage) { getCurrentUnitCheckStatus(); } getTableData({}); } }, [currentSelectedTreeNode, currentComputeDate]); //console.log({inputsRef,inputsRefKeys}); useEffect(() => { //初始化左侧树结构数据后 if (treeData?.length > 0) { if (!currentSelectedTreeNode) { if (treeData[0].child && treeData[0].child.length > 0) { const [node, nodeParent] = getDeepestTreeData(treeData[0], 'child'); set_currentSelectedTreeNode(node); setExpandedKeys([nodeParent.code]); getCurrentCommitStatus(); } } } }, [treeData]); useEffect(() => { if (location.pathname == "/secondaryDistribute/secondaryDitriCheck") { set_ifCheckPage(true); } else { set_ifCheckPage(false); } }, [location]) useEffect(() => { if (needSaveData) { buildTableData(needSaveData, inputsRefKeys); } }, [needSaveData]); useEffect(() => { if (dataSource && Object.keys(inputsRef.current).length > 0) { currentInputRefKeys && inputsRef.current[currentInputRefKeys].focus(); } }, [dataSource]) useEffect(() => { if (auditType == '1') { //当审核中时,禁掉所有操作 set_commitStatus('1'); } }, [auditType]); useEffect(() => { let keys: string[] = []; if (ifEditMode && needSaveData) { //获取所有输入框的ref key const { userList } = needSaveData; userList.forEach((a: any) => { a.itemValue.forEach((b: any) => { keys.push(`${a.account}-${b.code}`) }) }); set_inputsRefKeys(keys); } if (needSaveData) { if (ifEditMode) { gennerateColumns(needSaveData, keys) } else { gennerateColumns(needSaveData) } } if (!ifEditMode) { set_currentInputRefKeys(undefined); getTableData({}); //重新拉数据 } }, [ifEditMode]); useEffect(() => { if (ifEditMode && Object.keys(inputsRef.current).length > 0 && inputsRefKeys.length > 0) { inputsRef.current[`${inputsRefKeys[0]}`].focus(); set_currentInputRefKeys(inputsRefKeys[0]); } }, [inputsRef, inputsRefKeys]); useEffect(()=>{ changeTreeDataFilter(currentTreeDataFilter); },[treeDataDefault]) useEffect(() => { set_tableColumn(column as ProColumns[]); getCurrentComputeDate(); window.addEventListener('resize', (e) => handleResize(e)) //监听窗口大小改变 doResize(); return () => { window.removeEventListener('resize', (e) => handleResize(e)) } }, []); return (
{ treeFilterVisible && (
changeTreeDataFilter({ name: '全部单元', code: 0 })} className={currentTreeDataFilter.code == 0 ? 'list on' : 'list'}>全部单元
changeTreeDataFilter({ name: ifCheckPage ? '未审核' : '未提交', code: 1 })} className={currentTreeDataFilter.code == 1 ? 'list on' : 'list'}>{ifCheckPage ? '未审核' : '未提交'}
changeTreeDataFilter({ name: ifCheckPage ? '已审核' : '已提交', code: 2 })} className={currentTreeDataFilter.code == 2 ? 'list on' : 'list'}>{ifCheckPage ? '已审核' : '已提交'}
) }
} />
set_treeFilterVisible(true)}>
{ treeData && treeData.length > 0 && currentSelectedTreeNode && ( null} titleRender={ (nodeData: any) => { const strTitle = nodeData.name as string; const index = strTitle.indexOf(searchValue); const beforeStr = strTitle.substring(0, index); const afterStr = strTitle.slice(index + searchValue.length); const title = index > -1 ? ( {beforeStr} {searchValue} {afterStr} ) : ( {strTitle} ); return
{title} {!nodeData.map && }
} } defaultSelectedKeys={[treeData[0].child[0].code]} treeData={treeData as unknown as DataNode[]} // treeData={treeDataNew} switcherIcon={(props: any) => { const { expanded } = props; return !expanded ? : }} /> ) }
{/*
*/}
{currentComputeDate && (
核算年月: { set_currentComputeDate(dateString); }} allowClear={false} picker='month' locale={locale} defaultValue={moment(currentComputeDate,'YYYY-MM')} format='YYYY-MM' placeholder="请选择核算年月" />
)}
{ (!ifCheckPage&&!ifBanAllAction) && ( //计算界面 <>
auditType == '0' ? commitStatus == '1' ? set_ifShowTip(true) : set_ifShowTip(false) : set_ifShowTip(true)} onMouseLeave={() => set_ifShowTip(false)} > {(!ifEditMode&&userFunctionInThispage && (userFunctionInThispage.findIndex((a: { code: string, name: string }) => a.code == 'calculate') != -1)) && computeHandle() : () => { }}>计算} {!ifEditMode && set_ifEditMode(true) : () => { }}>编辑} {ifEditMode && set_ifEditMode(false) : () => { }}>取消} {ifEditMode && saveHandle() : () => { }}>保存}
{!ifEditMode &&
auditType == '0' ? commitBtnhandle() : () => { }}>{commitStatus == '1' ? '取消提交' : '提交'}
} ) } { !ifBanAllAction&&ifCheckPage && userFunctionInThispage && (userFunctionInThispage.findIndex((a: { code: string, name: string }) => a.code == 'audit') != -1) && ( <>
commitBtnhandle(1)}>{currentUnitAuditType == '1' ? '取消审核单个' : '审核单个'}
commitBtnhandle(2)}>{auditType == '1' ? '取消审核全部' : '审核全部'}
) }
可分配总额: {pageData.total} 已分配总额: {pageData.completedTotal} 剩余分配总额: {pageData.leftTotal}
{currentSelectedTreeNode && { const Caculate = ({ colData }: { colData: any }) => { const { dataIndex } = colData; const total = pageData.reduce((prev, cur) => { return prev + cur[`${dataIndex}`] }, 0); if (dataIndex != 'account' && dataIndex != 'name' && dataIndex != 'submitName') { return ( {formatMoneyNumber(Number(total.toFixed(2)))} ) } if (dataIndex == 'name') { return 合计 } return <> } return ( { tableColumn.map((item, index) => { return ( ) }) } ); }} />}
); }; export default SecondaryDitriComputed;