5.6.10 • Published 6 months ago
@cimom/vben-stores v5.6.10
@cimom/vben-stores
基于 Pinia 的状态管理工具包,提供了应用中常用的状态存储模块,包括用户状态、权限控制、标签页管理等。
安装
npm install @cimom/vben-stores基本使用
初始化 Store
import { setupStore } from '@cimom/vben-stores';
import type { App } from 'vue';
// 在应用启动时初始化
export function setupApp(app: App) {
// 初始化状态管理
setupStore(app);
// ... 其他初始化
}使用状态存储
import {
useUserStore,
useAccessStore,
useTabbarStore,
} from '@cimom/vben-stores';
// 用户状态
const userStore = useUserStore();
console.log(userStore.userInfo);
// 权限状态
const accessStore = useAccessStore();
console.log(accessStore.hasPermission('user:create'));
// 标签页状态
const tabbarStore = useTabbarStore();
console.log(tabbarStore.tabs);可用的状态存储模块
用户状态 (UserStore)
管理用户信息和登录状态。
import { useUserStore } from '@cimom/vben-stores';
const userStore = useUserStore();
// 获取用户信息
const userInfo = userStore.userInfo;
// 设置用户信息
userStore.setUserInfo({
id: '1',
username: 'admin',
realName: '管理员',
avatar: '/avatar.jpg',
// 其他用户信息...
});
// 清除用户信息
userStore.resetUserInfo();状态
| 状态名 | 类型 | 说明 |
|---|---|---|
userInfo | UserInfo | 用户信息 |
方法
| 方法名 | 参数 | 返回值 | 说明 |
|---|---|---|---|
setUserInfo | (info: UserInfo) => void | void | 设置用户信息 |
resetUserInfo | - | void | 重置用户信息 |
权限控制 (AccessStore)
管理用户权限和角色。
import { useAccessStore } from '@cimom/vben-stores';
const accessStore = useAccessStore();
// 检查是否有特定权限
if (accessStore.hasPermission('user:create')) {
// 有创建用户的权限
}
// 检查是否有特定角色
if (accessStore.hasRole('admin')) {
// 是管理员角色
}
// 设置权限列表
accessStore.setPermissions(['user:create', 'user:edit', 'user:delete']);
// 设置角色列表
accessStore.setRoles(['admin', 'editor']);
// 重置权限和角色
accessStore.resetPermissions();
accessStore.resetRoles();状态
| 状态名 | 类型 | 说明 |
|---|---|---|
permissions | string[] | 权限列表 |
roles | string[] | 角色列表 |
superAdmin | boolean | 是否为超级管理员 |
方法
| 方法名 | 参数 | 返回值 | 说明 |
|---|---|---|---|
setPermissions | (permissions: string[]) => void | void | 设置权限列表 |
resetPermissions | - | void | 重置权限列表 |
setRoles | (roles: string[]) => void | void | 设置角色列表 |
resetRoles | - | void | 重置角色列表 |
setSuperAdmin | (value: boolean) => void | void | 设置超级管理员状态 |
hasPermission | (permission: string \| string[]) => boolean | boolean | 检查是否有特定权限 |
hasRole | (role: string \| string[]) => boolean | boolean | 检查是否有特定角色 |
标签页管理 (TabbarStore)
管理应用的标签页。
import { useTabbarStore } from '@cimom/vben-stores';
const tabbarStore = useTabbarStore();
// 获取所有标签页
const tabs = tabbarStore.tabs;
// 获取当前激活的标签页
const activeTab = tabbarStore.activeTab;
// 添加标签页
tabbarStore.addTab({
path: '/dashboard',
title: '仪表盘',
name: 'Dashboard',
closable: false,
});
// 关闭标签页
tabbarStore.closeTab('/dashboard');
// 关闭其他标签页
tabbarStore.closeOtherTabs('/dashboard');
// 关闭左侧标签页
tabbarStore.closeLeftTabs('/dashboard');
// 关闭右侧标签页
tabbarStore.closeRightTabs('/dashboard');
// 关闭所有标签页
tabbarStore.closeAllTabs();
// 设置激活的标签页
tabbarStore.setActiveTab('/dashboard');
// 刷新当前标签页
tabbarStore.refreshTab();状态
| 状态名 | 类型 | 说明 |
|---|---|---|
tabs | TabItem[] | 标签页列表 |
activeTab | string | 当前激活的标签页路径 |
reloadFlag | boolean | 刷新标志 |
cachedTabs | Set<string> | 缓存的标签页 |
方法
| 方法名 | 参数 | 返回值 | 说明 |
|---|---|---|---|
setTabs | (tabs: TabItem[]) => void | void | 设置标签页列表 |
addTab | (tab: TabItem) => void | void | 添加标签页 |
updateTab | (path: string, tab: Partial<TabItem>) => void | void | 更新标签页 |
closeTab | (path: string) => void | void | 关闭标签页 |
closeOtherTabs | (path: string) => void | void | 关闭其他标签页 |
closeLeftTabs | (path: string) => void | void | 关闭左侧标签页 |
closeRightTabs | (path: string) => void | void | 关闭右侧标签页 |
closeAllTabs | - | void | 关闭所有标签页 |
setActiveTab | (path: string) => void | void | 设置激活的标签页 |
refreshTab | (path?: string) => void | void | 刷新标签页 |
addCachedTab | (name: string) => void | void | 添加缓存的标签页 |
removeCachedTab | (name: string) => void | void | 移除缓存的标签页 |
clearCachedTabs | - | void | 清除所有缓存的标签页 |
resetState | - | void | 重置状态 |
类型定义
用户信息 (UserInfo)
interface UserInfo {
id: string;
username: string;
realName: string;
avatar: string;
desc?: string;
homePath?: string;
roles?: string[];
}标签页项 (TabItem)
interface TabItem {
path: string;
name: string;
title: string;
icon?: string;
closable?: boolean;
affix?: boolean;
query?: Record<string, any>;
params?: Record<string, any>;
}高级用法
自定义 Store
可以基于提供的 Store 创建自定义的状态存储。
import { defineStore } from '@cimom/vben-stores';
// 定义状态接口
interface CounterState {
count: number;
lastUpdated: number;
}
// 创建自定义 Store
export const useCounterStore = defineStore('counter', {
state: (): CounterState => ({
count: 0,
lastUpdated: Date.now(),
}),
getters: {
doubleCount(): number {
return this.count * 2;
},
},
actions: {
increment() {
this.count++;
this.lastUpdated = Date.now();
},
decrement() {
this.count--;
this.lastUpdated = Date.now();
},
reset() {
this.count = 0;
this.lastUpdated = Date.now();
},
},
});持久化状态
可以使用 pinia-plugin-persistedstate 插件来持久化状态。
import { defineStore } from '@cimom/vben-stores';
export const useSettingsStore = defineStore('settings', {
state: () => ({
theme: 'light',
fontSize: 'medium',
showSidebar: true,
}),
actions: {
setTheme(theme: 'light' | 'dark') {
this.theme = theme;
},
setFontSize(size: 'small' | 'medium' | 'large') {
this.fontSize = size;
},
toggleSidebar() {
this.showSidebar = !this.showSidebar;
},
},
// 持久化配置
persist: {
key: 'app-settings',
storage: localStorage,
paths: ['theme', 'fontSize', 'showSidebar'],
},
});订阅状态变化
import { useUserStore } from '@cimom/vben-stores';
import { storeToRefs } from '@cimom/vben-stores';
import { watch } from 'vue';
const userStore = useUserStore();
const { userInfo } = storeToRefs(userStore);
// 监听用户信息变化
watch(
userInfo,
(newValue, oldValue) => {
console.log('用户信息变化:', newValue, oldValue);
},
{ deep: true },
);
// 使用 $subscribe 方法
userStore.$subscribe((mutation, state) => {
console.log('状态变化:', mutation, state);
// 可以在这里执行额外的操作,如保存到本地存储
});示例
权限控制组件
<template>
<div>
<!-- 根据权限显示按钮 -->
<button v-if="hasPermission('user:create')">创建用户</button>
<!-- 使用指令控制权限 -->
<button v-permission="'user:edit'">编辑用户</button>
<!-- 根据角色显示内容 -->
<div v-if="hasRole('admin')">仅管理员可见内容</div>
</div>
</template>
<script setup lang="ts">
import { useAccessStore } from '@cimom/vben-stores';
const accessStore = useAccessStore();
const { hasPermission, hasRole } = accessStore;
</script>标签页组件
<template>
<div class="tabs-container">
<!-- 标签页列表 -->
<div class="tabs">
<div
v-for="tab in tabs"
:key="tab.path"
:class="['tab', { active: activeTab === tab.path }]"
@click="setActiveTab(tab.path)"
>
<span>{{ tab.title }}</span>
<button
v-if="tab.closable"
class="close-btn"
@click.stop="closeTab(tab.path)"
>
×
</button>
</div>
</div>
<!-- 标签页操作 -->
<div class="tab-actions">
<button @click="refreshTab()">刷新</button>
<button @click="closeOtherTabs(activeTab)">关闭其他</button>
<button @click="closeAllTabs()">关闭所有</button>
</div>
</div>
</template>
<script setup lang="ts">
import { useTabbarStore } from '@cimom/vben-stores';
import { storeToRefs } from '@cimom/vben-stores';
const tabbarStore = useTabbarStore();
const { tabs, activeTab } = storeToRefs(tabbarStore);
const { setActiveTab, closeTab, closeOtherTabs, closeAllTabs, refreshTab } =
tabbarStore;
</script>
<style scoped>
.tabs-container {
display: flex;
align-items: center;
border-bottom: 1px solid #eee;
padding: 0 16px;
height: 40px;
}
.tabs {
display: flex;
flex: 1;
overflow-x: auto;
}
.tab {
display: flex;
align-items: center;
padding: 0 16px;
height: 100%;
cursor: pointer;
border-right: 1px solid #eee;
white-space: nowrap;
}
.tab.active {
background-color: #f0f0f0;
}
.close-btn {
margin-left: 8px;
width: 16px;
height: 16px;
border: none;
background: none;
cursor: pointer;
font-size: 14px;
line-height: 1;
border-radius: 50%;
}
.close-btn:hover {
background-color: #ddd;
}
.tab-actions {
display: flex;
gap: 8px;
margin-left: 16px;
}
.tab-actions button {
padding: 4px 8px;
border: 1px solid #ddd;
background: white;
border-radius: 4px;
cursor: pointer;
}
.tab-actions button:hover {
background-color: #f0f0f0;
}
</style>用户信息组件
<template>
<div v-if="userInfo.id" class="user-info">
<div class="avatar">
<img :src="userInfo.avatar" :alt="userInfo.realName" />
</div>
<div class="info">
<div class="name">{{ userInfo.realName }}</div>
<div class="username">@{{ userInfo.username }}</div>
</div>
<button @click="logout" class="logout-btn">退出登录</button>
</div>
<div v-else class="login-prompt">请先登录</div>
</template>
<script setup lang="ts">
import { useUserStore } from '@cimom/vben-stores';
import { storeToRefs } from '@cimom/vben-stores';
const userStore = useUserStore();
const { userInfo } = storeToRefs(userStore);
function logout() {
userStore.resetUserInfo();
// 其他登出逻辑...
}
</script>
<style scoped>
.user-info {
display: flex;
align-items: center;
padding: 12px;
border: 1px solid #eee;
border-radius: 8px;
}
.avatar {
width: 40px;
height: 40px;
border-radius: 50%;
overflow: hidden;
margin-right: 12px;
}
.avatar img {
width: 100%;
height: 100%;
object-fit: cover;
}
.info {
flex: 1;
}
.name {
font-weight: bold;
}
.username {
font-size: 12px;
color: #666;
}
.logout-btn {
padding: 4px 8px;
border: 1px solid #ddd;
background: white;
border-radius: 4px;
cursor: pointer;
}
.login-prompt {
padding: 12px;
text-align: center;
border: 1px solid #eee;
border-radius: 8px;
color: #999;
}
</style>5.6.10
6 months ago
5.6.9
6 months ago
5.6.8
6 months ago
5.6.7
6 months ago
5.6.6
6 months ago
5.6.5
6 months ago
5.6.4
6 months ago
5.6.3
6 months ago
5.6.2
6 months ago
5.6.1
6 months ago
5.6.0
6 months ago
5.5.21
6 months ago
5.5.20
6 months ago
5.5.18
6 months ago
5.5.17
6 months ago
5.5.16
6 months ago
5.5.15
6 months ago
5.5.14
6 months ago
5.5.13
6 months ago
5.5.12
6 months ago
5.5.11
6 months ago
5.5.10
6 months ago
5.5.9
6 months ago