You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

303 lines
9.7 KiB

  1. <?php
  2. /*
  3. * The MIT License
  4. *
  5. * Copyright 2019 Blobt.
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a copy
  8. * of this software and associated documentation files (the "Software"), to deal
  9. * in the Software without restriction, including without limitation the rights
  10. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. * copies of the Software, and to permit persons to whom the Software is
  12. * furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included in
  15. * all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23. * THE SOFTWARE.
  24. */
  25. namespace iron\widgets;
  26. use iron\web\UploadAsset;
  27. use yii\base\InvalidArgumentException;
  28. use yii\base\Model;
  29. use yii\helpers\Html;
  30. use yii\web\NotFoundHttpException;
  31. use yii\widgets\InputWidget;
  32. use yii;
  33. /***
  34. * @author iron <weiriron@gmail.com>
  35. * @created Sep 11, 2019
  36. */
  37. class Upload extends InputWidget
  38. {
  39. /**
  40. * @var string
  41. * 上传url
  42. */
  43. public $url;
  44. /**
  45. * @var bool
  46. * 是否支持多图
  47. */
  48. public $multiple;
  49. /**
  50. * @var string
  51. * 文件保存后ajax异步操作(如操作数据库)
  52. */
  53. public $afterSave;
  54. /**
  55. * @var bool
  56. * 显示预览
  57. */
  58. public $showPreviews;
  59. /**
  60. * @var integer
  61. * 最大数量
  62. */
  63. public $maxCount;
  64. /**
  65. * @var string
  66. * 支持上传的文件类型
  67. */
  68. public $acceptFile;
  69. /**
  70. * @var int
  71. * 最大现在尺寸(kB)
  72. */
  73. public $maxSize;
  74. /**
  75. * @var array
  76. * 预览设置
  77. */
  78. public $previewConfig;
  79. /**
  80. * @var string
  81. * 删除图片
  82. */
  83. public $deleteUrl;
  84. /**
  85. * @var bool
  86. * 显示删除按钮
  87. */
  88. public $showDelete;
  89. /**
  90. * @var int
  91. * 预览框大小
  92. */
  93. public $statusBarWidth;
  94. /**
  95. * @var int
  96. * 拉拽框大小
  97. */
  98. public $dragdropWidth;
  99. /**
  100. * @var
  101. * 数据模型
  102. */
  103. public $model;
  104. /**
  105. * @var
  106. * 填入结果的参数
  107. */
  108. public $fillInAttribute;
  109. /**
  110. * @var
  111. * 填入结果的输入框id
  112. */
  113. private $fillInId;
  114. /**
  115. * @var string Regular expression used for attribute name validation.
  116. * @since 2.0.12
  117. * 属性匹配规则
  118. */
  119. private static $attributeRegex = '/(^|.*\])([\w\.\+]+)(\[.*|$)/u';
  120. /**
  121. * @throws NotFoundHttpException
  122. * @throws \yii\base\InvalidConfigException
  123. * 初始化参数
  124. */
  125. public function init()
  126. {
  127. parent::init();
  128. if (!$this->url) {
  129. throw new NotFoundHttpException('(upload) 必须配置上传url');
  130. }
  131. if (isset($this->previewConfig['url'])) {
  132. $this->previewConfig['height'] = $this->previewConfig['height'] ?? '80px';
  133. $this->previewConfig['width'] = $this->previewConfig['width'] ?? '80px';
  134. }
  135. $this->showPreviews = $this->previewConfig['url'] ? 'true' : 'false';//默认不显示预览
  136. $this->showPreviews = $this->showPreviews ?: 'false';//默认关闭预览
  137. $this->statusBarWidth = $this->statusBarWidth ?: 300;//默认关闭预览
  138. $this->dragdropWidth = $this->dragdropWidth ?: 800;//默认关闭预览
  139. $this->acceptFile = $this->acceptFile ?: '*';//默认无限制文件类型
  140. $this->maxCount = $this->maxCount ?: 10;//默认数量限制十张图
  141. $this->showDelete = $this->deleteUrl ? 'true' : 'false';//默认不显示删除按钮
  142. $this->maxSize = $this->maxSize ? $this->maxSize *= 1024 : 2 * 1024 * 1024;//默认限制2M大小;
  143. if (!$this->fillInAttribute) {
  144. throw new NotFoundHttpException('(fillInAttribute) 必须配置填入参数');
  145. }
  146. if (!$this->model) {
  147. throw new NotFoundHttpException('(model) 必须配置model');
  148. }
  149. $this->fillInId = self::getInputId($this->model, $this->fillInAttribute);
  150. }
  151. /**
  152. * @return string
  153. * 执行
  154. */
  155. public function run()
  156. {
  157. $this->registerAsset();
  158. return $this->renderUploadHtml();
  159. }
  160. /**
  161. * 注册js和css
  162. */
  163. protected function registerAsset()
  164. {
  165. $view = $this->getView();
  166. UploadAsset::register($view);
  167. $js = <<< SCRIPT
  168. $("#upload-file-{$this->attribute}").uploadFile({
  169. url:"upload",
  170. returnType: "json",
  171. multiple:true,
  172. dragDrop:true,
  173. fileName:"file",
  174. statusBarWidth:{$this->statusBarWidth},
  175. dragdropWidth:{$this->dragdropWidth},
  176. dragDropStr:"<span><b>拖动上传</b></span>",
  177. sizeErrorStr:"超过最大尺寸限制",
  178. maxFileCountErrorStr:"超过最大上传数量",
  179. uploadErrorStr:"上传失败",
  180. maxFileCount:"{$this->acceptFile}",
  181. maxFileCount:{$this->maxCount},
  182. maxFileSize:{$this->maxSize},
  183. showPreview:{$this->showPreviews},
  184. previewHeight:"{$this->previewConfig['height']}",
  185. previewWidth:"{$this->previewConfig['width']}",
  186. showDelete: {$this->showDelete},
  187. onSuccess: function (files, data) {
  188. $.ajax({
  189. url: "{$this->afterSave}",
  190. dataType: "json",
  191. data: {data: data, fileName: files},
  192. success: function(data)
  193. {
  194. var imageval = $('#{$this->fillInId}').val();
  195. if(imageval == '' || imageval == 0){
  196. $('#{$this->fillInId}').val(data);
  197. }else{
  198. $('#{$this->fillInId}').val($('#{$this->fillInId}').val()+','+data);
  199. }
  200. }
  201. });
  202. },
  203. onLoad:function(obj)
  204. {
  205. $.ajax({
  206. cache: false,
  207. url: "{$this->previewConfig['url']}",
  208. dataType: "json",
  209. success: function(data)
  210. {
  211. for(var i=0;i<data.length;i++)
  212. {
  213. obj.createProgress(data[i]["name"],data[i]["path"],data[i]["size"]);
  214. }
  215. }
  216. });
  217. },
  218. deleteCallback: function (data, pd) {
  219. $.ajax({
  220. url: '{$this->deleteUrl}',
  221. data: {data: data, imgid: $('#{$this->fillInId}').val()},
  222. success: function(data)
  223. {
  224. $('#{$this->fillInId}').val(data);
  225. },
  226. });
  227. // for (var i = 0; i < data.length; i++) {
  228. // $.post("{$this->deleteUrl}", {op: "delete",name: data[i]},
  229. // function (resp,textStatus, jqXHR) {
  230. //
  231. // });
  232. // }
  233. pd.statusbar.hide(); //You choice.
  234. },
  235. });
  236. SCRIPT;
  237. $view->registerJs($js);
  238. }
  239. /**
  240. * @return string
  241. * 渲染html
  242. */
  243. protected function renderUploadHtml()
  244. {
  245. return '<div class="box-body">
  246. <div id="upload-file-' . $this->attribute . '">
  247. <div class="ajax-upload-dragdrop" style="vertical-align: top; width: 600px;">
  248. <div class="ajax-file-upload" style="position: relative; overflow: hidden; cursor: default;">Upload
  249. <form method="POST" action="upload.php" enctype="multipart/form-data" style="margin: 0px; padding: 0px;">
  250. <input type="file" id="ajax-upload-id-1573635462220" name="myfile[]" accept="*" multiple="" style="position: absolute; cursor: pointer; top: 0px; width: 100%; height: 100%; left: 0px; z-index: 100; opacity: 0;">
  251. </form>
  252. </div>
  253. <span><b>Drag &amp; Drop Files</b></span>
  254. </div>
  255. <div>
  256. </div>';
  257. }
  258. /**
  259. * @param $model
  260. * @param $attribute
  261. * @return string
  262. * 获取要填入属性的输入框name
  263. */
  264. private static function getInputName($model, $attribute)
  265. {
  266. $formName = $model->formName();
  267. if (!preg_match(static::$attributeRegex, $attribute, $matches)) {
  268. throw new InvalidArgumentException('Attribute name must contain word characters only.');
  269. }
  270. $prefix = $matches[1];
  271. $attribute = $matches[2];
  272. $suffix = $matches[3];
  273. if ($formName === '' && $prefix === '') {
  274. return $attribute . $suffix;
  275. } elseif ($formName !== '') {
  276. return $formName . $prefix . "[$attribute]" . $suffix;
  277. }
  278. throw new InvalidArgumentException(get_class($model) . '::formName() cannot be empty for tabular inputs.');
  279. }
  280. /**
  281. * @param $model
  282. * @param $attribute
  283. * @return mixed
  284. * 获取要填入属性的输入框id
  285. */
  286. private static function getInputId($model, $attribute)
  287. {
  288. $charset = Yii::$app ? Yii::$app->charset : 'UTF-8';
  289. $name = mb_strtolower(static::getInputName($model, $attribute), $charset);
  290. return str_replace(['[]', '][', '[', ']', ' ', '.'], ['', '-', '-', '', '-', '-'], $name);
  291. }
  292. }