index.tsx 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. /*
  2. * @Author: code4eat awesomedema@gmail.com
  3. * @Date: 2023-01-03 14:20:22
  4. * @LastEditors: code4eat awesomedema@gmail.com
  5. * @LastEditTime: 2023-08-03 10:02:42
  6. * @FilePath: /BudgetManaSystem/src/pages/budgetMana/personnelSalaryBudget/index.tsx
  7. * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  8. */
  9. import BMSPagecontainer from '@/components/BMSPageContainer'
  10. import { BMSTable } from '@/components/BMSTable';
  11. import { getComputeDate } from '@/pages/Home/service';
  12. import { createFromIconfontCN } from '@ant-design/icons';
  13. import { ActionType, ProColumns } from '@ant-design/pro-components';
  14. import { Input, InputNumber, message, Modal } from 'antd';
  15. import React, { useEffect, useRef, useState } from 'react'
  16. import { caculate, checkRequest, editAssessmentBonus, generate, getCurrentCheckStatus, getData } from './service';
  17. import editIcon from '../../../../static/editIcon.png';
  18. import conformIcon from '../../../../static/confirmIcon.png';
  19. import './style.less';
  20. import '../../../utils/zhongtaiB'
  21. import { formatMoneyNumber } from '@/utils/format';
  22. import { getJiezhuanStatus } from '../monthlySet/service';
  23. import { getParams } from '../monthlyInfoCheck/service';
  24. const IconFont = createFromIconfontCN({
  25. scriptUrl: '',
  26. });
  27. const PersonnelSalaryBudget = () => {
  28. const [auditType, set_auditType] = useState('0');
  29. const [currentComputeDate, set_currentComputeDate] = useState<string | undefined>();
  30. const [pageData, set_pageData] = useState({
  31. rate: 0, income: 0, personalCost: 0, cost: 0
  32. });
  33. const [editTableCellId, set_editTableCellId] = useState<number | undefined>(undefined);
  34. const [inputSalaryNum, set_inputSalaryNum] = useState(0);
  35. const tableRef = useRef<ActionType>();
  36. const [loading, set_loading] = useState(false);
  37. const [ifBanAllAction, set_ifBanAllAction] = useState(true); //是否掩藏所有操作
  38. const [ifEditTable,set_ifEditTable] = useState(true);
  39. const [ifEditIncome,set_ifEditIncome] = useState(false);
  40. const [ifEditCost,set_ifEditCost] = useState(false);
  41. const [ifEditRate,set_ifEditRate] = useState(false);
  42. const tableColumn: ProColumns[] = [
  43. {
  44. title: '职类',
  45. dataIndex: 'unitTypeName',
  46. key: 'unitTypeName',
  47. fixed:'left'
  48. },
  49. {
  50. title: '合理编制比例',
  51. dataIndex: 'staffRate',
  52. key: 'staffRate',
  53. },
  54. {
  55. title: '合理人均薪酬系数',
  56. dataIndex: 'averageSalary',
  57. key: 'averageSalary',
  58. },
  59. {
  60. title: '人事成本占比',
  61. dataIndex: 'percent',
  62. key: 'percent',
  63. },
  64. {
  65. title: '人事成本',
  66. dataIndex: 'cost',
  67. key: 'cost',
  68. renderText(num, record, index, action) {
  69. return formatMoneyNumber(num)
  70. },
  71. },
  72. {
  73. title: '基金',
  74. dataIndex: 'fundBonus',
  75. key: 'fundBonus',
  76. renderText(num, record, index, action) {
  77. return formatMoneyNumber(num)
  78. },
  79. },
  80. {
  81. title: '固定工资',
  82. dataIndex: 'salary',
  83. key: 'salary',
  84. renderText(num, record, index, action) {
  85. return formatMoneyNumber(num)
  86. },
  87. },
  88. {
  89. title: '专项补助',
  90. dataIndex: 'subsidies',
  91. key: 'subsidies',
  92. renderText(num, record, index, action) {
  93. return formatMoneyNumber(num)
  94. },
  95. },
  96. {
  97. title: '变动薪酬',
  98. dataIndex: 'variableCompensation',
  99. key: 'variableCompensation',
  100. renderText(num, record, index, action) {
  101. return formatMoneyNumber(num)
  102. },
  103. },
  104. {
  105. title: '不参与考核奖金',
  106. dataIndex: 'noAssessmentBonus',
  107. key: 'noAssessmentBonus',
  108. renderText(num, record, index, action) {
  109. return formatMoneyNumber(num)
  110. },
  111. },
  112. {
  113. title: '合理化考核奖金',
  114. dataIndex: 'rationalizeBonus',
  115. key: 'rationalizeBonus',
  116. renderText(num, record, index, action) {
  117. return formatMoneyNumber(num)
  118. },
  119. }
  120. ]
  121. const getPageData = async (currentComputeDate: string, params: any, sort: any, filter: any) => {
  122. const resp = await getData(currentComputeDate);
  123. if (resp) {
  124. set_pageData({
  125. rate: resp.rate,
  126. income: resp.income,
  127. personalCost: resp.personalCost,
  128. cost: resp.cost
  129. });
  130. return {
  131. data: resp.detail,
  132. success: true,
  133. }
  134. }
  135. return []
  136. }
  137. const checkHandle = async (type: string) => {
  138. const resp = await checkRequest({
  139. computeDate: currentComputeDate as string,
  140. auditType: type == '0' ? '1' : '0', //审核类型 1审核 0取消审核
  141. });
  142. if (resp) {
  143. if (type == '0') {
  144. message.success('审核提交成功!');
  145. set_auditType('1');
  146. }
  147. if (type == '1') {
  148. message.success('取消审核提交成功!');
  149. set_auditType('0');
  150. }
  151. }
  152. }
  153. const getCurrentComputeDate = async () => {
  154. const resp = await getComputeDate();
  155. set_currentComputeDate(resp);
  156. }
  157. const getCheckStatus = async (computeDate: string) => {
  158. const resp = await getCurrentCheckStatus(computeDate);
  159. if (resp) {
  160. set_auditType(`${resp}`); //0 未审核 1 已审核
  161. }
  162. }
  163. const editHandle = async (record: any) => {
  164. const { id } = record;
  165. if (id == editTableCellId) {
  166. //保存
  167. if (inputSalaryNum) {
  168. const resp = await editAssessmentBonus({
  169. assessmentBonus: inputSalaryNum,
  170. id
  171. });
  172. if (resp) {
  173. tableRef.current?.reload();
  174. }
  175. }
  176. set_editTableCellId(undefined);
  177. } else {
  178. //编辑
  179. set_editTableCellId(id);
  180. }
  181. }
  182. const confirmGenerateHandle = async (index: number) => {
  183. if (index == 1) {
  184. const resp = await generate(currentComputeDate as string);
  185. if (resp) {
  186. message.success('生成完成!');
  187. tableRef.current?.reload();
  188. }
  189. }
  190. if (index == 2) {
  191. const resp = await caculate({
  192. computeDate: currentComputeDate as string,
  193. ...pageData
  194. });
  195. if (resp) {
  196. message.success('计算完成!');
  197. tableRef.current?.reload();
  198. }
  199. }
  200. }
  201. const generateFunc = (index: number) => {
  202. /**
  203. * index == 1 生成 2 计算
  204. *
  205. */
  206. if (auditType == '1') {
  207. Modal.confirm({
  208. title: '注意',
  209. okText: '确定',
  210. cancelText: '',
  211. closable: true,
  212. content: '当前处于审核状态无法操作!',
  213. });
  214. return;
  215. }
  216. Modal.confirm({
  217. title: '注意',
  218. okText: '确定',
  219. cancelText: '',
  220. closable: true,
  221. content: index == 1 ? '生成后需重新计算数据,确定要进行生成操作?' : '计算会覆盖原有数据,确定要继续计算操作?',
  222. onOk: () => { set_loading(true); confirmGenerateHandle(index) }
  223. });
  224. }
  225. const getJiezhuanStatusHandle =async () => {
  226. const resp = await getJiezhuanStatus(currentComputeDate as string);
  227. if(resp == 2){
  228. set_ifBanAllAction(true);
  229. }else{
  230. set_ifBanAllAction(false);
  231. }
  232. }
  233. const setPageType = async () => {
  234. const resp = await getParams();
  235. if(resp){
  236. const needItems = resp.list.filter((a:any)=>a.code =='1686657454764597248' );
  237. if(needItems.length>0){
  238. if(needItems[0].value == '2'){
  239. set_ifEditTable(true);
  240. }else{
  241. set_ifEditTable(false);
  242. }
  243. }
  244. }
  245. }
  246. useEffect(() => {
  247. currentComputeDate && getCheckStatus(currentComputeDate);
  248. currentComputeDate && getJiezhuanStatusHandle();
  249. }, [currentComputeDate]);
  250. useEffect(() => {
  251. getCurrentComputeDate();
  252. setPageType();
  253. }, []);
  254. return (
  255. <BMSPagecontainer className='PersonnelSalaryBudget' title={`核算年月:${currentComputeDate}`} ghost>
  256. {!ifBanAllAction&&<div className='checkBtn' onClick={() => checkHandle(`${auditType}`)}>{auditType == '0' ? '审核' : '取消审核'}</div>}
  257. <div className='paramsWrap'>
  258. <div className='cardWrap'>
  259. <div className='card'>
  260. <span>收入</span>
  261. <div className='count'>
  262. {!ifEditIncome&&pageData.income}
  263. {(ifEditIncome&&ifEditTable)&&<Input style={{width:160}} autoFocus defaultValue={pageData.income} onBlur={()=>{
  264. set_ifEditIncome(false);
  265. }} />}
  266. {(!ifEditIncome&&ifEditTable)&&<div className='editBtn' onClick={()=>set_ifEditIncome(true)}><img src={editIcon} alt="" /></div>}
  267. </div>
  268. </div>
  269. <div className='card'>
  270. <span>成本</span>
  271. <div className='count'>
  272. {!ifEditCost&&pageData.cost}
  273. {(ifEditCost&&ifEditTable)&&<Input style={{width:160}} autoFocus defaultValue={pageData.cost} onBlur={()=>{
  274. set_ifEditCost(false);
  275. }} />}
  276. {(!ifEditCost&&ifEditTable)&&<div className='editBtn' onClick={()=>set_ifEditCost(true)}><img src={editIcon} alt="" /></div>}
  277. </div>
  278. </div>
  279. <div className='card'>
  280. <span>合理人事成本比例系数</span>
  281. <div className='count'>
  282. {!ifEditRate&&pageData.rate}
  283. {(ifEditRate&&ifEditTable)&&<Input style={{width:160}} autoFocus defaultValue={pageData.rate} onBlur={()=>{
  284. set_ifEditRate(false);
  285. }} />}
  286. {(!ifEditRate&&ifEditTable)&&<div className='editBtn' onClick={()=>set_ifEditRate(true)}><img src={editIcon} alt="" /></div>}
  287. </div>
  288. </div>
  289. </div>
  290. <div className='func'>
  291. <div className='title'>
  292. <span className='a'>全院人事成本(D=(A-B)*C)</span>
  293. {!ifBanAllAction&&<span className='btn' onClick={() => generateFunc(1)}> <IconFont style={{ color: '#3376FE' }} type='iconzhongxin' /> 重新生成</span>}
  294. </div>
  295. <InputNumber className={ifEditTable?'input borderUpper':'input'} size='large' min={-10000000} value={pageData.personalCost} placeholder='请输入'
  296. disabled={auditType == '1'}
  297. onChange={(value) => set_pageData({ ...pageData, personalCost: value as number })} />
  298. </div>
  299. {/* <div className='midLine'>
  300. <span>手动计算</span>
  301. 根据手动填写的全院人事成本计算出各职系的
  302. </div> */}
  303. </div>
  304. {!ifBanAllAction&&<div className='countBtn' onClick={() => generateFunc(2)}>计算</div>}
  305. <div className='b'>计算结果</div>
  306. {currentComputeDate && <BMSTable actionRef={tableRef} pagination={false} rowKey='unitType' scroll={{ x: 140 * 11 }} columns={[...tableColumn, {
  307. title: '可分配考核奖金',
  308. dataIndex: 'assessmentBonus',
  309. key: 'assessmentBonus',
  310. fixed: 'right',
  311. render: (text: any, record: any) => {
  312. if(ifBanAllAction)return text
  313. return (
  314. <div style={{ display: 'flex', flexDirection: 'row', width: '100%', justifyContent:'flex-start', alignItems: 'center' }}>
  315. <div style={{ height: 16, display: 'flex', flexDirection: 'row', justifyContent: 'center', alignItems: 'center' }}>
  316. {
  317. editTableCellId == record.id ? <Input size='small' defaultValue={record.assessmentBonus} width={80} placeholder='请输入' onChange={(e) => { set_inputSalaryNum(Number(e.target.value)) }} style={{ width: '80px' }} /> : <span>{formatMoneyNumber(text)}</span>
  318. }
  319. </div>
  320. {auditType == '0' && <img onClick={() => editHandle(record)} style={{ width: 16, height: 16, cursor: 'pointer', marginLeft: 8 }} src={editTableCellId == record.id ? conformIcon : editIcon} alt="" />}
  321. </div>
  322. )
  323. }
  324. },]} request={(params, sort, filter) => getPageData(currentComputeDate, params, sort, filter)} />}
  325. </BMSPagecontainer>
  326. )
  327. }
  328. export default PersonnelSalaryBudget;