Files
geo/apps/admin-web/src/main.ts
T
root 19527cdf42 feat(admin-web): proactively refresh access tokens before expiry
Track access token expires_at, dedupe concurrent refreshes, retry SSE on
401, and refresh on window focus/visibility so long-lived sessions stop
hitting the login redirect mid-task.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 16:48:15 +08:00

145 lines
2.3 KiB
TypeScript

import { createFromIconfontCN } from "@ant-design/icons-vue";
import { QueryClient, VueQueryPlugin } from "@tanstack/vue-query";
import { createApp } from "vue";
import {
Alert,
App as AntApp,
Avatar,
Badge,
Button,
Card,
Checkbox,
Col,
ConfigProvider,
DatePicker,
Descriptions,
Divider,
Drawer,
Dropdown,
Empty,
Form,
Input,
InputNumber,
Layout,
List,
Menu,
Modal,
Pagination,
Popconfirm,
Progress,
Radio,
Result,
Row,
Select,
Skeleton,
Space,
Spin,
Statistic,
Switch,
Steps,
Table,
Tabs,
Tag,
Tree,
TimePicker,
Tooltip,
Upload,
TreeSelect,
Popover,
Slider,
} from "ant-design-vue";
import App from "./App.vue";
import { i18n } from "./i18n";
import { subscribeAuthExpired } from "./lib/session";
import { router } from "./router";
import { pinia } from "./stores/pinia";
import "./styles.css";
import "ant-design-vue/dist/reset.css";
import select from "ant-design-vue/es/select";
import tree from "ant-design-vue/es/tree";
const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 30000,
refetchOnWindowFocus: false,
retry: false,
},
},
});
const app = createApp(App);
subscribeAuthExpired(() => {
const current = router.currentRoute.value;
if (current.name === "login") {
return;
}
void router.replace({
name: "login",
query: current.fullPath ? { redirect: current.fullPath } : undefined,
});
});
const IconFont = createFromIconfontCN({
// 需要替换为你自己真实项目的 js 地址,才能显示出你的 '#icon-line-global_undo'。
scriptUrl: "//at.alicdn.com/t/c/font_5154382_922oh81rh1.js",
});
app.component("IconFont", IconFont);
app.component("ATextarea", Input.TextArea);
[
Alert,
AntApp,
Avatar,
Badge,
Button,
Card,
Checkbox,
Col,
ConfigProvider,
DatePicker,
Descriptions,
Divider,
Drawer,
Dropdown,
Empty,
Form,
Input,
InputNumber,
Layout,
List,
Menu,
Modal,
Pagination,
Popconfirm,
Popover,
Progress,
Radio,
Result,
Row,
Select,
Skeleton,
Space,
Spin,
Statistic,
Switch,
Slider,
Steps,
Table,
Tabs,
Tag,
TimePicker,
Tooltip,
Tree,
TreeSelect,
Upload,
].forEach((component) => {
app.use(component);
});
app.use(i18n).use(pinia).use(router).use(VueQueryPlugin, { queryClient }).mount("#app");