做一个免费网站的流程,他达拉非片,平台推广销售话术,网站建设w亿码酷1流量订制目标
整合vue-element-plus-admin前端框架#xff0c;作为开发平台的前端。
准备工作
前端选用vue-element-plus-admin#xff0c;地址 https://gitee.com/kailong110120130/vue-element-plus-admin。 首先clone项目#xff0c;然后整合到开发平台中去。这是一个独立的前…目标
整合vue-element-plus-admin前端框架作为开发平台的前端。
准备工作
前端选用vue-element-plus-admin地址 https://gitee.com/kailong110120130/vue-element-plus-admin。 首先clone项目然后整合到开发平台中去。这是一个独立的前端的项目而我将其放到后端项目根目录下即建一个huayuan-web的目录将vue-element-plus-admin目录下的内容放进去相当于将前端项目视为整个工程项目的一个模块。 为什么要这么做呢原因也简单从架构上而言前后端是分离的不过当前这个平台前后端都是我在做因此开发模式并不是前后端分别开发通过mock数据和联调再整合到一块去而是对于一个功能例如组织机构管理往往是后端和前端是一块做的。这样从开发上从Git单次提交上都是对于一个功能的完整处理。
既然是将前端项目视为整个工程的一个模块是一个git仓库统一管理那么前端项目下就不应该还存在.git目录了。如果直接删除运行pnpm install会报错原因是使用了husky而husky是依赖git 才能安装。 经过几次尝试做了以下处理。先clone然后执行pnpm install确保前端项目能运转起来。然后执行 pnpm unistall husky既卸载掉husky然后再删除掉前端项目根目录下的.git目录这样既保证了前端项目能正常运转又将其纳入了整个工程。
调用后端服务
完成了基本的源码下载和整合到项目工程接下来考虑的就是怎么实现前端调用后端服务。 前端使用默认的localhost:4000,后端服务的地址是localhost:8080首先解决前后端联通性问题。 首先调整的是vite.config.ts中的server节点下的proxy设置具体如下
server: {port: 4000,proxy: {// 系统管理模块/system: {target: env.VITE_BASE_URL,changeOrigin: true } }
}即把路径以/system起始的请求转发到后端其中env.VITE_BASE_URL是在local.env中定义
# 环境
NODE_ENVdevelopment# 请求路径
VITE_BASE_URLhttp://localhost:8080# 接口前缀
VITE_API_BASEPATH/my-api# 打包路径
VITE_BASE_PATH/# 标题
VITE_APP_TITLEElementAdmin
系统登录
前后端联通后首先实现的功能肯定是登录。 结果看了下官方文档只有安装、目录结构和功能组件的大概介绍并没有如何跟后端整合的介绍。百度搜了下结果都是基vue-element-admin的也就是vue2.0Element UI 的框架。看来新技术与框架只能自己来开荒了通过源码阅读与摸索来实现。 前端框架能独立运行输入账号密码后完成登录进入系统首页实际上使用的是mock数据登录方法位于mock/user/index.ts中。
import { config } from /config/axios/config
import { MockMethod } from vite-plugin-mockconst { result_code } configconst timeout 1000const List: {username: stringpassword: stringrole: stringroleId: stringpermissions: string | string[]
}[] [{username: admin,password: admin,role: admin,roleId: 1,permissions: [*.*.*]},{username: test,password: test,role: test,roleId: 2,permissions: [example:dialog:create, example:dialog:delete]}]export default [// 列表接口{url: /user/list,method: get,response: ({ query }) {const { username, pageIndex, pageSize } queryconst mockList List.filter((item) {if (username item.username.indexOf(username) 0) return falsereturn true})const pageList mockList.filter((_, index) index pageSize * pageIndex index pageSize * (pageIndex - 1))return {code: result_code,data: {total: mockList.length,list: pageList}}}},// 登录接口{url: /user/login,method: post,timeout,response: ({ body }) {const data bodylet hasUser falsefor (const user of List) {if (user.username data.username user.password data.password) {hasUser truereturn {code: result_code,data: user}}}if (!hasUser) {return {code: 500,message: 账号或密码错误}}}},// 退出接口{url: /user/loginOut,method: get,timeout,response: () {return {code: result_code,data: null}}}
] as MockMethod[]
可以看到逻辑比较简单无非是比对下预先设置的账号密码如一致则直接构造一个admin用户返回。
接下来我来改造下直接调用后端服务。 系统后端使用SpringSecurity框架配置的登录路径是/system/user/login。 修改api/login/index.ts中的loginApi即可
export const loginApi (data: UserType) {return request.post({url: /system/user/login?username data.username password data.password,data})
}上面把账号密码通过url参数的方式传入后端实际是SpringSecurity的限制。SpringSecurity内置的过滤器不从post请求的body里取数据所以这地方做了点小处理。 完成上述调整后使用浏览器调试功能可以看到真正向后端发起请求了并且后端返回了登录成功后的数据。
缓存用户数据
vue-element-plus-admin框架对用户信息做了定义与我的设计差异较大这地方也做了比较大的改造。 用户信息如下
import { store } from ../index
import { defineStore } from pinia
import { useCache } from /hooks/web/useCache
import { USER_KEY } from /constant/common
const { wsCache } useCache()interface UserState {account: stringname: stringforceChangePassword: stringid: stringtoken: stringbuttonPermission: string[]menuPermission: string[]
}export const useUserStore defineStore(user, {state: (): UserState ({account: ,name: ,forceChangePassword: ,id: ,token: ,buttonPermission: [],menuPermission: []}),getters: {getAccount(): string {return this.account}},actions: {async setUserAction(user) {this.account user.accountthis.name user.namethis.forceChangePassword user.forceChangePasswordthis.id user.idthis.token user.tokenthis.buttonPermission user.buttonPermissionthis.menuPermission user.menuPermissionwsCache.set(USER_KEY, user)},async clear() {wsCache.clear()this.resetState()},resetState() {this.account this.name this.forceChangePassword this.id this.token this.buttonPermission []this.menuPermission []}}
})export const useUserStoreWithOut () {return useUserStore(store)
}
包括标识、账号、姓名、是否强制修改密码、令牌、菜单权限数组和按钮权限数组这几个关键字段。 在用户登录成功后将后端返回的用户信息缓存到浏览器SessionStorage中。
// 登录
const signIn async () {const formRef unref(elFormRef)await formRef?.validate(async (isValid) {if (isValid) {loading.value trueconst { getFormData } methodsconst formData await getFormDataUserType()try {const res await loginApi(formData)if (res) {// 保存用户信息userStore.setUserAction(res.data)// 是否使用动态路由略}} finally {loading.value false}}})实现动态路由
接下来就是最复杂的一块功能改造了即实现动态路由根据后端返回的菜单权限动态构造出前端路由来。 在vue-elment-ui框架里这块功能实际是没有的当初我自己费了不少劲最终实现了。 在vue-element-plus-admin框架中里这块功能有了支持预留了三种模式 1.静态路由也就是默认的前端独立运行模式看到的效果所有菜单固化预先配置好。 2.前端控制只初始化通用的路由至路由表中。对于动态路由在前端固定写死对应的角色。用户登录后通过角色去遍历动态路由表获取该角色可以访问的路由表生成动态路由表再通过 router.addRoutes 添加到路由实例。 3.后端控制通过接口动态生成路由表且遵循一定的数据结构返回。前端根据需要处理该数据为可识别的结构再通过 router.addRoutes 添加到路由实例。 上面三种模式第一种明显不可用第二种勉强可用但缺点也很明显灵活性不够如果服务端改动角色前端也需要跟着改动并且排序什么的都需要前端控制。第三种才是我们真正想要的后端调整权限前端无需修改自动动态获取处理后形成系统菜单。
虽然前端框架预留了口子但是调整起来仍然比较复杂下面具体说说。 首先得改一个全局变量将store/modules/app.ts 中的dynamicRouter 设置为 true即启用动态路由框架在多处会首先判断该配置的取值进行不同的处理。 其次是修改store/modules/permission.ts 中的generateRoutes方法。
generateRoutes(type: admin | test | none,routers?: AppCustomRouteRecordRaw[] | string[]): Promiseunknown {return new Promisevoid((resolve) {// TODO:前后端动态路由临时添加固定路由待去除let routerMap: AppRouteRecordRaw[] asyncRouterMapif (type admin) {// 后端过滤菜单routerMap generateRoutesFn2(routers as AppCustomRouteRecordRaw[]).concat(routerMap)} else if (type test) {// 模拟前端过滤菜单routerMap generateRoutesFn1(cloneDeep(asyncRouterMap), routers as string[])} else {// 直接读取静态路由表routerMap cloneDeep(asyncRouterMap)}// 动态路由404一定要放到最后面this.addRouters routerMap.concat([{path: /:path(.*)*,redirect: /404,name: 404Page,meta: {hidden: true,breadcrumb: false}}])// 渲染菜单的所有路由this.routers cloneDeep(constantRouterMap).concat(routerMap)resolve()})},这个方法有两个参数第一个是指定模式admin代表模式三从后端接口拿到动态路由数据第二个参数就是后端返回的路由数据。 再次是将后端返回的路由数据进行转换处理成为前端需要的数据结构需要调整/utils/routerHelper.ts中的 generateRoutesFn2方法。
// 后端控制路由生成
export const generateRoutesFn2 (routes: AppCustomRouteRecordRaw[]): AppRouteRecordRaw[] {const res: AppRouteRecordRaw[] []for (const route of routes) {const data: AppRouteRecordRaw {path: route.path,name: route.name,redirect: route.redirect,meta: route.meta}if (route.component) {const comModule modules[../modules/${route.component}.vue] || modules[../modules/${route.component}.tsx]const component route.component as stringif (!comModule !component.includes(#)) {console.error(未找到${route.component}.vue文件或${route.component}.tsx文件请创建)} else {// 动态加载路由文件data.component component # ? Layout : component.includes(##) ? getParentLayout() : comModule}}// recursive child routesif (route.children) {data.children generateRoutesFn2(route.children)}res.push(data as AppRouteRecordRaw)}return res
}
数据处理和转换跟后端返回的数据结构有关系特别是动态引入组件部分需根据自己的情况进行适配调整。
完成上述操作后动态路由就实现了回到登录环节实现加载动态路由然后进入系统默认加载第一个能找到的路由。
// 登录
const signIn async () {const formRef unref(elFormRef)await formRef?.validate(async (isValid) {if (isValid) {loading.value trueconst { getFormData } methodsconst formData await getFormDataUserType()try {const res await loginApi(formData)if (res) {// 保存用户信息userStore.setUserAction(res.data)// 是否使用动态路由if (appStore.getDynamicRouter) {const routers res.data.menuPermission || []await permissionStore.generateRoutes(admin, routers).catch(() {})permissionStore.getAddRouters.forEach((route) {addRoute(route as RouteRecordRaw) // 动态添加可访问路由表})permissionStore.setIsAddRouters(true)push({ path: redirect.value || permissionStore.addRouters[0].path })} else {await permissionStore.generateRoutes(none).catch(() {})permissionStore.getAddRouters.forEach((route) {addRoute(route as RouteRecordRaw) // 动态添加可访问路由表})permissionStore.setIsAddRouters(true)push({ path: redirect.value || permissionStore.addRouters[0].path })}}} finally {loading.value false}}})
}总结
今天主要介绍了如何对vue-element-plus-admin改造实现系统登录、缓存用户数据以及动态路由。完成上述操作后基本实现了前后端的打通工作。
平台设计与设计专栏地址https://blog.csdn.net/seawaving/category_12230971.html 开源项目地址[https://gitee.com/popsoft/huayuan-development-platform](https://gitee.com/popsoft/huayuan-development-platform]() 欢迎收藏、点赞、评论。