Parcourir la source

健康报告提取小程序码组件

cc12458 il y a 1 mois
Parent
commit
f9e228d6e8

+ 80 - 0
src/components/MiniProgram.vue

@@ -0,0 +1,80 @@
+<script setup lang="ts">
+import NavMiniProgram from '@/assets/images/mini-program.svg?url';
+import { Notify } from '@/platform';
+
+const props = defineProps<{ url?: string; closeable?: boolean; forcedShow?: boolean }>();
+
+const panelHeight = ref(0);
+const panelProps = reactive({
+  anchors: [0, window.innerWidth],
+  contentDraggable: false,
+  lockScroll: true,
+});
+const showOverlay = computed(() => panelHeight.value >= panelProps.anchors[0] && panelHeight.value > 0)
+
+watchEffect(() => {
+  panelProps.anchors[0] = props.closeable ? 0 : 100;
+});
+
+const handle = () => {
+  if (!props.url) {
+    Notify.warning(`未获取到小程序地址,请联系管理员或重试`);
+    return;
+  }
+  panelOpen();
+};
+
+const panelOpen = (min?: number) => {
+  if (min) panelProps.anchors[0] = min;
+  panelHeight.value = panelProps.anchors[1];
+};
+
+defineExpose({
+  open: handle,
+});
+</script>
+
+<template>
+  <div class="nav m-auto min-w-16 text-center hover:text-primary" v-if="url || props.forcedShow" @click="handle()">
+    <img class="nav-img" :src="NavMiniProgram" alt="小程序" />
+    <div class="mt-2">小程序</div>
+  </div>
+  <van-overlay :show="showOverlay" class="panel-mask"></van-overlay>
+  <van-floating-panel v-model:height="panelHeight" v-bind="panelProps">
+    <template #header>
+      <div class="van-floating-panel__header !justify-between">
+        <div></div>
+        <div class="van-floating-panel__header-bar"></div>
+        <div>
+          <van-icon v-if="props.closeable" name="cross" @click.stop="panelHeight = panelProps.anchors[0]" />
+        </div>
+      </div>
+    </template>
+    <Transition>
+      <div class="panel-content">
+        <img class="size-full object-contain" v-if="panelHeight === panelProps.anchors[1] || panelHeight > panelProps.anchors[0] * 1.5" :src="url" alt="小程序码" />
+        <div class="flex justify-center items-center" v-else @click="panelOpen()">
+          <img class="h-10 w-10" src="@/assets/images/mini-program.svg" alt="小程序" />
+          <span class="text-lg ml-2">小程序</span>
+        </div>
+      </div>
+    </Transition>
+  </van-floating-panel>
+</template>
+
+<style scoped lang="scss">
+.nav-img {
+  margin: auto;
+  width: 36px;
+  height: 36px;
+  object-fit: scale-down;
+}
+
+.panel-mask {
+  --van-overlay-background: transparent;
+}
+
+.panel-content {
+  padding: 0 var(--van-floating-panel-header-height) var(--van-floating-panel-header-height);
+}
+</style>

+ 9 - 56
src/modules/report/report.page.vue

@@ -13,6 +13,9 @@ import { useRouteParams }         from '@vueuse/router';
 import { useRequest, useWatcher } from 'alova/client';
 import { useRouter }              from 'vue-router';
 
+import MiniProgram from '@/components/MiniProgram.vue';
+const miniProgramRef = useTemplateRef<InstanceType<typeof MiniProgram>>('mini-program');
+
 const hidePulseExceptionTemplate = computed(() => platformIsAIO())
 
 const id = useRouteParams<string>('id');
