DialogTree.php 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. <?php
  2. namespace Dcat\Admin\Grid\Displayers;
  3. use Dcat\Admin\Admin;
  4. use Dcat\Admin\Support\Helper;
  5. use Illuminate\Contracts\Support\Arrayable;
  6. class DialogTree extends AbstractDisplayer
  7. {
  8. public static $js = '@jstree';
  9. public static $css = '@jstree';
  10. protected $url;
  11. protected $title;
  12. protected $area = ['650px', '600px'];
  13. protected $options = [
  14. 'plugins' => ['checkbox', 'types'],
  15. 'core' => [
  16. 'check_callback' => true,
  17. 'themes' => [
  18. 'name' => 'proton',
  19. 'responsive' => true,
  20. ],
  21. ],
  22. 'checkbox' => [
  23. 'keep_selected_style' => false,
  24. ],
  25. 'types' => [
  26. 'default' => [
  27. 'icon' => false,
  28. ],
  29. ],
  30. ];
  31. /**
  32. * @var array
  33. */
  34. protected $columnNames = [
  35. 'id' => 'id',
  36. 'text' => 'name',
  37. 'parent' => 'parent_id',
  38. ];
  39. protected $nodes = [];
  40. protected $checkAll;
  41. /**
  42. * @param array $data exp:
  43. * {
  44. * "id": "1",
  45. * "parent": "#",
  46. * "text": "Dashboard",
  47. * // "state": {"selected": true}
  48. * }
  49. * @param array $data
  50. *
  51. * @return $this
  52. */
  53. public function nodes($data)
  54. {
  55. if ($data instanceof Arrayable) {
  56. $data = $data->toArray();
  57. }
  58. $this->nodes = &$data;
  59. return $this;
  60. }
  61. public function url(string $source)
  62. {
  63. $this->url = admin_url($source);
  64. return $this;
  65. }
  66. public function checkAll()
  67. {
  68. $this->checkAll = true;
  69. return $this;
  70. }
  71. /**
  72. * @param array $options
  73. *
  74. * @return $this
  75. */
  76. public function options($options = [])
  77. {
  78. if ($options instanceof Arrayable) {
  79. $options = $options->toArray();
  80. }
  81. $this->options = array_merge($this->options, $options);
  82. return $this;
  83. }
  84. public function title($title)
  85. {
  86. $this->title = $title;
  87. return $this;
  88. }
  89. /**
  90. * @param string $width
  91. * @param string $height
  92. *
  93. * @return $this
  94. */
  95. public function area(string $width, string $height)
  96. {
  97. $this->area = [$width, $height];
  98. return $this;
  99. }
  100. public function setIdColumn(string $name)
  101. {
  102. $this->columnNames['id'] = $name;
  103. return $this;
  104. }
  105. public function setTitleColumn(string $name)
  106. {
  107. $this->columnNames['text'] = $name;
  108. return $this;
  109. }
  110. public function setParentColumn(string $name)
  111. {
  112. $this->columnNames['parent'] = $name;
  113. return $this;
  114. }
  115. public function display($callbackOrNodes = null)
  116. {
  117. if (is_array($callbackOrNodes) || $callbackOrNodes instanceof Arrayable) {
  118. $this->nodes($callbackOrNodes);
  119. } elseif ($callbackOrNodes instanceof \Closure) {
  120. $callbackOrNodes->call($this->row, $this);
  121. }
  122. $btn = $this->trans('view');
  123. $this->setupScript();
  124. $val = $this->format($this->value);
  125. return <<<EOF
  126. <a href="javascript:void(0)" class="{$this->getSelectorPrefix()}-open-tree" data-checked="{$this->checkAll}" data-val="{$val}">
  127. <i class='feather icon-align-right'></i> $btn
  128. </a>
  129. EOF;
  130. }
  131. protected function format($val)
  132. {
  133. return implode(',', Helper::array($val, true));
  134. }
  135. protected function getSelectorPrefix()
  136. {
  137. return $this->grid->getName().'_'.$this->column->getName();
  138. }
  139. protected function setupScript()
  140. {
  141. $title = $this->title ?: $this->column->getLabel();
  142. $area = json_encode($this->area);
  143. $opts = json_encode($this->options);
  144. $nodes = json_encode($this->nodes);
  145. Admin::script(
  146. <<<JS
  147. $('.{$this->getSelectorPrefix()}-open-tree').off('click').on('click', function () {
  148. var tpl = '<div class="jstree-wrapper p-1" style="border:0"><div class="da-tree" style="margin-top:10px"></div></div>',
  149. url = '{$this->url}',
  150. t = $(this),
  151. val = t.data('val'),
  152. ckall = t.data('checked'),
  153. idx,
  154. requesting,
  155. opts = $opts;
  156. val = val ? String(val).split(',') : [];
  157. if (url) {
  158. if (requesting) return;
  159. requesting = 1;
  160. t.buttonLoading();
  161. $.ajax(url, {data: {value: val}}).then(function (resp) {
  162. requesting = 0;
  163. t.buttonLoading(false);
  164. if (!resp.status) {
  165. return Dcat.error(resp.message || '系统繁忙,请稍后再试');
  166. }
  167. build(resp.value);
  168. });
  169. } else {
  170. build(val);
  171. }
  172. function build(val) {
  173. opts.core.data = formatNodes(val, $nodes);
  174. idx = layer.open({
  175. type: 1,
  176. area: {$area},
  177. content: tpl,
  178. title: '{$title}',
  179. success: function (a, idx) {
  180. var tree = $('#layui-layer'+idx).find('.da-tree');
  181. tree.on("loaded.jstree", function () {
  182. tree.jstree('open_all');
  183. }).jstree(opts);
  184. }
  185. });
  186. $(document).one('pjax:complete', function () {
  187. layer.close(idx);
  188. });
  189. }
  190. function formatNodes(value, all) {
  191. var idColumn = '{$this->columnNames['id']}',
  192. textColumn = '{$this->columnNames['text']}',
  193. parentColumn = '{$this->columnNames['parent']}';
  194. var parentIds = [], nodes = [], i, v, parentId;
  195. for (i in all) {
  196. v = all[i];
  197. if (!v[idColumn]) continue;
  198. parentId = v[parentColumn] || '#';
  199. if (!parentId) {
  200. parentId = '#';
  201. } else {
  202. parentIds.push(parentId);
  203. }
  204. v['state'] = {'disabled': true};
  205. if (ckall || (value && Dcat.helpers.inObject(value, v[idColumn]))) {
  206. v['state']['selected'] = true;
  207. }
  208. nodes.push({
  209. 'id' : v[idColumn],
  210. 'text' : v[textColumn] || null,
  211. 'parent' : parentId,
  212. 'state' : v['state'],
  213. });
  214. }
  215. return nodes;
  216. }
  217. });
  218. JS
  219. );
  220. }
  221. }