ControllerHasColumnSort.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. <?php
  2. namespace App\Traits;
  3. use App\Admin\Actions\Tree\RowAction\CustomColumnDeleteAction;
  4. use App\Admin\Actions\Tree\ToolAction\ConsumableColumnSortDeleteAction;
  5. use App\Admin\Actions\Tree\ToolAction\DeviceColumnSortDeleteAction;
  6. use App\Admin\Actions\Tree\ToolAction\PartColumnSortDeleteAction;
  7. use App\Admin\Actions\Tree\ToolAction\ServiceColumnSortDeleteAction;
  8. use App\Admin\Actions\Tree\ToolAction\SoftwareColumnSortDeleteAction;
  9. use App\Admin\Repositories\ConsumableRecord;
  10. use App\Admin\Repositories\DeviceRecord;
  11. use App\Admin\Repositories\PartRecord;
  12. use App\Admin\Repositories\ServiceRecord;
  13. use App\Admin\Repositories\SoftwareRecord;
  14. use App\Form;
  15. use App\Models\ColumnSort;
  16. use App\Models\CustomColumn;
  17. use App\Support\Data;
  18. use Dcat\Admin\Admin;
  19. use Dcat\Admin\Form\NestedForm;
  20. use Dcat\Admin\Layout\Column;
  21. use Dcat\Admin\Layout\Row;
  22. use Dcat\Admin\Tree;
  23. use Dcat\Admin\Widgets\Box;
  24. use Dcat\Admin\Widgets\Form as WidgetForm;
  25. use Exception;
  26. use Illuminate\Database\Schema\Blueprint;
  27. use Illuminate\Support\Facades\Schema;
  28. trait ControllerHasColumnSort
  29. {
  30. /**
  31. * 页面渲染.
  32. *
  33. * @return Row
  34. */
  35. protected function render(): Row
  36. {
  37. return new Row(function (Column $column) {
  38. $column->row(function (Row $row) {
  39. if ($this->creatable()) {
  40. $row->column(6, $this->treeView());
  41. $row->column(6, function (Column $column) {
  42. $column->row($this->createBox());
  43. });
  44. } else {
  45. $row->column(12, $this->treeView());
  46. }
  47. });
  48. });
  49. }
  50. /**
  51. * 判断当前实例和权限,是否有可创建的权限.
  52. *
  53. * @return bool
  54. */
  55. public function creatable(): bool
  56. {
  57. $repository = $this->repository();
  58. $creatable = false;
  59. // @permissions
  60. if ($repository instanceof DeviceRecord && Admin::user()->can('device.column.create')) {
  61. $creatable = true;
  62. }
  63. if ($repository instanceof PartRecord && Admin::user()->can('part.column.create')) {
  64. $creatable = true;
  65. }
  66. if ($repository instanceof SoftwareRecord && Admin::user()->can('software.column.create')) {
  67. $creatable = true;
  68. }
  69. if ($repository instanceof ConsumableRecord && Admin::user()->can('consumable.column.create')) {
  70. $creatable = true;
  71. }
  72. if ($repository instanceof ServiceRecord && Admin::user()->can('service.column.create')) {
  73. $creatable = true;
  74. }
  75. return $creatable;
  76. }
  77. /**
  78. * 模型树渲染,也就是字段排序的那块.
  79. *
  80. * @return Tree
  81. */
  82. protected function treeView(): Tree
  83. {
  84. $repository = $this->repository();
  85. $repository = new $repository();
  86. return new Tree($repository, function (Tree $tree) use ($repository) {
  87. $tree->maxDepth(1);
  88. /**
  89. * 行操作按钮.
  90. */
  91. $deletable = $this->deletable();
  92. $tree->actions(function (Tree\Actions $actions) use ($repository, $deletable) {
  93. $custom_column = CustomColumn::where('table_name', $repository->getTable())
  94. ->where('name', $actions->getRow()->title)
  95. ->first();
  96. if (!empty($custom_column) && $deletable) {
  97. $form_data = [
  98. 'table_name' => $repository->getTable(),
  99. 'name' => $actions->getRow()->title
  100. ];
  101. $html = '<i class="fa fa-fw feather icon-edit"></i>';
  102. $actions->append('<a href="' . admin_route('columns.update', $form_data) . '">' . $html . admin_trans('main.update_column') . '</a>');
  103. $actions->append('&nbsp;&nbsp;&nbsp;&nbsp;');
  104. $actions->append(new CustomColumnDeleteAction($repository->getTable(), $actions->getRow()->title));
  105. }
  106. $actions->disableQuickEdit();
  107. $actions->disableEdit();
  108. $actions->disableDelete();
  109. });
  110. $tree->tools(function (Tree\Tools $tools) {
  111. // @permissions
  112. if ($this->repository() instanceof DeviceRecord && Admin::user()->can('device.column.sort.delete')) {
  113. $tools->add(new DeviceColumnSortDeleteAction());
  114. }
  115. // @permissions
  116. if ($this->repository() instanceof PartRecord && Admin::user()->can('part.column.sort.delete')) {
  117. $tools->add(new PartColumnSortDeleteAction());
  118. }
  119. // @permissions
  120. if ($this->repository() instanceof SoftwareRecord && Admin::user()->can('software.column.sort.delete')) {
  121. $tools->add(new SoftwareColumnSortDeleteAction());
  122. }
  123. // @permissions
  124. if ($this->repository() instanceof ConsumableRecord && Admin::user()->can('consumable.column.sort.delete')) {
  125. $tools->add(new ConsumableColumnSortDeleteAction());
  126. }
  127. // @permissions
  128. if ($this->repository() instanceof ServiceRecord && Admin::user()->can('service.column.sort.delete')) {
  129. $tools->add(new ServiceColumnSortDeleteAction());
  130. }
  131. });
  132. /**
  133. * 按钮控制.
  134. */
  135. $tree->disableCreateButton();
  136. $tree->disableQuickCreateButton();
  137. $tree->disableDeleteButton();
  138. });
  139. }
  140. /**
  141. * 判断当前实例和权限,是否有可创建的权限.
  142. *
  143. * @return bool
  144. */
  145. public function deletable(): bool
  146. {
  147. $repository = $this->repository();
  148. $deletable = false;
  149. // @permissions
  150. if ($repository instanceof DeviceRecord && Admin::user()->can('device.column.delete')) {
  151. $deletable = true;
  152. }
  153. if ($repository instanceof PartRecord && Admin::user()->can('part.column.delete')) {
  154. $deletable = true;
  155. }
  156. if ($repository instanceof SoftwareRecord && Admin::user()->can('software.column.delete')) {
  157. $deletable = true;
  158. }
  159. if ($repository instanceof ConsumableRecord && Admin::user()->can('consumable.column.delete')) {
  160. $deletable = true;
  161. }
  162. if ($repository instanceof ServiceRecord && Admin::user()->can('service.column.delete')) {
  163. $deletable = true;
  164. }
  165. return $deletable;
  166. }
  167. /**
  168. * 表单渲染,也就是新建字段那块.
  169. *
  170. * @return Box
  171. */
  172. protected function createBox(): Box
  173. {
  174. $form = new WidgetForm();
  175. $form->text('name')
  176. ->help(admin_trans_label('Name Help'))
  177. ->required();
  178. $form->text('nick_name')
  179. ->help(admin_trans_label('Nick Name Help'))
  180. ->required();
  181. $form->select('type')
  182. ->when('select', function (WidgetForm $form) {
  183. $form->table('select_options', function (NestedForm $table) {
  184. $table->text('item');
  185. });
  186. })
  187. ->options(Data::customColumnTypes())
  188. ->required();
  189. $form->radio('must')
  190. ->options(['否', '是'])
  191. ->help(admin_trans_label('Must Help'))
  192. ->default(0);
  193. return Box::make(trans('admin.new'), $form);
  194. }
  195. /**
  196. * Make a form builder.
  197. *
  198. * @return Form
  199. */
  200. protected function form(): Form
  201. {
  202. $repository = $this->repository();
  203. $repository = new $repository();
  204. return Form::make($repository, function (Form $form) use ($repository) {
  205. /**
  206. * 拦截saving回调,是为了实现字段排序,因为默认是对DeviceRecord做数据处理
  207. * 但是DeviceRecord重写了数据仓库中toTree方法后,就变成了模型树排序也会走到这个方法中
  208. * 因此要做拦截,然后在拦截中做判断.
  209. */
  210. $form->saving(function (Form $form) use ($repository) {
  211. $table_name = $repository->getTable();
  212. /**
  213. * 如果请求中包含了_order字段,就表示这个请求是排序,而不是DeviceRecord的表单提交
  214. * 这里做判断是为了区别是排序还是对DeviceRecord数据做处理.
  215. */
  216. if (request()->has('_order')) {
  217. // orders的索引代表排序,orders['id']代表现在数据表中的排序
  218. $needle_columns = $repository->sortNeedleColumns($table_name);
  219. $orders = request('_order');
  220. $orders = json_decode($orders, true);
  221. foreach ($orders as $key => $order) {
  222. $column_name = $needle_columns[$order['id']];
  223. $column_sort = ColumnSort::where('table_name', $table_name)
  224. ->where('name', $column_name)
  225. ->first();
  226. if (empty($column_sort)) {
  227. $column_sort = new ColumnSort();
  228. }
  229. $column_sort->table_name = $table_name;
  230. $column_sort->name = $column_name;
  231. $column_sort->order = $key;
  232. $column_sort->save();
  233. }
  234. return $form->response()
  235. ->success(trans('main.success'))
  236. ->refresh();
  237. } else {
  238. /**
  239. * 这里是对字段创建拦截处理,拦截表单提交后自行代码实现字段新建的动作
  240. * 然后直接return请求,达到拦截并转而创建字段的目的.
  241. */
  242. $exist_columns = Schema::getColumnListing($table_name);
  243. if (in_array($form->input('name'), $exist_columns)) {
  244. return $form->response()
  245. ->error(trans('main.record_same'));
  246. }
  247. $custom_column = new CustomColumn();
  248. $custom_column->table_name = $table_name;
  249. $custom_column->name = $form->input('name');
  250. $custom_column->nick_name = $form->input('nick_name');
  251. $custom_column->type = $form->input('type');
  252. if ($custom_column->type == 'select') {
  253. $custom_column->select_options = $form->input('select_options');
  254. }
  255. $custom_column->must = $form->input('must');
  256. /**
  257. * 创建自定义字段的数据库迁移动作.
  258. */
  259. if ($custom_column->save()) {
  260. try {
  261. Schema::table($table_name, function (Blueprint $table) use ($custom_column) {
  262. $type = $custom_column->type;
  263. if ($type == 'select') {
  264. $type = 'string';
  265. }
  266. if ((bool)$custom_column->must == 0 || ($type == 'date' || $type == 'dateTime' || $type == 'select')) {
  267. $table->$type($custom_column->name)->nullable();
  268. } else {
  269. $table->$type($custom_column->name)->default(0);
  270. }
  271. });
  272. return $form->response()
  273. ->success(trans('main.success'))
  274. ->refresh();
  275. } catch (Exception $exception) {
  276. return $form->response()
  277. ->error(trans('main.fail') . ':' . $exception->getMessage());
  278. }
  279. } else {
  280. return $form->response()
  281. ->error(trans('main.fail'));
  282. }
  283. }
  284. });
  285. });
  286. }
  287. }