"app">
<
/div>
template>
样式:
页面效果如图:
用户登录页面
新建 UserLoginPage.vue,可以基于 Ant Design 的表单组件 快速开发登录页面。
先开发基础页面,可以按照需要增加一些前端校验,代码如下:
用户登录
style="max-width: 480px; margin: 0 auto"
label-align="left"
:label-col="{ span: 4 }"
:wrapper-col="{ span: 20 }"
:model="form"
@finish="handleSubmit"
>
name="userAccount"
label="账号"
:rules="[{ required: true, message: '请输入账号' }]"
>
name="userPassword"
label="密码"
:rules="[
{ required: true, message: '请输入密码' },
{ min: 8, message: '密码不少于 8 位' },
]"
>
v-model:value="form.userPassword"
placeholder="请输入密码"
/>
登录
需要定义一个响应式变量来接受表单输入的值:
/**
* 表单信息
*/
const form = reactive({
userAccount: "",
userPassword: "",
});
编写表单提交后执行的函数,登陆成功后需要在全局状态中记录当前登录用户的信息,并跳转到主页:
const router = useRouter();
const loginUserStore = useLoginUserStore();
/**
* 提交表单
* @param data
*/
const handleSubmit = async () => {
const res = await userLogin(form);
// 登录成功,跳转到主页
if (res.data.code === 0 && res.data.data) {
await loginUserStore.fetchLoginUser();
message.success("登录成功");
router.push({
path: "/",
replace: true,
});
} else {
message.error("登录失败");
}
};
页面效果如图:
用户注册页面
同样使用表单组件,在用户登录页面的基础上调整即可,涉及到更多表单项的填写:
用户注册
style="max-width: 480px; margin: 0 auto"
label-align="left"
:label-col="{ span: 4 }"
:wrapper-col="{ span: 20 }"
:model="form"
@finish="handleSubmit"
>
name="userAccount"
label="账号"
:rules="[{ required: true, message: '请输入账号' }]"
>
name="userPassword"
label="密码"
:rules="[
{ required: true, message: '请输入密码' },
{ min: 8, message: '密码不少于 8 位' },
]"
>
v-model:value="form.userPassword"
placeholder="请输入密码"
/>
name="checkPassword"
label="确认密码"
:rules="[
{ required: true, message: '请输入确认密码' },
{ min: 8, message: '确认密码不少于 8 位' },
]"
>
v-model:value="form.checkPassword"
placeholder="请输入密码"
/>
name="planetCode"
label="编号"
:rules="[{ required: true, message: '请输入编号' }]"
>
注册
定义表单信息变量:
const form = reactive({
userAccount: "",
userPassword: "",
checkPassword: "",
planetCode: "",
});
编写提交表单函数,可以增加一些前端校验,并且在注册成功后跳转到用户登录页:
const handleSubmit = async () => {
// 可以增加一些前端校验
if (form.checkPassword !== form.userPassword) {
message.error("二次输入的密码不一致");
return;
}
const res = await userRegister(form);
// 注册成功,跳转到登录页面
if (res.data.code === 0 && res.data.data) {
message.success("注册成功");
router.push({
path: "/user/login",
replace: true,
});
} else {
message.error("注册失败," + res.data.description);
}
};
页面效果如图:
用户管理页面
需求:允许管理员查看已注册的用户信息,能够根据用户名称搜索用户,并删除非法用户。
需要注意,要防止普通用户也能看到用户信息,所以要增加一定的权限控制,可以分为页面开发和权限控制两个步骤来实现。
1、页面开发
编写页面:上方搜索栏,下方表格。
1)先利用 Ant Design 的表格组件,展示全部用户信息。
只需要根据自己的数据表,编写 columns 表格列,并传入获取到的 data 数据,组件就能自动帮我们展示出表格,非常方便。
定义表格列:
const columns = [
{
title: "id",
dataIndex: "id",
},
{
title: "用户名",
dataIndex: "username",
},
{
title: "账号",
dataIndex: "userAccount",
},
{
title: "头像",
dataIndex: "avatarUrl",
},
{
title: "性别",
dataIndex: "gender",
},
{
title: "创建时间",
dataIndex: "createTime",
},
{
title: "用户角色",
dataIndex: "userRole",
},
{
title: "操作",
key: "action",
},
];
从后端获取数据:
// 数据
const data = ref([]);
// 获取数据
const fetchData = async () => {
const res = await searchUsers("");
if (res.data.data) {
data.value = res.data.data || [];
} else {
message.error("获取数据失败");
}
};
fetchData();
效果如图:
显然展示效果并不好,对于图片、用户角色、创建时间之类的数据,我们可以有更好的展示方式。
表格组件支持我们使用 Vue 的插槽自定义列的展示,参考 Demo 有样学样修改即可。
{{ dayjs(record.createTime).format("YYYY-MM-DD HH:mm:ss") }}
删除
效果如图:
2)利用 Ant Design 的搜索组件,实现对数据的搜索。
HTML 结构代码:
style="max-width: 320px"
v-model:value="searchValue"
placeholder="输入用户名搜索"
enter-button="搜索"
size="large"
@search="onSearch"
/>
改造获取数据函数,支持传入参数(搜索条件):
// 获取数据
const fetchData = async (username = "") => {
const res = await searchUsers(username);
if (res.data.data) {
data.value = res.data.data || [];
} else {
message.error("获取数据失败");
}
};
定义搜索变量,点击搜索按钮时会触发搜索,获取数据:
const searchValue = ref();
const onSearch = () => {
fetchData(searchValue.value);
};
效果如图:
3)开发删除功能
编写点击删除按钮后的处理函数:
// 删除数据
const doDelete = async (id: string) => {
if (!id) {
return;
}
const res = await deleteUser(id);
if (res.data.code === 0) {
message.success("删除成功");
} else {
message.error("删除失败");
}
};
绑定事件:
删除
2、权限控制
有 2 种实现方式 —— 单页面控制权限,或者全局控制权限。
思路都是一致的,在进入某个页面时判断用户是否具有该页面的权限,无非是把权限校验相关的代码写在单个页面内,还是写到一个独立的文件中罢了。
建议编写独立的全局权限控制文件,可以利用 Vue Router 的路由守卫实现,每次切换并进入页面前,都会检查一下当前用户是否具有特定页面的权限。
在 src 下编写 access.ts 权限校验文件,可以自己定义逻辑,比如用页面前缀来统一判断:
import { useLoginUserStore } from "@/store/user";
import { message } from "ant-design-vue";
import router from "@/router";
/**
* 全局权限校验
*/
router.beforeEach(async (to, from, next) => {
const loginUserStore = useLoginUserStore();
const loginUser = loginUserStore.loginUser;
const toUrl = to.fullPath;
if (toUrl.startsWith("/admin")) {
if (!loginUser || loginUser.userRole !== 1) {
message.error("没有权限");
next(`/user/login?redirect=${to.fullPath}`);
return;
}
}
next();
});
在 main.ts(全局入口文件)中引入:
import "./access";
用一个未登录的用户来测试,尝试访问用户管理页面,会报权限错误:
四、项目部署
多环境
多环境:指同一套项目代码在不同的阶段需要根据实际情况来调整配置并且部署到不同的机器上。
为什么需要多环境?
总之,就是针对不同环境做不同的事情。
多环境分类:
- 开发环境(远程开发)大家连同一台机器,为了大家开发方便
- 测试环境(测试)开发 / 测试 / 产品,单元测试 / 性能测试 / 功能测试 / 系统集成测试,独立的数据库、独立的服务器
- 预发布环境(体验服):和正式环境一致,正式数据库,更严谨,查出更多问题
- 正式环境(线上,公开对外访问的项目):尽量不要改动,保证上线前的代码是 “完美” 运行
前端多环境实战
对于前端来说,多环境很重要的一个目的就是区分请求地址,比如:
- 开发环境:http://localhost:8080
- 线上环境:https://codefather.cn
如何实现多环境呢?
前端不同的启动方式,对应的 process.env.NODE_ENV
变量的值也不同,可以在代码中根据这个值来判断不同的环境。
- 开发环境:npm run serve(本地启动,监听端口、自动更新),NODE_ENV == development
- 线上环境:npm run build(项目构建打包),NODE_ENV == production
此外,有些框架支持多套配置文件,可以在配置文件后添加对应的环境名称后缀来区分开发环境和生产环境。比如对于 Umi 这种框架,配置文件规则如下(参考文档):
所以,只需要修改 request.ts 请求配置文件,就能统一更改请求地址啦:
const myAxios = axios.create({
// 区分开发环境和线上环境
baseURL:
process.env.NODE_ENV === "development"
? "http://localhost:8080"
: "线上地址",
timeout: 10000,
withCredentials: true,
});
打包
执行 npm run build
后,会得到 dist 目录,这就是可以部署到服务器上的网站成品包啦~
部署上线
可以直接阅读我之前分享过的 4 种快速上线项目的方法,不再赘述:https://codefather.cn/post/1808578179510697986
OK,这就是本篇教程了,如果你能看到这里,那真是万分感谢!有帮助的话也请给鱼皮点个赞支持,谢谢~
👇🏻 点击下方阅读原文,获取鱼皮的编程学习路线、原创项目教程、求职面试宝典、编程交流圈子。