orderList.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559
  1. <template>
  2. <view class="orderList">
  3. <!-- 头部筛选 -->
  4. <view class="orderList_header">
  5. <view class="orderList_header_item" @click="openPicker('gdState')">
  6. <text class="orderList_header_itemText">{{selectedGdState}}</text>
  7. <text class="pda pda-xiala"></text>
  8. </view>
  9. <view class="orderList_header_item" @click="openPicker('associationType')">
  10. <text class="orderList_header_itemText">{{selectedAssociationType}}</text>
  11. <text class="pda pda-xiala"></text>
  12. </view>
  13. </view>
  14. <!-- 列表 -->
  15. <view class="orderList_list">
  16. <view class="orderList_listItem" v-for="newOrder in newOrderList" :key="newOrder.id"
  17. @click="toDetail(newOrder.id)">
  18. <image class="ji" src="../../static/imgs/icon_ji.png" mode="widthFix"
  19. v-if="newOrder.emergencyType && newOrder.emergencyType.value == 2"></image>
  20. <image class="jiaji" src="../../static/imgs/icon_jiaji.png" mode="widthFix"
  21. v-if="newOrder.emergencyType && newOrder.emergencyType.value == 3"></image>
  22. <view class="orderList_listItem_header">
  23. <view class="orderList_listItem_header_title">
  24. <view class="associationType_icon" v-if="newOrder.isHalfInspect === 1"> 半 </view>
  25. <view class="associationType_icon" v-else-if="newOrder.taskType.associationType.value == 'specimen'">标
  26. </view>
  27. <view class="associationType_icon" v-else-if="newOrder.taskType.associationType.value == 'drugsBag'"> 药
  28. </view>
  29. <view class="associationType_icon" v-else-if="newOrder.taskType.associationType.value == 'specimenPlan'"> 巡
  30. </view>
  31. <view class="associationType_icon" v-else-if="newOrder.taskType.associationType.value == 'jPBag'"> 静 </view>
  32. <view class="associationType_icon" v-else-if="newOrder.taskType.associationType.value == 'inspect'"> 病
  33. </view>
  34. <view class="associationType_icon"
  35. v-else-if="newOrder.taskType.associationType.value == 'patientTransport'"> 病
  36. </view>
  37. <view class="associationType_icon" v-else-if="newOrder.taskType.associationType.value == 'other'"> 其
  38. </view>
  39. <view class="taskNameAndWorkerName">
  40. <text class="taskName">{{newOrder.isHalfInspect === 1? "半程陪检": newOrder.taskType.taskName}}</text>
  41. <text class="workerName"
  42. v-if="newOrder.patient &&(newOrder.taskType.associationType.value =='patientTransport' ||newOrder.taskType.associationType.value =='inspect')">-{{newOrder.patient.patientName}}</text>
  43. </view>
  44. </view>
  45. <text class="orderList_listItem_header_more"
  46. :class="newOrder.stateTextClass">{{newOrder.gdState.name }}</text>
  47. </view>
  48. <view class="orderList_listItem_item">
  49. <view class="orderList_listItem_item_content">
  50. <text class="orderList_listItem_item_name"
  51. v-if="newOrder.worker">{{newOrder.worker.name}}{{newOrder.worker.phone? "-" + newOrder.worker.phone: ""}}</text>
  52. <text class="orderList_listItem_item_name" v-else>暂未接单</text>
  53. <text class="orderList_listItem_item_time" v-if="newOrder.showCreateTime">{{newOrder.showCreateTime}}</text>
  54. <text class="orderList_listItem_item_time"
  55. v-else-if="newOrder.yyjdTime && newOrder.gdState.value == GDSTATE['定时预约']">{{newOrder.yyjdTime | formatDate('MM-dd HH:mm')}}</text>
  56. </view>
  57. <view class="orderList_listItem_item_btns" v-if="
  58. newOrder.gdState.value == GDSTATE['待抢单'] ||
  59. newOrder.gdState.value == GDSTATE['待接单'] ||
  60. newOrder.gdState.value == GDSTATE['待到达'] ||
  61. newOrder.gdState.value == GDSTATE['定时预约'] ||
  62. newOrder.gdState.value == GDSTATE['待评价']
  63. ">
  64. <button type="primary" class="btn" v-if="newOrder.gdState.value == GDSTATE['待评价']"
  65. @click.stop="showAppraise(newOrder.id)">评价</button>
  66. <button type="primary" class="btn" v-if="
  67. newOrder.gdState.value == GDSTATE['待抢单'] ||
  68. newOrder.gdState.value == GDSTATE['待接单'] ||
  69. newOrder.gdState.value == GDSTATE['待到达'] ||
  70. newOrder.gdState.value == GDSTATE['定时预约']
  71. " @click.stop="openRecallModal(newOrder.id)">撤销</button>
  72. <button type="primary" class="btn" v-if="newOrder.gdState.value == GDSTATE['定时预约']"
  73. @click.stop="openExecModal(newOrder.id)">立即执行</button>
  74. <button type="primary" class="btn" v-if="
  75. (newOrder.gdState.value == GDSTATE['待抢单'] ||
  76. newOrder.gdState.value == GDSTATE['待到达']) &&
  77. newOrder.taskType.allowUrgent == 1 &&
  78. !newOrder.urgentDetails
  79. " @click.stop="showJiaji(newOrder.id)">加急</button>
  80. </view>
  81. </view>
  82. </view>
  83. </view>
  84. <seiminFooterNav></seiminFooterNav>
  85. <seiminModel ref="seiminModel"></seiminModel>
  86. <seiminPicker ref="sPicker" titleColor="#808080" titleFontSize="28rpx" confirmColor="#333" confirmFontSize="38rpx"
  87. confirmFontWeight="500" itemFontSize="32rpx" @onClose="closePicker" @onConfirm="confirmPicker"
  88. :pickerList="pickerList">
  89. </seiminPicker>
  90. </view>
  91. </template>
  92. <script>
  93. import {
  94. backPress
  95. } from '../../utils/index.js';
  96. import {
  97. mapState,
  98. mapActions
  99. } from "vuex";
  100. import {
  101. reqFetchDataList,
  102. } from "../../request/api.js";
  103. import {
  104. GDSTATE
  105. } from "../../utils/enum.gdstate.js";
  106. import {
  107. WORKORDER_EVALUATION
  108. } from "../../utils/enum.workorderEvaluation.js";
  109. import {
  110. showAppraise,
  111. openRecallModal,
  112. openExecModal,
  113. showJiaji,
  114. } from "../../utils/index.js";
  115. export default {
  116. name: 'orderList',
  117. onBackPress() {
  118. backPress();
  119. },
  120. data() {
  121. return {
  122. reFresh: '',
  123. // 工单状态
  124. GDSTATE: GDSTATE,
  125. // 当前筛选的工单状态
  126. selectedGdState: '执行中',
  127. // 当前筛选的关联类型
  128. selectedAssociationType: '全部',
  129. //工单状态筛选列表
  130. gdStates: [{
  131. value: -1,
  132. label: '全部'
  133. },
  134. {
  135. value: 1,
  136. label: '执行中'
  137. },
  138. {
  139. value: 2,
  140. label: '待评价'
  141. },
  142. ],
  143. //关联类型筛选列表
  144. associationTypes: [{
  145. value: -1,
  146. label: '全部'
  147. }, ],
  148. newOrderList: [], //工单列表
  149. totalNum: 0, //工单总数量
  150. idx: 0, //页码
  151. pageNum: 20, //每页的工单数量
  152. pickerList: [], //picker列表
  153. type: '', //打开picker的类型,工单状态||关联类型
  154. };
  155. },
  156. computed: {
  157. ...mapState("login", ["loginInfo"]),
  158. },
  159. methods: {
  160. ...mapActions("dictionary", ["vxDictionary"]),
  161. // 前往工单详情
  162. toDetail(id) {
  163. uni.navigateTo({
  164. url: `/pages/orderDetail/orderDetail?id=${id}`
  165. })
  166. },
  167. //评价
  168. showAppraise(id) {
  169. showAppraise.call(this, id, () => {
  170. this.$refs.seiminModel.close();
  171. this.init();
  172. });
  173. },
  174. //撤销
  175. openRecallModal(id) {
  176. openRecallModal.call(this, id, () => {
  177. this.$refs.seiminModel.close();
  178. this.init();
  179. });
  180. },
  181. //立即执行
  182. openExecModal(id) {
  183. openExecModal.call(this, id, () => {
  184. this.$refs.seiminModel.close();
  185. this.init();
  186. });
  187. },
  188. //加急
  189. showJiaji(id) {
  190. showJiaji.call(this, id, () => {
  191. this.$refs.seiminModel.close();
  192. this.init();
  193. });
  194. },
  195. //关闭
  196. closePicker() {
  197. this.$refs.sPicker._close();
  198. },
  199. //打开
  200. openPicker(type) {
  201. this.type = type;
  202. this.$refs.sPicker._open();
  203. if (type === 'gdState') {
  204. //工单状态
  205. this.pickerList = this.gdStates;
  206. let index = this.pickerList.findIndex(v => v.label === this.selectedGdState);
  207. let obj = this.pickerList.find(v => v.label === this.selectedGdState);
  208. this.$refs.sPicker._changeValue(index);
  209. this.selectedGdState = obj && obj.label;
  210. } else if (type === 'associationType') {
  211. //关联类型
  212. this.pickerList = this.associationTypes;
  213. let index = this.pickerList.findIndex(v => v.label === this.selectedAssociationType);
  214. let obj = this.pickerList.find(v => v.label === this.selectedAssociationType);
  215. this.$refs.sPicker._changeValue(index);
  216. this.selectedAssociationType = obj && obj.label;
  217. }
  218. },
  219. //确定:接收子组件传来的参数
  220. confirmPicker(checkedObj) {
  221. if (this.type === 'gdState') {
  222. //工单状态
  223. this.selectedGdState = checkedObj.label;
  224. } else if (this.type === 'associationType') {
  225. //关联类型
  226. this.selectedAssociationType = checkedObj.label;
  227. }
  228. let index = this.pickerList.findIndex(v => v.label === checkedObj.label);
  229. this.$refs.sPicker._changeValue(index);
  230. this.init();
  231. },
  232. // 获取页面数据
  233. init() {
  234. uni.showLoading({
  235. title: "加载中",
  236. mask: true,
  237. });
  238. Promise.all([
  239. this.queryWorkOrdersRequest(), //查询最新工单列表
  240. this.queryDictionary('association_types'), //获取数据字典-关联类型
  241. ]).then((values) => {
  242. uni.hideLoading();
  243. uni.stopPullDownRefresh();
  244. this.queryWorkOrdersResponse(values[0]);
  245. this.queryDictionaryResponse(values[1], 'association_types');
  246. });
  247. },
  248. // 查询最新工单列表(上拉)
  249. reachBottom() {
  250. //没有更多
  251. if (this.newOrderList.length == this.totalNum) {
  252. uni.showToast({
  253. icon: 'none',
  254. title: '没有更多工单了'
  255. })
  256. return;
  257. }
  258. uni.showLoading({
  259. title: "加载中",
  260. mask: true,
  261. });
  262. Promise.all([
  263. this.queryWorkOrdersRequest(true), //查询最新工单列表
  264. ]).then((values) => {
  265. uni.hideLoading();
  266. this.queryWorkOrdersResponse(values[0], true);
  267. });
  268. },
  269. // 查询最新工单列表
  270. queryWorkOrdersRequest(idxPlus = false) {
  271. console.log(this.selectedGdState, this.selectedAssociationType);
  272. console.log(this.gdStates, this.associationTypes);
  273. if (idxPlus) {
  274. //累加
  275. ++this.idx;
  276. } else {
  277. this.idx = 0;
  278. }
  279. let postData = {
  280. workOrder: {
  281. createDept: this.loginInfo.user.dept.id,
  282. platform: 2,
  283. searchDays: 2,
  284. },
  285. idx: this.idx,
  286. sum: this.pageNum,
  287. };
  288. let selectedGdStateValue = this.gdStates.find(v => v.label == this.selectedGdState).value;
  289. let associationTypesValue = this.associationTypes.find(v => v.label == this.selectedAssociationType).value;
  290. // 工单状态
  291. // 执行中包含状态:待抢单、待接单、待到达、待送达、执行中、定时预约
  292. if (selectedGdStateValue == 1) {
  293. // 执行中
  294. postData.workOrder.nurseState = 1;
  295. } else if (selectedGdStateValue == 2) {
  296. // 待评价
  297. postData.workOrder.gdState = {
  298. id: "73"
  299. };
  300. }
  301. //关联类型
  302. if (associationTypesValue != -1) {
  303. postData.workOrder.taskType = {
  304. associationType: {
  305. id: associationTypesValue,
  306. }
  307. }
  308. }
  309. return reqFetchDataList("nurse", "workOrder", postData);
  310. },
  311. // 查询最新工单列表
  312. queryWorkOrdersResponse(res, idxPlus = false) {
  313. if (res.status == 200) {
  314. res.list = res.list || [];
  315. this.totalNum = res.totalNum || 0;
  316. let newOrderList = res.list.map((v) => {
  317. if (v.gdState) {
  318. if (
  319. v.gdState.value == GDSTATE["待接单"] ||
  320. v.gdState.value == GDSTATE["待抢单"]
  321. ) {
  322. v.stateTextClass = "red";
  323. } else if (
  324. v.gdState.value == GDSTATE["待评价"] ||
  325. v.gdState.value == GDSTATE["已完成"]
  326. ) {
  327. v.stateTextClass = "green";
  328. } else {
  329. v.stateTextClass = "yellow";
  330. }
  331. }
  332. return v;
  333. });
  334. if (idxPlus) {
  335. //累加
  336. this.newOrderList = this.newOrderList.concat(newOrderList);
  337. } else {
  338. this.newOrderList = newOrderList;
  339. }
  340. } else {
  341. this.$refs.seiminModel.show({
  342. skin: "toast",
  343. icon: "error",
  344. content: res.msg || "获取数据失败",
  345. });
  346. throw new Error(res.msg || '获取数据失败');
  347. }
  348. },
  349. // 获取数据字典
  350. queryDictionary(key) {
  351. let postData = {
  352. "type": "list",
  353. key
  354. };
  355. return this.vxDictionary(postData);
  356. },
  357. // 获取数据字典
  358. queryDictionaryResponse(res, type) {
  359. let arr = [];
  360. switch (type) {
  361. case 'association_types':
  362. arr = res.map(v => ({
  363. value: v.id,
  364. label: v.name
  365. }));
  366. this.associationTypes = [{
  367. label: '全部',
  368. value: -1
  369. }, ...arr];
  370. break;
  371. }
  372. },
  373. },
  374. mounted() {
  375. this.init();
  376. },
  377. onPullDownRefresh() {
  378. this.init();
  379. },
  380. onReachBottom() {
  381. this.reachBottom();
  382. }
  383. }
  384. </script>
  385. <style lang="scss" scoped>
  386. .orderList {
  387. padding-bottom: 108rpx;
  388. // 头部筛选
  389. .orderList_header {
  390. height: 88rpx;
  391. background-color: #fff;
  392. position: fixed;
  393. left: 0;
  394. z-index: 99;
  395. width: 100%;
  396. @include border(bottom);
  397. @include flex(center, center);
  398. .orderList_header_item {
  399. flex: 1;
  400. height: 100%;
  401. padding: 0 50rpx;
  402. @include border(right);
  403. @include flex(space-between, center);
  404. &:last-of-type {
  405. border-right: none;
  406. }
  407. .orderList_header_itemText {
  408. color: #333;
  409. font-size: 38rpx;
  410. }
  411. .pda-xiala {
  412. color: #DDE1E5;
  413. }
  414. }
  415. }
  416. // 列表
  417. .orderList_list {
  418. padding: 88rpx 24rpx 0;
  419. .orderList_listItem {
  420. width: 702rpx;
  421. min-height: 320rpx;
  422. background-color: #fff;
  423. margin-top: 8rpx;
  424. border-radius: 8rpx;
  425. position: relative;
  426. padding: 0 24rpx;
  427. font-size: 32rpx;
  428. @include border;
  429. @include semicircle(#f9fafb, 82rpx);
  430. @include flex(flex-start, stretch, column);
  431. .ji,
  432. .jiaji {
  433. width: 60rpx;
  434. position: absolute;
  435. right: 0;
  436. top: 0;
  437. }
  438. .orderList_listItem_header {
  439. height: 86rpx;
  440. @include border($directive:bottom, $style:dashed);
  441. @include flex(space-between, center);
  442. .orderList_listItem_header_title {
  443. color: #333;
  444. flex: 1;
  445. @include flex(flex-start, center);
  446. .associationType_icon {
  447. width: 48rpx;
  448. height: 48rpx;
  449. border-radius: 50%;
  450. background-color: #F0F6ED;
  451. font-size: 24rpx;
  452. color: #39b199;
  453. margin-right: 8rpx;
  454. @include border($color:#39b199);
  455. @include flex(center, center);
  456. }
  457. .taskNameAndWorkerName {
  458. flex: 1;
  459. @include flex;
  460. .taskName {
  461. max-width: 10em;
  462. @include clamp;
  463. }
  464. .workerName {
  465. flex: 1;
  466. @include clamp;
  467. }
  468. }
  469. }
  470. .orderList_listItem_header_more {
  471. color: #666;
  472. @include clamp;
  473. }
  474. }
  475. .orderList_listItem_item {
  476. height: 88rpx;
  477. color: #333;
  478. font-size: 30rpx;
  479. flex: 1;
  480. @include border(bottom);
  481. @include flex(flex-start, stretch, column);
  482. &:last-of-type {
  483. border-bottom: none;
  484. }
  485. .orderList_listItem_item_content {
  486. min-height: 143rpx;
  487. flex: 1;
  488. @include flex(space-between, center);
  489. .orderList_listItem_item_name {
  490. font-size: 38rpx;
  491. font-weight: bold;
  492. }
  493. .orderList_listItem_item_time {
  494. color: #666;
  495. font-size: 28rpx;
  496. }
  497. }
  498. .orderList_listItem_item_btns {
  499. position: relative;
  500. left: -24rpx;
  501. width: 698rpx;
  502. height: 88rpx;
  503. @include btn_background;
  504. @include flex;
  505. .btn {
  506. flex: 1;
  507. background-color: transparent;
  508. position: relative;
  509. @include flex(center, center);
  510. &::before {
  511. content: '';
  512. position: absolute;
  513. right: 0;
  514. top: 0;
  515. width: 1px;
  516. height: 100%;
  517. @include border(right, #fff);
  518. }
  519. &:last-of-type::before {
  520. border-right: none;
  521. }
  522. &::after {
  523. border: none;
  524. }
  525. }
  526. }
  527. }
  528. }
  529. }
  530. }
  531. </style>