对于form表单里的多层对象编辑还得是vue更合适
但是查了一圈文档,laravel-admin前端没有给出明确的指导的文章,稍作整理,作为备忘
https://laravel-admin.org/docs/zh/1.x/frontend
- 模板指定路径
修改app/Admin/bootstrap.php 增加代码,管网文档有说明,把框架自带的views拷贝过来即可,这样就可以自定义修改业务功能需要的交互和排版了。
app('view')->prependNamespace('admin', resource_path('views/admin/views'));
- 制定Content
<?php
namespace App\Admin\VueLayout;
use Encore\Admin\Layout\Content;
class VueContent extends Content {
public function render() {
$items = [
'header' => $this->title,
'description' => $this->description,
'breadcrumb' => $this->breadcrumb,
'_content_' => $this->build(),
'_view_' => $this->view,
'_user_' => $this->getUserData(),
];
return view('admin::content-vue', $items)->render();
}
}
- 独立AdminController指定框架模板,避免影响原来的功能
<?php
namespace App\Admin\Controllers;
use App\Admin\VueLayout\VueContent;
use Encore\Admin\Controllers\HasResourceActions;
use Illuminate\Routing\Controller;
class AdminVueController extends Controller
{
use HasResourceActions;
/**
* Title for current resource.
*
* @var string
*/
protected $title = 'Title';
/**
* Set description for following 4 action pages.
*
* @var array
*/
protected $description = [
// 'index' => 'Index',
// 'show' => 'Show',
// 'edit' => 'Edit',
// 'create' => 'Create',
];
public $view;
public $data;
/**
* Get content title.
*
* @return string
*/
protected function title()
{
return $this->title;
}
/**
* Index interface.
*
* @param Content $content
*
* @return Content
*/
public function index(VueContent $content)
{
return $content
->title($this->title())
->description($this->description['index'] ?? trans('admin.list'))
->body($this->grid());
}
/**
* Show interface.
*
* @param mixed $id
* @param Content $content
*
* @return Content
*/
public function show($id, VueContent $content)
{
return $content
->title($this->title())
->description($this->description['show'] ?? trans('admin.show'))
->body($this->detail($id));
}
/**
* Edit interface.
*
* @param mixed $id
* @param Content $content
*
* @return Content
*/
public function edit($id, VueContent $content)
{
$this->form($id);
// var_dump($this->title(), $this->description['create'] ?? trans('admin.create'));exit;
$this->data['description_title'] = $this->description['edit'] ?? trans('admin.edit');
return $content
->title($this->title())
->description($this->description['edit'] ?? trans('admin.edit'))
->component($this->view, $this->data);
}
/**
* Create interface.
*
* @param Content $content
*
* @return Content
*/
public function create(VueContent $content)
{
$this->form();
// var_dump($this->title(), $this->description['create'] ?? trans('admin.create'));exit;
$this->data['description_title'] = $this->description['create'] ?? trans('admin.create');
return $content
->title($this->title())
->description($this->description['create'] ?? trans('admin.create'))
->component($this->view, $this->data);
}
}
- blade模板
resource/views/admin/views/vue-levels-form.php
<div class="box box-info" id="app1">
<div class="box-header with-border">
<h3 class="box-title">{{$description_title}}</h3>
</div>
<!-- /.box-header -->
<div class="box-body" >
<div class="fields-group">
<div class="col-md-12">
<div class="form-group row ">
<label class="col-sm-2 asterisk control-label">规则名称</label>
<div class="col-sm-10">
<div class="input-group">
<span class="input-group-addon"><i class="fa fa-pencil fa-fw"></i></span>
<input required="1" type="text" v-model="detail.title" class="form-control title" placeholder="输入 规则名称">
</div>
</div>
</div>
<div class="row" >
<div class="col-sm-2 asterisk">
<h4 class="pull-left">收费规则</h4>
</div>
<div class="col-sm-10">
<div id="has-many-vals" style="margin-top: 15px; overflow-y:scroll">
<table class="table table-has-many has-many-vals">
<thead>
<tr>
<th>任务类型</th>
<th>配置</th>
<th class="hidden"></th>
<th></th>
</tr>
</thead>
<tbody class="has-many-vals-forms">
<tr class="has-many-vals-form fields-group" v-for="(val, key) in detail.vals" v-key="key">
<td style="border-right: 1px solid #ccc;;">
<div class="form-group ">
<div class="col-sm-12">
<select class="form-control select2-accessible" style="width: 120px;"
placeholder="请选择"
v-model="val.type"
>
<!-- <option value="">-请选择-</option> -->
<option v-for="(v,index) in metas.task_types" v-key="index" :value="index">@{{v}}</option>
</select>
</div>
</div>
</td>
<td>
<table class="table table-has-many has-many-vals">
<thead>
<tr>
<th>最小粉丝量</th>
<th>最大粉丝量</th>
<th>收费</th>
<th>操作</th>
</tr>
</thead>
<tbody class="has-many-vals-forms">
<tr class="has-many-vals-form fields-group" v-for="(vv,kk) in val.cfgs" v-key="kk">
<td>
<div class="form-group ">
<div class="col-sm-12">
<div class="input-group">
<input required="1" style="width: 150px; text-align: right;" type="number" v-model="vv.fans_min" class="form-control" placeholder="输入 最小粉丝量" min=0>
</div>
</div>
</div>
</td>
<td>
<div class="form-group ">
<div class="col-sm-12">
<div class="input-group">
<input required="1" style="width: 150px; text-align: right;" type="number" v-model="vv.fans_max" class="form-control" placeholder="输入 最大粉丝量" min=100>
</div>
</div>
</div>
</td>
<td>
<div class="form-group ">
<div class="col-sm-12">
<div class="input-group">
<span class="input-group-addon">¥</span>
<input required="1" style="width: 150px; text-align: right;" type="number" v-model="vv.fee" class="form-control" placeholder="输入 收费金额" min=1>
</div>
</div>
</div>
</td>
<td>
<div class="remove btn btn-danger btn-sm " v-on:click="removeCfg(kk, val.type, key)" ><i class="fa fa-trash"> </i>删除</div>
</td>
</tr>
</tbody>
<tfoot>
<td></td>
<td></td>
<td></td>
<td>
<div class="add btn btn-warning btn-sm btn-add-cfg" v-on:click="addCfg(val.type, key)"><i class="fa fa-plus"></i> 增加收费配置</div>
</td>
</tfoot>
</table>
</td>
<td class="hidden">
</td>
<td class="form-group" style="border-left:1px solid #ccc;">
<div>
<div class="remove btn btn-danger btn-sm pull-right btn-remove-rule" v-on:click="removeRule(key)"><i class="fa fa-trash"> </i>移除规则</div>
</div>
</td>
</tr>
</tbody>
</table>
<div class="form-group">
<div class="col-sm-8">
<div class="add btn btn-success btn-sm btn-add-rule" v-on:click="addRule"><i class="fa fa-save"></i> 新增规则</div>
</div>
</div>
</div>
</div>
</div>
<hr style="margin-top: 0px;">
</div>
</div>
</div>
<!-- /.box-body -->
<div class="box-footer">
<div class="col-md-2">
</div>
<div class="col-md-8">
<div class="btn-group pull-right">
<button v-on:click="savePost" class="btn btn-primary">提交</button>
</div>
<div class="btn-group pull-left">
<!-- <button type="reset" class="btn btn-warning">重置</button> -->
</div>
</div>
</div>
<!-- /.box-footer -->
</div>
<script>
var vm = new Vue({
el:'#app1',
data: {
detail: <?php echo \Illuminate\Support\Js::from($detail); ?>,
metas: <?php echo \Illuminate\Support\Js::from($metas); ?>,
api: '<?php echo $api;?>',
token: '<?php echo $token;?>'
},
methods: {
removeCfg(k, type, pk){
// console.log(type, k, this.detail.vals[pk].cfgs, pk);
if(this.detail.vals[pk].cfgs.length <= 1){
return false;
}
this.detail.vals[pk].cfgs = this.detail.vals[pk].cfgs.splice(k, 1);
console.log(this.detail.vals[pk].cfgs);
},
addCfg(type, pk){
console.log(type);
this.detail.vals[pk].cfgs.push({fans_min: 0, fans_max: 0, fee:0});
},
removeRule(key){
console.log(key);
if(this.detail.vals.length<=1){
return false;
}
this.detail.vals.splice(key, 1);
},
addRule(){
// console.log(key);
this.detail.vals.push({type:null, cfgs:[]});
},
savePost(){
console.log(this.api, this.detail);
axios.post(this.api, this.detail)
.then((response) => {
if(response.data.code == 0){
window.location.href=response.data.data.goto_url;
return true;
}
console.log('数据已提交',response);
})
.catch((error) => {
console.error('提交失败', error);
});
}
}
});
</script>
- Admin业务controller编辑和创建方法,嵌入vuejs
<?php
namespace App\Admin\Controllers;
use App\Models\BizLeves;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Encore\Admin\Show;
use Illuminate\Support\MessageBag;
use Encore\Admin\Admin;
use Illuminate\Http\Request;
use \App\Libs\Resp;
class LevelsController extends AdminVueController
{
/**
* Title for current resource.
*
* @var string
*/
protected $title = '等级配置';
/**
* Make a grid builder.
*
* @return Grid
*/
protected function grid()
{
$grid = new Grid(new DhtGroupbuyMcXhsLevels());
$grid->column('id', __('ID'));
$grid->column('title', __('规则名称'));
$grid->column('vals', __('规则配置'))->display(function(){
if(empty($this->vals)){
return '--';
}
$tbl = '';
return $tbl;
});
$grid->column('created_at', __('创建时间'));
$grid->column('updated_at', __('修改时间'));
$grid->disableBatchActions();
$grid->actions(function(){
$this->disableView();
$this->disableDelete();
});
$grid->model()->orderBy('id', 'desc');
return $grid;
}
/**
* create and edit
*/
public function save()
{
$data = [];
$api = '/levels';
if(env('APP_ENV') == 'local'){
$api = '/admin'.$api;
}
$data['goto_url'] = url($api);
if(in_array(request()->method(), ['POST', 'PUT'])){
$params = request()->all();
if(!empty($params['id'])){
$model = BizLevels::find((int)$params['id']);
if(empty($model)){
return Resp::respJson($data);
}
} else {
$model = new DhtGroupbuyMcXhsLevels();
}
$model->title = $params['title'];
$model->vals = $params['vals'];//多层级对象
$model->save();
return Resp::respJson($data);
}
return back();
}
/**
* Make a form builder.
*
* @return Form
*/
protected function form($id = 0)
{
// 加载vuejs 和网络请求库
// 对应版本可以 https://www.bootcdn.cn/ 自行下载
Admin::headerJs('vendor/vuejs/vue@2.7.14.js');
Admin::headerJs('vendor/vuejs/axios@1.5.0.min.js');
//这里指定模板
$this->view = 'admin::vue-levels-form';
//新增时页面初始数据
$api = '/levels/save';
if(env('APP_ENV') == 'local'){
$api = '/admin'.$api;
}
$this->data = [
'token' => csrf_token(),
'api' => url($api),
'detail' => [
'id' => 0,
'title' => '',
'vals' => [
[
'type' => \App\Enums\BizTypes::yt,
'cfgs' => [
['fans_min' => 0, 'fans_max' => 0, 'fee' => 0],
// ['fans_min' => 200, 'fans_max' => 500, 'fee' => 150]
]
]
]
],
'metas' => [
'task_types' => \App\Enums\BizTypes::DICTS
]
];
if($id){
$detail = BizLevels::find($id);
$this->data['detail'] = $detail->toArray();
}
}
}
本文暂时没有评论,来添加一个吧(●'◡'●)