Tree.php 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. <?php
  2. namespace Dcat\Admin\Form\Field;
  3. use Dcat\Admin\Admin;
  4. use Dcat\Admin\Form\Field;
  5. use Dcat\Admin\Support\Helper;
  6. use Dcat\Admin\Widgets\Checkbox as WidgetCheckbox;
  7. use Illuminate\Contracts\Support\Arrayable;
  8. use Illuminate\Support\Arr;
  9. class Tree extends Field
  10. {
  11. protected $options = [
  12. 'plugins' => ['checkbox', 'types'],
  13. 'core' => [
  14. 'check_callback' => true,
  15. 'themes' => [
  16. 'name' => 'proton',
  17. 'responsive' => true,
  18. ],
  19. ],
  20. 'checkbox' => [
  21. 'keep_selected_style' => false,
  22. ],
  23. 'types' => [
  24. 'default' => [
  25. 'icon' => false,
  26. ],
  27. ],
  28. ];
  29. /**
  30. * @var array
  31. */
  32. protected $nodes = [];
  33. /**
  34. * @var array
  35. */
  36. protected $parents = [];
  37. /**
  38. * @var bool
  39. */
  40. protected $expand = true;
  41. /**
  42. * @var array
  43. */
  44. protected $columnNames = [
  45. 'id' => 'id',
  46. 'text' => 'name',
  47. 'parent' => 'parent_id',
  48. ];
  49. /**
  50. * @var bool
  51. */
  52. protected $filterParents = true;
  53. /**
  54. * @var bool
  55. */
  56. protected $readOnly = false;
  57. /**
  58. * @param array|Arrayable|\Closure $data exp:
  59. * {
  60. * "id": "1",
  61. * "parent": "#",
  62. * "text": "Dashboard",
  63. * // "state": {"selected": true}
  64. * }
  65. *
  66. * @return $this
  67. */
  68. public function nodes($data)
  69. {
  70. if ($data instanceof Arrayable) {
  71. $data = $data->toArray();
  72. }
  73. $this->nodes = &$data;
  74. return $this;
  75. }
  76. /**
  77. * @return $this
  78. */
  79. public function disableFilterParents()
  80. {
  81. $this->filterParents = false;
  82. return $this;
  83. }
  84. /**
  85. * Set the field as readonly mode.
  86. *
  87. * @return $this
  88. */
  89. public function readOnly()
  90. {
  91. $this->readOnly = true;
  92. return $this;
  93. }
  94. /**
  95. * @param string $idColumn
  96. * @param string $textColumn
  97. * @param string $parentColumn
  98. *
  99. * @return $this
  100. */
  101. public function name(string $idColumn = 'id', string $textColumn = 'name', string $parentColumn = 'parent_id')
  102. {
  103. $this->columnNames['id'] = $idColumn;
  104. $this->columnNames['text'] = $textColumn;
  105. $this->columnNames['parent'] = $parentColumn;
  106. return $this;
  107. }
  108. protected function formatNodes()
  109. {
  110. $value = Helper::array(
  111. old($this->column, $this->value())
  112. );
  113. $this->value = &$value;
  114. if ($this->nodes instanceof \Closure) {
  115. $this->nodes = $this->nodes->call($this->values(), $this->value(), $this);
  116. }
  117. if (! $this->nodes) {
  118. return;
  119. }
  120. $idColumn = $this->columnNames['id'];
  121. $textColumn = $this->columnNames['text'];
  122. $parentColumn = $this->columnNames['parent'];
  123. $parentIds = $nodes = [];
  124. foreach ($this->nodes as &$v) {
  125. if (empty($v[$idColumn])) {
  126. continue;
  127. }
  128. $parentId = $v[$parentColumn] ?? '#';
  129. if (empty($parentId)) {
  130. $parentId = '#';
  131. } else {
  132. $parentIds[] = $parentId;
  133. }
  134. $v['state'] = [];
  135. if ($value && in_array($v[$idColumn], $value)) {
  136. $v['state']['selected'] = true;
  137. }
  138. if ($this->readOnly) {
  139. $v['state']['disabled'] = true;
  140. }
  141. $nodes[] = [
  142. 'id' => $v[$idColumn],
  143. 'text' => $v[$textColumn] ?? null,
  144. 'parent' => $parentId,
  145. 'state' => $v['state'],
  146. ];
  147. }
  148. if ($this->filterParents) {
  149. // 筛选出所有父节点,最终点击树节点时过滤掉父节点
  150. $this->parents = array_unique($parentIds);
  151. }
  152. $this->nodes = &$nodes;
  153. }
  154. /**
  155. * Set type.
  156. *
  157. * @param array $value
  158. *
  159. * @return $this
  160. */
  161. public function type(array $value)
  162. {
  163. $this->options['types'] = array_merge($this->options['types'], $value);
  164. return $this;
  165. }
  166. /**
  167. * Set plugins.
  168. *
  169. * @param array $value
  170. *
  171. * @return $this
  172. */
  173. public function plugins(array $value)
  174. {
  175. $this->options['plugins'] = $value;
  176. return $this;
  177. }
  178. /**
  179. * Disable expand.
  180. *
  181. * @return $this
  182. */
  183. public function disableExpand()
  184. {
  185. $this->expand = false;
  186. return $this;
  187. }
  188. protected function formatFieldData($data)
  189. {
  190. $value = Arr::get($data, $this->column);
  191. return Helper::array($value, true);
  192. }
  193. /**
  194. * Prepare for saving.
  195. *
  196. * @param string|array $value
  197. *
  198. * @return array
  199. */
  200. protected function prepareToSave($value)
  201. {
  202. return Helper::array($value, true);
  203. }
  204. public function render()
  205. {
  206. $this->attribute('type', 'hidden');
  207. $checkboxes = new WidgetCheckbox();
  208. $checkboxes->style('primary');
  209. $checkboxes->inline();
  210. $checkboxes->circle(false);
  211. $checkboxes->options([
  212. 1 => trans('admin.selectall'),
  213. 2 => trans('admin.expand'),
  214. ]);
  215. if ($this->readOnly) {
  216. $checkboxes->disabled(1);
  217. }
  218. $this->expand && $checkboxes->checked(2);
  219. $this->formatNodes();
  220. if ($v = $this->value()) {
  221. $this->attribute('value', implode(',', $v));
  222. }
  223. $this->addVariables([
  224. 'checkboxes' => $checkboxes,
  225. 'options' => json_encode($this->options),
  226. 'nodes' => json_encode($this->nodes),
  227. 'expand' => $this->expand,
  228. 'disabled' => empty($this->attributes['disabled']) ? '' : 'disabled',
  229. 'parents' => json_encode($this->parents),
  230. ]);
  231. return parent::render(); // TODO: Change the autogenerated stub
  232. }
  233. public static function collectAssets()
  234. {
  235. Admin::collectAssets('jstree');
  236. }
  237. }