Vuetify+Laravel 實現的框架,有前途嗎?

idlewater發表於2020-04-09

上次徵集了HTML視覺化編輯工具的意見,扎心了,暫時先放一放,作為我專案的一個控制元件用好了。
我現在想重啟另外一個專案,大家幫忙看看可行不?
用Vuetify + laravel實現一個後臺管理框架,同時支援移動版跟PC版。現在實現了一大部分了,只是沒有釋出。
目標是,通過簡單的PHP程式碼,就可以做成一個應用。一些,目前實現供功能:
1、登陸

2、使用者管理

角色及許可權管理

相應程式碼:

class AdminList extends DataTablePage{
    protected $title = '管理員列表';

    function editPage(){
        return AdminEdit::make();
    }

    function register(){
        parent::register();
        $this->breadcrumbs->textItem('系統管理')
                    ->textItem('使用者管理')
                    ->textItem('管理員');
        $this->hiddenBy('users_module');
        $this->hiddenBy('admin_setting');
    }

    function columns(){

        return [ 
            //VularTableColumn::make('id','ID'),
            VularTableColumn::make('login_name','登入名')
                ->searchable(),
            VularTableColumn::make('name', '名稱')
                ->sortable()
                ->searchable(),
            VularTableColumn::make('email', '郵箱')
                ->sortable()
                ->searchable(),
                //->class('text-xs-right'),
                //->class('text-xs-right'),

            VularTableColumn::make('forbid','狀態'),
            VularTableColumn::make('rolesShow','角色'),
            VularTableColumn::make('created_at','時間')
                ->sortable()
                //->classes('text-xs-right')
        ];

    }

    function onRow($row){
        parent::onRow($row);
        $normalChip = VularNode::make()//VularNode的屬性會被賦予單元格
            ->children(VChip::make('正常')
                ->color('light-blue')
                ->textColor('white')
                ->small()
            );
        $forbidChip = VularNode::make()
            ->children(VChip::make('禁用')
                ->color('red')
                ->textColor('white')
                ->small()
            );
        $row->forbid = $row->forbid ? $forbidChip  : $normalChip;

        $roleChips = VularNode::make();

        foreach ($row->roles as $role) {
            $roleChips->children(
                VChip::make($role->name)
                //->color("transparent")
                ->small()
            );

        }
        //    \Log::notice(json_encode($roleChips));
        $row->rolesShow =  $roleChips;
        //return $row;
    }
class RoleEdit extends SimpleFormPage{
    protected $modelClass = \Water\Vular\Models\Role::class;
    protected $newTitle = '新建角色';
    protected $editTitle = '角色編輯';


    function register(){
        parent::register();
        $this->breadcrumbs->textItem('系統管理')
                    ->textItem('使用者管理')
                    ->textItem('角色');

    }

    function fields(){
        return [
            VTextField::make()
                ->field('name')
                ->label('角色名')
                ->requried()
                ->unique()
                ->maxLength(20),
            VTextArea::make()
                ->field('description')
                ->label('描述')
                ->rows(3)
                ->maxLength('500'),
            VularTreeSelect::make()
                ->field('permissions')
                ->label('許可權選擇')
                ->flat()
                ->tile()
                ->activatable()
                ->selectable()
                ->hoverable()
                ->openOnClick()
                ->items($this->permissions())
                ->itemKey('slug')
                ->style('border-bottom','solid #bbb 1px')
                ->showFilter(function($value){
                    return explode(",", $value);
                })
                ->saveFilter(function($value){
                    $value = array_filter($value, function($slug){
                        return ($slug & 'vular-per-group-') !== 'vular-per-group-';
                    });
                    return implode(",", $value);
                }),
            VSwitch::make()
                ->field('forbid')
                ->label('禁用')
        ];
    }


    function permissions(){
        $permissions = [];
        $permissionClasses = config('vular.permissions');
        foreach ($permissionClasses as $permissionClass) {
           $permissions = array_merge_recursive($permissions, (new $permissionClass)->toNodes());
        }
        return $permissions;
    }

}

3、訂單管理

相應程式碼:

class OrderList extends DataTablePage{
    protected $title = '訂單列表';

    function editPage(){
        return OrderEdit::make();
    }

