index.tsx 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586
  1. /*
  2. * @Author: code4eat awesomedema@gmail.com
  3. * @Date: 2023-03-03 11:30:33
  4. * @LastEditors: code4eat awesomedema@gmail.com
  5. * @LastEditTime: 2024-08-16 10:41:16
  6. * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/pubDicTypeMana/index.tsx
  7. * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  8. */
  9. import { createFromIconfontCN } from '@ant-design/icons';
  10. import { ActionType } from '@ant-design/pro-components';
  11. import { ModalForm, ProFormDigit, ProFormSelect, ProFormText, ProFormTextArea } from '@ant-design/pro-form';
  12. import { ProColumns } from '@ant-design/pro-table';
  13. import { Dropdown, Input, MenuProps, message, Form, Tooltip, Popconfirm } from 'antd';
  14. import { Key } from 'react';
  15. import { useEffect, useRef, useState } from 'react';
  16. import { getOrderList, getOrderItemList, addLeftList, editLeftList, delLeftList, batchDelTableData, addTableData, delData, getOrderType, importLeftListData, editTableData } from './service';
  17. import './style.less';
  18. import { SortableContainer, SortableElement, SortableHandle } from 'react-sortable-hoc';
  19. import '../../../../utils/zhongtaiB'
  20. import KCIMPagecontainer from '@/components/KCIMPageContainer';
  21. import { KCIMTable } from '@/components/KCIMTable';
  22. import { getTargetDic } from '@/services/auth';
  23. import TableSelecter from './tableSelector';
  24. import { downloadTemplateReq } from '@/utils/tooljs';
  25. import KCIMUpload from '@/components/KCIMUpload';
  26. const IconFont = createFromIconfontCN({
  27. scriptUrl: '',
  28. });
  29. let _currentSelectedType: any = undefined;
  30. const MedicalOrderProjectMana = () => {
  31. const [tableDataFilterParams, set_tableDataFilterParams] = useState<any | undefined>();
  32. const [tableDataSearchKeywords, set_tableDataSearchKeywords] = useState<string>('');
  33. const [selectedRowKeys, set_selectedRowKeys] = useState<Key[]>([]);
  34. const [typeList, set_typeList] = useState<any[]>([]);
  35. const [showTypeListArr, set_showTypeListArr] = useState<any[]>([]);
  36. const [currentSelectedType, set_currentSelectedType] = useState<any | undefined>(undefined);
  37. const [tableSelecterVisible, set_tableSelecterVisible] = useState(false);
  38. const [currentEditLeftData, set_currentEditLeftData] = useState<any | undefined>(undefined);
  39. const [currentEditRow, set_currentEditRow] = useState<undefined | any>(undefined);
  40. const [leftDataSearchKeyVal, set_leftDataSearchKeyVal] = useState<undefined | string>(undefined);
  41. const tableRef = useRef<ActionType>();
  42. const [orderType, set_orderType] = useState<undefined | string>(undefined);
  43. const column: ProColumns[] = [
  44. {
  45. title: '收费项目代码',
  46. ellipsis: true,
  47. width:120,
  48. dataIndex: 'itemCode',
  49. },
  50. {
  51. title: '收费项目名称',
  52. dataIndex: 'itemName',
  53. },
  54. {
  55. title: '收费项目类别',
  56. width: 100,
  57. dataIndex: 'itemTypeName',
  58. },
  59. {
  60. title: '数量',
  61. dataIndex: 'num',
  62. width: 100,
  63. renderText(num, record, index, action) {
  64. return (
  65. <div style={{ display: 'flex', flexDirection: 'row', alignItems: 'center' }}>
  66. {
  67. (currentEditRow && currentEditRow.id == record.id) && (
  68. <>
  69. <ProFormDigit
  70. width={80}
  71. noStyle
  72. fieldProps={{
  73. value: num,
  74. onChange(value) {
  75. set_currentEditRow({ ...record, num: value ? value : 0 });
  76. },
  77. }}
  78. />
  79. <img onClick={() => updateTable({ ...record }, 'EDIT')} style={{ width: 16, height: 16, display: 'inline-block', marginLeft: 8, cursor: 'pointer' }} src={require('../../../../../static/confirmIcon.png')} />
  80. </>
  81. )
  82. }
  83. {
  84. (!currentEditRow || (currentEditRow&&currentEditRow.id != record.id)) && (
  85. <>
  86. <div>{num}</div>
  87. <img onClick={() => set_currentEditRow(record)} style={{ width: 16, height: 16, display: 'inline-block', marginLeft: 8, cursor: 'pointer' }} src={require('../../../../../static/editIcon.png')} />
  88. </>
  89. )
  90. }
  91. </div>
  92. )
  93. },
  94. },
  95. {
  96. title: '操作',
  97. key: 'option',
  98. width:60,
  99. valueType: 'option',
  100. render: (_: any, record: any) => {
  101. return [
  102. <Popconfirm
  103. title="是否确认删除?"
  104. key="del"
  105. onConfirm={() => delTableData(record.id)}
  106. >
  107. <a>删除</a>
  108. </Popconfirm>
  109. ]
  110. },
  111. },
  112. ]
  113. const getTableData = async (params: any) => {
  114. const resp = await getOrderItemList({ ...params });
  115. if (resp) {
  116. return {
  117. data: resp.list,
  118. success: true,
  119. total: resp.totalCount,
  120. pageSize: resp.pageSize,
  121. totalPage: resp.totalPage,
  122. }
  123. } else {
  124. return []
  125. }
  126. }
  127. //获取左侧列表
  128. const getPageLeftReports = async (orderType?: string) => {
  129. const resp = await getOrderList(orderType);
  130. if (resp) {
  131. set_typeList(resp);
  132. set_showTypeListArr(resp);
  133. }
  134. }
  135. const delTableData = async (id: number) => {
  136. const resp = await delData(id);
  137. if (resp) {
  138. message.success('操作成功!');
  139. tableRef.current?.reload();
  140. }
  141. }
  142. const batchDelHandle = async () => {
  143. const resp = await batchDelTableData(selectedRowKeys);
  144. if (resp) {
  145. message.success('操作成功!');
  146. set_selectedRowKeys([]);
  147. tableRef.current?.reload();
  148. }
  149. }
  150. const tableSelecterCommit = async (keys: Key[], rows: any[]) => {
  151. const arr = rows.map((a, index) => ({
  152. itemCode: a.itemCode,
  153. itemName: a.itemName,
  154. itemType: a.itemType,
  155. }));
  156. const result = {
  157. orderCode: currentSelectedType.code,
  158. items: arr
  159. }
  160. const resp = await addTableData(result);
  161. if (resp) {
  162. message.success('操作成功');
  163. set_tableSelecterVisible(false);
  164. tableRef.current?.reload();
  165. }
  166. }
  167. const updateTable = async (formVal: any, type: 'EDIT' | "ADD" | 'ADD_LEFTDATA' | 'EDIT_LEFTDATA', data?: any[]) => {
  168. // console.log({formVal,type});
  169. if (type == 'ADD_LEFTDATA') {
  170. const resp = await addLeftList({
  171. name: formVal.name,
  172. type: formVal.type,
  173. code: formVal.code,
  174. description: formVal.description
  175. });
  176. if (resp) {
  177. getPageLeftReports();
  178. }
  179. }
  180. if (type == 'EDIT_LEFTDATA') {
  181. const resp = await editLeftList({
  182. id: formVal.id,
  183. name: formVal.name,
  184. code: formVal.code,
  185. type: formVal.type,
  186. description: formVal.description
  187. });
  188. if (resp) {
  189. getPageLeftReports();
  190. }
  191. }
  192. if (type == 'EDIT') {
  193. const resp = await editTableData({
  194. id: formVal.id,
  195. orderCode: currentSelectedType.code,
  196. itemCode: formVal.itemCode,
  197. num: currentEditRow.num
  198. });
  199. if (resp) {
  200. tableRef.current?.reload();
  201. }
  202. }
  203. set_currentEditRow(undefined);
  204. return true;
  205. }
  206. const downloadTemplate = async () => {
  207. await downloadTemplateReq('/costAccount/setting/exportOrder');
  208. };
  209. const importData = () => {
  210. return (
  211. <ModalForm
  212. width={360}
  213. title={`导入数据`}
  214. trigger={
  215. <a className="import" key="3">
  216. 导入
  217. </a>
  218. }
  219. submitter={{
  220. render: (props, defaultDoms) => {
  221. const needBtn = defaultDoms.filter((b) => {
  222. return b.key != 'rest';
  223. });
  224. return [
  225. ...needBtn,
  226. ];
  227. },
  228. }}
  229. onFinish={async (values) => {
  230. const {
  231. importFile: { fileList },
  232. } = values;
  233. let formData = new FormData();
  234. formData.append('file', fileList[0].originFileObj);
  235. const resp = await importLeftListData(formData);
  236. if (resp) {
  237. getPageLeftReports();
  238. return true;
  239. }
  240. }}
  241. >
  242. <Form.Item name={'importFile'}>
  243. <KCIMUpload downloadTemplateFile={() => downloadTemplate()} />
  244. </Form.Item>
  245. </ModalForm>
  246. );
  247. };
  248. const UpDataActBtn = ({ record, type }: { record: any, type: 'EDIT' | 'ADD' | 'ADD_LEFTDATA' | 'EDIT_LEFTDATA' }) => {
  249. const getTrriger = () => {
  250. if (type == 'ADD') {
  251. return <span className='add'>新增</span>
  252. }
  253. if (type == 'EDIT') {
  254. return <a key="edit" >编辑</a>
  255. }
  256. if (type == 'ADD_LEFTDATA') {
  257. return (<a key="edit" >新增</a>)
  258. }
  259. if (type == 'EDIT_LEFTDATA') {
  260. return <a key="edit" >编辑</a>
  261. }
  262. }
  263. return (
  264. <ModalForm
  265. title={type == 'ADD_LEFTDATA' ? `新增医嘱项目` : `编辑医嘱项目`}
  266. width={352}
  267. initialValues={type == 'EDIT_LEFTDATA' ? { ...record } : {}}
  268. trigger={
  269. getTrriger()
  270. }
  271. onFinish={(val) => {
  272. return updateTable(type == 'EDIT_LEFTDATA' ? { ...record, ...val } : val, type);
  273. }}
  274. >
  275. <ProFormText
  276. label='医嘱项目代码:'
  277. name='code'
  278. rules={[{ required: true, message: '医嘱项目代码不能为空!' }]}
  279. />
  280. <ProFormText
  281. label='医嘱项目名称:'
  282. name='name'
  283. rules={[{ required: true, message: '医嘱项目名称不能为空!' }]}
  284. />
  285. <ProFormSelect
  286. name="type"
  287. label="医嘱项目类别:"
  288. placeholder="请选择"
  289. request={async () => {
  290. const resp = await getOrderType();
  291. if (resp) {
  292. return resp.map((a: any) => ({ label: a.name, value: a.code }));
  293. }
  294. return []
  295. }}
  296. rules={[{ required: true, message: '医嘱项目类别不能为空!' }]}
  297. />
  298. <ProFormTextArea
  299. label='说明:'
  300. name='description'
  301. />
  302. </ModalForm>
  303. )
  304. }
  305. const optItems: MenuProps['items'] = [
  306. {
  307. key: '1',
  308. label: <UpDataActBtn key={'act'} record={undefined} type='ADD_LEFTDATA' />,
  309. },
  310. {
  311. key: '2',
  312. label: importData()
  313. },
  314. ];
  315. const moreItems: MenuProps['items'] = [
  316. {
  317. key: '1',
  318. label: <UpDataActBtn key={'act'} record={currentEditLeftData} type='EDIT_LEFTDATA' />,
  319. },
  320. {
  321. key: '2',
  322. label: (
  323. <a onClick={async (e) => {
  324. e.preventDefault();
  325. const resp = await delLeftList(currentEditLeftData.id);
  326. if (resp) {
  327. getPageLeftReports();
  328. }
  329. }}>
  330. 删除
  331. </a>
  332. ),
  333. },
  334. ];
  335. const tableDataSearchHandle = (paramName: string) => {
  336. set_tableDataFilterParams({
  337. ...tableDataFilterParams,
  338. [`${paramName}`]: tableDataSearchKeywords
  339. })
  340. }
  341. useEffect(() => {
  342. if (currentSelectedType) {
  343. set_tableDataFilterParams({ ...tableDataFilterParams, orderCode: currentSelectedType.code });
  344. }
  345. }, [currentSelectedType])
  346. useEffect(() => {
  347. if (showTypeListArr.length > 0) {
  348. set_currentSelectedType(showTypeListArr[0]);
  349. _currentSelectedType = showTypeListArr[0];
  350. // set_tableDataFilterParams({ ...tableDataFilterParams, orderCode: showTypeListArr[0].code });
  351. }
  352. }, [showTypeListArr]);
  353. useEffect(() => {
  354. const result = typeList.filter(item => item.name.indexOf(leftDataSearchKeyVal) != -1);
  355. set_showTypeListArr(result);
  356. }, [leftDataSearchKeyVal]);
  357. useEffect(() => {
  358. if (orderType != '-1') {
  359. getPageLeftReports(orderType);
  360. } else {
  361. getPageLeftReports();
  362. }
  363. }, [orderType])
  364. useEffect(() => {
  365. getPageLeftReports();
  366. }, [])
  367. return (
  368. <KCIMPagecontainer title={false} className='MedicalOrderProjectMana'>
  369. <TableSelecter
  370. onVisibleChange={(bool) => set_tableSelecterVisible(bool)}
  371. title='添加'
  372. rowKey={'itemCode'}
  373. defaultSelectedKeys={[]}
  374. record={_currentSelectedType}
  375. open={tableSelecterVisible}
  376. onFinish={(keys, rows) => tableSelecterCommit(keys, rows)}
  377. />
  378. {selectedRowKeys.length > 0 && (
  379. <div className='bottomBar'>
  380. <span>已选择<a>{selectedRowKeys.length}</a>项</span>
  381. <a onClick={() => batchDelHandle()}>批量删除</a>
  382. </div>
  383. )}
  384. <div className='left'>
  385. <div style={{ padding: '0 8px' }}>
  386. <ProFormSelect
  387. noStyle
  388. style={{ width: '100%', marginBottom: 8, }}
  389. placeholder='选择医嘱类型'
  390. fieldProps={{
  391. defaultValue: -1, onChange(value, option) {
  392. set_leftDataSearchKeyVal(undefined);
  393. set_orderType(`${value}`);
  394. },
  395. }}
  396. request={async () => {
  397. const resp = await getOrderType();
  398. if (resp) {
  399. const arr = resp.map((a: any) => ({ label: a.name, value: a.code }));
  400. return [
  401. { label: '全部医嘱类型', value:-1 },
  402. ...arr
  403. ]
  404. }
  405. return [
  406. { label: '全部医嘱类型', value:-1 }
  407. ]
  408. }}
  409. />
  410. </div>
  411. <div className='toolbar'>
  412. <Input placeholder={'报表名称'} allowClear
  413. suffix={
  414. <IconFont type="iconsousuo" style={{ color: '#99A6BF' }} />
  415. }
  416. value={leftDataSearchKeyVal}
  417. style={{ width: 156 }}
  418. onChange={(e) => {
  419. set_leftDataSearchKeyVal(e.target.value);
  420. }}
  421. />
  422. <Dropdown menu={{ items: optItems }} placement="bottom" >
  423. <div className='add'>
  424. <img src={require('../../../../../static/addIcon_black.png')} alt="" />
  425. </div>
  426. </Dropdown>
  427. </div>
  428. <div className='wrap'>
  429. {
  430. showTypeListArr.map((item, index) => {
  431. return (
  432. <div className={currentSelectedType ? currentSelectedType.id == item.id ? 'type on' : 'type' : 'type'}
  433. key={index}
  434. onClick={() => {
  435. set_currentSelectedType(item)
  436. _currentSelectedType = item;
  437. }}
  438. >
  439. <img className='icon' src={require('../../../../../static/reportIcon.png')} alt="" />
  440. <div className='content'>
  441. <Tooltip title={item.name} >
  442. <div className='name'>{item.name}</div>
  443. <div className='sub'>{item.typeName}</div>
  444. </Tooltip>
  445. </div>
  446. <Dropdown menu={{ items: moreItems }} placement="bottom" onOpenChange={(bool) => { bool && set_currentEditLeftData(item) }}>
  447. <div className='more'>
  448. <img src={require('../../../../../static/more_point_gray.png')} alt="" />
  449. </div>
  450. </Dropdown>
  451. </div>
  452. )
  453. })
  454. }
  455. </div>
  456. </div>
  457. <div className='right'>
  458. <div className='toolBar'>
  459. <div className='filter'>
  460. <div className='filterItem'>
  461. <span className='label' style={{ whiteSpace: 'nowrap' }}> 项目名称:</span>
  462. <Input placeholder={'请输入'} allowClear
  463. suffix={
  464. <IconFont type="iconsousuo" style={{ color: '#99A6BF' }} onClick={() => tableDataSearchHandle('itemName')} />
  465. }
  466. onChange={(e) => {
  467. set_tableDataSearchKeywords(e.target.value);
  468. if (e.target.value.length == 0) {
  469. set_tableDataFilterParams({
  470. ...tableDataFilterParams,
  471. itemName: ''
  472. });
  473. }
  474. }}
  475. onPressEnter={(e) => {
  476. set_tableDataFilterParams({
  477. ...tableDataFilterParams,
  478. itemName: (e.target as HTMLInputElement).value
  479. });
  480. }}
  481. />
  482. </div>
  483. </div>
  484. <div className='btnGroup'>
  485. <span className='add' onClick={() => set_tableSelecterVisible(true)}>添加</span>
  486. </div>
  487. </div>
  488. <div style={{ marginTop: 16 }}>
  489. {currentSelectedType && <KCIMTable actionRef={tableRef} columns={column}
  490. scroll={{ y:`calc(100vh - 233px)` }}
  491. rowKey='id'
  492. params={tableDataFilterParams}
  493. request={(params) => getTableData(params)}
  494. tableAlertRender={false}
  495. rowSelection={{
  496. onChange(selectedRowKeys, selectedRows, info) {
  497. set_selectedRowKeys(selectedRowKeys);
  498. },
  499. }}
  500. />}
  501. </div>
  502. </div>
  503. </KCIMPagecontainer>
  504. )
  505. }
  506. export default MedicalOrderProjectMana;