Files
ulthon_admin/extend/base/common/service/MenuServiceBase.php
2026-03-26 20:22:34 +08:00

309 lines
8.6 KiB
PHP

<?php
namespace base\common\service;
use app\common\constants\MenuConstant;
use app\common\service\AuthService;
use think\facade\Db;
class MenuServiceBase
{
/**
* 管理员ID.
* @var int
*/
protected $adminId;
public function __construct($adminId)
{
$this->adminId = $adminId;
return $this;
}
/**
* 获取首页信息.
* @return array|\think\Model|null
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getHomeInfo()
{
$data = Db::name('system_menu')
->field('title,icon,href')
->where('delete_time', 0)
->where('pid', MenuConstant::HOME_PID)
->find();
!empty($data) && $data['href'] = __url($data['href']);
$data['mb_title'] = '菜单';
$data['mb_href'] = (string)url('admin/Index/mobile');
return $data;
}
/**
* 获取后台菜单树信息.
* @return mixed
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getMenuTree()
{
/** @var AuthService $authService */
$authServer = app(AuthService::class, ['adminId' => $this->adminId]);
return $this->buildMenuChild(0, $this->getMenuData(), $authServer);
}
private function buildMenuChild($pid, $menuList, AuthService $authServer)
{
$treeList = [];
foreach ($menuList as &$v) {
$check = false;
if (!empty($v['auth_node'])) {
$check = $authServer->checkNode($v['auth_node']);
} elseif (!empty($v['href'])) {
$check = $authServer->checkNode($v['href']);
} else {
$check = true;
}
!empty($v['href']) && $v['href'] = __url($v['href']);
if ($pid == $v['pid'] && $check) {
$node = $v;
$child = $this->buildMenuChild($v['id'], $menuList, $authServer);
if (!empty($child)) {
$node['child'] = $child;
}
if (!empty($v['href']) || !empty($child)) {
$treeList[] = $node;
}
}
}
return $treeList;
}
/**
* 获取所有菜单数据.
* @return \think\Collection
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
protected function getMenuData()
{
$menuData = Db::name('system_menu')
->field('id,pid,title,icon,href,target,auth_node')
->where('delete_time', 0)
->where([
['status', '=', '1'],
['pid', '<>', MenuConstant::HOME_PID],
])
->order([
'sort' => 'desc',
'id' => 'asc',
])
->select();
return $menuData;
}
/**
* 创建菜单
*
* @param array $data 菜单数据
* @return int 返回新创建的菜单ID
* @throws \Exception
*/
public function create(array $data): int
{
$menu = Db::name('system_menu');
// 准备数据
$insertData = [
'pid' => $data['parent_id'] ?? 0,
'title' => $data['title'] ?? '',
'icon' => $data['icon'] ?? '',
'href' => $data['path'] ?? '',
'auth_node' => $data['node'] ?? '',
'sort' => $data['sort'] ?? 100,
'status' => 1,
'target' => '_self',
'remark' => $data['remark'] ?? '',
'create_time' => time(),
'update_time' => time(),
'delete_time' => 0,
];
// 验证必填字段
if (empty($insertData['title'])) {
throw new \Exception('菜单标题不能为空');
}
// 验证父菜单是否存在
if ($insertData['pid'] > 0) {
$parentMenu = Db::name('system_menu')
->where('id', $insertData['pid'])
->where('delete_time', 0)
->find();
if (empty($parentMenu)) {
throw new \Exception("父菜单ID {$insertData['pid']} 不存在");
}
}
// 插入数据
$menuId = $menu->insertGetId($insertData);
if (!$menuId) {
throw new \Exception('菜单创建失败');
}
return (int)$menuId;
}
/**
* 更新菜单
*
* @param int $menuId 菜单ID
* @param array $data 更新数据
* @return bool 是否更新成功
* @throws \Exception
*/
public function update(int $menuId, array $data): bool
{
// 验证菜单是否存在
$menu = Db::name('system_menu')
->where('id', $menuId)
->where('delete_time', 0)
->find();
if (empty($menu)) {
throw new \Exception("菜单ID {$menuId} 不存在");
}
// 准备更新数据
$updateData = [
'update_time' => time(),
];
if (isset($data['title'])) {
$updateData['title'] = $data['title'];
}
if (isset($data['parent_id'])) {
$updateData['pid'] = $data['parent_id'];
}
if (isset($data['icon'])) {
$updateData['icon'] = $data['icon'];
}
if (isset($data['path'])) {
$updateData['href'] = $data['path'];
}
if (isset($data['node'])) {
$updateData['auth_node'] = $data['node'];
}
if (isset($data['sort'])) {
$updateData['sort'] = $data['sort'];
}
if (isset($data['status'])) {
$updateData['status'] = $data['status'];
}
if (isset($data['remark'])) {
$updateData['remark'] = $data['remark'];
}
if (isset($data['target'])) {
$updateData['target'] = $data['target'];
}
// 验证必填字段
if (empty($menu['title']) && empty($updateData['title'])) {
throw new \Exception('菜单标题不能为空');
}
// 验证父菜单是否存在(如果修改了父菜单)
if (isset($updateData['pid']) && $updateData['pid'] > 0) {
// 不能将自己设置为父菜单
if ($updateData['pid'] == $menuId) {
throw new \Exception('不能将自己设置为父菜单');
}
$parentMenu = Db::name('system_menu')
->where('id', $updateData['pid'])
->where('delete_time', 0)
->find();
if (empty($parentMenu)) {
throw new \Exception("父菜单ID {$updateData['pid']} 不存在");
}
}
// 更新数据
$result = Db::name('system_menu')
->where('id', $menuId)
->update($updateData);
return $result !== false;
}
/**
* 删除菜单
*
* @param int $menuId 菜单ID
* @return bool 是否删除成功
* @throws \Exception
*/
public function delete(int $menuId): bool
{
// 验证菜单是否存在
$menu = Db::name('system_menu')
->where('id', $menuId)
->where('delete_time', 0)
->find();
if (empty($menu)) {
throw new \Exception("菜单ID {$menuId} 不存在");
}
// 检查是否有子菜单
$hasChildren = Db::name('system_menu')
->where('pid', $menuId)
->where('delete_time', 0)
->count();
if ($hasChildren > 0) {
throw new \Exception('该菜单下存在子菜单,请先删除子菜单');
}
// 软删除
$result = Db::name('system_menu')
->where('id', $menuId)
->update([
'delete_time' => time(),
'update_time' => time(),
]);
return $result !== false;
}
/**
* 获取菜单详情
*
* @param int $menuId 菜单ID
* @return array|null 菜单数据
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getMenu(int $menuId): ?array
{
$menu = Db::name('system_menu')
->where('id', $menuId)
->where('delete_time', 0)
->find();
return $menu ? $menu : null;
}
}