Tree.php 6.1 KB

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