Commit 861403fd by 吴春元

登录页面调试,其他修改

parent 60a0a033
...@@ -14,7 +14,7 @@ export function login( ...@@ -14,7 +14,7 @@ export function login(
uuid, uuid,
}; };
return request({ return request({
url: "/login", url: "/auth/login",
headers: { headers: {
isToken: false, isToken: false,
repeatSubmit: false, repeatSubmit: false,
...@@ -27,7 +27,7 @@ export function login( ...@@ -27,7 +27,7 @@ export function login(
// 注册方法 // 注册方法
export function register(data: any) { export function register(data: any) {
return request({ return request({
url: "/register", url: "/auth/register",
headers: { headers: {
isToken: false, isToken: false,
}, },
...@@ -39,7 +39,7 @@ export function register(data: any) { ...@@ -39,7 +39,7 @@ export function register(data: any) {
// 获取用户详细信息 // 获取用户详细信息
export function getInfo() { export function getInfo() {
return request({ return request({
url: "/getInfo", url: "/system/user/getInfo",
method: "get", method: "get",
}); });
} }
...@@ -48,7 +48,7 @@ export function getInfo() { ...@@ -48,7 +48,7 @@ export function getInfo() {
export function logout() { export function logout() {
return request({ return request({
url: "/auth/logout", url: "/auth/logout",
method: "post", method: "delete",
}); });
} }
......
@use "./_variables.scss" as vars; @use "./_variables.scss" as vars;
// 深蓝色主题变量 // 深蓝色主题变量
$dark-blue-primary: #1890FF; // 主蓝色 $dark-blue-primary: #1890ff; // 主蓝色
$dark-blue-bg: #001529; // 深蓝背景 $dark-blue-bg: #001529; // 深蓝背景
$dark-blue-secondary: #003a8c; // 次级蓝色 $dark-blue-secondary: #003a8c; // 次级蓝色
$dark-blue-border: #004d99; // 边框蓝色 $dark-blue-border: #004d99; // 边框蓝色
$white-text: #FFFFFF; // 白色文字 $white-text: #ffffff; // 白色文字
$light-gray-text: #D9D9D9; // 浅灰色文字 $light-gray-text: #d9d9d9; // 浅灰色文字
$blue-hover: #40a9ff; // 悬停蓝色 $blue-hover: #40a9ff; // 悬停蓝色
// 全局深蓝色主题 // 全局深蓝色主题
...@@ -130,6 +129,24 @@ $blue-hover: #40a9ff; // 悬停蓝色 ...@@ -130,6 +129,24 @@ $blue-hover: #40a9ff; // 悬停蓝色
} }
} }
// 选择器组件 - 深蓝色主题
.el-cascader .el-input {
--el-input-text-color: var(--el-text-color-regular);
--el-input-border: var(--el-border);
--el-input-hover-border: var(--el-border-color-hover);
--el-input-focus-border: var(--el-color-primary);
--el-input-transparent-border: 0 0 0 1px transparent inset;
--el-input-border-color: var(--el-border-color);
--el-input-border-radius: var(--el-border-radius-base);
--el-input-bg-color: #002766;
--el-input-icon-color: var(--el-text-color-placeholder);
--el-input-placeholder-color: var(--el-text-color-placeholder);
--el-input-hover-border-color: var(--el-border-color-hover);
--el-input-clear-hover-color: var(--el-text-color-secondary);
--el-input-focus-border-color: var(--el-color-primary);
--el-input-width: 100%;
}
// 表格组件 - 深蓝色主题 // 表格组件 - 深蓝色主题
.el-table { .el-table {
--el-table-border-color: var(--el-border-color); --el-table-border-color: var(--el-border-color);
......
import { login, logout, getInfo } from '@/api/login' import { login, logout, getInfo } from "@/api/login";
import { getToken, setToken, removeToken } from '@/utils/auth' import { getToken, setToken, removeToken } from "@/utils/auth";
import { defineStore } from 'pinia' import { defineStore } from "pinia";
const useUserStore = defineStore( const useUserStore = defineStore("user", {
'user',
{
state: (): any => ({ state: (): any => ({
token: getToken(), token: getToken(),
id: '', id: "",
name: '', name: "",
avatar: '', avatar: "",
roles: [], roles: [],
permissions: [] permissions: [],
}), }),
actions: { actions: {
// 登录 // 登录
login(userInfo: any) { login(userInfo: any) {
const username = userInfo.username.trim() const username = userInfo.username.trim();
const password = userInfo.password const password = userInfo.password;
const code = userInfo.code const code = userInfo.code;
const uuid = userInfo.uuid const uuid = userInfo.uuid;
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
login(username, password, code, uuid).then((res: any) => { login(username, password, code, uuid)
setToken(res.token) .then((res: any) => {
this.token = res.token setToken(res.data.access_token);
resolve(res) this.token = res.data.access_token;
}).catch(error => { resolve(res);
reject(error)
})
}) })
.catch((error) => {
reject(error);
});
});
}, },
// 获取用户信息 // 获取用户信息
getInfo() { getInfo() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
getInfo().then((res: any) => { getInfo()
const user = res.user .then((res: any) => {
const user = res.user;
const avatar = import.meta.env.VITE_APP_BASE_API + user.avatar; const avatar = import.meta.env.VITE_APP_BASE_API + user.avatar;
if (res.roles && res.roles.length > 0) { // 验证返回的roles是否是一个非空数组 if (res.roles && res.roles.length > 0) {
this.roles = res.roles // 验证返回的roles是否是一个非空数组
this.permissions = res.permissions this.roles = res.roles;
this.permissions = res.permissions;
} else { } else {
this.roles = ['ROLE_DEFAULT'] this.roles = ["ROLE_DEFAULT"];
} }
this.id = user.userId this.id = user.userId;
this.name = user.userName this.name = user.userName;
this.avatar = avatar this.avatar = avatar;
resolve(res) resolve(res);
}).catch(error => {
reject(error)
})
}) })
.catch((error) => {
reject(error);
});
});
}, },
// 退出系统 // 退出系统
logOut() { logOut() {
return new Promise((resolve, reject)=> { return new Promise((resolve, reject) => {
logout().then(() => { logout()
this.token = '' .then(() => {
this.roles = [] this.token = "";
this.permissions = [] this.roles = [];
removeToken() this.permissions = [];
resolve(true) removeToken();
}).catch(error => { resolve(true);
reject(error)
})
})
}
}
}) })
.catch((error) => {
reject(error);
});
});
},
},
});
export default useUserStore export default useUserStore;
import axios from 'axios' import axios from "axios";
import { ElNotification , ElMessageBox, ElMessage, ElLoading } from 'element-plus' import {
import { getToken } from '@/utils/auth' ElNotification,
import errorCode from '@/utils/errorCode' ElMessageBox,
import { tansParams, blobValidate } from '@/utils/ruoyi' ElMessage,
import cache from '@/plugins/cache' ElLoading,
import useUserStore from '@/store/modules/user' } from "element-plus";
import { getToken } from "@/utils/auth";
import errorCode from "@/utils/errorCode";
import { tansParams, blobValidate } from "@/utils/ruoyi";
import cache from "@/plugins/cache";
import useUserStore from "@/store/modules/user";
let downloadLoadingInstance; let downloadLoadingInstance;
// 是否显示重新登录 // 是否显示重新登录
export let isRelogin = { show: false }; export let isRelogin = { show: false };
axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8' axios.defaults.headers["Content-Type"] = "application/json;charset=utf-8";
// 创建axios实例 // 创建axios实例
const service = axios.create({ const service = axios.create({
// axios中请求配置有baseURL选项,表示请求URL公共部分 // axios中请求配置有baseURL选项,表示请求URL公共部分
baseURL: import.meta.env.VITE_APP_BASE_API, baseURL: import.meta.env.VITE_APP_BASE_API,
// 超时 // 超时
timeout: 100000 timeout: 100000,
}) });
// request拦截器 // request拦截器
service.interceptors.request.use(config => { service.interceptors.request.use(
(config) => {
// 是否需要设置 token // 是否需要设置 token
const isToken = (config.headers || {}).isToken === false const isToken = (config.headers || {}).isToken === false;
// 是否需要防止数据重复提交 // 是否需要防止数据重复提交
const isRepeatSubmit = (config.headers || {}).repeatSubmit === false const isRepeatSubmit = (config.headers || {}).repeatSubmit === false;
if (getToken() && !isToken) { if (getToken() && !isToken) {
config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改 console.log("getToken()-----" + getToken());
config.headers["Authorization"] = "Bearer " + getToken(); // 让每个请求携带自定义token 请根据实际情况自行修改
} }
// debugger;
// get请求映射params参数 // get请求映射params参数
if (config.method === 'get' && config.params) { if (config.method === "get" && config.params) {
let url = config.url + '?' + tansParams(config.params); let url = config.url + "?" + tansParams(config.params);
url = url.slice(0, -1); url = url.slice(0, -1);
config.params = {}; config.params = {};
config.url = url; config.url = url;
} }
if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) { if (
!isRepeatSubmit &&
(config.method === "post" || config.method === "put")
) {
const requestObj = { const requestObj = {
url: config.url, url: config.url,
data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data, data:
time: new Date().getTime() typeof config.data === "object"
} ? JSON.stringify(config.data)
: config.data,
time: new Date().getTime(),
};
const requestSize = Object.keys(JSON.stringify(requestObj)).length; // 请求数据大小 const requestSize = Object.keys(JSON.stringify(requestObj)).length; // 请求数据大小
const limitSize = 5 * 1024 * 1024; // 限制存放数据5M const limitSize = 5 * 1024 * 1024; // 限制存放数据5M
if (requestSize >= limitSize) { if (requestSize >= limitSize) {
console.warn(`[${config.url}]: ` + '请求数据大小超出允许的5M限制,无法进行防重复提交验证。') console.warn(
`[${config.url}]: ` +
"请求数据大小超出允许的5M限制,无法进行防重复提交验证。"
);
return config; return config;
} }
const sessionObj = cache.session.getJSON('sessionObj') const sessionObj = cache.session.getJSON("sessionObj");
if (sessionObj === undefined || sessionObj === null || sessionObj === '') { if (
cache.session.setJSON('sessionObj', requestObj) sessionObj === undefined ||
sessionObj === null ||
sessionObj === ""
) {
cache.session.setJSON("sessionObj", requestObj);
} else { } else {
const s_url = sessionObj.url; // 请求地址 const s_url = sessionObj.url; // 请求地址
const s_data = sessionObj.data; // 请求数据 const s_data = sessionObj.data; // 请求数据
const s_time = sessionObj.time; // 请求时间 const s_time = sessionObj.time; // 请求时间
const interval = 1000; // 间隔时间(ms),小于此时间视为重复提交 const interval = 1000; // 间隔时间(ms),小于此时间视为重复提交
if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) { if (
const message = '数据正在处理,请勿重复提交'; s_data === requestObj.data &&
console.warn(`[${s_url}]: ` + message) requestObj.time - s_time < interval &&
return Promise.reject(new Error(message)) s_url === requestObj.url
) {
const message = "数据正在处理,请勿重复提交";
console.warn(`[${s_url}]: ` + message);
return Promise.reject(new Error(message));
} else { } else {
cache.session.setJSON('sessionObj', requestObj) cache.session.setJSON("sessionObj", requestObj);
}
} }
} }
return config;
},
(error) => {
console.log(error);
Promise.reject(error);
} }
return config );
}, error => {
console.log(error)
Promise.reject(error)
})
// 响应拦截器 // 响应拦截器
service.interceptors.response.use(res => { service.interceptors.response.use(
(res) => {
// 未设置状态码则默认成功状态 // 未设置状态码则默认成功状态
const code = res.data.code || 200; const code = res.data.code || 200;
// 获取错误信息 // 获取错误信息
const msg = (code in errorCode ? errorCode[code as keyof typeof errorCode] : undefined) || res.data.msg || errorCode['default'] const msg =
(code in errorCode
? errorCode[code as keyof typeof errorCode]
: undefined) ||
res.data.msg ||
errorCode["default"];
// 二进制数据则直接返回 // 二进制数据则直接返回
if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') { if (
return res.data res.request.responseType === "blob" ||
res.request.responseType === "arraybuffer"
) {
return res.data;
} }
if (code === 401) { if (code === 401) {
if (!isRelogin.show) { if (!isRelogin.show) {
isRelogin.show = true; isRelogin.show = true;
ElMessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => { ElMessageBox.confirm(
"登录状态已过期,您可以继续留在该页面,或者重新登录",
"系统提示",
{
confirmButtonText: "重新登录",
cancelButtonText: "取消",
type: "warning",
}
)
.then(() => {
isRelogin.show = false; isRelogin.show = false;
useUserStore().logOut().then(() => { useUserStore()
location.href = '/index'; .logOut()
.then(() => {
location.href = "/index";
});
}) })
}).catch(() => { .catch(() => {
isRelogin.show = false; isRelogin.show = false;
}); });
} }
return Promise.reject('无效的会话,或者会话已过期,请重新登录。') return Promise.reject("无效的会话,或者会话已过期,请重新登录。");
} else if (code === 500) { } else if (code === 500) {
ElMessage({ message: msg, type: 'error' }) ElMessage({ message: msg, type: "error" });
return Promise.reject(new Error(msg)) return Promise.reject(new Error(msg));
} else if (code === 601) { } else if (code === 601) {
ElMessage({ message: msg, type: 'warning' }) ElMessage({ message: msg, type: "warning" });
return Promise.reject(new Error(msg)) return Promise.reject(new Error(msg));
} else if (code !== 200) { } else if (code !== 200) {
ElNotification.error({ title: msg }) ElNotification.error({ title: msg });
return Promise.reject('error') return Promise.reject("error");
} else { } else {
return Promise.resolve(res.data) return Promise.resolve(res.data);
} }
}, },
error => { (error) => {
console.log('err' + error) console.log("err" + error);
let { message } = error; let { message } = error;
if (message == "Network Error") { if (message == "Network Error") {
message = "后端接口连接异常"; message = "后端接口连接异常";
...@@ -116,9 +164,9 @@ service.interceptors.response.use(res => { ...@@ -116,9 +164,9 @@ service.interceptors.response.use(res => {
} else if (message.includes("Request failed with status code")) { } else if (message.includes("Request failed with status code")) {
message = "系统接口" + message.substr(message.length - 3) + "异常"; message = "系统接口" + message.substr(message.length - 3) + "异常";
} }
ElMessage({ message: message, type: 'error', duration: 5 * 1000 }) ElMessage({ message: message, type: "error", duration: 5 * 1000 });
return Promise.reject(error) return Promise.reject(error);
} }
) );
export default service export default service;
...@@ -57,47 +57,6 @@ ...@@ -57,47 +57,6 @@
</div> </div>
</el-col> </el-col>
</el-row> </el-row>
<!-- <div class="w-[454px] flex flex-col">
<ContainerWrap title="总览数据">
<DataInfo class="!h-[280px]" />
</ContainerWrap>
<ContainerWrap title="各公司隧道统计">
<TunnelStatusNum class="!h-[250px]" />
</ContainerWrap>
<ContainerWrap title="各隧道施工进度" class="flex-grow">
<ConstructionProgress />
</ContainerWrap>
</div>
<div class="flex-grow flex flex-col items-center h-full relative">
<div class="absolute top-[46px] right-0 z-50">
<el-cascader
placeholder="请选择机构"
:options="officeTree"
v-model="selectedOffice"
clearable
filterable
:show-all-levels="false"
:props="{
expandTrigger: 'hover',
multiple: false,
checkStrictly: true,
}"
@change="handleOfficeChange"
>
</el-cascader>
</div>
</div>
<div class="w-[454px] flex flex-col h-full">
<ContainerWrap title="设备统计" class="!h-fit">
<DeviceInfo />
</ContainerWrap>
<ContainerWrap title="视频监控" class="flex-grow !h-0">
<template #header-right>
<el-button type="primary" size="small" link>查看更多>></el-button>
</template>
<VideoControls />
</ContainerWrap>
</div> -->
</div> </div>
<el-dialog <el-dialog
v-model="dialogVisible" v-model="dialogVisible"
...@@ -174,7 +133,7 @@ import Alert7Days from "./components/Alert7Days.vue"; ...@@ -174,7 +133,7 @@ import Alert7Days from "./components/Alert7Days.vue";
import MapEcharts from "./components/MapEcharts.vue"; import MapEcharts from "./components/MapEcharts.vue";
import DeployProject from "./components/DeployProject.vue"; import DeployProject from "./components/DeployProject.vue";
import SubsidiaryCompanyEquipment from "./components/SubsidiaryCompanyEquipment.vue"; import SubsidiaryCompanyEquipment from "./components/SubsidiaryCompanyEquipment.vue";
import Map from "./components/Map.vue"; // import Map from "./components/Map.vue";
import { ref, onMounted, onUnmounted } from "vue"; import { ref, onMounted, onUnmounted } from "vue";
import { eventBus } from "@/eventBus"; import { eventBus } from "@/eventBus";
......
<template>
<div class="login flex-col pb-10">
<h3 class="text-5xl font-bold text-center mb-10">
{{ AppSetting.projectName }}
</h3>
<el-form
ref="loginRef"
:model="loginForm"
:rules="loginRules"
class="login-form"
>
<h3 class="title">用户登录</h3>
<el-form-item prop="username">
<el-input
v-model="loginForm.username"
type="text"
size="large"
auto-complete="off"
placeholder="请输入账号"
>
<template #prefix>
<el-icon color="#fff"><Avatar /></el-icon>
</template>
</el-input>
</el-form-item>
<el-form-item prop="password">
<el-input
v-model="loginForm.password"
type="password"
size="large"
auto-complete="off"
placeholder="请输入密码"
@keyup.enter="handleLogin"
>
<template #prefix
><el-icon color="#fff"><Lock /></el-icon
></template>
</el-input>
</el-form-item>
<el-form-item prop="code" v-if="captchaEnabled">
<el-input
v-model="loginForm.code"
size="large"
auto-complete="off"
placeholder="验证码"
style="width: 63%"
@keyup.enter="handleLogin"
>
<template #prefix
><el-icon color="#fff"><Opportunity /></el-icon
></template>
</el-input>
<div class="login-code">
<img :src="codeUrl" @click="getCode" class="login-code-img" />
</div>
</el-form-item>
<el-checkbox
v-model="loginForm.rememberMe"
style="margin: 0px 0px 10px 0px"
>记住密码</el-checkbox
>
<el-form-item style="width: 100%" class="pb-18">
<el-button
:loading="loading"
size="large"
type="primary"
style="width: 100%; height: 35px; border: 0px solid #4491fc"
color="#2261BA"
@click.prevent="handleLogin"
>
<span v-if="!loading">登 录</span>
<span v-else>登 录 中...</span>
</el-button>
<div style="float: right" v-if="register">
<router-link class="link-type" :to="'/register'"
>立即注册</router-link
>
</div>
</el-form-item>
</el-form>
<!-- 底部 -->
<div class="el-login-footer">
<span>Copyright © 2018-2024 ruoyi.vip All Rights Reserved.</span>
</div>
</div>
</template>
<script setup>
import { getCodeImg } from "@/api/login";
import Cookies from "js-cookie";
import { encrypt, decrypt } from "@/utils/jsencrypt";
import useUserStore from "@/store/modules/user";
import { AppSetting } from "@/setting";
const userStore = useUserStore();
const route = useRoute();
const router = useRouter();
const { proxy } = getCurrentInstance();
const loginForm = ref({
username: "admin",
password: "admin123",
rememberMe: false,
code: "",
uuid: "",
});
const loginRules = {
username: [{ required: true, trigger: "blur", message: "请输入您的账号" }],
password: [{ required: true, trigger: "blur", message: "请输入您的密码" }],
code: [{ required: true, trigger: "change", message: "请输入验证码" }],
};
const codeUrl = ref("");
const loading = ref(false);
// 验证码开关
const captchaEnabled = ref(true);
// 注册开关
const register = ref(false);
const redirect = ref(undefined);
watch(
route,
(newRoute) => {
redirect.value = newRoute.query && newRoute.query.redirect;
},
{ immediate: true }
);
function handleLogin() {
proxy.$refs.loginRef.validate((valid) => {
if (valid) {
loading.value = true;
// 勾选了需要记住密码设置在 cookie 中设置记住用户名和密码
if (loginForm.value.rememberMe) {
Cookies.set("username", loginForm.value.username, { expires: 30 });
Cookies.set("password", encrypt(loginForm.value.password), {
expires: 30,
});
Cookies.set("rememberMe", loginForm.value.rememberMe, { expires: 30 });
} else {
// 否则移除
Cookies.remove("username");
Cookies.remove("password");
Cookies.remove("rememberMe");
}
// 调用action的登录方法
userStore
.login(loginForm.value)
.then(() => {
const query = route.query;
const otherQueryParams = Object.keys(query).reduce((acc, cur) => {
if (cur !== "redirect") {
acc[cur] = query[cur];
}
return acc;
}, {});
router.push({ path: redirect.value || "/", query: otherQueryParams });
})
.catch(() => {
loading.value = false;
// 重新获取验证码
if (captchaEnabled.value) {
getCode();
}
});
}
});
}
function getCode() {
getCodeImg().then((res) => {
captchaEnabled.value =
res.captchaEnabled === undefined ? true : res.captchaEnabled;
if (captchaEnabled.value) {
codeUrl.value = "data:image/gif;base64," + res.img;
loginForm.value.uuid = res.uuid;
}
});
}
function getCookie() {
const username = Cookies.get("username");
const password = Cookies.get("password");
const rememberMe = Cookies.get("rememberMe");
loginForm.value = {
username: username === undefined ? loginForm.value.username : username,
password:
password === undefined ? loginForm.value.password : decrypt(password),
rememberMe: rememberMe === undefined ? false : Boolean(rememberMe),
};
}
getCode();
getCookie();
</script>
<style lang="scss" scoped>
.login {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
background-image: url("@/assets/images/login-background.jpg");
background-size: 100% 100%;
}
.title {
margin: 60px auto 10px auto;
text-align: center;
font-weight: 500;
color: #fff;
}
.login-form {
border-radius: 6px;
// background: #ffffff;
background-image: url("@/assets/images/login-center-bg1.png");
background-size: 100% 100%;
width: 700px;
padding: 20px 220px 5px 220px;
.el-input {
height: 35px;
input {
height: 35px;
}
}
.input-icon {
height: 39px;
width: 14px;
margin-left: 0px;
}
}
.login-tip {
font-size: 13px;
text-align: center;
color: #bfbfbf;
}
.login-code {
width: 33%;
height: 40px;
float: right;
img {
cursor: pointer;
vertical-align: middle;
}
}
.el-login-footer {
height: 40px;
line-height: 40px;
position: fixed;
bottom: 0;
width: 100%;
text-align: center;
color: #fff;
font-family: Arial;
font-size: 12px;
letter-spacing: 1px;
}
.login-code-img {
height: 40px;
padding-left: 12px;
}
:deep(.el-form-item) {
display: flex;
// --font-size: 14px;
margin-bottom: 13px;
}
:deep(.el-input .el-input__inner) {
color: #fff;
// background: yellow !important;
// border: 0px solid rgba(255, 255, 255, 0.3);
}
:deep(.el-input--large .el-input__wrapper) {
// padding: 1px 15px;
background-color: #163054;
// box-shadow: 0 0 0 0px #2261ba inset !important; /* 可选:修改边框颜色 */
box-shadow: 0px 2px 4px rgba(79, 151, 214, 0.33);
// border: 0px solid rgba(255, 255, 255, 0.3);
}
:deep(.el-input__inner) {
// background-color: rgba(22, 48, 84, 0.6);
}
</style>
...@@ -52,10 +52,10 @@ export default defineConfig({ ...@@ -52,10 +52,10 @@ export default defineConfig({
host: "0.0.0.0", host: "0.0.0.0",
port: 8080, port: 8080,
proxy: { proxy: {
"/api": { "/dev-api": {
target: "http://192.168.19.166:8081", target: "http://192.168.19.166:8081",
changeOrigin: true, changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ""), rewrite: (path) => path.replace(/^\/dev-api/, ""),
}, },
}, },
}, },
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment