index.tsx 55 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384
  1. /*
  2. * @Author: code4eat awesomedema@gmail.com
  3. * @Date: 2022-12-16 09:42:52
  4. * @LastEditors: code4eat awesomedema@gmail.com
  5. * @LastEditTime: 2023-06-29 15:56:47
  6. * @FilePath: /BudgetManaSystem/src/pages/budgetMana/monthlySet/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 { Fragment, Key, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react';
  11. import './style.less';
  12. import { Tree, TreeProps, Tabs, Input, Modal, Transfer, Popconfirm, message, Popover, Select } from 'antd';
  13. import { DataNode } from 'antd/es/tree';
  14. import expandedIcon from '../../../../../static/treenode_open.png';
  15. import closeIcon from '../../../../../static/treenode_collapse.png';
  16. import { BMSTable } from '@/components/BMSTable';
  17. import { ActionType, ModalForm, ProColumns, ProColumnType, ProFormDigit, ProFormSelect } from '@ant-design/pro-components';
  18. import { createFromIconfontCN } from '@ant-design/icons';
  19. import { delRequest, getIndicTableData, getBillingItemTableData, getTreeDataRespType, getTreeData, getAllCheckUnit, saveCopyRequest, getAllCheckUnitProjectData, addBillingItemData, editBillingItemData, addIndicItemData, editIndicItemData, getNonCheckTableData, addNonCheckItemData, getCostItemsTableData, addCostItemData, editCostItemData } from './service';
  20. import { TransferItem, TransferProps } from 'antd/es/transfer';
  21. import { getComputeDate } from '@/pages/Home/service';
  22. import 'dayjs/locale/zh-cn';
  23. import React from 'react';
  24. import DirectoryTree from 'antd/es/tree/DirectoryTree';
  25. import { getDeepestTreeData } from '@/utils/tooljs';
  26. import { ColumnsType, TableRowSelection } from 'antd/es/table/interface';
  27. import { difference } from 'lodash';
  28. import { getBillProjectData } from '../bilingProjectMana/service';
  29. import { getIndicProjectTableData } from '../indicProjectMana/service';
  30. import { getNonCheckProjectTableData } from '../nonAssessmentProjectMana/service';
  31. import '../../../../utils/zhongtaiB';
  32. import { getCostProjectTable } from '../costIncomeProjectSet/service';
  33. const IconFont = createFromIconfontCN({
  34. scriptUrl: '',
  35. });
  36. const SearchIcon = createFromIconfontCN({
  37. scriptUrl: '',
  38. });
  39. export type TableListItem = {
  40. key: number;
  41. name: string;
  42. };
  43. const CheckUnitProjectSet: React.FC = () => {
  44. const [treeData, set_treeData] = useState<getTreeDataRespType[]>([]);
  45. const [tableColumn, set_tableColumn] = useState<ProColumns[]>([]);
  46. const [currentSelectedTreeNode, set_currentSelectedTreeNode] = useState<any | undefined>();
  47. const [currentSelectedTabKey, set_currentSelectedTabKey] = useState<string>('1');
  48. const [currentComputeDate, set_currentComputeDate] = useState<string | undefined>();
  49. const [currentEditRow, set_currentEditRow] = useState<any>(undefined);
  50. const [searchKeywords, set_searchKeywords] = useState('');
  51. const [searchParams, set_searchParams] = useState<any>({});
  52. const [expandedKeys, setExpandedKeys] = useState<React.Key[]>([]);
  53. const [searchValue, setSearchValue] = useState('');
  54. const [autoExpandParent, setAutoExpandParent] = useState(true);
  55. const [ifEdit, set_ifEdit] = useState(false);
  56. const [ifShowModal, set_ifShowModal] = useState(false);
  57. const ref = React.createRef<{ save: any; getSelectedKeys: any }>();
  58. const [currentEditCoreFlag, set_currentEditCoreFlag] = useState(0);
  59. const [tableSelecterColumn, set_tableSelecterColumn] = useState<ProColumns[]>([]);
  60. const [isCopy, set_isCopy] = useState(false);
  61. const tableRef = useRef<ActionType>();
  62. const billingTableColumn: ProColumns[] = [
  63. {
  64. title: '项目代码',
  65. dataIndex: 'itemPointCode',
  66. renderText(text, record, index, action) {
  67. return <span style={{ display: 'inline-block', height: '26px', lineHeight: '26px' }}>{text}</span>
  68. },
  69. ellipsis: true
  70. },
  71. {
  72. title: '项目名称',
  73. dataIndex: 'itemName',
  74. ellipsis: true
  75. },
  76. {
  77. title: '项目类别',
  78. dataIndex: 'itemType',
  79. ellipsis: true
  80. },
  81. {
  82. title: '点值',
  83. width: 120,
  84. ellipsis: true,
  85. dataIndex: 'orderPointValue',
  86. renderText: (text, record, index, action) => {
  87. if (ifEdit && currentEditRow?.id == record.id) {
  88. return <ProFormDigit noStyle fieldProps={{
  89. defaultValue: text, onChange(value) {
  90. // console.log({value,currentEditRow});
  91. if (value && currentEditRow) {
  92. set_currentEditRow({ ...currentEditRow, orderPointValue: value })
  93. }
  94. },
  95. }} width={80} />
  96. } else {
  97. return <span style={{ display: 'inline-block', width: 80 }}>{text}</span>
  98. }
  99. },
  100. },
  101. {
  102. title: '类型',
  103. width: 120,
  104. ellipsis: true,
  105. dataIndex: 'coreFlagName',
  106. renderText: (text, record, index, action) => {
  107. if (ifEdit && currentEditRow && currentEditRow?.id == record.id) {
  108. return <Select defaultValue={record.coreFlag} style={{ width: '100%' }} options={
  109. [
  110. { label: '核心', value: 1 }, { label: '非核心', value: 0 }, { label: '不计', value: 2 }
  111. ]
  112. } onChange={(a, b) => { set_currentEditCoreFlag(a) }} />
  113. } else {
  114. return <span style={{ display: 'inline-block', width: 120 }}>{text}</span>
  115. }
  116. },
  117. }
  118. ];
  119. const indicTableColumn: ProColumns[] = [
  120. {
  121. title: '项目代码',
  122. dataIndex: 'indicatorCode',
  123. ellipsis: true,
  124. renderText(text, record, index, action) {
  125. return <span style={{ display: 'inline-block', height: '26px', lineHeight: '26px' }}>{text}</span>
  126. },
  127. },
  128. {
  129. title: '项目名称',
  130. ellipsis: true,
  131. dataIndex: 'indicatorName',
  132. },
  133. {
  134. title: '类型',
  135. ellipsis: true,
  136. dataIndex: 'indicatorTypeName',
  137. },
  138. {
  139. title: '定义',
  140. ellipsis: true,
  141. dataIndex: 'indicatorDefinition',
  142. },
  143. {
  144. title: '点值',
  145. width: 120,
  146. ellipsis: true,
  147. dataIndex: 'orderPointValue',
  148. renderText(text, record, index, action) {
  149. if (ifEdit && currentEditRow?.id == record.id) {
  150. return <ProFormDigit noStyle fieldProps={{
  151. defaultValue: text, onChange(value) {
  152. console.log({ value, currentEditRow });
  153. if (value && currentEditRow) {
  154. set_currentEditRow({ ...currentEditRow, orderPointValue: value })
  155. }
  156. },
  157. }} width={80} />
  158. } else {
  159. return <span style={{ display: 'inline-block', width: 80 }}>{text}</span>
  160. }
  161. },
  162. }
  163. ];
  164. const nonCheckTableColumn: ProColumns[] = [
  165. {
  166. title: '项目名称',
  167. ellipsis: true,
  168. dataIndex: 'nonAssessmentName',
  169. renderText(text, record, index, action) {
  170. return <span style={{ display: 'inline-block', height: '26px', lineHeight: '26px' }}>{text}</span>
  171. },
  172. },
  173. {
  174. title: '分配方式',
  175. ellipsis: true,
  176. dataIndex: 'distributionTypeName',
  177. },
  178. {
  179. title: '分配对象',
  180. ellipsis: true,
  181. dataIndex: 'distributionTargetName',
  182. },
  183. {
  184. title: '上限值',
  185. ellipsis: true,
  186. dataIndex: 'ceiling',
  187. },
  188. {
  189. title: '评分项',
  190. width: 260,
  191. dataIndex: 'orderPointValue',
  192. ellipsis: true,
  193. renderText(text, record) {
  194. return record.secondItem ? record.secondItem.reduce((prev: any, cur: any) => `${prev.length > 0 ? prev + '|' : prev}${cur.secondItemName}`, '') : ''
  195. },
  196. }
  197. ];
  198. const costTableColumn: ProColumns[] = [
  199. {
  200. title: '项目名称',
  201. ellipsis: true,
  202. dataIndex: 'name',
  203. // renderText(text, record, index, action) {
  204. // return <span style={{ display: 'inline-block', height: '26px', lineHeight: '26px' }}>{text}</span>
  205. // },
  206. },
  207. {
  208. title: '类型',
  209. ellipsis: true,
  210. dataIndex: 'itemTypeName',
  211. },
  212. {
  213. title: '可控',
  214. ellipsis: true,
  215. dataIndex: 'ctrlFlag',
  216. renderText(text, record, index, action) {
  217. return ifEdit ? <ProFormSelect noStyle fieldProps={{
  218. defaultValue: text, onChange(value, option) {
  219. set_currentEditRow({ ...currentEditRow, ctrlFlag: value })
  220. },
  221. }} options={[{ label: '是', value: 1 }, { label: '否', value: 0 }]} /> : text == 1 ? '是' : '否'
  222. },
  223. },
  224. {
  225. title: '序号',
  226. ellipsis: true,
  227. dataIndex: 'seqNo',
  228. },
  229. ];
  230. const delHandle = async (record: any) => {
  231. const { id } = record;
  232. const resp = await delRequest({ id: id }, currentSelectedTabKey);
  233. if (resp) {
  234. message.success('操作成功');
  235. tableRef.current?.reload();
  236. }
  237. }
  238. const onSelect: TreeProps['onSelect'] = (selectedKeys, info: any) => {
  239. // console.log('selected', selectedKeys, info);
  240. const { node } = info;
  241. if (!node.child) set_currentSelectedTreeNode(node);
  242. };
  243. const getCurrentComputeDate = async () => {
  244. const resp = await getComputeDate();
  245. set_currentComputeDate(resp);
  246. }
  247. const onTabChange = (activeKey: string) => {
  248. set_currentSelectedTabKey(activeKey);
  249. }
  250. const getTableData = async (type: 'BILL' | 'INDIC' | 'NONCHECK' | 'COST', params: any, sort: any, filter: any) => {
  251. // console.log({ currentSelectedTreeNode });
  252. // console.log({ params, sort, filter });
  253. if (currentSelectedTreeNode && currentComputeDate) {
  254. if (type == 'BILL') {
  255. const resp = await getBillingItemTableData({
  256. unitCode: currentSelectedTreeNode.code,
  257. ...params,
  258. });
  259. if (resp) {
  260. return {
  261. data: resp.list,
  262. success: true,
  263. total: resp.totalCount,
  264. pageSize: resp.pageSize,
  265. totalPage: resp.totalPage,
  266. }
  267. }
  268. return {
  269. data: [],
  270. success: true
  271. }
  272. }
  273. if (type == 'INDIC') {
  274. const resp = await getIndicTableData({
  275. unitCode: currentSelectedTreeNode.code,
  276. ...params
  277. });
  278. if (resp) {
  279. return {
  280. data: resp.list,
  281. success: true,
  282. total: resp.totalCount,
  283. pageSize: resp.pageSize,
  284. totalPage: resp.totalPage,
  285. }
  286. }
  287. return {
  288. data: [],
  289. success: true
  290. }
  291. }
  292. if (type == 'NONCHECK') {
  293. const resp = await getNonCheckTableData({
  294. unitCode: currentSelectedTreeNode.code,
  295. ...params
  296. });
  297. if (resp) {
  298. return {
  299. data: resp.list,
  300. success: true,
  301. total: resp.totalCount,
  302. pageSize: resp.pageSize,
  303. totalPage: resp.totalPage,
  304. }
  305. }
  306. return {
  307. data: [],
  308. success: true
  309. }
  310. }
  311. if (type == 'COST') {
  312. const resp = await getCostItemsTableData({
  313. unitCode: currentSelectedTreeNode.code,
  314. ...params
  315. });
  316. if (resp) {
  317. return {
  318. data: resp,
  319. success: true,
  320. }
  321. }
  322. return {
  323. data: [],
  324. success: true
  325. }
  326. }
  327. }
  328. return []
  329. }
  330. interface TableTransferProps extends TransferProps<TransferItem> {
  331. leftColumns: ColumnsType<any>;
  332. rightColumns: ColumnsType<any>;
  333. }
  334. const transferTableColumn = [
  335. {
  336. title: '项目名称',
  337. dataIndex: 'itemName',
  338. ellipsis: true,
  339. width: 220
  340. },
  341. {
  342. title: '类型',
  343. dataIndex: 'itemType',
  344. },
  345. ];
  346. const checkUnitColumns = [
  347. {
  348. title: '核算单元名称',
  349. dataIndex: 'unitName',
  350. },
  351. {
  352. title: '职类',
  353. dataIndex: 'unitTypeName',
  354. },
  355. ];
  356. const costItemColumns = [
  357. {
  358. title: '项目名称',
  359. dataIndex: 'name',
  360. }
  361. ]
  362. const openCopyHandleModal = () => {
  363. set_ifShowModal(true);
  364. set_isCopy(true);
  365. }
  366. const openTransfer = () => {
  367. const ref = React.createRef<{ save: any }>();
  368. Modal.confirm({
  369. title: '添加',
  370. icon: <></>,
  371. width: 800,
  372. centered: true,
  373. okText: '确定',
  374. cancelText: '取消',
  375. content: <TableTransfer
  376. ref={ref}
  377. leftColumns={transferTableColumn}
  378. rightColumns={transferTableColumn}
  379. ></TableTransfer>,
  380. onOk: () => {
  381. return ref.current && ref.current.save();
  382. }
  383. })
  384. }
  385. interface TableSelecterProps extends TransferProps<TransferItem> {
  386. tableSelecterColumn: any[];
  387. record: any
  388. }
  389. const TableSelecter = React.forwardRef(({ tableSelecterColumn, record }: TableSelecterProps, ref) => {
  390. const [datasource, set_datasource] = useState<any[]>([]);
  391. const [selectedKeys, setSelectedKeys] = useState<React.Key[]>([]);
  392. const [selectedRows, set_selectedRows] = useState<any[]>([])
  393. const [showList, set_showList] = useState<any[]>([]);
  394. const [tableParams, set_tableParams] = useState<any>({});
  395. const [keywords, set_keywords] = useState('');
  396. //获取表格数据
  397. const getFuncList = async () => {
  398. if (isCopy) {
  399. const resp = await getAllCheckUnit();
  400. if (resp) {
  401. const filteredData = resp.filter((a: any) => a.code != currentSelectedTreeNode.code);
  402. set_datasource(filteredData);
  403. set_showList(filteredData);
  404. }
  405. } else {
  406. //成本项目添加
  407. const resp = await getCostProjectTable();
  408. if (resp) {
  409. //const filteredData = resp.filter((a:any)=>a.code != currentSelectedTreeNode.code);
  410. set_datasource(resp);
  411. set_showList(resp);
  412. }
  413. }
  414. }
  415. const onSelectChange = (newSelectedRowKeys: React.Key[], selectedRows: any) => {
  416. setSelectedKeys([...newSelectedRowKeys]);
  417. set_selectedRows(selectedRows);
  418. };
  419. const save = async () => {
  420. if (!isCopy && currentSelectedTabKey == '4') {
  421. //console.log({selectedKeys,selectedRows});
  422. const result = {
  423. itemList: selectedRows.map((a: any) => ({
  424. code: a.code,
  425. ctrlFlag: a.ctrlFlag,
  426. itemType: a.itemType,
  427. name: a.name,
  428. parentCode: a.parentCode,
  429. seqNo: a.seqNo,
  430. statFlag: a.statFlag,
  431. summaryFlag: a.summaryFlag
  432. })),
  433. unitCode: currentSelectedTreeNode.code
  434. };
  435. const resp = await addCostItemData(result);
  436. if (resp) {
  437. message.success('操作成功!');
  438. set_ifShowModal(false);
  439. tableRef.current?.reload();
  440. }
  441. } else {
  442. const result = {
  443. unitCodeList: selectedKeys,
  444. unitCode: currentSelectedTreeNode.code
  445. };
  446. const resp = await saveCopyRequest(result, currentSelectedTabKey);
  447. if (resp) {
  448. message.success('复制成功!');
  449. set_ifShowModal(false);
  450. tableRef.current?.reload();
  451. }
  452. }
  453. }
  454. useEffect(() => {
  455. getFuncList();
  456. }, [])
  457. return (
  458. <div className='TableSelecter'>
  459. <Input placeholder={'请输入'} allowClear
  460. suffix={
  461. <IconFont type="iconsousuo" onClick={() => {
  462. //console.log('iconsousuo', currentSelectedTabKey, keywords);
  463. if (isCopy) {
  464. set_tableParams({ ...tableParams, name: keywords })
  465. }
  466. }} />
  467. }
  468. style={{ marginBottom: 8 }}
  469. onChange={(e) => {
  470. if (currentSelectedTabKey != '4') {
  471. if (e.target.value.length != 0) {
  472. const result = datasource.filter(item => item.unitName.indexOf(e.target.value) != -1);
  473. set_showList(result);
  474. } else {
  475. set_showList(datasource);
  476. }
  477. }
  478. if (currentSelectedTabKey == '4') {
  479. //set_keywords(e.target.value);
  480. const search: any = (data: any, name: string) => {
  481. let result = [];
  482. for (let i = 0; i < data.length; i++) {
  483. const item = data[i];
  484. if (item.name.indexOf(name) != -1) {
  485. result.push(item);
  486. }
  487. if (item.children) {
  488. result.push(...search(item.children, name));
  489. }
  490. }
  491. return result;
  492. }
  493. if(e.target.value.length>0){
  494. const foundItem = search(datasource,e.target.value);
  495. set_showList(foundItem);
  496. }else{
  497. set_showList(datasource);
  498. }
  499. }
  500. }}
  501. />
  502. <BMSTable columns={tableSelecterColumn}
  503. options={{
  504. density: true,
  505. setting: {
  506. listsHeight: 100,
  507. },
  508. }}
  509. params={tableParams}
  510. rowKey='code'
  511. tableAlertRender={false}
  512. rowSelection={{
  513. // 自定义选择项参考: https://ant.design/components/table-cn/#components-table-demo-row-selection-custom
  514. // 注释该行则默认不显示下拉选项
  515. onChange: onSelectChange,
  516. checkStrictly: false
  517. }}
  518. pagination={{ showSizeChanger: false, pageSize: 10, simple: true, showTitle: false }}
  519. dataSource={showList}
  520. />
  521. <div className='footer'>
  522. <span className='cancel' onClick={() => set_ifShowModal(false)}>取消</span>
  523. <span className='ok' onClick={() => save()}>{`确认(${selectedKeys.length > 0 && selectedKeys.length})`}</span>
  524. </div>
  525. </div>
  526. )
  527. });
  528. const TableTransfer = React.forwardRef(({ leftColumns, rightColumns, ...restProps }: TableTransferProps, ref) => {
  529. const [_data, _set_data] = useState<any>();
  530. const [targetKeys, setTargetKeys] = useState<string[]>([]);
  531. const [datasource, set_datasource] = useState<any[]>([]);
  532. const [selectedKeys, setSelectedKeys] = useState<string[]>([]);
  533. const [targetData, set_targetData] = useState<any[]>([]);
  534. const [loading, set_loading] = useState(true);
  535. //获取单元
  536. const getFuncList = async () => {
  537. if (currentSelectedTabKey == '1') {
  538. const resp = await getAllCheckUnitProjectData();
  539. if (resp) {
  540. const resp1 = await getBillingItemTableData({
  541. unitCode: currentSelectedTreeNode.code,
  542. pageSize: 500, current: 1
  543. });
  544. if (resp1) {
  545. let allData = resp;
  546. set_targetData(resp1.list);
  547. const defaultSelctedkeys = (resp1.list).map((a: any) => a.itemPointCode);
  548. set_datasource(allData);
  549. setTargetKeys(defaultSelctedkeys);
  550. }
  551. }
  552. }
  553. if (currentSelectedTabKey == '2') {
  554. const resp = await getIndicProjectTableData({ pageSize: 500, current: 1 });
  555. if (resp) {
  556. const resp1 = await getIndicTableData({
  557. unitCode: currentSelectedTreeNode.code,
  558. pageSize: 500, current: 1
  559. });
  560. if (resp1) {
  561. set_targetData(resp1.list);
  562. set_datasource(resp.list.map((a: any) => ({ ...a, itemName: a.indicatorName, itemType: a.indicatorTypeName })));
  563. const defaultSelctedkeys = (resp1.list).map((a: any) => a.indicatorCode);
  564. setTargetKeys(defaultSelctedkeys);
  565. }
  566. }
  567. }
  568. if (currentSelectedTabKey == '3') {
  569. const resp = await getNonCheckProjectTableData({ pageSize: 500, current: 1 });
  570. if (resp) {
  571. const resp1 = await getNonCheckTableData({
  572. unitCode: currentSelectedTreeNode.code,
  573. pageSize: 1000000, current: 1
  574. });
  575. if (resp1) {
  576. set_targetData(resp1.list);
  577. set_datasource(resp.list.map((a: any) => ({ ...a, itemName: a.name, itemType: a.distributionTypeName })));
  578. const defaultSelctedkeys = (resp1.list).map((a: any) => a.nonAssessmentCode);
  579. setTargetKeys(defaultSelctedkeys);
  580. }
  581. }
  582. }
  583. set_loading(false);
  584. }
  585. const onChange = (nextTargetKeys: string[]) => {
  586. setTargetKeys(nextTargetKeys);
  587. };
  588. const onSelectChange = (sourceSelectedKeys: string[], targetSelectedKeys: string[]) => {
  589. //console.log('sourceSelectedKeys:', sourceSelectedKeys,'targetSelectedKeys:',targetSelectedKeys);
  590. setSelectedKeys([...sourceSelectedKeys, ...targetSelectedKeys]);
  591. };
  592. useImperativeHandle(ref, () => ({
  593. save: async () => {
  594. let flag = false;
  595. if (currentSelectedTabKey == '1') {
  596. const items = datasource.filter(a => targetKeys.includes(a.code));
  597. //拿到当前的表格数据覆盖全量表格数据
  598. //console.log({items,targetKeys});
  599. const uodatedData = items.map(a => {
  600. if (targetData.length > 0) {
  601. const result = targetData.filter(b => b.itemPointCode == a.code);
  602. if (result.length > 0) {
  603. return {
  604. ...a,
  605. orderPointValue: result[0].orderPointValue,
  606. coreFlag: result[0].coreFlag,
  607. }
  608. } else {
  609. return a
  610. }
  611. } else {
  612. return a
  613. }
  614. })
  615. const result = {
  616. unitCode: currentSelectedTreeNode.code,
  617. item: uodatedData.map(a => ({
  618. itemPointCode: a.itemCode,
  619. itemName: a.itemName,
  620. orderPointValue: a.orderPointValue,
  621. coreFlag: a.coreFlag
  622. }))
  623. }
  624. const resp = await addBillingItemData(result);
  625. if (resp) {
  626. flag = true
  627. }
  628. }
  629. if (currentSelectedTabKey == '2') {
  630. const items = datasource.filter(a => targetKeys.includes(a.code));
  631. //拿到当前的表格数据覆盖全量表格数据
  632. const uodatedData = items.map(a => {
  633. if (targetData.length > 0) {
  634. const result = targetData.filter(b => b.indicatorCode == a.code);
  635. if (result.length > 0) {
  636. return {
  637. ...a,
  638. orderPointValue: result[0].orderPointValue
  639. }
  640. } else {
  641. return a
  642. }
  643. } else {
  644. return a
  645. }
  646. })
  647. const commitData = uodatedData.map((a: any) => ({
  648. indicatorCode: a.code,
  649. indicatorName: a.indicatorName,
  650. orderPointValue: a.orderPointValue,
  651. executePointValue: a.executePointValue
  652. }))
  653. const result = {
  654. unitCode: currentSelectedTreeNode.code,
  655. indicatorValues: commitData
  656. }
  657. const resp = await addIndicItemData(result);
  658. if (resp) {
  659. flag = true
  660. }
  661. }
  662. if (currentSelectedTabKey == '3') {
  663. const items = datasource.filter(a => targetKeys.includes(a.code));
  664. const commitData = items.map(a => ({
  665. code: a.code,
  666. name: a.name
  667. }))
  668. const result = {
  669. unitCode: currentSelectedTreeNode.code,
  670. assessments: commitData
  671. }
  672. const resp = await addNonCheckItemData(result);
  673. if (resp) {
  674. flag = true
  675. }
  676. }
  677. if (flag) {
  678. message.success('操作成功!');
  679. tableRef.current?.reload();
  680. }
  681. }
  682. }));
  683. useEffect(() => {
  684. getFuncList();
  685. }, [])
  686. return (
  687. <Transfer className='TableTransfer' showSearch
  688. titles={['待选项', '已选项']}
  689. locale={{
  690. itemUnit: '项',
  691. itemsUnit: '项',
  692. searchPlaceholder: '请输入',
  693. }}
  694. // oneWay={true}
  695. onChange={onChange}
  696. onSelectChange={onSelectChange}
  697. dataSource={datasource}
  698. rowKey={record => record.code}
  699. targetKeys={targetKeys}
  700. selectedKeys={selectedKeys}
  701. filterOption={(inputValue, item) => {
  702. if (item.itemName!.indexOf(inputValue) !== -1) {
  703. console.log({ item });
  704. }
  705. return item.itemName!.indexOf(inputValue) !== -1
  706. }}
  707. >
  708. {({
  709. direction,
  710. filteredItems,
  711. onItemSelectAll,
  712. onItemSelect,
  713. selectedKeys: listSelectedKeys,
  714. disabled: listDisabled,
  715. }) => {
  716. //console.log({ filteredItems, listSelectedKeys, direction });
  717. const columns = direction === 'left' ? leftColumns : rightColumns;
  718. const rowSelection: TableRowSelection<TransferItem> = {
  719. getCheckboxProps: (item) => ({ disabled: listDisabled || item.disabled }),
  720. onSelectAll(selected, selectedRows) {
  721. const treeSelectedKeys = selectedRows.map(({ code }) => code);
  722. const diffKeys = selected
  723. ? difference(treeSelectedKeys, listSelectedKeys)
  724. : difference(listSelectedKeys, treeSelectedKeys);
  725. onItemSelectAll(diffKeys as string[], selected);
  726. },
  727. onSelect({ code }, selected) {
  728. console.log({ code, selected })
  729. onItemSelect(code as string, selected);
  730. },
  731. selectedRowKeys: listSelectedKeys,
  732. };
  733. return (
  734. <BMSTable
  735. rowSelection={rowSelection}
  736. columns={columns as TransferItem[]}
  737. dataSource={filteredItems}
  738. size="small"
  739. loading={loading}
  740. bordered={false}
  741. rowKey={'code'}
  742. pagination={{ showTitle: false, pageSize: 9, showLessItems: false, simple: true, showTotal: () => false }}
  743. tableAlertRender={false}
  744. style={{ pointerEvents: listDisabled ? 'none' : undefined }}
  745. onRow={({ code, disabled: itemDisabled }) => ({
  746. onClick: () => {
  747. if (itemDisabled || listDisabled) return;
  748. onItemSelect(code as string, !listSelectedKeys.includes(code as string));
  749. },
  750. })}
  751. />
  752. );
  753. }}
  754. </Transfer>
  755. )
  756. });
  757. //成本项目添加
  758. const addCostProject = () => {
  759. set_isCopy(false);
  760. set_ifShowModal(true);
  761. }
  762. const tableSearchHandle = () => {
  763. set_searchParams({
  764. name: searchKeywords
  765. })
  766. }
  767. //编辑按钮操作
  768. const editBtnHandle = async () => {
  769. let flag = false;
  770. if (ifEdit) {
  771. //保存操作
  772. if (currentSelectedTabKey == '1' && currentEditRow) {
  773. //收费项目
  774. console.log({ currentEditRow });
  775. const result = {
  776. id: currentEditRow.id,
  777. unitCode: currentSelectedTreeNode.code,
  778. orderPointValue: `${currentEditRow.orderPointValue}`,
  779. coreFlag: currentEditCoreFlag
  780. }
  781. const resp = await editBillingItemData(result);
  782. if (resp) flag = true;
  783. }
  784. if (currentSelectedTabKey == '2' && currentEditRow) {
  785. //收费项目
  786. const result = {
  787. id: currentEditRow.id,
  788. unitCode: currentSelectedTreeNode.code,
  789. indicatorCode: currentEditRow.indicatorCode,
  790. indicatorName: currentEditRow.indicatorName,
  791. orderPointValue: currentEditRow.orderPointValue,
  792. executePointValue: currentEditRow.executePointValue
  793. }
  794. const resp = await editIndicItemData(result);
  795. if (resp) flag = true;
  796. }
  797. if (currentSelectedTabKey == '4' && currentEditRow) {
  798. //成本项目
  799. //console.log({ currentEditRow });
  800. const result = {
  801. id: currentEditRow.id,
  802. ctrlFlag: currentEditRow.ctrlFlag
  803. }
  804. const resp = await editCostItemData(result);
  805. if (resp) flag = true;
  806. }
  807. } else {
  808. //开启编辑模式
  809. set_ifEdit(true);
  810. }
  811. if (flag) {
  812. set_ifEdit(false);
  813. message.success('操作成功!');
  814. tableRef.current?.reload();
  815. }
  816. }
  817. const dataList: any[] = [];
  818. const getParentKey = (key: React.Key, tree: any[]): React.Key => {
  819. let parentKey: React.Key;
  820. for (let i = 0; i < tree.length; i++) {
  821. const node = tree[i];
  822. if (node.child) {
  823. if (node.child.some((item: { code: React.Key; }) => item.code === key)) {
  824. parentKey = node.code;
  825. } else if (getParentKey(key, node.child)) {
  826. parentKey = getParentKey(key, node.child);
  827. }
  828. }
  829. }
  830. return parentKey!;
  831. };
  832. const onTreeSearchKeyChange = (e: React.ChangeEvent<HTMLInputElement>) => {
  833. const { value } = e.target;
  834. const newExpandedKeys = dataList
  835. .map((item) => {
  836. if (item.name.indexOf(value) > -1) {
  837. return getParentKey(item.code, treeData);
  838. }
  839. return null;
  840. });
  841. const b = newExpandedKeys.filter((item, i, self) => item && self.indexOf(item) === i);
  842. setExpandedKeys(newExpandedKeys as React.Key[]);
  843. setSearchValue(value);
  844. setAutoExpandParent(true);
  845. }
  846. const onExpand = (newExpandedKeys: React.Key[]) => {
  847. setExpandedKeys(newExpandedKeys);
  848. setAutoExpandParent(false);
  849. };
  850. const generateList = (data: getTreeDataRespType[]) => {
  851. for (let i = 0; i < data.length; i++) {
  852. const node = data[i];
  853. const { code, name } = node;
  854. dataList.push({ code: code, name: name });
  855. if (node.child) {
  856. generateList(node.child);
  857. }
  858. }
  859. };
  860. generateList(treeData as any);
  861. const getTreeReqFunc = async (computeDate: string) => {
  862. const resp = await getTreeData(computeDate);
  863. set_treeData(resp);
  864. }
  865. const setTableColumn = () => {
  866. if (currentSelectedTabKey == '1') {
  867. set_tableColumn(billingTableColumn);
  868. }
  869. if (currentSelectedTabKey == '2') {
  870. set_tableColumn(indicTableColumn);
  871. }
  872. if (currentSelectedTabKey == '3') {
  873. set_tableColumn(nonCheckTableColumn);
  874. }
  875. if (currentSelectedTabKey == '4') {
  876. set_tableColumn(costTableColumn);
  877. }
  878. }
  879. useEffect(() => {
  880. if (currentComputeDate) {
  881. getTreeReqFunc(currentComputeDate);
  882. }
  883. }, [currentComputeDate]);
  884. useEffect(() => {
  885. setTableColumn();
  886. }, [ifEdit]);
  887. useEffect(() => {
  888. tableRef.current?.reload();
  889. }, [currentSelectedTreeNode]);
  890. useEffect(() => {
  891. setTableColumn();
  892. }, [currentSelectedTabKey]);
  893. useEffect(() => {
  894. if (!isCopy) {
  895. set_tableSelecterColumn(costItemColumns);
  896. } else {
  897. set_tableSelecterColumn(checkUnitColumns);
  898. }
  899. }, [isCopy])
  900. useEffect(() => {
  901. //初始化左侧树结构数据后
  902. if (treeData?.length > 0) {
  903. if (treeData[0].child && treeData[0].child.length > 0) {
  904. const [node, nodeParent] = getDeepestTreeData(treeData[0], 'child');
  905. set_currentSelectedTreeNode(node);
  906. setExpandedKeys([nodeParent.code]);
  907. }
  908. }
  909. }, [treeData]);
  910. useEffect(() => {
  911. set_tableColumn(billingTableColumn as ProColumns[]);
  912. getCurrentComputeDate();
  913. }, []);
  914. return (
  915. <div className='CheckUnitProjectSet'>
  916. <ModalForm title={isCopy ? `复制(${currentSelectedTreeNode ? currentSelectedTreeNode.name : ''})` : `添加成本项目(${currentSelectedTreeNode ? currentSelectedTreeNode.name : ''})`} width={400} submitter={{
  917. render: (props, defaultDoms) => []
  918. }} open={ifShowModal} modalProps={{
  919. closable: false,
  920. }}>
  921. <TableSelecter
  922. ref={ref}
  923. record={undefined}
  924. tableSelecterColumn={tableSelecterColumn}
  925. ></TableSelecter>
  926. </ModalForm>
  927. <div className='leftTree'>
  928. <div className='search'>
  929. <Input
  930. className='searchInput'
  931. placeholder="请输入类目名称"
  932. size='small'
  933. allowClear
  934. style={{ marginBottom: 16 }}
  935. onChange={onTreeSearchKeyChange}
  936. suffix={
  937. <SearchIcon type='iconsousuo' />
  938. }
  939. />
  940. </div>
  941. {
  942. treeData && treeData.length > 0 && currentSelectedTreeNode && (
  943. <DirectoryTree
  944. fieldNames={{ title: 'name', key: 'code', children: 'child' }}
  945. rootStyle={{ height: '100%', paddingBottom: 50, overflowY: 'scroll', overflowX: 'hidden' }}
  946. onSelect={onSelect}
  947. onExpand={onExpand}
  948. expandedKeys={expandedKeys}
  949. autoExpandParent={autoExpandParent}
  950. selectedKeys={[currentSelectedTreeNode.code]}
  951. blockNode={true}
  952. icon={() => null}
  953. titleRender={
  954. (nodeData: any) => {
  955. const strTitle = nodeData.name as string;
  956. const index = strTitle.indexOf(searchValue);
  957. const beforeStr = strTitle.substring(0, index);
  958. const afterStr = strTitle.slice(index + searchValue.length);
  959. const title =
  960. index > -1 ? (
  961. <span>
  962. {beforeStr}
  963. <span className="site-tree-search-value" style={{ color: 'red', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{searchValue}</span>
  964. {afterStr}
  965. </span>
  966. ) : (
  967. <span className='strTitle'>{strTitle}</span>
  968. );
  969. return <div style={{
  970. display: 'flex', flexDirection: 'row',
  971. width: '100%',
  972. justifyContent: 'flex-start', alignItems: 'center', height: 32,
  973. borderRadius: '4px',
  974. overflow: 'hidden',
  975. color: '#17181A',
  976. textOverflow: 'ellipsis',
  977. whiteSpace: 'nowrap'
  978. }}>{title}</div>
  979. }
  980. }
  981. defaultSelectedKeys={[treeData[0].child[0].code]}
  982. treeData={treeData as unknown as DataNode[]}
  983. // treeData={treeDataNew}
  984. switcherIcon={(props: any) => {
  985. const { expanded } = props;
  986. return !expanded ? <img style={{ width: 20, height: 20, position: 'relative', top: 5 }} src={expandedIcon} /> : <img style={{ width: 20, height: 20, position: 'relative', top: 5 }} src={closeIcon} />
  987. }}
  988. />
  989. )
  990. }
  991. </div>
  992. {/* <div style={{width:16,height:'92vh',background:'#F5F7FA'}}></div> */}
  993. <div className='rightContent'>
  994. <BMSPagecontainer title={false} ghost>
  995. <div></div>
  996. <Tabs
  997. defaultActiveKey="1"
  998. onChange={onTabChange}
  999. items={[
  1000. {
  1001. label: `收费项目`,
  1002. key: '1',
  1003. },
  1004. {
  1005. label: `指标项目`,
  1006. key: '2',
  1007. },
  1008. {
  1009. label: `非考核项目`,
  1010. key: '3',
  1011. },
  1012. {
  1013. label: `成本项目`,
  1014. key: '4',
  1015. },
  1016. ]}
  1017. />
  1018. {
  1019. currentSelectedTabKey == '1' && (
  1020. <div className='tabContent'>
  1021. <div className='tableToolbar'>
  1022. <div className='search'>
  1023. <span>检索:</span><Input className='searchInput' allowClear onChange={(e) => {
  1024. set_searchKeywords(e.target.value)
  1025. if (e.target.value.length == 0) {
  1026. set_searchParams({
  1027. ...searchParams,
  1028. name: e.target.value
  1029. })
  1030. }
  1031. }} placeholder="请输入项目名称" suffix={
  1032. <IconFont type="iconsousuo" onClick={() => tableSearchHandle()} />
  1033. } />
  1034. </div>
  1035. <div className={'btnGroup'}>
  1036. <span key="2" onClick={() => openCopyHandleModal()}>复制</span>
  1037. <span key="3" onClick={() => openTransfer()}>添加</span>
  1038. </div>
  1039. </div>
  1040. {currentSelectedTreeNode && <BMSTable params={searchParams} actionRef={tableRef} rowKey='id' columns={[...tableColumn, {
  1041. title: '操作',
  1042. key: 'option',
  1043. width: 140,
  1044. valueType: 'option',
  1045. render: (text, record: any) => [
  1046. <a key={'edit'} onClick={() => {
  1047. if (!ifEdit) {
  1048. set_ifEdit(true);
  1049. set_currentEditRow(record)
  1050. }
  1051. if (ifEdit) {
  1052. editBtnHandle();
  1053. }
  1054. }}>{(ifEdit && currentEditRow?.id == record.id) ? '保存' : '编辑'}</a>,
  1055. <Fragment key={'cancel'}>{(ifEdit && currentEditRow?.id == record.id) && <a onClick={() => set_ifEdit(false)}>取消</a>}</Fragment>,
  1056. <Popconfirm key="popconfirm" title={`确认删除吗?`} okText="是" cancelText="否" onConfirm={() => delHandle(record)}>
  1057. {(currentEditRow?.id != record.id || !ifEdit) && <a key={'del'}>删除</a>}
  1058. </Popconfirm>
  1059. ],
  1060. }]} request={(params, sort, filter) => getTableData('BILL', params, sort, filter)} />}
  1061. </div>
  1062. )
  1063. }
  1064. {
  1065. currentSelectedTabKey == '2' && (
  1066. <div className='tabContent'>
  1067. <div className='tableToolbar'>
  1068. <div className='search'>
  1069. <span>检索:</span><Input className='searchInput' allowClear placeholder="请输入项目名称" onChange={(e) => {
  1070. set_searchKeywords(e.target.value);
  1071. if (e.target.value.length == 0) {
  1072. set_searchParams({
  1073. ...searchParams,
  1074. name: ''
  1075. });
  1076. }
  1077. }} suffix={
  1078. <IconFont type="iconsousuo" onClick={() => tableSearchHandle()} />
  1079. } />
  1080. </div>
  1081. <div className={'btnGroup'}>
  1082. <span key="2" onClick={() => openCopyHandleModal()}>复制</span>
  1083. <span key="3" onClick={() => openTransfer()}>添加</span>
  1084. </div>
  1085. </div>
  1086. {currentSelectedTreeNode && <BMSTable actionRef={tableRef} params={searchParams} rowKey='id' columns={[...tableColumn, {
  1087. title: '操作',
  1088. key: 'option',
  1089. width: 140,
  1090. valueType: 'option',
  1091. render: (text, record: any) => [
  1092. <a key={'edit'} onClick={() => {
  1093. if (!ifEdit) {
  1094. set_ifEdit(true);
  1095. set_currentEditRow(record)
  1096. }
  1097. if (ifEdit) {
  1098. editBtnHandle();
  1099. }
  1100. }}>{(ifEdit && currentEditRow?.id == record.id) ? '保存' : '编辑'}</a>,
  1101. <Fragment key={'cancel'}>{(ifEdit && currentEditRow?.id == record.id) && <a onClick={() => set_ifEdit(false)}>取消</a>}</Fragment>,
  1102. <Popconfirm key="popconfirm" title={`确认删除吗?`} okText="是" cancelText="否" onConfirm={() => delHandle(record)}>
  1103. {(currentEditRow?.id != record.id || !ifEdit) && <a key={'del'}>删除</a>}
  1104. </Popconfirm>
  1105. ],
  1106. }]} request={(params, sort, filter) => getTableData('INDIC', params, sort, filter)} />}
  1107. </div>
  1108. )
  1109. }
  1110. {
  1111. currentSelectedTabKey == '3' && (
  1112. <div className='tabContent'>
  1113. <div className='tableToolbar'>
  1114. <div className='search'>
  1115. <span>检索:</span><Input className='searchInput' allowClear placeholder="请输入项目名称" onChange={(e) => {
  1116. set_searchKeywords(e.target.value);
  1117. if (e.target.value.length == 0) {
  1118. set_searchParams({
  1119. ...searchParams,
  1120. name: ''
  1121. });
  1122. }
  1123. }} suffix={
  1124. <IconFont type="iconsousuo" onClick={() => tableSearchHandle()} />
  1125. } />
  1126. </div>
  1127. <div className={'btnGroup'}>
  1128. <span key="2" onClick={() => openCopyHandleModal()}>复制</span>
  1129. <span key="3" onClick={() => openTransfer()}>添加</span>
  1130. </div>
  1131. </div>
  1132. {currentSelectedTreeNode && <BMSTable actionRef={tableRef} params={searchParams} rowKey='id' columns={[...tableColumn, {
  1133. title: '操作',
  1134. key: 'option',
  1135. valueType: 'option',
  1136. render: (text, record: any) => [
  1137. <Popconfirm key="popconfirm" title={`确认删除吗?`} okText="是" cancelText="否" onConfirm={() => delHandle(record)}>
  1138. {<a key={'del'}>删除</a>}
  1139. </Popconfirm>
  1140. ],
  1141. }]} request={(params, sort, filter) => getTableData('NONCHECK', params, sort, filter)} />}
  1142. </div>
  1143. )
  1144. }
  1145. {
  1146. currentSelectedTabKey == '4' && (
  1147. <div className='tabContent'>
  1148. <div className='tableToolbar'>
  1149. <div className='search'>
  1150. <span>检索:</span><Input className='searchInput' allowClear placeholder="请输入项目名称" onChange={(e) => {
  1151. set_searchKeywords(e.target.value);
  1152. if (e.target.value.length == 0) {
  1153. set_searchParams({
  1154. ...searchParams,
  1155. name: ''
  1156. });
  1157. }
  1158. }} suffix={
  1159. <IconFont type="iconsousuo" onClick={() => tableSearchHandle()} />
  1160. } />
  1161. </div>
  1162. <div className={'btnGroup'}>
  1163. <span key="2" onClick={() => openCopyHandleModal()}>复制</span>
  1164. <span key="3" onClick={() => addCostProject()}>添加</span>
  1165. </div>
  1166. </div>
  1167. {currentSelectedTreeNode && <BMSTable actionRef={tableRef} pagination={false} params={searchParams} rowKey='id' columns={[...tableColumn, {
  1168. title: '操作',
  1169. key: 'option',
  1170. width: 140,
  1171. valueType: 'option',
  1172. render: (text, record: any) => [
  1173. <a key={'edit'} onClick={() => {
  1174. if (!ifEdit) {
  1175. set_ifEdit(true);
  1176. set_currentEditRow(record)
  1177. }
  1178. if (ifEdit) {
  1179. editBtnHandle();
  1180. }
  1181. }}>{(ifEdit && currentEditRow?.id == record.id) ? '保存' : '编辑'}</a>,
  1182. <Fragment key={'cancel'}>{(ifEdit && currentEditRow?.id == record.id) && <a onClick={() => set_ifEdit(false)}>取消</a>}</Fragment>,
  1183. <Popconfirm key="popconfirm" title={`确认删除吗?`} okText="是" cancelText="否" onConfirm={() => delHandle(record)}>
  1184. {(currentEditRow?.id != record.id || !ifEdit) && <a key={'del'}>删除</a>}
  1185. </Popconfirm>
  1186. ],
  1187. }]} request={(params, sort, filter) => getTableData('COST', params, sort, filter)} />}
  1188. </div>
  1189. )
  1190. }
  1191. </BMSPagecontainer>
  1192. </div>
  1193. </div>
  1194. );
  1195. };
  1196. export default CheckUnitProjectSet;