fix: 药师详情
Some checks failed
CI / Test (ubuntu-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Lint (ubuntu-latest) (push) Has been cancelled
CI / Lint (windows-latest) (push) Has been cancelled
CI / Check (ubuntu-latest) (push) Has been cancelled
CI / Check (windows-latest) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Website on push / Deploy Push Playground Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Docs Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Antd Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Element Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Naive Ftp (push) Has been cancelled
Release Drafter / update_release_draft (push) Has been cancelled
CI / CI OK (push) Has been cancelled
Lock Threads / action (push) Has been cancelled
Issue Close Require / close-issues (push) Has been cancelled
Close stale issues / stale (push) Has been cancelled

This commit is contained in:
2025-05-17 15:49:45 +08:00
parent a3a09d967e
commit 6445162b85
2 changed files with 255 additions and 13 deletions

View File

@@ -0,0 +1,220 @@
<script lang="ts" setup>
import { computed, ref } from 'vue';
import { useVbenModal } from '@vben/common-ui';
import { getPharmacistInfo } from '../api';
import { Image } from 'ant-design-vue';
const data = ref();
const loading = ref(false);
const error = ref('');
// 日期格式化工具函数
const formatDate = (dateStr: string) => {
if (!dateStr) return '';
return new Date(dateStr).toLocaleDateString('zh-CN', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
});
};
// 身份证号脱敏处理
const formatIdCard = (idCard: string) => {
if (!idCard) return '';
try {
// 假设需要Base64解码根据实际情况调整
const decoded = atob(idCard);
return `${decoded.slice(0, 6)}********${decoded.slice(14)}`;
} catch {
return idCard;
}
};
const [Modal, modalApi] = useVbenModal({
fullscreenButton: false,
draggable: true,
onCancel() {
modalApi.close();
},
onConfirm: async () => {
modalApi.close();
},
onOpenChange(isOpen: boolean) {
if (isOpen) {
const { values } = modalApi.getData<Record<string, any>>();
if (values && values.id) {
fetchPharmacistInfo(values.id);
}
}
},
});
// 获取药师信息
const fetchPharmacistInfo = async (id: number) => {
loading.value = true;
error.value = '';
try {
const res = await getPharmacistInfo(id);
data.value = res;
} catch (error_: any) {
error.value = error_.message || '获取药师信息失败';
} finally {
loading.value = false;
}
};
// 计算属性处理资格证图片URL
const qualificationImages = computed(() => {
if (!data.value?.pharmacist_practicing?.qualification) return [];
try {
// 解析资格证图片数组假设为JSON字符串
return JSON.parse(data.value.pharmacist_practicing.qualification);
} catch {
return [data.value.pharmacist_practicing.qualification];
}
});
</script>
<template>
<Modal v-if="data" class="w-[60%]" title="药师详情">
<!-- 加载状态 -->
<div v-if="loading" class="py-20 text-center">
<div
class="border-primary inline-block h-8 w-8 animate-spin rounded-full border-4 border-t-transparent"
></div>
<p class="mt-2 text-gray-500">正在加载药师信息...</p>
</div>
<!-- 错误状态 -->
<div v-else-if="error" class="py-20 text-center">
<div class="mb-2 text-3xl text-red-500">
<i class="fa fa-exclamation-circle"></i>
</div>
<p class="text-gray-600">{{ error }}</p>
<button
class="bg-primary hover:bg-primary/90 mt-4 rounded px-4 py-2 text-white transition"
@click="fetchPharmacistInfo(modalApi.getData().values.id)"
>
重试
</button>
</div>
<!-- 内容区域 -->
<div
v-else
class="mx-auto mt-8 max-w-4xl rounded-lg bg-white p-6 shadow-md md:p-10"
>
<!-- 头部信息栏 -->
<div class="mb-8 flex flex-col items-center">
<!-- 头像 -->
<div
class="mb-4 h-32 w-32 overflow-hidden rounded-full border-4 border-gray-200"
>
<Image
:src="data.avatar"
alt="药师头像"
class="h-full w-full object-cover"
onerror="this.src='https://picsum.photos/200/200'"
/>
</div>
<!-- 姓名及编号 -->
<h2 class="mb-2 text-2xl font-bold text-gray-800">
{{ data.name }}
<span class="ml-2 text-sm text-gray-500">药师编号: {{ data.id }}</span>
</h2>
<div class="text-sm text-gray-600">
注册时间: {{ formatDate(data.created_at) }}
<span class="ml-4">最近更新: {{ formatDate(data.updated_at) }}</span>
</div>
</div>
<!-- 基础信息卡片 -->
<div class="mb-8 rounded-lg bg-gray-50 p-6">
<h3 class="mb-4 text-lg font-medium text-gray-800">基础信息</h3>
<div class="grid grid-cols-1 gap-4 md:grid-cols-2">
<div class="flex items-center">
<span class="w-24 text-sm font-medium text-gray-600">姓名:</span>
<span class="text-gray-700">{{ data.name }}</span>
</div>
<div class="flex items-center">
<span class="w-24 text-sm font-medium text-gray-600">手机号:</span>
<span class="text-gray-700">{{ data.mobile }}</span>
</div>
<!-- <div class="flex items-center">-->
<!-- <span class="w-24 text-sm font-medium text-gray-600">身份证号:</span>-->
<!-- <span class="text-gray-700">{{ data.idcard }}</span>-->
<!-- </div>-->
<div class="flex items-center">
<span class="w-24 text-sm font-medium text-gray-600">门店ID:</span>
<span class="text-gray-700">{{ data.store_id }}</span>
</div>
<div class="flex items-center">
<span class="w-24 text-sm font-medium text-gray-600">状态:</span>
<span class="text-gray-700">
{{ data.service_user?.status === 2 ? '已审核' : '未审核' }}
</span>
</div>
</div>
</div>
<!-- 证件展示区域 -->
<div>
<h3 class="mb-4 text-lg font-medium text-gray-800">执业证件</h3>
<div class="grid grid-cols-1 gap-6 md:grid-cols-2">
<!-- 身份证正面 -->
<div class="rounded-lg border p-4 transition-all hover:shadow-lg">
<h4 class="mb-2 text-sm font-medium text-gray-700">身份证正面</h4>
<Image
:src="data.identity?.card_up"
alt="身份证正面"
class="mb-2 h-48 w-full object-cover"
onerror="this.src='https://picsum.photos/400/300'"
/>
</div>
<!-- 身份证反面 -->
<div class="rounded-lg border p-4 transition-all hover:shadow-lg">
<h4 class="mb-2 text-sm font-medium text-gray-700">身份证反面</h4>
<Image
:src="data.identity?.card_down"
alt="身份证反面"
class="mb-2 h-48 w-full object-cover"
onerror="this.src='https://picsum.photos/400/300'"
/>
</div>
</div>
<!-- 执业药师资格证 -->
<div class="mt-6 grid grid-cols-1 gap-6 md:grid-cols-2">
<div
v-for="(img, index) in qualificationImages"
:key="index"
class="rounded-lg border p-4 transition-all hover:shadow-lg"
>
<h4 class="mb-2 text-sm font-medium text-gray-700">
{{ index === 0 ? '资格证封面' : '资格证详情页' }}
</h4>
<Image
:alt="index === 0 ? '资格证封面' : '资格证详情页'"
:src="img"
class="mb-2 h-48 w-full object-cover"
onerror="this.src='https://picsum.photos/400/300'"
/>
</div>
</div>
</div>
</div>
</Modal>
</template>
<style lang="scss">
/* 自定义样式 */
.hover-scale {
transition: transform 0.3s ease;
}
.hover-scale:hover {
transform: scale(1.02);
}
</style>

