patientList.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  1. <template>
  2. <view class="patientList">
  3. <view class="search-box">
  4. <seiminSearch class="mSearch-input-box" :mode="2" button="inside" placeholder="输入床号或姓名支持拼音检索" @input="debounceInp"
  5. v-model="keyword"></seiminSearch>
  6. </view>
  7. <view class="search-keyword">
  8. <view class="orderList_listItem" v-for="patient in patientList" :key="patient.id">
  9. <view class="orderList_listItem_header">
  10. <view class="orderList_listItem_header_title">
  11. <block v-if="patient.illnessState">
  12. <view class="associationType_icon red" v-if="patient.illnessState.value === '2'">危</view>
  13. <view class="associationType_icon red" v-else-if="patient.illnessState.value === '3'">重</view>
  14. </block>
  15. <block v-if="patient.careLevel">
  16. <view class="associationType_icon red" v-if="patient.careLevel.value === '0'">特</view>
  17. <view class="associationType_icon red" v-else-if="patient.careLevel.value === '1'">1</view>
  18. <view class="associationType_icon green" v-else-if="patient.careLevel.value === '2'">2</view>
  19. <view class="associationType_icon green" v-else-if="patient.careLevel.value === '3'">3</view>
  20. </block>
  21. <view class="taskNameAndWorkerName">
  22. <text class="workerName">{{patient.patientName || '暂无'}}</text>
  23. </view>
  24. </view>
  25. <text class="orderList_listItem_header_more">{{patient.bedNum }}床</text>
  26. </view>
  27. <view class="orderList_listItem_item">
  28. <view class="orderList_listItem_item_content">
  29. <text class="orderList_listItem_item_name">{{patient.residenceNo || '暂无'}}</text>
  30. <text class="orderList_listItem_item_time">待检{{patient.watingCount}}</text>
  31. </view>
  32. <view class="orderList_listItem_item_btns">
  33. <button type="primary" class="btn"
  34. @click.stop="toDetail(patient.patientCode,patient.patientName)">患者详情</button>
  35. <button type="primary" class="btn" @click.stop="buildOrder(patient)">一键建单</button>
  36. </view>
  37. </view>
  38. </view>
  39. </view>
  40. <seiminFooterNav></seiminFooterNav>
  41. <seiminModel ref="seiminModel"></seiminModel>
  42. <seiminPicker ref="sPicker" :title="pickerTitle" titleColor="#808080" titleFontSize="28rpx" confirmColor="#333"
  43. confirmFontSize="38rpx" confirmFontWeight="500" itemFontSize="32rpx" @onClose="closePicker"
  44. @onConfirm="confirmPicker" :pickerList="taskTypeList">
  45. </seiminPicker>
  46. </view>
  47. </template>
  48. <script>
  49. import {
  50. backPress,
  51. } from '../../utils/index.js';
  52. import {
  53. debounce
  54. } from 'lodash/function';
  55. import {
  56. reqFetchDataList,
  57. reqDeptTSPTaskType,
  58. reqBuildTrip,
  59. } from "../../request/api.js";
  60. import {
  61. mapState,
  62. mapMutations,
  63. } from "vuex";
  64. import {
  65. ASSOCIATION_TYPES
  66. } from '../../utils/enum.association_types.js';
  67. export default {
  68. onBackPress() {
  69. backPress();
  70. },
  71. data() {
  72. return {
  73. reFresh: '',
  74. ASSOCIATION_TYPES,
  75. checkedShowMsg: {}, //当前选中的任务类型的buildtrip信息
  76. selectedPatient: {}, //当前选中的患者
  77. taskTypeListResource: [], //任务类型列表(请求的原始数据)
  78. taskTypeList: [], //任务类型列表
  79. pickerTitle: "", //一键建单picker的title
  80. debounceInp: null,
  81. keyword: "",
  82. patientList: [],
  83. totalNum: 0, //工单总数量
  84. idx: 0, //页码
  85. };
  86. },
  87. computed: {
  88. ...mapState("login", ["loginInfo"]),
  89. ...mapState('other', ["deptDisplay"]),
  90. },
  91. methods: {
  92. ...mapMutations('other', ['changeQucikCreateOrderType', 'clearPatientBuildData', 'changePatientBuildData']),
  93. //关闭
  94. closePicker() {
  95. this.$refs.sPicker._close();
  96. },
  97. //打开
  98. openPicker() {
  99. this.$refs.sPicker._open();
  100. },
  101. //确定:接收子组件传来的参数
  102. confirmPicker(checkedObj) {
  103. console.log(checkedObj);
  104. // 补充:清除建单数据
  105. this.clearPatientBuildData();
  106. // 2,获取buildTrip信息
  107. let postData = {
  108. "taskTypeId": checkedObj.value,
  109. "patientCode": this.selectedPatient.patientCode
  110. };
  111. uni.showLoading({
  112. mask: true,
  113. title: '加载中'
  114. })
  115. reqBuildTrip(postData).then(res => {
  116. uni.hideLoading();
  117. let taskType = this.taskTypeListResource.find(v => v.id == checkedObj.value);
  118. let patientTaskType = taskType || {};
  119. if (patientTaskType.associationType.value == this.ASSOCIATION_TYPES['患者其他服务业务']) {
  120. // 患者其他服务业务--无法用status判断,运输过程“默认患者所在科室”没有返回status==200,估计是后端漏掉了这种情况,如果后期后端可以返回status,则可以根据status判断。
  121. if (res.start && res.end) {
  122. if (res.status == 100013 || res.status == 100014 || res.status == 100015) {
  123. this.checkedShowMsg = res.data;
  124. //需要选择起点科室和目标科室
  125. this.changeQucikCreateOrderType({
  126. type: "patient",
  127. taskTypeId: checkedObj.value,
  128. patientTaskType,
  129. selectedPatient: this.selectedPatient,
  130. patientBuildTrip: res,
  131. });
  132. uni.navigateTo({
  133. url: "/pages/quickCreateOrder/quickCreateOrder",
  134. });
  135. } else {
  136. //无需选择科室
  137. this.checkedShowMsg = res.data;
  138. this.changePatientBuildData({
  139. key: 'dept',
  140. value: {
  141. startDept: res.start.start.list[0],
  142. endDept: res.end.end.list[0],
  143. }
  144. });
  145. this.changeQucikCreateOrderType({
  146. type: "patient",
  147. taskTypeId: checkedObj.value,
  148. patientTaskType,
  149. selectedPatient: this.selectedPatient,
  150. patientBuildTrip: res,
  151. });
  152. uni.navigateTo({
  153. url: "/pages/patientBuild/patientBuild",
  154. });
  155. }
  156. } else {
  157. this.$refs.seiminModel.show({
  158. skin: "toast",
  159. icon: "error",
  160. content: res.msg || "获取数据失败",
  161. });
  162. throw new Error(res.msg || '获取数据失败');
  163. }
  164. } else if (patientTaskType.associationType.value == this.ASSOCIATION_TYPES['患者陪检业务']) {
  165. // 患者陪检业务
  166. if (res.status == 200) {
  167. this.checkedShowMsg = res.data;
  168. this.changePatientBuildData({
  169. key: 'dept',
  170. value: {
  171. startDept: {
  172. id: res.startDept,
  173. dept: res.startDeptName,
  174. deptalias: res.startDeptAlias
  175. }, //待改
  176. endDept: {
  177. id: res.startDept,
  178. dept: res.startDeptName,
  179. deptalias: res.startDeptAlias
  180. }, //待改
  181. }
  182. });
  183. this.changeQucikCreateOrderType({
  184. type: "patient",
  185. taskTypeId: checkedObj.value,
  186. patientTaskType,
  187. selectedPatient: this.selectedPatient,
  188. patientBuildTrip: res,
  189. });
  190. uni.navigateTo({
  191. url: "/pages/appointmentInspect/appointmentInspect",
  192. });
  193. } else {
  194. this.$refs.seiminModel.show({
  195. skin: "toast",
  196. icon: "error",
  197. content: res.msg || "获取数据失败",
  198. });
  199. throw new Error(res.msg || '获取数据失败');
  200. }
  201. }
  202. })
  203. },
  204. // 一键建单
  205. buildOrder(patient) {
  206. this.selectedPatient = patient;
  207. // 1,请求任务类型列表
  208. uni.showLoading({
  209. mask: true,
  210. title: '加载中'
  211. })
  212. reqDeptTSPTaskType().then(res => {
  213. uni.hideLoading();
  214. if (res.status == 200) {
  215. res.data = res.data || [];
  216. this.taskTypeListResource = res.data;
  217. this.taskTypeList = res.data.map((v) => ({
  218. value: v.id,
  219. label: v.taskName,
  220. }));
  221. this.pickerTitle = `您选择了<b class="green">${patient.patientName}</b>患者,请选择下方具体服务项`;
  222. this.openPicker();
  223. } else {
  224. this.$refs.seiminModel.show({
  225. skin: "toast",
  226. icon: "error",
  227. content: res.msg || "获取数据失败",
  228. });
  229. throw new Error(res.msg || "获取数据失败");
  230. }
  231. })
  232. },
  233. // 跳转患者详情
  234. toDetail(patientCode, patientName) {
  235. uni.navigateTo({
  236. url: `/pages/patientDetail/patientDetail?patientCode=${patientCode}&patientName=${patientName}`
  237. })
  238. },
  239. //监听输入
  240. inputChange(event = '', idxPlus = false) {
  241. let keyWord = event.detail ? event.detail.value : event;
  242. if (idxPlus) {
  243. //累加
  244. ++this.idx;
  245. } else {
  246. this.idx = 0;
  247. }
  248. let postData = {
  249. "idx": this.idx,
  250. "sum": 9999,
  251. "patient": {
  252. keyWord,
  253. parentIdOnly: true,
  254. "department": {
  255. "id": this.loginInfo.user.dept.id
  256. }
  257. }
  258. };
  259. uni.showLoading({
  260. title: "加载中",
  261. });
  262. reqFetchDataList("nurse", "patient", postData).then((res) => {
  263. uni.hideLoading();
  264. uni.stopPullDownRefresh();
  265. if (res.status == 200) {
  266. res.list = res.list || [];
  267. if (idxPlus) {
  268. //累加
  269. this.patientList = this.patientList.concat(res.list);
  270. } else {
  271. this.patientList = res.list;
  272. }
  273. this.totalNum = res.totalNum || 0;
  274. } else {
  275. this.$refs.seiminModel.show({
  276. skin: "toast",
  277. icon: "error",
  278. content: res.msg || "获取数据失败",
  279. });
  280. throw new Error(res.msg || "获取数据失败");
  281. }
  282. });
  283. },
  284. // 查询最新列表(上拉)
  285. reachBottom() {
  286. //没有更多
  287. if (this.patientList.length == this.totalNum) {
  288. uni.showToast({
  289. icon: 'none',
  290. title: '没有更多数据了'
  291. })
  292. return;
  293. }
  294. this.inputChange(this.keyword, true);
  295. },
  296. },
  297. onReachBottom() {
  298. this.reachBottom();
  299. },
  300. onPullDownRefresh() {
  301. this.inputChange(this.keyword)
  302. },
  303. created() {
  304. this.debounceInp = debounce(this.inputChange, 500);
  305. },
  306. beforeDestroy() {
  307. this.debounceInp.cancel()
  308. },
  309. onLoad() {
  310. this.inputChange();
  311. },
  312. };
  313. </script>
  314. <style lang="scss" scoped>
  315. .patientList {
  316. padding-bottom: 108rpx;
  317. .search-box {
  318. background-color: rgb(242, 242, 242);
  319. padding: 15rpx 2.5%;
  320. position: fixed;
  321. z-index: 99;
  322. width: 100%;
  323. @include flex(space-between);
  324. .mSearch-input-box {
  325. width: 100%;
  326. }
  327. .input-box {
  328. width: 85%;
  329. flex-shrink: 1;
  330. @include flex(center, center);
  331. &>input {
  332. width: 100%;
  333. height: 60rpx;
  334. font-size: 32rpx;
  335. border: 0;
  336. border-radius: 60rpx;
  337. appearance: none;
  338. padding: 0 3%;
  339. margin: 0;
  340. background-color: #ffffff;
  341. }
  342. }
  343. .search-btn {
  344. width: 15%;
  345. margin: 0 0 0 2%;
  346. flex-shrink: 0;
  347. font-size: 28rpx;
  348. color: #fff;
  349. background: linear-gradient(to right, #ff9801, #ff570a);
  350. border-radius: 60rpx;
  351. @include flex(center, center);
  352. }
  353. }
  354. .search-keyword {
  355. padding: 88rpx 24rpx 0;
  356. // 列表项
  357. .orderList_listItem {
  358. width: 702rpx;
  359. min-height: 320rpx;
  360. background-color: #fff;
  361. position: relative;
  362. margin-top: 8rpx;
  363. border-radius: 8rpx;
  364. padding: 0 24rpx;
  365. font-size: 32rpx;
  366. @include border;
  367. @include semicircle(#F9FAFB, 82rpx);
  368. @include flex(flex-start, stretch, column);
  369. .orderList_listItem_header {
  370. height: 86rpx;
  371. @include border($directive:bottom, $style:dashed);
  372. @include flex(space-between, center);
  373. .orderList_listItem_header_title {
  374. color: #333;
  375. flex: 1;
  376. @include flex(flex-start, center);
  377. .associationType_icon {
  378. width: 48rpx;
  379. height: 48rpx;
  380. border-radius: 50%;
  381. font-size: 24rpx;
  382. margin-right: 8rpx;
  383. @include border($color:#39b199);
  384. @include flex(center, center);
  385. &.green {
  386. color: $defaultColor;
  387. border: 1px solid $defaultColor;
  388. background-color: rgba(73, 184, 86, 0.1);
  389. }
  390. &.red {
  391. color: #FF3B53;
  392. border: 1px solid #FF3B53;
  393. background-color: #FFE8EB;
  394. }
  395. }
  396. .taskNameAndWorkerName {
  397. flex: 1;
  398. @include flex;
  399. .taskName {
  400. max-width: 10em;
  401. @include clamp;
  402. }
  403. .workerName {
  404. flex: 1;
  405. @include clamp;
  406. }
  407. }
  408. }
  409. .orderList_listItem_header_more {
  410. color: #333;
  411. font-weight: bold;
  412. @include clamp;
  413. }
  414. }
  415. .orderList_listItem_item {
  416. height: 88rpx;
  417. color: #333;
  418. font-size: 30rpx;
  419. flex: 1;
  420. @include border(bottom);
  421. @include flex(flex-start, stretch, column);
  422. &:last-of-type {
  423. border-bottom: none;
  424. }
  425. .orderList_listItem_item_content {
  426. min-height: 143rpx;
  427. flex: 1;
  428. @include flex(space-between, center);
  429. .orderList_listItem_item_name {
  430. font-size: 34rpx;
  431. }
  432. .orderList_listItem_item_time {
  433. color: #333;
  434. font-size: 34rpx;
  435. font-weight: bold;
  436. }
  437. }
  438. .orderList_listItem_item_btns {
  439. position: relative;
  440. left: -24rpx;
  441. width: 698rpx;
  442. height: 88rpx;
  443. @include btn_background;
  444. @include flex;
  445. .btn {
  446. flex: 1;
  447. background-color: transparent;
  448. position: relative;
  449. @include flex(center, center);
  450. &::before {
  451. content: '';
  452. position: absolute;
  453. right: 0;
  454. top: 0;
  455. width: 1px;
  456. height: 100%;
  457. @include border(right, #fff);
  458. }
  459. &:last-of-type::before {
  460. border-right: none;
  461. }
  462. &::after {
  463. border: none;
  464. }
  465. }
  466. }
  467. }
  468. }
  469. }
  470. }
  471. </style>