From fb8ae6878c0104f100fd98a5fda3f2e9a5e15a58 Mon Sep 17 00:00:00 2001 From: Guoxianpeng <744964089@qq.com> Date: Thu, 16 Apr 2026 10:31:54 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BB=9F=E8=AE=A1=E4=B8=AD=E5=BF=83-=E3=80=8B?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=83=A8=E9=97=A8=E7=BB=9F=E8=AE=A1=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- admin/src/api/doctor.ts | 12 + admin/src/views/doctor/dept-tongji.vue | 356 ++++++++++++++++++ .../doctor/StatisticsController.php | 9 + .../adminapi/lists/doctor/StatisticsLists.php | 77 ++++ 4 files changed, 454 insertions(+) create mode 100644 admin/src/views/doctor/dept-tongji.vue diff --git a/admin/src/api/doctor.ts b/admin/src/api/doctor.ts index a96b2cd1..c05892d0 100644 --- a/admin/src/api/doctor.ts +++ b/admin/src/api/doctor.ts @@ -82,3 +82,15 @@ export function completeAppointment(params: any) { export function getDoctorStatistics(params: any) { return request.get({ url: '/doctor.statistics/lists', params }) } + +// ========== 部门统计 ========== + +// 获取部门列表 +export function getDeptList() { + return request.get({ url: '/dept.dept/all' }) +} + +// 获取部门统计 +export function getDeptStatistics(params: any) { + return request.get({ url: '/doctor.statistics/deptLists', params }) +} diff --git a/admin/src/views/doctor/dept-tongji.vue b/admin/src/views/doctor/dept-tongji.vue new file mode 100644 index 00000000..dc4d87fe --- /dev/null +++ b/admin/src/views/doctor/dept-tongji.vue @@ -0,0 +1,356 @@ + + + + + + + 筛选条件 + + + + + + + + + + + + 今天 + 最近7天 + 最近30天 + 自定义 + + + + + + + + + 查询 + 重置 + + + + + + + + + 部门统计数据 + + + + + + + + + + + + + + 已挂号: {{ row.registered_count }} + + + 已完成: {{ row.completed_count }} + + + 已取消: {{ row.canceled_count }} + + + 已过号: {{ row.expired_count }} + + + 总数量: {{ row.total_count }} + + + 完成率: {{ row.completion_rate }}% + + + + + + + + + + + + + + + + + + + diff --git a/server/app/adminapi/controller/doctor/StatisticsController.php b/server/app/adminapi/controller/doctor/StatisticsController.php index 97b2b8a9..b312a3e5 100644 --- a/server/app/adminapi/controller/doctor/StatisticsController.php +++ b/server/app/adminapi/controller/doctor/StatisticsController.php @@ -20,4 +20,13 @@ class StatisticsController extends BaseAdminController { return $this->dataLists(new StatisticsLists()); } + + /** + * @notes 部门统计列表 + * @return \think\response\Json + */ + public function deptLists() + { + return $this->dataLists(new StatisticsLists('dept')); + } } diff --git a/server/app/adminapi/lists/doctor/StatisticsLists.php b/server/app/adminapi/lists/doctor/StatisticsLists.php index e5840337..9139014c 100644 --- a/server/app/adminapi/lists/doctor/StatisticsLists.php +++ b/server/app/adminapi/lists/doctor/StatisticsLists.php @@ -13,6 +13,17 @@ use app\common\model\auth\Admin; */ class StatisticsLists extends BaseAdminDataLists { + protected $type = 'doctor'; + + /** + * @param string $type 统计类型:doctor(医生统计) 或 dept(部门统计) + */ + public function __construct($type = 'doctor') + { + parent::__construct(); + $this->type = $type; + } + /** * @notes 搜索条件 * @return array @@ -28,6 +39,10 @@ class StatisticsLists extends BaseAdminDataLists */ public function lists(): array { + if ($this->type === 'dept') { + return $this->getDeptStatistics(); + } + $doctorId = $this->params['doctor_id'] ?? ''; $timeType = $this->params['time_type'] ?? 'today'; $startDate = $this->params['start_date'] ?? ''; @@ -377,6 +392,68 @@ class StatisticsLists extends BaseAdminDataLists return $result; } + /** + * @notes 获取部门统计数据 + * @return array + */ + private function getDeptStatistics() + { + $deptId = $this->params['dept_id'] ?? ''; + $timeType = $this->params['time_type'] ?? 'today'; + $startDate = $this->params['start_date'] ?? ''; + $endDate = $this->params['end_date'] ?? ''; + + // 计算时间范围 + list($startDate, $endDate, $timeRangeText) = $this->getTimeRange($timeType, $startDate, $endDate); + + // 查询部门统计数据 + $deptStatsQuery = \think\facade\Db::name('doctor_appointment') + ->alias('apt') + ->leftJoin('zyt_admin_dept ad', 'apt.assistant_id = ad.admin_id') + ->leftJoin('zyt_dept dept', 'ad.dept_id = dept.id') + ->field([ + 'dept.id as dept_id', + 'dept.name as dept_name', + 'COUNT(*) as total_count', + 'SUM(CASE WHEN apt.status = 1 THEN 1 ELSE 0 END) as registered_count', + 'SUM(CASE WHEN apt.status = 3 THEN 1 ELSE 0 END) as completed_count', + 'SUM(CASE WHEN apt.status = 2 THEN 1 ELSE 0 END) as canceled_count', + 'SUM(CASE WHEN apt.status = 4 THEN 1 ELSE 0 END) as expired_count' + ]) + ->where('apt.appointment_date', '>=', $startDate) + ->where('apt.appointment_date', '<=', $endDate) + ->whereNotNull('dept.id'); + + if ($deptId) { + $deptStatsQuery->where('dept.id', $deptId); + } + + $deptStats = $deptStatsQuery->group('dept.id')->select()->toArray(); + + // 组装结果 + $result = []; + foreach ($deptStats as $stat) { + // 计算完成率 + $completionRate = $stat['total_count'] > 0 + ? round(($stat['completed_count'] / $stat['total_count']) * 100, 2) + : 0; + + $result[] = [ + 'dept_id' => $stat['dept_id'], + 'dept_name' => $stat['dept_name'], + 'total_count' => (int)$stat['total_count'] ?? 0, + 'registered_count' => (int)$stat['registered_count'] ?? 0, + 'completed_count' => (int)$stat['completed_count'] ?? 0, + 'canceled_count' => (int)$stat['canceled_count'] ?? 0, + 'expired_count' => (int)$stat['expired_count'] ?? 0, + 'completion_rate' => $completionRate, + 'time_range' => $timeRangeText + ]; + } + + return $result; + } + /** * @notes 获取时间范围 * @param string $timeType