ソースを参照

fix hasMany/array/table表单在Widgtet/Form中使用图片上传表单需要手动设置上传链接以及设置dimensions验证规则后无法提交表单问题

Jiang qinghua 3 年 前
コミット
65ca0d3ecc

+ 4 - 0
src/Form.php

@@ -11,6 +11,7 @@ use Dcat\Admin\Form\Concerns;
 use Dcat\Admin\Form\Condition;
 use Dcat\Admin\Form\Field;
 use Dcat\Admin\Form\NestedForm;
+use Dcat\Admin\Form\ResolveField;
 use Dcat\Admin\Http\JsonResponse;
 use Dcat\Admin\Support\Helper;
 use Dcat\Admin\Traits\HasBuilderEvents;
@@ -91,6 +92,7 @@ class Form implements Renderable
 {
     use HasBuilderEvents;
     use HasFormResponse;
+    use ResolveField;
     use Concerns\HasEvents;
     use Concerns\HasFiles;
     use Concerns\HandleCascadeFields;
@@ -322,6 +324,8 @@ class Form implements Renderable
 
         $field->width($width['field'], $width['label']);
 
+        $this->callResolvingFieldCallbacks($field);
+
         $field::requireAssets();
 
         return $this;

+ 4 - 0
src/Form/EmbeddedForm.php

@@ -66,6 +66,8 @@ use Illuminate\Support\Collection;
  */
 class EmbeddedForm
 {
+    use ResolveField;
+
     /**
      * @var Form
      */
@@ -287,6 +289,8 @@ class EmbeddedForm
 
         $this->fields->push($field);
 
+        $this->callResolvingFieldCallbacks($field);
+
         $field::requireAssets();
 
         return $this;

+ 2 - 0
src/Form/Field/ArrayField.php

@@ -62,6 +62,8 @@ class ArrayField extends HasMany
         $form->setForm($this->form)
             ->setKey($key);
 
+        $form->setResolvingFieldCallbacks($this->resolvingFieldCallbacks);
+
         call_user_func($this->builder, $form);
 
         $form->hidden(NestedForm::REMOVE_FLAG_NAME)->default(0)->addElementClass(NestedForm::REMOVE_FLAG_CLASS);

+ 7 - 0
src/Form/Field/Embeds.php

@@ -4,6 +4,7 @@ namespace Dcat\Admin\Form\Field;
 
 use Dcat\Admin\Form\EmbeddedForm;
 use Dcat\Admin\Form\Field;
+use Dcat\Admin\Form\ResolveField;
 use Dcat\Admin\Support\Helper;
 use Illuminate\Support\Arr;
 use Illuminate\Support\Facades\Validator;
@@ -11,6 +12,8 @@ use Illuminate\Support\Str;
 
 class Embeds extends Field
 {
+    use ResolveField;
+
     /**
      * @var \Closure
      */
@@ -69,6 +72,8 @@ class Embeds extends Field
                 continue;
             }
 
+            File::deleteRules($field, $fieldRules);
+
             $column = $field->column();
 
             /*
@@ -247,6 +252,8 @@ class Embeds extends Field
 
         $form->setParent($this->form);
 
+        $form->setResolvingFieldCallbacks($this->resolvingFieldCallbacks);
+
         call_user_func($this->builder, $form);
 
         $form->fill($this->getEmbeddedData());

+ 17 - 2
src/Form/Field/File.php

@@ -11,8 +11,8 @@ use Illuminate\Support\Facades\Validator;
 
 class File extends Field implements UploadFieldInterface
 {
-    use WebUploader,
-        UploadField;
+    use WebUploader;
+    use UploadField;
 
     /**
      * @var array
@@ -215,4 +215,19 @@ class File extends Field implements UploadFieldInterface
     {
         return $this->on($event, $script, true);
     }
+
+    /**
+     * @param Field $field
+     * @param string|array $fieldRules
+     *
+     * @return void
+     */
+    public static function deleteRules(Field $field, &$fieldRules)
+    {
+        if ($field instanceof self) {
+            $fieldRules = is_string($fieldRules) ? explode('|', $fieldRules) : $fieldRules;
+
+            Helper::deleteContains($fieldRules, ['image', 'file', 'dimensions', 'size', 'max', 'min']);
+        }
+    }
 }

+ 5 - 5
src/Form/Field/HasMany.php

@@ -15,6 +15,8 @@ use Illuminate\Support\Str;
  */
 class HasMany extends Field
 {
+    use Form\ResolveField;
+
     /**
      * Relation name.
      *
@@ -127,11 +129,7 @@ class HasMany extends Field
                 continue;
             }
 
-            if ($field instanceof File) {
-                $fieldRules = is_string($fieldRules) ? explode('|', $fieldRules) : $fieldRules;
-
-                Helper::deleteByValue($fieldRules, ['image', 'file']);
-            }
+            File::deleteRules($field, $fieldRules);
 
             $column = $field->column();
 
@@ -370,6 +368,8 @@ class HasMany extends Field
 
         $form->setForm($this->form);
 
+        $form->setResolvingFieldCallbacks($this->resolvingFieldCallbacks);
+
         call_user_func($this->builder, $form);
 
         $form->hidden($this->getKeyName());

+ 13 - 1
src/Form/Field/WebUploader.php

@@ -31,6 +31,18 @@ trait WebUploader
         return $this;
     }
 
+    /**
+     * @param string $mimeTypes  exp. image/*
+     *
+     * @return $this
+     */
+    public function mimeTypes(string $mimeTypes)
+    {
+        $this->options['accept']['mimeTypes'] = $mimeTypes;
+
+        return $this;
+    }
+
     /**
      * @param bool $value
      *
@@ -233,7 +245,7 @@ trait WebUploader
             'elementName'         => $this->getElementName(), // 字段name属性值
             'lang'                => trans('admin.uploader'),
             'compress'            => false,
-
+            'accept'              => [],
             'deleteData' => [
                 static::FILE_DELETE_FLAG => '',
                 'primary_key'            => $key,

+ 2 - 0
src/Form/NestedForm.php

@@ -296,6 +296,8 @@ class NestedForm extends WidgetForm
             $this->form->builder()->pushField((clone $field)->display(false));
         }
 
+        $this->callResolvingFieldCallbacks($field);
+
         $field->setRelation([
             'relation' => $this->relationName,
             'key'      => $this->key,

+ 43 - 0
src/Form/ResolveField.php

@@ -0,0 +1,43 @@
+<?php
+
+namespace Dcat\Admin\Form;
+
+trait ResolveField
+{
+    protected $resolvingFieldCallbacks = [];
+
+    /**
+     * @example $form->resolvingField(function ($field, $form) {
+     *     ...
+     * });
+     *
+     * @param \Closure $callback
+     *
+     * @return $this
+     */
+    public function resolvingField(\Closure $callback)
+    {
+        $this->resolvingFieldCallbacks[] = $callback;
+
+        return $this;
+    }
+
+    public function setResolvingFieldCallbacks(array $callbacks)
+    {
+        $this->resolvingFieldCallbacks = $callbacks;
+    }
+
+    /**
+     * @param Field $field
+     *
+     * @return void
+     */
+    protected function callResolvingFieldCallbacks(Field $field)
+    {
+        foreach ($this->resolvingFieldCallbacks as $callback) {
+            if ($callback($field, $this) === false) {
+                break;
+            }
+        }
+    }
+}

+ 30 - 5
src/Http/Controllers/HandleFormController.php

@@ -3,7 +3,9 @@
 namespace Dcat\Admin\Http\Controllers;
 
 use Dcat\Admin\Exception\AdminException;
+use Dcat\Admin\Form\Field\Embeds;
 use Dcat\Admin\Form\Field\File;
+use Dcat\Admin\Form\Field\HasMany;
 use Dcat\Admin\Http\JsonResponse;
 use Dcat\Admin\Traits\HasUploadedFile;
 use Dcat\Admin\Widgets\Form;
@@ -38,10 +40,34 @@ class HandleFormController
 
         $form->form();
 
-        /* @var $field File */
-        $field = $form->field($this->uploader()->upload_column);
+        return $this->getField($request, $form)->upload($this->file());
+    }
+
+    /**
+     * @param Request $request
+     * @param $form
+     *
+     * @return File
+     */
+    protected function getField(Request $request, $form)
+    {
+        $column = $this->uploader()->upload_column ?: $request->get('_column');
 
-        return $field->upload($this->file());
+        if (! $relation = $request->get('_relation')) {
+            return $form->field($column);
+        }
+
+        $relation = is_array($relation) ? current($relation) : $relation;
+
+        $relationField = $form->field($relation);
+
+        if (! $relationField) {
+            return;
+        }
+
+        if ($relationField instanceof HasMany) {
+            return $relationField->buildNestedForm()->field($column);
+        }
     }
 
     public function destroyFile(Request $request)
