调整综合转化统计医生维度口径

This commit is contained in:
2026-07-02 11:55:15 +08:00
parent e2a1e62867
commit 4a17fe8a0c
2 changed files with 213 additions and 92 deletions
+142 -58
View File
@@ -129,7 +129,7 @@
<el-card class="!border-none" shadow="never"> <el-card class="!border-none" shadow="never">
<template #header> <template #header>
<div class="card-header"> <div class="card-header">
<span>诊单金额占比</span> <span>{{ amountPieTitle }}</span>
<span class="card-hint">TOP 10</span> <span class="card-hint">TOP 10</span>
</div> </div>
</template> </template>
@@ -146,17 +146,17 @@
<el-card class="!border-none" shadow="never"> <el-card class="!border-none" shadow="never">
<template #header> <template #header>
<div class="card-header"> <div class="card-header">
<span>加粉占比</span> <span>{{ secondaryPieTitle }}</span>
<span class="card-hint">TOP 10</span> <span class="card-hint">TOP 10</span>
</div> </div>
</template> </template>
<v-charts <v-charts
v-if="fanPieHasData" v-if="secondaryPieHasData"
class="stats-chart" class="stats-chart"
:option="fanPieOption" :option="secondaryPieOption"
autoresize autoresize
/> />
<el-empty v-else description="暂无加粉数据" /> <el-empty v-else :description="secondaryPieEmptyText" />
</el-card> </el-card>
</el-col> </el-col>
</el-row> </el-row>
@@ -311,10 +311,13 @@ const overview = reactive<Record<string, any>>({
amounts: [], amounts: [],
order_counts: [], order_counts: [],
fan_counts: [], fan_counts: [],
rois: [] rois: [],
appointment_counts: [],
interview_counts: []
}, },
amount_share: [], amount_share: [],
fan_share: [] fan_share: [],
order_share: []
} }
}) })
@@ -392,7 +395,7 @@ const currentEntityId = computed({
} }
}) })
const summaryCards: MetricCard[] = [ const defaultSummaryCards: MetricCard[] = [
{ key: 'add_fans_count', label: '加粉数', type: 'count' }, { key: 'add_fans_count', label: '加粉数', type: 'count' },
{ key: 'paid_appointment_count', label: '付费挂号', type: 'count' }, { key: 'paid_appointment_count', label: '付费挂号', type: 'count' },
{ key: 'free_appointment_count', label: '免费挂号', type: 'count' }, { key: 'free_appointment_count', label: '免费挂号', type: 'count' },
@@ -410,7 +413,15 @@ const summaryCards: MetricCard[] = [
{ key: 'roi', label: 'ROI', type: 'ratio' } { key: 'roi', label: 'ROI', type: 'ratio' }
] ]
const tableColumns: MetricColumn[] = [ const doctorSummaryCards: MetricCard[] = [
{ key: 'appointment_total_count', label: '挂号数', type: 'count' },
{ key: 'interview_count', label: '面诊数', type: 'count' },
{ key: 'completed_order_count', label: '接诊单数', type: 'count' },
{ key: 'completed_order_amount', label: '开药金额', type: 'money' },
{ key: 'receive_rate', label: '接诊率', type: 'percent' }
]
const defaultTableColumns: MetricColumn[] = [
{ key: 'add_fans_count', label: '加粉数', type: 'count' }, { key: 'add_fans_count', label: '加粉数', type: 'count' },
{ key: 'total_open_count', label: '总开口', type: 'count', placeholder: true }, { key: 'total_open_count', label: '总开口', type: 'count', placeholder: true },
{ key: 'unreplied_count', label: '未回复', type: 'count', placeholder: true }, { key: 'unreplied_count', label: '未回复', type: 'count', placeholder: true },
@@ -431,6 +442,18 @@ const tableColumns: MetricColumn[] = [
{ key: 'roi', label: 'ROI', type: 'ratio', minWidth: 90 } { key: 'roi', label: 'ROI', type: 'ratio', minWidth: 90 }
] ]
const doctorTableColumns: MetricColumn[] = [
{ key: 'appointment_total_count', label: '挂号数', type: 'count' },
{ key: 'interview_count', label: '面诊数', type: 'count' },
{ key: 'completed_order_count', label: '接诊单数', type: 'count' },
{ key: 'completed_order_amount', label: '开药金额', type: 'money', minWidth: 120 },
{ key: 'receive_rate', label: '接诊率', type: 'percent', minWidth: 100 }
]
const isDoctorDimension = computed(() => queryParams.dimension === 'doctor')
const summaryCards = computed(() => isDoctorDimension.value ? doctorSummaryCards : defaultSummaryCards)
const tableColumns = computed(() => isDoctorDimension.value ? doctorTableColumns : defaultTableColumns)
const dateRangeText = computed(() => { const dateRangeText = computed(() => {
if (!overview.date_range?.length) return '未选择' if (!overview.date_range?.length) return '未选择'
return `${overview.date_range[0]}${overview.date_range[1]}` return `${overview.date_range[0]}${overview.date_range[1]}`
@@ -438,7 +461,14 @@ const dateRangeText = computed(() => {
const rankingChartHasData = computed(() => overview.charts.ranking.names.length > 0) const rankingChartHasData = computed(() => overview.charts.ranking.names.length > 0)
const amountPieHasData = computed(() => overview.charts.amount_share.length > 0) const amountPieHasData = computed(() => overview.charts.amount_share.length > 0)
const fanPieHasData = computed(() => overview.charts.fan_share.length > 0) const secondaryPieHasData = computed(() =>
isDoctorDimension.value
? (overview.charts.order_share?.length || 0) > 0
: (overview.charts.fan_share?.length || 0) > 0
)
const amountPieTitle = computed(() => isDoctorDimension.value ? '开药金额占比' : '诊单金额占比')
const secondaryPieTitle = computed(() => isDoctorDimension.value ? '接诊单数占比' : '加粉占比')
const secondaryPieEmptyText = computed(() => isDoctorDimension.value ? '暂无接诊数据' : '暂无加粉数据')
const rankingChartData = computed(() => { const rankingChartData = computed(() => {
const ranking = overview.charts?.ranking || {} const ranking = overview.charts?.ranking || {}
@@ -448,56 +478,110 @@ const rankingChartData = computed(() => {
return { return {
names, names,
amounts: normalize(Array.isArray(ranking.amounts) ? ranking.amounts : []), amounts: normalize(Array.isArray(ranking.amounts) ? ranking.amounts : []),
appointmentCounts: normalize(Array.isArray(ranking.appointment_counts) ? ranking.appointment_counts : []),
interviewCounts: normalize(Array.isArray(ranking.interview_counts) ? ranking.interview_counts : []),
orderCounts: normalize(Array.isArray(ranking.order_counts) ? ranking.order_counts : []), orderCounts: normalize(Array.isArray(ranking.order_counts) ? ranking.order_counts : []),
fanCounts: normalize(Array.isArray(ranking.fan_counts) ? ranking.fan_counts : []), fanCounts: normalize(Array.isArray(ranking.fan_counts) ? ranking.fan_counts : [])
} }
}) })
const rankingChartOption = computed(() => ({ const rankingChartOption = computed(() => {
tooltip: { trigger: 'axis' }, const common = {
legend: { data: ['诊单金额', '接诊诊单', '加粉数'] }, tooltip: { trigger: 'axis' },
grid: { left: 48, right: 24, top: 48, bottom: 48 }, grid: { left: 48, right: 24, top: 48, bottom: 48 },
xAxis: { xAxis: {
type: 'category', type: 'category',
data: rankingChartData.value.names, data: rankingChartData.value.names,
axisLabel: { axisLabel: {
interval: 0, interval: 0,
rotate: rankingChartData.value.names.length > 6 ? 25 : 0 rotate: rankingChartData.value.names.length > 6 ? 25 : 0
} }
},
yAxis: [
{ type: 'value', name: '金额 / 数量' }
],
series: [
{
name: '诊单金额',
type: 'bar',
barMaxWidth: 36,
data: rankingChartData.value.amounts,
itemStyle: { color: '#4a78ff' }
}, },
{ yAxis: [
name: '接诊诊单', { type: 'value', name: '金额 / 数量' }
type: 'line', ]
smooth: true, }
showSymbol: true,
symbolSize: 8, if (!isDoctorDimension.value) {
lineStyle: { width: 3 }, return {
data: rankingChartData.value.orderCounts, ...common,
itemStyle: { color: '#15b8a6' } legend: { data: ['诊单金额', '接诊诊单', '加粉数'] },
}, series: [
{ {
name: '加粉数', name: '诊单金额',
type: 'line', type: 'bar',
smooth: true, barMaxWidth: 36,
showSymbol: true, data: rankingChartData.value.amounts,
symbolSize: 8, itemStyle: { color: '#4a78ff' }
lineStyle: { width: 3 }, },
data: rankingChartData.value.fanCounts, {
itemStyle: { color: '#ff9f43' } name: '接诊诊单',
type: 'line',
smooth: true,
showSymbol: true,
symbolSize: 8,
lineStyle: { width: 3 },
data: rankingChartData.value.orderCounts,
itemStyle: { color: '#15b8a6' }
},
{
name: '加粉数',
type: 'line',
smooth: true,
showSymbol: true,
symbolSize: 8,
lineStyle: { width: 3 },
data: rankingChartData.value.fanCounts,
itemStyle: { color: '#ff9f43' }
}
]
} }
] }
}))
return {
...common,
legend: { data: ['开药金额', '挂号数', '面诊数', '接诊单数'] },
series: [
{
name: '开药金额',
type: 'bar',
barMaxWidth: 36,
data: rankingChartData.value.amounts,
itemStyle: { color: '#4a78ff' }
},
{
name: '挂号数',
type: 'line',
smooth: true,
showSymbol: true,
symbolSize: 8,
lineStyle: { width: 3 },
data: rankingChartData.value.appointmentCounts,
itemStyle: { color: '#15b8a6' }
},
{
name: '面诊数',
type: 'line',
smooth: true,
showSymbol: true,
symbolSize: 8,
lineStyle: { width: 3 },
data: rankingChartData.value.interviewCounts,
itemStyle: { color: '#ff9f43' }
},
{
name: '接诊单数',
type: 'line',
smooth: true,
showSymbol: true,
symbolSize: 8,
lineStyle: { width: 3 },
data: rankingChartData.value.orderCounts,
itemStyle: { color: '#7c3aed' }
}
]
}
})
const amountPieOption = computed(() => ({ const amountPieOption = computed(() => ({
tooltip: { trigger: 'item' }, tooltip: { trigger: 'item' },
@@ -511,7 +595,7 @@ const amountPieOption = computed(() => ({
}, },
series: [ series: [
{ {
name: '诊单金额', name: amountPieTitle.value,
type: 'pie', type: 'pie',
radius: ['42%', '70%'], radius: ['42%', '70%'],
center: ['50%', '42%'], center: ['50%', '42%'],
@@ -531,7 +615,7 @@ const amountPieOption = computed(() => ({
] ]
})) }))
const fanPieOption = computed(() => ({ const secondaryPieOption = computed(() => ({
tooltip: { trigger: 'item' }, tooltip: { trigger: 'item' },
legend: { legend: {
bottom: 0, bottom: 0,
@@ -543,7 +627,7 @@ const fanPieOption = computed(() => ({
}, },
series: [ series: [
{ {
name: '加粉数', name: secondaryPieTitle.value,
type: 'pie', type: 'pie',
radius: ['42%', '70%'], radius: ['42%', '70%'],
center: ['50%', '42%'], center: ['50%', '42%'],
@@ -558,7 +642,7 @@ const fanPieOption = computed(() => ({
labelLayout: { labelLayout: {
hideOverlap: true, hideOverlap: true,
}, },
data: overview.charts.fan_share data: isDoctorDimension.value ? overview.charts.order_share : overview.charts.fan_share
} }
] ]
})) }))
@@ -48,8 +48,8 @@ class ConversionLogic
$emptyResult = [ $emptyResult = [
'dimension' => $dimension, 'dimension' => $dimension,
'date_range' => [$startDate, $endDate], 'date_range' => [$startDate, $endDate],
'summary' => self::buildSummary([]), 'summary' => self::buildSummary([], $dimension),
'charts' => self::buildCharts([]), 'charts' => self::buildCharts([], $dimension),
'lists' => [], 'lists' => [],
'count' => 0, 'count' => 0,
'page_no' => $pageNo, 'page_no' => $pageNo,
@@ -57,8 +57,8 @@ class ConversionLogic
'extend' => [ 'extend' => [
'dimension' => $dimension, 'dimension' => $dimension,
'date_range' => [$startDate, $endDate], 'date_range' => [$startDate, $endDate],
'summary' => self::buildSummary([]), 'summary' => self::buildSummary([], $dimension),
'charts' => self::buildCharts([]), 'charts' => self::buildCharts([], $dimension),
], ],
]; ];
if ($includeFilters) { if ($includeFilters) {
@@ -75,8 +75,8 @@ class ConversionLogic
$result = [ $result = [
'dimension' => $dimension, 'dimension' => $dimension,
'date_range' => [$startDate, $endDate], 'date_range' => [$startDate, $endDate],
'summary' => self::buildSummary([]), 'summary' => self::buildSummary([], $dimension),
'charts' => self::buildCharts([]), 'charts' => self::buildCharts([], $dimension),
'lists' => [], 'lists' => [],
'count' => 0, 'count' => 0,
'page_no' => $pageNo, 'page_no' => $pageNo,
@@ -84,8 +84,8 @@ class ConversionLogic
'extend' => [ 'extend' => [
'dimension' => $dimension, 'dimension' => $dimension,
'date_range' => [$startDate, $endDate], 'date_range' => [$startDate, $endDate],
'summary' => self::buildSummary([]), 'summary' => self::buildSummary([], $dimension),
'charts' => self::buildCharts([]), 'charts' => self::buildCharts([], $dimension),
], ],
]; ];
if ($includeFilters) { if ($includeFilters) {
@@ -124,8 +124,8 @@ class ConversionLogic
$result = [ $result = [
'dimension' => $dimension, 'dimension' => $dimension,
'date_range' => [$startDate, $endDate], 'date_range' => [$startDate, $endDate],
'summary' => self::buildSummary([]), 'summary' => self::buildSummary([], $dimension),
'charts' => self::buildCharts([]), 'charts' => self::buildCharts([], $dimension),
'lists' => [], 'lists' => [],
'count' => 0, 'count' => 0,
'page_no' => $pageNo, 'page_no' => $pageNo,
@@ -133,8 +133,8 @@ class ConversionLogic
'extend' => [ 'extend' => [
'dimension' => $dimension, 'dimension' => $dimension,
'date_range' => [$startDate, $endDate], 'date_range' => [$startDate, $endDate],
'summary' => self::buildSummary([]), 'summary' => self::buildSummary([], $dimension),
'charts' => self::buildCharts([]), 'charts' => self::buildCharts([], $dimension),
], ],
]; ];
if ($includeFilters) { if ($includeFilters) {
@@ -191,8 +191,8 @@ class ConversionLogic
$result = [ $result = [
'dimension' => $dimension, 'dimension' => $dimension,
'date_range' => [$startDate, $endDate], 'date_range' => [$startDate, $endDate],
'summary' => self::buildSummary($allRows), 'summary' => self::buildSummary($allRows, $dimension),
'charts' => self::buildCharts($chartRows), 'charts' => self::buildCharts($chartRows, $dimension),
'lists' => $pagedRows, 'lists' => $pagedRows,
'count' => count($allRows), 'count' => count($allRows),
'page_no' => $pageNo, 'page_no' => $pageNo,
@@ -200,8 +200,8 @@ class ConversionLogic
'extend' => [ 'extend' => [
'dimension' => $dimension, 'dimension' => $dimension,
'date_range' => [$startDate, $endDate], 'date_range' => [$startDate, $endDate],
'summary' => self::buildSummary($allRows), 'summary' => self::buildSummary($allRows, $dimension),
'charts' => self::buildCharts($chartRows), 'charts' => self::buildCharts($chartRows, $dimension),
], ],
]; ];
if ($includeFilters) { if ($includeFilters) {
@@ -226,8 +226,8 @@ class ConversionLogic
$result = [ $result = [
'dimension' => $dimension, 'dimension' => $dimension,
'date_range' => [$startDate, $endDate], 'date_range' => [$startDate, $endDate],
'summary' => self::buildSummary($rows), 'summary' => self::buildSummary($rows, $dimension),
'charts' => self::buildCharts($rows), 'charts' => self::buildCharts($rows, $dimension),
'lists' => array_slice($rows, $offset, $pageSize), 'lists' => array_slice($rows, $offset, $pageSize),
'count' => $count, 'count' => $count,
'page_no' => $pageNo, 'page_no' => $pageNo,
@@ -235,8 +235,8 @@ class ConversionLogic
'extend' => [ 'extend' => [
'dimension' => $dimension, 'dimension' => $dimension,
'date_range' => [$startDate, $endDate], 'date_range' => [$startDate, $endDate],
'summary' => self::buildSummary($rows), 'summary' => self::buildSummary($rows, $dimension),
'charts' => self::buildCharts($rows), 'charts' => self::buildCharts($rows, $dimension),
], ],
]; ];
if ($includeFilters) { if ($includeFilters) {
@@ -1226,7 +1226,7 @@ class ConversionLogic
$entity['paid_appointment_rate'] = self::percent($paidAppointmentCount, $addFansCount); $entity['paid_appointment_rate'] = self::percent($paidAppointmentCount, $addFansCount);
$entity['open_appointment_rate'] = self::percent($paidAppointmentCount, $totalOpenCount); $entity['open_appointment_rate'] = self::percent($paidAppointmentCount, $totalOpenCount);
$entity['interview_rate'] = self::percent($interviewCount, $appointmentTotalCount); $entity['interview_rate'] = self::percent($interviewCount, $appointmentTotalCount);
$entity['receive_rate'] = self::percent($completedOrderCount, $addFansCount); $entity['receive_rate'] = self::receiveRate($completedOrderCount, $addFansCount, $interviewCount, $dimension);
$entity['interview_receive_rate'] = self::percent($completedOrderCount, $interviewCount); $entity['interview_receive_rate'] = self::percent($completedOrderCount, $interviewCount);
$entity['open_receive_rate'] = self::percent($completedOrderCount, $totalOpenCount); $entity['open_receive_rate'] = self::percent($completedOrderCount, $totalOpenCount);
$entity['avg_unit_price'] = self::safeDivideMoney($completedOrderAmount, $completedOrderCount); $entity['avg_unit_price'] = self::safeDivideMoney($completedOrderAmount, $completedOrderCount);
@@ -1459,7 +1459,7 @@ class ConversionLogic
$node['paid_appointment_rate'] = self::percent($paidAppointmentCount, $addFansCount); $node['paid_appointment_rate'] = self::percent($paidAppointmentCount, $addFansCount);
$node['open_appointment_rate'] = self::percent($paidAppointmentCount, $totalOpenCount); $node['open_appointment_rate'] = self::percent($paidAppointmentCount, $totalOpenCount);
$node['interview_rate'] = self::percent($interviewCount, $appointmentTotalCount); $node['interview_rate'] = self::percent($interviewCount, $appointmentTotalCount);
$node['receive_rate'] = self::percent($completedOrderCount, $addFansCount); $node['receive_rate'] = self::receiveRate($completedOrderCount, $addFansCount, $interviewCount, 'dept');
$node['interview_receive_rate'] = self::percent($completedOrderCount, $interviewCount); $node['interview_receive_rate'] = self::percent($completedOrderCount, $interviewCount);
$node['open_receive_rate'] = self::percent($completedOrderCount, $totalOpenCount); $node['open_receive_rate'] = self::percent($completedOrderCount, $totalOpenCount);
$node['avg_unit_price'] = self::safeDivideMoney($completedOrderAmount, $completedOrderCount); $node['avg_unit_price'] = self::safeDivideMoney($completedOrderAmount, $completedOrderCount);
@@ -2010,7 +2010,12 @@ class ConversionLogic
'paid_appointment_rate' => self::percent($paidAppointmentCount, $addFansCount), 'paid_appointment_rate' => self::percent($paidAppointmentCount, $addFansCount),
'open_appointment_rate' => self::percent($paidAppointmentCount, $totalOpenCount), 'open_appointment_rate' => self::percent($paidAppointmentCount, $totalOpenCount),
'interview_rate' => self::percent($interviewCount, $appointmentTotalCount), 'interview_rate' => self::percent($interviewCount, $appointmentTotalCount),
'receive_rate' => self::percent($completedOrderCount, $addFansCount), 'receive_rate' => self::receiveRate(
$completedOrderCount,
$addFansCount,
$interviewCount,
'member'
),
'interview_receive_rate' => self::percent($completedOrderCount, $interviewCount), 'interview_receive_rate' => self::percent($completedOrderCount, $interviewCount),
'open_receive_rate' => self::percent($completedOrderCount, $totalOpenCount), 'open_receive_rate' => self::percent($completedOrderCount, $totalOpenCount),
'avg_unit_price' => self::safeDivideMoney($completedOrderAmount, $completedOrderCount), 'avg_unit_price' => self::safeDivideMoney($completedOrderAmount, $completedOrderCount),
@@ -2149,7 +2154,7 @@ class ConversionLogic
* @param array<int, array<string, mixed>> $rows * @param array<int, array<string, mixed>> $rows
* @return array<string, mixed> * @return array<string, mixed>
*/ */
private static function buildSummary(array $rows): array private static function buildSummary(array $rows, string $dimension = 'dept'): array
{ {
$summary = [ $summary = [
'add_fans_count' => 0, 'add_fans_count' => 0,
@@ -2181,7 +2186,12 @@ class ConversionLogic
$summary['paid_appointment_rate'] = self::percent($summary['paid_appointment_count'], $summary['add_fans_count']); $summary['paid_appointment_rate'] = self::percent($summary['paid_appointment_count'], $summary['add_fans_count']);
$summary['open_appointment_rate'] = self::percent($summary['paid_appointment_count'], $summary['total_open_count']); $summary['open_appointment_rate'] = self::percent($summary['paid_appointment_count'], $summary['total_open_count']);
$summary['interview_rate'] = self::percent($summary['interview_count'], $summary['appointment_total_count']); $summary['interview_rate'] = self::percent($summary['interview_count'], $summary['appointment_total_count']);
$summary['receive_rate'] = self::percent($summary['completed_order_count'], $summary['add_fans_count']); $summary['receive_rate'] = self::receiveRate(
$summary['completed_order_count'],
$summary['add_fans_count'],
$summary['interview_count'],
$dimension
);
$summary['interview_receive_rate'] = self::percent($summary['completed_order_count'], $summary['interview_count']); $summary['interview_receive_rate'] = self::percent($summary['completed_order_count'], $summary['interview_count']);
$summary['open_receive_rate'] = self::percent($summary['completed_order_count'], $summary['total_open_count']); $summary['open_receive_rate'] = self::percent($summary['completed_order_count'], $summary['total_open_count']);
$summary['avg_unit_price'] = self::safeDivideMoney($summary['completed_order_amount'], $summary['completed_order_count']); $summary['avg_unit_price'] = self::safeDivideMoney($summary['completed_order_amount'], $summary['completed_order_count']);
@@ -2310,7 +2320,7 @@ class ConversionLogic
* @param array<int, array<string, mixed>> $rows * @param array<int, array<string, mixed>> $rows
* @return array<string, mixed> * @return array<string, mixed>
*/ */
private static function buildCharts(array $rows): array private static function buildCharts(array $rows, string $dimension = 'dept'): array
{ {
$chartableRows = array_values(array_filter($rows, static fn (array $row): bool => !((bool)($row['_virtual_bucket'] ?? false)))); $chartableRows = array_values(array_filter($rows, static fn (array $row): bool => !((bool)($row['_virtual_bucket'] ?? false))));
$topRows = array_slice($chartableRows, 0, 10); $topRows = array_slice($chartableRows, 0, 10);
@@ -2319,29 +2329,56 @@ class ConversionLogic
'names' => [], 'names' => [],
'amounts' => [], 'amounts' => [],
'order_counts' => [], 'order_counts' => [],
'fan_counts' => [],
'rois' => [],
]; ];
if ($dimension === 'doctor') {
$ranking['appointment_counts'] = [];
$ranking['interview_counts'] = [];
} else {
$ranking['fan_counts'] = [];
$ranking['rois'] = [];
}
foreach ($topRows as $row) { foreach ($topRows as $row) {
$ranking['names'][] = $row['name']; $ranking['names'][] = $row['name'];
$ranking['amounts'][] = $row['completed_order_amount']; $ranking['amounts'][] = $row['completed_order_amount'];
$ranking['order_counts'][] = $row['completed_order_count']; $ranking['order_counts'][] = $row['completed_order_count'];
$ranking['fan_counts'][] = $row['add_fans_count']; if ($dimension === 'doctor') {
$ranking['rois'][] = $row['roi']; $ranking['appointment_counts'][] = $row['appointment_total_count'];
$ranking['interview_counts'][] = $row['interview_count'];
} else {
$ranking['fan_counts'][] = $row['add_fans_count'];
$ranking['rois'][] = $row['roi'];
}
} }
return [ $charts = [
'ranking' => $ranking, 'ranking' => $ranking,
'amount_share' => array_map( 'amount_share' => array_map(
static fn (array $row): array => ['name' => $row['name'], 'value' => $row['completed_order_amount']], static fn (array $row): array => ['name' => $row['name'], 'value' => $row['completed_order_amount']],
array_filter($topRows, static fn (array $row): bool => (float)$row['completed_order_amount'] > 0) array_filter($topRows, static fn (array $row): bool => (float)$row['completed_order_amount'] > 0)
), ),
'fan_share' => array_map( ];
if ($dimension === 'doctor') {
$charts['order_share'] = array_map(
static fn (array $row): array => ['name' => $row['name'], 'value' => $row['completed_order_count']],
array_filter($topRows, static fn (array $row): bool => (int)$row['completed_order_count'] > 0)
);
} else {
$charts['fan_share'] = array_map(
static fn (array $row): array => ['name' => $row['name'], 'value' => $row['add_fans_count']], static fn (array $row): array => ['name' => $row['name'], 'value' => $row['add_fans_count']],
array_filter($topRows, static fn (array $row): bool => (int)$row['add_fans_count'] > 0) array_filter($topRows, static fn (array $row): bool => (int)$row['add_fans_count'] > 0)
), );
]; }
return $charts;
}
private static function receiveRate(int $completedOrderCount, int $addFansCount, int $interviewCount, string $dimension): float
{
$denominator = $dimension === 'doctor' ? $interviewCount : $addFansCount;
return self::percent($completedOrderCount, $denominator);
} }
private static function percent(int $numerator, int $denominator): float private static function percent(int $numerator, int $denominator): float