编程开源技术交流,分享技术与知识

网站首页 > 开源技术 正文

laravel-admin 1.8使用vue

wxchong 2024-06-27 01:43:55 开源技术 12 ℃ 0 评论

对于form表单里的多层对象编辑还得是vue更合适

但是查了一圈文档,laravel-admin前端没有给出明确的指导的文章,稍作整理,作为备忘

https://laravel-admin.org/docs/zh/1.x/frontend

  1. 模板指定路径

修改app/Admin/bootstrap.php 增加代码,管网文档有说明,把框架自带的views拷贝过来即可,这样就可以自定义修改业务功能需要的交互和排版了。

app('view')->prependNamespace('admin', resource_path('views/admin/views'));
  1. 制定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();
    }
}
  1. 独立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);
    }
}


  1. 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>


  1. 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();
        }
        
    }
}

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表