index.tsx 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. /*
  2. * @Author: code4eat awesomedema@gmail.com
  3. * @Date: 2024-03-18 15:52:26
  4. * @LastEditors: code4eat awesomedema@gmail.com
  5. * @LastEditTime: 2024-08-16 15:54:53
  6. * @FilePath: /CostAccountingSys/src/pages/monthlyInfoCollection/index.tsx
  7. * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  8. */
  9. import KCIMPagecontainer from "@/components/KCIMPageContainer"
  10. import { DatePicker, message, Input, Modal, Table } from 'antd';
  11. import { Key, useEffect, useRef, useState } from "react";
  12. import moment from 'moment';
  13. import 'moment/locale/zh-cn';
  14. import locale from 'antd/es/date-picker/locale/zh_CN';
  15. import './style.less';
  16. import { KCIMLeftList } from "@/components/KCIMLeftList";
  17. import { formatMoneyNumber } from "@/utils/format";
  18. import { createFromIconfontCN } from "@ant-design/icons";
  19. import { KCIMTable } from "@/components/KCIMTable";
  20. import { ActionType, ProColumns } from "@ant-design/pro-components";
  21. import { getResponsibilityCenterList } from "../baseSetting/responsibilityCenterSet/responsibilityCenter/service";
  22. import { getIncomeCollectionReq, getTableDataReq } from "./service";
  23. import { cancelIncomeCollection, getAfterIncomeCollectionTableData, startIncomeCollection } from "../costAccounting/calcPageTemplate/service";
  24. import { useModel } from "@umijs/max";
  25. const IconFont = createFromIconfontCN({
  26. scriptUrl: '',
  27. });
  28. const tableColumn: ProColumns[] = [
  29. {
  30. title: '科室代码',
  31. ellipsis: true,
  32. dataIndex: 'departmentCode',
  33. },
  34. {
  35. title: '科室名称',
  36. ellipsis: true,
  37. dataIndex: 'departmentName',
  38. },
  39. {
  40. title: '会计科目',
  41. ellipsis: true,
  42. dataIndex: 'accountingName',
  43. },
  44. {
  45. title: '收入项目',
  46. ellipsis: true,
  47. dataIndex: 'productName',
  48. },
  49. {
  50. title: '金额',
  51. ellipsis: true,
  52. dataIndex: 'amount',
  53. },
  54. ];
  55. const IncomeCollectionAction = () => {
  56. const tableRef = useRef<ActionType>();
  57. const { initialState,setInitialState } = useModel('@@initialState');
  58. const [computeDate, set_computeDate] = useState<string>(initialState?initialState.computeDate:'');
  59. const [tableDataFilterParams, set_tableDataFilterParams] = useState<any | undefined>({ computeDate });
  60. const [incomeCollectionData,set_incomeCollectionData] = useState<any>(undefined);
  61. const [loading, set_loading] = useState(false);
  62. const [tableDataSearchKeywords, set_tableDataSearchKeywords] = useState('');
  63. const [leftTreeData, set_leftTreeData] = useState<any[]>([]);
  64. const [currentResp, set_currentResp] = useState<any>(undefined);
  65. const [currentSelectedLeftObj, set_currentSelectedLeftObj] = useState<any>(undefined);
  66. const onLeftChange = (item: any) => {
  67. set_currentSelectedLeftObj(item);
  68. // _currentSelectedLeftObj = item;
  69. }
  70. const getIncomeCollection = async ()=>{
  71. const resp = await getIncomeCollectionReq({computeDate,current:1,pageSize:100});
  72. if(resp&&resp.list.length>0){
  73. set_incomeCollectionData(resp.list[0])
  74. }else{
  75. set_incomeCollectionData(undefined)
  76. }
  77. }
  78. const getTableData = async (params: any) => {
  79. const { computeDate, responsibilityCode } = params;
  80. if (!computeDate && !responsibilityCode) return [];
  81. const resp = await getTableDataReq({ ...params, ...tableDataFilterParams });
  82. if (resp) {
  83. set_currentResp(resp);
  84. return {
  85. data: resp.list,
  86. success: true,
  87. total: resp.totalCount,
  88. pageSize: resp.pageSize,
  89. totalPage: resp.totalPage,
  90. }
  91. }
  92. return {
  93. data: [],
  94. success: true
  95. }
  96. }
  97. const tableDataSearchHandle = (paramName: string) => {
  98. set_tableDataFilterParams({
  99. ...tableDataFilterParams,
  100. [`${paramName}`]: tableDataSearchKeywords
  101. })
  102. }
  103. const getTreeData = async () => {
  104. let totalData: any[] = [];
  105. let page = 1;
  106. const pageSize = 500;
  107. const fetchPage = async (page: number) => {
  108. const resp = await getResponsibilityCenterList({ pageSize, current: page });
  109. if (resp && resp.list.length > 0) {
  110. totalData = totalData.concat(resp.list);
  111. // 如果返回的数据量等于每页的大小,说明可能还有下一页
  112. if (resp.list.length === pageSize) {
  113. await fetchPage(page + 1);
  114. }
  115. }
  116. };
  117. await fetchPage(page);
  118. set_leftTreeData([...totalData]);
  119. return totalData;
  120. };
  121. const openDataTable = async () => {
  122. set_loading(true);
  123. try {
  124. const { responsibilityCode = null } = tableDataFilterParams;
  125. const resp = await getAfterIncomeCollectionTableData(
  126. { date: `${computeDate.replace(/-/g, '')}` }
  127. );
  128. if (resp) {
  129. const { titleMap = {}, realData = [], totalMap = {} } = resp;
  130. const titleMapToArr = Object.entries(titleMap);
  131. const totalMapToArr = Object.entries(totalMap);
  132. const columns = [...titleMapToArr].map((item, index) => {
  133. if (index == 0 || index == [...titleMapToArr].length - 1) {
  134. return {
  135. title: item[1],
  136. key: item[0],
  137. dataIndex: item[0],
  138. fixed: index == 0 ? 'left' : 'right',
  139. width: 150,
  140. }
  141. }
  142. return {
  143. title: item[1],
  144. dataIndex: item[0],
  145. key: item[0],
  146. width: 150,
  147. }
  148. });
  149. set_loading(false);
  150. Modal.info({
  151. title: '报表数据',
  152. icon: '',
  153. okText: '确定',
  154. width: 800,
  155. content: (
  156. <KCIMTable
  157. rowKey='id'
  158. scroll={{ x: (columns.length) * 150, y: 450 }}
  159. columns={columns as ProColumns[]}
  160. dataSource={[...realData]}
  161. pagination={false}
  162. summary={() => (
  163. <Table.Summary fixed >
  164. <Table.Summary.Row className="rowCell">
  165. {/* <Table.Summary.Cell className="firstCell" index={0}>合计</Table.Summary.Cell> */}
  166. {
  167. totalMapToArr.map((item, index) => {
  168. return (
  169. <Table.Summary.Cell key={index} className={index == totalMapToArr.length - 1 ? 'ant-table-cell ant-table-cell-fix-right ant-table-cell-fix-right-last' : 'cell'} index={index}>{item[1] as any}</Table.Summary.Cell>
  170. )
  171. })
  172. }
  173. </Table.Summary.Row>
  174. </Table.Summary>
  175. )}
  176. />
  177. )
  178. })
  179. }
  180. } catch (err) {
  181. console.log({ err });
  182. }
  183. }
  184. const optionBtnGroupshandle = async () => {
  185. const { year, month } = incomeCollectionData?incomeCollectionData:{year:(computeDate.split('-'))[0],month:(computeDate.split('-'))[1]};
  186. if (incomeCollectionData&&incomeCollectionData.isCollection) {
  187. const resp = await cancelIncomeCollection({ year, month });
  188. if (resp) {
  189. message.success('操作成功!');
  190. getIncomeCollection();
  191. tableRef.current?.reload();
  192. }
  193. } else {
  194. Modal.confirm({
  195. title: '注意',
  196. content: '收入归集操作会覆盖已有的归集后数据,确定要继续操作?',
  197. okText: '确定',
  198. cancelText: '取消',
  199. onOk: async (...args) => {
  200. set_loading(true);
  201. const resp = await startIncomeCollection({ year, month });
  202. if (resp) {
  203. set_loading(false);
  204. message.success('操作成功!');
  205. tableRef?.current?.reload();
  206. getIncomeCollection();
  207. } else {
  208. set_loading(false);
  209. }
  210. },
  211. })
  212. }
  213. }
  214. useEffect(() => {
  215. if (currentSelectedLeftObj) {
  216. set_tableDataFilterParams({ ...tableDataFilterParams, responsibilityCode: currentSelectedLeftObj.responsibilityCode,accountFilter:'' })
  217. set_tableDataSearchKeywords('');
  218. }
  219. }, [currentSelectedLeftObj]);
  220. useEffect(()=>{
  221. getIncomeCollection();
  222. },[computeDate])
  223. useEffect(() => {
  224. getTreeData();
  225. getIncomeCollection();
  226. }, [])
  227. return (
  228. <KCIMPagecontainer className="IncomeCollectionAction" title={false}>
  229. <div className="header">
  230. <div className="search">
  231. <span>核算年月:</span>
  232. <DatePicker
  233. onChange={(data, dateString) => {
  234. set_computeDate(dateString);
  235. set_tableDataFilterParams({
  236. ...tableDataFilterParams,
  237. computeDate: dateString,
  238. accountFilter:''
  239. });
  240. setInitialState((s:any)=>({...s,computeDate: dateString,}));
  241. set_tableDataSearchKeywords('');
  242. }}
  243. picker="month"
  244. locale={locale}
  245. defaultValue={moment(computeDate, 'YYYY-MM')}
  246. format="YYYY-MM"
  247. placeholder="选择年月"
  248. />
  249. </div>
  250. <div className="btnGroup">
  251. <span className="check" onClick={() => openDataTable()}>报表数据</span>
  252. <span className="oneKeyGet" onClick={() => optionBtnGroupshandle()}>{(incomeCollectionData&&incomeCollectionData.isCollection) ? '撤销归集' : '开始归集'}</span>
  253. </div>
  254. </div>
  255. <div className="pageContent">
  256. <div className="line">
  257. <div className="info">
  258. <img src={require('../../../static/multiblock.png')} alt="" />
  259. 全部科室合计:
  260. <span>{currentResp ? formatMoneyNumber(currentResp.totalAmount) : '0.00'}元</span>
  261. </div>
  262. </div>
  263. <div className="contentWrapper">
  264. <div className="left">
  265. <KCIMLeftList
  266. fieldNames={{ title: 'responsibilityName', key: 'responsibilityCode', children: 'child' }}
  267. rowKey={'responsibilityCode'}
  268. contentH={`calc(100vh - 270px)`}
  269. dataSource={leftTreeData} searchKey={'responsibilityName'} onChange={onLeftChange}
  270. placeholder={'责任中心'} listType={'tree'}
  271. icon={undefined}
  272. />
  273. </div>
  274. <div className="right">
  275. <div className="toolBar" style={{ display: 'flex' }}>
  276. <div className="leftTool">当前科室合计:<span>{currentResp ? formatMoneyNumber(currentResp.departmentAmount) ? currentResp.departmentAmount : '0.00' : '0.00'}元</span></div>
  277. <div className="rightTool">
  278. <div className='filterItem' style={{ marginLeft: 16, width: 233 }}>
  279. <span className='label' style={{ whiteSpace: 'nowrap' }}> 检索:</span>
  280. <Input placeholder={'会计科目代码/名称'} allowClear value={tableDataSearchKeywords}
  281. suffix={
  282. <IconFont type="iconsousuo" style={{ color: '#99A6BF' }} onClick={() => tableDataSearchHandle(`accountFilter`)} />
  283. }
  284. onChange={(e) => {
  285. set_tableDataSearchKeywords(e.target.value);
  286. if (e.target.value.length == 0) {
  287. set_tableDataFilterParams({
  288. ...tableDataFilterParams,
  289. 'accountFilter': ''
  290. });
  291. }
  292. }}
  293. onPressEnter={(e) => {
  294. set_tableDataFilterParams({
  295. ...tableDataFilterParams,
  296. 'accountFilter': ((e.target) as HTMLInputElement).value
  297. });
  298. }}
  299. />
  300. </div>
  301. </div>
  302. </div>
  303. <KCIMTable actionRef={tableRef} columns={tableColumn}
  304. rowKey='id'
  305. request={(params) => getTableData(params)}
  306. tableAlertRender={false}
  307. scroll={{ x: scrollX,y:`calc(100vh - 322px)` }}
  308. params={tableDataFilterParams}
  309. />
  310. </div>
  311. </div>
  312. </div>
  313. </KCIMPagecontainer>
  314. )
  315. }
  316. export default IncomeCollectionAction