scan.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646
  1. <template>
  2. <view class="content">
  3. <view class="info">
  4. <view class="header">
  5. <view class="center" :class="list.length < infoData.specimenNum?'par-top1':'par-top2'">
  6. <view class="sign red">{{specimenNum}}/{{list.length}}</view>
  7. </view>
  8. <view class="tip" v-if="list.length < infoData.specimenNum">请继续扫描标本!</view>
  9. <view class="title">申请单共有<span class="red">{{totalNum}}</span>份,已固定<span class="red">{{fixationNum}}</span>份还需固定<span class="red">{{specimenNum}}</span>份</view>
  10. </view>
  11. <view>
  12. <view class="list" v-for="(item, index) in list" :key="index">
  13. <view class="df-list">
  14. <view class="list-title">标本名称:</view>
  15. <view class="no-center">{{item.specimenName}}</view>
  16. </view>
  17. <view class="df-list">
  18. <view class="list-title">条码号:</view>
  19. <view class="no-center">{{item.specimenCode}}</view>
  20. </view>
  21. </view>
  22. </view>
  23. <view class="list list-top" v-if="infoData">
  24. <view class="df-list">
  25. <view class="list-title">患者姓名:</view>
  26. <view class="no-center">{{infoData.patientName}}({{infoData.patientDTO.bedNum}}床)</view>
  27. </view>
  28. <view class="df-list">
  29. <view class="list-title">住院号:</view>
  30. <view class="no-center">{{infoData.patientDTO.patientCode}}</view>
  31. </view>
  32. <view class="df-list">
  33. <view class="list-title">科室名称:</view>
  34. <view class="no-center">{{infoData.patientDTO.department.dept}}</view>
  35. </view>
  36. <view class="df-list">
  37. <view class="list-title">申请单号:</view>
  38. <view class="no-center">{{infoData.applyCode}}</view>
  39. </view>
  40. </view>
  41. </view>
  42. <!-- <view class="btn-view" v-if="list.length < infoData.specimenNum">
  43. <button class="back-btn" @click="back">返回</button>
  44. </view> -->
  45. <view class="btn-view df-sb">
  46. <button class="back-btn2" @click="back">返回</button>
  47. <button class="back-btn3" @click="fixation">标本固定存放</button>
  48. </view>
  49. <!-- PDA扫描 -->
  50. <scanner></scanner>
  51. <!-- 标本固定 -->
  52. <uni-popup ref="popup" type="dialog" background-color="#fff" :mask-click="false">
  53. <view class="pop-content">
  54. <view class="pop-title">提示</view>
  55. <view class="pop-tip">您标本已扫描完成,请填写固定信息。</view>
  56. <uni-forms ref="baseForm" :model="form" label-width="110px">
  57. <uni-forms-item label="工号" required>
  58. <uni-easyinput v-model="form.code" :clearable="false" @input="inputChange" primaryColor='#49b856' placeholder="请输入工号" />
  59. </uni-forms-item>
  60. <uni-forms-item label="姓名" required>
  61. <view class="text-left">{{form.name}}</view>
  62. </uni-forms-item>
  63. <uni-forms-item label="固定液类型" required class="select">
  64. <uni-data-picker placeholder="请选择固定液类型" :clear-icon="false" :localdata="fixedData" v-model="form.fixative"
  65. :map="{text:'name',value:'id'}">
  66. </uni-data-picker>
  67. </uni-forms-item>
  68. <uni-forms-item label="固定时间" required class="time">
  69. <uni-datetime-picker type="datetime" :clear-icon="false" placeholder="请选择固定时间" v-model="form.fixationTime"/>
  70. </uni-forms-item>
  71. </uni-forms>
  72. <view class="pou-btn">
  73. <view class="btn border-right" @click="fixationClose">取消</view>
  74. <view class="btn confirm" @click="dialogConfirm">固定标本</view>
  75. </view>
  76. </view>
  77. </uni-popup>
  78. </view>
  79. </template>
  80. <script>
  81. import {
  82. get,
  83. post
  84. } from "../../http/http.js";
  85. import scanner from "../../components/scanner/scanner.vue";
  86. export default {
  87. data(){
  88. return{
  89. infoData:null,
  90. list:[],
  91. SMFlag:true,
  92. fixationModal:false,
  93. fixedData:[],
  94. styles:{
  95. borderColor: '#49b856',
  96. },
  97. userInfo:uni.getStorageSync('userData').user,
  98. hosId: uni.getStorageSync('userData').user.currentHospital.id,
  99. form:{
  100. name:'',
  101. code:'',
  102. fixationTime:'',
  103. fixative:'',
  104. handoverUserId:''
  105. },
  106. pathologyFormId:null,
  107. fixationNum:null,
  108. specimenNum:null,
  109. totalNum:null,
  110. }
  111. },
  112. components: {
  113. scanner
  114. },
  115. methods:{
  116. // 时间格式化
  117. yyTimeFilter(timestamp) {
  118. var date = new Date(timestamp); // 时间戳为毫秒级别
  119. var year = date.getFullYear();
  120. var month = date.getMonth() + 1;
  121. var day = date.getDate();
  122. var hours = date.getHours();
  123. var minutes = date.getMinutes();
  124. var seconds = date.getSeconds();
  125. // 格式化月份、日期、小时、分钟、秒
  126. month = month < 10 ? '0' + month : month;
  127. day = day < 10 ? '0' + day : day;
  128. hours = hours < 10 ? '0' + hours : hours;
  129. minutes = minutes < 10 ? '0' + minutes : minutes;
  130. seconds = seconds < 10 ? '0' + seconds : seconds;
  131. return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
  132. },
  133. inputChange(e){
  134. console.log(e)
  135. if(e.length < 3) {
  136. return
  137. }
  138. let query = {
  139. account: e
  140. };
  141. post('/data/isRepeat',query).then((data) => {
  142. if(data.status==200){
  143. this.form.name = data.userName;
  144. this.form.handoverUserId = data.userId
  145. }else{
  146. this.form.name = '';
  147. this.form.handoverUserId =null
  148. }
  149. });
  150. },
  151. back(){
  152. // this.padChange('86386627710976\n')
  153. this.cancelSpecimenModal()
  154. uni.setStorageSync('pathologyFormId', null)
  155. uni.navigateTo({
  156. url: `/pages/specimenPort/specimenPort?backType=detail`
  157. });
  158. },
  159. // 标本重置
  160. cancelSpecimenModal(){
  161. let ids = []
  162. for(let i of this.list){
  163. ids.push(i.id)
  164. }
  165. let data = {
  166. pathologySpecimenIds:ids.join(',')
  167. }
  168. post('/pathology/cancel', data).then((res) => {
  169. });
  170. },
  171. // 标本固定
  172. fixation(){
  173. this.form={
  174. name:'',
  175. code:'',
  176. fixationTime: Date.now() - 2*24*1000,
  177. fixative:this.fixedData[0].id,
  178. handoverUserId:''
  179. }
  180. // this.form.fixationTime = Date.now() - 2*24*1000
  181. this.$refs.popup.open()
  182. },
  183. // 获取固定液类型
  184. getFixation(){
  185. post('/common/common/getDictionary', {
  186. key: "fixing_liquid_type",
  187. type: "list"
  188. }).then((res) => {
  189. this.fixedData = res
  190. });
  191. },
  192. fixationClose(){
  193. this.$refs.popup.close()
  194. },
  195. // 确定固定标本
  196. dialogConfirm(){
  197. if(!this.form.code){
  198. uni.showToast({
  199. title: '工号不能为空',
  200. duration: 1000,
  201. icon:'none'
  202. });
  203. return
  204. }
  205. if(!this.form.name){
  206. uni.showToast({
  207. title: '姓名不能为空',
  208. duration: 1000,
  209. icon:'none'
  210. });
  211. return
  212. }
  213. if(!this.form.fixative){
  214. uni.showToast({
  215. title: '固定液类型不能为空',
  216. duration: 1000,
  217. icon:'none'
  218. });
  219. return
  220. }
  221. if(!this.form.fixationTime){
  222. uni.showToast({
  223. title: '固定时间不能为空',
  224. duration: 1000,
  225. icon:'none'
  226. });
  227. return
  228. }
  229. let time = null
  230. if(Number.isInteger(this.form.fixationTime) && this.form.fixationTime > 0){
  231. time = this.yyTimeFilter(this.form.fixationTime)
  232. }else{
  233. time = this.form.fixationTime
  234. }
  235. let str = this.list.map(i=>{
  236. return i.specimenCode
  237. })
  238. uni.showLoading({
  239. title: "加载中",
  240. mask: true,
  241. });
  242. let query={
  243. hosId:this.hosId,
  244. id:this.infoData.id,
  245. specimenFixingLiquid:{
  246. id:this.form.fixative
  247. },
  248. specimenCodes:str.join(','),
  249. handoverUserId:this.form.handoverUserId,
  250. fixationTime:time,
  251. specimenDeptId:this.userInfo.dept.id,
  252. operationType:'pda'
  253. }
  254. post('/simple/data/addData/pathologyForm',query).then((res) => {
  255. uni.hideLoading();
  256. this.$refs.popup.close()
  257. uni.showToast({
  258. title: '固定成功',
  259. duration: 1000
  260. });
  261. setTimeout(_=>{
  262. this.back()
  263. },1000)
  264. });
  265. },
  266. // PDA扫描
  267. padChange(scannerCode){
  268. scannerCode = scannerCode.replace('\n','')
  269. if (!this.SMFlag) {
  270. return;
  271. }
  272. this.SMFlag = false;
  273. uni.showLoading({
  274. title: "加载中",
  275. mask: true,
  276. });
  277. this.pathologyFormId = uni.getStorageSync('pathologyFormId');
  278. let query={
  279. barcode:scannerCode,
  280. pathologyFormId:this.pathologyFormId,
  281. platform:"app"
  282. }
  283. if(!this.pathologyFormId){
  284. delete query.pathologyFormId
  285. }
  286. post("/pathology/scanCode", query).then((res) => {
  287. this.SMFlag = true
  288. uni.hideLoading();
  289. if(res.status==200){
  290. let data = res.data[0]
  291. let item = null
  292. let str = null
  293. if(scannerCode.indexOf(':')!=-1){
  294. str = scannerCode.split(':')
  295. item = data.pathologySpecimenDTOList.find(i=>i.specimenCode == str[1])
  296. }else{
  297. item = data.pathologySpecimenDTOList.find(i=>i.specimenCode == scannerCode)
  298. }
  299. // let item = data.pathologySpecimenDTOList.find(i=>i.specimenCode == scannerCode)
  300. uni.setStorageSync('pathologyFormId', data.id);
  301. if(!item.fixationTime && data.pathologyFormType==0){
  302. if(data.status.value==2 || data.status.value==3 ||
  303. data.status.value==4){
  304. uni.navigateTo({
  305. url: `/pages/specimenPort/scan?data=${JSON.stringify(data)}&type=${res.type}`
  306. });
  307. }else{
  308. uni.showToast({
  309. title: '查询到标本申请单信息',
  310. duration: 1000,
  311. icon:'none'
  312. });
  313. setTimeout(_=>{
  314. uni.navigateTo({
  315. url: `/pages/specimenPort/detail?detailId=${data.id}`
  316. });
  317. },800)
  318. }
  319. }else if(item.fixationTime && data.pathologyFormType==0){
  320. uni.showToast({
  321. title: '查询到标本申请单信息',
  322. duration: 1000,
  323. icon:'none'
  324. });
  325. setTimeout(_=>{
  326. uni.navigateTo({
  327. url: `/pages/specimenPort/detail?detailId=${data.id}`
  328. });
  329. },800)
  330. }else{
  331. uni.showToast({
  332. title: '该申请单类型不是病理检查申请单',
  333. duration: 1000,
  334. icon:'none'
  335. });
  336. }
  337. }else{
  338. uni.showModal({
  339. title: "提示",
  340. content: `${res.msg} \n 扫描内容:${scannerCode}`,
  341. confirmColor:'#49b856',
  342. success: (res) => {
  343. if (res.confirm) {
  344. console.log("用户点击确定");
  345. } else if (res.cancel) {
  346. console.log("用户点击取消");
  347. }
  348. },
  349. });
  350. }
  351. })
  352. },
  353. getSpecimenNum(){
  354. post(`/pathology/check/pathologyForm/${this.infoData.id}`, {
  355. operationType:'fixation'
  356. }).then(res=>{
  357. this.fixationNum = res.fixationNum
  358. this.specimenNum = res.specimenNum
  359. this.totalNum = res.totalNum
  360. })
  361. }
  362. },
  363. onBackPress(e) {
  364. // backbutton:物理按键返回
  365. if (e.from === 'backbutton') {
  366. this.back()
  367. return true
  368. }
  369. },
  370. onShow() {
  371. let that = this
  372. // #ifdef APP-PLUS
  373. uni.$off('scan') // 每次进来先 移除全局自定义事件监听器
  374. uni.$on('scan', function(data) {
  375. that.padChange(data)
  376. })
  377. // #endif
  378. },
  379. onLoad(option){
  380. let data = JSON.parse(option.data)
  381. this.infoData = data
  382. this.getSpecimenNum()
  383. this.type = option.type
  384. this.list = data.pathologySpecimenDTOList?data.pathologySpecimenDTOList:[]
  385. // if(this.list.length == this.infoData.specimenNum){
  386. // uni.showToast({
  387. // title: '您标本已扫描完成,请填写固定信息',
  388. // duration: 2000,
  389. // icon:'none'
  390. // });
  391. // }
  392. this.getFixation()
  393. }
  394. }
  395. </script>
  396. <style scoped>
  397. >>> .uni-forms-item__content{
  398. display: flex;
  399. align-items: center;
  400. }
  401. >>>.uni-easyinput__content-input,
  402. >>>.uni-input-wrapper,
  403. >>>.uni-input-placeholder{
  404. display: flex;
  405. align-items: center;
  406. line-height: 1;
  407. height: 35px;
  408. }
  409. .select >>>.dialog-close{
  410. /* display: flex !important; */
  411. }
  412. .select >>>.dialog-close-plus{
  413. }
  414. .select >>>.dialog-close-rotate{
  415. top: 20.8px;
  416. left: 14px;
  417. }
  418. .time >>>.dialog-close-rotate{
  419. top: 24px;
  420. left: 24.5px;
  421. }
  422. </style>
  423. <style lang="less" scoped>
  424. page {
  425. background: #F8F8F8;
  426. }
  427. .red{
  428. color: red;
  429. }
  430. .content {
  431. .header {
  432. width: 100%;
  433. height: 450rpx;
  434. text-align: center;
  435. .center{
  436. .sign{
  437. font-size: 70rpx;
  438. font-weight: bold;
  439. }
  440. }
  441. .title{
  442. font-weight: 500;
  443. font-size: 34rpx;
  444. padding: 0 20rpx;
  445. }
  446. .par-top1{
  447. padding-top: 100rpx;
  448. }
  449. .par-top2{
  450. padding-top: 150rpx;
  451. }
  452. .tip{
  453. font-size: 30rpx;
  454. font-weight: bold;
  455. padding: 40rpx 0;
  456. }
  457. }
  458. .info{
  459. // padding: 0 20rpx;
  460. // background: #fff;
  461. height: calc(100vh - 120rpx);
  462. overflow-y: auto;
  463. background: #F8F8F8;
  464. .info-list{
  465. padding: 14rpx 0;
  466. display: flex;
  467. font-size: 28rpx;
  468. color: #555555;
  469. .info-title{
  470. color: #000;
  471. }
  472. .info-content{
  473. flex: 1;
  474. }
  475. }
  476. }
  477. .height-list {
  478. height: 44px;
  479. }
  480. .list {
  481. background: #fff;
  482. border-bottom: 1px solid #D2D2D2;
  483. .df-list {
  484. display: flex;
  485. align-items: center;
  486. padding: 14rpx 20rpx;
  487. font-size: 28rpx;
  488. color: #555555;
  489. .no-center{
  490. align-items: baseline;
  491. line-height: 1;
  492. }
  493. .list-title{
  494. color: #000;
  495. line-height: 1;
  496. }
  497. }
  498. }
  499. .list-top{
  500. margin-top: 20rpx;
  501. }
  502. .info-log{
  503. background: #fff;
  504. height: calc(100vh - 80rpx);
  505. }
  506. .df {
  507. display: flex;
  508. height: 80rpx;
  509. align-items: center;
  510. padding: 0 20rpx;
  511. border-bottom: 1px solid #D2D2D2;
  512. }
  513. .execFilterMask{
  514. .execFilter{
  515. position: relative;
  516. background-color: #fff;
  517. height: calc(100vh - 80rpx);
  518. .execFilterHeader{
  519. height: 70rpx;
  520. display: flex;
  521. justify-content: center;
  522. align-items: center;
  523. border-bottom: 2rpx solid #ccc;
  524. }
  525. .execFilterBody{
  526. .execFilterItem{
  527. padding: 32rpx;
  528. border-bottom: 2rpx dashed #ccc;
  529. &:last-of-type{
  530. border-bottom: none;
  531. }
  532. .execFilterItemHeader{}
  533. .execFilterItemBody{
  534. display: flex;
  535. flex-wrap: wrap;
  536. padding: 32rpx 0 0;
  537. justify-content: space-between;
  538. text-align: left;
  539. .execFilterItemBox{
  540. width: 200rpx;
  541. height: 80rpx;
  542. text-align: center;
  543. line-height: 80rpx;
  544. background-color: #f6f6f6;
  545. margin-bottom: 20rpx;
  546. &.active{
  547. color: #fff;
  548. background-color: #49b856;
  549. }
  550. }
  551. .deptName {
  552. height: 80rpx;
  553. background-color: #f6f6f6;
  554. padding: 0 20rpx;
  555. width: 100%;
  556. }
  557. }
  558. }
  559. }
  560. }
  561. }
  562. .btn-view{
  563. width: 100%;
  564. bottom: 20rpx;
  565. position: fixed;
  566. .back-btn{
  567. background: #49B856;
  568. border-radius: 10rpx;
  569. color: #fff;
  570. font-size: 30rpx;
  571. text-align: center;
  572. line-height: 80rpx;
  573. width: 95%;
  574. }
  575. .back-btn2{
  576. background: #8F939C;
  577. border-radius: 10rpx;
  578. color: #fff;
  579. font-size: 30rpx;
  580. text-align: center;
  581. line-height: 80rpx;
  582. width: 45%;
  583. }
  584. .back-btn3{
  585. background: #49B856;
  586. border-radius: 10rpx;
  587. color: #fff;
  588. font-size: 30rpx;
  589. text-align: center;
  590. line-height: 80rpx;
  591. width: 45%;
  592. }
  593. }
  594. .df-sb{
  595. display: flex;
  596. justify-content: space-between;
  597. }
  598. .pop-content{
  599. text-align: center;
  600. .pop-title{
  601. font-size: 32rpx;
  602. color: #000;
  603. margin-top: 20rpx;
  604. }
  605. .pop-tip{
  606. font-size: 28rpx;
  607. color: #6C6C6C;
  608. margin-top: 10rpx;
  609. }
  610. .uni-forms{
  611. padding: 20rpx 20rpx 0 20rpx;
  612. }
  613. .text-left{
  614. text-align: left;
  615. }
  616. .pou-btn{
  617. color: #000;
  618. font-size: 30rpx;
  619. border-top: 1px solid #E3E3E3;
  620. display: flex;
  621. padding: 0 20rpx;
  622. .btn{
  623. text-align: center;
  624. line-height: 80rpx;
  625. width: 50%;
  626. }
  627. }
  628. .border-right{
  629. border-right: 1px solid #E3E3E3;
  630. }
  631. .confirm{
  632. color: #49B856 !important;
  633. }
  634. }
  635. }
  636. </style>