Laravel 10 应用程序,带有 Jetstream/Inertia/Vue 3。
我使用laravel-spatie-permissions-vue来处理用户权限和角色,分配ok。目前我正在使用默认的 Jetstream 视图,因此当用户登录仪表板时会显示,我将其放在 Components/Welcome.vue 上:
<div v-if="is('administrator')">is administrator.</div>
<div v-if="is('user')">is user.</div>
出于测试目的,有两个角色:管理员和用户,也有一些权限,但由于它们都有相同的问题,所以我们只保留角色。 问题是,第一次登录时,以用户为例,没有显示任何内容,这是错误的。如果刷新页面,“是用户”。将会出现,正如它应该出现的那样。然后,如果您注销并使用管理员身份登录,则“是用户”。将显示(不正确),但如果刷新页面“是管理员”。将显示(正确)。 我在开发中使用 valet 和“npm run dev”得到的行为与部署到 apache 服务器并执行“npm run build”时的行为相同。
我遵循了 https://github.com/geowrgetudor/laravel-spatie-permissions-vue 上的所有说明。
我已经搜索了两天,但由于我没有找到任何人有同样的问题,我想我犯了一些愚蠢的错误。我认为问题应该与 app.blade.php 部分有关,也许它必须与缓存相关,但没有找到任何沿着这条路走的东西,所以目前没有线索。
我尝试过的(仅相关步骤):
laravel new application
composer require laravel/jetstream
php artisan jetstream:install inertia
npm i @vitejs/plugin-vue
npm install -D tailwindcss postcss autoprefixer
composer require spatie/laravel-permission
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider"
composer require geowrgetudor/laravel-spatie-permissions-vue
use SpatiePermissionVue\Traits\RolesPermissionsToVue;
class User extends Authenticatable
{
// ...
use RolesPermissionsToVue;
}
import RolesPermissionsToVue from "../../vendor/geowrgetudor/laravel-spatie-permissions-vue/src/js";
// createInertiaApp, right after '.use(ZiggyVue, Ziggy)':
.use(RolesPermissionsToVue)
<script type="text/javascript">
window.vueSpatiePermissions = {!! auth()->check() ? auth()->user()->getRolesPermissionsAsJson() : 0 !!}
</script>
在 Components/Welcome.vue 上添加了这个:
<div v-if="is('administrator')">is administrator.</div>
<div v-if="is('user')">is user.</div>
我期待“是管理员”。或“是用户”。将在用户登录后显示,无需刷新页面。
用户已正确分配其角色和权限,可以在 HandleInertiaRequests 的 share() 函数中添加此代码来检查:
$permissions = Auth::check() ? Auth::user()->permissions->pluck('name') : "";
$roles = Auth::check() ? Auth::user()->roles->pluck('name') : "";
return array_merge(parent::share($request), [
'auth.user.permissions' => $permissions,
'auth.user.roles' => $roles
]);
然后在视图中添加 {{ $page.props.auth.user.roles }} 或 {{ $page.props.auth.user.permissions }} ,所以这不是问题。
如有任何帮助,我们将不胜感激。谢谢。
最后,感谢 cengsemihsahin 的回应,我改变了处理此问题的方式,最终将我带到了 How to Add Roles and Permission to Laravel Fortify + Inertia + vue? 我最终使用了 Viduranga 的方法,如下所示这样就不需要 laravel-apatie-permissions-vue 或 laravel-permission-to-vuejs,只需更改 HandleInertiaRequests 中的 share() 函数(这是我的):
public function share(Request $request): array
{
$permissions = Auth::check() ? Auth::user()->permissions->mapWithKeys(function($pr){ return [$pr['name'] => true]; }) : [];
$roles = Auth::check() ? Auth::user()->roles->mapWithKeys(function($pr){ return [$pr['name'] => true]; }) : [];
return array_merge(parent::share($request), [
'auth.user.permissions' => $permissions,
'auth.user.roles' => $roles
]);
}
然后你可以在你的视图中使用它:
v-if="$page.props.auth.user.roles['administrator']"
我认为这个解决方案比我在项目中使用的解决方案更好。
window.Laravel
文件中分配的 window.vueSpatiePermissions
或 app.blade.php
变量是在创建 vue 应用程序时分配的。因此,更改 vue 应用程序上浏览器中的路由或通过 api 进行 login 或 logout 不会更改你的 `app.blade.php` 视图或不会重新加载。use LaravelPermissionToVueJS;
在 app.blade.php
<script type="text/javascript">
window.Laravel = {
csrfToken: "{{ csrf_token() }}",
jsPermissions: {!! auth()->check() ? auth()->user()->jsPermissions() : 0 !!}
};
</script>
在 main.js (创建应用程序时)
import App from './App.vue';
import LaravelPermissionToVueJS from 'laravel-permission-to-vuejs';
const app = createApp(App);
app.use(LaravelPermissionToVueJS);
app.mount('#app');
在我的解决方案中(在我自己的应用程序中),通过在每次 login 或 logout 操作时在浏览器上提供 HTTP 请求来重定向页面,从而重新加载页面。
这是一个不必要且不专业的解决方案。除此之外,我将在下面解释您可以再次执行的解决方案。
我的
login.vue
(以最短为例)
<form class="d-none" method="post" action="/auth/login">
<input type="hidden" name="_token" :value="csrf">
<input type="hidden" name="username" :value="user.username">
<input type="hidden" name="password" :value="user.password">
<button ref="submitLoginForm" class="d-none"></button>
</form>
<form class="text-start" @submit="login">
<div class="form">
<div id="username-field" class="field-wrapper input">
<input type="text" name="username" class="form-control"
required v-model="user.username"
placeholder="username" />
</div>
<div id="password-field" class="field-wrapper input mb-2">
<input
:type="show_password ? 'text' : 'password'"
v-model="user.password"
name="password"
class="form-control"
required
placeholder="passphrase"
/>
</div>
<button type="submit" class="btn btn-primary">login</button>
</div>
</form>
<script>
export default {
data() {
return {
csrf: document.querySelector('meta[name="csrf-token"]').getAttribute('content'),
user: {
username: '',
password: '',
remember: false,
}
}
},
methods: {
login(e) {
e.preventDefault();
store.dispatch('login', this.user);
this.$refs.submitLoginForm.click();
}
}
}
</script>
您可以使用composition api,您可以通过
参考并提交表单。defineExpose
然后页面自动刷新,并且api端和web端都提供登录。我针对自己的应用程序执行此操作是有原因的。
window.Echo.private('permissions').listen('.user_permissions_changed', (e) => {
console.log(e);
window.Laravel.jsPermissions.permissions = e.user_permissions;
});
由于我没有时间,所以无法详述。如果您还有疑问,请写为评论。