|
| 1 | +# 自定义页面视图 |
| 2 | + |
| 3 | +`AdminController` 默认使用 `Grid`、`Form`、`Show` 组件来构建列表、新建/编辑、详情页面。如果你需要完全自定义某个页面的 HTML,可以通过实现 `custom*` 方法来替代默认行为,无需重写整个控制器方法。 |
| 4 | + |
| 5 | +## 基本用法 |
| 6 | + |
| 7 | +在子类控制器中,实现以下任意 `custom*` 方法即可接管对应页面,未实现的方法仍走原有的 `grid()`、`form()`、`detail()` 逻辑。 |
| 8 | + |
| 9 | +### 可用方法 |
| 10 | + |
| 11 | +| 方法 | 作用 | 替代原来的 | |
| 12 | +|------|------|-----------| |
| 13 | +| `customIndex()` | 自定义列表页内容 | `grid()` | |
| 14 | +| `customShow($id)` | 自定义详情页内容 | `detail($id)` | |
| 15 | +| `customCreate()` | 自定义新建页内容 | `form()` | |
| 16 | +| `customEdit($id)` | 自定义编辑页内容 | `form()->edit($id)` | |
| 17 | +| `customStore()` | 自定义新建提交处理 | `form()->store()` | |
| 18 | +| `customUpdate($id)` | 自定义更新提交处理 | `form()->update($id)` | |
| 19 | +| `customDestroy($id)` | 自定义删除处理 | `form()->destroy($id)` | |
| 20 | + |
| 21 | +### 返回值约定 |
| 22 | + |
| 23 | +**展示方法** (`customIndex`、`customShow`、`customCreate`、`customEdit`): |
| 24 | + |
| 25 | +返回值会传给 `Content::body()`,支持以下类型: |
| 26 | +- `string` — 直接输出 HTML 字符串 |
| 27 | +- `Renderable` — 如 `view()` 返回的视图、自定义 Widget |
| 28 | +- `Closure` — 回调接收 `Row` 对象,用于 Row/Column 栅格布局 |
| 29 | +- `Htmlable` — Laravel 的 `Htmlable` 接口实现 |
| 30 | + |
| 31 | +**提交方法** (`customStore`、`customUpdate`、`customDestroy`): |
| 32 | + |
| 33 | +返回 `JsonResponse` 对象以对接前端 AJAX 响应机制,在控制器中使用时需要加上 `send` 方法: |
| 34 | + |
| 35 | +```php |
| 36 | +use Dcat\Admin\Http\JsonResponse; |
| 37 | + |
| 38 | +return JsonResponse::make()->success('操作成功')->redirect('orders')->send(); |
| 39 | +``` |
| 40 | + |
| 41 | +更多 `JsonResponse` 用法请参考[动作以及表单响应](response.md)。 |
| 42 | + |
| 43 | +## 完整示例 |
| 44 | + |
| 45 | +### 所有页面自定义 |
| 46 | + |
| 47 | +```php |
| 48 | +<?php |
| 49 | + |
| 50 | +namespace App\Admin\Controllers; |
| 51 | + |
| 52 | +use App\Models\Order; |
| 53 | +use Dcat\Admin\Http\Controllers\AdminController; |
| 54 | +use Dcat\Admin\Http\JsonResponse; |
| 55 | + |
| 56 | +class OrderController extends AdminController |
| 57 | +{ |
| 58 | + protected $title = '订单管理'; |
| 59 | + |
| 60 | + // 自定义列表页 |
| 61 | + protected function customIndex() |
| 62 | + { |
| 63 | + return view('admin.order.index', [ |
| 64 | + 'orders' => Order::paginate(20), |
| 65 | + ]); |
| 66 | + } |
| 67 | + |
| 68 | + // 自定义详情页 |
| 69 | + protected function customShow($id) |
| 70 | + { |
| 71 | + return view('admin.order.show', [ |
| 72 | + 'order' => Order::findOrFail($id), |
| 73 | + ]); |
| 74 | + } |
| 75 | + |
| 76 | + // 自定义新建页 |
| 77 | + protected function customCreate() |
| 78 | + { |
| 79 | + return view('admin.order.create'); |
| 80 | + } |
| 81 | + |
| 82 | + // 自定义编辑页 |
| 83 | + protected function customEdit($id) |
| 84 | + { |
| 85 | + return view('admin.order.edit', [ |
| 86 | + 'order' => Order::findOrFail($id), |
| 87 | + ]); |
| 88 | + } |
| 89 | + |
| 90 | + // 自定义新建提交 |
| 91 | + protected function customStore() |
| 92 | + { |
| 93 | + $data = request()->validate([ |
| 94 | + 'title' => 'required|string|max:255', |
| 95 | + 'amount' => 'required|numeric|min:0', |
| 96 | + ]); |
| 97 | + |
| 98 | + $order = Order::create($data); |
| 99 | + |
| 100 | + return JsonResponse::make() |
| 101 | + ->success('创建成功') |
| 102 | + ->redirect('orders/' . $order->id) |
| 103 | + ->send(); |
| 104 | + } |
| 105 | + |
| 106 | + // 自定义更新提交 |
| 107 | + protected function customUpdate($id) |
| 108 | + { |
| 109 | + $data = request()->validate([ |
| 110 | + 'title' => 'required|string|max:255', |
| 111 | + 'amount' => 'required|numeric|min:0', |
| 112 | + ]); |
| 113 | + |
| 114 | + Order::findOrFail($id)->update($data); |
| 115 | + |
| 116 | + return JsonResponse::make() |
| 117 | + ->success('更新成功') |
| 118 | + ->redirect('orders') |
| 119 | + ->send(); |
| 120 | + } |
| 121 | + |
| 122 | + // 自定义删除 |
| 123 | + protected function customDestroy($id) |
| 124 | + { |
| 125 | + Order::destroy(explode(',', $id)); |
| 126 | + |
| 127 | + return JsonResponse::make() |
| 128 | + ->success('删除成功') |
| 129 | + ->send(); |
| 130 | + } |
| 131 | +} |
| 132 | +``` |
| 133 | + |
| 134 | +### 混合模式 |
| 135 | + |
| 136 | +可以只对部分页面使用自定义视图,其余继续使用默认组件: |
| 137 | + |
| 138 | +```php |
| 139 | +class ProductController extends AdminController |
| 140 | +{ |
| 141 | + // 列表页继续使用 Grid |
| 142 | + protected function grid() |
| 143 | + { |
| 144 | + return Grid::make(new Product(), function (Grid $grid) { |
| 145 | + $grid->column('id')->sortable(); |
| 146 | + $grid->column('name'); |
| 147 | + $grid->column('price'); |
| 148 | + }); |
| 149 | + } |
| 150 | + |
| 151 | + // 详情页继续使用 Show |
| 152 | + protected function detail($id) |
| 153 | + { |
| 154 | + return Show::make($id, new Product(), function (Show $show) { |
| 155 | + $show->field('id'); |
| 156 | + $show->field('name'); |
| 157 | + $show->field('price'); |
| 158 | + }); |
| 159 | + } |
| 160 | + |
| 161 | + // 只有新建和编辑页使用自定义视图 |
| 162 | + protected function customCreate() |
| 163 | + { |
| 164 | + return view('admin.product.create'); |
| 165 | + } |
| 166 | + |
| 167 | + protected function customEdit($id) |
| 168 | + { |
| 169 | + return view('admin.product.edit', [ |
| 170 | + 'product' => Product::findOrFail($id), |
| 171 | + ]); |
| 172 | + } |
| 173 | + |
| 174 | + protected function customStore() |
| 175 | + { |
| 176 | + // 自定义新建逻辑... |
| 177 | + } |
| 178 | + |
| 179 | + protected function customUpdate($id) |
| 180 | + { |
| 181 | + // 自定义更新逻辑... |
| 182 | + } |
| 183 | + |
| 184 | + // form() 仍然需要定义,因为 destroy 默认使用它 |
| 185 | + protected function form() |
| 186 | + { |
| 187 | + return Form::make(new Product(), function (Form $form) { |
| 188 | + $form->text('name'); |
| 189 | + $form->currency('price'); |
| 190 | + }); |
| 191 | + } |
| 192 | +} |
| 193 | +``` |
| 194 | + |
| 195 | +## 自定义样式和JS |
| 196 | + |
| 197 | +在 `custom*` 方法中,可以通过 `Admin::style()`、`Admin::css()`、`Admin::js()`、`Admin::script()` 注入页面资源: |
| 198 | + |
| 199 | +```php |
| 200 | +use Dcat\Admin\Admin; |
| 201 | + |
| 202 | +protected function customEdit($id) |
| 203 | +{ |
| 204 | + // 注入 CSS 文件 |
| 205 | + Admin::css('vendor/order/edit.css'); |
| 206 | + |
| 207 | + // 注入内联样式 |
| 208 | + Admin::style('.order-form .amount { font-weight: bold; color: #e74c3c; }'); |
| 209 | + |
| 210 | + // 注入 JS 文件 |
| 211 | + Admin::js('vendor/order/edit.js'); |
| 212 | + |
| 213 | + // 注入 JS 代码 |
| 214 | + Admin::script( |
| 215 | + <<<JS |
| 216 | +$('.order-form').on('submit', function(e) { |
| 217 | + // ... |
| 218 | +}); |
| 219 | +JS |
| 220 | + ); |
| 221 | + |
| 222 | + return view('admin.order.edit', [ |
| 223 | + 'order' => Order::findOrFail($id), |
| 224 | + ]); |
| 225 | +} |
| 226 | +``` |
| 227 | + |
| 228 | +也可以在 Blade 视图中使用 `admin_view` 来组织 HTML、CSS、JS,参考[视图与自定义页面](../getting-started/custom-page.md)。 |
| 229 | + |
| 230 | +## 使用 Row/Column 布局 |
| 231 | + |
| 232 | +展示方法支持传入闭包来使用栅格布局: |
| 233 | + |
| 234 | +```php |
| 235 | +use Dcat\Admin\Layout\Row; |
| 236 | +use Dcat\Admin\Layout\Column; |
| 237 | + |
| 238 | +protected function customShow($id) |
| 239 | +{ |
| 240 | + $order = Order::findOrFail($id); |
| 241 | + |
| 242 | + return function (Row $row) use ($order) { |
| 243 | + $row->column(8, view('admin.order.detail', compact('order'))); |
| 244 | + $row->column(4, view('admin.order.sidebar', compact('order'))); |
| 245 | + }; |
| 246 | +} |
| 247 | +``` |
0 commit comments