pulse.page.vue 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. <script setup lang="ts">
  2. import { Notify } from '@/platform';
  3. import { tryOnBeforeMount, tryOnUnmounted, useCountdown } from '@vueuse/core';
  4. import { useRequest } from 'alova/client';
  5. import { putPulseMethod } from '@/request/api/pulse.api';
  6. import type { Flow, FlowRoute } from '@/request/model';
  7. import { getRoutePath, useRouteNext } from '@/computable/useRouteNext';
  8. import { useVisitor } from '@/stores';
  9. import NavHomeSelect from '@/assets/images/nav-home.select.png?url';
  10. const router = useRouter();
  11. const Visitor = useVisitor();
  12. const finished = ref(false);
  13. const supported = ref(true);
  14. const actionText = computed(() => supported.value ? `获取健康调理方案` : `下一步`);
  15. /* 倒计时完成动作 */
  16. const done = shallowRef<Flow>();
  17. /* 下一动作可选 */
  18. const next = shallowRef<Flow>();
  19. const { handle, loading } = useRouteNext({
  20. onSuccess(flow) { return pulse(flow); },
  21. onError(error) { Notify.warning(error.message); },
  22. });
  23. const { remaining, start, stop } = useCountdown(5, {
  24. onComplete() { replace(done.value!); },
  25. immediate: false,
  26. });
  27. const countdown = computed(() => remaining.value.toString().padStart(2, '0'));
  28. tryOnBeforeMount(() => handle());
  29. tryOnUnmounted(() => stop());
  30. async function pulse(flow: FlowRoute) {
  31. stop();
  32. const showReport = flow.next.route === '/pulse/result';
  33. try {
  34. const patientId = Visitor.patientId;
  35. const result = await Bridge.pulse(patientId!!);
  36. await submit(patientId, result);
  37. if (showReport) await replace(flow.next);
  38. else {
  39. finished.value = true;
  40. done.value = flow.next.optional ? { title: '返回首页', route: '/screen' } : flow.next;
  41. next.value = flow.next.optional ? flow.next : void 0;
  42. start(10);
  43. }
  44. } catch (e) {
  45. let message;
  46. let countdown;
  47. if (e instanceof ReferenceError) {
  48. supported.value = false;
  49. message = `当前环境不支持脉诊设备,请联系管理员!`;
  50. countdown = 5;
  51. } else {
  52. message = `请再次测量脉诊!`;
  53. countdown = 10;
  54. }
  55. done.value = flow.value.optional && !showReport ? flow.next : { title: '返回首页', route: '/screen' };
  56. start(countdown);
  57. Notify.warning(message);
  58. }
  59. }
  60. const { data: report, loading: submitting, send: submit, } = useRequest((id, result) => putPulseMethod(id, result), { immediate: false }).onSuccess(({ data }) => {
  61. Visitor.updatePulseReport(data);
  62. });
  63. const replace = (flow: Flow) => router.push({ path: getRoutePath(flow), replace: true });
  64. </script>
  65. <template>
  66. <div>
  67. <div class="page-header flex py-4 px-4">
  68. <div class="grow shrink-0 h-full min-w-16"></div>
  69. <div class="grow-[3] shrink mx-2 flex flex-col justify-center overflow-hidden">
  70. <div class="font-bold text-3xl text-nowrap text-center tracking-wide overflow-ellipsis overflow-hidden">
  71. {{ finished ? '完成脉诊采集' : '脉诊采集' }}
  72. </div>
  73. </div>
  74. <div class="grow shrink-0 h-full min-w-16 flex items-center justify-end overflow-hidden">
  75. <router-link :to="{ path: '/screen' }" replace>
  76. <img class="size-8 object-scale-down" :src="NavHomeSelect" alt="返回首页" />
  77. </router-link>
  78. </div>
  79. </div>
  80. <div class="page-content flex flex-col">
  81. <header></header>
  82. <main class="flex flex-col justify-evenly">
  83. <template v-if="finished && report">
  84. <img class="size-40 mx-auto" src="@/assets/images/tips.png" alt="" />
  85. <div>
  86. <div class="text-3xl text-center">恭喜您!</div>
  87. <div class="text-3xl text-center my-8">完成脉诊采集</div>
  88. </div>
  89. <AnalysisPulseComponent title="" v-bind="report" disabled>
  90. <template #exception>
  91. <div><!--空占位符--></div>
  92. </template>
  93. </AnalysisPulseComponent>
  94. </template>
  95. </main>
  96. <footer class="flex flex-col justify-center items-center">
  97. <template v-if="!loading">
  98. <van-button v-if="next" class="decorate !text-xl" @click="replace(next)">
  99. {{ next.title ?? actionText }}
  100. </van-button>
  101. <van-button v-if="done" class="decorate !text-xl !text-primary-400" @click="replace(done)">
  102. {{ done.title ?? actionText }}
  103. <template v-if="remaining">({{ countdown }}s)</template>
  104. </van-button>
  105. </template>
  106. <div v-if="supported && !finished" class="van-button decorate" @click="!loading && handle()">
  107. <div class="van-button__content">
  108. <van-loading v-if="loading || submitting" />
  109. <span v-else class="van-button__text">连接脉诊</span>
  110. </div>
  111. </div>
  112. </footer>
  113. </div>
  114. </div>
  115. </template>
  116. <style scoped lang="scss">
  117. header {
  118. flex: 1 1 10%;
  119. }
  120. footer {
  121. flex: 1 1 30%;
  122. }
  123. main {
  124. position: relative;
  125. flex: 1 1 50%;
  126. }
  127. .decorate {
  128. margin: 24px 0;
  129. }
  130. </style>