From 5f6bc93a46dc6bed28555f80694d8097b5c59a04 Mon Sep 17 00:00:00 2001 From: ShengLong <452591453@qq.com> Date: Fri, 24 Apr 2026 12:18:50 +0800 Subject: [PATCH 1/2] 1 --- admin/src/views/stats/conversion/index.vue | 1 + server/app/adminapi/logic/stats/ConversionLogic.php | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/admin/src/views/stats/conversion/index.vue b/admin/src/views/stats/conversion/index.vue index 17710931..79ad83f9 100644 --- a/admin/src/views/stats/conversion/index.vue +++ b/admin/src/views/stats/conversion/index.vue @@ -64,6 +64,7 @@ 今天 + 昨天 最近7天 最近30天 自定义 diff --git a/server/app/adminapi/logic/stats/ConversionLogic.php b/server/app/adminapi/logic/stats/ConversionLogic.php index a66c828e..ac29279a 100644 --- a/server/app/adminapi/logic/stats/ConversionLogic.php +++ b/server/app/adminapi/logic/stats/ConversionLogic.php @@ -147,6 +147,10 @@ class ConversionLogic $timeType = (string)($params['time_type'] ?? 'today'); switch ($timeType) { + case 'yesterday': + $startDate = date('Y-m-d', strtotime('-1 day')); + $endDate = $startDate; + break; case 'week': $startDate = date('Y-m-d', strtotime('-6 days')); $endDate = $today; From d408ffabe8c0554d5b918dd137d891658adedfa3 Mon Sep 17 00:00:00 2001 From: ShengLong <452591453@qq.com> Date: Fri, 24 Apr 2026 12:39:13 +0800 Subject: [PATCH 2/2] =?UTF-8?q?add=20=E4=B8=9A=E5=8A=A1=E8=AE=A2=E5=8D=95?= =?UTF-8?q?=E9=A2=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- admin/src/views/stats/conversion/index.vue | 1 + .../adminapi/logic/stats/ConversionLogic.php | 55 ++++++++++++++++--- 2 files changed, 48 insertions(+), 8 deletions(-) diff --git a/admin/src/views/stats/conversion/index.vue b/admin/src/views/stats/conversion/index.vue index 79ad83f9..e6a6f45e 100644 --- a/admin/src/views/stats/conversion/index.vue +++ b/admin/src/views/stats/conversion/index.vue @@ -354,6 +354,7 @@ const summaryCards: MetricCard[] = [ { key: 'interview_rate', label: '面诊率', type: 'percent' }, { key: 'receive_rate', label: '接诊率', type: 'percent' }, { key: 'interview_receive_rate', label: '面诊接诊率', type: 'percent' }, + { key: 'business_order_amount', label: '业务订单额', type: 'money' }, { key: 'completed_order_amount', label: '诊单金额', type: 'money' }, { key: 'avg_unit_price', label: '平均单价', type: 'money' }, { key: 'account_cost', label: '账户消耗', type: 'money' }, diff --git a/server/app/adminapi/logic/stats/ConversionLogic.php b/server/app/adminapi/logic/stats/ConversionLogic.php index ac29279a..a99be33a 100644 --- a/server/app/adminapi/logic/stats/ConversionLogic.php +++ b/server/app/adminapi/logic/stats/ConversionLogic.php @@ -306,6 +306,7 @@ class ConversionLogic 'free_appointment_count' => 0, 'appointment_total_count' => 0, 'interview_count' => 0, + 'business_order_amount' => 0.0, 'completed_order_amount' => 0.0, 'completed_order_count' => 0, 'account_cost' => 0.0, @@ -493,25 +494,25 @@ class ConversionLogic int $endTimestamp, ?array $mediaChannel ): void { - $sourceExpr = $dimension === 'doctor' ? 'rx.creator_id' : 'rx.assistant_id'; - $query = Db::name('tcm_prescription_order') + $completedSourceExpr = $dimension === 'doctor' ? 'rx.creator_id' : 'rx.assistant_id'; + $completedQuery = Db::name('tcm_prescription_order') ->alias('po') ->leftJoin('tcm_prescription rx', 'rx.id = po.prescription_id') ->leftJoin('tcm_diagnosis dg', 'dg.id = po.diagnosis_id') ->whereNull('po.delete_time') ->where('po.payment_slip_audit_status', 1) ->where('po.create_time', 'between', [$startTimestamp, $endTimestamp]) - ->fieldRaw("{$sourceExpr} AS source_admin_id, SUM(CASE WHEN po.prescription_audit_status = 1 THEN 1 ELSE 0 END) AS order_count, SUM(CASE WHEN po.prescription_audit_status = 1 THEN po.amount ELSE 0 END) AS total_amount") - ->group($sourceExpr); + ->fieldRaw("{$completedSourceExpr} AS source_admin_id, SUM(CASE WHEN po.prescription_audit_status = 1 THEN 1 ELSE 0 END) AS order_count, SUM(CASE WHEN po.prescription_audit_status = 1 THEN po.amount ELSE 0 END) AS total_amount") + ->group($completedSourceExpr); if ($mediaChannel !== null) { - $query->leftJoin('qywx_external_contact q', 'q.external_userid = dg.external_userid'); - MediaChannelService::applyFollowUsersChannelFilter($query, 'q.follow_users', $mediaChannel); + $completedQuery->leftJoin('qywx_external_contact q', 'q.external_userid = dg.external_userid'); + MediaChannelService::applyFollowUsersChannelFilter($completedQuery, 'q.follow_users', $mediaChannel); } - $rows = $query->select()->toArray(); + $completedRows = $completedQuery->select()->toArray(); - foreach ($rows as $row) { + foreach ($completedRows as $row) { $sourceAdminId = (int)($row['source_admin_id'] ?? 0); $mappedEntityIds = self::mapEntityIds($dimension, $sourceAdminId, $entityIds, $adminToDeptIds); @@ -527,6 +528,36 @@ class ConversionLogic $entities[$entityId]['completed_order_amount'] = round($entities[$entityId]['completed_order_amount'] + $amount, 2); } } + + $businessSourceExpr = $dimension === 'doctor' ? 'po.creator_id' : 'dg.assistant_id'; + $businessQuery = Db::name('tcm_prescription_order') + ->alias('po') + ->leftJoin('tcm_diagnosis dg', 'dg.id = po.diagnosis_id') + ->whereNull('po.delete_time') + ->where('po.create_time', 'between', [$startTimestamp, $endTimestamp]) + ->where('po.fulfillment_status', '<>', 4) + ->fieldRaw("{$businessSourceExpr} AS source_admin_id, SUM(po.amount) AS total_amount") + ->group($businessSourceExpr); + + if ($mediaChannel !== null) { + $businessQuery->leftJoin('qywx_external_contact q2', 'q2.external_userid = dg.external_userid'); + MediaChannelService::applyFollowUsersChannelFilter($businessQuery, 'q2.follow_users', $mediaChannel); + } + + $businessRows = $businessQuery->select()->toArray(); + + foreach ($businessRows as $row) { + $sourceAdminId = (int)($row['source_admin_id'] ?? 0); + $mappedEntityIds = self::mapEntityIds($dimension, $sourceAdminId, $entityIds, $adminToDeptIds); + if ($mappedEntityIds === []) { + continue; + } + + $amount = round((float)($row['total_amount'] ?? 0), 2); + foreach ($mappedEntityIds as $entityId) { + $entities[$entityId]['business_order_amount'] = round($entities[$entityId]['business_order_amount'] + $amount, 2); + } + } } /** @@ -597,6 +628,7 @@ class ConversionLogic $addFansCount = (int)$entity['add_fans_count']; $totalOpenCount = (int)$entity['total_open_count']; $completedOrderCount = (int)$entity['completed_order_count']; + $businessOrderAmount = round((float)$entity['business_order_amount'], 2); $completedOrderAmount = round((float)$entity['completed_order_amount'], 2); $accountCost = round((float)$entity['account_cost'], 2); $globalAccountCost = max($globalAccountCost, round((float)($entity['_global_account_cost'] ?? 0), 2)); @@ -605,6 +637,7 @@ class ConversionLogic $entity['paid_appointment_count'] = $paidAppointmentCount; $entity['free_appointment_count'] = $freeAppointmentCount; $entity['appointment_total_count'] = $appointmentTotalCount; + $entity['business_order_amount'] = $businessOrderAmount; $entity['completed_order_amount'] = $completedOrderAmount; $entity['account_cost'] = $effectiveAccountCost; $entity['paid_appointment_rate'] = self::percent($paidAppointmentCount, $addFansCount); @@ -686,6 +719,7 @@ class ConversionLogic $node['appointment_total_count'] += (int)$childNode['appointment_total_count']; $node['interview_count'] += (int)$childNode['interview_count']; $node['completed_order_count'] += (int)$childNode['completed_order_count']; + $node['business_order_amount'] = round((float)$node['business_order_amount'] + (float)$childNode['business_order_amount'], 2); $node['completed_order_amount'] = round((float)$node['completed_order_amount'] + (float)$childNode['completed_order_amount'], 2); $node['account_cost'] = round((float)$node['account_cost'] + (float)$childNode['account_cost'], 2); } @@ -801,6 +835,7 @@ class ConversionLogic $addFansCount = (int)$node['add_fans_count']; $totalOpenCount = (int)$node['total_open_count']; $completedOrderCount = (int)$node['completed_order_count']; + $businessOrderAmount = round((float)$node['business_order_amount'], 2); $completedOrderAmount = round((float)$node['completed_order_amount'], 2); $accountCost = round((float)$node['account_cost'], 2); $globalAccountCost = round((float)($node['_global_account_cost'] ?? 0), 2); @@ -809,6 +844,7 @@ class ConversionLogic $node['paid_appointment_count'] = $paidAppointmentCount; $node['free_appointment_count'] = $freeAppointmentCount; $node['appointment_total_count'] = $appointmentTotalCount; + $node['business_order_amount'] = $businessOrderAmount; $node['completed_order_amount'] = $completedOrderAmount; $node['account_cost'] = $effectiveAccountCost; $node['paid_appointment_rate'] = self::percent($paidAppointmentCount, $addFansCount); @@ -842,6 +878,7 @@ class ConversionLogic 'free_appointment_count' => 0, 'appointment_total_count' => 0, 'interview_count' => 0, + 'business_order_amount' => 0.0, 'completed_order_amount' => 0.0, 'completed_order_count' => 0, 'account_cost' => 0.0, @@ -857,6 +894,7 @@ class ConversionLogic $summary['appointment_total_count'] += (int)$row['appointment_total_count']; $summary['interview_count'] += (int)$row['interview_count']; $summary['completed_order_count'] += (int)$row['completed_order_count']; + $summary['business_order_amount'] = round($summary['business_order_amount'] + (float)($row['business_order_amount'] ?? 0), 2); $summary['completed_order_amount'] = round($summary['completed_order_amount'] + (float)$row['completed_order_amount'], 2); $globalAccountCost = max($globalAccountCost, round((float)($row['_global_account_cost'] ?? 0), 2)); } @@ -887,6 +925,7 @@ class ConversionLogic || (int)($row['appointment_total_count'] ?? 0) > 0 || (int)($row['interview_count'] ?? 0) > 0 || (int)($row['completed_order_count'] ?? 0) > 0 + || (float)($row['business_order_amount'] ?? 0) > 0 || (float)($row['completed_order_amount'] ?? 0) > 0; }