改进
This commit is contained in:
parent
a0c325cd97
commit
92da9181e1
4
.eslintignore
Normal file
4
.eslintignore
Normal file
@ -0,0 +1,4 @@
|
||||
node_modules
|
||||
dist
|
||||
out
|
||||
.gitignore
|
17
.eslintrc.cjs
Normal file
17
.eslintrc.cjs
Normal file
@ -0,0 +1,17 @@
|
||||
/* eslint-env node */
|
||||
require('@rushstack/eslint-patch/modern-module-resolution')
|
||||
|
||||
module.exports = {
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:vue/vue3-recommended',
|
||||
'@electron-toolkit',
|
||||
'@electron-toolkit/eslint-config-ts/eslint-recommended',
|
||||
'@vue/eslint-config-typescript/recommended',
|
||||
'@vue/eslint-config-prettier'
|
||||
],
|
||||
rules: {
|
||||
'vue/require-default-prop': 'off',
|
||||
'vue/multi-word-component-names': 'off'
|
||||
}
|
||||
}
|
7
openapitools.json
Normal file
7
openapitools.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"$schema": "./node_modules/@openapitools/openapi-generator-cli/config.schema.json",
|
||||
"spaces": 2,
|
||||
"generator-cli": {
|
||||
"version": "7.8.0"
|
||||
}
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
.gitignore
|
||||
.npmignore
|
||||
.openapi-generator-ignore
|
||||
api.ts
|
||||
base.ts
|
||||
common.ts
|
||||
|
4
src/components.d.ts
vendored
4
src/components.d.ts
vendored
@ -7,14 +7,14 @@ export {}
|
||||
/* prettier-ignore */
|
||||
declare module 'vue' {
|
||||
export interface GlobalComponents {
|
||||
AssistantMenu: typeof import('./components/AssistantMenu.vue')['default']
|
||||
Chat: typeof import('./components/chat/chat.vue')['default']
|
||||
ChatMenu: typeof import('./components/ChatMenu.vue')['default']
|
||||
Container: typeof import('./components/Container.vue')['default']
|
||||
copy: typeof import('./components/Menu copy.vue')['default']
|
||||
copy: typeof import('./components/AssistantMenu.vue')['default']
|
||||
Menu: typeof import('./components/Menu.vue')['default']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
Test: typeof import('./components/chat/test.vue')['default']
|
||||
UserMenu: typeof import('./components/UserMenu.vue')['default']
|
||||
}
|
||||
}
|
||||
|
41
src/components/AssistantMenu.vue
Normal file
41
src/components/AssistantMenu.vue
Normal file
@ -0,0 +1,41 @@
|
||||
<template>
|
||||
<n-list hoverable clickable>
|
||||
<template #header>
|
||||
<div>
|
||||
<span class="text-xl">切换助理</span>
|
||||
</div>
|
||||
</template>
|
||||
<n-list-item v-for="a in assistantStore.assistants" :key="a.id">
|
||||
<n-thing>
|
||||
{{ a.name }}
|
||||
</n-thing>
|
||||
</n-list-item>
|
||||
</n-list>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useRoute } from "vue-router";
|
||||
import { useUserStore } from "../stores/user";
|
||||
import { updateAll } from "../plugins/update/update";
|
||||
import { useAssistantStore } from "../stores/assistants";
|
||||
|
||||
const route = useRoute();
|
||||
const currentRoute: any = computed(() => route.name);
|
||||
const collapsed = ref(false);
|
||||
const userStore = useUserStore();
|
||||
const assistantStore = useAssistantStore();
|
||||
|
||||
watch(
|
||||
() => userStore.logined,
|
||||
(newValue, oldValue) => {
|
||||
if (newValue) {
|
||||
update();
|
||||
}
|
||||
}
|
||||
);
|
||||
function update() {
|
||||
updateAll();
|
||||
}
|
||||
|
||||
update();
|
||||
</script>
|
@ -8,8 +8,10 @@
|
||||
/> -->
|
||||
<n-list hoverable clickable>
|
||||
<template #header>
|
||||
<!-- <n-icon :component="ChatboxOutline" /> -->
|
||||
<span>对话列表</span>
|
||||
<div class="text-xl">
|
||||
<n-icon :component="ChatboxOutline" class="align-middle" />
|
||||
<span class="font-xl ml-2">对话列表</span>
|
||||
</div>
|
||||
</template>
|
||||
<n-list-item v-for="i in 10" :key="i">
|
||||
<n-thing> 对话 </n-thing>
|
||||
|
@ -5,7 +5,7 @@ import { useIsMobile } from "../utils/composables.js";
|
||||
import Menu from "../components/Menu.vue";
|
||||
import { useUserStore } from "../stores/user";
|
||||
import Guest from "../pages/guest/index.vue";
|
||||
import router from "../plugins/router";
|
||||
import router from "../router";
|
||||
const currentRoute = computed(() => router.currentRoute.value.name);
|
||||
|
||||
const userStore = useUserStore();
|
||||
|
@ -17,10 +17,28 @@
|
||||
</template>
|
||||
<Menu></Menu>
|
||||
</n-popover>
|
||||
|
||||
<!-- 更新状态 -->
|
||||
<div v-show="appStore.updating">正在更新数据</div>
|
||||
</n-grid-item>
|
||||
|
||||
<n-grid-item class="flex items-center justify-end mr-1.5">
|
||||
<!-- 右侧 -->
|
||||
<!-- 助理选择 -->
|
||||
<n-popover
|
||||
:placement="userPlacement"
|
||||
class="w-full"
|
||||
trigger="click"
|
||||
style="padding: 0"
|
||||
>
|
||||
<template #trigger>
|
||||
<n-icon class="text-2xl mr-4">
|
||||
<PersonOutline />
|
||||
</n-icon>
|
||||
</template>
|
||||
<AssistantMenu class="select-none" />
|
||||
</n-popover>
|
||||
<!-- 用户弹出 -->
|
||||
<n-popover
|
||||
:placement="userPlacement"
|
||||
class="w-full"
|
||||
@ -45,16 +63,18 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import UserMenu from "../components/UserMenu.vue";
|
||||
import AssistantMenu from "../components/AssistantMenu.vue";
|
||||
import { useAppStore } from "../stores/app";
|
||||
import { useUserStore } from "../stores/user";
|
||||
import { useIsMobile, useIsTablet } from "../utils/composables";
|
||||
import { MenuOutline } from "@vicons/ionicons5";
|
||||
import { MenuOutline, PersonOutline } from "@vicons/ionicons5";
|
||||
const userStore = useUserStore();
|
||||
const isMobile = useIsMobile();
|
||||
const isTablet = useIsTablet();
|
||||
const appStore = useAppStore();
|
||||
|
||||
const userPlacement = ref("bottom");
|
||||
if (isMobile.value) {
|
||||
userPlacement.value = "bottom";
|
||||
}
|
||||
|
||||
</script>
|
||||
|
21
src/main.ts
21
src/main.ts
@ -1,30 +1,23 @@
|
||||
console.log("load")
|
||||
const meta = document.createElement("meta");
|
||||
meta.name = "naive-ui-style";
|
||||
document.head.appendChild(meta);
|
||||
|
||||
import "./style.css";
|
||||
import { registerPlugins } from "./plugins";
|
||||
import router from "./router";
|
||||
|
||||
import { createApp } from "vue";
|
||||
import { createPinia } from "pinia";
|
||||
import piniaPluginPersistedstate from "pinia-plugin-persistedstate";
|
||||
import naive from "naive-ui";
|
||||
// 通用字体
|
||||
import "vfonts/Lato.css";
|
||||
// 等宽字体
|
||||
import "vfonts/FiraCode.css";
|
||||
|
||||
import App from "./App.vue";
|
||||
import router from "./plugins/router";
|
||||
|
||||
const pinia = createPinia();
|
||||
pinia.use(piniaPluginPersistedstate);
|
||||
import { createApp } from "vue";
|
||||
|
||||
const app = createApp(App);
|
||||
|
||||
app.use(pinia);
|
||||
app.use(naive);
|
||||
|
||||
registerPlugins(app);
|
||||
app.use(router);
|
||||
|
||||
|
||||
// @ts-ignore ...
|
||||
if (process.env.NODE_ENV === "production") {
|
||||
setTimeout(() => {
|
||||
|
@ -7,7 +7,7 @@
|
||||
<script setup lang="ts">
|
||||
import axios from "axios";
|
||||
import { useUserStore } from "../../stores/user";
|
||||
import router from "../../plugins/router";
|
||||
import router from "../../router";
|
||||
import config from "../../config/config";
|
||||
|
||||
const userStore = useUserStore();
|
||||
|
@ -8,7 +8,7 @@
|
||||
import config from "../../config/config";
|
||||
import axios from "axios";
|
||||
import { useUserStore } from "../../stores/user";
|
||||
import router from "../../plugins/router";
|
||||
import router from "../../router";
|
||||
const userStore = useUserStore();
|
||||
|
||||
function generateRandomString(length: number) {
|
||||
|
@ -14,7 +14,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import router from "../../plugins/router";
|
||||
import router from "../../router";
|
||||
import { useUserStore } from "../../stores/user";
|
||||
const userStore = useUserStore();
|
||||
|
||||
|
@ -15,7 +15,6 @@
|
||||
:text="text"
|
||||
@input="handleInput"
|
||||
height="500px"
|
||||
|
||||
></v-md-preview>
|
||||
</div>
|
||||
</div>
|
||||
@ -24,20 +23,18 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted, onUnmounted, watch } from "vue";
|
||||
|
||||
|
||||
import VMdPreview from '@kangc/v-md-editor/lib/preview';
|
||||
import '@kangc/v-md-editor/lib/style/preview.css';
|
||||
import githubTheme from '@kangc/v-md-editor/lib/theme/github.js';
|
||||
import '@kangc/v-md-editor/lib/theme/style/github.css';
|
||||
import VMdPreview from "@kangc/v-md-editor/lib/preview";
|
||||
import "@kangc/v-md-editor/lib/style/preview.css";
|
||||
import githubTheme from "@kangc/v-md-editor/lib/theme/github.js";
|
||||
import "@kangc/v-md-editor/lib/theme/style/github.css";
|
||||
|
||||
// highlightjs
|
||||
import hljs from 'highlight.js';
|
||||
import hljs from "highlight.js";
|
||||
|
||||
VMdPreview.use(githubTheme, {
|
||||
Hljs: hljs,
|
||||
});
|
||||
|
||||
|
||||
const text = ref("text");
|
||||
const textLength = 10; // 每次生成的文本长度
|
||||
const textParts = ref<string[]>([]);
|
||||
@ -59,10 +56,10 @@ onMounted(() => {
|
||||
updateTextParts();
|
||||
|
||||
// 随机生成字符串到 text.value
|
||||
// setInterval(() => {
|
||||
// const randomString = Math.random().toString(36).substring(2, 2 + textLength);
|
||||
// text.value += randomString;
|
||||
// }, 1000);
|
||||
// setInterval(() => {
|
||||
// const randomString = Math.random().toString(36).substring(2, 2 + textLength);
|
||||
// text.value += randomString;
|
||||
// }, 1000);
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
|
@ -1,36 +1,57 @@
|
||||
// import {
|
||||
// AssistantApi,
|
||||
// ChatApi,
|
||||
// ChatMessageApi,
|
||||
// ChatPublicApi,
|
||||
// Configuration,
|
||||
// PingApi,
|
||||
// ToolApi,
|
||||
// } from "@/api";
|
||||
// import config from "@/config/config";
|
||||
// import { useUserStore } from "@/stores/user";
|
||||
//
|
||||
// const userStore = useUserStore();
|
||||
//
|
||||
// const conf = new Configuration();
|
||||
//
|
||||
// conf.basePath = config.backend;
|
||||
// conf.apiKey = () => {
|
||||
// return "Bearer " + userStore.id_token;
|
||||
// };
|
||||
import {
|
||||
AssistantApi,
|
||||
ChatApi,
|
||||
ChatMessageApi,
|
||||
ChatPublicApi,
|
||||
Configuration,
|
||||
PingApi,
|
||||
ToolApi,
|
||||
} from "../api";
|
||||
import config from "../config/config";
|
||||
|
||||
// userStore.$subscribe((mutation, state) => {
|
||||
// console.log(mutation);
|
||||
// conf.apiKey = "Bearer " + state.id_token;
|
||||
// });
|
||||
import { useUserStore } from "../stores/user";
|
||||
import axios from "./axios";
|
||||
|
||||
// const api = {
|
||||
// Chat: new ChatApi(conf),
|
||||
// Assistant: new AssistantApi(conf),
|
||||
// Ping: new PingApi(conf),
|
||||
// Tool: new ToolApi(conf),
|
||||
// ChatMessage: new ChatMessageApi(conf),
|
||||
// ChatPublic: new ChatPublicApi(conf),
|
||||
// };
|
||||
//
|
||||
// export { api, conf };
|
||||
// 定义 Api 类型
|
||||
interface Api {
|
||||
Chat: ChatApi;
|
||||
Assistant: AssistantApi;
|
||||
Ping: PingApi;
|
||||
Tool: ToolApi;
|
||||
ChatMessage: ChatMessageApi;
|
||||
ChatPublic: ChatPublicApi;
|
||||
}
|
||||
|
||||
let api: Api | null = null; // 使用联合类型来表示初始状态可能是 null
|
||||
|
||||
const getApi = () => {
|
||||
if (api) {
|
||||
return api;
|
||||
}
|
||||
|
||||
const userStore = useUserStore();
|
||||
|
||||
const conf = new Configuration();
|
||||
|
||||
conf.basePath = config.backend;
|
||||
conf.apiKey = () => {
|
||||
return "Bearer " + userStore.id_token;
|
||||
};
|
||||
|
||||
userStore.$subscribe((mutation, state) => {
|
||||
conf.apiKey = "Bearer " + state.id_token;
|
||||
});
|
||||
|
||||
api = {
|
||||
Chat: new ChatApi(conf, undefined, axios),
|
||||
Assistant: new AssistantApi(conf, undefined, axios),
|
||||
Ping: new PingApi(conf, undefined, axios),
|
||||
Tool: new ToolApi(conf, undefined, axios),
|
||||
ChatMessage: new ChatMessageApi(conf, undefined, axios),
|
||||
ChatPublic: new ChatPublicApi(conf, undefined, axios),
|
||||
};
|
||||
|
||||
return api;
|
||||
};
|
||||
|
||||
export default getApi;
|
||||
|
@ -1,5 +1,10 @@
|
||||
import axios from 'axios'
|
||||
|
||||
import { request, response } from "./httpInterceptors";
|
||||
|
||||
axios.interceptors.request.use(request.onFulfilled, request.onRejected)
|
||||
axios.interceptors.response.use(response.onFulfilled, response.onRejected)
|
||||
|
||||
// axios.defaults.adapter = window.axiosHttpAdapter
|
||||
|
||||
export default axios
|
||||
|
71
src/plugins/httpInterceptors.ts
Normal file
71
src/plugins/httpInterceptors.ts
Normal file
@ -0,0 +1,71 @@
|
||||
import { useUserStore } from "../stores/user";
|
||||
import { h, computed } from "vue";
|
||||
import { createDiscreteApi, darkTheme, lightTheme, useOsTheme } from "naive-ui";
|
||||
import type { ConfigProviderProps } from "naive-ui";
|
||||
|
||||
const osThemeRef = useOsTheme();
|
||||
|
||||
const configProviderPropsRef = computed<ConfigProviderProps>(() => ({
|
||||
theme: osThemeRef.value === "light" ? lightTheme : darkTheme,
|
||||
}));
|
||||
const { dialog, loadingBar } = createDiscreteApi(
|
||||
["message", "dialog", "notification", "loadingBar", "modal"],
|
||||
{
|
||||
configProviderProps: configProviderPropsRef,
|
||||
}
|
||||
);
|
||||
|
||||
const request = {
|
||||
onFulfilled: (config: any) => {
|
||||
if (config.headers === undefined) {
|
||||
config.headers = {};
|
||||
}
|
||||
|
||||
loadingBar.start();
|
||||
|
||||
return Promise.resolve(config);
|
||||
},
|
||||
onRejected: (error: any) => {
|
||||
console.error(error);
|
||||
|
||||
// loadingBar.error()
|
||||
|
||||
return Promise.reject(error);
|
||||
},
|
||||
};
|
||||
|
||||
const response = {
|
||||
onFulfilled: (res: any) => {
|
||||
// if 20x
|
||||
if (res.status >= 200 && res.status < 300) {
|
||||
loadingBar.finish();
|
||||
} else if (res.status >= 400 && res.status < 600) {
|
||||
loadingBar.error();
|
||||
}
|
||||
|
||||
return Promise.resolve(res);
|
||||
},
|
||||
onRejected: (error: any) => {
|
||||
loadingBar.error();
|
||||
|
||||
console.error("axios error", error);
|
||||
|
||||
let data = [];
|
||||
|
||||
if (error.response.data.data) {
|
||||
data = error.response.data.data;
|
||||
}
|
||||
|
||||
if (error.response.data.message) {
|
||||
data = error.response.data.message;
|
||||
}
|
||||
|
||||
if (error.response.data.error) {
|
||||
data = error.response.data.error.message;
|
||||
}
|
||||
|
||||
return Promise.reject(error);
|
||||
},
|
||||
};
|
||||
|
||||
export { request, response };
|
13
src/plugins/index.ts
Normal file
13
src/plugins/index.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import pinia from "../stores";
|
||||
import naive from "naive-ui";
|
||||
|
||||
// Types
|
||||
import type { App } from "vue";
|
||||
// 通用字体
|
||||
import "vfonts/Lato.css";
|
||||
// 等宽字体
|
||||
import "vfonts/FiraCode.css";
|
||||
|
||||
export function registerPlugins(app: App) {
|
||||
app.use(naive).use(pinia);
|
||||
}
|
14
src/plugins/update/update.ts
Normal file
14
src/plugins/update/update.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { useAssistantStore } from "../../stores/assistants";
|
||||
import api from "../../plugins/api";
|
||||
import { useUserStore } from "../../stores/user";
|
||||
|
||||
const updateAll = async () => {
|
||||
// 更新所有的数据
|
||||
const userStore = useUserStore();
|
||||
const assistantStore = useAssistantStore();
|
||||
|
||||
const assistantList = await api().Assistant.apiV1AssistantsGet();
|
||||
assistantStore.assistants = assistantList.data.data;
|
||||
};
|
||||
|
||||
export { updateAll };
|
@ -4,28 +4,6 @@ import { defineStore } from "pinia";
|
||||
export const useAppStore = defineStore("app", {
|
||||
persist: false,
|
||||
state: () => ({
|
||||
navigation_drawer: false,
|
||||
navigation_items: [
|
||||
{
|
||||
icon: "mdi-home",
|
||||
text: "主页",
|
||||
to: "/",
|
||||
},
|
||||
{
|
||||
icon: "mdi-assistant",
|
||||
text: "助理",
|
||||
to: "/assistants",
|
||||
},
|
||||
{
|
||||
icon: "mdi-tools",
|
||||
text: "工具",
|
||||
to: "/tools",
|
||||
},
|
||||
{
|
||||
icon: "mdi-key",
|
||||
text: "令牌",
|
||||
to: "/tokens",
|
||||
},
|
||||
],
|
||||
updating: false,
|
||||
}),
|
||||
});
|
||||
|
10
src/stores/assistants.ts
Normal file
10
src/stores/assistants.ts
Normal file
@ -0,0 +1,10 @@
|
||||
// Utilities
|
||||
import { defineStore } from "pinia";
|
||||
import { EntityAssistant } from "../api";
|
||||
|
||||
export const useAssistantStore = defineStore("assistant", {
|
||||
persist: false,
|
||||
state: () => ({
|
||||
assistants: <EntityAssistant[] | undefined> [],
|
||||
}),
|
||||
});
|
9
src/stores/chat.ts
Normal file
9
src/stores/chat.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { defineStore } from "pinia";
|
||||
import { EntityChat } from "../api";
|
||||
|
||||
export const useChatStore = defineStore("chats", {
|
||||
persist: false,
|
||||
state: () => ({
|
||||
chats: <EntityChat[] | undefined>[],
|
||||
}),
|
||||
});
|
15
src/stores/index.ts
Normal file
15
src/stores/index.ts
Normal file
@ -0,0 +1,15 @@
|
||||
// Utilities
|
||||
import { createPinia, setActivePinia } from "pinia";
|
||||
|
||||
import piniaPluginPersistedstate from "pinia-plugin-persistedstate";
|
||||
|
||||
const pinia = createPinia();
|
||||
|
||||
pinia.use(piniaPluginPersistedstate);
|
||||
|
||||
// console
|
||||
|
||||
// 设置当前活跃的 Pinia 实例
|
||||
// setActivePinia(pinia);
|
||||
|
||||
export default pinia;
|
@ -4,93 +4,101 @@ import config from "../config/config";
|
||||
import { Base64 } from "js-base64";
|
||||
|
||||
let timer: any = null;
|
||||
export const useUserStore = () => {
|
||||
const innerStore = defineStore("user", {
|
||||
persist: true,
|
||||
state: () => ({
|
||||
logined: false,
|
||||
id_token: "",
|
||||
refresh_token: "",
|
||||
access_token: "",
|
||||
expired_at: 0,
|
||||
user: {
|
||||
id: 0,
|
||||
name: "",
|
||||
email: "",
|
||||
avatar: "",
|
||||
},
|
||||
timer: 0,
|
||||
}),
|
||||
actions: {
|
||||
login(
|
||||
idToken: string,
|
||||
accessToken: string,
|
||||
refreshToken: string,
|
||||
expiredAt: number
|
||||
) {
|
||||
const idTokenParts = idToken.split(".");
|
||||
|
||||
export const useUserStore = defineStore("user", {
|
||||
persist: true,
|
||||
state: () => ({
|
||||
logined: false,
|
||||
id_token: "",
|
||||
refresh_token: "",
|
||||
access_token: "",
|
||||
expired_at: 0,
|
||||
user: {
|
||||
id: 0,
|
||||
name: "",
|
||||
email: "",
|
||||
avatar: "",
|
||||
},
|
||||
timer: 0,
|
||||
}),
|
||||
actions: {
|
||||
login(
|
||||
idToken: string,
|
||||
accessToken: string,
|
||||
refreshToken: string,
|
||||
expiredAt: number
|
||||
) {
|
||||
const idTokenParts = idToken.split(".");
|
||||
const idTokenPayload = JSON.parse(Base64.decode(idTokenParts[1]));
|
||||
|
||||
const idTokenPayload = JSON.parse(Base64.decode(idTokenParts[1]));
|
||||
expiredAt = Date.now() + expiredAt * 1000;
|
||||
this.expired_at = expiredAt;
|
||||
|
||||
expiredAt = Date.now() + expiredAt * 1000;
|
||||
this.expired_at = expiredAt;
|
||||
this.refresh_token = refreshToken;
|
||||
this.access_token = accessToken;
|
||||
|
||||
this.refresh_token = refreshToken;
|
||||
this.access_token = accessToken;
|
||||
|
||||
this.id_token = idToken;
|
||||
this.user = { ...idTokenPayload };
|
||||
this.logined = true;
|
||||
},
|
||||
checkAndRefresh() {
|
||||
if (this.logined) {
|
||||
if (this.expired_at - Date.now() < 60000) {
|
||||
this.refresh();
|
||||
}
|
||||
}
|
||||
},
|
||||
setupTimer() {
|
||||
this.checkAndRefresh();
|
||||
timer = setInterval(() => {
|
||||
this.checkAndRefresh();
|
||||
}, 10 * 1000);
|
||||
},
|
||||
async refresh() {
|
||||
const discovery = await axios.get(config.oauth_discovery_url);
|
||||
|
||||
// post /oauth/token to refresh
|
||||
// 构建 form 参数
|
||||
const data = new URLSearchParams();
|
||||
data.set("grant_type", "refresh_token");
|
||||
data.set("refresh_token", this.refresh_token);
|
||||
data.set("client_id", config.oauth_client_id);
|
||||
data.set("scope", config.oauth_scope);
|
||||
|
||||
axios
|
||||
.post(discovery.data.token_endpoint, data)
|
||||
.then((response) => {
|
||||
this.login(
|
||||
response.data.id_token,
|
||||
response.data.access_token,
|
||||
response.data.refresh_token,
|
||||
response.data.expires_in
|
||||
);
|
||||
})
|
||||
.catch((error) => {
|
||||
// if 401
|
||||
if (error.response.status === 401) {
|
||||
console.log("Refresh token failed");
|
||||
this.id_token = idToken;
|
||||
this.user = { ...idTokenPayload };
|
||||
this.logined = true;
|
||||
},
|
||||
checkAndRefresh() {
|
||||
if (this.logined) {
|
||||
if (this.expired_at - Date.now() < 60000) {
|
||||
this.refresh();
|
||||
}
|
||||
// logout
|
||||
this.logout();
|
||||
clearInterval(timer);
|
||||
});
|
||||
}
|
||||
},
|
||||
setupTimer() {
|
||||
this.checkAndRefresh();
|
||||
timer = setInterval(() => {
|
||||
this.checkAndRefresh();
|
||||
}, 10 * 1000);
|
||||
},
|
||||
async refresh() {
|
||||
const discovery = await axios.get(config.oauth_discovery_url);
|
||||
|
||||
// post /oauth/token to refresh
|
||||
// 构建 form 参数
|
||||
const data = new URLSearchParams();
|
||||
data.set("grant_type", "refresh_token");
|
||||
data.set("refresh_token", this.refresh_token);
|
||||
data.set("client_id", config.oauth_client_id);
|
||||
data.set("scope", config.oauth_scope);
|
||||
|
||||
axios
|
||||
.post(discovery.data.token_endpoint, data)
|
||||
.then((response) => {
|
||||
this.login(
|
||||
response.data.id_token,
|
||||
response.data.access_token,
|
||||
response.data.refresh_token,
|
||||
response.data.expires_in
|
||||
);
|
||||
})
|
||||
.catch((error) => {
|
||||
// if 401
|
||||
if (error.response.status === 401) {
|
||||
console.log("Refresh token failed");
|
||||
}
|
||||
// logout
|
||||
this.logout();
|
||||
clearInterval(timer);
|
||||
});
|
||||
},
|
||||
logout() {
|
||||
this.$reset();
|
||||
this.user = this.$state.user;
|
||||
this.id_token = this.$state.id_token;
|
||||
this.logined = this.$state.logined;
|
||||
},
|
||||
getIdToken() {
|
||||
return this.id_token;
|
||||
},
|
||||
},
|
||||
logout() {
|
||||
this.$reset();
|
||||
this.user = this.$state.user;
|
||||
this.id_token = this.$state.id_token;
|
||||
this.logined = this.$state.logined;
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
console.log("storage")
|
||||
|
||||
return innerStore()
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user