    function register(){
        parent::register();
        $this->breadcrumbs->textItem('訂單管理')
                    ->textItem('訂單');

        $this->filter(TableFilter::make()
                ->item(function($item){
                    $item->input(
                            VTextField::make()
                                ->field('startTime')
                                ->type('date')
                                ->label('最早合同日期')
                        )
                        ->field('cotract_date')
                        ->min()
                        ->halfWidth();
                        //->field('name')
                })
                ->item(function($item){
                    $item->input(
                            VTextField::make()
                                ->type('date')
                                ->field('endTime')
                                ->label('最晚合同日期')
                        )
                        ->field('cotract_date')
                        ->max()
                        ->halfWidth();
                        //->field('name')
                })
            );

        $this->batchMenu()->itemOfDelete()->hiddenBy('order_delete');
    }


    function columns(){

        return [ 
            //VularTableColumn::make('id','ID'),
            VularTableColumn::make('cotract_no', '合同號')
                ->sortable()
                ->searchable(),
                //->class('text-xs-right'),
            VularTableColumn::make('customers.name','客戶')
                ->sortable()
                ->searchable(),
                //->class('text-xs-right'),
            VularTableColumn::make('contract_amount','合同金額')
                ->sortable(),
            //VularTableColumn::make('collection_value','已收賬款'),
            VularTableColumn::make('collection_percent','收款比例')
                ->sortable(),
            VularTableColumn::make('royalty_amount','已付提成')
                ->sortable(),

            VularTableColumn::make('cotract_date','合同日期')
                ->sortable(),
            VularTableColumn::make('passed','狀態')
                ->sortable(),
            VularTableColumn::make('user','業務員')
                ->hiddenBy('order_user_column')
                ->sortable(),
        ];

    }

    function onRow($row){
        parent::onRow($row);
        $normalChip = VularNode::make()//VularNode的屬性會被賦予單元格
            ->children(VChip::make('完成')
                ->light()
                ->textColor('white')
                ->small()
            );
        $waitingChip = VularNode::make()
            ->children(VChip::make('未完成')
                ->color('red')
                ->textColor('white')
                ->small()
            );
        //\Log::notice(json_encode($row));
        $row->passed = $row->passed ? $normalChip  : $waitingChip;
        $row->collection_percent = number_format($row->collection_percent,0);
        $row->collection_percent = $row->collection_percent > 99?100: $row->collection_percent;
        $row->collection_percent = $row->collection_percent . '%';
    }

    function queryBuilder(){
        return \DB::table('orders')
                    ->join('customers', 'customers.id', '=', 'orders.customer_id')
                    ->leftJoin('admins', 'admins.id', '=', 'orders.user_id')
                    ->select('orders.*','customers.name as customers.name','admins.name as user')
                    ->selectRaw(' 
                           (orders.first_collection_amount + ifnull(orders.second_collection_amount,0))*100/orders.contract_amount as collection_percent
                        '
                    );
    }

    function appendToQuery($queryBuilder){
        $queryBuilder->orderBy('passed','asc')
                            ->orderBy('cotract_date','desc');
        $user = user();
        if($user->isPermitted('order_all_data')){
            return $queryBuilder;
        }
        return $queryBuilder->where('orders.user_id', $user->id);

    }


    function rowEditButton($btn, $row){
        //$btn->hiddenBy('order_edit')
        return $btn->disabled($row->passed && !user()->isPermitted('order_edit_passed'));
    }

    function rowDeleteButton($btn, $row){
        return $btn->hiddenBy('order_delete');
    }

}
class OrderEdit extends OneColumnFormPage{

    protected $modelClass = \Water\Vular\Order\Models\Order::class;

    protected $newTitle = '新建訂單';

    protected $editTitle = '訂單編輯';

    function register(){
        parent::register();
        $this->breadcrumbs->textItem('訂單管理')
                    ->textItem('訂單');
        //$dbModel = $this->dbModel();
        $this->bottomButton(
            VBtn::make(trans('vular.finished'))
                ->large()
                ->round()
                ->light()
                ->valid()
                ->color('orange')
                //->disabled(!$dbModel || ($dbModel&&$dbModel->passed))
                ->hiddenBy('order_pass')
                //->disabledBy('order_pass')
                ->click(
                    VularAction::make()
                        ->action('pass')
                        ->post()
                        ->valid()
                        ->bindsTo($this->form)
                )            
        );

        //$this->permitActionBy('save','order_save');
        //$this->permitActionBy('saveAndContinue','order_save');

    }

