ایجاد پنل مدیریت (AdminPanel) با لاراول و Vue.js

لاراول و Vue.js اغلب با هم مورد استفاده می‌گیرند. ابزارهای زیادی روی این تکنولوژی‌ها وجود دارد که یکی از این ابزارهای ارائه شده Vue+Laravel Admin Panel Generator است.


در این مقاله، علاوه بر ایجاد پنل مدیریت (AdminPanel) با لاراول و Vue.js، توضیح اینکه چه چیزی ایجاد می‌شود و اینکه Vue و لاراول چگونه با هم کار می‌کنند نیز ارائه شده است. همچنین، می‌توانید یک پروژه نمونه را با منبع آن در Github مشاهده کنید. همچنین، برای انجام این کار می‌توانید از QuickAdminPanel در لاراول نیز استفاده کنید.

استفاده از Generator برای ایجاد پنل مدیریت (AdminPanel)

در ادامه، اجازه دهید مراحل انجام کار را با هم بررسی کنیم:

مرحله اول: در این مرحله، پنل را بدون کدنویسی ایجاد کرده و سپس آیتم‌های منو و فیلدها را به آن اضافه می‌کنیم.

laravel-vue-1

مرحله دوم: در این مرحله، می‌توانید کد تولید شده را در فایل‌ مشاهده کنید.

laravel-vue-2

مرحله سوم: سپس، در این مرحله کد را دانلود کرده و آن را به صورت محلی یا در سرور راه دور خود با دستورات زیر نصب کنید.

composer install
php artisan key:generate
php artisan migrate --seed
php artisan passport:install

البته، فایل .env شما باید پیکربندی شود.

سپس، در قسمت فرانت اند برنامه دستورات زیر را وارد کنید:

npm install
npm run dev

مرحله چهارم: در این مرحله، شما پنل خود را دارید.

laravel-vue-3

 

laravel-vue-4
مرحله پنجم: نکته مهم این است که می‌توانید کد را به دلخواه خود تغییر دهید، این Laravel + Vue خالص بدون پکیج generator به عنوان یک وابستگی است. این تفاوت آشکار این روش نسبت به پکیج‌هایی مانند Voyagerو Laravel Backpack است.

بیشتر بخوانید:

نحوه ایجاد ساختار پروژه برای ایجاد پنل مدیریت (AdminPanel) با لاراول و Vue.js

پس از دانلود پروژه، چیزی شبیه به این را مشاهده می‌کنید:

laravel-vue-5

کدهای تولید شده در back end لاراول

ابتدا اجازه دهید، بخش back end لاراول که به عنوان API عمل می‌کند را آنالیز کنیم.
این قسمت، فایل routes/api.php است:

Route::group(['prefix' => '/v1', 'middleware' => ['auth:api'], 'namespace' => 'Api\V1', 'as' => 'api.'], function () {
Route::post('change-password', '[email protected]')->name('auth.change_password');
Route::apiResource('roles', 'RolesController');
Route::apiResource('users', 'UsersController');
Route::apiResource('companies', 'CompaniesController');
Route::apiResource('employees', 'EmployeesController');
});

در اینجا، می‌توانید apiResource را برای هر عمل CRUD و یک POST جداگانه برای تغییر پسورد را مشاهده کنید.

کنترلرها فضاهای نامی تحت Api / V1 هستند، بنابراین در اینجا فضای نامی به صورت زیر خواهد بود: app/Http/Controllers/Api/V1/CompaniesController.php

namespace App\Http\Controllers\Api\V1;

use App\Company;
use App\Http\Controllers\Controller;
use App\Http\Resources\Company as CompanyResource;
use App\Http\Requests\Admin\StoreCompaniesRequest;
use App\Http\Requests\Admin\UpdateCompaniesRequest;
use Illuminate\Http\Request;

class CompaniesController extends Controller
{
    public function index()
    {
        return new CompanyResource(Company::with([])->get());
    }

    public function show($id)
    {
        $company = Company::with([])->findOrFail($id);

        return new CompanyResource($company);
    }

    public function store(StoreCompaniesRequest $request)
    {
        $company = Company::create($request->all());

        return (new CompanyResource($company))
            ->response()
            ->setStatusCode(201);
    }

    public function update(UpdateCompaniesRequest $request, $id)
    {
        $company = Company::findOrFail($id);
        $company->update($request->all());

        return (new CompanyResource($company))
            ->response()
            ->setStatusCode(202);
    }

    public function destroy($id)
    {
        $company = Company::findOrFail($id);
        $company->delete();

        return response(null, 204);
    }
}

در اینجا، یک کنترلر resourceful وجود دارد، همراه با یک exception و کلاس‌های Resources که در لاراول 5.5 در دسترس هستند.
هر resource یک تبدیل ساده به آرایه است، در اینجا فایل  Http / Resources / Company.php را مشاهده می‌کنید:

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

