refactor(admin):重构注解获取 upgrade annotations

- Replace Doctrine annotations with PHP 8.1 attributes
- Update annotation classes to use Attribute interface
- Modify attribute usage across multiple controller files
- Update composer.json to use doctrine/annotations ^2.0.0
This commit is contained in:
wolfcode
2025-01-02 17:04:10 +08:00
parent 4baa4e185d
commit 3d19c8d337
19 changed files with 114 additions and 237 deletions

View File

@@ -8,11 +8,7 @@ use app\admin\service\annotation\ControllerAnnotation;
use app\admin\service\annotation\NodeAnnotation;
use think\App;
/**
* Class Admin
* @package app\admin\controller\system
* @ControllerAnnotation(title="商品分类管理")
*/
#[ControllerAnnotation(title: '商品分类管理')]
class Cate extends AdminController
{

View File

@@ -9,14 +9,9 @@ use app\admin\service\annotation\ControllerAnnotation;
use app\admin\service\annotation\NodeAnnotation;
use app\Request;
use think\App;
use think\db\exception\DbException;
use think\response\Json;
/**
* Class Goods
* @package app\admin\controller\mall
* @ControllerAnnotation(title="商城商品管理")
*/
#[ControllerAnnotation(title: '商城商品管理')]
class Goods extends AdminController
{
@@ -33,10 +28,7 @@ class Goods extends AdminController
$this->assign('cate', (new MallCate())->column('title', 'id'));
}
/**
* @NodeAnnotation(title="列表")
* @throws DbException
*/
#[NodeAnnotation(title: '列表', auth: true)]
public function index(Request $request): Json|string
{
if ($request->isAjax()) {
@@ -55,9 +47,7 @@ class Goods extends AdminController
return $this->fetch();
}
/**
* @NodeAnnotation(title="入库")
*/
#[NodeAnnotation(title: '入库', auth: true)]
public function stock(Request $request, $id): string
{
$row = $this->model->find($id);

View File

@@ -10,14 +10,9 @@ use app\admin\service\annotation\ControllerAnnotation;
use app\admin\service\annotation\NodeAnnotation;
use app\Request;
use think\App;
use think\db\exception\DbException;
use think\response\Json;
/**
* Class Admin
* @package app\admin\controller\system
* @ControllerAnnotation(title="管理员管理")
*/
#[ControllerAnnotation(title: '管理员管理')]
class Admin extends AdminController
{
@@ -33,10 +28,7 @@ class Admin extends AdminController
$this->assign('auth_list', $this->model->getAuthList());
}
/**
* @NodeAnnotation(title="列表")
* @throws DbException
*/
#[NodeAnnotation(title: '列表', auth: true)]
public function index(Request $request): Json|string
{
if ($request->isAjax()) {
@@ -64,9 +56,7 @@ class Admin extends AdminController
return $this->fetch();
}
/**
* @NodeAnnotation(title="添加")
*/
#[NodeAnnotation(title: '添加', auth: true)]
public function add(Request $request): string
{
if ($request->isPost()) {
@@ -87,9 +77,7 @@ class Admin extends AdminController
return $this->fetch();
}
/**
* @NodeAnnotation(title="编辑")
*/
#[NodeAnnotation(title: '编辑', auth: true)]
public function edit(Request $request, $id = 0): string
{
$row = $this->model->find($id);
@@ -116,9 +104,7 @@ class Admin extends AdminController
return $this->fetch();
}
/**
* @NodeAnnotation(title="编辑")
*/
#[NodeAnnotation(title: '设置密码', auth: true)]
public function password(Request $request, $id): string
{
$row = $this->model->find($id);
@@ -147,9 +133,7 @@ class Admin extends AdminController
return $this->fetch();
}
/**
* @NodeAnnotation(title="删除")
*/
#[NodeAnnotation(title: '删除', auth: true)]
public function delete(Request $request): void
{
$this->checkPostRequest();
@@ -170,9 +154,7 @@ class Admin extends AdminController
$save ? $this->success('删除成功') : $this->error('删除失败');
}
/**
* @NodeAnnotation(title="属性修改")
*/
#[NodeAnnotation(title: '属性修改', auth: true)]
public function modify(Request $request): void
{
$this->checkPostRequest();

View File

@@ -11,11 +11,7 @@ use app\admin\service\annotation\NodeAnnotation;
use app\Request;
use think\App;
/**
* @ControllerAnnotation(title="角色权限管理")
* Class Auth
* @package app\admin\controller\system
*/
#[ControllerAnnotation(title: '角色权限管理', auth: true)]
class Auth extends AdminController
{
@@ -30,9 +26,7 @@ class Auth extends AdminController
$this->model = new SystemAuth();
}
/**
* @NodeAnnotation(title="授权")
*/
#[NodeAnnotation(title: '授权', auth: true)]
public function authorize(Request $request, $id): string
{
$row = $this->model->find($id);
@@ -45,9 +39,7 @@ class Auth extends AdminController
return $this->fetch();
}
/**
* @NodeAnnotation(title="授权保存")
*/
#[NodeAnnotation(title: '授权保存', auth: true)]
public function saveAuthorize(Request $request): void
{
$this->checkPostRequest();

View File

@@ -9,14 +9,9 @@ use app\admin\service\annotation\ControllerAnnotation;
use app\admin\service\annotation\NodeAnnotation;
use app\Request;
use think\App;
use think\facade\Cache;
use think\response\Json;
/**
* Class Config
* @package app\admin\controller\system
* @ControllerAnnotation(title="系统配置管理")
*/
#[ControllerAnnotation(title: '系统配置管理')]
class Config extends AdminController
{
@@ -28,17 +23,13 @@ class Config extends AdminController
$this->assign('editor_types', config('admin.editor_types'));
}
/**
* @NodeAnnotation(title="列表")
*/
#[NodeAnnotation(title: '列表', auth: true)]
public function index(Request $request): Json|string
{
return $this->fetch();
}
/**
* @NodeAnnotation(title="保存")
*/
#[NodeAnnotation(title: '保存', auth: true)]
public function save(Request $request): void
{
$this->checkPostRequest();

View File

@@ -3,7 +3,6 @@
namespace app\admin\controller\system;
use app\admin\service\curd\BuildCurd;
use app\admin\service\curd\exceptions\TableException;
use app\common\controller\AdminController;
use app\admin\service\annotation\ControllerAnnotation;
use app\admin\service\annotation\NodeAnnotation;
@@ -15,24 +14,16 @@ use think\facade\Db;
use think\helper\Str;
use think\response\Json;
/**
* @ControllerAnnotation(title="CURD可视化管理")
* @package app\admin\controller\system
*/
#[ControllerAnnotation(title: 'CURD可视化管理')]
class CurdGenerate extends AdminController
{
/**
* @NodeAnnotation(title="列表")
*/
#[NodeAnnotation(title: '列表', auth: true)]
public function index(Request $request): Json|string
{
return $this->fetch();
}
/**
* @NodeAnnotation(title="操作")
* @throws TableException
*/
#[NodeAnnotation(title: '操作', auth: true)]
public function save(Request $request, string $type = ''): ?Json
{
if (!$request->isAjax()) $this->error();

View File

@@ -3,6 +3,7 @@
namespace app\admin\controller\system;
use app\admin\model\SystemLog;
use app\admin\service\annotation\MiddlewareAnnotation;
use app\admin\service\tool\CommonTool;
use app\common\controller\AdminController;
use app\admin\service\annotation\ControllerAnnotation;
@@ -15,24 +16,16 @@ use think\db\exception\PDOException;
use think\facade\Db;
use think\response\Json;
/**
* @ControllerAnnotation(title="操作日志管理")
* Class Auth
* @package app\admin\controller\system
*/
#[ControllerAnnotation(title: '操作日志管理')]
class Log extends AdminController
{
protected array $ignoreLog = ['record'];
public function __construct(App $app)
{
parent::__construct($app);
$this->model = new SystemLog();
}
/**
* @NodeAnnotation(title="列表")
*/
#[NodeAnnotation(title: '列表', auth: true)]
public function index(Request $request): Json|string
{
if ($request->isAjax()) {
@@ -60,9 +53,7 @@ class Log extends AdminController
return $this->fetch();
}
/**
* @NodeAnnotation(title="导出")
*/
#[NodeAnnotation(title: '导出', auth: true)]
public function export(): bool
{
if (env('EASYADMIN.IS_DEMO', false)) {
@@ -96,9 +87,8 @@ class Log extends AdminController
return Excel::exportData($list, $header, $fileName, 'xlsx');
}
/**
* @NodeAnnotation(title="框架日志")
*/
#[MiddlewareAnnotation(ignore: MiddlewareAnnotation::IGNORE_LOG)]
#[NodeAnnotation(title: '框架日志', auth: true, ignore: NodeAnnotation::IGNORE_NODE)]
public function record(): Json|string
{
return (new \Wolfcode\PhpLogviewer\thinkphp\LogViewer())->fetch();

View File

@@ -11,14 +11,9 @@ use app\admin\service\annotation\NodeAnnotation;
use app\common\controller\AdminController;
use app\Request;
use think\App;
use think\db\exception\DbException;
use think\response\Json;
/**
* Class Menu
* @package app\admin\controller\system
* @ControllerAnnotation(title="菜单管理",auth=true)
*/
#[ControllerAnnotation(title: '菜单管理')]
class Menu extends AdminController
{
@@ -33,10 +28,7 @@ class Menu extends AdminController
$this->model = new SystemMenu();
}
/**
* @NodeAnnotation(title="列表")
* @throws DbException
*/
#[NodeAnnotation(title: '列表', auth: true)]
public function index(Request $request): Json|string
{
if ($request->isAjax()) {
@@ -56,9 +48,7 @@ class Menu extends AdminController
return $this->fetch();
}
/**
* @NodeAnnotation(title="添加")
*/
#[NodeAnnotation(title: '添加', auth: true)]
public function add(Request $request): string
{
$id = $request->param('id');
@@ -92,9 +82,7 @@ class Menu extends AdminController
return $this->fetch();
}
/**
* @NodeAnnotation(title="编辑")
*/
#[NodeAnnotation(title: '编辑', auth: true)]
public function edit(Request $request, $id = 0): string
{
$row = $this->model->find($id);
@@ -129,9 +117,7 @@ class Menu extends AdminController
return $this->fetch();
}
/**
* @NodeAnnotation(title="删除")
*/
#[NodeAnnotation(title: '删除', auth: true)]
public function delete(Request $request): void
{
$this->checkPostRequest();
@@ -151,9 +137,7 @@ class Menu extends AdminController
}
}
/**
* @NodeAnnotation(title="属性修改")
*/
#[NodeAnnotation(title: '属性修改', auth: true)]
public function modify(Request $request): void
{
$this->checkPostRequest();
@@ -190,9 +174,7 @@ class Menu extends AdminController
$this->success('保存成功');
}
/**
* @NodeAnnotation(title="添加菜单提示")
*/
#[NodeAnnotation(title: '添加菜单提示', auth: true)]
public function getMenuTips(): Json
{
$node = input('get.keywords');

View File

@@ -10,14 +10,9 @@ use app\admin\service\annotation\NodeAnnotation;
use app\admin\service\NodeService;
use app\Request;
use think\App;
use think\db\exception\DbException;
use think\response\Json;
/**
* @ControllerAnnotation(title="系统节点管理")
* Class Node
* @package app\admin\controller\system
*/
#[ControllerAnnotation(title: '系统节点管理')]
class Node extends AdminController
{
@@ -27,10 +22,7 @@ class Node extends AdminController
$this->model = new SystemNode();
}
/**
* @NodeAnnotation(title="列表")
* @throws DbException
*/
#[NodeAnnotation(title: '列表', auth: true)]
public function index(Request $request): Json|string
{
if ($request->isAjax()) {
@@ -52,9 +44,7 @@ class Node extends AdminController
return $this->fetch();
}
/**
* @NodeAnnotation(title="系统节点更新")
*/
#[NodeAnnotation(title: '系统节点更新', auth: true)]
public function refreshNode($force = 0): void
{
@@ -94,9 +84,7 @@ class Node extends AdminController
$this->success('节点更新成功');
}
/**
* @NodeAnnotation(title="清除失效节点")
*/
#[NodeAnnotation(title: '清除失效节点', auth: true)]
public function clearNode(): void
{
$this->checkPostRequest();

View File

@@ -9,11 +9,7 @@ use app\admin\service\annotation\ControllerAnnotation;
use app\admin\service\annotation\NodeAnnotation;
use think\App;
/**
* @ControllerAnnotation(title="快捷入口管理")
* Class Quick
* @package app\admin\controller\system
*/
#[ControllerAnnotation(title: '快捷入口管理')]
class Quick extends AdminController
{

View File

@@ -8,10 +8,7 @@ use app\admin\service\annotation\ControllerAnnotation;
use app\admin\service\annotation\NodeAnnotation;
use think\App;
/**
* @ControllerAnnotation(title="上传文件管理")
* @package app\admin\controller\system
*/
#[ControllerAnnotation(title: '上传文件管理')]
class Uploadfile extends AdminController
{

View File

@@ -3,6 +3,7 @@
namespace app\admin\middleware;
use app\admin\service\annotation\ControllerAnnotation;
use app\admin\service\annotation\MiddlewareAnnotation;
use app\admin\service\annotation\NodeAnnotation;
use app\admin\service\SystemLogService;
use app\common\traits\JumpTrait;
@@ -59,6 +60,15 @@ class SystemLog
$_controller = ucfirst($pathInfoExp[1] ?? '');
$className = $_controller ? "app\admin\controller\\{$_name}\\{$_controller}" : "app\admin\controller\\{$_name}";
if ($_name && $_action) {
$reflectionMethod = new \ReflectionMethod($className, $_action);
$attributes = $reflectionMethod->getAttributes(MiddlewareAnnotation::class);
foreach ($attributes as $attribute) {
$annotation = $attribute->newInstance();
$_ignore = (array)$annotation->ignore;
if (in_array('log', array_map('strtolower', $_ignore))) return $response;
}
// 支持旧写法
$reflectionClass = new \ReflectionClass($className);
$properties = $reflectionClass->getDefaultProperties();
$ignoreLog = $properties['ignoreLog'] ?? [];

View File

@@ -2,38 +2,20 @@
namespace app\admin\service\annotation;
use Doctrine\Common\Annotations\Annotation\Attributes;
use Doctrine\Common\Annotations\Annotation\Required;
use Doctrine\Common\Annotations\Annotation\Target;
use Attribute;
/**
* Class ControllerAnnotation
*
* @Annotation
* @Target("CLASS")
* @Attributes({
* @Attribute("title", type="string"),
* })
*
* @since 2.0
* controller 节点注解类
*/
#[Attribute]
final class ControllerAnnotation
{
/**
* Route group prefix for the controller
*
* @Required()
*
* @var string
* @param string $title
* @param bool $auth 是否需要权限
* @param string|array $ignore
*/
public $title = '';
/**
* 是否开启权限控制
* @Enum({true,false})
* @var bool
*/
public $auth = true;
public function __construct(public string $title = '', public bool $auth = true, public string|array $ignore = '')
{
}
}

View File

@@ -0,0 +1,16 @@
<?php
namespace app\admin\service\annotation;
use Attribute;
#[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_METHOD)]
final class MiddlewareAnnotation
{
/** 过滤日志 */
const IGNORE_LOG = 'LOG';
public function __construct(public string $type = '', public string|array $ignore = '')
{
}
}

View File

@@ -3,31 +3,24 @@
namespace app\admin\service\annotation;
use Doctrine\Common\Annotations\Annotation\Attributes;
use Attribute;
/**
* 创建节点注解类
*
* @Annotation
* @Target({"METHOD","CLASS"})
* @Attributes({
* @Attribute("time", type = "int")
* })
* action 节点注解类
*/
#[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_METHOD)]
final class NodeAnnotation
{
/** 过滤节点 */
const IGNORE_NODE = 'NODE';
/**
* 节点名称
* @Required()
* @var string
* @param string $title
* @param bool $auth 是否需要权限
* @param string|array $ignore
*/
public string $title;
/**
* 是否开启权限控制
* @Enum({true,false})
* @var bool
*/
public bool $auth = true;
public function __construct(public string $title = '', public bool $auth = true, public string|array $ignore = '')
{
}
}

View File

@@ -68,20 +68,14 @@ class Node
// 遍历读取所有方法的注释的参数信息
foreach ($methods as $method) {
// 忽略的节点
$properties = $reflectionClass->getDefaultProperties();
$ignoreNode = $properties['ignoreNode'] ?? [];
if (!empty($ignoreNode)) if (in_array($method->name, $ignoreNode)) continue;
// 读取NodeAnnotation的注解
$nodeAnnotation = $reader->getMethodAnnotation($method, NodeAnnotation::class);
if (!empty($nodeAnnotation)) {
$actionTitle = !empty($nodeAnnotation->title) ? $nodeAnnotation->title : null;
$actionAuth = !empty($nodeAnnotation->auth) ? $nodeAnnotation->auth : false;
$attributes = $reflectionClass->getMethod($method->name)->getAttributes(NodeAnnotation::class);
foreach ($attributes as $attribute) {
$annotation = $attribute->newInstance();
if (!empty($annotation->ignore)) if (strtolower($annotation->ignore) == 'node') continue;
$actionList[] = [
'node' => $controllerFormat . '/' . $method->name,
'title' => $actionTitle,
'is_auth' => $actionAuth,
'title' => $annotation->title ?? null,
'is_auth' => $annotation->auth ?? null,
'type' => 2,
];
}
@@ -89,15 +83,16 @@ class Node
// 方法非空才读取控制器注解
if (!empty($actionList)) {
// 读取Controller的注解
$controllerAnnotation = $reader->getClassAnnotation($reflectionClass, ControllerAnnotation::class);
$controllerTitle = !empty($controllerAnnotation->title) ? $controllerAnnotation->title : null;
$controllerAuth = !empty($controllerAnnotation->auth) ? $controllerAnnotation->auth : false;
$nodeList[] = [
'node' => $controllerFormat,
'title' => $controllerTitle,
'is_auth' => $controllerAuth,
'type' => 1,
];
$attributes = $reflectionClass->getAttributes(ControllerAnnotation::class);
foreach ($attributes as $attribute) {
$controllerAnnotation = $attribute->newInstance();
$nodeList[] = [
'node' => $controllerFormat,
'title' => $controllerAnnotation->title ?? null,
'is_auth' => $controllerAnnotation->auth ?? false,
'type' => 1,
];
}
$nodeList = array_merge($nodeList, $actionList);
}

View File

@@ -7,9 +7,7 @@ use app\admin\service\annotation\ControllerAnnotation;
use app\admin\service\annotation\NodeAnnotation;
use think\App;
/**
* @ControllerAnnotation(title="{{controllerAnnotation}}")
*/
#[ControllerAnnotation(title: '{{controllerAnnotation}}')]
class {{controllerName}} extends AdminController
{

View File

@@ -17,9 +17,7 @@ use think\response\Json;
trait Curd
{
/**
* @NodeAnnotation(title="列表")
*/
#[NodeAnnotation(title: '列表', auth: true)]
public function index(Request $request): Json|string
{
if ($request->isAjax()) {
@@ -40,9 +38,7 @@ trait Curd
return $this->fetch();
}
/**
* @NodeAnnotation(title="添加")
*/
#[NodeAnnotation(title: '添加', auth: true)]
public function add(Request $request): string
{
if ($request->isPost()) {
@@ -61,9 +57,7 @@ trait Curd
return $this->fetch();
}
/**
* @NodeAnnotation(title="编辑")
*/
#[NodeAnnotation(title: '编辑', auth: true)]
public function edit(Request $request, $id = 0): string
{
$row = $this->model->find($id);
@@ -85,9 +79,7 @@ trait Curd
return $this->fetch();
}
/**
* @NodeAnnotation(title="删除")
*/
#[NodeAnnotation(title: '删除', auth: true)]
public function delete(Request $request): void
{
// 如果不是id作为主键 请在对应的控制器中覆盖重写
@@ -103,9 +95,7 @@ trait Curd
$save ? $this->success('删除成功') : $this->error('删除失败');
}
/**
* @NodeAnnotation(title="导出")
*/
#[NodeAnnotation(title: '导出', auth: true)]
public function export()
{
if (env('EASYADMIN.IS_DEMO', false)) {
@@ -133,9 +123,7 @@ trait Curd
return Excel::exportData($list, $header, $fileName, 'xlsx');
}
/**
* @NodeAnnotation(title="属性修改")
*/
#[NodeAnnotation(title: '属性修改', auth: true)]
public function modify(Request $request): void
{
$this->checkPostRequest();

View File

@@ -30,15 +30,15 @@
"aliyuncs/oss-sdk-php": "^2.6",
"qcloud/cos-sdk-v5": "^2.6",
"jianyan74/php-excel": "^1.0.2",
"doctrine/annotations": "^1.13",
"doctrine/annotations": "^2.0.0",
"phpoffice/phpspreadsheet": "^1.28",
"myclabs/php-enum": "^1.8",
"ext-json": "*",
"qiniu/php-sdk": "v7.11.0",
"ext-mysqli": "*",
"ext-pdo": "*",
"qiniu/php-sdk": "^7.11.0",
"wolf-leo/phplogviewer": "^0.11.3",
"wolfcode/authenticator": "^0.0.6"
"wolfcode/authenticator": "^0.0.6",
"ext-json": "*",
"ext-mysqli": "*",
"ext-pdo": "*"
},
"require-dev": {
"symfony/var-dumper": ">=4.2",