Files
2026-08-08 15:53:53 +08:00

131 lines
4.8 KiB
PHP

<?php
namespace App\Controllers\CRM;
use App\Controllers\Controller;
use App\Models\CRM\Customer;
use App\Models\CRM\Lead;
use App\Models\CRM\FollowUp;
/**
* CRM 入口与子路由
* 权限:super_admin 或 crm_role ∈ {admin,user}(路由层已拦截)。
*/
class DashboardController extends Controller
{
public function nav(string $seg): array
{
return [
['k' => 'dashboard', 'label' => '仪表盘', 'icon' => '📊', 'url' => 'CRM'],
['k' => 'customers', 'label' => '客户管理', 'icon' => '🤝', 'url' => 'CRM/customers'],
['k' => 'leads', 'label' => '商机线索', 'icon' => '💡', 'url' => 'CRM/leads'],
['k' => 'followups', 'label' => '跟进记录', 'icon' => '📞', 'url' => 'CRM/followups'],
['k' => 'contacts', 'label' => '客户联系人', 'icon' => '👥', 'url' => 'CRM/contacts'],
];
}
/** 统一子路由入口 */
public function dispatch(array $s)
{
$res = $s[0] ?? 'dashboard';
$action = $s[1] ?? '';
$id = $s[2] ?? null;
// 仪表盘始终可进
if ($res === 'dashboard') {
return $this->dashboard();
}
// 用户管理(仅该系统管理员):统一管理本系统用户及其页面权限
if ($res === 'users') {
if (!\subsys_admin('crm')) {
\Core\App::forbidden('需要 CRM 管理员权限');
return;
}
$uc = new \App\Controllers\CRM\UsersController();
if ($action === '' || $action === 'index') return $uc->index();
if ($action === 'create') return $uc->create();
if ($action === 'store') return $uc->store();
if ($action === 'edit') return $uc->edit($id);
if ($action === 'update') return $uc->update($id);
if ($action === 'destroy') return $uc->destroy($id);
if ($action === 'reset') return $uc->reset($id);
\Core\App::notFound('未知操作: ' . $action);
return;
}
$map = [
'customers' => 'CustomersController',
'leads' => 'LeadsController',
'followups' => 'FollowUpsController',
'contacts' => 'ContactsController',
];
if (!isset($map[$res])) {
\Core\App::notFound('未知页面: ' . $res);
return;
}
// 页面级权限:仪表盘始终可进,其余页面按分系统「页面可见权限」拦截
if (!\subsys_page_can('crm', $res)) {
\Core\App::forbidden('您没有访问该页面的权限');
return;
}
// 资源子操作路由:/CRM/{resource}[/{action}[/{id}]]
$method = $this->resolveSubsysAction($action);
if ($method === null) {
\Core\App::notFound('未知操作: ' . $action);
return;
}
$class = 'App\\Controllers\\CRM\\' . $map[$res];
$instance = new $class();
if (!method_exists($instance, $method)) {
\Core\App::notFound('操作不存在: ' . $method);
return;
}
return $instance->$method($id);
}
/** 将 URL 动作段解析为控制器方法名;不支持的动作返回 null */
private function resolveSubsysAction(string $action): ?string
{
$verbs = [
'' => 'index',
'index' => 'index',
'create' => 'create',
'store' => 'store',
'edit' => 'edit',
'update' => 'update',
'destroy' => 'destroy',
];
return $verbs[$action] ?? null;
}
public function dashboard()
{
$customers = (new Customer())->all();
$leads = (new Lead())->all();
$follows = (new FollowUp())->all();
$stageCount = [];
foreach ($leads as $l) {
$stageCount[$l['stage'] ?? 'new'] = ($stageCount[$l['stage'] ?? 'new'] ?? 0) + 1;
}
$amountTotal = array_sum(array_map(fn($l) => (float)($l['amount'] ?? 0), $leads));
$typeCount = [];
foreach ($customers as $c) {
$typeCount[$c['type'] ?? 'trade'] = ($typeCount[$c['type'] ?? 'trade'] ?? 0) + 1;
}
$recent = array_slice(array_reverse($follows), 0, 8);
$recentCustomers = array_slice(array_reverse($customers), 0, 8);
return $this->renderSubsys('crm', 'crm/dashboard', [
'customerTotal' => count($customers),
'leadTotal' => count($leads),
'followTotal' => count($follows),
'amountTotal' => $amountTotal,
'stageCount' => $stageCount,
'typeCount' => $typeCount,
'recent' => $recent,
'recentCustomers'=> $recentCustomers,
], $this->nav('dashboard'), 'dashboard');
}
}