laravel-admin恶心的图片上传功能,让广大开发者很是苦恼,今天分享一个 手动改为异步传图的完整方案给大家,如果有大神在,也可以考虑将其封装为扩展~
同时也分享一下列表使用tab的解决方案~以及如何使用json方式存储动态性字段比较强的类型的数据~
话不多,看代码
grid()控制器
protected function grid() { $grid = new Grid(new Ad()); $grid->column('id', __('广告编号'))->sortable();; //$grid->column('group', __('广告位置')); $grid->column('value', __('广告信息')); $grid->column('status', __('广告状态'))->radio(Ad::STATUS); //$grid->column('created_at', __('创建时间')); //$grid->column('updated_at', __('最后更新')); //return $grid; $tab = new Tab(); $tabs = Ad::GROUP; $tab_type = request('tab_type', 1); $grid->disableCreateButton();//禁用默认的推荐按钮 foreach ($tabs as $key => $value) { if ($tab_type == $key) { $grid->model()->where('group', $key); $grid->tools(function ($tools)use($key,$value) { $url = "ads/create?group={$key}"; $icon = "fa fa-plus"; $text = "新建{$value}"; $tools->append(new ShowArtwork($url,$icon,$text)); }); $tab->add($value, $grid->render(), true); }else { $tab->addLink($value,'?tab_type='.$key); } } return $tab; }
form()控制器代码
/** * Make a form builder. * * @return Form */ protected function form() { $form = new Form(new Ad()); $form->saving(function (Form $form) {//保存数据前,合并一下value $original = $form->model()->value ?? [];// 原数据 $now = $form->value;// 表单数据 $merge = array_merge($original,$now);// 合并数据 //echo "requset:";dump(request()->all()); // 根据model->value配置的字段处理数据 $groupInfo = Ad::GROUPINFO[$form->model()->group??request('group',1)]; $groupInfo = array_merge(Ad::GROUPALL,$groupInfo); //dump($groupInfo); foreach ($groupInfo as $mk => $mv){ try{ $key = strstr($mk, '_tmp',true); if(!$key){//_tmp结尾的字段为图片上传字段不需要保存 $file_key = $mk . '_upload_file'; $file = Session::get($file_key); if($file){// 判断session中有没有图片 // 删除原图 $disk = QiniuStorage::disk('qiniu'); if(isset($merge[$mk]) && $file['key'] != $merge[$mk])//避免传的新图和老图是同一张 $disk->delete($merge[$mk]); // 存储新图 $merge[$mk] = $file['key']; Session::forget($file_key); } $endValue[$mk] = $merge[$mk]??''; } } catch (\Exception $exception ){ dd($exception); } } //dd($endValue); $form->value = $endValue; }); //$form->radio('group', __('广告位置'))->options(Ad::GROUP)->default(1); $form->hidden('group')->default(request('group',1)); $form->display('group', __('广告位置'))->with(function ($group) { return '' . Ad::GROUP[$group?:request('group',1)] . ''; }); //$form->text('value', __('广告信息')); $form->embeds('value', '广告信息', function ($em_form) use($form) { $groupInfo = Ad::GROUPINFO[$form->model()->group??request('group',1)]; $groupInfo = array_merge(Ad::GROUPALL,$groupInfo); foreach ($groupInfo as $gik => $giv){ $type = $giv[0]; switch ($type){ case 'image' : case 'file' : $em_form->$type($gik,$giv[1]??$gik)->rules($giv[2]??'')->removable() ->options( [ 'showPreview' => true, //'allowedFileExtensions'=>['apk'], 'showUpload' => false, 'uploadAsync' => true, 'uploadUrl' => '/admin/upload_file', 'uploadExtraData' => [ '_token' => csrf_token(), '_method' => 'POST', 'dir' => 'ads',//保存路径 'file_field' => "value.{$gik}",//文件存放字段 ], ] ); break; case 'multipleImage' : case 'multipleFile' : $em_form->$type($gik,$giv[1]??$gik)->rules($giv[2]??'')->sortable()->removable(); break; case 'display' : $config = config("filesystems.disks.qiniu"); $em_form->$type($gik,$giv[1]??$gik)->rules($giv[2]??'')->with(function ($value) use($config) { if($value) return ""; }); break; case 'radio' : $em_form->$type($gik,$giv[1]??$gik)->rules($giv[2]??'') ->options($giv[4])->default(1); break; default: $em_form->$type($gik,$giv[1]??$gik)->rules($giv[2]??'')->attribute($giv[3]??[]);; } } }); $form->switch('status', __('广告状态'))->default(1)->rules(); return $form; }
Ad的Model类
'开屏广告', 2 => '首页幻灯', 3 => '首页滚动', 4 => '首页推荐', 5 => '首页大图', ]; const GROUPALL = [ 'title'=>[ 'text', '标题', 'required',['required' => '1'] ], 'type'=>[ 'radio', '类型', 'required',['required' => '1'],['1' => '外链', '2'=> '信息详情'] ], 'url'=>[ 'text', '链接', 'required',['required' => '1'] ] ]; const GROUPINFO = [// 广告位字段配置 1 => [ // 'title'=>[ // 'text', '标题', 'required',['required' => '1'] // ], 'image'=>[// _tmp为固定必加后缀,实际上字段为image 'display', '图片预览', '' ], 'image_tmp'=>[// _tmp为固定必加后缀,实际上字段为image 'image', '替换图片', '' ], // 'url'=>[ // 'text', '链接', 'required',['required' => '1'] // ] ], 2 => [ // 'title'=>[ // 'text', '标题', 'required',['required' => '1'] // ], 'image'=>[// _tmp为固定必加后缀,实际上字段为image 'display', '图片预览', '' ], 'image_tmp'=>[// _tmp为固定必加后缀,实际上字段为image 'image', '替换图片', '' ], // 'url'=>[ // 'text', '链接', 'required',['required' => '1'] // ] ], 3 => [ ], 4 => [ // 'title'=>[ // 'text', '标题', 'required',['required' => '1'] // ], 'image'=>[// _tmp为固定必加后缀,实际上字段为image 'display', '图片预览', '' ], 'image_tmp'=>[// _tmp为固定必加后缀,实际上字段为image 'image', '替换图片', '' ], // 'url'=>[ // 'text', '链接', 'required',['required' => '1'] // ] ], 5 => [ // 'title'=>[ // 'text', '标题', 'required',['required' => '1'] // ], 'image'=>[// _tmp为固定必加后缀,实际上字段为image 'display', '图片预览', '' ], 'image_tmp'=>[// _tmp为固定必加后缀,实际上字段为image 'image', '替换图片', '' ], // 'url'=>[ // 'text', '链接', 'required',['required' => '1'] // ] ], ]; const STATUS = [ '0' => '隐藏', '1' => '显示', ]; /** * The attributes that are mass assignable. * * @var array */ protected $fillable = [ 'group', 'value', 'status', ]; /** * The attributes that should be hidden for arrays. * * @var array */ protected $hidden = [ ]; protected $casts = [ 'value' => 'json', ]; }
上传文件的控制器/admin/upload_file
/** * 上传文件到七牛 * @param Request $request [description] * @return [type][description] */ public function uploadFile(Request $request) { $dir = $request->input('dir','images'); $file_field = $request->input('file_field'); // 判断是否有文件上传 if ($request->hasFile($file_field)) { // 获取文件,file对应的是前端表单上传input的name $file = $request->file($file_field); $extension = $file->getClientOriginalExtension(); // 初始化 $disk = QiniuStorage::disk('qiniu'); // 重命名文件 //$fileName = md5($file->getClientOriginalName().time().rand()).'.'.$extension; //$fileName = $file->getClientOriginalName();//使用原文件名 $fileName = md5_file($file->getRealPath()).'.'.$extension;//用md5值 // 上传到七牛 $bool = $disk->put($dir.'/'.$fileName,file_get_contents($file->getRealPath())); // 判断是否上传成功 if ($bool) { $data['key'] = $dir.'/'.$fileName; $data['url'] = $disk->downloadUrl($data['key']); $data['type'] = $extension; //$data['md5'] = $disk->avInfo($data['key']); $file_key = strstr(substr(strrchr($file_field,'.'),1), '_tmp',true) . '_upload_file'; Session::put($file_key, $data); return Response::json(['success' => "true", 'message' => "上传成功", "data" => $data]); } return Response::json(['success' => "false", 'message' => "上传失败"],401); } return Response::json(['success' => "false", 'message' => "没有文件"],401); }
简单说一下异步传图实现方案,也是同事传授的方法,使用seesion缓存传上来的图
这里我根据字段名称进行了缓存,看代码
$file_key = strstr(substr(strrchr($file_field,'.'),1), '_tmp',true) . '_upload_file';
然后在控制器层再将它读出来使用。。。
由于json方式传图字段每次提交都会报错,索性只要是图文的字段就必须两个一个真实字段,一个是上传图片的临时字段例如:image_tmp,数据库中并不保存该值
总之方案也不是很完美,如果你也要解决这恶心的事情,可以优化一下,或者分享更好的方案~
也可以使用js解决方案
$this->script = script);
@admin 我要来评论啦!你好啊~~~~~~~~~~~~~~~