Przeglądaj źródła

fix(@six/smart-pharmacy): 智慧药事系统第一版弹框查看图片

cmj 1 miesiąc temu
rodzic
commit
724333dc7a

+ 104 - 13
apps/smart-pharmacy/src/views/prescription/management/detail.vue

@@ -6,7 +6,14 @@ import { useRoute } from 'vue-router';
 
 import { Page } from '@vben/common-ui';
 
-import { Breadcrumb, Descriptions, Empty, Spin, Tabs } from 'ant-design-vue';
+import {
+  Breadcrumb,
+  Descriptions,
+  Empty,
+  Modal,
+  Spin,
+  Tabs,
+} from 'ant-design-vue';
 
 import { createEmptyPrescriptionDetail } from '#/api/model/prescription-detail';
 import {
@@ -193,6 +200,43 @@ function goBack() {
   window.history.back();
 }
 
+const previewVisible = ref(false);
+const previewUrl = ref('');
+const previewTitle = ref('预览');
+const previewLoading = ref(false);
+const previewError = ref(false);
+
+const previewIsPdf = computed(() => isPdfUrl(previewUrl.value));
+
+function isPdfUrl(url: string): boolean {
+  const path = url.split('?')[0]?.split('#')[0] ?? '';
+  return /\.pdf$/i.test(path);
+}
+
+function openPreview(url: string, title = '预览') {
+  previewUrl.value = url;
+  previewTitle.value = title;
+  previewError.value = false;
+  previewLoading.value = true;
+  previewVisible.value = true;
+}
+
+function onPreviewLoad() {
+  previewLoading.value = false;
+}
+
+function onPreviewError() {
+  previewLoading.value = false;
+  previewError.value = true;
+}
+
+function closePreview() {
+  previewVisible.value = false;
+  previewLoading.value = false;
+  previewError.value = false;
+  previewUrl.value = '';
+}
+
 watch(prescriptionId, loadDetail, { immediate: true });
 </script>
 
@@ -515,15 +559,13 @@ watch(prescriptionId, loadDetail, { immediate: true });
                           <span>操作人: {{ item.operator }}</span>
                           <span v-if="item.hasPhoto">
                             环节照片/视频:
-                            <a
+                            <span
                               v-if="item.photoUrl"
-                              :href="item.photoUrl"
-                              class="text-primary hover:text-primary/80"
-                              rel="noopener noreferrer"
-                              target="_blank"
+                              class="text-primary hover:text-primary/80 cursor-pointer"
+                              @click="openPreview(item.photoUrl, '环节照片')"
                             >
                               查看照片
-                            </a>
+                            </span>
                             <span v-else>有</span>
                           </span>
                         </div>
@@ -667,15 +709,13 @@ watch(prescriptionId, loadDetail, { immediate: true });
                       <td class="border-border text-foreground border-b px-4 py-3">{{ item.productionDate }}</td>
                       <td class="border-border text-foreground border-b px-4 py-3">{{ item.expiryDate }}</td>
                       <td class="border-border border-b px-4 py-3 text-center">
-                        <a
+                        <span
                           v-if="item.reportUrl"
-                          :href="item.reportUrl"
-                          class="text-primary hover:text-primary/80 underline"
-                          rel="noopener noreferrer"
-                          target="_blank"
+                          class="text-primary hover:text-primary/80 cursor-pointer underline"
+                          @click="openPreview(item.reportUrl, '检验报告')"
                         >
                           查看
-                        </a>
+                        </span>
                         <span v-else>-</span>
                       </td>
                     </tr>
@@ -688,6 +728,57 @@ watch(prescriptionId, loadDetail, { immediate: true });
         </Tabs>
       </div>
     </Spin>
+
+    <Modal
+      :open="previewVisible"
+      :title="previewTitle"
+      :footer="null"
+      :width="previewIsPdf ? '80vw' : 720"
+      destroy-on-close
+      @cancel="closePreview"
+    >
+      <div
+        class="relative flex min-h-[240px] w-full items-center justify-center"
+      >
+        <div
+          v-if="previewLoading"
+          class="absolute inset-0 z-10 flex items-center justify-center"
+        >
+          <Spin tip="加载中..." />
+        </div>
+
+        <Empty v-if="previewError" description="文件加载失败">
+          <a
+            v-if="previewUrl"
+            :href="previewUrl"
+            class="text-primary"
+            rel="noopener noreferrer"
+            target="_blank"
+          >
+            在新窗口打开
+          </a>
+        </Empty>
+
+        <iframe
+          v-else-if="previewIsPdf"
+          referrerpolicy="no-referrer"
+          :src="previewUrl"
+          class="h-[70vh] w-full border-0"
+          title="PDF预览"
+          @load="onPreviewLoad"
+        />
+        <img
+          v-else-if="previewUrl"
+          referrerpolicy="no-referrer"
+          :src="previewUrl"
+          alt="预览"
+          class="mx-auto block max-h-[70vh] max-w-full transition-opacity"
+          :class="previewLoading ? 'opacity-0' : 'opacity-100'"
+          @error="onPreviewError"
+          @load="onPreviewLoad"
+        />
+      </div>
+    </Modal>
   </Page>
 </template>