一 将前端代码跑起来。
导入代码 。 github.com/hsiangleev/…
npm install
npm run dev
二 装个软件.hbuilderx
三 分析登录接口。
3.1 登录接口.
method : postjson
request
{username: "admin", password: "admin"}
response
{"Code":200,"Msg":"登陆成功","Data":"token_value"}
失败
{"Code":401,"Msg":"用户名或密码错误","Data":""}
3.2 getRoute 获取菜单 .
method : get
request
header: Access-Token: token_value
Access-Token:token
{
"Code": 200,
"Msg": "",
"Data": [
{
"id": 2,
"parentId": 0,
"name": "Project",
"path": "/Project",
"component": "Layout",
"redirect": "/Project/ProjectList",
"meta": {
"title": "项目管理",
"icon": "el-icon-phone",
"permission": []
}
},
{
"id": 20,
"parentId": 2,
"name": "ProjectList",
"path": "/Project/ProjectList",
"component": "ProjectList",
"meta": {
"title": "项目列表",
"icon": "el-icon-goods",
"permission": []
}
},
{
"id": 21,
"parentId": 2,
"name": "ProjectDetail",
"path": "/Project/ProjectDetail/:projName",
"component": "ProjectDetail",
"meta": {
"title": "项目详情",
"icon": "el-icon-question",
"activeMenu": "/Project/ProjectList",
"hidden": true,
"permission": []
}
},
{
"id": 22,
"parentId": 2,
"name": "ProjectImport",
"path": "/Project/ProjectImport",
"component": "ProjectImport",
"meta": {
"title": "项目导入",
"icon": "el-icon-help",
"permission": []
}
},
{
"id": 3,
"parentId": 0,
"name": "Nav",
"path": "/Nav",
"component": "Layout",
"redirect": "/Nav/SecondNav/ThirdNav",
"meta": {
"title": "多级导航",
"icon": "el-icon-picture",
"permission": []
}
},
{
"id": 30,
"parentId": 3,
"name": "SecondNav",
"path": "/Nav/SecondNav",
"redirect": "/Nav/SecondNav/ThirdNav",
"component": "SecondNav",
"meta": {
"title": "二级导航",
"icon": "el-icon-camera",
"alwaysShow": true,
"permission": []
}
},
{
"id": 300,
"parentId": 30,
"name": "ThirdNav",
"path": "/Nav/SecondNav/ThirdNav",
"component": "ThirdNav",
"meta": {
"title": "三级导航",
"icon": "el-icon-platform",
"permission": []
}
},
{
"id": 31,
"parentId": 3,
"name": "SecondText",
"path": "/Nav/SecondText",
"redirect": "/Nav/SecondText/ThirdText",
"component": "SecondText",
"meta": {
"title": "二级文本",
"icon": "el-icon-opportunity",
"alwaysShow": true,
"permission": []
}
},
{
"id": 310,
"parentId": 31,
"name": "ThirdText",
"path": "/Nav/SecondText/ThirdText",
"component": "ThirdText",
"meta": {
"title": "三级文本",
"icon": "el-icon-menu",
"permission": []
}
},
{
"id": 4,
"parentId": 0,
"name": "Components",
"path": "/Components",
"component": "Layout",
"redirect": "/Components/OpenWindowTest",
"meta": {
"title": "组件测试",
"icon": "el-icon-phone",
"permission": []
}
},
{
"id": 40,
"parentId": 4,
"name": "OpenWindowTest",
"path": "/Components/OpenWindowTest",
"component": "OpenWindowTest",
"meta": {
"title": "选择页",
"icon": "el-icon-goods",
"permission": []
}
},
{
"id": 41,
"parentId": 4,
"name": "CardListTest",
"path": "/Components/CardListTest",
"component": "CardListTest",
"meta": {
"title": "卡片列表",
"icon": "el-icon-question-filled",
"permission": []
}
},
{
"id": 42,
"parentId": 4,
"name": "TableSearchTest",
"path": "/Components/TableSearchTest",
"component": "TableSearchTest",
"meta": {
"title": "表格搜索",
"icon": "el-icon-question-filled",
"permission": []
}
},
{
"id": 43,
"parentId": 4,
"name": "ListTest",
"path": "/Components/ListTest",
"component": "ListTest",
"meta": {
"title": "标签页列表",
"icon": "el-icon-question-filled",
"permission": []
}
},
{
"id": 5,
"parentId": 0,
"name": "Permission",
"path": "/Permission",
"component": "Layout",
"redirect": "/Permission/Directive",
"meta": {
"title": "权限管理",
"icon": "el-icon-phone",
"alwaysShow": true,
"permission": []
}
},
{
"id": 50,
"parentId": 5,
"name": "Directive",
"path": "/Permission/Directive",
"component": "Directive",
"meta": {
"title": "指令管理",
"icon": "el-icon-goods",
"permission": [
"add",
"update",
"remove"
]
}
}
]
}
得到菜单 。
3.3 获取用户信息.
method : get
request
header: Access-Token: token_value
response
{"Code":200,"Msg":"",
"Data":
{"name":"admin","role":["admin"]}
}
4 接口base_url 更换。
一波查找后,修改
const request = axios.create({
// API 请求的默认前缀
baseURL: import.meta.env.VUE_APP_API_BASE_URL as string | undefined,
timeout: 60000 // 请求超时时间
})
将配置改一下
package.json
"scripts": {
"dev": "vite --mode development"
...
}
新建 .env.development
VITE_BASE_URL=http://127.0.0.1
修改 utils/request.ts
// 创建 axios 实例
const request = axios.create({
// API 请求的默认前缀
baseURL: import.meta.env.VITE_BASE_URL as string | undefined,
timeout: 60000 // 请求超时时间
})
修改后端代码 使其符合需求 。
{"Code":401,"Msg":"用户名或密码错误","Data":""} 碰到hyperf 的恶心问题,route 不支持大写字母。 折中一下,后端改为
/api/user/login
前端进行修改 src/api/layout/index.ts
import request from '/@/utils/request'
import { AxiosResponse } from 'axios'
import { IMenubarList } from '/@/type/store/layout'
const api = {
login: '/api/user/login',
getUser: '/api/user/get-user',
getRouterList: '/api/user/get-route',
publickey: '/api/User/public-key'
}
又产生跨域问题。
Access to XMLHttpRequest at 'http://127.0.0.1/api/user/login' from origin 'http://localhost:3003' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
先把问题解决掉。
docker exec -it nginx bash
apt-get update
apt-get install vim
#将这几行塞location 里面。
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
add_header Access-Control-Allow-Headers 'DNT,Keep-Alive,User-Agent,Cache-Control,Content-Type,Authorization';
if ($request_method = 'OPTIONS') { return 204; }
重启nginx 后,再测试
新的报错
has been blocked by CORS policy: Request header field access-token is not allowed by Access-Control-Allow-Headers in preflight response.
接着改nginx 配置 ,Access-Control-Allow-Headers 加上 access-token
然后实现后端代码 。角色,菜单 先hardcode 处理。
实现效果如下。
后端代码如下。 route.php
Router::addRoute(['GET', 'HEAD'], '/api/user/get-route', 'App\Controller\MenuController::list');
Router::addRoute(['GET', 'HEAD'], '/api/user/get-user', 'App\Controller\UserController::getUser');
MenuController
<?php
declare(strict_types=1);
/**
*
* @Author xuxing
* @description 机构申请接口. (apply_auto_audit 打开后,自动生效)
*/
namespace App\Controller;
use App\Constants\Enum;
use App\Constants\ErrorCode;
use App\Service\UserService;
use Hyperf\Di\Annotation\Inject;
class MenuController extends AbstractController
{
public function list()
{
$menus = [
[
"id"=> 2,
"parentId"=> 0,
"name"=> "Project",
"path"=> "/Project",
"component"=> "Layout",
"redirect"=> "/Project/ProjectList",
"meta"=> [
"title"=> "项目管理",
"icon"=> "el-icon-phone",
"permission"=> []
]
],
[
"id"=> 20,
"parentId"=> 2,
"name"=> "ProjectList",
"path"=> "/Project/ProjectList",
"component"=> "ProjectList",
"meta"=> [
"title"=> "项目管理",
"icon"=> "el-icon-phone",
"permission"=> []
]
],
[
"id"=> 22,
"parentId"=> 2,
"name"=> "ProjectImport",
"path"=> "/Project/ProjectImport",
"component"=> "ProjectImport",
"meta"=> [
"title"=> "项目导入",
"icon"=> "el-icon-help",
"permission"=> []
]
],
];
return $this->code(ErrorCode::API_SUCCESS,['Data' => $menus] );
}
}
UserController.php
<?php
declare(strict_types=1);
/**
*
* @Author xuxing
* @description 机构申请接口. (apply_auto_audit 打开后,自动生效)
*/
namespace App\Controller;
use App\Constants\ErrorCode;
use Hyperf\Di\Annotation\Inject;
use App\Service\AuthenService;
class UserController extends AbstractController
{
#[Inject]
protected AuthenService $authenService;
public function getUser()
{
$token = $this->request->getHeader("Access-Token");
$user = $this->authenService->getUinfo($token[0]);
$data = ["name" => $user["tname"], "role"=>["admin"]];
return $this->code(ErrorCode::API_SUCCESS, ['token' => $token,"user" => $user, 'Data' => $data]);
}
}