Selaa lähdekoodia

1. 修改图片
2. 添加患者充值功能
3. 登录用户密码重置

cc12458 1 vuosi sitten
vanhempi
commit
8a75aec4e3

+ 1 - 0
@types/components.d.ts

@@ -39,6 +39,7 @@ declare module 'vue' {
     RecordsAnalysisPreview: typeof import('./../src/components/RecordsAnalysisPreview.vue')['default']
     RecordsIndicatorPreview: typeof import('./../src/components/RecordsIndicatorPreview.vue')['default']
     RecordsPatientPreview: typeof import('./../src/components/RecordsPatientPreview.vue')['default']
+    ReportAnalysisCountEdit: typeof import('./../src/components/ReportAnalysisCountEdit.vue')['default']
     ReportAnalysisEdit: typeof import('./../src/components/ReportAnalysisEdit.vue')['default']
     ReportHistoryPreview: typeof import('./../src/components/ReportHistoryPreview.vue')['default']
     ReportPreview: typeof import('./../src/components/ReportPreview.vue')['default']

+ 67 - 0
src/components/ReportAnalysisCountEdit.vue

@@ -0,0 +1,67 @@
+<script setup lang="ts">
+import type { PatientModel }                                            from '@/model';
+import { patientAnalysisCountMethod, updatePatientAnalysisCountMethod } from '@/request/api/patient.api';
+import { useRequest, useWatcher }                                       from 'alova/client';
+import { message as Message }                                           from 'ant-design-vue/es/components';
+
+
+const props = defineProps<{
+  patient: Partial<PatientModel>;
+}>();
+const emits = defineEmits<{
+  destroy: [];
+}>();
+
+const patientId = computed(() => props.patient?.id);
+const model = reactive({
+  total: 0,
+  count: 0,
+})
+const { loading } = useWatcher(
+  () => patientAnalysisCountMethod(patientId.value!),
+  [ () => props.patient?.id ],
+  {
+    initialData: {}, immediate: true,
+    middleware: (_, next) => { if ( patientId.value ) next(); },
+  },
+).onSuccess(({data})=>{
+  model.total = data.total;
+  model.count = data.count;
+});
+const { loading: updating, send: updata } = useRequest(
+  () => updatePatientAnalysisCountMethod(patientId.value!, model.count),
+  { immediate: false },
+).onSuccess(() => {
+  Message.success(`充值成功`);
+  emits('destroy');
+});
+</script>
+<template>
+  <div id="page-container-scroller" class="page-container flex flex-col">
+    <a-spin :spinning="loading">
+      <a-descriptions bordered :column="1">
+        <a-descriptions-item label="姓名">{{ props.patient.name }}</a-descriptions-item>
+        <a-descriptions-item label="健康分析次数">
+          <a-form
+            ref="formRef" :model="model" :label-col="{span: 12}"
+            @finish="updata()"
+          >
+            <a-form-item label="已用次数">{{ model.total }}</a-form-item>
+            <a-form-item label="剩余次数" name="count" :rules="[{ required: true, message: '请输入剩余次数' }]">
+              <a-input-number :min="0" :max="100" v-model:value="model.count" />
+            </a-form-item>
+            <a-form-item>
+              <a-space>
+                <a-button type="primary" html-type="submit" :loading="updating">保存</a-button>
+                <a-button type="default" @click="emits('destroy')">取消</a-button>
+              </a-space>
+            </a-form-item>
+          </a-form>
+        </a-descriptions-item>
+      </a-descriptions>
+    </a-spin>
+  </div>
+</template>
+<style scoped lang="scss">
+@import "@/themes/report-card";
+</style>

+ 3 - 3
src/components/ReportAnalysisEdit.vue

@@ -55,8 +55,8 @@ const { data: indicator, loading: indicatorLoading } = useWatcher(
         <a-descriptions :column="2">
           <a-descriptions-item v-if="report.tongueAnalysisResult">
             <a-space align="start">
-              <a-image :width="200" :height="200" :src="report.upImg" :preview="false" />
-              <a-image :width="200" :height="200" :src="report.downImg" :preview="false" />
+              <a-image :width="200" :height="200" :src="report.upImg" :preview="true" />
+              <a-image :width="200" :height="200" :src="report.downImg" :preview="true" />
               <a-card size="small" title="舌象分析结果">
                 {{ report.tongueAnalysisResult }}
               </a-card>
@@ -65,7 +65,7 @@ const { data: indicator, loading: indicatorLoading } = useWatcher(
           <a-descriptions-item v-if="report.faceAnalysisResult">
             <a-space wrap>
               <a-space align="start">
-                <a-image :width="200" :height="200" :src="report.faceImg" :preview="false" />
+                <a-image :width="200" :height="200" :src="report.faceImg" :preview="true" />
                 <a-card size="small" title="面象分析结果">
                   {{ report.faceAnalysisResult }}
                 </a-card>

+ 3 - 3
src/components/ReportHistoryPreview.vue

@@ -258,9 +258,9 @@ const { height } = useElementSize(patientCardRef);
           </a-col>
           <a-col :span="12">
             <a-space style="margin-left: 8px;">
-              <a-image v-if="report?.upImg" :width="200" :height="200" :src="report.upImg" :preview="false" />
-              <a-image v-if="report?.downImg" :width="200" :height="200" :src="report.downImg" :preview="false" />
-              <a-image v-if="report?.faceImg" :width="200" :height="200" :src="report.faceImg" :preview="false" />
+              <a-image v-if="report?.upImg" :width="200" :height="200" :src="report.upImg" :preview="true" />
+              <a-image v-if="report?.downImg" :width="200" :height="200" :src="report.downImg" :preview="true" />
+              <a-image v-if="report?.faceImg" :width="200" :height="200" :src="report.faceImg" :preview="true" />
             </a-space>
           </a-col>
         </a-row>

+ 17 - 5
src/components/UserPassword.vue

@@ -11,25 +11,37 @@ interface FormModel {
   twice?: string;
 }
 
-const props = defineProps<{ data: UserModel }>();
+const props = defineProps<{ data: UserModel, update?: boolean }>();
 const emits = defineEmits<{
   submit: [],
 }>();
-const { loading: submitting, send: submit } = useRequest(updateUserPasswordMethod, { immediate: false }).onSuccess(
-  ({ data }) => {
-    emits('submit');
-  });
+const { loading: submitting, send: submit } = useRequest(
+  (data) => updateUserPasswordMethod(data, props.update),
+  { immediate: false },
+).onSuccess(({ data }) => {
+  emits('submit');
+});
 const formProps = reactive<VxeFormProps<FormModel>>({
   titleWidth: 100,
   titleAlign: 'right',
   titleColon: true,
   data: { userId: props.data.userId },
   items: [
+    {
+      visible: props.update,
+      field: 'old',
+      title: '旧密码',
+      span: 24,
+      itemRender: { name: 'VxeInput', props: { type: 'password' } },
+    },
     { field: 'password', title: '新密码', span: 24, itemRender: { name: 'VxeInput', props: { type: 'password' } } },
     { field: 'twice', title: '再次输入', span: 24, itemRender: { name: 'VxeInput', props: { type: 'password' } } },
     { align: 'center', span: 24, slots: { default: 'active' } },
   ],
   rules: {
+    old: [
+      { required: props.update, validator: 'ValidPassword' },
+    ],
     password: [
       { required: true, validator: 'ValidPassword' },
     ],

+ 8 - 1
src/components/UserPreview.vue

@@ -21,7 +21,10 @@ const { data, loading } = useRequest(
       <a-descriptions-item label="系统账号">{{ data.userId }}</a-descriptions-item>
       <a-descriptions-item label="角色" :span="2">{{ data.roles?.map(t => t.roleName)?.join(', ') }}
       </a-descriptions-item>
-      <a-descriptions-item label="医院 / 科室" :span="2">{{ data[ 'dept' ]?.deptName }}</a-descriptions-item>
+      <a-descriptions-item label="医院 / 科室" :span="2">
+        <span class="separate" v-if="data.dept?.ancestors">{{ data.dept?.ancestors }}</span>
+        <span class="separate" v-if="data.dept?.deptName && data.dept?.deptName !== data.dept?.ancestors">{{ data.dept?.deptName }}</span>
+      </a-descriptions-item>
       <a-descriptions-item label="工号">{{ data.jobnumber }}</a-descriptions-item>
       <a-descriptions-item label="姓名">{{ data.nickName }}</a-descriptions-item>
       <a-descriptions-item label="手机号码">{{ data.phonenumber }}</a-descriptions-item>
@@ -29,4 +32,8 @@ const { data, loading } = useRequest(
   </a-spin>
 </template>
 <style scoped lang="scss">
+.separate + .separate::before{
+  content: '/';
+  margin: 0 2px;
+}
 </style>

+ 23 - 1
src/components/UserQRCode.vue

@@ -3,10 +3,32 @@ import type { UserModel } from '@/model/system.model';
 
 
 const props = defineProps<{ dataset: UserModel }>();
+const loading = ref(false);
+
+async function handle() {
+  loading.value = true;
+  try {
+    const response = await fetch(props.dataset.appletImg);
+    const blob = await response.blob();
+    const url = window.URL.createObjectURL(blob);
+    const link = document.createElement('a');
+
+    link.href = url;
+    link.download = `${ props.dataset.nickName }专属小程序码.png`;
+    link.click();
+
+    setTimeout(() => window.URL.revokeObjectURL(url), 20);
+  } catch ( e ) {}
+  loading.value = false;
+}
 </script>
 <template>
   <div class="text-center" style="padding: 12px">
-    <a-image :src="props.dataset?.appletImg" :width="256" :height="256" :preview="false"></a-image>
+    <a-image
+      :src="props.dataset?.appletImg" :width="256" :height="256" :preview="false"
+      style="object-fit: scale-down;"
+    />
+    <a-button type="primary" block style="margin-top: 12px;" :loading="loading" @click="handle()">下载</a-button>
   </div>
 </template>
 <style scoped lang="scss"></style>

+ 4 - 3
src/libs/vxe/validator.ts

@@ -2,13 +2,15 @@ import { VxeUI } from 'vxe-pc-ui';
 
 // 手机号校验
 VxeUI.validators.add('ValidMobile', {
-  itemValidatorMethod({ itemValue }) {
+  itemValidatorMethod({ itemValue, rule }) {
+    if ( !rule.required ) return;
     if ( !itemValue ) return new Error(`请输入手机号码`);
     if ( !/^1[3-9]\d{9}$/.test(itemValue) ) return new Error('手机号码格式不正确');
   },
 });
 VxeUI.validators.add('ValidPassword', {
-  itemValidatorMethod({ itemValue }) {
+  itemValidatorMethod({ itemValue, rule }) {
+    if ( !rule.required ) return;
     if ( !itemValue ) return new Error(`请输入密码`);
     if ( !(
       itemValue.length > 8 &&
@@ -17,6 +19,5 @@ VxeUI.validators.add('ValidPassword', {
     ) ) {
       return new Error('密码格式不正确(由数字、字母组成,最少8位)');
     }
-
   },
 });

+ 2 - 0
src/model/system.model.ts

@@ -17,10 +17,12 @@ export interface RoleModel {
 export interface UserModel {
   userId: string;
   userName: string;
+  nickName?: string;
   phonenumber?: string;
   jobnumber?: string;
 
   roles?: any[];
+  dept?: Record<string, any>;
 
   appletImg: string;
 }

+ 2 - 0
src/pages/index.vue

@@ -79,12 +79,14 @@ function updateUserPassword(model: UserModel, index?: number) {
     slots: {
       default() {
         return h(UserPassword, <any> {
+          update: true,
           data: model, onSubmit(data?: UserModel) {
             notification.success({
               message: `重置用户: ${ userName } 的登录密码`,
               description: '操作成功',
             });
             VxeUI.modal.close(`user-edit-password-modal`);
+            router.push({ path: '/login' });
           },
         });
       },

+ 28 - 5
src/pages/index/patient/history.vue

@@ -1,4 +1,5 @@
 <script setup lang="ts">
+import ReportAnalysisCountEdit                   from '@/components/ReportAnalysisCountEdit.vue';
 import ReportHistoryPreview                      from '@/components/ReportHistoryPreview.vue';
 import type { PatientQuery, PatientReportModel } from '@/model';
 import { patientsHistoryMethod }                 from '@/request/api/patient.api';
@@ -93,24 +94,27 @@ const gridOptions = reactive<VxeGridProps<PatientReportModel>>({
     { field: 'name', title: '姓名', minWidth: 80 },
     { field: 'gender', title: '性别', minWidth: 40, formatter: 'gender' },
     { field: 'age', title: '年龄', minWidth: 40, formatter: ({ cellValue }) => cellValue ? `${ cellValue }岁` : '' },
-    { field: 'tags', title: '标签', minWidth: 160 },
-    { field: 'report.time', title: '最近一次健康分析时间', minWidth: 160 },
-    { field: 'createTime', title: '创建时间', minWidth: 160 },
+    { field: 'tags', title: '标签' },
+    { field: 'report.time', title: '最近一次健康分析时间' },
+    { field: 'createTime', title: '创建时间' },
     {
       title: '操作',
-      width: 200,
+      align: 'center',
+      width: 140,
       cellRender: {
         name: 'VxeButtonGroup',
         props: {
           mode: 'text',
         },
         options: [
-          { content: '健康档案', name: 'previewPatientHistoryRecord' },
+          { content: '健康档案', status: 'primary', name: 'previewPatientHistoryRecord' },
+          { content: '充值', status: 'warning', name: 'resetPatientAnalysisCount' },
         ],
         events: {
           click({ row, rowIndex }, { name }) {
             let method;
             if ( name === 'previewPatientHistoryRecord' ) { method = openHistoryPreviewHandle; }
+            else if ( name === 'resetPatientAnalysisCount' ) { method = openPatientAnalysisCountResetHandle; }
             method?.(row, rowIndex);
           },
         },
@@ -161,6 +165,25 @@ function openHistoryPreviewHandle({ report, ...patient }: PatientReportModel, in
     },
   });
 }
+
+function openPatientAnalysisCountResetHandle({ report, ...patient }: PatientReportModel) {
+  const id = `modal:patient-analysis-count:reset`;
+  const onDestroy = () => { VxeUI.modal.close(id); };
+  onDestroy();
+  VxeUI.modal.open({
+    id,
+    title: `充值`,
+    maskClosable: true,
+    escClosable: true,
+    slots: {
+      default() {
+        return h(ReportAnalysisCountEdit, {
+          patient, onDestroy,
+        });
+      },
+    },
+  })
+}
 </script>
 <template>
   <div class="page-container flex flex-col">

+ 9 - 8
src/pages/index/system/role.vue

@@ -74,13 +74,13 @@ const gridOptions = reactive<VxeGridProps<RoleModel>>({
   },
   columns: [
     { type: 'seq', width: 70, fixed: 'left' },
-    { field: 'roleName', title: '角色名称', minWidth: 160 },
-    { field: 'updateTime', title: '最近一次修改时间', minWidth: 160 },
-    { field: 'updateBy', title: '操作者', minWidth: 160 },
-    { field: 'createTime', title: '创建时间', minWidth: 160 },
-    { field: 'createBy', title: '创建者', minWidth: 160 },
+    { field: 'roleName', title: '角色名称' },
+    { field: 'updateTime', title: '最近一次修改时间' },
+    { field: 'updateBy', title: '操作者' },
+    { field: 'createTime', title: '创建时间' },
+    { field: 'createBy', title: '创建者' },
     {
-      field: 'status', title: '启用状态', minWidth: 100, cellRender: {
+      field: 'status', title: '启用状态', align: 'center', minWidth: 90, cellRender: {
         name: 'VxeSwitch',
         props: {
           openLabel: '启用', openValue: '0',
@@ -96,14 +96,15 @@ const gridOptions = reactive<VxeGridProps<RoleModel>>({
     },
     {
       title: '操作',
-      width: 200,
+      align: 'center',
+      width: 120,
       cellRender: {
         name: 'VxeButtonGroup',
         props: {
           mode: 'text',
         },
         options: [
-          { content: '修改', name: 'editRole' },
+          { content: '修改', status: 'warning', name: 'editRole' },
           { content: '删除', status: 'error', name: 'deleteRole' },
         ],
         events: {

+ 8 - 7
src/pages/index/system/tag.vue

@@ -85,12 +85,12 @@ const gridOptions = reactive<VxeGridProps<TagModel>>({
   },
   columns: [
     { type: 'seq', width: 70, fixed: 'left' },
-    { field: 'name', title: '标签名称', minWidth: 160 },
-    { field: 'parentName', title: '上级标签', minWidth: 160 },
-    { field: 'update_time', title: '最近一次修改时间', minWidth: 160 },
-    { field: 'user_name', title: '创建者', minWidth: 160 },
+    { field: 'name', title: '标签名称' },
+    { field: 'parentName', title: '上级标签' },
+    { field: 'updateTime', title: '最近一次修改时间' },
+    { field: 'nickName', title: '创建者' },
     {
-      field: 'status', title: '启用状态', minWidth: 100, cellRender: {
+      field: 'status', title: '启用状态', align: 'center', minWidth: 90, cellRender: {
         name: 'VxeSwitch',
         props: {
           openLabel: '启用', openValue: '0',
@@ -106,14 +106,15 @@ const gridOptions = reactive<VxeGridProps<TagModel>>({
     },
     {
       title: '操作',
-      width: 200,
+      align: 'center',
+      width: 120,
       cellRender: {
         name: 'VxeButtonGroup',
         props: {
           mode: 'text',
         },
         options: [
-          { content: '修改', name: 'editTag' },
+          { content: '修改', status: 'warning', name: 'editTag' },
           { content: '删除', status: 'error', name: 'deleteTag' },
         ],
         events: {

+ 20 - 13
src/pages/index/system/user.vue

@@ -5,8 +5,8 @@ import UserPreview                        from '@/components/UserPreview.vue';
 import UserQRCode                         from '@/components/UserQRCode.vue';
 import { type UserModel, type UserQuery } from '@/model/system.model';
 
-import { branchMethod, deleteUserMethod, userMethod, usersMethod } from '@/request/api/system.api';
-import { usePagination, useRequest }                               from 'alova/client';
+import { branchMethod, deleteUserMethod, usersMethod } from '@/request/api/system.api';
+import { usePagination, useRequest }                   from 'alova/client';
 import { notification }                                from 'ant-design-vue';
 
 import {
@@ -82,26 +82,33 @@ const gridOptions = reactive<VxeGridProps<UserModel>>({
   },
   columns: [
     { type: 'seq', width: 70, fixed: 'left' },
-    { field: 'userName', title: '系统账号', minWidth: 160 },
-    { field: 'nickName', title: '姓名', minWidth: 160 },
-    { field: 'dept.deptName', title: '医院 / 科室', minWidth: 160 },
-    { field: 'jobnumber', title: '工号', minWidth: 160 },
-    { field: 'phonenumber', title: '手机号码', minWidth: 160 },
+    { field: 'userName', title: '系统账号' },
+    { field: 'nickName', title: '姓名' },
     {
-      field: 'roles', title: '角色', minWidth: 160,
+      field: 'dept', title: '医院 / 科室',
+      formatter: ({ cellValue, row }) => [
+        row.dept?.ancestors,
+        row.dept?.deptName !== row.dept?.ancestors ? row.dept?.deptName : '',
+      ].filter(Boolean).join(' / '),
+    },
+    { field: 'jobnumber', title: '工号' },
+    { field: 'phonenumber', title: '手机号码' },
+    {
+      field: 'roles', title: '角色',
       formatter: ({ cellValue, row }) => row.roles?.map?.(t => t.roleName)?.join(', ') ?? '',
     },
     {
       title: '操作',
-      width: 200,
+      align: 'center',
+      width: 180,
       cellRender: {
         name: 'VxeButtonGroup',
         props: {
           mode: 'text',
         },
         options: [
-          { content: '小程序码', name: 'QRCode' },
-          { content: '修改', name: 'editUser' },
+          { content: '小程序码', status: 'primary', name: 'QRCode' },
+          { content: '修改', status: 'warning', name: 'editUser' },
           { content: '删除', status: 'error', name: 'deleteUser' },
         ],
         events: {
@@ -232,9 +239,9 @@ function updateUserPassword(model: UserModel, index?: number) {
 }
 
 function QRCode(model: UserModel) {
-  const { userName } = model;
+  const { nickName } = model;
   VxeUI.modal.open({
-    title: `${ userName } 专属小程序码`,
+    title: `${ nickName } 专属小程序码`,
     escClosable: true,
     destroyOnClose: true,
     id: `user-preview-qr-code`,

+ 22 - 0
src/request/api/patient.api.ts

@@ -63,3 +63,25 @@ export function patientTags(id: string) {
 export function updatePatientTagsMethod(id: string, data: string[]) {
   return request.Post(`/fdhb-pc/patientInfoManage/updatePatientTag`, { patientId: id, tagIds: data }, { name: 'update-tags' });
 }
+
+export function patientAnalysisCountMethod(id: string) {
+  return request.Get(`/fdhb-pc/patientInfoManage/rechargeUseDetail`, {
+    hitSource: 'update-analysis-count',
+    params: { patientId: id },
+    transform(data: any) {
+      return {
+        total: Math.max(0, data.usedCou),
+        count: Math.max(0, data.residuedCou),
+      };
+    },
+  });
+}
+
+export function updatePatientAnalysisCountMethod(id: string, count: number) {
+  return request.Get(`/fdhb-pc/patientInfoManage/rechargeUpdate`, {
+    name: 'update-analysis-count',
+    params: { patientId: id, residuedCou: count },
+    cacheFor: null,
+  });
+}
+

+ 6 - 2
src/request/api/system.api.ts

@@ -39,7 +39,11 @@ export function deleteUserMethod(data: Partial<UserModel>) {
   return request.Delete(`/prod-api/system/user/${ data.userId }`, { name: 'delete-user' });
 }
 
-export function updateUserPasswordMethod(data: Partial<UserModel>) {
+export function updateUserPasswordMethod(data: Record<string, any>, update = false) {
+  if ( update ) {
+    const params = { oldPassword: data.old, newPassword: data.password };
+    return request.Get(`/system/user/profile/updatePwd`, { params, cacheFor: null });
+  }
   return request.Put(`/prod-api/system/user/resetPwd`, data);
 }
 
@@ -106,7 +110,7 @@ export function getRoleMenusMethod(data?: Partial<RoleModel>) {
 export function tagsMethod(page: number, size: number, query?: TagQuery) {
   if ( Array.isArray(query?.parentIds) && query.parentIds.length === 1 ) {
     query.parentId = query.parentIds[ 0 ];
-  } else if ( query?.parentIds ) query.parentId = query?.parentIds;
+  } else if ( query?.parentIds ) query.parentId = query?.parentIds as string;
   return request.Post<List<TagModel>>(`/fdhb-pc/tagManage/pageTag`, query ?? {}, {
     hitSource: /tag$/,
     params: { pageNum: page, pageSize: size },

+ 6 - 0
src/themes/fix.scss

@@ -78,6 +78,12 @@
   align-items: center !important;
 }
 
+.ant-image {
+  img.ant-image-img {
+    object-fit: cover;
+  }
+}
+
 /* 设置滚动条的样式 */
 ::-webkit-scrollbar {
   width: 8px;

+ 3 - 3
src/widgets/AnalysisReportWidget.vue

@@ -64,10 +64,10 @@ const { data: indicator, loading: indicatorLoading } = useWatcher(
     <a-card class="card" size="small" title="舌象分析">
       <a-descriptions :column="3">
         <a-descriptions-item>
-          <a-image :width="200" :src="report.upImg" :preview="false" />
+          <a-image :width="200" :src="report.upImg" :preview="true" />
         </a-descriptions-item>
         <a-descriptions-item>
-          <a-image :width="200" :src="report.downImg" :preview="false" />
+          <a-image :width="200" :src="report.downImg" :preview="true" />
         </a-descriptions-item>
         <a-descriptions-item></a-descriptions-item>
       </a-descriptions>
@@ -140,7 +140,7 @@ const { data: indicator, loading: indicatorLoading } = useWatcher(
     <a-card class="card no-bordered" size="small" title="面象分析" v-if="report.faceAnalysisResult">
       <a-descriptions :column="3">
         <a-descriptions-item>
-          <a-image :width="200" :src="report.faceImg" :preview="false" />
+          <a-image :width="200" :src="report.faceImg" :preview="true" />
         </a-descriptions-item>
         <a-descriptions-item :span="2">{{ report.faceAnalysisResult }}</a-descriptions-item>
       </a-descriptions>

+ 1 - 1
src/widgets/ReportAnalysisWidgetFace.vue

@@ -18,7 +18,7 @@ const props = withDefaults(defineProps<{
   >
     <a-descriptions :column="3" size="small">
       <a-descriptions-item>
-        <a-image :width="200" :src="props.dataset.faceImg" :preview="false" />
+        <a-image :width="200" :src="props.dataset.faceImg" :preview="true" />
       </a-descriptions-item>
       <a-descriptions-item :span="2">{{ props.dataset.faceAnalysisResult }}</a-descriptions-item>
     </a-descriptions>

+ 3 - 3
src/widgets/ReportAnalysisWidgetTongue.vue

@@ -27,10 +27,10 @@ const exceptionData = computed(() => {
   <a-card class="card" size="small" :title="props.title" :loading="props.loading">
     <a-descriptions :column="3" size="small">
       <a-descriptions-item>
-        <a-image :width="200" :src="props.dataset.upImg" :preview="false" />
+        <a-image :width="200" :src="props.dataset.upImg" :preview="true" />
       </a-descriptions-item>
       <a-descriptions-item>
-        <a-image :width="200" :src="props.dataset.downImg" :preview="false" />
+        <a-image :width="200" :src="props.dataset.downImg" :preview="true" />
       </a-descriptions-item>
       <a-descriptions-item v-if="props.dataset.tongueAnalysisResult">
         <div class="flex flex-col">
@@ -119,7 +119,7 @@ const exceptionData = computed(() => {
           <a-descriptions :column="1" bordered size="small" :label-style="{width: '120px',textAlign:'center' }">
             <a-descriptions-item>
               <div class="flex flex-row">
-                <a-image v-if="panel.splitImage" :src="panel.splitImage" :width="200" :preview="false" />
+                <a-image v-if="panel.splitImage" :src="panel.splitImage" :width="200" :preview="true" />
                 <a-space v-if="panel.attrs" direction="vertical">
                   <a-tag v-for="v in panel.attrs" color="#cd201f" style="margin-left: 8px;margin-right: 0;">{{ v }}
                   </a-tag>

+ 4 - 4
src/widgets/ReportCardWidget.vue

@@ -127,7 +127,7 @@ defineExpose({
                   <a-descriptions :column="1" bordered size="small" :label-style="{width: '120px',textAlign:'center' }">
                     <a-descriptions-item>
                       <div class="flex flex-row">
-                        <a-image v-if="panel.splitImage" :src="panel.splitImage" :width="200" :preview="false" />
+                        <a-image v-if="panel.splitImage" :src="panel.splitImage" :width="200" :preview="true" />
                         <a-space v-if="panel.attrs" direction="vertical">
                           <a-tag v-for="v in panel.attrs" color="#cd201f" style="margin-left: 8px;margin-right: 0;">
                             {{ v }}
@@ -210,15 +210,15 @@ defineExpose({
                 <a-descriptions-item>{{ props.dataset.sublingualVein.standardValue }}</a-descriptions-item>
               </template>
             </a-descriptions>
-            <a-image :width="200" :height="200" :src="props.dataset.upImg" :preview="false" />
-            <a-image :width="200" :height="200" :src="props.dataset.downImg" :preview="false" />
+            <a-image :width="200" :height="200" :src="props.dataset.upImg" :preview="true" />
+            <a-image :width="200" :height="200" :src="props.dataset.downImg" :preview="true" />
           </a-space>
         </a-card>
         <template v-if="props.dataset?.faceAnalysisResult">
           <a-card class="card background" size="small" title="面象分析" :loading="props.loading">
             <a-space align="start" class="w-full analysis-wrapper">
               <div>{{ props.dataset.faceAnalysisResult }}</div>
-              <a-image :width="200" :height="200" :src="props.dataset.faceImg" :preview="false" />
+              <a-image :width="200" :height="200" :src="props.dataset.faceImg" :preview="true" />
             </a-space>
           </a-card>
         </template>