    function cards(){
        return[
            VularFormGridCard::make()
                ->title('客戶合同')
                ->flex(
                    VSelect::make()
                        ->field('customer')
                        ->label('客戶')
                        ->items($this->customers())
                        ->prependInnerIcon('account_box')
                        //->belongsTo()
                        ->requried(),
                    'xs4'
                )
                ->flex(
                    VTextField::make()
                        ->field('cotract_date')
                        ->label('合同日期')
                        ->prependInnerIcon("today")
                        ->type('date')
                        ->requried(),
                    'xs4'
                )
                ->flex(
                    VTextField::make()
                        ->field('cotract_no')
                        ->label('合同號')
                        ->prefix("#")
                        ->requried()
                        ->unique()
                        ->maxLength(20),
                    'xs4'
                )
                ->flex(
                    VSelect::make()
                        ->field('payment_mode')
                        ->label('付款方式')
                        ->prependInnerIcon('payment')
                        ->items(['T/T 100%/0%','T/T 30%/70%','T/T 20%/80%','T/T 10%/90%','T/T 0%/100%','LC at sight', 'DP at sight'])
                        ->requried(),
                    'xs4'
                )
                ->flex(
                    VSelect::make()
                        ->field('currency')
                        ->label('幣種')
                        ->prependInnerIcon('monetization_on')
                        ->items([
                            ['id'=>'Dollar', 'name'=>'美元'], 
                            ['id'=>'Euro', 'name'=>'歐元'], 
                            ['id'=>'RMB', 'name'=>'人民幣']
                        ])
                        ->requried()
                        ,
                    'xs4'
                )
                ->flex(
                    VTextField::make()
                        ->field('contract_amount')
                        ->label('合同金額')
                        ->prependInnerIcon("attach_money")
                        ->float()
                        ->requried(),
                    'xs4'
                )
                ->flex(
                    VTextArea::make()
                        ->field('goods_description')
                        //->prependInnerIcon('description')
                        ->label('貨物描述')
                        ->rows(3)
                        ->requried(),
                    'xs12'
                )
                ->flex(
                    VTextField::make()
                        ->field('estimated_shipping_date')
                        ->label('預計發貨日期')
                        ->prependInnerIcon("today")
                        ->type('date'),
                    'xs3'
                )
                ->flex(
                    VTextField::make()
                        ->field('estimated_arrival_date')
                        ->label('預計到港日期')
                        ->prependInnerIcon("today")
                        ->type('date'),
                    'xs3'
                )
                ->flex(
                    VTextField::make()
                        ->field('shipping_date')
                        ->label('實際發貨日期')
                        ->prependInnerIcon("today")
                        ->type('date'),
                    'xs3'
                )
                ->flex(
                    VTextField::make()
                        ->field('arrival_date')
                        ->label('實際到港日期')
                        ->prependInnerIcon("today")
                        ->type('date'),
                    'xs3'
                )
                ->flex(
                    VTextField::make()
                        ->field('first_collection_date')
                        ->label('第一次收匯日期')
                        ->prependInnerIcon("today")
                        ->type('date'),
                    'xs4'
                )
                ->flex(
                    VTextField::make()
                        ->field('first_collection_amount')
                        ->label('第一次收匯金額')
                        ->prependInnerIcon("attach_money")
                        ->float(),
                    'xs4'
                )
                ->flex(
                    VTextField::make()
                        ->field('first_exchange_rate')
                        ->label('結匯匯率')
                        ->prependInnerIcon('trending_up')
                        ->float(),
                    'xs4'
                )
                ->flex(
                    VTextField::make()
                        ->field('second_collection_date')
                        ->label('第二次收匯日期')
                        ->prependInnerIcon("today")
                        ->type('date')
                        ,
                    'xs4'
                )
                ->flex(
                    VTextField::make()
                        ->field('second_collection_amount')
                        ->label('第二次收匯金額')
                        ->prependInnerIcon("attach_money")
                        ->float(),
                    'xs4'
                )
                ->flex(
                    VTextField::make()
                        ->field('second_exchange_rate')
                        ->label('結匯匯率')
                        ->prependInnerIcon('trending_up')
                        ->float()
                        ,
                    'xs4'
                )
                ->flex(
                    VTextArea::make()
                        ->field('remarks')
                        ->label('備註')
                        ->rows(2),
                    'xs12'
                )
                ,
            VularFormHasManyCard::make()
                ->title('工廠合同')
                ->field('factoryOrders')
                ->flex(
                    VSelect::make()
                        ->field('supplier')
                        ->label('工廠')
                        ->items(Supplier::orderBy('name')->get())
                        ->prependInnerIcon('portrait')
                        //->belongsTo()
                        ->requried(),
                    'xs4'
                )
                ->flex(
                    VTextField::make()
                        ->field('cotract_date')
                        ->label('合同日期')
                        ->prependInnerIcon('today')
                        ->type('date')
                        ->requried(),
                    'xs4'
                )
                ->flex(
                    VTextField::make()
                        ->field('cotract_no')
                        ->label('合同號')
                        ->prefix('#')
                        ->requried()
                        ->unique()
                        ->maxLength(20),
                    'xs4'
                )
                ->flex(
                    VSelect::make()
                        ->field('payment_mode')
                        ->label('付款方式')
                        ->prependInnerIcon('payment')
                        ->items(['T/T 100%/0%','T/T 30%/70%','T/T 20%/80%','T/T 10%/90%','T/T 0%/100%'])
                        ->requried(),
                    'xs4'
                )
                ->flex(
                    VSelect::make()
                        ->field('currency')
                        ->label('幣種')
                        ->prependInnerIcon('monetization_on')
                        ->items([
                            ['id'=>'RMB', 'name'=>'人民幣'],
                            ['id'=>'Dollar', 'name'=>'美元'],
                            ['id'=>'Euro', 'name'=>'歐元']
                        ])
                        ->requried(),
                    'xs4'
                )
                ->flex(
                    VTextField::make()
                        ->field('contract_amount')
                        ->prependInnerIcon("attach_money")
                        ->label('合同金額')
                        ->float()
                        ->requried(),
                    'xs4'
                )
                ->flex(
                    VTextArea::make()
                        ->field('goods_description')
                        ->label('貨物描述')
                        ->rows(3)
                        ->maxLength(500)
                        ->requried(),
                    'xs12'
                )
                ->flex(
                    VTextField::make()
                        ->field('estimated_delivery_date')
                        ->label('預計發貨時間')
                        ->prependInnerIcon("today")
                        ->type('date')
                        ,
                    'xs6'
                )
                ->flex(
                    VTextField::make()
                        ->field('delivery_date')
                        ->label('實際發貨時間')
                        ->prependInnerIcon("today")
                        ->type('date')
                        ,
                    'xs6'
                )
                ->flex(
                    VTextField::make()
                        ->field('first_pay_date')
                        ->label('第一次付款日期')
                        ->prependInnerIcon("today")
                        ->type('date')
                        ,
                    'xs4'
                )
                ->flex(
                    VTextField::make()
                        ->field('first_pay_amount')
                        ->label('第一次付款金額')
                        ->prependInnerIcon("attach_money")
                        ->float(),
                    'xs4'
                )
                ->flex(
                    VTextField::make()
                        ->field('first_pay_exchange_rate')
                        ->label('匯率')
                        ->prependInnerIcon('trending_up')
                        ->float()
                        ,
                    'xs4'
                )
                ->flex(
                    VTextField::make()
                        ->field('second_pay_date')
                        ->label('第二次付款日期')
                        ->prependInnerIcon("today")
                        ->type('date')
                        ,
                    'xs4'
                )
                ->flex(
                    VTextField::make()
                        ->field('second_pay_amount')
                        ->label('第二次付款金額')
                        ->prependInnerIcon("attach_money")
                        ->float(),
                    'xs4'
                )
                ->flex(
                    VTextField::make()
                        ->field('second_pay_exchange_rate')
                        ->label('匯率')
                        ->prependInnerIcon('trending_up')
                        ->float()
                        ,
                    'xs4'
                )
                ->flex(
                    VTextField::make()
                        ->field('export_rebate')
                        ->label('退稅金額')
                        ->prependInnerIcon("attach_money")
                        ->float(),
                    'xs12'
                )
                ->flex(
                    VTextArea::make()
                        ->field('remarks')
                        ->label('備註')
                        ->maxLength(500)
                        ->rows(2),
                    'xs12'
                ),
            VularFormHasManyCard::make('table')
                ->title('訂單費用')
                ->field('fees')
                ->flex(
                    VTextField::make()
                        ->field('pay_date')
                        ->label('付款日期')
                        ->prependInnerIcon("today")
                        ->type('date')
                        ,
                    'xs6'
                )
                ->flex(
                    VTextField::make()
                        ->field('name')
                        ->label('名稱')
                        ->prependInnerIcon('payment')
                        ->requried()
                        ,
                    'xs6'
                )
                ->flex(
                    VSelect::make()
                        ->field('currency')
                        ->label('幣種')
                        ->prependInnerIcon('monetization_on')
                        ->items([
                            ['id'=>'RMB', 'name'=>'人民幣'],
                            ['id'=>'Dollar', 'name'=>'美元'], 
                            ['id'=>'Euro', 'name'=>'歐元']
                        ])
                        ->requried()
                        ,
                    'xs4'
                )
                ->flex(
                    VTextField::make()
                        ->field('amount')
                        ->label('金額')
                        ->prependInnerIcon("attach_money")
                        ->requried()
                        ->float()
                        ,
                    'xs4'
                )
                ->flex(
                    VTextField::make()
                        ->field('exchange_rate')
                        ->label('匯率')
                        ->prependInnerIcon('trending_up')
                        ->float()
                        ,
                    'xs4'
                )
                ->flex(
                    VTextArea::make()
                        ->field('remarks')
                        ->label('備註')
                        ->rows(2)
                        ,
                    'xs12'
                )
                ,
            VularFormGridCard::make()
                ->title('提成核算')
                ->flex(
                    VTextField::make()
                        //->field('xxx')
                        ->label('毛利')
                        ->disabled()
                        ->defaultValue(number_format($this->grossProfit(),2)),
                    'xs6'
                )
                ->flex(
                    VSlider::make()
                        ->field('royalty_rate')
                        ->label('提成比例')
                        ->thumbLabel('always')
                        ->step(5),
                    'xs6'
                )
                ->flex(
                    VTextField::make()
                        //->field('')
                        ->label('應付提成')
                        ->disabled()
                        ->defaultValue(number_format($this->royalty(),2)),
                    'xs6'
                )
                ->flex(
                    VTextField::make()
                        ->field('royalty_amount')
                        ->label('實付提成')
                        ->float(),
                    'xs6'
                )

        ];
    }

