Index.jsx 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566
  1. import React from 'react';
  2. import Login from '@components/login/Index.jsx';
  3. import DoctorScreen from '@pages/doctorScreen/Index.jsx';
  4. import BigScreen from '@pages/bigScreen/Index.jsx';
  5. import OperateScreen from '@pages/operateScreen/Index.jsx';
  6. import FingerprintJS from '@fingerprintjs/fingerprintjs';
  7. import { initSocket } from '@api/index.js';
  8. import { AntOutline, SetOutline } from 'antd-mobile-icons';
  9. import { Toast } from 'antd-mobile';
  10. // // 安卓相关处理
  11. import audioSrc from './../../assets/mp3.wav';
  12. window.webGetDeviceId = function (callback) {
  13. window.callback = callback;
  14. };
  15. class Home extends React.Component {
  16. constructor(props) {
  17. super(props);
  18. this.state = {
  19. visibleLogin: false,
  20. userData: {}, // 用户及房间数据
  21. patList: [], // 就诊等待数据
  22. waitPat: [],
  23. patListArea: [], //区域等待就诊患者数据
  24. reWaitPat: [], // 复诊的患者
  25. roomObj: {},
  26. delayPat: [], //候诊数据
  27. showType: 'doctor', // doctor医生诊室 area诊区叫号 operate手术室
  28. cache: {},
  29. colorName: localStorage.getItem('ZZJ-color'), // white-bg白色 dark-bg深色
  30. deviceID: '',
  31. hosLogo: '',
  32. voiceSrc: [],
  33. isPlay: false,
  34. voiceList: [],
  35. myStatus: false,
  36. // 模拟数据
  37. tempList: [
  38. {
  39. 'roomDesc': '专家诊室一', 'docName': '宦大达', 'callMsg':
  40. {
  41. 'callPat': [{ 'patCallNo': '11号', 'patName': '患*者' }],
  42. 'waitPat': [
  43. { 'patCallNo': '1', 'patName': '患*者1' },
  44. { 'patCallNo': '2', 'patName': '患*者2' },
  45. { 'patCallNo': '3', 'patName': '患*者3' },
  46. { 'patCallNo': '4', 'patName': '患*者4' },
  47. { 'patCallNo': '5', 'patName': '患*者5' },
  48. { 'patCallNo': '6', 'patName': '患*者6' },
  49. { 'patCallNo': '7', 'patName': '患*者7' },
  50. { 'patCallNo': '8', 'patName': '患*者8' },
  51. { 'patCallNo': '9', 'patName': '患*者9' },
  52. { 'patCallNo': '10', 'patName': '患*者10' },
  53. { 'patCallNo': '11', 'patName': '患*者11' },
  54. { 'patCallNo': '12', 'patName': '患*者12' }],
  55. 'reWaitPat': [
  56. { 'patCallNo': '复01', 'patName': '患*者1' },
  57. { 'patCallNo': '复02', 'patName': '患*者2' },
  58. { 'patCallNo': '复03', 'patName': '患者3a' },
  59. { 'patCallNo': '复01', 'patName': '患*者1' },
  60. { 'patCallNo': '复02', 'patName': '患*者2' },
  61. { 'patCallNo': '复03', 'patName': '患者3a' },
  62. { 'patCallNo': '复04', 'patName': '患者4a' }],
  63. },
  64. delayPat: '患*者1,患*者2,患者3a,患*者1,患*者2,患者3a,患者4a,患*者1,患*者2,患者3a,患*者1,患*者2,患者3a,患者4a患*者1,患*者2,患者3a,患*者1,患*者2,患者3a,患者4a',
  65. },
  66. {
  67. 'roomDesc': '诊室1', 'docName': '医生1', 'callMsg':
  68. {
  69. 'callPat': [{ 'patCallNo': '1号', 'patName': '患*者' }],
  70. 'waitPat': [
  71. { 'patCallNo': '复01', 'patName': '患*者1' },
  72. ],
  73. 'reWaitPat': [
  74. { 'patCallNo': '复01', 'patName': '患*者1' },
  75. ],
  76. }
  77. },
  78. {
  79. 'roomDesc': '诊室2', 'docName': '医生1', 'callMsg':
  80. {
  81. 'callPat': [{ 'patCallNo': '1号', 'patName': '患*者' }],
  82. 'waitPat': [
  83. { 'patCallNo': '复01', 'patName': '患*者1' },
  84. ],
  85. 'reWaitPat': [
  86. { 'patCallNo': '复01', 'patName': '患*者1' },
  87. ],
  88. }
  89. },
  90. {
  91. 'roomDesc': '诊室3', 'docName': '医生1', 'callMsg':
  92. {
  93. 'callPat': [{ 'patCallNo': '1号', 'patName': '患*者' }],
  94. 'waitPat': [
  95. { 'patCallNo': '复01', 'patName': '患*者1' },
  96. ],
  97. 'reWaitPat': [
  98. { 'patCallNo': '复01', 'patName': '患*者1' },
  99. ],
  100. }
  101. },
  102. {
  103. 'roomDesc': '诊室4', 'docName': '医生1', 'callMsg':
  104. {
  105. 'callPat': [{ 'patCallNo': '1号', 'patName': '患*者' }],
  106. 'waitPat': [
  107. { 'patCallNo': '复01', 'patName': '患*者1' },
  108. ],
  109. 'reWaitPat': [
  110. { 'patCallNo': '复01', 'patName': '患*者1' },
  111. ],
  112. }
  113. },
  114. {
  115. 'roomDesc': '诊室5', 'docName': '医生1', 'callMsg':
  116. {
  117. 'callPat': [{ 'patCallNo': '1号', 'patName': '患*者' }],
  118. 'waitPat': [
  119. { 'patCallNo': '复01', 'patName': '患*者1' },
  120. ],
  121. 'reWaitPat': [
  122. { 'patCallNo': '复01', 'patName': '患*者1' },
  123. ],
  124. }
  125. },
  126. {
  127. 'roomDesc': '诊室6', 'docName': '医生1', 'callMsg':
  128. {
  129. 'callPat': [{ 'patCallNo': '1号', 'patName': '患*者' }],
  130. 'waitPat': [
  131. { 'patCallNo': '复01', 'patName': '患*者1' },
  132. ],
  133. 'reWaitPat': [
  134. { 'patCallNo': '复01', 'patName': '患*者1' },
  135. ],
  136. }
  137. },
  138. {
  139. 'roomDesc': '诊室7', 'docName': '医生1', 'callMsg':
  140. {
  141. 'callPat': [{ 'patCallNo': '1号', 'patName': '患*者' }],
  142. 'waitPat': [
  143. { 'patCallNo': '复01', 'patName': '患*者1' },
  144. ],
  145. 'reWaitPat': [
  146. { 'patCallNo': '复01', 'patName': '患*者1' },
  147. ],
  148. }
  149. },
  150. {
  151. 'roomDesc': '诊室8', 'docName': '医生1', 'callMsg':
  152. {
  153. 'callPat': [{ 'patCallNo': '1号', 'patName': '患*者' }],
  154. 'waitPat': [
  155. { 'patCallNo': '复01', 'patName': '患*者1' },
  156. ],
  157. 'reWaitPat': [
  158. { 'patCallNo': '复01', 'patName': '患*者1' },
  159. ],
  160. }
  161. },
  162. {
  163. 'roomDesc': '诊室9', 'docName': '医生1', 'callMsg':
  164. {
  165. 'callPat': [{ 'patCallNo': '1号', 'patName': '患*者' }],
  166. 'waitPat': [
  167. { 'patCallNo': '复01', 'patName': '患*者1' },
  168. ],
  169. 'reWaitPat': [
  170. { 'patCallNo': '复01', 'patName': '患*者1' },
  171. ],
  172. }
  173. },
  174. {
  175. 'roomDesc': '诊室10', 'docName': '医生1', 'callMsg':
  176. {
  177. 'callPat': [{ 'patCallNo': '1号', 'patName': '患*者' }],
  178. 'waitPat': [
  179. { 'patCallNo': '复01', 'patName': '患*者1' },
  180. ],
  181. 'reWaitPat': [
  182. { 'patCallNo': '复01', 'patName': '患*者1' },
  183. ],
  184. }
  185. },
  186. {
  187. 'roomDesc': '诊室11', 'docName': '医生1', 'callMsg':
  188. {
  189. 'callPat': [{ 'patCallNo': '11号', 'patName': '患*者' }],
  190. 'waitPat': [
  191. { 'patCallNo': '1', 'patName': '患*者1' },
  192. { 'patCallNo': '2', 'patName': '患*者2' },
  193. { 'patCallNo': '3', 'patName': '患*者3' },
  194. { 'patCallNo': '4', 'patName': '患*者4' },
  195. { 'patCallNo': '5', 'patName': '患*者5' },
  196. { 'patCallNo': '6', 'patName': '患*者6' },
  197. { 'patCallNo': '7', 'patName': '患*者7' },
  198. { 'patCallNo': '8', 'patName': '患*者8' },
  199. { 'patCallNo': '9', 'patName': '患*者9' },
  200. { 'patCallNo': '10', 'patName': '患*者10' },
  201. { 'patCallNo': '11', 'patName': '患*者11' },
  202. { 'patCallNo': '12', 'patName': '患*者12' }],
  203. 'reWaitPat': [
  204. { 'patCallNo': '复01', 'patName': '患*者1' },
  205. { 'patCallNo': '复02', 'patName': '患*者2' },
  206. { 'patCallNo': '复03', 'patName': '患者3a' },
  207. { 'patCallNo': '复04', 'patName': '患者4a' }],
  208. }
  209. },
  210. {
  211. 'roomDesc': '诊室12', 'docName': '医生1', 'callMsg':
  212. {
  213. 'callPat': [{ 'patCallNo': '1号', 'patName': '患*者' }],
  214. 'waitPat': [
  215. { 'patCallNo': '复01', 'patName': '患*者1' },
  216. ],
  217. 'reWaitPat': [
  218. { 'patCallNo': '复01', 'patName': '患*者1' },
  219. ],
  220. }
  221. },
  222. {
  223. 'roomDesc': '诊室13', 'docName': '医生1', 'callMsg':
  224. {
  225. 'callPat': [{ 'patCallNo': '1号', 'patName': '患*者' }],
  226. 'waitPat': [
  227. { 'patCallNo': '复01', 'patName': '患*者1' },
  228. ],
  229. 'reWaitPat': [
  230. { 'patCallNo': '复01', 'patName': '患*者1' },
  231. ],
  232. }
  233. },
  234. ],
  235. };
  236. }
  237. componentDidMount() {
  238. this.initDevice();
  239. this.initAndroidVoice();
  240. const test = () => {
  241. var start = 0;
  242. setInterval(() => {
  243. const data = this.state.tempList[start];
  244. const patList = [...data.callMsg.callPat, ...data.callMsg.waitPat.map(v => {
  245. return { ...v, status: 'waiting' };
  246. })];
  247. const { roomObj } = this.state;
  248. roomObj[data.roomDesc] = data;
  249. const newArray = Object.keys(roomObj).map(key => {
  250. return roomObj[key];
  251. });
  252. this.setState({
  253. userData: {
  254. ...data?.userData,
  255. areaDesc: data.locDesc, // 大屏诊区
  256. roomDesc: data.roomDesc, // 诊室
  257. },
  258. patList,
  259. waitPat: data.callMsg.waitPat,
  260. reWaitPat: data.callMsg.reWaitPat,
  261. patListArea: newArray,
  262. roomObj,
  263. delayPat: data.delayPat,
  264. });
  265. ++start;
  266. if (start > 13) {
  267. start = 0;
  268. }
  269. this.initVoice('/mp3.wav');
  270. }, 2950);
  271. };
  272. //test();
  273. }
  274. initAndroidVoice() {
  275. window.mediaPlayOver = (flag) => {
  276. if (flag == 'success') {
  277. this.state.voiceList.splice(0, 1);
  278. this.setState({
  279. voiceList: this.state.voiceList,
  280. }, () => {
  281. this.soundPaly();
  282. });
  283. }
  284. };
  285. }
  286. soundPaly() {
  287. if (this.state.voiceList.length > 0) {
  288. this.setState({
  289. myStatus: true,
  290. }, () => {
  291. const ua = navigator.userAgent.toLowerCase();
  292. if (/android/.test(ua)) {
  293. window.JavaClientCall && window.JavaClientCall.mediaFilePlay(this.state.voiceList[0]);
  294. }
  295. });
  296. } else {
  297. this.setState({
  298. myStatus: false
  299. });
  300. }
  301. }
  302. // 音频播放事件
  303. initVoice = (src) => {
  304. const { voiceSrc } = this.state;
  305. voiceSrc.push(src);
  306. this.setState({
  307. voiceSrc,
  308. }, () => {
  309. if (voiceSrc.length == 1) {
  310. playVioce(src);
  311. }
  312. });
  313. const playVioce = (audioSrc) => {
  314. if (this.state.isPlay) {
  315. return;
  316. }
  317. this.setState({
  318. isPlay: true,
  319. }, () => {
  320. const domAudio = document.querySelector('#audio');
  321. domAudio.src = audioSrc;
  322. domAudio.playbackRate = 1;
  323. domAudio.currentTime = 0;
  324. domAudio.load();
  325. domAudio.play();
  326. const mes = () => {
  327. Toast.show({
  328. duration: 10000,
  329. content: '播放完成',
  330. });
  331. const { voiceSrc } = this.state;
  332. voiceSrc.splice(0, 1);
  333. const newArr = voiceSrc;
  334. this.setState({
  335. isPlay: false,
  336. voiceSrc: newArr,
  337. }, () => {
  338. if (newArr.length > 0) {
  339. playVioce(newArr[0]);
  340. }
  341. domAudio.removeEventListener('ended', mes);
  342. });
  343. };
  344. domAudio.addEventListener('ended', mes);
  345. // 10s看是否播放结束
  346. // setTimeout(() => {
  347. // if (this.state.isPlay) {
  348. // mes();
  349. // }
  350. // }, 10000);
  351. });
  352. };
  353. };
  354. initDevice = async () => {
  355. //接收Android端身份证信息函数
  356. window.webGetDeviceId = (deviceId) => {
  357. this.setState({
  358. deviceID: deviceId,
  359. }, () => {
  360. this.loginInit();
  361. });
  362. };
  363. const ua = navigator.userAgent.toLowerCase();
  364. if (/android/.test(ua)) {
  365. window.JavaClientCall && window.JavaClientCall.getDeviceID();
  366. }
  367. // 测试环境无法从安卓获取数据
  368. const isDev = import.meta.env.MODE == 'development';
  369. if (isDev) {
  370. const fp = await FingerprintJS.load();
  371. const AndroidInfo = await fp.get();
  372. this.setState({
  373. deviceID: AndroidInfo.visitorId,
  374. }, () => {
  375. this.loginInit();
  376. });
  377. }
  378. };
  379. // 改变颜色
  380. changeSwitch = () => {
  381. let { colorName } = this.state;
  382. if (!colorName) {
  383. colorName = 'white-bg';
  384. } else if (colorName == 'white-bg') {
  385. colorName = 'dark-bg';
  386. } else {
  387. colorName = '';
  388. }
  389. this.setState({
  390. colorName,
  391. });
  392. localStorage.setItem('ZZJ-color', colorName);
  393. };
  394. openLogin = (cache) => {
  395. if (!cache) {
  396. cache = {
  397. BASE_URL: 'http://10.1.?.29:8090',
  398. Address: '/bdhealth/',
  399. room: '',
  400. use: '',
  401. hospital: '',
  402. };
  403. }
  404. this.setState({
  405. cache,
  406. visibleLogin: true,
  407. });
  408. };
  409. hideLogin = () => {
  410. this.setState({
  411. visibleLogin: false,
  412. });
  413. };
  414. loginInit = async() => {
  415. let cache = localStorage.getItem('ZZJ-base');
  416. if (cache) {
  417. cache = JSON.parse(cache);
  418. }
  419. if (!cache || (cache && !cache.room)) {
  420. this.openLogin(cache);
  421. return;
  422. }
  423. const obj = await this.login(cache);
  424. if (!obj) {
  425. return;
  426. }
  427. obj.deviceID = this.state.deviceID;
  428. initSocket(obj, (data) => {
  429. // console.log('Room接收消息:',data );
  430. data = JSON.parse(data);
  431. if (data.callMsg) {
  432. const patList = [...data.callMsg.callPat, ...data.callMsg.waitPat.map(v => {
  433. return { ...v, status: 'waiting' };
  434. })];
  435. const { roomObj } = this.state;
  436. roomObj[data.roomDesc] = data;
  437. const newArray = Object.keys(roomObj).map(key => {
  438. return roomObj[key];
  439. });
  440. this.setState({
  441. userData: {
  442. ...data?.userData,
  443. areaDesc: data.locDesc, // 大屏诊区
  444. roomDesc: data.roomDesc, // 诊室
  445. },
  446. patList,
  447. waitPat: data.callMsg.waitPat,
  448. reWaitPat: data.callMsg.reWaitPat,
  449. patListArea: newArray,
  450. roomObj,
  451. delayPat: data.delayPat,
  452. });
  453. if (!data.path || !data.voiceFileName) {
  454. return;
  455. }
  456. this.state.voiceList.push(data.path + data.voiceFileName);
  457. this.setState({
  458. voiceList: this.state.voiceList,
  459. }, () => {
  460. if (!this.state.myStatus) {
  461. this.soundPaly();
  462. }
  463. });
  464. // this.initVoice(data.path + data.voiceFileName);
  465. }
  466. });
  467. };
  468. //登录事件
  469. login = async () => {
  470. let cache = localStorage.getItem('ZZJ-base');
  471. if (!cache) {
  472. return;
  473. }
  474. cache = JSON.parse(cache);
  475. return React.$fetchPost('04150020', {
  476. params: [{
  477. ip: cache.BASE_URL,
  478. identifyCode: this.state.deviceID,
  479. }],
  480. }, true).then((data) => {
  481. if (data) {
  482. const obj = {
  483. Loc: 'area',
  484. Room: 'doctor',
  485. OptomeRoom: 'doctor',
  486. OperLoc: 'operate',
  487. };
  488. this.setState({
  489. userData: data?.result[0] || {},
  490. // https://172.16.1.6/images/hoslogo/H02.png 医院logo
  491. hosLogo: `/images/hoslogo/${data?.result[0]?.hospCode}.png`
  492. });
  493. if (obj[data.code]) {
  494. this.setState({
  495. showType: obj[data.code], // Loc医生诊室 Room,OptomeRoom大屏 OperLoc 手术室
  496. });
  497. if (obj[data.code] == 'doctor') {
  498. document.querySelector('html').className = '';
  499. } else {
  500. document.querySelector('html').className = 'big';
  501. }
  502. return data?.result[0] || null;
  503. } else {
  504. this.openLogin();
  505. return null;
  506. }
  507. }
  508. });
  509. };
  510. render () {
  511. return (
  512. <>
  513. <div className={ this.state.colorName}>
  514. {/* 设备信息配置,选择医院 */}
  515. <Login
  516. visibleLogin={this.state.visibleLogin}
  517. formData={this.state.cache}
  518. hideLogin={this.hideLogin}
  519. loginInit={this.loginInit}
  520. deviceID={this.state.deviceID}
  521. />
  522. {/* 医生诊室呼叫 */}
  523. {this.state.showType == 'doctor'
  524. ? <DoctorScreen
  525. userData={this.state.userData}
  526. patList={this.state.patList}
  527. reWaitPat={this.state.reWaitPat}
  528. hosLogo={this.state.hosLogo}
  529. />
  530. : this.state.showType == 'operate'
  531. ? <OperateScreen
  532. patList={this.state.waitPat}
  533. userData={this.state.userData}
  534. hosLogo={this.state.hosLogo}
  535. />
  536. : < BigScreen
  537. userData={this.state.userData}
  538. patListArea={this.state.patListArea}
  539. delayPat={this.state.delayPat}
  540. hosLogo={this.state.hosLogo}
  541. />
  542. }
  543. </div>
  544. <span
  545. className='bottom-set'
  546. >
  547. <AntOutline
  548. style={{color: this.state.colorName == 'dark-bg' ? '#fff' : '#0D2764', marginLeft: '10px'}}
  549. onClick={this.changeSwitch}
  550. />
  551. <SetOutline
  552. onClick={this.openLogin}
  553. style={{color: this.state.colorName == 'dark-bg' ? '#fff' : '#0D2764', marginLeft: '10px'}}
  554. />
  555. </span>
  556. <audio controls id="audio"
  557. style={{ position: 'fixed', left: '-1000px', top: '100px' }}
  558. ></audio>
  559. </>
  560. );
  561. }
  562. }
  563. export default Home;