SelectResource.php 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. <?php
  2. namespace Dcat\Admin\Form\Field;
  3. use Dcat\Admin\Admin;
  4. use Dcat\Admin\Form\Field;
  5. use Dcat\Admin\IFrameGrid;
  6. use Dcat\Admin\Support\Helper;
  7. use Illuminate\Contracts\Support\Arrayable;
  8. class SelectResource extends Field
  9. {
  10. use PlainInput;
  11. protected static $js = [
  12. '@resource-selector',
  13. ];
  14. protected $area = ['51%', '65%'];
  15. protected $source;
  16. protected $maxItem = 1;
  17. protected $style = 'primary';
  18. protected $btnId;
  19. /**
  20. * Set window's area.
  21. *
  22. * @param string $width
  23. * @param string $height
  24. *
  25. * @return $this
  26. */
  27. public function area(string $width, string $height)
  28. {
  29. $this->area = [$width, $height];
  30. return $this;
  31. }
  32. /**
  33. * Set button style.
  34. *
  35. * @param string $style
  36. *
  37. * @return $this
  38. */
  39. public function style(string $style = 'primary')
  40. {
  41. $this->style = $style;
  42. return $this;
  43. }
  44. /**
  45. * Set the field options.
  46. *
  47. * @param array|\Closure $options
  48. *
  49. * @return $this
  50. */
  51. public function options($options = [])
  52. {
  53. if ($options instanceof Arrayable) {
  54. $options = $options->toArray();
  55. }
  56. $this->options = $options;
  57. return $this;
  58. }
  59. protected function formatOptions()
  60. {
  61. if ($this->options instanceof \Closure) {
  62. $value = Helper::array(old($this->column, $this->value()));
  63. $this->options = $this->options->call($this->values(), $value, $this);
  64. }
  65. $this->options = Helper::array($this->options);
  66. }
  67. /**
  68. * Multiple select.
  69. *
  70. * @param int|null|null $max
  71. *
  72. * @return SelectResource
  73. */
  74. public function multiple(?int $max = null)
  75. {
  76. return $this->max($max);
  77. }
  78. /**
  79. * @param ?int $max
  80. *
  81. * @return $this
  82. */
  83. public function max(?int $max)
  84. {
  85. $this->maxItem = $max;
  86. return $this;
  87. }
  88. /**
  89. * Set source path.
  90. *
  91. * @param string $source
  92. *
  93. * @return $this
  94. */
  95. public function path($source)
  96. {
  97. $this->source = admin_url($source);
  98. return $this;
  99. }
  100. protected function formatValue()
  101. {
  102. $value = Helper::array(old($this->column, $this->value));
  103. $this->value = [];
  104. foreach ($this->options as $id => $label) {
  105. foreach ($value as $v) {
  106. if ($v == $id && $v !== null) {
  107. $this->value[$v] = $label;
  108. }
  109. }
  110. }
  111. $this->value = json_encode((object) $this->value);
  112. }
  113. protected function setDefaultSource()
  114. {
  115. if (! $this->source) {
  116. if (strpos($this->column, '.')) {
  117. $this->path(str_replace('_id', '', last(explode('.', $this->column))));
  118. } else {
  119. $this->path(str_replace('_id', '', $this->column));
  120. }
  121. }
  122. }
  123. protected function prepareInputValue($value)
  124. {
  125. if ($this->maxItem == 1) {
  126. if ($value === null || $value === '') {
  127. return 0;
  128. }
  129. return $value;
  130. }
  131. return Helper::array($value, true);
  132. }
  133. protected function setupScript()
  134. {
  135. $label = ucfirst(trans('admin.choose')).' '.$this->label;
  136. $area = json_encode($this->area);
  137. $disabled = empty($this->attributes['disabled']) ? '' : 'disabled';
  138. $containerId = $this->id.$this->getFormElementId();
  139. $maxItem = (int) $this->maxItem;
  140. $queryName = IFrameGrid::QUERY_NAME;
  141. $displayerContainer = $this->isMultiple() ? "#{$containerId} .select2-selection" : "#{$containerId}";
  142. $this->script = <<<JS
  143. Dcat.ResourceSelector({
  144. title: '{$label}',
  145. column: "{$this->getElementName()}",
  146. source: '{$this->source}',
  147. selector: '#{$this->btnId}',
  148. maxItem: {$maxItem},
  149. area: {$area},
  150. queryName: '{$queryName}',
  151. items: {$this->value()},
  152. placeholder: '{$this->placeholder()}',
  153. showCloseButton: false,
  154. disabled: '{$disabled}',
  155. displayer: 'default',
  156. displayerContainer: $('$displayerContainer'),
  157. });
  158. JS;
  159. }
  160. protected function setupStyle()
  161. {
  162. $containerClass = 'form-control';
  163. if ($this->isMultiple()) {
  164. // 选项大于两个时使用select2样式布局
  165. Admin::css('@select2');
  166. $containerClass = 'select2 select2-container select2-container--default select2-container--below ';
  167. }
  168. $this->attribute('class', "{$containerClass} {$this->getElementClassString()}");
  169. }
  170. public function isMultiple()
  171. {
  172. return ! $this->maxItem || $this->maxItem > 2;
  173. }
  174. /**
  175. * {@inheritdoc}
  176. */
  177. public function render()
  178. {
  179. $this->btnId = $this->id.'-select-resource';
  180. $this->formatOptions();
  181. $this->formatValue();
  182. $this->setDefaultSource();
  183. $this->setupStyle();
  184. $this->setupScript();
  185. $name = $this->elementName ?: $this->formatName($this->column);
  186. $this->prepend('<i class="feather icon-arrow-up"></i>')
  187. ->defaultAttribute('type', 'text')
  188. ->defaultAttribute('id', $this->id.$this->getFormElementId())
  189. ->defaultAttribute('name', $name);
  190. $this->addVariables([
  191. 'className' => str_replace(['[', ']'], '_', $name),
  192. 'prepend' => $this->prepend,
  193. 'append' => $this->append,
  194. 'maxItem' => $this->maxItem,
  195. 'placeholder' => $this->placeholder(),
  196. 'style' => $this->style,
  197. 'btnId' => $this->btnId,
  198. ]);
  199. return parent::render();
  200. }
  201. }