View File

@@ -13,6 +13,7 @@ import { TableAction } from '#/components/table-action';
import { auditApi, openPcWindowsApi, refuseApi } from './api';
import BindStore from './components/BindStoreModal.vue';
import FormModalDemo from './components/modal.vue';
import PharmacistDetail from './components/detail.vue';
import { formOptions } from './config/search';
import { gridOptions } from './config/table';
@@ -45,6 +46,10 @@ const [BindStoreModal, BindStoreModalApi] = useVbenModal({
connectedComponent: BindStore,
});
const [PharmacistDetailModal, PharmacistDetailModalApi] = useVbenModal({
connectedComponent: PharmacistDetail,
});
const showModal = (data = {}, isUpdate = false) => {
formModalApi.setData({
// 表单值
@@ -55,6 +60,14 @@ const showModal = (data = {}, isUpdate = false) => {
formModalApi.open();
};
const showPharmacistDetailModal = (data = {}) => {
PharmacistDetailModalApi.setData({
// 表单值
values: data,
});
PharmacistDetailModalApi.open();
};
const showBindStoreModal = (data: number) => {
BindStoreModalApi.setData({
// 表单值
@@ -90,6 +103,7 @@ const refuse = (id: number) => {
<Page auto-content-height title="药师管理">
<FormModal />
<BindStoreModal />
<PharmacistDetailModal />
<Grid>
<template #toolbar-buttons>
<TableAction
@@ -151,22 +165,12 @@ const refuse = (id: number) => {
<TableAction
:actions="[
{
label: '审核通过',
label: '查看',
type: 'link',
icon: 'uil:edit',
icon: 'marketeq:eye',
size: 'small',
ifShow: row.service_user?.status === 1,
// auth: ['pharmacist', 'sys:role:detail'],
onClick: audit.bind(null, row.id),
},
{
label: '拒绝审核',
type: 'link',
icon: 'uil:edit',
size: 'small',
ifShow: row.service_user?.status === 1,
// auth: ['pharmacist', 'sys:role:detail'],
onClick: refuse.bind(null, row.id),
onClick: showPharmacistDetailModal.bind(null, row),
},
// {
// label: '绑定诊所',
@@ -186,6 +190,24 @@ const refuse = (id: number) => {
// },
]"
:drop-down-actions="[
{
label: '审核通过',
type: 'link',
icon: 'uil:edit',
size: 'small',
ifShow: row.service_user?.status === 1,
// auth: ['pharmacist', 'sys:role:detail'],
onClick: audit.bind(null, row.id),
},
{
label: '拒绝审核',
type: 'link',
icon: 'uil:edit',
size: 'small',
ifShow: row.service_user?.status === 1,
// auth: ['pharmacist', 'sys:role:detail'],
onClick: refuse.bind(null, row.id),
},
// {
// label: '审核通过',
// type: 'link',