该文章出于想使用vben的架构结果发现vben的接口处理是固定形式,该文章只是基于我需求进行的一些变更
了解使用
简单了解下vben架构
├── build # 打包脚本相关
│ ├── config # 配置文件
│ ├── generate # 生成器
│ ├── script # 脚本
│ └── vite # vite配置
├── mock # mock文件夹,假的信息接口
├── public # 公共静态资源目录
├── src # 主目录
│ ├── api # 接口文件(管理的是后台中使用的 API ,放在这里管理更规范)
│ ├── assets # 资源文件
│ │ ├── icons # icon sprite 图标文件夹
│ │ ├── images # 项目存放图片的文件夹
│ │ └── svg # 项目存放svg图片的文件夹
│ ├── components # 公共组件(现有 vben 对 AntDesign 组件的二次封装,包括框架层面使用的菜单…)
│ ├── design # 样式文件
│ ├── directives # 指令
│ ├── enums # 枚举/常量(一般用不到)
│ ├── hooks # hook (组件层面,某些位置方便的使用框架中的某些功能,这里封装后并暴漏的出来)
│ │ ├── component # 组件相关hook
│ │ ├── core # 基础hook
│ │ ├── event # 事件相关hook
│ │ ├── setting # 配置相关hook
│ │ └── web # web相关hook
│ ├── layouts # 布局文件(整个框架中的页面布局控制)
│ │ ├── default # 默认布局
│ │ ├── iframe # iframe布局
│ │ └── page # 页面布局
│ ├── locales # 多语言
│ ├── logics # 逻辑
│ ├── main.ts # 主入口
│ ├── router # 路由配置(路由分两个部分,路由/菜单 必须要有路由,菜单才会生效,如果有菜单,没有路由,菜单是不会显示的)
│ ├── settings # 项目配置
│ │ ├── componentSetting.ts # 组件配置(组件封装的默认数据)
│ │ ├── designSetting.ts # 样式配置
│ │ ├── encryptionSetting.ts # 加密配置
│ │ ├── localeSetting.ts # 多语言配置
│ │ ├── projectSetting.ts # 项目配置
│ │ └── siteSetting.ts # 站点配置
│ ├── store # 数据仓库(数据存储)
│ ├── utils # 工具类
│ └── views # 页面(视图层,组件,页面都在这里面)
├── test # 测试(单元测试相关的)
│ └── server # 测试用到的服务
│ ├── api # 测试服务器
│ ├── upload # 测试上传服务器
│ └── websocket # 测试ws服务器
├── types # 类型文件
├── vite.config.ts # vite配置文件
└── windi.config.ts # windcss配置文件
- vben菜单分为前端和后端模式(由于前端模式作者是使用mock作为模拟数据,所以后端模式跟前端模式是区分开来的)
- 删除router/routes/module/demo下的跟后端模式没有关联的页面以及相关模块,当然api下的demo接口也可以清除,来使页面结构看起来没有那么冗杂
前期工作准备完毕,开始配置
- 配置vite
- 切换环境
- https需要做下面的操作 http则不需要
- 由于整体接口都是使用/api所以可在.env文件中让 VITE_GLOB_API_URL=/api 这样会默认所有接口都在拼接/api
- 接下来在vite中配置代理
- 由于是使用的https协议,vite无法直接使用所以在server配置项中配置以下代码
https: { cert: fs.readFileSync(path.join(__dirname, 'keys/cert.crt')), key: fs.readFileSync(path.join(__dirname, 'keys/cert.key')), }
- 接下来就可以配置登录
- 登录配置
- view/login/Login 是登陆主页 而登录模块是LoginFrom
- 由于自定义提供的接口跟项目提供的形式不同 所以导致在userStore.login try抛出了异常
- 异常原因是由于axios封装的返回跟提供的返回不同
- src\utils\http\axios\index.ts 文件内重写响应逻辑
- 在54行解构data时 由于返回的数据结构与原结构不同所以这里使用
// menuList是后面对接菜单接口所需要的所以它是非必须条件 const { msg, success, menuList } = data; // 增加现在判断返回不满足 let message: string; let code: number; // 错误提示也是200所以要额外判断success是否在 if (res.status === 200) { if (success === false) { code = -1; message = msg; } else { code = 0; } } else if (res.status === 401) { code = 401; } else { code = -1; } // code的赋值跟ResultEnum有关 // 这里逻辑可以根据项目进行修改 const hasSuccess = data && code === ResultEnum.SUCCESS;
- 注意data的类型 types\axios.d.ts 更改为所需要的类型,至此源文件更改完毕
- src\store\modules\user.ts login方法的逻辑已经完整,可以正常登录
- 配置用户信息
- 经过解析分析发现 src\store\modules\user.ts 在登陆之后会调用获取用户信息接口
- 由于提供的用户信息接口还需要提供用户信息,此处直接省去了调用获取用户接口
- 登录接口返回的有用户信息,所以94行解构存储token中在将user解构出来
- 调用afterLoginAction方法时传入user,调用getUserInfoAction方法传入user
// 不调用接口 // const userInfo = await getUserInfo(); // 接口跟框架需求的数据不同,现在数据重赋值 userInfo.realName = userInfo.name; userInfo.userId = userInfo.id; const { roles } = userInfo; // 重构用户权限内容 for (let index = 0; index < roles.length; index++) { // 用户类型判断,新增直接加判断 if (roles[index] === 'CERT_PROVINCE_BOSS_ADMIN') { roles[index] = { roleName: 'Super Admin', value: 'super' }; } }
- 有了用户信息发现没有菜单权限
- 转换菜单权限
- 由于提供的是直接数组,无法满足下面的判断需求,所以将用户类型转化为跟框架类似的返回以满足判断
- 需注意RoleInfo的类型结构是 src\api\sys\model\userModel.ts
- 至此菜单也拥有了
- 配置为后端管理菜单
- 经过前面的判断发现 PermissionModeEnum.BACK 就是切换为后端模式的入口
- src\settings\projectSetting.ts permissionMode 的值配置为 PermissionModeEnum.BACK 就可以切换为后端模式
- 切换为后端模式发现页面没有加载
- 配置菜单接口
- 发现接口增加时间节点参数
- src\utils\http\axios\index.ts 138行注释掉 在get请求后面增加时间节点参数
- 经过前面的经验发现返回数据增加了menuList数组,且不满足之前返回的判断
- src\utils\http\axios\index.ts 上文提到menuList解构就用到了
- 在返回之前增加一层菜单接口判断
// 增加当前为菜单接口的过滤方法(框架提供的跟目前接口冲突) if (menuList) { return menuList; } return data;
- 至此菜单也出现了
存储问题处理
- 接口配置完毕后,刷新后发现没有数据
- 经过分析发现是因为用户信息接口被弃用的原因
- 经过思考决定使用短暂存储session的方法去处理刷新后数据丢失的问题
- src\App.vue 增加一些逻辑
- 导入 import { useUserStore } from ‘/@/store/modules/user’;
// 刷新页面前把用户信息数据放在session里并在刷新完毕 const setUserStore = useUserStore(); window.addEventListener('beforeunload', function () { window.sessionStorage.setItem('userInfo', JSON.stringify(setUserStore)); }); const getUserInfo: any = window.sessionStorage.getItem('userInfo'); setUserStore.setUserInfo(JSON.parse(getUserInfo)); // 加载完毕移除 window.sessionStorage.removeItem('userInfo');
- 刷新之前 => 存储store内的用户信息 => 刷新完毕 => store赋值完毕 => 卸载存储