mirror of https://github.com/halo-dev/halo-admin
refactor: improve login-related logic (#617)
#### What type of PR is this? /kind improvement /milestone 2.0 #### What this PR does / why we need it: 适配 https://github.com/halo-dev/halo/pull/2453 1. 将生产构建的 base url 更改为 console 2. 优化登录之后跳转的逻辑。 #### Which issue(s) this PR fixes: #### Special notes for your reviewer: /cc @halo-dev/sig-halo-admin 测试方式: 1. 在本地根据此 PR 构建生产版本(pnpm build) 2. 根据 https://github.com/halo-dev/halo/pull/2453#issue-1381947867 中的描述修改配置文件。 3. 访问 http://localhost:8090/console #### Does this PR introduce a user-facing change? ```release-note None ```pull/615/head
parent
32356070e4
commit
539fd8fd14
|
@ -1,2 +1,2 @@
|
||||||
VITE_API_URL=
|
VITE_API_URL=
|
||||||
VITE_BASE_URL=/admin/
|
VITE_BASE_URL=/console/
|
||||||
|
|
|
@ -8,7 +8,7 @@ import type {
|
||||||
MenuItemType,
|
MenuItemType,
|
||||||
Plugin,
|
Plugin,
|
||||||
} from "@halo-dev/admin-shared";
|
} from "@halo-dev/admin-shared";
|
||||||
import { apiClient, setApiUrl } from "@/utils/api-client";
|
import { apiClient } from "@/utils/api-client";
|
||||||
import { menus, minimenus, registerMenu } from "./router/menus.config";
|
import { menus, minimenus, registerMenu } from "./router/menus.config";
|
||||||
// setup
|
// setup
|
||||||
import "./setup/setupStyles";
|
import "./setup/setupStyles";
|
||||||
|
@ -24,7 +24,6 @@ import { useRoleStore } from "@/stores/role";
|
||||||
const app = createApp(App);
|
const app = createApp(App);
|
||||||
|
|
||||||
setupComponents(app);
|
setupComponents(app);
|
||||||
setApiUrl(import.meta.env.VITE_API_URL);
|
|
||||||
|
|
||||||
app.use(createPinia());
|
app.use(createPinia());
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,8 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import {
|
import { IconShieldUser, IconUserLine, VButton } from "@halo-dev/components";
|
||||||
IconShieldUser,
|
|
||||||
IconUserSettings,
|
|
||||||
VButton,
|
|
||||||
} from "@halo-dev/components";
|
|
||||||
import { v4 as uuid } from "uuid";
|
import { v4 as uuid } from "uuid";
|
||||||
import qs from "qs";
|
import qs from "qs";
|
||||||
import logo from "../../../assets/logo.svg";
|
import logo from "@/assets/logo.svg";
|
||||||
import { onMounted, ref } from "vue";
|
import { onMounted, ref } from "vue";
|
||||||
import { submitForm } from "@formkit/vue";
|
import { submitForm } from "@formkit/vue";
|
||||||
import router from "@/router";
|
import router from "@/router";
|
||||||
|
@ -17,30 +13,22 @@ interface LoginForm {
|
||||||
password: string;
|
password: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface LoginFormState {
|
const loginForm = ref<LoginForm>({
|
||||||
logging: boolean;
|
_csrf: "",
|
||||||
state: LoginForm;
|
username: "",
|
||||||
}
|
password: "",
|
||||||
|
|
||||||
const loginForm = ref<LoginFormState>({
|
|
||||||
logging: false,
|
|
||||||
state: {
|
|
||||||
_csrf: "",
|
|
||||||
username: "ryanwang",
|
|
||||||
password: "12345678",
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
const loading = ref(false);
|
||||||
|
|
||||||
const handleGenerateToken = async () => {
|
const handleGenerateToken = async () => {
|
||||||
const token = uuid();
|
const token = uuid();
|
||||||
loginForm.value.state._csrf = token;
|
loginForm.value._csrf = token;
|
||||||
document.cookie = `XSRF-TOKEN=${token}; Path=/;`;
|
document.cookie = `XSRF-TOKEN=${token}; Path=/;`;
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleLogin = async () => {
|
const handleLogin = async () => {
|
||||||
try {
|
try {
|
||||||
loginForm.value.logging = true;
|
loading.value = true;
|
||||||
|
|
||||||
await fetch(`${import.meta.env.VITE_API_URL}/login`, {
|
await fetch(`${import.meta.env.VITE_API_URL}/login`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
|
@ -48,14 +36,14 @@ const handleLogin = async () => {
|
||||||
},
|
},
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
redirect: "manual",
|
redirect: "manual",
|
||||||
body: qs.stringify(loginForm.value.state),
|
body: qs.stringify(loginForm.value),
|
||||||
});
|
});
|
||||||
await router.push({ name: "Dashboard" });
|
await router.push({ name: "Dashboard" });
|
||||||
await router.go(0);
|
await router.go(0);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error("Failed to login", e);
|
||||||
} finally {
|
} finally {
|
||||||
loginForm.value.logging = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -66,13 +54,15 @@ onMounted(() => {
|
||||||
<template>
|
<template>
|
||||||
<div class="flex h-screen flex-col items-center justify-center">
|
<div class="flex h-screen flex-col items-center justify-center">
|
||||||
<img :src="logo" alt="Logo" class="mb-8 w-20" />
|
<img :src="logo" alt="Logo" class="mb-8 w-20" />
|
||||||
<div class="login-form w-72">
|
<div class="login-form flex w-72 flex-col gap-4">
|
||||||
<FormKit
|
<FormKit
|
||||||
id="login"
|
id="login-form"
|
||||||
v-model="loginForm.state"
|
v-model="loginForm"
|
||||||
:actions="false"
|
:actions="false"
|
||||||
type="form"
|
type="form"
|
||||||
|
:config="{ animation: 'none' }"
|
||||||
@submit="handleLogin"
|
@submit="handleLogin"
|
||||||
|
@keyup.enter="submitForm('login-form')"
|
||||||
>
|
>
|
||||||
<FormKit
|
<FormKit
|
||||||
:validation-messages="{
|
:validation-messages="{
|
||||||
|
@ -84,7 +74,7 @@ onMounted(() => {
|
||||||
validation="required"
|
validation="required"
|
||||||
>
|
>
|
||||||
<template #prefixIcon>
|
<template #prefixIcon>
|
||||||
<IconUserSettings />
|
<IconUserLine />
|
||||||
</template>
|
</template>
|
||||||
</FormKit>
|
</FormKit>
|
||||||
<FormKit
|
<FormKit
|
||||||
|
@ -100,10 +90,10 @@ onMounted(() => {
|
||||||
<IconShieldUser />
|
<IconShieldUser />
|
||||||
</template>
|
</template>
|
||||||
</FormKit>
|
</FormKit>
|
||||||
<VButton block type="secondary" @click="submitForm('login')">
|
|
||||||
登录
|
|
||||||
</VButton>
|
|
||||||
</FormKit>
|
</FormKit>
|
||||||
|
<VButton block type="secondary" @click="submitForm('login-form')">
|
||||||
|
登录
|
||||||
|
</VButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -32,95 +32,101 @@ import {
|
||||||
} from "@halo-dev/api-client";
|
} from "@halo-dev/api-client";
|
||||||
import type { AxiosInstance } from "axios";
|
import type { AxiosInstance } from "axios";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
import router from "@/router";
|
||||||
|
|
||||||
|
const baseURL = import.meta.env.VITE_API_URL;
|
||||||
|
|
||||||
let apiUrl: string | undefined;
|
|
||||||
const axiosInstance = axios.create({
|
const axiosInstance = axios.create({
|
||||||
|
baseURL,
|
||||||
withCredentials: true,
|
withCredentials: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
let apiClient = setupApiClient(axiosInstance);
|
|
||||||
|
|
||||||
axiosInstance.interceptors.response.use(
|
axiosInstance.interceptors.response.use(
|
||||||
(response) => {
|
(response) => {
|
||||||
return response;
|
return response;
|
||||||
},
|
},
|
||||||
async (error) => {
|
async (error) => {
|
||||||
console.log("error", error);
|
|
||||||
if (error.response.status === 401) {
|
if (error.response.status === 401) {
|
||||||
window.location.href = "/#/login";
|
router.push({
|
||||||
|
name: "Login",
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const setApiUrl = (url: string) => {
|
const apiClient = setupApiClient(axiosInstance);
|
||||||
axiosInstance.defaults.baseURL = url;
|
|
||||||
apiUrl = url;
|
|
||||||
apiClient = setupApiClient(axiosInstance);
|
|
||||||
};
|
|
||||||
|
|
||||||
function setupApiClient(axios: AxiosInstance) {
|
function setupApiClient(axios: AxiosInstance) {
|
||||||
return {
|
return {
|
||||||
extension: {
|
extension: {
|
||||||
configMap: new V1alpha1ConfigMapApi(undefined, apiUrl, axios),
|
configMap: new V1alpha1ConfigMapApi(undefined, baseURL, axios),
|
||||||
personalAccessToken: new V1alpha1PersonalAccessTokenApi(
|
personalAccessToken: new V1alpha1PersonalAccessTokenApi(
|
||||||
undefined,
|
undefined,
|
||||||
apiUrl,
|
baseURL,
|
||||||
axios
|
axios
|
||||||
),
|
),
|
||||||
roleBinding: new V1alpha1RoleBindingApi(undefined, apiUrl, axios),
|
roleBinding: new V1alpha1RoleBindingApi(undefined, baseURL, axios),
|
||||||
role: new V1alpha1RoleApi(undefined, apiUrl, axios),
|
role: new V1alpha1RoleApi(undefined, baseURL, axios),
|
||||||
setting: new V1alpha1SettingApi(undefined, apiUrl, axios),
|
setting: new V1alpha1SettingApi(undefined, baseURL, axios),
|
||||||
reverseProxy: new PluginHaloRunV1alpha1ReverseProxyApi(
|
reverseProxy: new PluginHaloRunV1alpha1ReverseProxyApi(
|
||||||
undefined,
|
undefined,
|
||||||
apiUrl,
|
baseURL,
|
||||||
axios
|
axios
|
||||||
),
|
),
|
||||||
plugin: new PluginHaloRunV1alpha1PluginApi(undefined, apiUrl, axios),
|
plugin: new PluginHaloRunV1alpha1PluginApi(undefined, baseURL, axios),
|
||||||
user: new V1alpha1UserApi(undefined, apiUrl, axios),
|
user: new V1alpha1UserApi(undefined, baseURL, axios),
|
||||||
theme: new ThemeHaloRunV1alpha1ThemeApi(undefined, apiUrl, axios),
|
theme: new ThemeHaloRunV1alpha1ThemeApi(undefined, baseURL, axios),
|
||||||
menu: new V1alpha1MenuApi(undefined, apiUrl, axios),
|
menu: new V1alpha1MenuApi(undefined, baseURL, axios),
|
||||||
menuItem: new V1alpha1MenuItemApi(undefined, apiUrl, axios),
|
menuItem: new V1alpha1MenuItemApi(undefined, baseURL, axios),
|
||||||
post: new ContentHaloRunV1alpha1PostApi(undefined, apiUrl, axios),
|
post: new ContentHaloRunV1alpha1PostApi(undefined, baseURL, axios),
|
||||||
singlePage: new ContentHaloRunV1alpha1SinglePageApi(
|
singlePage: new ContentHaloRunV1alpha1SinglePageApi(
|
||||||
undefined,
|
undefined,
|
||||||
apiUrl,
|
baseURL,
|
||||||
axios
|
axios
|
||||||
),
|
),
|
||||||
category: new ContentHaloRunV1alpha1CategoryApi(undefined, apiUrl, axios),
|
category: new ContentHaloRunV1alpha1CategoryApi(
|
||||||
tag: new ContentHaloRunV1alpha1TagApi(undefined, apiUrl, axios),
|
undefined,
|
||||||
snapshot: new ContentHaloRunV1alpha1SnapshotApi(undefined, apiUrl, axios),
|
baseURL,
|
||||||
comment: new ContentHaloRunV1alpha1CommentApi(undefined, apiUrl, axios),
|
axios
|
||||||
reply: new ContentHaloRunV1alpha1ReplyApi(undefined, apiUrl, axios),
|
),
|
||||||
|
tag: new ContentHaloRunV1alpha1TagApi(undefined, baseURL, axios),
|
||||||
|
snapshot: new ContentHaloRunV1alpha1SnapshotApi(
|
||||||
|
undefined,
|
||||||
|
baseURL,
|
||||||
|
axios
|
||||||
|
),
|
||||||
|
comment: new ContentHaloRunV1alpha1CommentApi(undefined, baseURL, axios),
|
||||||
|
reply: new ContentHaloRunV1alpha1ReplyApi(undefined, baseURL, axios),
|
||||||
storage: {
|
storage: {
|
||||||
group: new StorageHaloRunV1alpha1GroupApi(undefined, apiUrl, axios),
|
group: new StorageHaloRunV1alpha1GroupApi(undefined, baseURL, axios),
|
||||||
attachment: new StorageHaloRunV1alpha1AttachmentApi(
|
attachment: new StorageHaloRunV1alpha1AttachmentApi(
|
||||||
undefined,
|
undefined,
|
||||||
apiUrl,
|
baseURL,
|
||||||
axios
|
axios
|
||||||
),
|
),
|
||||||
policy: new StorageHaloRunV1alpha1PolicyApi(undefined, apiUrl, axios),
|
policy: new StorageHaloRunV1alpha1PolicyApi(undefined, baseURL, axios),
|
||||||
policyTemplate: new StorageHaloRunV1alpha1PolicyTemplateApi(
|
policyTemplate: new StorageHaloRunV1alpha1PolicyTemplateApi(
|
||||||
undefined,
|
undefined,
|
||||||
apiUrl,
|
baseURL,
|
||||||
axios
|
axios
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// custom endpoints
|
// custom endpoints
|
||||||
user: new ApiConsoleHaloRunV1alpha1UserApi(undefined, apiUrl, axios),
|
user: new ApiConsoleHaloRunV1alpha1UserApi(undefined, baseURL, axios),
|
||||||
plugin: new ApiConsoleHaloRunV1alpha1PluginApi(undefined, apiUrl, axios),
|
plugin: new ApiConsoleHaloRunV1alpha1PluginApi(undefined, baseURL, axios),
|
||||||
theme: new ApiConsoleHaloRunV1alpha1ThemeApi(undefined, apiUrl, axios),
|
theme: new ApiConsoleHaloRunV1alpha1ThemeApi(undefined, baseURL, axios),
|
||||||
post: new ApiConsoleHaloRunV1alpha1PostApi(undefined, apiUrl, axios),
|
post: new ApiConsoleHaloRunV1alpha1PostApi(undefined, baseURL, axios),
|
||||||
singlePage: new ApiConsoleHaloRunV1alpha1SinglePageApi(
|
singlePage: new ApiConsoleHaloRunV1alpha1SinglePageApi(
|
||||||
undefined,
|
undefined,
|
||||||
apiUrl,
|
baseURL,
|
||||||
axios
|
axios
|
||||||
),
|
),
|
||||||
content: new ApiConsoleHaloRunV1alpha1ContentApi(undefined, apiUrl, axios),
|
content: new ApiConsoleHaloRunV1alpha1ContentApi(undefined, baseURL, axios),
|
||||||
comment: new ApiConsoleHaloRunV1alpha1CommentApi(undefined, apiUrl, axios),
|
comment: new ApiConsoleHaloRunV1alpha1CommentApi(undefined, baseURL, axios),
|
||||||
reply: new ApiConsoleHaloRunV1alpha1ReplyApi(undefined, apiUrl, axios),
|
reply: new ApiConsoleHaloRunV1alpha1ReplyApi(undefined, baseURL, axios),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export { apiClient, setApiUrl };
|
export { apiClient };
|
||||||
|
|
Loading…
Reference in New Issue