class Company extends JsonResource
{
    /**
     * Transform the resource into an array.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    public function toArray($request)
    {
        return parent::toArray($request);
    }
}

می‌توانید این کد را گسترش دهید، منطق و کد دلخواه خود را به آن اضافه کنید. مثال‌های بیشتر را می‌توانید در اینجا و اینجا مشاهده کنید.

در آخر، Laravel Passport از تمام مسیرها محافظت می‌کند، برای این منظور، در زمان نصب پروژه باید دستور زیر را اجرا کنید:

php artisan passport:install

به عنوان نتیجه‌ نهایی back-end، هر کنترلر مسئولیت عملیات CRUD خاص را که API نامیده می‌شود را دارد.

کد تولید شده Vue.js در قسمت فرانت اند برنامه

اکنون، اجازه دهید نگاهی به قسمت فرانت اند برنامه داشته باشیم. فایل اصلی در این قسمت، resource / client / assets / js / app.js است، جایی که Vue و بعضی از کتابخانه‌ها را در آن وارد می‌‌کنیم:

// ...
window.Vue = require('vue')
Vue.prototype.$eventHub = new Vue()

import router from './routes'
import store from './store'
import Datatable from 'vue2-datatable-component'
import VueAWN from 'vue-awesome-notifications'
import vSelect from 'vue-select'
import datePicker from 'vue-bootstrap-datetimepicker'
import VueSweetalert2 from 'vue-sweetalert2'
import 'eonasdan-bootstrap-datetimepicker/build/css/bootstrap-datetimepicker.css'

Vue.use(Datatable)
Vue.use(VueAWN, {
    position: 'top-right'
})
Vue.use(datePicker)
Vue.use(VueSweetalert2)

Vue.component('back-buttton', require('./components/BackButton.vue'))
Vue.component('bootstrap-alert', require('./components/Alert.vue'))
Vue.component('event-hub', require('./components/EventHub.vue'))
Vue.component('vue-button-spinner', require('./components/VueButtonSpinner.vue'))
Vue.component('v-select', vSelect)

moment.updateLocale(window.app_locale, {
    week: {
        dow: 1
    }
})

const app = new Vue({
    data: {
        relationships: {},
        dpconfigDate: {
            format: window.date_format_moment
        },
        dpconfigTime: {
            format: window.time_format_moment
        },
        dpconfigDatetime: {
            format: window.datetime_format_moment,
            sideBySide: true
        }
    },
    router,
    store
}).$mount('#app')

در اینجا، هر عمل CRUD مجموعه‌ای از اجزای خود را دارد:

laravel-vue-6

برای نمایش جدول داده از Vue2-dataatable-component استفاده می‌کنیم. در اینجا کد کامل resources/clients/assets/components/cruds/Companies/Index.vue را مشاهده می‌کنید:

<template>
    <section class="content-wrapper" style="min-height: 960px;">
        <section class="content-header">
            <h1>Companies</h1>
        </section>

        <section class="content">
            <div class="row">
                <div class="col-xs-12">
                    <div class="box">
                        <div class="box-header with-border">
                            <h3 class="box-title">List</h3>
                        </div>

                        <div class="box-body">
                            <div class="btn-group">
                                <router-link :to="{ name: xprops.route + '.create' }" class="btn btn-success btn-sm">
                                    <i class="fa fa-plus"></i> Add new
                                </router-link>
                                <button type="button" class="btn btn-default btn-sm" @click="fetchData">
                                    <i class="fa fa-refresh" :class="{'fa-spin': loading}"></i> Refresh
                                </button>
                            </div>
                        </div>

                        <div class="box-body">
                            <div class="row" v-if="loading">
                                <div class="col-xs-4 col-xs-offset-4">
                                    <div class="alert text-center">
                                        <i class="fa fa-spin fa-refresh"></i> Loading
                                    </div>
                                </div>
                            </div>

                            <datatable
                                    v-if="!loading"
                                    :columns="columns"
                                    :data="data"
                                    :total="total"
                                    :query="query"
                                    :xprops="xprops"
                                    />
                        </div>
                    </div>
                </div>
            </div>
        </section>
    </section>
</template>

<script>
import { mapGetters, mapActions } from 'vuex'
import DatatableActions from '../../dtmodules/DatatableActions'
import DatatableSingle from '../../dtmodules/DatatableSingle'
import DatatableList from '../../dtmodules/DatatableList'
import DatatableCheckbox from '../../dtmodules/DatatableCheckbox'

export default {
    data() {
        return {
            columns: [
                { title: '#', field: 'id', sortable: true, colStyle: 'width: 50px;' },
                { title: 'Name', field: 'name', sortable: true },
                { title: 'Description', field: 'description', sortable: true },
                { title: 'Actions', tdComp: DatatableActions, visible: true, thClass: 'text-right', tdClass: 'text-right', colStyle: 'width: 130px;' }
            ],
            query: { sort: 'id', order: 'desc' },
            xprops: {
                module: 'CompaniesIndex',
                route: 'companies'
            }
        }
    },
    created() {
        this.$root.relationships = this.relationships
        this.fetchData()
    },
    destroyed() {
        this.resetState()
    },
    computed: {
        ...mapGetters('CompaniesIndex', ['data', 'total', 'loading', 'relationships']),
    },
    watch: {
        query: {
            handler(query) {
                this.setQuery(query)
            },
            deep: true
        }
    },
    methods: {
        ...mapActions('CompaniesIndex', ['fetchData', 'setQuery', 'resetState']),
    }
}
</script>

<style scoped>

</style>

برای انجام این کارها کد زیادی تولید می‌شود البته، این موارد را می‌توان با کد کمتر و به صورت ساده‌تر نیز انجام داد، اما ما سعی کردیم مستندات رسمی و بهترین روش‌ها را استفاده کنیم و کدی را که می‌توان برای پروژه‌های بزرگتر نیز استفاده کرد،. برای شما آماده کنیم.

 اجازه دهید، مروری بر Create.vue داشته باشیم:

<template>
    <section class="content-wrapper" style="min-height: 960px;">
        <section class="content-header">
            <h1>Companies</h1>
        </section>

        <section class="content">
            <div class="row">
                <div class="col-xs-12">
                    <form @submit.prevent="submitForm">
                        <div class="box">
                            <div class="box-header with-border">
                                <h3 class="box-title">Create</h3>
                            </div>

                            <div class="box-body">
                                <back-buttton></back-buttton>
                            </div>

                            <bootstrap-alert />

                            <div class="box-body">
                                <div class="form-group">
                                    <label for="name">Name</label>
                                    <input
                                            type="text"
                                            class="form-control"
                                            name="name"
                                            placeholder="Enter Name"
                                            :value="item.name"
                                            @input="updateName"
                                            >
                                </div>
                                <div class="form-group">
                                    <label for="description">Description</label>
                                    <textarea
                                            rows="3"
                                            class="form-control"
                                            name="description"
                                            placeholder="Enter Description"
                                            :value="item.description"
                                            @input="updateDescription"
                                            >
                                    </textarea>
                                </div>
                            </div>

                            <div class="box-footer">
                                <vue-button-spinner
                                        class="btn btn-primary btn-sm"
                                        :isLoading="loading"
                                        :disabled="loading"
                                        >
                                    Save
                                </vue-button-spinner>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </section>
    </section>
</template>

<script>
import { mapGetters, mapActions } from 'vuex'

export default {
    data() {
        return {
            // Code...
        }
    },
    computed: {
        ...mapGetters('CompaniesSingle', ['item', 'loading'])
    },
    created() {
        // Code ...
    },
    destroyed() {
        this.resetState()
    },
    methods: {
        ...mapActions('CompaniesSingle', ['storeData', 'resetState', 'setName', 'setDescription']),
        updateName(e) {
            this.setName(e.target.value)
        },
        updateDescription(e) {
            this.setDescription(e.target.value)
        },
        submitForm() {
            this.storeData()
                .then(() => {
                    this.$router.push({ name: 'companies.index' })
                    this.$eventHub.$emit('create-success')
                })
                .catch((error) => {
                    console.error(error)
                })
        }
    }
}
</script>

<style scoped>

</style>

عملیات Edit  و Show در CRUD بسیار شبیه به هم هستند، بنابراین در اینجا زیاد درباره آن‌ها توضیح داده نشده است..

علاوه بر کد Vue، در اینجا جزئیات بیشتر و همچنین helperهایی مانند Sweet Alert، Notifications، Datepickers و داده‌های روابط setting/getting برای فرم‌ها وجود دارد. می‌توانید خودتان کدهای موجود را تجزیه تحلیل کنید.

توجه داشته باشید که انتخاب کتابخانه‌های Vue.js  بخش چالش برانگیز پروژه است، زیرا باید کتابخانه های Vue مناسب را انتخاب کنید.

همچنین، اگر بخواهید مروری سریع بر Vue + Laravel QuickAdminPanel  داشته باشید، می‌توانید از لینک زیر استفاده کنید: https://vue.quickadminpanel.com

همچنین، در اینجا دموی پروژه را با دو CRUD مشاهده می‌کنید: customers و  companies

laravel-vue-7

آموزش‌های بیشتر در لیداوب:

آموزش پایه لاراول ۵,۵

آموزش CSS

آموزش HTML مقدماتی

امیدوارم که توضیح این generator علاوه بر صرفه‌جویی در وقت شما در نوشتن کد، چگونگی کار کردن لاراول با vue را نیز به شما نشان دهد. روش ما در انجام این کار، تنها روش ممکن نیست و می‌توانید کدهای خود را به شکل دیگری طراحی و پیاده سازی کنید. می‌توانید مقالات تخصصی مشابه درباره لاراول و vue.js را در لیداوب دنبال کنید. همچنین، اگر در هر یک از زمینه‌های طراحی وب و برنامه نویسی موبایل مهارت دارید، می‌توانید از امکان ارائه و فروش محصولات سایت ما استفاده کنید. با استفاده از این ویژگی در کتابخانه آنلاین لیداوب، شما صاحب یک صفحه شخصی به صورت رایگان خواهید بود که می‌توانید مقالات و ویدیوهای آموزشی خودتان را در آن بارگزاری نمایید. برای اطلاعات بیشتر می‌توانید این صفحه از سایت را مطالعه نمایید.