@@ -25,7 +28,9 @@ const { data, loading } = useWatcher(() => getReportMethod(id.value), [ id ], {
   },
   immediate: true,
 }).onSuccess(({ data }) => {
-  if ( data?.miniProgramURL && data.payLock ) panelOpen(100);
+  if ( data?.miniProgramURL && data.payLock ) {
+    nextTick(() => miniProgramRef.value?.open());
+  }
 })
 
 const { loading: uploading, send: upload } = useRequest(() => updateReportMethod(id.value, data.value), {
@@ -72,36 +77,12 @@ async function print() {
   }
 }
 
-async function miniProgram() {
-  let url = data.value.miniProgramURL;
-  if ( !url ) {
-    Notify.warning(`未获取到小程序地址,请联系管理员或重试`);
-    return;
-  }
-  panelOpen();
-}
-
 const router = useRouter();
 
 function toggle() {
   const path = `${ router.currentRoute.value.fullPath }/scheme`.replace(/\/{2,}/g, '/');
   router.replace({ path });
 }
-
-const panelHeight = ref(0);
-const panelProps = reactive({
-  anchors: [0, window.innerWidth],
-  contentDraggable: false,
-  lockScroll: true,
-});
-const panelOpen = (min?: number) => {
-  if ( min ) panelProps.anchors[ 0 ] = min;
-  panelHeight.value = panelProps.anchors[1];
-};
-
-const scrollable = computed(() => !data.value.payLock &&
-                                  panelHeight.value < panelProps.anchors[ 1 ] || panelHeight.value === 0,
-);
 </script>
 <template>
   <div class="report-wrapper">
@@ -120,7 +101,7 @@ const scrollable = computed(() => !data.value.payLock &&
     </div>
     <div class="page-content flex flex-col overflow-hidden">
       <van-skeleton class="flex-auto" title :row="3" :loading>
-        <div class="flex-auto" :class="{ 'overflow-y-auto': scrollable }">
+        <div class="flex-auto overflow-y-auto">
           <div class="my-6 text-primary text-2xl text-center">报告日期:{{ data.date }}</div>
           <div class="card m-6 text-lg">
             <div class="card__title text-primary text-3xl font-bold"></div>
@@ -219,10 +200,7 @@ const scrollable = computed(() => !data.value.payLock &&
           <img :src="NavScheme" alt="调理方案">
           <div class="mt-2">调理方案</div>
         </div>
-        <div class="m-auto min-w-16 text-center hover:text-primary" v-if="data.miniProgramURL" @click="miniProgram()">
-          <img :src="NavMiniProgram" alt="小程序">
-          <div class="mt-2">小程序</div>
-        </div>
+        <mini-program ref="mini-program" :url="data.miniProgramURL" :closeable="!data.payLock"></mini-program>
         <div class="m-auto min-w-16 text-center hover:text-primary" @click="print()">
           <van-loading v-if="uploading" color="#38ff6e" style="font-size: 24px;" />
           <img v-else :src="NavPrint" alt="打印">
@@ -230,31 +208,6 @@ const scrollable = computed(() => !data.value.payLock &&
         </div>
       </div>
       <Component :is="ReportPreview" v-bind="reportPreviewProps" v-model:show="reportPreviewProps.show"></Component>
-      <van-floating-panel v-model:height="panelHeight" v-bind="panelProps">
-        <template #header>
-          <div class="van-floating-panel__header !justify-between">
-            <div></div>
-            <div class="van-floating-panel__header-bar"></div>
-            <div>
-              <van-icon v-if="!data.payLock" name="cross" @click.stop="panelHeight = panelProps.anchors[0];" />
-            </div>
-          </div>
-        </template>
-        <Transition>
-          <div class="panel-content">
-            <img
-              class="size-full object-contain"
-              v-if="panelHeight === panelProps.anchors[1] || panelHeight > panelProps.anchors[0] * 1.5"
-              :src="data.miniProgramURL"
-              alt="小程序码"
-            />
-            <div class="flex justify-center items-center" v-else @click="panelOpen()">
-              <img class="h-10 w-10" src="@/assets/images/mini-program.svg" alt="小程序" />
-              <span class="text-lg ml-2">小程序</span>
-            </div>
-          </div>
-        </Transition>
-      </van-floating-panel>
     </div>
   </div>
 </template>
@@ -299,7 +252,7 @@ const scrollable = computed(() => !data.value.payLock &&
 }
 
 .nav-wrapper {
-  img {
+  .nav-img {
     margin: auto;
     width: 36px;
     height: 36px;

+ 12 - 3
src/modules/report/scheme.page.vue

@@ -49,7 +49,7 @@ function toggle() {
                 <div class="text-xl text-center text-primary">{{ card.title }}</div>
                 <SchemeMedia :media="card.media"></SchemeMedia>
                 <div v-if="card.description">{{ card.description }}</div>
-                <div v-for="(item,index) in card.descriptions ">
+                <div v-for="(item, index) in card.descriptions">
                   <span class="text-primary">【{{ item.title }}】</span>
                   <span v-html="item.description"></span>
                 </div>
@@ -58,9 +58,9 @@ function toggle() {
           </div>
         </div>
       </van-skeleton>
-      <div class="flex-none flex justify-between py-2 nav-wrapper" style="background-color: #12312c;">
+      <div class="flex-none flex justify-between py-2 nav-wrapper" style="background-color: #12312c">
         <div class="m-auto min-w-16 text-center hover:text-primary" @click="toggle()">
-          <img :src="NavScheme" alt="健康报告">
+          <img class="nav-img" :src="NavScheme" alt="健康报告" />
           <div class="mt-2">健康报告</div>
         </div>
       </div>
@@ -85,4 +85,13 @@ function toggle() {
 .text-grey {
   color: #e3e3e3;
 }
+
+.nav-wrapper {
+  .nav-img {
+    margin: auto;
+    width: 36px;
+    height: 36px;
+    object-fit: scale-down;
+  }
+}
 </style>