Laravel Vue Admin - #1 Admin panel Setup
首先,用到了laravel ui扩展包 及基础的 vue 脚手架:
执行:
composer require laravel/ui
执行:
php artisan ui vue --auth
执行:
npm install & npm run watch
介绍一下Laravel Permission 扩展包:
A package to add roles and permissions to Laravel
https://github.com/spatie/laravel-permission
因为自Laravel 5.1.1版本开始就提供了很不错的授权功能,用起来比较简洁,检查用户是否有操作的权限也是超级简单。这个Laravel Permission扩展包就是以Jeffrey's code 为基础,发展起来的,可以很方便的给用户授予角色,权限。
参考:https://docs.spatie.be/laravel-permission/v3/introduction/
// Adding permissions to a user
$user->givePermissionTo('edit articles');
// Adding permissions via a role
$user->assignRole('writer');
$role->givePermissionTo('edit articles');前言
由于这个扩展包提供所有的权限都是注册于Laravel Gate之上。
只要你的User模型类实现了 Illuminate\Contracts\Auth\Access\Authorizable【这个是默认的Illuminate\Foundation\Auth\User中实现了的】,那么默认提供的can方法也是可以使用的:
$user->can('edit articles');blade中也可以使用:
@can('edit articles') ... @endcan记得User模型类中需要使用HasRoles这个trait来实现扩展包的功能。
所以至少你的User模型类应该有这个:
use Illuminate\Foundation\Auth\User as Authenticatable; use Spatie\Permission\Traits\HasRoles; class User extends Authenticatable { use HasRoles; // ... }
另外,你的User模型不能有role或者roles属性以及roles()方法,且数据库中也不能有这两个字段。
因为HasRoles trait已经提供了,否则你重写的方法可能造成不当的结果。
同样,你的User模型类也不能有permission或者permissions属性或者permissions()方法,数据库中也不能有这两个字段。
因为HasRoles trait中的 HasPermissions trait已经提供了。
这个安装包会生成config/permission.php文件。如果你有一个自建文件和这个文件同名,那移动到其他位置或者重命名一下,否则会冲突。视个人的需要也可以添加自己的方法到里面。
安装:
执行:
composer require spatie/laravel-permission
config/app.php修改如下:
'providers' => [
// ...
Spatie\Permission\PermissionServiceProvider::class,
];然后执行:
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider"
生成了permission.php文件,以及一个create_permission_tables.php文件:
如果需要UUID请看:UUID
执行migrate之前确保env中DB_DATABASE设置正确,否则会报错:
我的database是vue
所以:
然后执行:
php artisan migrate
最后,按照前言中的要求,修改User模型类。
Vuetify安装:
参考: Webpack install 执行:
npm i vuetify --save
然后需要引用vuetify:
js/app.js添加:
import Vuetify from "vuetify"; Vue.use(Vuetify); import 'vuetify/dist/vuetify.min.css';
为了让修改的样式不受缓存影响,在webpack.mix.js后添加一个version();
然后layout/app.blade.php中 asset()方法改为mix()方法:
参考https://vuetifyjs.com/en/getting-started/quick-start/#bootstrapping-the-vuetify-object:
添加下面代码到webpack.mix.js中:
// webpack.config.js
module.exports = {
rules: [
{
test: /\.s(c|a)ss$/,
use: [
'vue-style-loader',
'css-loader',
{
loader: 'sass-loader',
// Requires sass-loader@^7.0.0
options: {
implementation: require('sass'),
fiber: require('fibers'),
indentedSyntax: true // optional
},
// Requires sass-loader@^8.0.0
options: {
implementation: require('sass'),
sassOptions: {
fiber: require('fibers'),
indentedSyntax: true // optional
},
},
},
],
},
],
}创建一插件文件:src/plugins/vuetify.js
// src/plugins/vuetify.js
import Vue from 'vue'
import Vuetify from 'vuetify'
import 'vuetify/dist/vuetify.min.css'
Vue.use(Vuetify)
const opts = {}
export default new Vuetify(opts)
然后修改app.js对vuetify的引用:
路由:
web.php中添加:
Route::any('/admin/{any?}', 'AdminController@index')->where('any', '.*')->middleware('auth');
控制器:
执行:
php artisan make:controller AdminController
新建的控制器添加方法:
public function __construct()
{
$this->middleware('auth');
}
//
public function index(Request $request)
{
return view('admin');
}
index方法返回admin这个view视图,现在来新建这个视图文件:
如果不用layouts.app基础框架那么 拷贝一下layouts.app中的内容 替换div#app中的内容:
注意这里添加了一个Admin的vue component【vue组件】,所以开始处理这个vue组件:
在components文件夹下新建一个Admin.vue文件:
Admin.vue直接用vuetify的模板:Pre-made layouts 暂时选了 Dark附上代码链接。
初步的Admin.vue:
<template> <v-app id="inspire"> <v-navigation-drawer v-model="drawer" app clipped > <v-list dense> <v-list-item link> <v-list-item-action> <v-icon>mdi-view-dashboard</v-icon> </v-list-item-action> <v-list-item-content> <v-list-item-title>Dashboard</v-list-item-title> </v-list-item-content> </v-list-item> <v-list-item link> <v-list-item-action> <v-icon>mdi-settings</v-icon> </v-list-item-action> <v-list-item-content> <v-list-item-title>Settings</v-list-item-title> </v-list-item-content> </v-list-item> </v-list> </v-navigation-drawer> <v-app-bar app clipped-left > <v-app-bar-nav-icon @click.stop="drawer = !drawer"/> <v-toolbar-title>Application</v-toolbar-title> </v-app-bar> <v-content> <v-container class="fill-height" fluid > <v-row align="center" justify="center" > <v-col class="shrink"> <v-tooltip right> <template v-slot:activator="{ on }"> <v-btn :href="source" icon large target="_blank" v-on="on" > <v-icon large>mdi-code-tags</v-icon> </v-btn> </template> <span>Source</span> </v-tooltip> <v-tooltip right> <template v-slot:activator="{ on }"> <v-btn icon large href="https://codepen.io/johnjleider/pen/bXNzZL" target="_blank" v-on="on" > <v-icon large>mdi-codepen</v-icon> </v-btn> </template> <span>Codepen</span> </v-tooltip> </v-col> </v-row> </v-container> </v-content> <v-footer app> <span>© 2019</span> </v-footer> </v-app> </template> <script> export default { name: "Admin", props: { source: String, user: Object, }, data: function () { return { drawer: null, } }, created() { this.$vuetify.theme.dark = true; }, } </script> <style scoped> </style>
Vue-router
安装:
执行:
npm i vue-router
安装完成:
然后app.js中引用:
因为admin route及AdminController都经过了auth中间件,所以注册一个用户是必须的:
然后登录 :
注意执行:
npm install & npm run watch-poll
打开链接:http://vue.test/admin 即可看到:
接下来添加vue的route文件:
先添加,再编辑:
app.js里面需要添加代码应用这几个route:
import Dashboard from "./components/pages/Dashboard";
import Users from "./components/pages/Users";
import Settings from "./components/pages/Settings";
import Roles from "./components/pages/Roles";
import Permissions from "./components/pages/Permissions";
const routes = [
{
path: '/admin/',
component: Dashboard,
},
{
path: '/admin/users',
component: Users,
},
{
path: '/admin/roles',
component: Roles,
},
{
path: '/admin/settings',
component: Settings,
},
{
path: '/admin/permissions',
component: Permissions,
},
];
const router = new VueRouter({
mode: 'history',
routes,
});
并且vue实例需要配置这个router:
const app = new Vue({
el: '#app',
vuetify,
router,
});
接下来 用户点击dashboard按钮 setting按钮的跳转,以及添加用户的users roles permissions按钮:
需要修改Admin.vue:
<template> <v-app id="inspire"> <v-navigation-drawer v-model="drawer" app clipped > <v-list dense> <v-list-item link to="/admin"> <v-list-item-action> <v-icon>mdi-view-dashboard</v-icon> </v-list-item-action> <v-list-item-content> <v-list-item-title>Dashboard</v-list-item-title> </v-list-item-content> </v-list-item> <v-list-group no-action> <v-list-item slot="activator"> <v-list-item-action> <v-icon>mdi-account</v-icon> </v-list-item-action> <v-list-item-content> <v-list-item-title>User Management</v-list-item-title> </v-list-item-content> </v-list-item> <v-list-item link to="/admin/users"> <v-list-item-action> <v-icon>mdi-account</v-icon> </v-list-item-action> <v-list-item-content> <v-list-item-title>Users</v-list-item-title> </v-list-item-content> </v-list-item> <v-list-item link to="/admin/roles"> <v-list-item-action> <v-icon>mdi-account</v-icon> </v-list-item-action> <v-list-item-content> <v-list-item-title>Roles</v-list-item-title> </v-list-item-content> </v-list-item> <v-list-item link to="/admin/permissions"> <v-list-item-action> <v-icon>mdi-account</v-icon> </v-list-item-action> <v-list-item-content> <v-list-item-title>Permissions</v-list-item-title> </v-list-item-content> </v-list-item> </v-list-group> <v-list-item link to="/admin/settings"> <v-list-item-action> <v-icon>mdi-settings</v-icon> </v-list-item-action> <v-list-item-content> <v-list-item-title>Settings</v-list-item-title> </v-list-item-content> </v-list-item> </v-list> </v-navigation-drawer> <v-app-bar app clipped-left > <v-app-bar-nav-icon @click.stop="drawer = !drawer"/> <v-toolbar-title>Application</v-toolbar-title> </v-app-bar> <v-content> <v-container class="fill-height" fluid > <v-row align="center" justify="center" > <v-col class="shrink"> <v-tooltip right> <template v-slot:activator="{ on }"> <v-btn :href="source" icon large target="_blank" v-on="on" > <v-icon large>mdi-code-tags</v-icon> </v-btn> </template> <span>Source</span> </v-tooltip> <v-tooltip right> <template v-slot:activator="{ on }"> <v-btn icon large href="https://codepen.io/johnjleider/pen/bXNzZL" target="_blank" v-on="on" > <v-icon large>mdi-codepen</v-icon> </v-btn> </template> <span>Codepen</span> </v-tooltip> </v-col> </v-row> </v-container> </v-content> <v-footer app> <span>© 2019</span> </v-footer> </v-app> </template> <script> export default { name: "Admin", props: { source: String, user: Object, }, data: function () { return { drawer: null, } }, created() { this.$vuetify.theme.dark = true }, } </script> <style scoped> </style>
vue-router会在点击按钮的时候跳转到对应的route加载component,但是目前代码中缺少一个展示加载的component的代码:添加
<router-view></router-view>
到内容的地方:
<template> <v-app id="inspire"> <v-navigation-drawer v-model="drawer" app clipped > <v-list dense> <v-list-item link to="/admin"> <v-list-item-action> <v-icon>mdi-view-dashboard</v-icon> </v-list-item-action> <v-list-item-content> <v-list-item-title>Dashboard</v-list-item-title> </v-list-item-content> </v-list-item> <v-list-group no-action> <v-list-item slot="activator"> <v-list-item-action> <v-icon>mdi-account</v-icon> </v-list-item-action> <v-list-item-content> <v-list-item-title>User Management</v-list-item-title> </v-list-item-content> </v-list-item> <v-list-item link to="/admin/users"> <v-list-item-action> <v-icon>mdi-account</v-icon> </v-list-item-action> <v-list-item-content> <v-list-item-title>Users</v-list-item-title> </v-list-item-content> </v-list-item> <v-list-item link to="/admin/roles"> <v-list-item-action> <v-icon>mdi-account</v-icon> </v-list-item-action> <v-list-item-content> <v-list-item-title>Roles</v-list-item-title> </v-list-item-content> </v-list-item> <v-list-item link to="/admin/permissions"> <v-list-item-action> <v-icon>mdi-account</v-icon> </v-list-item-action> <v-list-item-content> <v-list-item-title>Permissions</v-list-item-title> </v-list-item-content> </v-list-item> </v-list-group> <v-list-item link to="/admin/settings"> <v-list-item-action> <v-icon>mdi-settings</v-icon> </v-list-item-action> <v-list-item-content> <v-list-item-title>Settings</v-list-item-title> </v-list-item-content> </v-list-item> </v-list> </v-navigation-drawer> <v-app-bar app clipped-left > <v-app-bar-nav-icon @click.stop="drawer = !drawer"/> <v-toolbar-title>Application</v-toolbar-title> </v-app-bar> <v-content> <v-container class="fill-height" fluid > <v-row align="center" justify="center" > <v-col class="shrink"> <router-view></router-view> </v-col> </v-row> </v-container> </v-content> <v-footer app> <span>© 2019</span> </v-footer> </v-app> </template> <script> export default { name: "Admin", props: { source: String, user: Object, }, data: function () { return { drawer: null, } }, created() { this.$vuetify.theme.dark = true }, } </script> <style scoped> </style>
最后效果:





























浙公网安备 33010602011771号