page.vue 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. <script setup lang="ts">
  2. import { Notify, Toast } from '@/platform';
  3. import { questionnaireMethod } from '@/request/api';
  4. import type { QuestionnaireProps } from '@/request/model';
  5. import TierSelectField from './TierSelect.field.vue';
  6. defineOptions({
  7. name: 'QuestionnairePage',
  8. });
  9. const router = useRouter();
  10. const first = ref(true);
  11. const showTitle = ref(true);
  12. const loading = ref(false);
  13. const data = ref<QuestionnaireProps[]>([]);
  14. // const { data, loading, send } = useRequest((data) => questionnaireMethod(data), {
  15. // initialData: { reportId: null, questionnaires: [] },
  16. // }).onSuccess(({ data }) => {
  17. // if ( data.reportId ) router.replace(`/report/${ data.reportId }`);
  18. // });
  19. function handle() {
  20. const questionnaires = data.value;
  21. const tips: string[] = [];
  22. for (const { label, required, name, options } of questionnaires) {
  23. if (!required) continue;
  24. switch (name) {
  25. case 'select':
  26. if (!options.some((op) => op.checked)) tips.push(label);
  27. break;
  28. }
  29. }
  30. if (tips.length) {
  31. Notify.warning(`问卷请补充完整\n\n${tips.join('\n')}`);
  32. } else {
  33. load();
  34. }
  35. }
  36. async function load() {
  37. const _first = first.value;
  38. loading.value = true;
  39. try {
  40. const { reportId, questionnaires } = await questionnaireMethod(data.value);
  41. if (reportId) return await router.replace(`/report/${reportId}`);
  42. showTitle.value = _first;
  43. data.value = [];
  44. // TODO 延迟渲染
  45. setTimeout(() => (data.value = questionnaires), 300);
  46. } catch (e) {
  47. } finally {
  48. loading.value = false;
  49. first.value = false;
  50. }
  51. }
  52. load();
  53. </script>
  54. <template>
  55. <div>
  56. <div class="page-header flex py-4 px-4">
  57. <div class="grow shrink-0 h-full min-w-16"></div>
  58. <div class="grow-[3] shrink mx-2 flex flex-col justify-center overflow-hidden">
  59. <div class="font-bold text-3xl text-nowrap text-center tracking-wide overflow-ellipsis overflow-hidden">
  60. 问卷
  61. </div>
  62. </div>
  63. <div class="grow shrink-0 h-full min-w-16"></div>
  64. </div>
  65. <div class="page-content">
  66. <template v-if="data.length">
  67. <div v-if="showTitle" class="my-8 text-2xl text-primary text-center">
  68. <div>为了更全面地评估您的健康状况</div>
  69. <div>还需要您回答6-9个问题,耗时2-3分钟</div>
  70. </div>
  71. <div class="m-6" v-for="item in data" :key="item.id">
  72. <div class="text-2xl" :class="{ required: item.required }">{{ item.label }}</div>
  73. <TierSelectField
  74. v-if="item.name === 'select'"
  75. v-model:options="item.options"
  76. :multiple="item.multiple"
  77. :disabled="loading"
  78. />
  79. </div>
  80. <van-button class="decorate" block :loading @click="handle()">提交</van-button>
  81. </template>
  82. <van-toast v-else-if="first" :show="loading" type="loading" message="加载中" />
  83. </div>
  84. </div>
  85. </template>
  86. <style scoped lang="scss">
  87. .required::after {
  88. content: '*';
  89. color: #f53030;
  90. font-size: 2rem;
  91. }
  92. </style>