登录与品类

This commit is contained in:
孙景学
2025-08-04 16:06:23 +08:00
parent ad4efd8e46
commit b5cb08deb5
29 changed files with 665 additions and 270 deletions

192
src/models/tab.ts Normal file
View File

@ -0,0 +1,192 @@
import { Effect, Reducer, Subscription } from 'umi';
import { history } from 'umi';
import routes from '../../config/router.config';
export interface TabItem {
tab: string;
key: string;
path: string;
closable: boolean;
}
export interface TabModelState {
tabList: TabItem[];
activeKey: string;
}
export interface TabModelType {
namespace: 'tab';
state: TabModelState;
effects: {
addTab: Effect;
closeTab: Effect;
switchTab: Effect;
};
reducers: {
updateState: Reducer<TabModelState>;
};
subscriptions: {
setup: Subscription;
};
}
// 递归查找路由
const findRouteByPath = (path: string, routeData: any[]): any => {
let result = null;
for (const route of routeData) {
if (route.path === path) {
result = route;
break;
}
if (route.routes) {
const subResult = findRouteByPath(path, route.routes);
if (subResult) {
result = subResult;
break;
}
}
}
return result;
};
const TabModel: TabModelType = {
namespace: 'tab',
state: {
tabList: [],
activeKey: '/',
},
effects: {
*addTab({ payload }, { call, put, select }) {
const { tabList } = yield select((state: any) => state.tab);
const { path, tab, key } = payload;
// 检查tab是否已存在
const isExist = tabList.find((item: TabItem) => item.key === key);
if (!isExist) {
// 添加新tab
yield put({
type: 'updateState',
payload: {
tabList: [...tabList, { tab, key, path, closable: true }],
activeKey: key,
},
});
} else {
// 切换到已有tab
yield put({
type: 'updateState',
payload: {
activeKey: key,
},
});
}
},
*closeTab({ payload }, { call, put, select }) {
const { key } = payload;
const { tabList, activeKey } = yield select((state: any) => state.tab);
// 过滤掉要关闭的tab
const newTabList = tabList.filter((item: TabItem) => item.key !== key);
// 如果关闭的是当前激活的tab则切换到前一个tab
let newActiveKey = activeKey;
if (key === activeKey) {
const index = tabList.findIndex((item: TabItem) => item.key === key);
// 判断关闭后是否还有tab
if (newTabList.length === 0) {
// 没有剩余tab时导航到首页
history.push('/');
newActiveKey = '/';
} else {
// 有剩余tab时选择适当的tab作为活动tab
newActiveKey = index === 0 ? newTabList[0].key : tabList[index - 1].key;
// 切换路由
const targetTab = newTabList.find((item: TabItem) => item.key === newActiveKey);
if (targetTab) {
history.push(targetTab.path);
}
}
}
yield put({
type: 'updateState',
payload: {
tabList: newTabList,
activeKey: newActiveKey,
},
});
},
*switchTab({ payload }, { call, put, select }) {
const { key } = payload;
const { tabList } = yield select((state: any) => state.tab);
// 找到目标tab并跳转
const targetTab = tabList.find((item: TabItem) => item.key === key);
if (targetTab) {
history.push(targetTab.path);
}
yield put({
type: 'updateState',
payload: {
activeKey: key,
},
});
}
},
reducers: {
updateState(state, { payload }) {
return {
...state,
...payload,
};
},
},
subscriptions: {
setup({ dispatch }) {
return history.listen((location) => {
const { pathname } = location;
// 需要排除的路由
const excludeRoutes = ['/login', '/register'];
// 首页特殊处理
if (pathname === '/') {
dispatch({
type: 'updateState',
payload: {
activeKey: '/',
},
});
return;
}
// 查找当前路由对应的菜单项
const currentRoute = findRouteByPath(pathname, routes);
if (currentRoute && !excludeRoutes.includes(pathname)) {
// 如果找到对应路由添加或激活对应的tab
dispatch({
type: 'addTab',
payload: {
path: pathname,
key: pathname,
// 直接使用菜单名称作为国际化ID
tab: currentRoute.name || '未命名页面',
},
});
}
});
},
},
};
export default TabModel;

View File

@ -1,35 +1,39 @@
import type { Effect, Reducer } from 'umi';
import { queryCurrent, query as queryUsers } from '@/servers/user';
import { getUserinfo, Logout } from '@/servers/api/login';
export type CurrentUser = {
avatar?: string;
name?: string;
title?: string;
group?: string;
signature?: string;
tags?: {
key: string;
label: string;
}[];
userid?: string;
unreadCount?: number;
export type User = {
userId: string;
userName: string;
userType: string;
};
export type UserInfo = {
userId: string;
fullName: string;
loginName: string;
userType: string;
authorityList: { roleId: string, roleName: string, roleCode: string, roleScope: string }[];
};
export type UserModelState = {
currentUser?: CurrentUser;
user?: User;
token?: string;
userInfo?: UserInfo;
};
export type UserModelType = {
namespace: 'user';
state: UserModelState;
effects: {
fetch: Effect;
fetchCurrent: Effect;
fetchUserInfo: Effect;
logout: Effect;
};
reducers: {
saveCurrentUser: Reducer<UserModelState>;
changeNotifyCount: Reducer<UserModelState>;
saveLoginUser: Reducer<UserModelState>;
saveUserInfo: Reducer<UserModelState>;
clearUserInfo: Reducer;
};
};
@ -37,49 +41,53 @@ const UserModel: UserModelType = {
namespace: 'user',
state: {
currentUser: {},
user: undefined, // 登录返回的用户信息
token: sessionStorage.getItem('token') || '', // 登录返回的token
userInfo: undefined, // 请求userInfo返回的用户信息
},
effects: {
*fetch(_, { call, put }) {
const response = yield call(queryUsers);
*fetchUserInfo(_, { call, put }): Generator<any, void, any> {
const userinfo = JSON.parse(sessionStorage.getItem('Userinfo') ?? '{}');
console.log(userinfo,'userinfo');
yield put({
type: 'save',
payload: response,
type: 'saveUserInfo',
payload: userinfo,
});
},
*fetchCurrent(_, { call, put }) {
const response = yield call(queryCurrent);
*logout(_, { call, put }): Generator<any, void, any> {
yield call(Logout);
yield put({
type: 'saveCurrentUser',
payload: response,
type: 'clearUserInfo'
});
},
},
reducers: {
saveCurrentUser(state, action) {
clearUserInfo(state) {
return {
...state,
currentUser: action.payload || {},
userInfo: undefined,
token: '',
user: {},
};
},
changeNotifyCount(
state = {
currentUser: {},
},
action,
) {
saveLoginUser(state, action) {
return {
...state,
currentUser: {
...state.currentUser,
notifyCount: action.payload.totalCount,
unreadCount: action.payload.unreadCount,
},
user: action.payload.user || {},
token: action.payload.token || '',
};
},
},
saveUserInfo(state, action) {
return {
...state,
userInfo: action.payload || {},
};
},
}
};
export default UserModel;