欢迎光临
我们一直在努力

小白学前端--第六天(2026/2/7)智慧商城项目-1 (登录界面搭建)

呜呜,应该早一点测试好了QAQ

经历了上一次项目后端接口挂了的经验,这回我选取了一个之前我用vue做过的项目后端接口

接口文档链接如下:wiki – 智慧商城-实战项目

好,那让我们开始今天的搭建吧!

智慧商城项目

零、修改准备

昨天的工作没有白费哦,只需稍作修改就可以适配啦。

首先我们来调整一下request的接口基地址:

//axios

import axios from "axios";

const request= axios.create({
baseURL:'http://smart-shop.itheima.net/index.php?s=/api',//需填写
timeout:5000
})

request.interceptors.request.use((config)=>{
return config
},(error)=>{
return Promise.reject(error)
})
request.interceptors.response.use((response)=>{
return response.data
},(error)=>{
return Promise.reject(error)
})

export {request}

然后查看文档可知,要发的信息长这个样子

要配置一个header,里面要有platform,所以我们继续添加一个请求头

//axios

import axios from "axios";

const request= axios.create({
baseURL:'http://smart-shop.itheima.net/index.php?s=/api',//需填写
timeout:5000
})

request.interceptors.request.use((config)=>{

// 必传 platform
config.headers = config.headers || {};
config.headers.platform = config.headers.platform || "H5";

return config
},(error)=>{
return Promise.reject(error)
})
request.interceptors.response.use((response)=>{
return response.data
},(error)=>{
return Promise.reject(error)
})

export {request}

token的话加后面再加

一、登录界面(续)

没看前面的建议补一下前面的准备阶段哦~

小白学前端–第五天(2026/2/6)电商后台管理-1 (登录页面)-CSDN博客

1.业务逻辑实现(续)

通过观察请求body里面的格式我们可以发现,请求要传一个对象form,里面必须要有四个字段:smsCode,mobile,isParty和partyData 所以我们小小的改动一下Login表单里的字段名称

{
"form": {
"smsCode": "609649",
"mobile": "18917286702",
"isParty": false,
"partyData": {}
}
}

将username和password的name改成mobile字段和smsCode字段,然后再onFinish函数中传过去form,Login的index.js如下:

import React from "react";
import { Form, Input, Button, Typography, Space, Checkbox, Divider } from "antd";
import { UserOutlined, LockOutlined } from "@ant-design/icons";
import "./index.scss";
import bg from "@/assets/Login/login-bg.png";
import { fetchLogin } from "@/store/modules/user";
import { useDispatch } from "react-redux";

const { Title, Text, Link } = Typography;

const Login = () => {
const dispatch =useDispatch()

const onFinish = (value) => {
//异步触发action dispatch

const data={

form: {
…value,
isParty: false,
partyData: {},
},
}

dispatch(fetchLogin(data))

}

return (
<div className="login-page">
{/* 背景图层 */}
<div className="login-bg" style={{ backgroundImage: `url(${bg})` }} />
{/* 整体背景虚化层(只糊背景,不糊内容) */}
<div className="login-blur" />
{/* 轻微遮罩层(更有层次) */}
<div className="login-mask" />

{/* 内容层 */}
<div className="login-wrapper">
{/* 左侧宣传 */}
<div className="left-box">
<Title level={2} className="brand-title">
Smart Mall Admin
</Title>

<Text className="brand-subtitle">
智慧商城管理系统 · 高效运营 · 数据驱动
</Text>

<div className="brand-points">
<div>✔ 商品全生命周期管理</div>
<div>✔ 实时订单与库存监控</div>
<div>✔ 精准数据分析与运营决策</div>
</div>
</div>

{/* 右侧登录 */}
<div className="right-box">
<Title level={4} className="login-title">
您好!欢迎登录智慧商城
</Title>

<Form layout="vertical" onFinish={onFinish}>
<Form.Item label="用户名"
name="mobile"
rules={[{ required: true, message: "请输入用户名" }]
}
>
<Input prefix={<UserOutlined />} placeholder="请输入用户名" />
</Form.Item>

<Form.Item label="密码"
name="smsCode"
rules={[{ required: true, message: "请输入密码" }]}>
<Input.Password prefix={<LockOutlined />} placeholder="请输入密码" />
</Form.Item>

<div className="extra">
<Space>
<Checkbox>记住我</Checkbox>
</Space>
<Link>忘记密码?</Link>
</div>

<Button type="primary" block className="login-btn" htmlType="submit">
登录
</Button>

<Divider plain>其他</Divider>

<div className="login-footer">
<Text type="secondary">
没有账号? <Link>去注册</Link>
</Text>
</div>
</Form>
</div>
</div>
</div>
);
};

