refactor: 添加角色选择
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
58df855801
commit
8e05abbd2c
|
|
@ -90,16 +90,17 @@ const teacherName = computed(() => {
|
||||||
return userInfo.nickname || '教师'
|
return userInfo.nickname || '教师'
|
||||||
})
|
})
|
||||||
|
|
||||||
const teacherSubject = computed(() => {
|
const currentRoleText = computed(() => {
|
||||||
const userInfo = userStore.info
|
const role = userStore.selectedRole
|
||||||
// 从角色信息中获取学科,假设角色名包含学科信息
|
if (!role)
|
||||||
const roleName = userInfo.roles?.[0]?.name
|
return '暂无角色'
|
||||||
if (roleName) {
|
const parts = [
|
||||||
// 提取学科信息,例如"语文教师"中的"语文"
|
role.grade,
|
||||||
const subjectMatch = roleName.match(/^(.+?)教师$/)
|
role.class,
|
||||||
return subjectMatch ? subjectMatch[1] : '学科'
|
role.subject,
|
||||||
}
|
role.role,
|
||||||
return '学科'
|
].filter(Boolean)
|
||||||
|
return parts.join(' ') || '教师'
|
||||||
})
|
})
|
||||||
|
|
||||||
// 计算当前选中的班级名称
|
// 计算当前选中的班级名称
|
||||||
|
|
@ -245,13 +246,6 @@ const showClassPicker = ref(false)
|
||||||
|
|
||||||
// 班级选择处理
|
// 班级选择处理
|
||||||
function handleClassChange() {
|
function handleClassChange() {
|
||||||
if (homeStore.classOptions.length === 0) {
|
|
||||||
uni.showToast({
|
|
||||||
title: '暂无班级数据',
|
|
||||||
icon: 'none',
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
showClassPicker.value = true
|
showClassPicker.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -259,8 +253,6 @@ function handleClassChange() {
|
||||||
watch(() => homeStore.selectedClassKey, () => {
|
watch(() => homeStore.selectedClassKey, () => {
|
||||||
// 选择班级后重新获取统计数据
|
// 选择班级后重新获取统计数据
|
||||||
fetchExamStats()
|
fetchExamStats()
|
||||||
// 关闭弹窗
|
|
||||||
showClassPicker.value = false
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// 设置按钮处理
|
// 设置按钮处理
|
||||||
|
|
@ -400,7 +392,7 @@ onMounted(async () => {
|
||||||
</view>
|
</view>
|
||||||
<view class="flex flex-col">
|
<view class="flex flex-col">
|
||||||
<text class="text-base text-white font-bold">{{ teacherName }}</text>
|
<text class="text-base text-white font-bold">{{ teacherName }}</text>
|
||||||
<text class="text-xs text-blue-100 opacity-80">{{ teacherSubject }}教师</text>
|
<text class="text-xs text-blue-100 opacity-80">{{ currentRoleText }}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
|
@ -625,26 +617,54 @@ onMounted(async () => {
|
||||||
|
|
||||||
<wd-popup v-model="showClassPicker" position="bottom" custom-class="rounded-t-3xl" :z-index="100">
|
<wd-popup v-model="showClassPicker" position="bottom" custom-class="rounded-t-3xl" :z-index="100">
|
||||||
<view class="bg-white pb-safe">
|
<view class="bg-white pb-safe">
|
||||||
<view class="border-b border-slate-100 p-4 text-center">
|
<!-- 班级列表 -->
|
||||||
<text class="text-lg text-slate-800 font-bold">切换班级</text>
|
<view class="border-b border-slate-100 p-4">
|
||||||
</view>
|
<text class="mb-2 block text-sm text-slate-600 font-bold">切换班级</text>
|
||||||
<scroll-view scroll-y class="box-border max-h-80 p-4">
|
<scroll-view scroll-y class="box-border max-h-40">
|
||||||
<view class="space-y-2">
|
<view v-if="homeStore.classOptions.length > 0" class="space-y-1">
|
||||||
<view
|
<view
|
||||||
v-for="classItem in homeStore.classOptions"
|
v-for="classItem in homeStore.classOptions"
|
||||||
:key="classItem.value"
|
:key="classItem.value"
|
||||||
class="flex items-center justify-between rounded-xl p-4 transition-colors"
|
class="flex items-center justify-between rounded-lg px-3 py-2 transition-colors"
|
||||||
:class="homeStore.selectedClassId === classItem.value ? 'bg-blue-50 border border-blue-100' : 'bg-slate-50'"
|
:class="homeStore.selectedClassId === classItem.value ? 'bg-blue-50 text-blue-600' : 'hover:bg-slate-50 text-slate-600'"
|
||||||
@tap="homeStore.selectedClassId = classItem.value;showClassPicker = false"
|
@tap="homeStore.selectedClassId = classItem.value;showClassPicker = false"
|
||||||
>
|
>
|
||||||
<text class="text-base" :class="homeStore.selectedClassId === classItem.value ? 'text-blue-600 font-bold' : 'text-slate-700'">{{ classItem.label }}</text>
|
<text class="text-sm font-medium">{{ classItem.label }}</text>
|
||||||
<view
|
<view
|
||||||
v-if="homeStore.selectedClassId === classItem.value"
|
v-if="homeStore.selectedClassId === classItem.value"
|
||||||
class="i-mingcute:check-circle-fill text-xl text-blue-500"
|
class="i-mingcute:check-line text-lg"
|
||||||
/>
|
/>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
<view v-else class="py-4 text-center text-sm text-slate-400">
|
||||||
|
当前角色无可选班级
|
||||||
|
</view>
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 角色选择区域 -->
|
||||||
|
<view v-if="userStore.teacherInfo?.role_class_list && userStore.teacherInfo.role_class_list.length > 0" class="border-b border-slate-100 p-4">
|
||||||
|
<text class="mb-2 block text-sm text-slate-600 font-bold">切换角色</text>
|
||||||
|
<scroll-view scroll-y class="max-h-40">
|
||||||
|
<view class="space-y-1">
|
||||||
|
<view
|
||||||
|
v-for="(roleItem, index) in userStore.teacherInfo.role_class_list"
|
||||||
|
:key="index"
|
||||||
|
class="flex items-center justify-between rounded-lg px-3 py-2 transition-colors"
|
||||||
|
:class="userStore.selectedRole === roleItem ? 'bg-blue-50 text-blue-600' : 'hover:bg-slate-50 text-slate-600'"
|
||||||
|
@tap="userStore.setSelectedRole(roleItem)"
|
||||||
|
>
|
||||||
|
<view class="flex items-center gap-2 text-sm">
|
||||||
|
<text class="font-medium">{{ roleItem.grade }}{{ roleItem.class }}</text>
|
||||||
|
<text>{{ roleItem.subject }}</text>
|
||||||
|
<text>{{ roleItem.role }}</text>
|
||||||
|
</view>
|
||||||
|
<view v-if="userStore.selectedRole === roleItem" class="i-mingcute:check-line text-lg" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
</view>
|
||||||
|
|
||||||
<view class="p-4">
|
<view class="p-4">
|
||||||
<wd-button block type="default" size="large" custom-class="!rounded-xl !bg-slate-100 !text-slate-600 !border-none" @click="showClassPicker = false">
|
<wd-button block type="default" size="large" custom-class="!rounded-xl !bg-slate-100 !text-slate-600 !border-none" @click="showClassPicker = false">
|
||||||
关闭
|
关闭
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
import type { ModelTeacherAnalysisClassInfo, ModelTeacherAnalysisExamInfo } from '@/api/data-contracts'
|
import type { ModelTeacherAnalysisExamInfo } from '@/api/data-contracts'
|
||||||
import { whenever } from '@vueuse/core'
|
import { whenever } from '@vueuse/core'
|
||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
import { computed, ref } from 'vue'
|
import { computed, onMounted, ref } from 'vue'
|
||||||
import { teacherScoreAnalysisApi } from '@/api'
|
import { teacherScoreAnalysisApi } from '@/api'
|
||||||
import { useUserStorage } from '@/composables/useUserStorage'
|
import { useUserStorage } from '@/composables/useUserStorage'
|
||||||
|
import { useUserStore } from '@/store/user'
|
||||||
|
|
||||||
export interface SelectOption {
|
export interface SelectOption {
|
||||||
label: string
|
label: string
|
||||||
|
|
@ -14,23 +15,18 @@ export interface SelectOption {
|
||||||
gradeKey?: number
|
gradeKey?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
// 班级信息类型
|
|
||||||
export interface ClassItem {
|
|
||||||
label: string
|
|
||||||
value: number
|
|
||||||
gradeKey: number
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 首页状态管理
|
* 首页状态管理
|
||||||
*/
|
*/
|
||||||
export const useHomeStore = defineStore(
|
export const useHomeStore = defineStore(
|
||||||
'homeStore',
|
'homeStore',
|
||||||
() => {
|
() => {
|
||||||
|
// 获取 userStore
|
||||||
|
const userStore = useUserStore()
|
||||||
|
|
||||||
// 数据存储
|
// 数据存储
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const examDataMap = ref<Map<number, ModelTeacherAnalysisExamInfo>>(new Map())
|
const examDataMap = ref<Map<number, ModelTeacherAnalysisExamInfo>>(new Map())
|
||||||
const classList = ref<ClassItem[]>([])
|
|
||||||
|
|
||||||
// 已选择的数据(使用 useUserStorage 实现基于用户的持久化)
|
// 已选择的数据(使用 useUserStorage 实现基于用户的持久化)
|
||||||
const selectedClassId = useUserStorage<number>('home_selectedClassId', 0)
|
const selectedClassId = useUserStorage<number>('home_selectedClassId', 0)
|
||||||
|
|
@ -46,14 +42,53 @@ export const useHomeStore = defineStore(
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
|
|
||||||
// 计算属性:班级选项
|
// 计算属性:班级选项(带角色权限筛选)
|
||||||
const classOptions = computed((): SelectOption[] => {
|
const classOptions = computed((): SelectOption[] => {
|
||||||
return classList.value.map((item, index) => ({
|
if (!selectedExamId.value) {
|
||||||
label: item.label,
|
return []
|
||||||
|
}
|
||||||
|
const examData = examDataMap.value.get(selectedExamId.value)
|
||||||
|
if (!examData?.classes) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
const allClasses = examData.classes.map((item, index) => ({
|
||||||
|
label: `${item.grade_name || ''} ${item.class_name || ''}`.trim(),
|
||||||
value: index,
|
value: index,
|
||||||
classKey: item.value,
|
classKey: item.class_key,
|
||||||
gradeKey: item.gradeKey,
|
gradeKey: Number(item.grade_key),
|
||||||
}))
|
})) || []
|
||||||
|
|
||||||
|
// 如果没有选择角色,返回所有班级
|
||||||
|
const currentRole = userStore.selectedRole
|
||||||
|
if (!currentRole) {
|
||||||
|
return allClasses
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据角色类型筛选班级
|
||||||
|
return allClasses.filter((classItem) => {
|
||||||
|
// 1. 任课老师 (role_key: 1): 只能访问特定科目的特定班级
|
||||||
|
if (currentRole.role_key === 1) {
|
||||||
|
return currentRole.grade_key === classItem.gradeKey && currentRole.class_key === classItem.classKey
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 班主任 (role_key: 2): 可以访问管理的班级
|
||||||
|
if (currentRole.role_key === 2) {
|
||||||
|
return currentRole.grade_key === classItem.gradeKey && currentRole.class_key === classItem.classKey
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 年级主任 (role_key: 3): 可以访问对应年级的所有班级
|
||||||
|
if (currentRole.role_key === 3) {
|
||||||
|
return currentRole.grade_key === classItem.gradeKey
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 学科组长 (role_key: 4): 可以访问对应科目的所有班级(在当前角色的年级内)
|
||||||
|
if (currentRole.role_key === 4) {
|
||||||
|
// 学科组长可以看当前角色年级的所有班级
|
||||||
|
return currentRole.grade_key === classItem.gradeKey
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
const selectedClassKey = computed(() => {
|
const selectedClassKey = computed(() => {
|
||||||
|
|
@ -64,7 +99,7 @@ export const useHomeStore = defineStore(
|
||||||
return classOptions.value.find(item => item.value === selectedClassId.value)?.gradeKey || 0
|
return classOptions.value.find(item => item.value === selectedClassId.value)?.gradeKey || 0
|
||||||
})
|
})
|
||||||
|
|
||||||
// 计算属性:根据选中考试获取科目选项
|
// 计算属性:根据选中考试获取科目选项(带角色权限筛选)
|
||||||
const subjectOptions = computed((): SelectOption[] => {
|
const subjectOptions = computed((): SelectOption[] => {
|
||||||
if (!selectedExamId.value) {
|
if (!selectedExamId.value) {
|
||||||
return []
|
return []
|
||||||
|
|
@ -73,12 +108,45 @@ export const useHomeStore = defineStore(
|
||||||
if (!examData?.subjects) {
|
if (!examData?.subjects) {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
return examData.subjects.map(subject => ({
|
|
||||||
|
// 先生成所有科目选项
|
||||||
|
const allSubjects = examData.subjects.map(subject => ({
|
||||||
label: subject.subject_name || '',
|
label: subject.subject_name || '',
|
||||||
value: subject.exam_subject_id || 0,
|
value: subject.exam_subject_id || 0,
|
||||||
examSubjectId: subject.exam_subject_id || 0,
|
examSubjectId: subject.exam_subject_id || 0,
|
||||||
subjectId: subject.subject_id || 0,
|
subjectId: subject.subject_id || 0,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
// 如果没有选择角色,返回所有科目
|
||||||
|
const currentRole = userStore.selectedRole
|
||||||
|
if (!currentRole) {
|
||||||
|
return allSubjects
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据角色类型筛选科目
|
||||||
|
return allSubjects.filter((subjectItem) => {
|
||||||
|
// 1. 任课老师 (role_key: 1): 只能访问特定科目
|
||||||
|
if (currentRole.role_key === 1) {
|
||||||
|
return currentRole.subject_id === subjectItem.subjectId
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 班主任 (role_key: 2): 可以访问所有科目
|
||||||
|
if (currentRole.role_key === 2) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 年级主任 (role_key: 3): 可以访问所有科目
|
||||||
|
if (currentRole.role_key === 3) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 学科组长 (role_key: 4): 只能访问负责的科目
|
||||||
|
if (currentRole.role_key === 4) {
|
||||||
|
return currentRole.subject_id === subjectItem.subjectId
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -90,31 +158,19 @@ export const useHomeStore = defineStore(
|
||||||
const response = await teacherScoreAnalysisApi.dataList()
|
const response = await teacherScoreAnalysisApi.dataList()
|
||||||
|
|
||||||
if (response) {
|
if (response) {
|
||||||
// 处理班级数据并建立班级到年级的映射
|
|
||||||
classList.value = (response.class_list || []).map((item: ModelTeacherAnalysisClassInfo) => {
|
|
||||||
if (!item.class_key || !item.grade_key) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
const classKey = item.class_key
|
|
||||||
const gradeKey = item.grade_key
|
|
||||||
|
|
||||||
return {
|
|
||||||
label: `${item.grade || ''} ${item.class || ''}`.trim(),
|
|
||||||
value: classKey,
|
|
||||||
gradeKey,
|
|
||||||
}
|
|
||||||
}).filter(item => item !== null) as ClassItem[]
|
|
||||||
|
|
||||||
// 处理考试数据,存储到 map 中
|
// 处理考试数据,存储到 map 中
|
||||||
examDataMap.value.clear()
|
examDataMap.value.clear();
|
||||||
;(response.exam_list || []).forEach((exam: ModelTeacherAnalysisExamInfo) => {
|
(response.exam_list || []).forEach((exam: ModelTeacherAnalysisExamInfo) => {
|
||||||
if (exam.exam_id) {
|
if (exam.exam_id) {
|
||||||
examDataMap.value.set(exam.exam_id, exam)
|
examDataMap.value.set(exam.exam_id, exam)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if (!selectedExamId.value) {
|
||||||
|
selectedExamId.value = examOptions.value[0]?.value as number
|
||||||
|
}
|
||||||
|
|
||||||
console.log('数据获取完成:')
|
console.log('数据获取完成:')
|
||||||
console.log('classList数量:', classList.value.length)
|
|
||||||
console.log('examDataMap数量:', examDataMap.value.size)
|
console.log('examDataMap数量:', examDataMap.value.size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -132,9 +188,11 @@ export const useHomeStore = defineStore(
|
||||||
*/
|
*/
|
||||||
const onExamChange = (examId: number | null) => {
|
const onExamChange = (examId: number | null) => {
|
||||||
selectedExamId.value = examId
|
selectedExamId.value = examId
|
||||||
|
if (subjectOptions.value.length > 0) {
|
||||||
selectedSubjectId.value = subjectOptions.value[0].subjectId || null
|
selectedSubjectId.value = subjectOptions.value[0].subjectId || null
|
||||||
selectedExamSubjectId.value = subjectOptions.value[0].examSubjectId || null
|
selectedExamSubjectId.value = subjectOptions.value[0].examSubjectId || null
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置选项数据(兼容旧接口)
|
* 设置选项数据(兼容旧接口)
|
||||||
|
|
@ -158,7 +216,6 @@ export const useHomeStore = defineStore(
|
||||||
* 重置store状态
|
* 重置store状态
|
||||||
*/
|
*/
|
||||||
const reset = () => {
|
const reset = () => {
|
||||||
classList.value = []
|
|
||||||
examDataMap.value.clear()
|
examDataMap.value.clear()
|
||||||
loading.value = false
|
loading.value = false
|
||||||
clearSelections()
|
clearSelections()
|
||||||
|
|
@ -166,8 +223,10 @@ export const useHomeStore = defineStore(
|
||||||
|
|
||||||
// 监听考试ID变化,自动选择第一个科目
|
// 监听考试ID变化,自动选择第一个科目
|
||||||
whenever(selectedExamId, (examId) => {
|
whenever(selectedExamId, (examId) => {
|
||||||
|
if (subjectOptions.value.length > 0) {
|
||||||
selectedSubjectId.value = subjectOptions.value[0].subjectId || null
|
selectedSubjectId.value = subjectOptions.value[0].subjectId || null
|
||||||
selectedExamSubjectId.value = subjectOptions.value[0].examSubjectId || null
|
selectedExamSubjectId.value = subjectOptions.value[0].examSubjectId || null
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
import type { ModelSysUser, ModelTeacherListResponse, ModelUserProfileResponse } from '@/api'
|
import type { ModelSysUser, ModelTeacherListResponse, ModelTeacherRoleClassInfo, ModelUserProfileResponse } from '@/api'
|
||||||
import type { LoginRequest, SysUser } from '@/service/types'
|
import type { LoginRequest, SysUser } from '@/service/types'
|
||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
import { computed, ref } from 'vue'
|
import { computed, ref } from 'vue'
|
||||||
import { authApi } from '@/api'
|
import { authApi } from '@/api'
|
||||||
|
import { useUserStorage } from '@/composables/useUserStorage'
|
||||||
import {
|
import {
|
||||||
authCodeLoginUsingPost,
|
authCodeLoginUsingPost,
|
||||||
authLoginUsingPost,
|
authLoginUsingPost,
|
||||||
|
|
@ -24,6 +25,8 @@ export const useUserStore = defineStore(
|
||||||
const info = ref<Partial<ModelSysUser>>({})
|
const info = ref<Partial<ModelSysUser>>({})
|
||||||
// 教师信息
|
// 教师信息
|
||||||
const teacherInfo = ref<Partial<ModelTeacherListResponse>>({})
|
const teacherInfo = ref<Partial<ModelTeacherListResponse>>({})
|
||||||
|
// 当前选择的角色
|
||||||
|
const selectedRole = useUserStorage<ModelTeacherRoleClassInfo>('selectedRole', null)
|
||||||
// 访问令牌
|
// 访问令牌
|
||||||
const accessToken = ref('')
|
const accessToken = ref('')
|
||||||
// 刷新令牌
|
// 刷新令牌
|
||||||
|
|
@ -46,6 +49,18 @@ export const useUserStore = defineStore(
|
||||||
const setUserInfo = (newInfo: ModelUserProfileResponse) => {
|
const setUserInfo = (newInfo: ModelUserProfileResponse) => {
|
||||||
info.value = newInfo.sys_user
|
info.value = newInfo.sys_user
|
||||||
teacherInfo.value = newInfo.teacher
|
teacherInfo.value = newInfo.teacher
|
||||||
|
// 自动选择第一个角色作为默认值
|
||||||
|
if (newInfo.teacher?.role_class_list && newInfo.teacher.role_class_list.length > 0) {
|
||||||
|
selectedRole.value = newInfo.teacher.role_class_list[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置当前选择的角色
|
||||||
|
* @param role 角色信息
|
||||||
|
*/
|
||||||
|
const setSelectedRole = (role: ModelTeacherRoleClassInfo) => {
|
||||||
|
selectedRole.value = role
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -242,11 +257,14 @@ export const useUserStore = defineStore(
|
||||||
isLogin,
|
isLogin,
|
||||||
isTeacher,
|
isTeacher,
|
||||||
info,
|
info,
|
||||||
|
teacherInfo,
|
||||||
|
selectedRole,
|
||||||
accessToken,
|
accessToken,
|
||||||
refreshToken,
|
refreshToken,
|
||||||
tokenExpireTime,
|
tokenExpireTime,
|
||||||
getUserInfo,
|
getUserInfo,
|
||||||
setUserInfo,
|
setUserInfo,
|
||||||
|
setSelectedRole,
|
||||||
setLoginStatus,
|
setLoginStatus,
|
||||||
setToken,
|
setToken,
|
||||||
isTokenNearExpiry,
|
isTokenNearExpiry,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue