5.6.10 • Published 10 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
10 months ago
5.6.9
10 months ago
5.6.8
10 months ago
5.6.7
10 months ago
5.6.6
10 months ago
5.6.5
10 months ago
5.6.4
10 months ago
5.6.3
10 months ago
5.6.2
10 months ago
5.6.1
10 months ago
5.6.0
10 months ago
5.5.21
10 months ago
5.5.20
10 months ago
5.5.18
10 months ago
5.5.17
10 months ago
5.5.16
10 months ago
5.5.15
10 months ago
5.5.14
10 months ago
5.5.13
10 months ago
5.5.12
10 months ago
5.5.11
10 months ago
5.5.10
10 months ago
5.5.9
10 months ago