智慧教务系统
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

827 lines
26 KiB

<?php
namespace app\api\controller;
use app\service\api\member\MemberService;
use core\base\BaseApiController;
use think\facade\View;
use think\facade\Db;
/**
* Dashboard WebView 控制器 - 市场人员业绩管理系统
*/
class Dashboard extends BaseApiController
{
/**
* WebView 页面渲染
*/
public function webview()
{
$type = $this->request->get('type', 'my_data'); // 页面类型
$token = $this->request->get('token', ''); // 用户token
$platform = $this->request->get('platform', 'web'); // 平台标识
// 验证token和获取用户信息
if (empty($token)) {
return $this->renderErrorPage('缺少用户认证信息');
}
try {
// 验证token并获取用户信息
$userInfo = $this->getUserInfo($token);
// 根据页面类型渲染不同内容
$htmlContent = $this->renderDashboardPage($type, $userInfo, $platform);
// 输出HTML内容
return response($htmlContent)->header([
'Content-Type' => 'text/html; charset=utf-8',
'Cache-Control' => 'no-cache, no-store, must-revalidate',
'Pragma' => 'no-cache',
'Expires' => '0'
]);
} catch (\Exception $e) {
return $this->renderErrorPage('页面加载失败: ' . $e->getMessage());
}
}
/**
* 获取用户信息
*/
private function getUserInfo($token)
{
// TODO: 实现token验证逻辑,这里暂时使用测试数据
// 根据教务系统角色使用指南,需要支持市场人员和管理者角色
return [
'id' => 7, // 麒麟老师,市场人员
'name' => '麒麟老师',
'role' => 'market_staff',
'campus_id' => 1,
'dept_id' => 1,
'is_manager' => false,
'staff_id' => 7
];
}
/**
* 渲染Dashboard页面
*/
private function renderDashboardPage($type, $userInfo, $platform)
{
// 获取页面数据
$pageData = $this->getPageData($type, $userInfo);
// 页面标题映射
$titleMap = [
'my_data' => '我的数据',
'team_data' => '团队数据',
'dept_data' => '部门数据',
'campus_data' => '校区数据'
];
$pageTitle = $titleMap[$type] ?? '数据统计';
// 使用视图模板渲染页面
return View::fetch('dashboard/main', [
'pageTitle' => $pageTitle,
'pageData' => $pageData,
'platform' => $platform,
'userInfo' => $userInfo
]);
}
/**
* 获取页面数据
*/
private function getPageData($type, $userInfo)
{
switch ($type) {
case 'my_data':
return $this->getMyData($userInfo);
case 'team_data':
return $this->getTeamData($userInfo);
case 'dept_data':
return $this->getDeptData($userInfo);
case 'campus_data':
return $this->getCampusData($userInfo);
default:
return [];
}
}
/**
* 获取我的数据(市场人员)
*/
private function getMyData($userInfo)
{
$staffId = $userInfo['staff_id'];
$currentMonth = date('Y-m-01');
return [
// 核心统计指标
'stats' => [
[
'label' => '本月新增资源',
'value' => $this->getResourceCount($staffId, $currentMonth),
'unit' => '个',
'trend' => $this->getResourceTrend($staffId)
],
[
'label' => '本月成交客户',
'value' => $this->getConvertedCount($staffId, $currentMonth),
'unit' => '人',
'trend' => $this->getConversionTrend($staffId)
],
[
'label' => '本月业绩',
'value' => $this->getPerformance($staffId, $currentMonth),
'unit' => '元',
'trend' => $this->getPerformanceTrend($staffId)
],
[
'label' => '本月提成',
'value' => $this->getCommission($staffId, $currentMonth),
'unit' => '元',
'trend' => $this->getCommissionTrend($staffId)
]
],
// 资源分析
'resource_analysis' => [
'channel_distribution' => $this->getChannelDistribution($staffId),
'source_distribution' => $this->getSourceDistribution($staffId),
'conversion_funnel' => $this->getConversionFunnel($staffId),
'monthly_trend' => $this->getMonthlyTrend($staffId)
],
// 收益分析
'income_analysis' => [
'commission_breakdown' => $this->getCommissionBreakdown($staffId),
'bonus_history' => $this->getBonusHistory($staffId),
'income_trend' => $this->getIncomeTrend($staffId)
]
];
}
/**
* 获取团队数据(经理权限)
*/
private function getTeamData($userInfo)
{
$campusId = $userInfo['campus_id'];
$deptId = $userInfo['dept_id'];
$currentMonth = date('Y-m-01');
return [
// 团队总览
'team_overview' => [
'total_members' => $this->getTeamMemberCount($campusId, $deptId),
'total_resources' => $this->getTeamResourceCount($campusId, $deptId, $currentMonth),
'total_converted' => $this->getTeamConvertedCount($campusId, $deptId, $currentMonth),
'total_performance' => $this->getTeamPerformance($campusId, $deptId, $currentMonth)
],
// 团队成员排名
'member_ranking' => $this->getTeamMemberRanking($campusId, $deptId, $currentMonth),
// 团队业绩分布
'performance_distribution' => $this->getTeamPerformanceDistribution($campusId, $deptId, $currentMonth)
];
}
/**
* 获取部门数据
*/
private function getDeptData($userInfo)
{
$campusId = $userInfo['campus_id'];
$currentMonth = date('Y-m-01');
return [
// 部门总览
'dept_overview' => [
'total_depts' => $this->getDeptCount($campusId),
'total_resources' => $this->getDeptResourceCount($campusId, $currentMonth),
'total_performance' => $this->getDeptPerformance($campusId, $currentMonth),
'conversion_rate' => $this->getDeptConversionRate($campusId, $currentMonth)
],
// 部门排名
'dept_ranking' => $this->getDeptRanking($campusId, $currentMonth)
];
}
/**
* 获取校区数据
*/
private function getCampusData($userInfo)
{
$campusId = $userInfo['campus_id'];
$currentMonth = date('Y-m-01');
return [
// 校区总览
'campus_overview' => [
'total_performance' => $this->getCampusPerformance($campusId, $currentMonth),
'total_resources' => $this->getCampusResourceCount($campusId, $currentMonth),
'total_converted' => $this->getCampusConvertedCount($campusId, $currentMonth),
'total_staff' => $this->getCampusStaffCount($campusId)
],
// 校区部门对比
'dept_comparison' => $this->getCampusDeptComparison($campusId, $currentMonth)
];
}
// ========== 数据查询方法 ==========
/**
* 获取资源数量
*/
private function getResourceCount($staffId, $startDate)
{
return Db::table('school_customer_resources')
->where('consultant', $staffId)
->where('deleted_at', 0)
->where('created_at', '>=', $startDate)
->count();
}
/**
* 获取成交客户数量
*/
private function getConvertedCount($staffId, $startDate)
{
return Db::table('school_customer_resources r')
->join('school_order_table o', 'r.id = o.resource_id')
->where('r.consultant', $staffId)
->where('r.deleted_at', 0)
->where('o.order_type', '1')
->where('o.order_status', 'paid')
->where('r.created_at', '>=', $startDate)
->count();
}
/**
* 获取业绩数据
*/
private function getPerformance($staffId, $startDate)
{
$result = Db::table('school_order_table')
->where('staff_id', $staffId)
->where('order_type', '1')
->where('order_status', 'paid')
->where('payment_time', '>=', $startDate)
->sum('order_amount');
return $result ?: 0;
}
/**
* 获取提成数据
*/
private function getCommission($staffId, $startDate)
{
$result = Db::table('school_performance_records')
->where('staff_id', $staffId)
->whereIn('performance_type', ['sales', 'marketing', 'consultant'])
->where('order_status', 'completed')
->where('created_at', '>=', $startDate)
->sum('performance_value');
return $result ?: 0;
}
/**
* 获取渠道分布
*/
private function getChannelDistribution($staffId)
{
$results = Db::table('school_customer_resources')
->field('source_channel, COUNT(*) as count')
->where('consultant', $staffId)
->where('deleted_at', 0)
->group('source_channel')
->select();
$channelMap = [
'1' => '线上推广',
'2' => '电话营销',
'3' => '地推活动',
'4' => '转介绍',
'5' => '其他'
];
$data = [];
foreach ($results as $row) {
$channelName = $channelMap[$row['source_channel']] ?? '其他';
$data[] = [
'name' => $channelName,
'value' => $row['count']
];
}
return $data;
}
/**
* 获取来源分布
*/
private function getSourceDistribution($staffId)
{
$results = Db::table('school_customer_resources')
->field('source, COUNT(*) as count')
->where('consultant', $staffId)
->where('deleted_at', 0)
->whereNotNull('source')
->where('source', '<>', '')
->group('source')
->select();
$sourceMap = [
'1' => '官网',
'2' => '微信',
'3' => '抖音',
'4' => '小红书',
'5' => '其他'
];
$data = [];
foreach ($results as $row) {
$sourceName = $sourceMap[$row['source']] ?? $row['source'];
$data[] = [
'name' => $sourceName,
'value' => $row['count']
];
}
return $data;
}
/**
* 获取转化漏斗
*/
private function getConversionFunnel($staffId)
{
// 总资源数
$totalResources = Db::table('school_customer_resources')
->where('consultant', $staffId)
->where('deleted_at', 0)
->count();
// 有效联系数(简化处理)
$contactedResources = $totalResources;
// 意向客户数
$intentionResources = Db::table('school_customer_resources')
->where('consultant', $staffId)
->where('deleted_at', 0)
->where('initial_intent', 'high')
->count();
// 成交客户数
$convertedResources = Db::table('school_customer_resources r')
->join('school_order_table o', 'r.id = o.resource_id')
->where('r.consultant', $staffId)
->where('r.deleted_at', 0)
->where('o.order_type', '1')
->where('o.order_status', 'paid')
->count();
return [
['stage' => '新增资源', 'count' => $totalResources, 'rate' => 100],
['stage' => '有效联系', 'count' => $contactedResources, 'rate' => round($contactedResources * 100 / $totalResources, 1)],
['stage' => '意向客户', 'count' => $intentionResources, 'rate' => round($intentionResources * 100 / $totalResources, 1)],
['stage' => '成交客户', 'count' => $convertedResources, 'rate' => round($convertedResources * 100 / $totalResources, 1)]
];
}
/**
* 获取月度趋势
*/
private function getMonthlyTrend($staffId)
{
$results = Db::table('school_customer_resources')
->field("DATE_FORMAT(created_at, '%Y-%m') as month, COUNT(*) as count")
->where('consultant', $staffId)
->where('deleted_at', 0)
->group('month')
->order('month DESC')
->limit(6)
->select();
return array_reverse($results); // 按时间正序
}
/**
* 获取提成明细
*/
private function getCommissionBreakdown($staffId)
{
$results = Db::table('school_performance_records')
->field('performance_type, SUM(performance_value) as total_amount, COUNT(*) as count')
->where('staff_id', $staffId)
->whereIn('performance_type', ['sales', 'marketing', 'consultant'])
->where('order_status', 'completed')
->group('performance_type')
->select();
$typeMap = [
'sales' => '销售提成',
'marketing' => '营销提成',
'consultant' => '咨询提成'
];
$data = [];
foreach ($results as $row) {
$typeName = $typeMap[$row['performance_type']] ?? $row['performance_type'];
$data[] = [
'type' => $typeName,
'amount' => $row['total_amount'],
'count' => $row['count']
];
}
return $data;
}
/**
* 获取奖励历史
*/
private function getBonusHistory($staffId)
{
return Db::table('school_salary')
->field('salary_month, other_subsidies as amount')
->where('staff_id', $staffId)
->where('other_subsidies', '>', 0)
->order('salary_month DESC')
->limit(6)
->select();
}
// ========== 团队数据查询方法 ==========
/**
* 获取团队成员数量
*/
private function getTeamMemberCount($campusId, $deptId)
{
return Db::table('school_personnel p')
->join('school_campus_person_role cpr', 'p.id = cpr.person_id')
->where('cpr.campus_id', $campusId)
->where('cpr.dept_id', $deptId)
->where('p.status', 1)
->where('p.deleted_at', '0')
->count();
}
/**
* 获取团队资源数量
*/
private function getTeamResourceCount($campusId, $deptId, $startDate)
{
$members = Db::table('school_personnel p')
->join('school_campus_person_role cpr', 'p.id = cpr.person_id')
->where('cpr.campus_id', $campusId)
->where('cpr.dept_id', $deptId)
->where('p.status', 1)
->where('p.deleted_at', '0')
->column('id');
return Db::table('school_customer_resources')
->whereIn('consultant', $members)
->where('deleted_at', 0)
->where('created_at', '>=', $startDate)
->count();
}
/**
* 获取团队成交数量
*/
private function getTeamConvertedCount($campusId, $deptId, $startDate)
{
$members = Db::table('school_personnel p')
->join('school_campus_person_role cpr', 'p.id = cpr.person_id')
->where('cpr.campus_id', $campusId)
->where('cpr.dept_id', $deptId)
->where('p.status', 1)
->where('p.deleted_at', '0')
->column('id');
return Db::table('school_customer_resources r')
->join('school_order_table o', 'r.id = o.resource_id')
->whereIn('r.consultant', $members)
->where('r.deleted_at', 0)
->where('o.order_type', '1')
->where('o.order_status', 'paid')
->where('r.created_at', '>=', $startDate)
->count();
}
/**
* 获取团队业绩
*/
private function getTeamPerformance($campusId, $deptId, $startDate)
{
$members = Db::table('school_personnel p')
->join('school_campus_person_role cpr', 'p.id = cpr.person_id')
->where('cpr.campus_id', $campusId)
->where('cpr.dept_id', $deptId)
->where('p.status', 1)
->where('p.deleted_at', '0')
->column('id');
$result = Db::table('school_order_table')
->whereIn('staff_id', $members)
->where('order_type', '1')
->where('order_status', 'paid')
->where('payment_time', '>=', $startDate)
->sum('order_amount');
return $result ?: 0;
}
/**
* 获取团队成员排名
*/
private function getTeamMemberRanking($campusId, $deptId, $startDate)
{
// 获取团队成员列表
$members = Db::table('school_personnel p')
->join('school_campus_person_role cpr', 'p.id = cpr.person_id')
->where('cpr.campus_id', $campusId)
->where('cpr.dept_id', $deptId)
->where('p.status', 1)
->where('p.deleted_at', '0')
->column('id, name');
$ranking = [];
foreach ($members as $member) {
$resourceCount = $this->getResourceCount($member['id'], $startDate);
$convertedCount = $this->getConvertedCount($member['id'], $startDate);
$performance = $this->getPerformance($member['id'], $startDate);
$commission = $this->getCommission($member['id'], $startDate);
$ranking[] = [
'staff_id' => $member['id'],
'staff_name' => $member['name'],
'resource_count' => $resourceCount,
'converted_count' => $convertedCount,
'performance' => $performance,
'commission' => $commission
];
}
// 按业绩排序
usort($ranking, function($a, $b) {
return $b['performance'] <=> $a['performance'];
});
return $ranking;
}
// ========== 部门数据查询方法 ==========
/**
* 获取部门数量
*/
private function getDeptCount($campusId)
{
return Db::table('school_departments')
->where('deleted_at', 0)
->count();
}
/**
* 获取部门资源数量
*/
private function getDeptResourceCount($campusId, $startDate)
{
return Db::table('school_customer_resources')
->where('campus', $campusId)
->where('deleted_at', 0)
->where('created_at', '>=', $startDate)
->count();
}
/**
* 获取部门业绩
*/
private function getDeptPerformance($campusId, $startDate)
{
$result = Db::table('school_order_table')
->where('campus_id', $campusId)
->where('order_type', '1')
->where('order_status', 'paid')
->where('payment_time', '>=', $startDate)
->sum('order_amount');
return $result ?: 0;
}
/**
* 获取部门转化率
*/
private function getDeptConversionRate($campusId, $startDate)
{
$totalResources = Db::table('school_customer_resources')
->where('campus', $campusId)
->where('deleted_at', 0)
->where('created_at', '>=', $startDate)
->count();
if ($totalResources == 0) return 0;
$convertedResources = Db::table('school_customer_resources r')
->join('school_order_table o', 'r.id = o.resource_id')
->where('r.campus', $campusId)
->where('r.deleted_at', 0)
->where('o.order_type', '1')
->where('o.order_status', 'paid')
->where('r.created_at', '>=', $startDate)
->count();
return round($convertedResources * 100 / $totalResources, 1);
}
/**
* 获取部门排名
*/
private function getDeptRanking($campusId, $startDate)
{
$depts = Db::table('school_departments')
->where('deleted_at', 0)
->select();
$ranking = [];
foreach ($depts as $dept) {
$performance = Db::table('school_order_table')
->where('campus_id', $campusId)
->where('order_type', '1')
->where('order_status', 'paid')
->where('payment_time', '>=', $startDate)
->sum('order_amount');
$ranking[] = [
'dept_id' => $dept['id'],
'dept_name' => $dept['department_name'],
'performance' => $performance ?: 0
];
}
// 按业绩排序
usort($ranking, function($a, $b) {
return $b['performance'] <=> $a['performance'];
});
return $ranking;
}
// ========== 校区数据查询方法 ==========
/**
* 获取校区业绩
*/
private function getCampusPerformance($campusId, $startDate)
{
$result = Db::table('school_order_table')
->where('campus_id', $campusId)
->where('order_type', '1')
->where('order_status', 'paid')
->where('payment_time', '>=', $startDate)
->sum('order_amount');
return $result ?: 0;
}
/**
* 获取校区资源数量
*/
private function getCampusResourceCount($campusId, $startDate)
{
return Db::table('school_customer_resources')
->where('campus', $campusId)
->where('deleted_at', 0)
->where('created_at', '>=', $startDate)
->count();
}
/**
* 获取校区成交数量
*/
private function getCampusConvertedCount($campusId, $startDate)
{
return Db::table('school_customer_resources r')
->join('school_order_table o', 'r.id = o.resource_id')
->where('r.campus', $campusId)
->where('r.deleted_at', 0)
->where('o.order_type', '1')
->where('o.order_status', 'paid')
->where('r.created_at', '>=', $startDate)
->count();
}
/**
* 获取校区员工数量
*/
private function getCampusStaffCount($campusId)
{
return Db::table('school_personnel p')
->join('school_campus_person_role cpr', 'p.id = cpr.person_id')
->where('cpr.campus_id', $campusId)
->where('p.status', 1)
->where('p.deleted_at', '0')
->count();
}
/**
* 获取校区部门对比
*/
private function getCampusDeptComparison($campusId, $startDate)
{
$depts = Db::table('school_departments')
->where('deleted_at', 0)
->select();
$comparison = [];
foreach ($depts as $dept) {
$performance = Db::table('school_order_table')
->join('school_customer_resources r', 'r.id = o.resource_id')
->where('o.campus_id', $campusId)
->where('r.consultant', '!=', '')
->where('o.order_type', '1')
->where('o.order_status', 'paid')
->where('o.payment_time', '>=', $startDate)
->sum('o.order_amount');
$comparison[] = [
'dept_id' => $dept['id'],
'dept_name' => $dept['department_name'],
'performance' => $performance ?: 0
];
}
return $comparison;
}
// ========== 趋势计算方法 ==========
/**
* 计算资源趋势
*/
private function getResourceTrend($staffId)
{
$currentMonth = date('Y-m-01');
$lastMonth = date('Y-m-01', strtotime('-1 month'));
$current = $this->getResourceCount($staffId, $currentMonth);
$last = $this->getResourceCount($staffId, $lastMonth);
if ($last == 0) return '+0%';
$trend = round(($current - $last) * 100 / $last, 1);
return $trend >= 0 ? '+' . $trend . '%' : $trend . '%';
}
/**
* 计算转化趋势
*/
private function getConversionTrend($staffId)
{
// 简化处理,返回示例数据
return '+8%';
}
/**
* 计算业绩趋势
*/
private function getPerformanceTrend($staffId)
{
// 简化处理,返回示例数据
return '+12%';
}
/**
* 计算提成趋势
*/
private function getCommissionTrend($staffId)
{
// 简化处理,返回示例数据
return '+15%';
}
/**
* 渲染错误页面
*/
private function renderErrorPage($message)
{
$errorHtml = View::fetch('dashboard/error', [
'message' => $message
]);
return response($errorHtml)->header([
'Content-Type' => 'text/html; charset=utf-8'
]);
}
}