    function pass($viewModel){
        return $this->doSave($viewModel, function($dbModel){
                $dbModel->passed = true;
            })
            ->success()
            ->closePage();
    }

    function beforeSave($dbModel){
        $dbModel->passed = false;
        if(!$dbModel->id){
            $dbModel->user()->associate(user());
        }
        return $dbModel;
    }

    function customers(){
        $user = user();
        if($user->isPermitted('customer_all_data')){
            return Customer::orderBy('name')->get();
        }
        return Customer::where('user_id', $user->id)->orderBy('name')->get();
    }


    //計算毛利
    protected function grossProfit($model = null){
        if(!$this->modelId()){
            return 0;
        }

        $model = $model ? $model : $this->dbModel();

        //<----------------
        //已收RMB賬款
        $firstRmbAmount =  $model->first_exchange_rate? $model->first_collection_amount * $model->first_exchange_rate: $model->first_collection_amount;

        $secondRmbAmount =  $model->second_exchange_rate? $model->second_collection_amount * $model->second_exchange_rate: $model->second_collection_amount;

        $collectionRmbAmount = $firstRmbAmount + $secondRmbAmount;
        //<------------

        //已付RMB貨款
        $rmbPayment = 0;
        foreach ($model->factoryOrders as $factoryOrder) {
            $firstPayment = $factoryOrder->first_pay_exchange_rate? $factoryOrder->first_pay_amount * $factoryOrder->first_pay_exchange_rate : $factoryOrder->first_pay_amount;
            $secondPayment = $factoryOrder->second_pay_exchange_rate? $factoryOrder->second_pay_amount * $factoryOrder->second_pay_exchange_rate : $factoryOrder->second_pay_amount;

            $rmbPayment += ($firstPayment + $secondPayment - $factoryOrder->export_rebate);
        }

        //已付RMB費用
        $rmbFee = 0;
        foreach ($model->fees as $fee) {
            $feeAmount = $fee->exchange_rate ? $fee->amount * $fee->exchange_rate : $fee->amount;

            $rmbFee += $feeAmount;
        }

        return   $collectionRmbAmount - $rmbPayment - $rmbFee;
    }

    //己算提成
    protected function royalty(){
        if(!$this->modelId()){
            return 0;
        }
        $model = $this->dbModel();

        return ($this->grossProfit($model) * $model->royalty_rate)/100;
    }

    protected function modelId(){
        return request('id');
    }

    protected function dbModel(){
        $modelClass =$this->modelClass;
        //\Log::notice($modelClass);
        return $modelClass::find($this->modelId());
    }

}

4、文章管理

程式碼我就不貼了,基於Vuetify的特性,還可以做移動版應用。
這個框架,我要是把它整理好,釋出出來,有用嗎?
支援關聯編輯,跟編輯屬性一樣方便。

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章