Editor.php 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. <?php
  2. namespace Dcat\Admin\Form\Field;
  3. use Dcat\Admin\Form\Field;
  4. use Dcat\Admin\Support\Helper;
  5. use Dcat\Admin\Support\JavaScript;
  6. /**
  7. * TinyMCE editor.
  8. *
  9. * @see https://www.tiny.cloud/docs
  10. * @see http://tinymce.ax-z.cn/
  11. */
  12. class Editor extends Field
  13. {
  14. protected static $js = [
  15. '@tinymce',
  16. ];
  17. protected $options = [
  18. 'plugins' => [
  19. 'advlist',
  20. 'autolink',
  21. 'link',
  22. 'image',
  23. 'media',
  24. 'lists',
  25. 'preview',
  26. 'code',
  27. 'help',
  28. 'fullscreen',
  29. 'table',
  30. 'autoresize',
  31. 'codesample',
  32. ],
  33. 'toolbar' => [
  34. 'undo redo | preview fullscreen | styleselect | fontsizeselect bold italic underline strikethrough forecolor backcolor | link image media blockquote removeformat codesample',
  35. 'alignleft aligncenter alignright alignjustify| indent outdent bullist numlist table subscript superscript | code',
  36. ],
  37. 'min_height' => 400,
  38. 'save_enablewhendirty' => true,
  39. 'convert_urls' => false,
  40. ];
  41. protected $disk;
  42. protected $imageUploadDirectory = 'tinymce/images';
  43. /**
  44. * 设置文件上传存储配置.
  45. *
  46. * @param string $disk
  47. *
  48. * @return $this
  49. */
  50. public function disk(string $disk)
  51. {
  52. $this->disk = $disk;
  53. return $this;
  54. }
  55. /**
  56. * 设置图片上传文件夹.
  57. *
  58. * @param string $dir
  59. *
  60. * @return $this
  61. */
  62. public function imageDirectory(string $dir)
  63. {
  64. $this->imageUploadDirectory = $dir;
  65. return $this;
  66. }
  67. /**
  68. * 自定义图片上传接口.
  69. *
  70. * @param string $url
  71. *
  72. * @return $this
  73. */
  74. public function imageUrl(string $url)
  75. {
  76. return $this->mergeOptions(['images_upload_url' => $this->formatUrl(admin_url($url))]);
  77. }
  78. /**
  79. * 设置语言包url.
  80. *
  81. * @param string $url
  82. *
  83. * @return $this
  84. */
  85. public function languageUrl(string $url)
  86. {
  87. return $this->mergeOptions(['language_url' => $url]);
  88. }
  89. /**
  90. * 设置编辑器高度.
  91. *
  92. * @param int $height
  93. *
  94. * @return $this
  95. */
  96. public function height(int $height)
  97. {
  98. return $this->mergeOptions(['min_height' => $height]);
  99. }
  100. /**
  101. * @return string
  102. */
  103. protected function formatOptions()
  104. {
  105. $this->options['selector'] = '#'.$this->id;
  106. $this->options['language'] = config('app.locale');
  107. $this->options['readonly'] = ! empty($this->attributes['readonly']) || ! empty($this->attributes['disabled']);
  108. if (empty($this->options['images_upload_url'])) {
  109. $this->options['images_upload_url'] = $this->defaultImageUploadUrl();
  110. }
  111. // 内容更改后保存到隐藏表单
  112. $this->options['init_instance_callback'] = JavaScript::make($this->buildSaveContentScript());
  113. return JavaScript::format($this->options);
  114. }
  115. /**
  116. * @return string
  117. */
  118. protected function defaultImageUploadUrl()
  119. {
  120. return $this->formatUrl(route(admin_api_route('tinymce.upload')));
  121. }
  122. /**
  123. * @param string $url
  124. *
  125. * @return string
  126. */
  127. protected function formatUrl(string $url)
  128. {
  129. return Helper::urlWithQuery(
  130. $url,
  131. [
  132. '_token' => csrf_token(),
  133. 'disk' => $this->disk,
  134. 'dir' => $this->imageUploadDirectory,
  135. ]
  136. );
  137. }
  138. /**
  139. * @return string
  140. */
  141. protected function buildSaveContentScript()
  142. {
  143. return <<<JS
  144. function (editor) {
  145. editor.on('Change', function(e) {
  146. var content = e.level.content;
  147. if (! content) {
  148. content = e.level.fragments;
  149. content = content.length && content.join('');
  150. }
  151. $(replaceNestedFormIndex('#{$this->id}')).val(String(content).replace('<p><br data-mce-bogus="1"></p>', '').replace('<p><br></p>', ''));
  152. });
  153. }
  154. JS;
  155. }
  156. /**
  157. * @return string
  158. */
  159. public function render()
  160. {
  161. $this->script = <<<JS
  162. (function () {
  163. var opts = {$this->formatOptions()};
  164. opts.selector = replaceNestedFormIndex(opts.selector);
  165. tinymce.init(opts)
  166. })();
  167. JS;
  168. return parent::render();
  169. }
  170. }