|
|
@@ -7,6 +7,7 @@ use App\Module\Cleanup\Models\CleanupPlan;
|
|
|
use App\Module\Cleanup\Models\CleanupConfig;
|
|
|
use App\Module\Cleanup\Repositories\CleanupPlanContentRepository;
|
|
|
use App\Module\Cleanup\Enums\CLEANUP_TYPE;
|
|
|
+use App\Module\Cleanup\Logics\ModelScannerLogic;
|
|
|
use UCore\DcatAdmin\AdminController;
|
|
|
use Dcat\Admin\Form;
|
|
|
use Dcat\Admin\Grid;
|
|
|
@@ -46,7 +47,29 @@ class CleanupPlanContentController extends AdminController
|
|
|
|
|
|
// 计划信息
|
|
|
$grid->column('plan.plan_name', '所属计划')->sortable();
|
|
|
- $grid->column('table_name', '表名')->sortable();
|
|
|
+
|
|
|
+ // Model/表信息
|
|
|
+ $grid->column('model_class', 'Model类')->display(function ($value) {
|
|
|
+ if (!empty($value)) {
|
|
|
+ $className = class_basename($value);
|
|
|
+ return "<span class='label label-success'>{$className}</span>";
|
|
|
+ }
|
|
|
+ return '<span class="label label-warning">未设置</span>';
|
|
|
+ })->sortable();
|
|
|
+
|
|
|
+ $grid->column('table_name', '表名')->display(function ($value) {
|
|
|
+ if (!empty($this->model_class)) {
|
|
|
+ try {
|
|
|
+ $model = new $this->model_class();
|
|
|
+ $actualTable = $model->getTable();
|
|
|
+ return "<span class='text-muted'>{$actualTable}</span>";
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ return "<span class='text-danger'>{$value} (Model错误)</span>";
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ return "<span class='text-warning'>{$value} (旧数据)</span>";
|
|
|
+ }
|
|
|
+ })->sortable();
|
|
|
|
|
|
// 清理类型
|
|
|
$grid->column('cleanup_type', '清理类型')->using([
|
|
|
@@ -87,7 +110,22 @@ class CleanupPlanContentController extends AdminController
|
|
|
// 按计划筛选
|
|
|
$plans = CleanupPlan::pluck('plan_name', 'id')->toArray();
|
|
|
$filter->equal('plan_id', '所属计划')->select($plans);
|
|
|
-
|
|
|
+
|
|
|
+ // 数据类型筛选
|
|
|
+ $filter->where(function ($query) {
|
|
|
+ $type = $this->input;
|
|
|
+ if ($type === 'model') {
|
|
|
+ $query->whereNotNull('model_class')->where('model_class', '!=', '');
|
|
|
+ } elseif ($type === 'table') {
|
|
|
+ $query->where(function($q) {
|
|
|
+ $q->whereNull('model_class')->orWhere('model_class', '');
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }, '数据类型')->select([
|
|
|
+ 'model' => '基于Model类',
|
|
|
+ 'table' => '基于表名(旧数据)',
|
|
|
+ ]);
|
|
|
+
|
|
|
// 按清理类型筛选
|
|
|
$filter->equal('cleanup_type', '清理类型')->select([
|
|
|
1 => '清空表',
|
|
|
@@ -119,6 +157,7 @@ class CleanupPlanContentController extends AdminController
|
|
|
$grid->batchActions([
|
|
|
new \App\Module\Cleanup\AdminControllers\Actions\BatchEnableAction(),
|
|
|
new \App\Module\Cleanup\AdminControllers\Actions\BatchDisableAction(),
|
|
|
+ new \App\Module\Cleanup\AdminControllers\Actions\BatchMigrateToModelAction(),
|
|
|
]);
|
|
|
|
|
|
// 行操作
|
|
|
@@ -126,6 +165,7 @@ class CleanupPlanContentController extends AdminController
|
|
|
$actions->append(new \App\Module\Cleanup\AdminControllers\Actions\EditPlanContentAction());
|
|
|
$actions->append(new \App\Module\Cleanup\AdminControllers\Actions\DeletePlanContentAction());
|
|
|
$actions->append(new \App\Module\Cleanup\AdminControllers\Actions\TestCleanupAction());
|
|
|
+ $actions->append(new \App\Module\Cleanup\AdminControllers\Actions\MigrateToModelAction());
|
|
|
});
|
|
|
|
|
|
// 设置每页显示数量
|
|
|
@@ -143,7 +183,28 @@ class CleanupPlanContentController extends AdminController
|
|
|
|
|
|
// 关联信息
|
|
|
$show->field('plan.plan_name', '所属计划');
|
|
|
- $show->field('table_name', '表名');
|
|
|
+
|
|
|
+ // Model/表信息
|
|
|
+ $show->field('model_class', 'Model类')->as(function ($value) {
|
|
|
+ if (!empty($value)) {
|
|
|
+ return $value;
|
|
|
+ } else {
|
|
|
+ return '未设置(旧数据)';
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ $show->field('table_name', '表名')->as(function ($value) {
|
|
|
+ if (!empty($this->model_class)) {
|
|
|
+ try {
|
|
|
+ $model = new $this->model_class();
|
|
|
+ return $model->getTable() . ' (从Model获取)';
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ return $value . ' (Model错误: ' . $e->getMessage() . ')';
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ return $value . ' (旧数据)';
|
|
|
+ }
|
|
|
+ });
|
|
|
|
|
|
// 清理配置
|
|
|
$show->field('cleanup_type', '清理类型')->using([
|
|
|
@@ -185,12 +246,37 @@ class CleanupPlanContentController extends AdminController
|
|
|
->options(CleanupPlan::pluck('plan_name', 'id')->toArray())
|
|
|
->required();
|
|
|
|
|
|
- // 表名选择(可以从已有配置中选择或手动输入)
|
|
|
- $availableTables = CleanupConfig::pluck('table_name', 'table_name')->toArray();
|
|
|
- $form->select('table_name', '表名')
|
|
|
- ->options($availableTables)
|
|
|
- ->required()
|
|
|
- ->help('选择要清理的数据表');
|
|
|
+ // Model类选择(推荐使用)
|
|
|
+ $availableModels = $this->getAvailableModels();
|
|
|
+ $form->select('model_class', 'Model类')
|
|
|
+ ->options($availableModels)
|
|
|
+ ->help('选择要清理的Model类(推荐使用)')
|
|
|
+ ->when('!=', '', function (Form $form) {
|
|
|
+ // 当选择了Model类时,自动填充表名
|
|
|
+ $form->display('auto_table_name', '自动获取表名')->with(function ($value, $model) {
|
|
|
+ if (!empty($model->model_class)) {
|
|
|
+ try {
|
|
|
+ $modelInstance = new $model->model_class();
|
|
|
+ return $modelInstance->getTable();
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ return 'Model错误: ' . $e->getMessage();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return '请先选择Model类';
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ // 表名选择(兼容旧数据)
|
|
|
+ $availableTables = CleanupConfig::whereNull('model_class')
|
|
|
+ ->orWhere('model_class', '')
|
|
|
+ ->pluck('table_name', 'table_name')
|
|
|
+ ->toArray();
|
|
|
+
|
|
|
+ if (!empty($availableTables)) {
|
|
|
+ $form->select('table_name', '表名(兼容旧数据)')
|
|
|
+ ->options($availableTables)
|
|
|
+ ->help('仅用于兼容旧数据,建议使用Model类选择');
|
|
|
+ }
|
|
|
|
|
|
// 清理类型
|
|
|
$form->select('cleanup_type', '清理类型')
|
|
|
@@ -229,9 +315,107 @@ class CleanupPlanContentController extends AdminController
|
|
|
$form->textarea('notes', '备注说明')
|
|
|
->help('对此清理配置的说明');
|
|
|
|
|
|
+ // 表单验证
|
|
|
+ $form->saving(function (Form $form) {
|
|
|
+ // 验证至少选择了Model类或表名
|
|
|
+ if (empty($form->model_class) && empty($form->table_name)) {
|
|
|
+ return $form->response()->error('请至少选择Model类或表名');
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果选择了Model类,验证Model是否存在
|
|
|
+ if (!empty($form->model_class)) {
|
|
|
+ if (!class_exists($form->model_class)) {
|
|
|
+ return $form->response()->error('选择的Model类不存在:' . $form->model_class);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 自动设置表名
|
|
|
+ try {
|
|
|
+ $modelInstance = new $form->model_class();
|
|
|
+ $form->table_name = $modelInstance->getTable();
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ return $form->response()->error('Model类实例化失败:' . $e->getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
// 时间字段
|
|
|
$form->display('created_at', '创建时间');
|
|
|
$form->display('updated_at', '更新时间');
|
|
|
+
|
|
|
+ // 添加JavaScript增强用户体验
|
|
|
+ $form->html('
|
|
|
+ <script>
|
|
|
+ $(document).ready(function() {
|
|
|
+ // 监听Model类选择变化
|
|
|
+ $(document).on("change", "select[name=model_class]", function() {
|
|
|
+ var modelClass = $(this).val();
|
|
|
+ if (modelClass) {
|
|
|
+ // 显示提示信息
|
|
|
+ var className = modelClass.split("\\\\").pop();
|
|
|
+ var moduleName = modelClass.match(/App\\\\Module\\\\([^\\\\]+)\\\\/);
|
|
|
+ moduleName = moduleName ? moduleName[1] : "Unknown";
|
|
|
+
|
|
|
+ // 创建提示信息
|
|
|
+ var infoHtml = "<div class=\"alert alert-info\">" +
|
|
|
+ "<strong>已选择Model:</strong>" + className + "<br>" +
|
|
|
+ "<strong>所属模块:</strong>" + moduleName + "<br>" +
|
|
|
+ "<strong>建议:</strong>使用Model类可以利用Laravel的所有特性,如软删除、事件等" +
|
|
|
+ "</div>";
|
|
|
+
|
|
|
+ // 移除旧的提示信息
|
|
|
+ $(".model-info-alert").remove();
|
|
|
+
|
|
|
+ // 添加新的提示信息
|
|
|
+ $(this).closest(".form-group").after("<div class=\"model-info-alert\">" + infoHtml + "</div>");
|
|
|
+ } else {
|
|
|
+ $(".model-info-alert").remove();
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // 页面加载时如果已有选择,显示提示
|
|
|
+ var initialModel = $("select[name=model_class]").val();
|
|
|
+ if (initialModel) {
|
|
|
+ $("select[name=model_class]").trigger("change");
|
|
|
+ }
|
|
|
+ });
|
|
|
+ </script>
|
|
|
+ ', '用户体验增强');
|
|
|
});
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取可用的Model类列表
|
|
|
+ */
|
|
|
+ private function getAvailableModels(): array
|
|
|
+ {
|
|
|
+ // 从CleanupConfig中获取已配置的Model类
|
|
|
+ $configuredModels = CleanupConfig::whereNotNull('model_class')
|
|
|
+ ->where('model_class', '!=', '')
|
|
|
+ ->pluck('model_class', 'model_class')
|
|
|
+ ->toArray();
|
|
|
+
|
|
|
+ // 格式化显示名称
|
|
|
+ $formattedModels = [];
|
|
|
+ foreach ($configuredModels as $modelClass) {
|
|
|
+ $className = class_basename($modelClass);
|
|
|
+ $moduleName = $this->extractModuleName($modelClass);
|
|
|
+ $formattedModels[$modelClass] = "{$moduleName} - {$className}";
|
|
|
+ }
|
|
|
+
|
|
|
+ // 按模块和类名排序
|
|
|
+ asort($formattedModels);
|
|
|
+
|
|
|
+ return $formattedModels;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 从Model类名中提取模块名
|
|
|
+ */
|
|
|
+ private function extractModuleName(string $modelClass): string
|
|
|
+ {
|
|
|
+ if (preg_match('/App\\\\Module\\\\([^\\\\]+)\\\\Models\\\\/', $modelClass, $matches)) {
|
|
|
+ return $matches[1];
|
|
|
+ }
|
|
|
+ return 'Unknown';
|
|
|
+ }
|
|
|
}
|