支持登录
This commit is contained in:
@@ -25,12 +25,12 @@
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { KafkaClusterApi } from "@/utils/api";
|
||||
import { KafkaClusterApi, AuthApi } from "@/utils/api";
|
||||
import request from "@/utils/request";
|
||||
import { mapMutations, mapState } from "vuex";
|
||||
import { getClusterInfo } from "@/utils/local-cache";
|
||||
import notification from "ant-design-vue/lib/notification";
|
||||
import { CLUSTER } from "@/store/mutation-types";
|
||||
import {AUTH, CLUSTER} from "@/store/mutation-types";
|
||||
|
||||
export default {
|
||||
data() {
|
||||
@@ -39,24 +39,8 @@ export default {
|
||||
};
|
||||
},
|
||||
created() {
|
||||
const clusterInfo = getClusterInfo();
|
||||
if (!clusterInfo) {
|
||||
request({
|
||||
url: KafkaClusterApi.peekClusterInfo.url,
|
||||
method: KafkaClusterApi.peekClusterInfo.method,
|
||||
}).then((res) => {
|
||||
if (res.code == 0) {
|
||||
this.switchCluster(res.data);
|
||||
} else {
|
||||
notification.error({
|
||||
message: "error",
|
||||
description: res.msg,
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.switchCluster(clusterInfo);
|
||||
}
|
||||
this.intAuthState();
|
||||
this.initClusterInfo();
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
@@ -67,7 +51,40 @@ export default {
|
||||
methods: {
|
||||
...mapMutations({
|
||||
switchCluster: CLUSTER.SWITCH,
|
||||
enableAuth: AUTH.ENABLE,
|
||||
}),
|
||||
intAuthState() {
|
||||
request({
|
||||
url: AuthApi.enable.url,
|
||||
method: AuthApi.enable.method,
|
||||
}).then((res) => {
|
||||
const enable = res;
|
||||
this.enableAuth(enable);
|
||||
// if (!enable){
|
||||
// this.initClusterInfo();
|
||||
// }
|
||||
});
|
||||
},
|
||||
initClusterInfo() {
|
||||
const clusterInfo = getClusterInfo();
|
||||
if (!clusterInfo) {
|
||||
request({
|
||||
url: KafkaClusterApi.peekClusterInfo.url,
|
||||
method: KafkaClusterApi.peekClusterInfo.method,
|
||||
}).then((res) => {
|
||||
if (res.code == 0) {
|
||||
this.switchCluster(res.data);
|
||||
} else {
|
||||
notification.error({
|
||||
message: "error",
|
||||
description: res.msg,
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.switchCluster(clusterInfo);
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import Vue from "vue";
|
||||
import VueRouter from "vue-router";
|
||||
import Home from "../views/Home.vue";
|
||||
import Store from "@/store";
|
||||
|
||||
Vue.use(VueRouter);
|
||||
|
||||
@@ -53,13 +54,21 @@ const routes = [
|
||||
path: "/client-quota-page",
|
||||
name: "ClientQuota",
|
||||
component: () =>
|
||||
import(/* webpackChunkName: "cluster" */ "../views/quota/ClientQuota.vue"),
|
||||
import(
|
||||
/* webpackChunkName: "cluster" */ "../views/quota/ClientQuota.vue"
|
||||
),
|
||||
},
|
||||
{
|
||||
path: "/user-page",
|
||||
name: "UserManage",
|
||||
component: () =>
|
||||
import(/* webpackChunkName: "cluster" */ "../views/user/UserManage.vue"),
|
||||
import(/* webpackChunkName: "cluster" */ "../views/user/UserManage.vue"),
|
||||
},
|
||||
{
|
||||
path: "/login-page",
|
||||
name: "Login",
|
||||
component: () =>
|
||||
import(/* webpackChunkName: "cluster" */ "../views/login/Login.vue"),
|
||||
},
|
||||
];
|
||||
|
||||
@@ -70,4 +79,49 @@ const router = new VueRouter({
|
||||
routes,
|
||||
});
|
||||
|
||||
router.beforeEach((to, from, next) => {
|
||||
const enableAuth = Store.state.auth.enable;
|
||||
if (!enableAuth) {
|
||||
next();
|
||||
} else {
|
||||
if (to.path === "/login-page") {
|
||||
next();
|
||||
} else {
|
||||
let token = localStorage.getItem("access_token");
|
||||
if (token === null || token === "") {
|
||||
next("/login-page");
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let originPush = VueRouter.prototype.push;
|
||||
let originReplace = VueRouter.prototype.replace;
|
||||
VueRouter.prototype.push = function (location, resolve, reject) {
|
||||
if (resolve && reject) {
|
||||
originPush.call(this, location, resolve, reject);
|
||||
} else {
|
||||
originPush.call(
|
||||
this,
|
||||
location,
|
||||
() => {},
|
||||
() => {}
|
||||
);
|
||||
}
|
||||
};
|
||||
VueRouter.prototype.replace = function (location, resolve, reject) {
|
||||
if (resolve && reject) {
|
||||
originReplace.call(this, location, resolve, reject);
|
||||
} else {
|
||||
originReplace.call(
|
||||
this,
|
||||
location,
|
||||
() => {},
|
||||
() => {}
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default router;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import Vue from "vue";
|
||||
import Vuex from "vuex";
|
||||
import { CLUSTER } from "@/store/mutation-types";
|
||||
import { CLUSTER, AUTH } from "@/store/mutation-types";
|
||||
import { setClusterInfo } from "@/utils/local-cache";
|
||||
|
||||
Vue.use(Vuex);
|
||||
@@ -12,6 +12,9 @@ export default new Vuex.Store({
|
||||
clusterName: undefined,
|
||||
enableSasl: false,
|
||||
},
|
||||
auth: {
|
||||
enable: false,
|
||||
},
|
||||
},
|
||||
mutations: {
|
||||
[CLUSTER.SWITCH](state, clusterInfo) {
|
||||
@@ -28,6 +31,12 @@ export default new Vuex.Store({
|
||||
state.clusterInfo.enableSasl = enableSasl;
|
||||
setClusterInfo(clusterInfo);
|
||||
},
|
||||
[AUTH.ENABLE](state, enable) {
|
||||
state.auth.enable = enable;
|
||||
},
|
||||
[AUTH.SET](state, info) {
|
||||
localStorage.setItem("access_token", info);
|
||||
},
|
||||
},
|
||||
actions: {},
|
||||
modules: {},
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
export const CLUSTER = {
|
||||
SWITCH: "switchCluster",
|
||||
};
|
||||
|
||||
export const AUTH = {
|
||||
ENABLE: "enable",
|
||||
SET: "setToken",
|
||||
};
|
||||
|
||||
@@ -346,4 +346,15 @@ export const UserManageApi = {
|
||||
url: "/sys/user/manage/user/password",
|
||||
method: "post",
|
||||
},
|
||||
};
|
||||
|
||||
export const AuthApi = {
|
||||
enable: {
|
||||
url: "/auth/enable",
|
||||
method: "get",
|
||||
},
|
||||
login: {
|
||||
url: "/auth/login",
|
||||
method: "post",
|
||||
},
|
||||
};
|
||||
@@ -2,7 +2,7 @@ import axios from "axios";
|
||||
import notification from "ant-design-vue/es/notification";
|
||||
import { VueAxios } from "./axios";
|
||||
import { getClusterInfo } from "@/utils/local-cache";
|
||||
|
||||
import Router from "@/router";
|
||||
// 创建 axios 实例
|
||||
const request = axios.create({
|
||||
// API 请求的默认前缀
|
||||
@@ -10,14 +10,24 @@ const request = axios.create({
|
||||
timeout: 120000, // 请求超时时间
|
||||
});
|
||||
|
||||
// axios.defaults.headers.common['X-Auth-Token'] = localStorage.getItem('access_token');
|
||||
|
||||
// 异常拦截处理器
|
||||
const errorHandler = (error) => {
|
||||
if (error.response) {
|
||||
const data = error.response.data;
|
||||
notification.error({
|
||||
message: error.response.status,
|
||||
description: JSON.stringify(data),
|
||||
});
|
||||
if (error.response.status == 401) {
|
||||
notification.error({
|
||||
message: error.response.status,
|
||||
description: "请登录",
|
||||
});
|
||||
Router.push({ path: "/login-page" });
|
||||
} else {
|
||||
const data = error.response.data;
|
||||
notification.error({
|
||||
message: error.response.status,
|
||||
description: JSON.stringify(data),
|
||||
});
|
||||
}
|
||||
}
|
||||
return Promise.reject(error);
|
||||
};
|
||||
@@ -29,6 +39,10 @@ request.interceptors.request.use((config) => {
|
||||
config.headers["X-Cluster-Info-Id"] = clusterInfo.id;
|
||||
// config.headers["X-Cluster-Info-Name"] = encodeURIComponent(clusterInfo.clusterName);
|
||||
}
|
||||
const token = localStorage.getItem('access_token')
|
||||
if (token) {
|
||||
config.headers["X-Auth-Token"] = token;
|
||||
}
|
||||
return config;
|
||||
}, errorHandler);
|
||||
|
||||
|
||||
103
ui/src/views/login/Login.vue
Normal file
103
ui/src/views/login/Login.vue
Normal file
@@ -0,0 +1,103 @@
|
||||
<template>
|
||||
<a-form
|
||||
:form="form"
|
||||
:label-col="{ span: 5 }"
|
||||
:wrapper-col="{ span: 12 }"
|
||||
@submit="handleSubmit"
|
||||
class="login-box"
|
||||
>
|
||||
<h3 class="login-title">登录kafka-console-ui</h3>
|
||||
<a-form-item label="账号">
|
||||
<a-input
|
||||
style="width: 200px"
|
||||
allowClear
|
||||
v-decorator="[
|
||||
'username',
|
||||
{ rules: [{ required: true, message: '请输入账号' }] },
|
||||
]"
|
||||
>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
<a-form-item label="密码">
|
||||
<a-input-password
|
||||
style="width: 200px"
|
||||
v-decorator="[
|
||||
'password',
|
||||
{ rules: [{ required: true, message: '请输入密码' }] },
|
||||
]"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item :wrapper-col="{ span: 16, offset: 5 }">
|
||||
<a-button type="primary" @click="handleSubmit" :loading="loading"
|
||||
>登录</a-button
|
||||
>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import request from "@/utils/request";
|
||||
import {AuthApi} from "@/utils/api";
|
||||
import notification from "ant-design-vue/lib/notification";
|
||||
import {mapMutations} from "vuex";
|
||||
import {AUTH} from "@/store/mutation-types";
|
||||
|
||||
export default {
|
||||
name: "Login",
|
||||
data() {
|
||||
return {
|
||||
form: this.$form.createForm(this, { name: "login-form" }),
|
||||
loading: false,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
this.form.validateFields((err, values) => {
|
||||
if (!err) {
|
||||
this.loading = true;
|
||||
const params = Object.assign({}, values);
|
||||
request({
|
||||
url: AuthApi.login.url,
|
||||
method: AuthApi.login.method,
|
||||
data: params,
|
||||
}).then((res) => {
|
||||
this.loading = false;
|
||||
if (res.code == 0) {
|
||||
this.setToken(res.data.token);
|
||||
this.$router.push("/");
|
||||
} else {
|
||||
notification.error({
|
||||
message: "error",
|
||||
description: res.msg,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
...mapMutations({
|
||||
setToken: AUTH.SET,
|
||||
}),
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.login-box {
|
||||
border: 1px solid #dcdfe6;
|
||||
width: 350px;
|
||||
height: 300px;
|
||||
margin: 120px auto;
|
||||
padding: 35px 35px 15px 35px;
|
||||
-webkit-border-radius: 5px;
|
||||
-moz-border-radius: 5px;
|
||||
box-shadow: 0 0 25px #909399;
|
||||
}
|
||||
|
||||
.login-title {
|
||||
text-align: center;
|
||||
margin: 0 auto 40px auto;
|
||||
color: #303133;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user