本项目是基于ant-design开发的一个前端项目,项目的上线地址:http://user-front.66bond.com/

本项目的开发软件:

  • webstorm2021:关注公众号”青椒工具”,发送”webstorm”获取安装包下载链接;

今天的主要任务是在登录页增加”注册”链接,然后登录后直接进入到Welcome页面。

1、登录页增加注册链接

我们在登录页增加一个注册链接,位于”登录”按钮和”自动登录”checkBox之间。增加的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
       <ProFormCheckbox noStyle name="autoLogin">
自动登录
</ProFormCheckbox>
/**
** 增加新用户注册链接。
**/
<Link href='/user/register'>新用户注册</Link>

<a
style={{
float: 'right',
}}
href="https://www.baidu.com"
target="_blank"
>
忘记密码 ?
</a>

保存刷新后,界面如下:

图4.6登录页添加注册链接-裁剪

图1 登录页增加注册链接

点击后,可以正常打开注册页。

2、 修改当前用户接口

在app.tsx中的方法getInitialState()中的queryCurrentUser()方法要修改,

1
2
3
4
5
6
7
8
9
10
/** 获取当前的用户 GET /api/user/current */
export async function currentUser(options?: { [key: string]: any }) {
return request<{
data: API.CurrentUser;
// }>('/api/currentUser', {
}>('/api/user/current', {
method: 'GET',
...(options || {}),
});
}

根据后台接口,将/api/currentUser修改为”/api/user/current”,其中的API.CurrentUser根据后台用户的数据修改如下:

1
2
3
4
5
6
7
8
9
10
11
12
type CurrentUser = {
id:number;
username:string;
userAccount: string;
avatarUrl:string;
gender:number;
phone:string;
email:string;
userStatus: number;
userRole: number;
createTime: Date;
};

另外,app.tsx中其他的逻辑及修改:

fetchUserInfo方法的内容是获取当前用户信息,如果出错,则返回到login页面;

1
2
3
4
5
6
7
8
9
const fetchUserInfo = async () => {
try {
const user = await queryCurrentUser();
return user;
} catch (error) {
history.push(loginPath);
}
return undefined;
};

定义网页访问白名单whiteList,如果当前访问路径是login或者register,则直接返回;

如果当前不是login或者register,则首先尝试获取当前用户信息(调用fetchUserInfo()),并返回;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const whiteList = ['/user/register', loginPath];
// 如果不是登录页面或者注册页面,执行
// if (history.location.pathname !== loginPath) {
if(whiteList.includes(history.location.pathname)){
return {
fetchUserInfo,
settings: defaultSettings,
};
}
const currentUser = await fetchUserInfo();
return {
fetchUserInfo,
currentUser,
settings: defaultSettings,
};

上述的currentUser会出现类型错误,修改api.ts中的currentUser方法的返回类型即可:

1
2
3
4
5
6
7
/** 获取当前的用户 GET /api/user/current */
export async function currentUser(options?: { [key: string]: any }) {
return request<API.CurrentUser>('/api/user/current', {
method: 'GET',
...(options || {}),
});
}

另外app.tsx中还要设置水印语句:

1
2
3
waterMarkProps: {
content: initialState?.currentUser?.name,
},

要把上述的name变量值,修改为我们的变量userAccount,即水印显示userAccount字符串:

1
2
3
waterMarkProps: {
content: initialState?.currentUser?.userAccount,
},

完成上述修改后,我们保存打开登录页,输入账号yupi,可以正常跳转到Welcome页面,如图2所示。

图5.2登录到Welcome页

图2 登录后跳转到Welcome页

图2中的主要问题,右上角的avatar没有正常显示,原因是我们的数据库中没有设置,当数据库中完成设置,发现avatar还是不能正常显示,通过全局搜索avatar关键词,找到如下的相关代码:

1
2
3
4
5
6
<HeaderDropdown overlay={menuHeaderDropdown}>
<span className={`${styles.action} ${styles.account}`}>
<Avatar size="small" className={styles.avatar} src={currentUser.avatar} alt="avatar" />
<span className={`${styles.name} anticon`}>{currentUser.name}</span>
</span>
</HeaderDropdown>

上述代码中,currentUser.avatar变量与我们设置的avatarUrl不符,所以修改下,具体代码如下:

这里我出了个低级错误:数据库中的avatarUrl,我写成了avatarUlr,这里就不分散精力去修改后台数据和代码了,将错就错了。

1
2
3
4
5
6
<HeaderDropdown overlay={menuHeaderDropdown}>
<span className={`${styles.action} ${styles.account}`}>
<Avatar size="small" className={styles.avatar} src={currentUser.avatarUrl} alt="avatarUrl" />
<span className={`${styles.name} anticon`}>{currentUser.userAccount}</span>
</span>
</HeaderDropdown>

保存刷新,可以发现页面可以正常显示用户名和头像:

图5.3头像正常显示

图3 头像显示正常

鼠标移动右上角的头像,会弹出”退出登录”的下拉选项,点击后前端和后端都要退出,先看下前端代码:

1
2
3
4
5
6
7
8
9
10
11
12
const onMenuClick = useCallback(
(event: MenuInfo) => {
const { key } = event;
if (key === 'logout') {
setInitialState((s) => ({ ...s, currentUser: undefined }));
loginOut();
return;
}
history.push(`/account/${key}`);
},
[setInitialState],
);

前端根据key是否等于logout,将currentUser设置为空;然后再调用loginOut方法:

1
2
3
4
5
6
7
/** 退出登录接口 POST /api/login/outLogin */
export async function outLogin(options?: { [key: string]: any }) {
return request<Record<string, any>>('/api/login/outLogin', {
method: 'POST',
...(options || {}),
});
}

outLogin方法,需要我们根据自己的后端来调整和修改:

1
2
3
4
5
6
7
/** 退出登录接口 POST /api/user/logout */
export async function outLogin(options?: { [key: string]: any }) {
return request<Record<string, any>>('/api/user/logout', {
method: 'POST',
...(options || {}),
});
}

经过上述修改,前端可以顺利退出转到登录页,后端的logout接口也被正常访问。

3、参考资料:

本文参考自如下知识星球中的视频教程,更多的完整的相关视频教程,见如下的收费知识星球,近3万人的学习社区,

编程有人同行,学习不再迷茫

编程导航知识星球