文件还在测试中

This commit is contained in:
2026-08-08 15:53:53 +08:00
parent 5f1e7adb64
commit 8101177cb5
241 changed files with 18074 additions and 22 deletions
+267
View File
@@ -0,0 +1,267 @@
<?php
namespace App\Controllers\PSI;
use App\Controllers\Controller;
use App\Models\PSI\Material;
use App\Models\PSI\Product;
use App\Models\PSI\Purchase;
use App\Models\PSI\Sales;
use App\Models\PSI\StockMove;
/** PSI 进销存入口与子路由。权限:super_admin 或 psi_role ∈ {admin,user} */
class DashboardController extends Controller
{
public function nav(string $seg): array
{
return \psi_nav();
}
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('psi')) {
\Core\App::forbidden('需要 PSI 管理员权限');
return;
}
$uc = new \App\Controllers\PSI\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;
}
// 订单管理:合并原「后台订单」到 PSI,方便管理人员在同一系统内快速处理
if ($res === 'orders') {
if (!\subsys_page_can('psi', 'orders')) {
\Core\App::forbidden('您没有访问订单管理的权限');
return;
}
$oc = new \App\Controllers\PSI\OrdersController();
if ($action === '' || $action === 'index') return $oc->index();
if ($action === 'show') return $oc->show($id);
if ($action === 'markPaid') return $oc->markPaid($id);
if ($action === 'destroy') return $oc->destroy($id);
\Core\App::notFound('未知操作: ' . $action);
return;
}
// 销售订单:录入 / 打印 / 关联出库
if ($res === 'sales_orders') {
if (!\subsys_page_can('psi', 'sales_orders')) { \Core\App::forbidden('您没有访问销售订单的权限'); return; }
$c = new \App\Controllers\PSI\SalesOrdersController();
if ($action === '' || $action === 'index') return $c->index();
if ($action === 'create') return $c->create();
if ($action === 'store') return $c->store();
if ($action === 'show') return $c->show($id);
if ($action === 'edit') return $c->edit($id);
if ($action === 'update') return $c->update($id);
if ($action === 'destroy') return $c->destroy($id);
if ($action === 'print') return $c->printDoc($id);
\Core\App::notFound('未知操作: ' . $action); return;
}
// 采购订单:录入 / 打印 / 收货入库
if ($res === 'purchase_orders') {
if (!\subsys_page_can('psi', 'purchase_orders')) { \Core\App::forbidden('您没有访问采购订单的权限'); return; }
$c = new \App\Controllers\PSI\PurchaseOrdersController();
if ($action === '' || $action === 'index') return $c->index();
if ($action === 'create') return $c->create();
if ($action === 'store') return $c->store();
if ($action === 'show') return $c->show($id);
if ($action === 'edit') return $c->edit($id);
if ($action === 'update') return $c->update($id);
if ($action === 'destroy') return $c->destroy($id);
if ($action === 'receive') return $c->receive($id);
if ($action === 'print') return $c->printDoc($id);
\Core\App::notFound('未知操作: ' . $action); return;
}
// 出库单:录入 / 打印(关联销售订单、扣减库存)
if ($res === 'outbounds') {
if (!\subsys_page_can('psi', 'outbounds')) { \Core\App::forbidden('您没有访问出库单的权限'); return; }
$c = new \App\Controllers\PSI\OutboundsController();
if ($action === '' || $action === 'index') return $c->index();
if ($action === 'create') return $c->create();
if ($action === 'store') return $c->store();
if ($action === 'show') return $c->show($id);
if ($action === 'edit') return $c->edit($id);
if ($action === 'update') return $c->update($id);
if ($action === 'destroy') return $c->destroy($id);
if ($action === 'print') return $c->printDoc($id);
\Core\App::notFound('未知操作: ' . $action); return;
}
// 报表中心:采购订单明细 / 销售·采购订单明细 / 交付明细
if ($res === 'reports') {
if (!\subsys_page_can('psi', 'reports')) { \Core\App::forbidden('您没有访问报表中心的权限'); return; }
$c = new \App\Controllers\PSI\ReportsController();
if ($action === '' || $action === 'index') return $c->index();
if ($action === 'poDetail') return $c->poDetail();
if ($action === 'soPo') return $c->soPo();
if ($action === 'delivery') return $c->delivery();
\Core\App::notFound('未知操作: ' . $action); return;
}
// 紧急提醒中心(所有 PSI 用户可见)
if ($res === 'reminders') {
$c = new \App\Controllers\PSI\RemindersController();
return $c->handle(array_slice($s, 1));
}
// 通知设置(仅 PSI 管理员,控制器内二次鉴权)
if ($res === 'notifications') {
$c = new \App\Controllers\PSI\NotificationsController();
return $c->handle(array_slice($s, 1));
}
// 销售出库(支持 show/print 查看与打印预览)
if ($res === 'sales') {
if (!\subsys_page_can('psi', 'sales')) { \Core\App::forbidden('您没有访问销售出库的权限'); return; }
$c = new \App\Controllers\PSI\SalesController();
if ($action === '' || $action === 'index') return $c->index();
if ($action === 'create') return $c->create();
if ($action === 'store') return $c->store();
if ($action === 'show') return $c->show($id);
if ($action === 'destroy') return $c->destroy($id);
if ($action === 'print') return $c->printDoc($id);
\Core\App::notFound('未知操作: ' . $action); return;
}
$map = [
'materials' => 'MaterialsController',
'products' => 'ProductsController',
'suppliers' => 'SuppliersController',
'purchases' => 'PurchasesController',
'stock' => 'StockController',
];
if (!isset($map[$res])) {
\Core\App::notFound('未知页面: ' . $res);
return;
}
// 页面级权限:按分系统「页面可见权限」拦截
if (!\subsys_page_can('psi', $res)) {
\Core\App::forbidden('您没有访问该页面的权限');
return;
}
// 资源子操作路由:/PSI/{resource}[/{action}[/{id}]]
// 支持 index/create/store/edit/update/destroy/adjust
$method = $this->resolveSubsysAction($action);
if ($method === null) {
\Core\App::notFound('未知操作: ' . $action);
return;
}
$class = 'App\\Controllers\\PSI\\' . $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',
'adjust' => 'adjust',
];
return $verbs[$action] ?? null;
}
public function dashboard()
{
$materials = (new Material())->all();
$products = (new Product())->all();
$purchases = (new Purchase())->all();
$sales = (new Sales())->all();
$matStock = array_sum(array_map(fn($m) => (float)($m['stock'] ?? 0), $materials));
$prodStock = array_sum(array_map(fn($p) => (float)($p['stock'] ?? 0), $products));
$purchaseAmt = array_sum(array_map(fn($p) => (float)($p['amount'] ?? 0), $purchases));
$salesAmt = array_sum(array_map(fn($s) => (float)($s['amount'] ?? 0), $sales));
$lowStock = [];
foreach ($materials as $m) { if ((float)($m['stock'] ?? 0) < 20) $lowStock[] = ['type' => '物料', 'item' => $m]; }
foreach ($products as $p) { if ((float)($p['stock'] ?? 0) < 20) $lowStock[] = ['type' => '成品', 'item' => $p]; }
$recentPurchases = array_slice(array_reverse($purchases), 0, 5);
$recentSales = array_slice(array_reverse($sales), 0, 5);
// 订单/出库业务指标(表未创建时静默降级)
$bySalesman = [];
$salesAmount = 0; $salesAmountMonth = 0;
$undelivered = ['count' => 0, 'amount' => 0];
$monthDeliveries = ['count' => 0, 'amount' => 0];
try {
$bySalesman = \Core\Db::query(
"SELECT o.salesman AS salesman, COUNT(DISTINCT o.id) AS orders,
COALESCE(SUM(i.amount),0) AS amount
FROM psi_sales_orders o
LEFT JOIN psi_sales_order_items i ON i.so_id=o.id
WHERE o.salesman <> '' AND o.status <> 'closed'
GROUP BY o.salesman ORDER BY amount DESC"
)->fetchAll();
$r = \Core\Db::query(
"SELECT COALESCE(SUM(i.amount),0) AS amt,
COALESCE(SUM(CASE WHEN MONTH(o.created_at)=MONTH(CURDATE()) AND YEAR(o.created_at)=YEAR(CURDATE()) THEN i.amount ELSE 0 END),0) AS amt_m
FROM psi_sales_orders o LEFT JOIN psi_sales_order_items i ON i.so_id=o.id
WHERE o.status <> 'closed'"
)->fetch();
$salesAmount = (float)($r['amt'] ?? 0);
$salesAmountMonth = (float)($r['amt_m'] ?? 0);
$u = \Core\Db::query(
"SELECT COUNT(*) AS c, COALESCE(SUM(i.amount),0) AS amt
FROM psi_sales_orders o LEFT JOIN psi_sales_order_items i ON i.so_id=o.id
WHERE o.status IN ('pending','partial')"
)->fetch();
$undelivered = ['count' => (int)($u['c'] ?? 0), 'amount' => (float)($u['amt'] ?? 0)];
$d = \Core\Db::query(
"SELECT COUNT(*) AS c, COALESCE(SUM(i.amount),0) AS amt
FROM psi_outbounds ob LEFT JOIN psi_outbound_items i ON i.ob_id=ob.id
WHERE MONTH(ob.created_at)=MONTH(CURDATE()) AND YEAR(ob.created_at)=YEAR(CURDATE())"
)->fetch();
$monthDeliveries = ['count' => (int)($d['c'] ?? 0), 'amount' => (float)($d['amt'] ?? 0)];
} catch (\Throwable $e) { /* 表未创建时不报错 */ }
return $this->renderSubsys('psi', 'psi/dashboard', [
'materialTotal' => count($materials),
'productTotal' => count($products),
'matStock' => $matStock,
'prodStock' => $prodStock,
'purchaseAmt' => $purchaseAmt,
'salesAmt' => $salesAmt,
'lowStock' => $lowStock,
'recentPurchases' => $recentPurchases,
'recentSales' => $recentSales,
'bySalesman' => $bySalesman,
'salesAmount' => $salesAmount,
'salesAmountMonth' => $salesAmountMonth,
'undelivered' => $undelivered,
'monthDeliveries' => $monthDeliveries,
], $this->nav('dashboard'), 'dashboard');
}
}