AddData.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  1. import { useEffect, useState, useContext } from 'react';
  2. import { Form, Input, Button, Tabs, Space, Switch, Breadcrumb, Radio, TreeSelect, message, Modal } from 'antd';
  3. import './index.less';
  4. import DataContext from './data-context';
  5. import SelectedTag from '@common/SelectedTag.js';
  6. import MyDeptStruct from '@common/MyDeptStruct.js';
  7. import { useSelector } from 'react-redux'
  8. import apiObj from '@api/index';
  9. import {filterIds } from '@utils/index';
  10. import backIcon from "@images/back.png";
  11. import DoctorList from "./doctorList"
  12. const { api, xPost } = apiObj;
  13. const { SHOW_PARENT } = TreeSelect;
  14. const { TabPane } = Tabs;
  15. function AddData(props) {
  16. useEffect(() => {
  17. getOrgList();
  18. if (isEdit) {
  19. setEditData();
  20. }
  21. }, []);
  22. const { back } = props;
  23. const [form] = Form.useForm();
  24. const [isChange, setIsChange] = useState(false);
  25. const [visible, setVisible] = useState(false);
  26. const [checkedUser, setCheckedUser] = useState([]); //指定用户选中项
  27. const [checkedUserIds, setCheckedUserIds] = useState([]); //指定用户选中项id
  28. const [checkedDepts, setCheckedDepts] = useState([]); //指定科室选中项
  29. const [checkedDeptIds, setCheckedDeptIds] = useState([]); //指定科室选中的科室项id
  30. const [checkedHosIds, setCheckedHosIds] = useState([]); //指定科室选中的医院项id
  31. const [checkedTreeItems, setCheckedTreeItems] = useState([]); //指定科室选中的树结构
  32. const [value, setValue] = useState([]);
  33. const [tabKey, setTabKey] = useState(); //权限范围选中的tab id
  34. const [tabIndex, setTabIndex] = useState('0'); //权限范围选中的tab index
  35. const [showCustom,setShowCustom]=useState(false); //是否显示自定义内容
  36. const [treeRloe, setTreeRloe] = useState([]);
  37. const [tags, setTags] = useState([[]]);
  38. const [orgList, setOrgList] = useState([]);
  39. const [selectedRowKeys, setSelectedRowKeys] = useState([]);
  40. const { save, formData, operType, val, tag,authChecksArr, originData} = useContext(DataContext);
  41. const isEdit = operType===3; //是否为编辑
  42. const staticInfo = useSelector(state => {
  43. return state.staticInfo;
  44. });
  45. const { dataList } = staticInfo;
  46. const initialValues = formData
  47. const validateMessages = {
  48. required: '${label}不能为空',
  49. };
  50. function handleOk() {
  51. back()
  52. }
  53. function handleCancel() {
  54. setVisible(false)
  55. }
  56. const goback = () => {
  57. if (form.isFieldsTouched()) {
  58. setVisible(true)
  59. } else {
  60. back()
  61. }
  62. };
  63. //编辑数据填充
  64. function setEditData(){
  65. const data = (originData[tabIndex]||{}).dataAuthDetail||{};
  66. const sysObj = form.getFieldValue().softwareVOS[tabIndex]||{};
  67. const dataType = sysObj.dataType;
  68. const isCustom = dataType === '7';
  69. //判断权限范围类型,是否显示自定义内容
  70. setShowCustom(isCustom);
  71. if(!isCustom||!data){ //非自定义不处理
  72. return;
  73. }
  74. const depts = data.depts||[];
  75. const doctors = data.doctors||[];
  76. const hospitals = data.hospitals||[];
  77. const hosIds = filterIds(hospitals);
  78. const deptIds = filterIds(depts);
  79. setCheckedUser(doctors);
  80. setCheckedUserIds(filterIds(doctors,['id','name']));
  81. setCheckedTreeItems(filterIds(hospitals,['hospitalId','hospitalName','id','name'],true));
  82. setCheckedHosIds(hosIds);
  83. //setHosArr(hospitals||[]);
  84. setCheckedDepts([...hospitals,...depts]);
  85. setCheckedDeptIds(hosIds.concat(deptIds));
  86. }
  87. //获取当前用于所属角色
  88. function getCreateRoles(softwareId) {
  89. const params = {
  90. softwareId: softwareId
  91. }
  92. xPost(api.getCreateRoles, params).then((res) => {
  93. if (res.data.code === 200) {
  94. const data = res.data.data;
  95. let arr = JSON.parse(JSON.stringify(data).replace(/name/g, 'title').replace(/id/g, 'value'))
  96. setTreeRloe(arr)
  97. }
  98. })
  99. }
  100. //获取组织列表
  101. function getOrgList() {
  102. xPost(api.getUserHospitals).then((res) => {
  103. if (res.data.code === 200) {
  104. const data = res.data.data;
  105. const { software } = data;
  106. setOrgList(software);
  107. setTabKey(software[0].id)
  108. getCreateRoles(software[0].id)
  109. if (isEdit) {
  110. software.forEach((it, index) => {
  111. tag.forEach((item, i) => {
  112. tags[index] = []
  113. if (i == index) {
  114. tags[index] = tag[i]
  115. }
  116. })
  117. setTags([...tags])
  118. })
  119. } else {
  120. software.forEach((it, index) => {
  121. tags[index] = []
  122. setTags([...tags])
  123. })
  124. }
  125. } else {
  126. message.warning(res.data.msg || '获取医院列表失败');
  127. }
  128. }).catch(() => {
  129. message.error("接口出错");
  130. });
  131. }
  132. const onChange = (e, i) => {
  133. let val = value
  134. const formData = form.getFieldsValue();
  135. let arr = formData.softwareVOS;
  136. arr[tabIndex].id = tabKey
  137. arr[tabIndex].softwareMenuIds = []
  138. arr[tabIndex].dataAuthDetails = []
  139. //arr[tabIndex].selectedRowKeys = []
  140. if (e.target.value !== '7') {
  141. setShowCustom(false);
  142. arr[tabIndex].dataAuthDetails = [{
  143. dataType: e.target.value
  144. }]
  145. }else{
  146. setShowCustom(true);
  147. }
  148. //tags[tabIndex] = []
  149. val[i] = e.target.value
  150. //selectedRowKeys[tabIndex] = []
  151. form.setFieldsValue({
  152. softwareVOS: arr
  153. });
  154. //setTags([...tags])
  155. //setValue([...val])
  156. //setSelectedRowKeys([...selectedRowKeys])
  157. setIsChange(true)
  158. };
  159. function callback(key) {
  160. const ikey = key.split('-');
  161. setTabKey(ikey[0])
  162. setTabIndex(ikey[1])
  163. const soft = form.getFieldValue().softwareVOS[ikey[1]];
  164. if(soft){
  165. setShowCustom(soft.dataType === '7');
  166. }else{
  167. setShowCustom(false);
  168. }
  169. getCreateRoles(ikey[0])
  170. }
  171. function treeChange(value) {
  172. const formData = form.getFieldsValue();
  173. let arr = formData.softwareVOS;
  174. arr[tabIndex].roles = value
  175. form.setFieldsValue({
  176. softwareVOS: arr
  177. });
  178. setIsChange(true)
  179. }
  180. // 去重
  181. function unique(arr) {
  182. let result = {};
  183. let finalResult = [];
  184. for (let i = 0; i < arr.length; i++) {
  185. result[arr[i].detailId] = arr[i];
  186. }
  187. for (let item in result) {
  188. finalResult.push(result[item]);
  189. }
  190. return finalResult;
  191. }
  192. //医生选中
  193. function checkDoctEvent(selectedRowKeys) {
  194. const formData = form.getFieldsValue();
  195. //const tempAuthData = formData.softwareVOS[tabIndex].dataAuthDetails;
  196. let arr = [];
  197. let docIds=[];
  198. selectedRowKeys.forEach(it => {
  199. arr.push({
  200. id: it.split('-')[0],
  201. dataType: '7',
  202. detailId: it.split('-')[0],
  203. detailType: 3,
  204. name: it.split('-')[1],
  205. })
  206. docIds.push(it);
  207. });
  208. const docArr = unique(arr);
  209. formData.softwareVOS[tabIndex].dataAuthDetails = [...docArr,...checkedDepts];
  210. //formData.softwareVOS[tabIndex].selectedRowKeys = selectedRowKeys;
  211. form.setFieldsValue({
  212. softwareVOS: formData.softwareVOS
  213. });
  214. //保存需要展示的已选中标签数据
  215. setCheckedUser(docArr)
  216. setCheckedUserIds(docIds);
  217. }
  218. //树形结构选中事件
  219. //选中科室
  220. function handleCheckDept(checks,e){
  221. setCheckedTreeItems(checks);
  222. //排序,短的在前长的在后,为去重(组织下全选,只传组织id)做准备
  223. const posArr = [...e.checkedNodesPositions].sort((a,b)=>{
  224. return a.pos.length-b.pos.length;
  225. });
  226. //console.log('排序后:',posArr);
  227. const structDepts = structureDeptTag(posArr);
  228. const {deptIds,hosIds,paramHos,paramDept} = structDepts;
  229. let deptIdsArr=[...deptIds];
  230. let deptArr=[...paramDept];
  231. let hosIdsArr=[...hosIds];
  232. let hosArr=[...paramHos];console.log('树选中:',hosIdsArr)
  233. setCheckedDepts(hosArr.concat(deptArr)); //显示的排序可能需要再考虑一下
  234. setCheckedDeptIds(deptIdsArr);
  235. setCheckedHosIds(hosIdsArr);
  236. const tempFormData = form.getFieldsValue();
  237. tempFormData.softwareVOS[tabIndex].dataAuthDetails=[...checkedUser,...hosArr,...deptArr];
  238. form.setFieldsValue(tempFormData);
  239. }
  240. //格式化选中科室数据
  241. function structureDeptTag(pos){ //全选传医院id,非全选传科室id
  242. let tempPos=[],hosIds=[],hosArr=[],len=0,deptIds=[],deptArr=[],temp=[],tempKey='';//作为已选中标签显示的数据
  243. let paramHos=[],paramDept=[]; //作为新增接口参数的数据
  244. let it=null,checks=[];
  245. for(let i=0;i<pos.length;i++){
  246. it=pos[i];
  247. tempKey=it.node.key;
  248. if(it.pos==='0-0'){ //全选了平台,终止遍历
  249. temp = tempKey.split("-");
  250. //hosArr.push({key:tempKey});
  251. paramHos.push({id:temp[0],detailId:temp[0],detailType:1,name:temp[1],dataType:'7',key:tempKey});
  252. hosIds.push(temp[0]);
  253. setCheckedTreeItems([tempKey]);
  254. return {hosIds:hosIds,deptIds:deptIds,deptObj:deptArr};
  255. }
  256. //如果当前节点的pos包含了tempPos里的某个数据,说明该节点的父节点已被选中并记录,自身则不需要记录
  257. if(!(tempPos.includes(it.pos.substr(0,5))||tempPos.includes(it.pos.substr(0,7)))){
  258. tempPos.push(it.pos); //记录需要展示的节点pos,作为去重的依据
  259. temp = tempKey.split("-");
  260. len=temp.length;
  261. //记录选中的节点id,从已选中标签中删除时控制树形结构选中状态用
  262. checks.push(tempKey);
  263. setCheckedTreeItems(checks);
  264. //医院id存入sendHospitals,科室id存入sendDepts
  265. if(len===2){
  266. //hosArr.push({key:tempKey});
  267. paramHos.push({id:temp[0],detailId:temp[0],name:temp[1],detailType:1,dataType:'7',key:tempKey});
  268. hosIds.push(temp[0]);
  269. }else{
  270. //deptArr.push({key:tempKey});
  271. paramDept.push({id:temp[2],detailId:temp[2],detailType:2,name:temp[1]+"-"+temp[3],dataType:'7',key:tempKey});
  272. deptIds.push(temp[2]);
  273. }
  274. }
  275. }
  276. return {hosIds:hosIds,deptIds:deptIds,paramDept,paramHos};
  277. }
  278. //删除已选用户/科室
  279. function handleTagDel(idx,type){ //type=1可看意思,type=2可看科室
  280. if(idx===undefined){ //无入参,清空所有
  281. //情况树状结构选中状态
  282. setCheckedTreeItems([]);
  283. //清空用户
  284. setCheckedUser([]);
  285. setCheckedUserIds([]);
  286. //清空科室
  287. setCheckedDepts([]);
  288. setCheckedDeptIds([]);
  289. setCheckedHosIds([]);
  290. const tempFormData = form.getFieldsValue();
  291. tempFormData.softwareVOS[tabIndex].dataAuthDetails=[];
  292. form.setFieldsValue(tempFormData);
  293. return;
  294. }
  295. //const idx=checkedUserIds.findIndex((it)=>it===id);
  296. const tempFormData = form.getFieldsValue();
  297. if(type===1){
  298. let checkedIdsArr=[...checkedUserIds];
  299. let checkedUserArr=[...checkedUser];
  300. checkedIdsArr.splice(idx,1);
  301. checkedUserArr.splice(idx,1);
  302. setCheckedUser(checkedUserArr);
  303. setCheckedUserIds(checkedIdsArr);
  304. tempFormData.softwareVOS[tabIndex].dataAuthDetails=[...checkedUserArr,...checkedDepts];
  305. form.setFieldsValue(tempFormData);
  306. }else if(type===2){
  307. //删除树结构中对应的选中状态
  308. const ikey = checkedDepts[idx].key;
  309. const tempItems = [...checkedTreeItems];
  310. const index = tempItems.findIndex((it)=>it===ikey);
  311. tempItems.splice(index,1);
  312. setCheckedTreeItems(tempItems);
  313. //console.log(ikey,index,checkedDepts,checkedTreeItems,tempItems)
  314. //删除对应的显示数据及传参数据
  315. let checkedDeptsArr=[...checkedDepts];
  316. let checkedHosIdsArr=[...checkedHosIds];
  317. let checkedDeptIdsArr=[...checkedDeptIds];
  318. checkedDeptsArr.splice(idx,1);
  319. checkedHosIdsArr.splice(idx,1);
  320. checkedDeptIdsArr.splice(idx-checkedHosIdsArr.length,1);
  321. setCheckedDepts(checkedDeptsArr); //选中的科室和医院合并过的
  322. setCheckedHosIds(checkedHosIdsArr);
  323. setCheckedDeptIds(checkedDeptIdsArr);
  324. tempFormData.softwareVOS[tabIndex].dataAuthDetails=[...checkedUser,...checkedDeptsArr];
  325. form.setFieldsValue(tempFormData);
  326. }
  327. }
  328. const onFinish = () => {
  329. console.log(form.getFieldsValue());
  330. save(form.getFieldsValue())
  331. };
  332. function swichChange(val) {
  333. form.setFieldsValue({ status: val ? 1 : 0 })
  334. }
  335. return (
  336. <>
  337. <Breadcrumb separator="">
  338. <Breadcrumb.Item><img className='back-icon' src={backIcon} onClick={goback} alt="返回上一页" /></Breadcrumb.Item>
  339. <Breadcrumb.Item>数据权限</Breadcrumb.Item>
  340. <Breadcrumb.Separator />
  341. <Breadcrumb.Item>{isEdit ? '修改' : '新增'}数据权限</Breadcrumb.Item>
  342. </Breadcrumb>
  343. <div className='form-center'>
  344. <Form labelCol={{ span: 4 }} wrapperCol={{ span: 18 }} form={form} name="nest-messages" onFinish={onFinish} initialValues={initialValues} validateMessages={validateMessages}>
  345. <Form.Item name="name" label="数据权限名称" rules={[{ required: true }]}>
  346. <Input placeholder="请填写数据权限名称" style={{ width: 300 }} autoComplete='off'/>
  347. </Form.Item>
  348. <Form.Item label="权限范围" rules={[{ required: true }]} >
  349. <Tabs type="card" onChange={callback}>
  350. {
  351. orgList.map((it, i) => {
  352. return (
  353. <TabPane tab={it.name} key={it.id + "-" + i} forceRender={isEdit && form.getFieldValue().softwareVOS[i] ? true : false}>
  354. <Form.Item
  355. key={i}
  356. name={['softwareVOS', i, 'dataType']} noStyle>
  357. <Radio.Group onChange={e => { onChange(e, i) }} className="radio">
  358. <Space direction="vertical">
  359. {dataList.map((Item) => {
  360. return (
  361. <Radio key={i} value={Item.name}>{Item.val}</Radio>
  362. )
  363. })
  364. }
  365. </Space>
  366. </Radio.Group>
  367. </Form.Item>
  368. <Form.Item key={i + "a"} hidden={true} name={['softwareVOS', i, 'id']} noStyle>
  369. <Input />
  370. </Form.Item>
  371. <Form.Item key={i + "b"} hidden={true} name={['softwareVOS', i, 'dataAuthDetails']} noStyle>
  372. <Input />
  373. </Form.Item>
  374. <Form.Item key={i + "e"} hidden={true} name={['softwareVOS', i, 'roles']} noStyle>
  375. <Input />
  376. </Form.Item>
  377. <Form.Item key={i + "c"} style={{ display: showCustom && it.id == tabKey ? 'block' : 'none' }}>
  378. <SelectedTag userData={checkedUser} deptData={checkedDepts} delTag={handleTagDel}></SelectedTag>
  379. </Form.Item>
  380. <Form.Item key={i + "d"} style={{ display: showCustom && it.id == tabKey ? 'block' : 'none' }}>
  381. <Tabs defaultActiveKey="0" className='tab-content'>
  382. <TabPane tab="可看医生" key="0" forceRender={isEdit && form.getFieldValue().softwareVOS[i] ? true : false}>
  383. <Form.Item
  384. name={['softwareVOS', i, 'selectedRowKeys']}
  385. >
  386. <DoctorList checkeds={checkedUserIds} checkDoct={(selectedRowKeys) => checkDoctEvent(selectedRowKeys)} />
  387. </Form.Item>
  388. </TabPane>
  389. <TabPane tab="可看科室" key="1" forceRender={isEdit && form.getFieldValue().softwareVOS[i] ? true : false}>
  390. <Form.Item>
  391. <MyDeptStruct checkeds={checkedTreeItems} checkEv={handleCheckDept} />
  392. </Form.Item>
  393. </TabPane>
  394. </Tabs>
  395. </Form.Item>
  396. </TabPane>
  397. )
  398. })
  399. }
  400. </Tabs>
  401. </Form.Item>
  402. <Form.Item label="所属角色" style={{marginLeft: '123px'}} required>
  403. {
  404. orgList.map((it, i) => {
  405. return (
  406. <Form.Item
  407. key={i}
  408. style={{ display: i == tabIndex ? 'block' : 'none' }}
  409. >
  410. {tabIndex == i ?
  411. <Form.Item key={i + "b"}
  412. name={['softwareVOS', i, 'roles']}
  413. rules={[
  414. {
  415. required: true,
  416. message: '请选择所属角色',
  417. },
  418. ]}>
  419. <TreeSelect
  420. style={{ width: 300 }}
  421. showSearch={false}
  422. treeData={treeRloe}
  423. onChange={treeChange}
  424. maxTagCount={1}
  425. treeCheckable
  426. showCheckedStrategy={SHOW_PARENT}
  427. placeholder="请选择角色"
  428. />
  429. </Form.Item>
  430. : null}
  431. </Form.Item>
  432. )
  433. })
  434. }
  435. </Form.Item>
  436. <Form.Item
  437. name="status"
  438. valuePropName="checked"
  439. label="当前状态"
  440. rules={[{ required: true, message: '请选择状态' }]}
  441. >
  442. <Switch onChange={swichChange} />
  443. </Form.Item>
  444. <Form.Item wrapperCol={{ span: 6, offset: 20 }}>
  445. <Button className='but' onClick={goback}>
  446. 取消
  447. </Button>
  448. <Button type="primary" htmlType="submit">
  449. 保存
  450. </Button>
  451. </Form.Item>
  452. </Form>
  453. <Modal
  454. title="提示"
  455. okText='确定'
  456. cancelText='取消'
  457. width={400}
  458. visible={visible}
  459. onOk={handleOk}
  460. onCancel={handleCancel}
  461. >
  462. <p>您还有内容未保存,确定要退出?</p>
  463. </Modal>
  464. </div>
  465. </>
  466. )
  467. }
  468. export default AddData;