export default Login;

(顺便改动了一些样式)

让我们再运行一下结果:

这边看到返回200登录成功啦!大家也可以试试自己的登录信息,用户名随便,密码是246810即可哦~

那么接下来就是把我们拿到的token本地化存储,并进行小小的优化啦~

2.优化处理

首先,我们现在utils里面创建一个token.js文件专门管理token有关的操作

之后进行本地化存储

const TOKEN_KEY = "my_smartshop_token";

export const getToken = () => localStorage.getItem(TOKEN_KEY) || "";
export const setToken = (token) => localStorage.setItem(TOKEN_KEY, token);
export const removeToken = () => localStorage.removeItem(TOKEN_KEY);

token_key是标识符,大家可以用下划线命名法命名,不过不要过于简单,容易跟其他程序的Token_key叫一个名就不好了。

然后再request.js里面的请求拦截器里面配置一下请求头,有token再携带token,因为像购物

const token = getToken();
if (token) {
config.headers["Access-Token"] = token;
}

接下来在user.js里面的 fetchLogin加入setToken,已有的token可以暂时不用先注释掉,加上message组件做一个提示,更好的显示登录状态是否成功

user.js如下:

import { createSlice } from "@reduxjs/toolkit";

import { loginAPI } from "@/apis/user";
import { setToken } from "@/utils/token";
import { message } from "antd";

const userStore = createSlice({
name: "user", //

//将这个模块里面的变量放在initialState里面
initialState: {
// token:'',
},
//reducer负责同步修改方法,注意必须是同步哦
reducers: {
// setToken(state,payload)//payload 是专门用于传递「要更新的 token
// // 数据 / 信息」的参数,是状态更新时的数据载体。
// {
// state.token=payload
// }
}

})

const userReducer = userStore.reducer//导出reducer

// const {setToken} = userStore.actions//导出action

const fetchLogin = (loginForm) => {
return async (dispatch) => {
const res = await loginAPI(loginForm)
setToken(res.data.token)
if (res.status === 200) {
setToken(res.data.token);

message.success("登录成功");

return true; // 登录成功,返回 true
}

else {
message.error("登录失败,请检查用户名和密码");

return false; // 登录失败,返回 false
}
}
}

export { setToken, fetchLogin }

export default userReducer

通过true和false返回值决定是否跳转。

在完善onFinish的时候有个要点要注意,因为dispatch是异步更新,所以必须要等到函数执行完才能进行判断是否登录成功。所以要用到async和await机制。

onFinish函数更新如下:

const onFinish = async (value) => {
//异步触发action dispatch

const data={

form: {
…value,
isParty: false,
partyData: {},
},
}

const res = await dispatch(fetchLogin(data))

if (res) {
// 登录成功,执行后续操作,例如跳转到主页
navigate("/");
} else {
// 登录失败

}
}

最后我们跑一下,检验一下是否能够成功跳转以及拿到本地的Token

打开F12的应用程序可以看到token已经拿到了,不会随着刷新而消失了

想了想还是把token字段存在user.js里面吧,重命名一下防止setToken冲突。

import { createSlice } from "@reduxjs/toolkit";

import { loginAPI } from "@/apis/user";
import { setToken as setTokenLocal } from "@/utils/token";
import { message } from "antd";

const userStore = createSlice({
name: "user", //

//将这个模块里面的变量放在initialState里面
initialState: {
token: '',
},
//reducer负责同步修改方法,注意必须是同步哦
reducers: {
setToken(state, payload)//payload 是专门用于传递「要更新的 token
// 数据 / 信息」的参数,是状态更新时的数据载体。
{
state.token = payload
}
}

})

const userReducer = userStore.reducer//导出reducer

const { setToken } = userStore.actions//导出action

const fetchLogin = (loginForm) => {
return async (dispatch) => {
const res = await loginAPI(loginForm)
setToken(res.data.token)
if (res.status === 200) {
setToken(res.data.token);
setTokenLocal(res.data.token); // 将 token 存储到 localStorage
message.success("登录成功");

return true; // 登录成功,返回 true
}

else {
message.error("登录失败,请检查用户名和密码");

return false; // 登录失败,返回 false
}
}
}

export { setToken, fetchLogin }

export default userReducer

可以看到刷新之后redux里面也会有token,说明我们配置本地token已经成功了!

最后检查一下失败情况(输入非246810密码即可),也可以正常实现。

美美提交,我会把代码提交到我的gitCode上公开,大家可以免费查看学习哦~

项目地址:https://gitcode.com/2401_86252365/react

赞(0)
未经允许不得转载:171主机测评 » 小白学前端--第六天(2026/2/7)智慧商城项目-1 (登录界面搭建)
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址