@@ -50,8 +76,7 @@ class HandleFormController
 
         $form->form();
 
-        /* @var $field File */
-        $field = $form->field($request->_column);
+        $field = $this->getField($request, $form);
 
         $field->deleteFile($request->key);
 

+ 17 - 0
src/Support/Helper.php

@@ -425,6 +425,23 @@ class Helper
         }
     }
 
+    /**
+     * @param array $array
+     * @param mixed $value
+     */
+    public static function deleteContains(&$array, $value)
+    {
+        $value = (array) $value;
+
+        foreach ($array as $index => $item) {
+            foreach ($value as  $v) {
+                if (Str::contains($item, $v)) {
+                    unset($array[$index]);
+                }
+            }
+        }
+    }
+
     /**
      * 颜色转亮.
      *

+ 13 - 1
src/Support/WebUploader.php

@@ -27,7 +27,7 @@ class WebUploader
 
     public function __construct(Request $request = null)
     {
-        $request = $request ?: request();
+        $request = $this->prepareRequest($request ?: request());
 
         $this->_id = $request->get('_id');
         $this->chunk = $request->get('chunk');
@@ -36,6 +36,18 @@ class WebUploader
         $this->file = $request->file(static::FILE_NAME);
     }
 
+    protected function prepareRequest($request)
+    {
+        $relation = $request->get('_relation');
+        if (! $relation || ! is_string($relation)) {
+            return $request;
+        }
+
+        return $request->merge([
+            '_relation' => trim($relation, ','),
+        ]);
+    }
+
     /**
      * 判断是否是分块上传.
      *

+ 28 - 5
src/Widgets/Form.php

@@ -11,6 +11,7 @@ use Dcat\Admin\Form\Concerns\HasLayout;
 use Dcat\Admin\Form\Concerns\HasRows;
 use Dcat\Admin\Form\Concerns\HasTabs;
 use Dcat\Admin\Form\Field;
+use Dcat\Admin\Form\ResolveField;
 use Dcat\Admin\Support\Helper;
 use Dcat\Admin\Traits\HasAuthorization;
 use Dcat\Admin\Traits\HasFormResponse;
@@ -92,6 +93,7 @@ class Form implements Renderable
     use HasRows;
     use HasTabs;
     use HasLayout;
+    use ResolveField;
     use HasFormResponse {
         setCurrentUrl as defaultSetCurrentUrl;
     }
@@ -193,6 +195,26 @@ class Form implements Renderable
         $this->initCurrentUrl();
 
         $this->initPayload();
+
+        $formData = [static::REQUEST_NAME => static::class];
+
+        $this->resolvingField(function ($field) use ($formData) {
+            if (! method_exists($this, 'form')) {
+                return;
+            }
+
+            if ($field instanceof Field\File) {
+                $this->setFileUploadUrl($field, $formData);
+            }
+
+            if ($field instanceof Field\Embeds || $field instanceof Field\HasMany) {
+                $field->resolvingField(function ($field) use ($formData) {
+                    if (($field instanceof Field\File)) {
+                        $this->setFileUploadUrl($field, $formData);
+                    }
+                });
+            }
+        });
     }
 
     /**
@@ -561,18 +583,19 @@ class Form implements Renderable
         $field->setForm($this);
         $field->width($this->width['field'], $this->width['label']);
 
-        $this->setFileUploadUrl($field);
+        $this->callResolvingFieldCallbacks($field);
 
         $field::requireAssets();
 
         return $this;
     }
 
-    protected function setFileUploadUrl(Field $field)
+    protected function setFileUploadUrl(Field $field, $formData)
     {
-        if ($field instanceof Field\File && method_exists($this, 'form')) {
-            $formData = [static::REQUEST_NAME => get_called_class()];
-
+        if (
+            $field instanceof Field\File
+            && method_exists($this, 'form')
+        ) {
             $field->url(route(admin_api_route_name('form.upload')));
             $field->deleteUrl(route(admin_api_route_name('form.destroy-file'), $formData));
             $field->withFormData($formData);