Laravel + Vue.js 管理面板生成器

最后更新于 作者:

Laravel + Vue.js AdminPanel Generator image

Laravel 和 Vue.js 通常一起使用。随着这些技术上更多工具的发布,这里有一个新的工具 - 向您介绍 Vue+Laravel 管理面板生成器

免责声明:我是该工具的创始人兼开发人员之一,也是 Laravel 专用生成器 QuickAdminPanel 的开发人员,但本文的目标不仅是向您展示产品,而是解释它生成的內容以及 Vue + Laravel 如何协同工作。此外,您将在 Github 上找到一个具有源代码的示例项目。

生成器如何工作?

对于喜欢视频的人,这里有一个快速演示

现在,让我们更详细地看看它。

步骤 1. 您无需编写代码,只需添加菜单项和字段即可创建面板。

步骤 2. 在任何时候,您都可以查看生成的代码,逐个文件查看。

步骤 3. 然后,您下载代码并安装它 - 在本地或远程服务器上,使用以下命令

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

当然,您的 .env 文件应该在此时配置好。

然后,在前端

npm install
npm run dev

步骤 4. 就这样;您拥有了自己的面板。

步骤 5. 最重要的一点:您可以随意更改代码,它纯粹是 Laravel+Vue,没有我们的生成器包作为依赖项。这是它与像 VoyagerLaravel Backpack (顺便说一句,它们都很棒!) 这样的包的主要区别。


我们正在生成什么 - 项目结构

下载项目后,您会看到类似这样的内容

生成的代码:后端 Laravel

首先,让我们分析充当 API 的后端 Laravel 部分

以下是 routes/api.php 文件

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

您可以看到每个 CRUD 的 apiResource,以及一个单独的 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);
}
}

我们有一个典型的资源控制器,只有一个例外 - 资源类,自 Laravel 5.5 以来一直可用。

在我们的案例中,每个资源都是一个简单的数组转换,这里是一个文件 app/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

作为后端结果,每个控制器都负责从 Vue.js 前端调用 API 的特定 CRUD 操作。

生成的代码:前端 Vue.js

现在,让我们看看前端部分。主要文件是 resources/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')

相关: Laravel Sweetalert

接下来,每个 CRUD 都有自己的一组组件

为了显示数据表,我们使用的是 vue2-datatable-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>

EditShow CRUD 的组件非常相似,所以这里就不讨论了。

除了 Vue 代码之外,还有许多小的细节和辅助工具,如 Sweet AlertNotificationsDatepickers 以及设置/获取表单的关系数据。我想我会留给您去分析。

注意:Vue.js 库的选择非常主观,也是项目中最具挑战性的部分 - 选择值得信赖的 Vue 库。生态系统仍然缺乏标准,或 100% 可信赖的开源 - 市场上有很大的变动,一些库的支持比其他库更好。所以总是很难预测,最好的库可能会随着时间的推移而改变,或者会出现新的库。


这就是对 Vue+Laravel QuickAdminPanel 的快速概述的结尾,请在这里尝试它:https://vue.quickadminpanel.com

最后,这里是 包含两个 CRUD 的演示项目的源代码:公司和客户

我希望我们的生成器不仅能节省您编写代码的时间,还能向您展示 Vue 如何与 Laravel 协同工作。我们对代码进行结构化的方法不是唯一的方法,您可以以不同的方式对代码进行结构化,但我们尽力坚持标准。

PovilasKorop photo

Laravel Daily 的课程和教程创作者

归档于
Cube

Laravel 新闻稿

加入 40,000 多名其他开发者,永远不要错过新的技巧、教程等。

Laravel Forge logo

Laravel Forge

轻松创建和管理服务器,并在几秒钟内部署您的 Laravel 应用程序。

Laravel Forge
Tinkerwell logo

Tinkerwell

Laravel 开发人员必备的代码运行器。使用 AI、自动完成和对本地和生产环境的即时反馈进行调试。

Tinkerwell
No Compromises logo

不妥协

Joel 和 Aaron,两位来自 No Compromises 播客的经验丰富的开发者,现在可以为您的 Laravel 项目雇佣。⬧ 固定价格为每月 7500 美元。⬧ 没有冗长的销售流程。⬧ 没有合同。⬧ 100% 退款保证。

不妥协
Kirschbaum logo

Kirschbaum

提供创新和稳定性,以确保您的 Web 应用程序成功。

Kirschbaum
Shift logo

Shift

运行旧版本的 Laravel?即时、自动化的 Laravel 升级和代码现代化,让您的应用程序保持新鲜。

Shift
Bacancy logo

Bacancy

仅需每月 2500 美元,即可让您拥有经验丰富的 Laravel 开发人员,拥有 4-6 年的经验。获得 160 小时的专用专业知识和 15 天的无风险试用。立即安排电话会议!

Bacancy
Lucky Media logo

Lucky Media

现在就来试试 Get Lucky Now - Laravel 开发的理想选择,拥有十多年的经验!

Lucky Media
Lunar: Laravel E-Commerce logo

Lunar:Laravel 电子商务

Laravel 的电子商务解决方案。一个开源包,为 Laravel 带来了现代无头电子商务功能的力量。

Lunar:Laravel 电子商务
LaraJobs logo

LaraJobs

官方 Laravel 招聘网站

LaraJobs
SaaSykit: Laravel SaaS Starter Kit logo

SaaSykit:Laravel SaaS 启动工具包

SaaSykit 是一个 Laravel SaaS 启动工具包,它包含运行现代 SaaS 所需的所有功能。包括支付、美观的结账流程、管理面板、用户仪表盘、身份验证、即用型组件、统计数据、博客、文档等等。

SaaSykit:Laravel SaaS 启动工具包
Rector logo

Rector

您无缝升级 Laravel 的合作伙伴,降低成本,加速创新,助力企业取得成功

Rector
MongoDB logo

MongoDB

通过强大的 MongoDB 和 Laravel 集成,增强您的 PHP 应用程序,让开发人员能够轻松高效地构建应用程序。支持事务、搜索、分析和移动用例,同时使用熟悉的 Eloquent API。探索灵活、现代的 MongoDB 数据库如何改变您的 Laravel 应用程序。

MongoDB

最新消息

查看全部 →
Maska is a Simple Zero-dependency Input Mask Library image

Maska 是一个简单的零依赖输入掩码库

阅读文章
Add Swagger UI to Your Laravel Application image

在 Laravel 应用程序中添加 Swagger UI

阅读文章
Assert the Exact JSON Structure of a Response in Laravel 11.19 image

在 Laravel 11.19 中断言响应的 JSON 结构

阅读文章
Build SSH Apps with PHP and Laravel Prompts image

使用 PHP 和 Laravel Prompts 构建 SSH 应用程序

阅读文章
Building fast, fuzzy site search with Laravel and Typesense image

使用 Laravel 和 Typesense 构建快速模糊站点搜索

阅读文章
Add Comments to your Laravel Application with the Commenter Package image

使用 Commenter 包在 Laravel 应用程序中添加评论

阅读文章