perf: improve the logic related to login expiration
parent
8e6c1abf19
commit
d62a3da009
|
@ -0,0 +1,23 @@
|
||||||
|
import type { Response } from 'express';
|
||||||
|
|
||||||
|
import { Controller, Get, Query, Res } from '@nestjs/common';
|
||||||
|
|
||||||
|
@Controller('mock')
|
||||||
|
export class MockController {
|
||||||
|
/**
|
||||||
|
* 用于模拟任意的状态码
|
||||||
|
* @param res
|
||||||
|
*/
|
||||||
|
@Get('status')
|
||||||
|
async mockAnyStatus(
|
||||||
|
@Res() res: Response,
|
||||||
|
@Query() { status }: { status: string },
|
||||||
|
) {
|
||||||
|
res.status(Number.parseInt(status, 10)).send({
|
||||||
|
code: 1,
|
||||||
|
data: null,
|
||||||
|
error: null,
|
||||||
|
message: `code is ${status}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,10 @@
|
||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
|
|
||||||
|
import { MockController } from './mock.controller';
|
||||||
import { MockService } from './mock.service';
|
import { MockService } from './mock.service';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
|
controllers: [MockController],
|
||||||
exports: [MockService],
|
exports: [MockService],
|
||||||
providers: [MockService],
|
providers: [MockService],
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
export * from './menu';
|
export * from './menu';
|
||||||
|
export * from './mock';
|
||||||
export * from './user';
|
export * from './user';
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
import { requestClient } from '#/forward';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模拟人意状态码
|
||||||
|
*/
|
||||||
|
async function getMockStatus(status: string) {
|
||||||
|
return requestClient.get('/mock/status', { params: { status } });
|
||||||
|
}
|
||||||
|
|
||||||
|
export { getMockStatus };
|
|
@ -1,23 +1,14 @@
|
||||||
/**
|
/**
|
||||||
* 该文件可自行根据业务逻辑进行调整
|
* 该文件可自行根据业务逻辑进行调整
|
||||||
*/
|
*/
|
||||||
|
import type { HttpResponse } from '@vben-core/request';
|
||||||
|
|
||||||
import type { AxiosResponse } from '@vben-core/request';
|
import { preferences } from '@vben-core/preferences';
|
||||||
|
import { RequestClient } from '@vben-core/request';
|
||||||
import { RequestClient, isCancelError } from '@vben-core/request';
|
|
||||||
import { useCoreAccessStore } from '@vben-core/stores';
|
|
||||||
|
|
||||||
import { message } from 'ant-design-vue';
|
import { message } from 'ant-design-vue';
|
||||||
|
|
||||||
interface HttpResponse<T = any> {
|
import { useAccessStore } from '#/store';
|
||||||
/**
|
|
||||||
* 0 表示成功 其他表示失败
|
|
||||||
* 0 means success, others means fail
|
|
||||||
*/
|
|
||||||
code: number;
|
|
||||||
data: T;
|
|
||||||
message: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建请求实例
|
* 创建请求实例
|
||||||
|
@ -29,59 +20,42 @@ function createRequestClient() {
|
||||||
// 为每个请求携带 Authorization
|
// 为每个请求携带 Authorization
|
||||||
makeAuthorization: () => {
|
makeAuthorization: () => {
|
||||||
return {
|
return {
|
||||||
handler: () => {
|
// 默认
|
||||||
// 这里不能用 useAccessStore,因为 useAccessStore 会导致循环引用
|
key: 'Authorization',
|
||||||
const accessStore = useCoreAccessStore();
|
tokenHandler: () => {
|
||||||
|
const accessStore = useAccessStore();
|
||||||
return {
|
return {
|
||||||
refreshToken: `Bearer ${accessStore.refreshToken}`,
|
refreshToken: `Bearer ${accessStore.refreshToken}`,
|
||||||
token: `Bearer ${accessStore.accessToken}`,
|
token: `Bearer ${accessStore.accessToken}`,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
// 默认
|
unAuthorizedHandler: async () => {
|
||||||
key: 'Authorization',
|
const accessStore = useAccessStore();
|
||||||
|
accessStore.setAccessToken(null);
|
||||||
|
|
||||||
|
if (preferences.app.loginExpiredMode === 'modal') {
|
||||||
|
accessStore.openLoginExpiredModal = true;
|
||||||
|
} else {
|
||||||
|
// 退出登录
|
||||||
|
await accessStore.logout();
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
makeErrorMessage: (msg) => message.error(msg),
|
||||||
|
});
|
||||||
|
client.addResponseInterceptor<HttpResponse>((response) => {
|
||||||
|
const { data: responseData, status } = response;
|
||||||
|
|
||||||
|
const { code, data, message: msg } = responseData;
|
||||||
|
if (status >= 200 && status < 400 && code === 0) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
throw new Error(msg);
|
||||||
});
|
});
|
||||||
setupRequestInterceptors(client);
|
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupRequestInterceptors(client: RequestClient) {
|
|
||||||
client.addResponseInterceptor(
|
|
||||||
(response: AxiosResponse<HttpResponse>) => {
|
|
||||||
const { data: responseData, status } = response;
|
|
||||||
|
|
||||||
const { code, data, message: msg } = responseData;
|
|
||||||
|
|
||||||
if (status >= 200 && status < 400 && code === 0) {
|
|
||||||
return data;
|
|
||||||
} else {
|
|
||||||
message.error(msg);
|
|
||||||
throw new Error(msg);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
(error: any) => {
|
|
||||||
if (isCancelError(error)) {
|
|
||||||
return Promise.reject(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
const err: string = error?.toString?.() ?? '';
|
|
||||||
let errMsg = '';
|
|
||||||
if (err?.includes('Network Error')) {
|
|
||||||
errMsg = '网络错误。';
|
|
||||||
} else if (error?.message?.includes?.('timeout')) {
|
|
||||||
errMsg = '请求超时。';
|
|
||||||
} else {
|
|
||||||
const data = error?.response?.data;
|
|
||||||
errMsg = (data?.message || data?.error?.message) ?? '';
|
|
||||||
}
|
|
||||||
|
|
||||||
message.error(errMsg);
|
|
||||||
return Promise.reject(error);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const requestClient = createRequestClient();
|
const requestClient = createRequestClient();
|
||||||
|
|
||||||
// 其他配置的请求方法
|
// 其他配置的请求方法
|
||||||
|
|
|
@ -6,11 +6,11 @@ import { LOGIN_PATH } from '@vben/constants';
|
||||||
import { IcRoundCreditScore, MdiDriveDocument, MdiGithub } from '@vben/icons';
|
import { IcRoundCreditScore, MdiDriveDocument, MdiGithub } from '@vben/icons';
|
||||||
import {
|
import {
|
||||||
BasicLayout,
|
BasicLayout,
|
||||||
LoginDialog,
|
|
||||||
Notification,
|
Notification,
|
||||||
NotificationItem,
|
NotificationItem,
|
||||||
UserDropdown,
|
UserDropdown,
|
||||||
} from '@vben/layouts';
|
} from '@vben/layouts';
|
||||||
|
import { AuthenticationLoginExpiredModal } from '@vben/universal-ui';
|
||||||
import { openWindow } from '@vben/utils';
|
import { openWindow } from '@vben/utils';
|
||||||
import { preferences } from '@vben-core/preferences';
|
import { preferences } from '@vben-core/preferences';
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ const menus = computed(() => [
|
||||||
|
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
const accessStore = useAccessStore();
|
const accessStore = useAccessStore();
|
||||||
const { showLoginDialog, userInfo } = toRefs(accessStore);
|
const { openLoginExpiredModal, userInfo } = toRefs(accessStore);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
async function handleLogout() {
|
async function handleLogout() {
|
||||||
|
@ -124,11 +124,11 @@ function handleMakeAll() {
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #dialog>
|
<template #dialog>
|
||||||
<LoginDialog
|
<AuthenticationLoginExpiredModal
|
||||||
:open="showLoginDialog"
|
v-model:open="openLoginExpiredModal"
|
||||||
password-placeholder="123456"
|
password-placeholder="123456"
|
||||||
username-placeholder="vben"
|
username-placeholder="vben"
|
||||||
@login="accessStore.authLogin"
|
@submit="accessStore.authLogin"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</BasicLayout>
|
</BasicLayout>
|
||||||
|
|
|
@ -28,7 +28,12 @@
|
||||||
"embedded": "Embedded",
|
"embedded": "Embedded",
|
||||||
"externalLink": "External Link"
|
"externalLink": "External Link"
|
||||||
},
|
},
|
||||||
"fallback": { "title": "Fallback Page" }
|
"fallback": { "title": "Fallback Page" },
|
||||||
|
"features": {
|
||||||
|
"title": "Features",
|
||||||
|
"hideChildrenInMenu": "Hide Menu Children",
|
||||||
|
"loginExpired": "Login Expired"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,11 @@
|
||||||
},
|
},
|
||||||
"fallback": {
|
"fallback": {
|
||||||
"title": "缺省页"
|
"title": "缺省页"
|
||||||
|
},
|
||||||
|
"features": {
|
||||||
|
"title": "功能",
|
||||||
|
"hideChildrenInMenu": "隐藏菜单子项",
|
||||||
|
"loginExpired": "登录过期"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,24 +93,9 @@ function setupAccessGuard(router: Router) {
|
||||||
// 生成路由表
|
// 生成路由表
|
||||||
// 当前登录用户拥有的角色标识列表
|
// 当前登录用户拥有的角色标识列表
|
||||||
let userRoles: string[] = [];
|
let userRoles: string[] = [];
|
||||||
try {
|
const userInfo =
|
||||||
const userInfo =
|
accessStore.userInfo || (await accessStore.fetchUserInfo());
|
||||||
accessStore.userInfo || (await accessStore.fetchUserInfo());
|
userRoles = userInfo.roles ?? [];
|
||||||
userRoles = userInfo.roles ?? [];
|
|
||||||
} catch (error: any) {
|
|
||||||
if (error.status === 409) {
|
|
||||||
accessStore.setShowLoginDialog(true);
|
|
||||||
} else if (error.status === 401) {
|
|
||||||
accessStore.reset();
|
|
||||||
return {
|
|
||||||
path: LOGIN_PATH,
|
|
||||||
// 如不需要,直接删除 query
|
|
||||||
query: { redirect: encodeURIComponent(to.fullPath) },
|
|
||||||
// 携带当前跳转的页面,登录后重新跳转该页面
|
|
||||||
replace: true,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 生成菜单和路由
|
// 生成菜单和路由
|
||||||
const { accessibleMenus, accessibleRoutes } = await generateAccess({
|
const { accessibleMenus, accessibleRoutes } = await generateAccess({
|
||||||
|
|
|
@ -125,6 +125,48 @@ const routes: RouteRecordRaw[] = [
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
meta: {
|
||||||
|
icon: 'mdi:feature-highlight',
|
||||||
|
title: $t('page.demos.features.title'),
|
||||||
|
},
|
||||||
|
name: 'Features',
|
||||||
|
path: '/features',
|
||||||
|
redirect: '/features/hide-menu-children',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
name: 'HideChildrenInMenuParent',
|
||||||
|
path: 'hide-children-in-menu',
|
||||||
|
component: () =>
|
||||||
|
import('#/views/demos/features/hide-menu-children/parent.vue'),
|
||||||
|
meta: {
|
||||||
|
hideChildrenInMenu: true,
|
||||||
|
icon: 'ic:round-menu',
|
||||||
|
title: 'page.demos.features.hideChildrenInMenu',
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
name: 'HideChildrenInMenuChildren',
|
||||||
|
path: 'hide-children-in-menu',
|
||||||
|
component: () =>
|
||||||
|
import(
|
||||||
|
'#/views/demos/features/hide-menu-children/children.vue'
|
||||||
|
),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'LoginExpired',
|
||||||
|
path: 'login-expired',
|
||||||
|
component: () =>
|
||||||
|
import('#/views/demos/features/login-expired/index.vue'),
|
||||||
|
meta: {
|
||||||
|
icon: 'mdi:encryption-expiration',
|
||||||
|
title: $t('page.demos.features.loginExpired'),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
meta: {
|
meta: {
|
||||||
icon: 'mdi:lightbulb-error-outline',
|
icon: 'mdi:lightbulb-error-outline',
|
||||||
|
|
|
@ -5,7 +5,7 @@ import type { RouteRecordRaw } from 'vue-router';
|
||||||
import { computed, ref } from 'vue';
|
import { computed, ref } from 'vue';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
|
|
||||||
import { DEFAULT_HOME_PATH } from '@vben/constants';
|
import { DEFAULT_HOME_PATH, LOGIN_PATH } from '@vben/constants';
|
||||||
import { useCoreAccessStore } from '@vben-core/stores';
|
import { useCoreAccessStore } from '@vben-core/stores';
|
||||||
|
|
||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
|
@ -17,12 +17,10 @@ export const useAccessStore = defineStore('access', () => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
|
|
||||||
const showLoginDialog = ref(false);
|
const openLoginExpiredModal = ref(false);
|
||||||
function setShowLoginDialog(value: boolean) {
|
|
||||||
showLoginDialog.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
const accessToken = computed(() => coreStoreAccess.accessToken);
|
const accessToken = computed(() => coreStoreAccess.accessToken);
|
||||||
|
const refreshToken = computed(() => coreStoreAccess.refreshToken);
|
||||||
const userRoles = computed(() => coreStoreAccess.userRoles);
|
const userRoles = computed(() => coreStoreAccess.userRoles);
|
||||||
const userInfo = computed(() => coreStoreAccess.userInfo);
|
const userInfo = computed(() => coreStoreAccess.userInfo);
|
||||||
const accessRoutes = computed(() => coreStoreAccess.accessRoutes);
|
const accessRoutes = computed(() => coreStoreAccess.accessRoutes);
|
||||||
|
@ -31,6 +29,10 @@ export const useAccessStore = defineStore('access', () => {
|
||||||
coreStoreAccess.setAccessMenus(menus);
|
coreStoreAccess.setAccessMenus(menus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setAccessToken(token: null | string) {
|
||||||
|
coreStoreAccess.setAccessToken(token);
|
||||||
|
}
|
||||||
|
|
||||||
function setAccessRoutes(routes: RouteRecordRaw[]) {
|
function setAccessRoutes(routes: RouteRecordRaw[]) {
|
||||||
coreStoreAccess.setAccessRoutes(routes);
|
coreStoreAccess.setAccessRoutes(routes);
|
||||||
}
|
}
|
||||||
|
@ -70,7 +72,7 @@ export const useAccessStore = defineStore('access', () => {
|
||||||
coreStoreAccess.setUserInfo(userInfo);
|
coreStoreAccess.setUserInfo(userInfo);
|
||||||
coreStoreAccess.setAccessCodes(accessCodes);
|
coreStoreAccess.setAccessCodes(accessCodes);
|
||||||
|
|
||||||
showLoginDialog.value = false;
|
openLoginExpiredModal.value = false;
|
||||||
onSuccess
|
onSuccess
|
||||||
? await onSuccess?.()
|
? await onSuccess?.()
|
||||||
: await router.push(userInfo.homePath || DEFAULT_HOME_PATH);
|
: await router.push(userInfo.homePath || DEFAULT_HOME_PATH);
|
||||||
|
@ -85,6 +87,19 @@ export const useAccessStore = defineStore('access', () => {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function logout() {
|
||||||
|
coreStoreAccess.$reset();
|
||||||
|
openLoginExpiredModal.value = false;
|
||||||
|
|
||||||
|
// 回登陆页带上当前路由地址
|
||||||
|
await router.replace({
|
||||||
|
path: LOGIN_PATH,
|
||||||
|
query: {
|
||||||
|
redirect: encodeURIComponent(router.currentRoute.value.fullPath),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
async function fetchUserInfo() {
|
async function fetchUserInfo() {
|
||||||
let userInfo: UserInfo | null = null;
|
let userInfo: UserInfo | null = null;
|
||||||
userInfo = await getUserInfo();
|
userInfo = await getUserInfo();
|
||||||
|
@ -102,11 +117,13 @@ export const useAccessStore = defineStore('access', () => {
|
||||||
authLogin,
|
authLogin,
|
||||||
fetchUserInfo,
|
fetchUserInfo,
|
||||||
loading,
|
loading,
|
||||||
|
logout,
|
||||||
|
openLoginExpiredModal,
|
||||||
|
refreshToken,
|
||||||
reset,
|
reset,
|
||||||
setAccessMenus,
|
setAccessMenus,
|
||||||
setAccessRoutes,
|
setAccessRoutes,
|
||||||
setShowLoginDialog,
|
setAccessToken,
|
||||||
showLoginDialog,
|
|
||||||
userInfo,
|
userInfo,
|
||||||
userRoles,
|
userRoles,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,16 +1,18 @@
|
||||||
import { useCoreAccessStore, useCoreTabbarStore } from '@vben-core/stores';
|
import { useCoreTabbarStore } from '@vben-core/stores';
|
||||||
|
|
||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
|
|
||||||
|
import { useAccessStore } from './access';
|
||||||
|
|
||||||
export const useAppStore = defineStore('app', () => {
|
export const useAppStore = defineStore('app', () => {
|
||||||
const coreStoreAccess = useCoreAccessStore();
|
const accessStore = useAccessStore();
|
||||||
const coreTabbarStore = useCoreTabbarStore();
|
const coreTabbarStore = useCoreTabbarStore();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 重置所有状态
|
* 重置所有状态
|
||||||
*/
|
*/
|
||||||
async function resetAppState() {
|
async function resetAppState() {
|
||||||
coreStoreAccess.$reset();
|
accessStore.$reset();
|
||||||
coreTabbarStore.$reset();
|
coreTabbarStore.$reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
<template>
|
||||||
|
<div>children</div>
|
||||||
|
</template>
|
|
@ -0,0 +1,13 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { Fallback } from '@vben/universal-ui';
|
||||||
|
|
||||||
|
defineOptions({ name: 'HideMenuChildren' });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Fallback
|
||||||
|
description="当前菜单子菜单不可见"
|
||||||
|
status="comming-soon"
|
||||||
|
title="隐藏子菜单"
|
||||||
|
/>
|
||||||
|
</template>
|
|
@ -0,0 +1,40 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { LoginExpiredModeType } from '@vben-core/preferences';
|
||||||
|
|
||||||
|
import { preferences, updatePreferences } from '@vben-core/preferences';
|
||||||
|
|
||||||
|
import { Button } from 'ant-design-vue';
|
||||||
|
|
||||||
|
import { getMockStatus } from '#/apis';
|
||||||
|
|
||||||
|
defineOptions({ name: 'LoginExpired' });
|
||||||
|
|
||||||
|
async function handleClick(type: LoginExpiredModeType) {
|
||||||
|
const loginExpiredMode = preferences.app.loginExpiredMode;
|
||||||
|
|
||||||
|
updatePreferences({ app: { loginExpiredMode: type } });
|
||||||
|
await getMockStatus('401');
|
||||||
|
updatePreferences({ app: { loginExpiredMode } });
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="p-5">
|
||||||
|
<div class="card-box p-5">
|
||||||
|
<h1 class="text-xl font-semibold">登录过期演示</h1>
|
||||||
|
<div class="text-foreground/80 mt-2">
|
||||||
|
401状态码转到登录页,登录成功后跳转回原页面。
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card-box mt-5 p-5 font-semibold">
|
||||||
|
<div class="mb-3 text-lg">跳转登录页面方式</div>
|
||||||
|
<Button type="primary" @click="handleClick('page')"> 点击触发 </Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card-box mt-5 p-5 font-semibold">
|
||||||
|
<div class="mb-3 text-lg">登录弹窗方式</div>
|
||||||
|
<Button type="primary" @click="handleClick('modal')"> 点击触发 </Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
|
@ -39,7 +39,7 @@
|
||||||
"eslint-config-prettier": "^9.1.0",
|
"eslint-config-prettier": "^9.1.0",
|
||||||
"eslint-plugin-eslint-comments": "^3.2.0",
|
"eslint-plugin-eslint-comments": "^3.2.0",
|
||||||
"eslint-plugin-i": "^2.29.1",
|
"eslint-plugin-i": "^2.29.1",
|
||||||
"eslint-plugin-jsdoc": "^48.6.0",
|
"eslint-plugin-jsdoc": "^48.7.0",
|
||||||
"eslint-plugin-jsonc": "^2.16.0",
|
"eslint-plugin-jsonc": "^2.16.0",
|
||||||
"eslint-plugin-n": "^17.9.0",
|
"eslint-plugin-n": "^17.9.0",
|
||||||
"eslint-plugin-no-only-tests": "^3.1.0",
|
"eslint-plugin-no-only-tests": "^3.1.0",
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
"nanoid": "^5.0.7",
|
"nanoid": "^5.0.7",
|
||||||
"pkg-types": "^1.1.3",
|
"pkg-types": "^1.1.3",
|
||||||
"prettier": "^3.3.2",
|
"prettier": "^3.3.2",
|
||||||
"rimraf": "^6.0.0",
|
"rimraf": "^6.0.1",
|
||||||
"zx": "^7.2.3"
|
"zx": "^7.2.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,12 +68,12 @@
|
||||||
"husky": "^9.0.11",
|
"husky": "^9.0.11",
|
||||||
"is-ci": "^3.0.1",
|
"is-ci": "^3.0.1",
|
||||||
"jsdom": "^24.1.0",
|
"jsdom": "^24.1.0",
|
||||||
"rimraf": "^6.0.0",
|
"rimraf": "^6.0.1",
|
||||||
"turbo": "^2.0.6",
|
"turbo": "^2.0.6",
|
||||||
"typescript": "^5.5.3",
|
"typescript": "^5.5.3",
|
||||||
"unbuild": "^2.0.0",
|
"unbuild": "^2.0.0",
|
||||||
"vite": "^5.3.3",
|
"vite": "^5.3.3",
|
||||||
"vitest": "^2.0.1",
|
"vitest": "^2.0.2",
|
||||||
"vue-tsc": "^2.0.26"
|
"vue-tsc": "^2.0.26"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|
|
@ -16,6 +16,7 @@ const defaultPreferences: Preferences = {
|
||||||
isMobile: false,
|
isMobile: false,
|
||||||
layout: 'sidebar-nav',
|
layout: 'sidebar-nav',
|
||||||
locale: 'zh-CN',
|
locale: 'zh-CN',
|
||||||
|
loginExpiredMode: 'page',
|
||||||
name: 'Vben Admin Pro',
|
name: 'Vben Admin Pro',
|
||||||
},
|
},
|
||||||
breadcrumb: {
|
breadcrumb: {
|
||||||
|
|
|
@ -7,6 +7,12 @@ import type {
|
||||||
ThemeModeType,
|
ThemeModeType,
|
||||||
} from '@vben-core/typings';
|
} from '@vben-core/typings';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录过期模式
|
||||||
|
* 'modal' 弹窗模式 | 'page' 页面模式
|
||||||
|
*/
|
||||||
|
type LoginExpiredModeType = 'modal' | 'page';
|
||||||
|
|
||||||
type BreadcrumbStyleType = 'background' | 'normal';
|
type BreadcrumbStyleType = 'background' | 'normal';
|
||||||
|
|
||||||
type AccessModeType = 'allow-all' | 'backend' | 'frontend';
|
type AccessModeType = 'allow-all' | 'backend' | 'frontend';
|
||||||
|
@ -44,6 +50,8 @@ interface AppPreferences {
|
||||||
layout: LayoutType;
|
layout: LayoutType;
|
||||||
/** 支持的语言 */
|
/** 支持的语言 */
|
||||||
locale: SupportedLanguagesType;
|
locale: SupportedLanguagesType;
|
||||||
|
/** 登录过期模式 */
|
||||||
|
loginExpiredMode: LoginExpiredModeType;
|
||||||
/** 应用名 */
|
/** 应用名 */
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
@ -236,6 +244,7 @@ export type {
|
||||||
HeaderPreferences,
|
HeaderPreferences,
|
||||||
LayoutHeaderModeType,
|
LayoutHeaderModeType,
|
||||||
LayoutType,
|
LayoutType,
|
||||||
|
LoginExpiredModeType,
|
||||||
LogoPreferences,
|
LogoPreferences,
|
||||||
NavigationPreferences,
|
NavigationPreferences,
|
||||||
NavigationStyleType,
|
NavigationStyleType,
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@vben-core/locales": "workspace:*",
|
||||||
"@vben-core/toolkit": "workspace:*",
|
"@vben-core/toolkit": "workspace:*",
|
||||||
"axios": "^1.7.2",
|
"axios": "^1.7.2",
|
||||||
"vue-request": "^2.0.4"
|
"vue-request": "^2.0.4"
|
||||||
|
|
|
@ -1,3 +1,2 @@
|
||||||
export * from './request-client';
|
export * from './request-client';
|
||||||
export type * from './types';
|
export type * from './types';
|
||||||
export * from './util';
|
|
||||||
|
|
|
@ -17,16 +17,22 @@ class InterceptorManager {
|
||||||
) => InternalAxiosRequestConfig | Promise<InternalAxiosRequestConfig>,
|
) => InternalAxiosRequestConfig | Promise<InternalAxiosRequestConfig>,
|
||||||
rejected?: (error: any) => any,
|
rejected?: (error: any) => any,
|
||||||
) {
|
) {
|
||||||
this.axiosInstance.interceptors.request.use(fulfilled, rejected);
|
this.axiosInstance.interceptors.request.use(
|
||||||
|
fulfilled,
|
||||||
|
rejected || ((res) => res),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
addResponseInterceptor(
|
addResponseInterceptor<T = any>(
|
||||||
fulfilled: (
|
fulfilled: (
|
||||||
response: AxiosResponse,
|
response: AxiosResponse<T>,
|
||||||
) => AxiosResponse | Promise<AxiosResponse>,
|
) => AxiosResponse | Promise<AxiosResponse>,
|
||||||
rejected?: (error: any) => any,
|
rejected?: (error: any) => any,
|
||||||
) {
|
) {
|
||||||
this.axiosInstance.interceptors.response.use(fulfilled, rejected);
|
this.axiosInstance.interceptors.response.use(
|
||||||
|
fulfilled,
|
||||||
|
rejected || ((res) => res),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ import type {
|
||||||
|
|
||||||
import type { MakeAuthorizationFn, RequestClientOptions } from './types';
|
import type { MakeAuthorizationFn, RequestClientOptions } from './types';
|
||||||
|
|
||||||
|
import { $t } from '@vben-core/locales';
|
||||||
import { merge } from '@vben-core/toolkit';
|
import { merge } from '@vben-core/toolkit';
|
||||||
|
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
@ -19,6 +20,7 @@ import { FileUploader } from './modules/uploader';
|
||||||
class RequestClient {
|
class RequestClient {
|
||||||
private instance: AxiosInstance;
|
private instance: AxiosInstance;
|
||||||
private makeAuthorization: MakeAuthorizationFn | undefined;
|
private makeAuthorization: MakeAuthorizationFn | undefined;
|
||||||
|
private options: RequestClientOptions;
|
||||||
public addRequestInterceptor: InterceptorManager['addRequestInterceptor'];
|
public addRequestInterceptor: InterceptorManager['addRequestInterceptor'];
|
||||||
public addResponseInterceptor: InterceptorManager['addResponseInterceptor'];
|
public addResponseInterceptor: InterceptorManager['addResponseInterceptor'];
|
||||||
public download: FileDownloader['download'];
|
public download: FileDownloader['download'];
|
||||||
|
@ -39,6 +41,7 @@ class RequestClient {
|
||||||
timeout: 10_000,
|
timeout: 10_000,
|
||||||
};
|
};
|
||||||
const { makeAuthorization, ...axiosConfig } = options;
|
const { makeAuthorization, ...axiosConfig } = options;
|
||||||
|
this.options = options;
|
||||||
const requestConfig = merge(axiosConfig, defaultConfig);
|
const requestConfig = merge(axiosConfig, defaultConfig);
|
||||||
|
|
||||||
this.instance = axios.create(requestConfig);
|
this.instance = axios.create(requestConfig);
|
||||||
|
@ -77,24 +80,86 @@ class RequestClient {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private errorHandler(error: any) {
|
private setupAuthorizationInterceptor() {
|
||||||
return Promise.reject(error);
|
this.addRequestInterceptor(
|
||||||
|
(config: InternalAxiosRequestConfig) => {
|
||||||
|
const authorization = this.makeAuthorization?.(config);
|
||||||
|
if (authorization) {
|
||||||
|
const { token } = authorization.tokenHandler?.() ?? {};
|
||||||
|
config.headers[authorization.key || 'Authorization'] = token;
|
||||||
|
}
|
||||||
|
return config;
|
||||||
|
},
|
||||||
|
(error: any) => Promise.reject(error),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private setupAuthorizationInterceptor() {
|
private setupDefaultResponseInterceptor() {
|
||||||
this.addRequestInterceptor((config: InternalAxiosRequestConfig) => {
|
this.addResponseInterceptor(
|
||||||
const authorization = this.makeAuthorization?.(config);
|
(response: AxiosResponse) => {
|
||||||
if (authorization) {
|
return response;
|
||||||
const { token } = authorization.handler?.() ?? {};
|
},
|
||||||
config.headers[authorization.key || 'Authorization'] = token;
|
(error: any) => {
|
||||||
}
|
if (axios.isCancel(error)) {
|
||||||
return config;
|
return Promise.reject(error);
|
||||||
}, this.errorHandler);
|
}
|
||||||
|
|
||||||
|
const err: string = error?.toString?.() ?? '';
|
||||||
|
let errMsg = '';
|
||||||
|
if (err?.includes('Network Error')) {
|
||||||
|
errMsg = $t('fallback.http.networkError');
|
||||||
|
} else if (error?.message?.includes?.('timeout')) {
|
||||||
|
errMsg = $t('fallback.http.requestTimeout');
|
||||||
|
}
|
||||||
|
const { makeAuthorization, makeErrorMessage } = this.options;
|
||||||
|
if (errMsg) {
|
||||||
|
makeErrorMessage?.(errMsg);
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
let errorMessage = error?.response?.data?.error?.message ?? '';
|
||||||
|
const status = error?.response?.status;
|
||||||
|
|
||||||
|
switch (status) {
|
||||||
|
case 400: {
|
||||||
|
errorMessage = $t('fallback.http.badRequest');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 401: {
|
||||||
|
errorMessage = $t('fallback.http.unauthorized');
|
||||||
|
makeAuthorization?.().unAuthorizedHandler?.();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 403: {
|
||||||
|
errorMessage = $t('fallback.http.forbidden');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// 404请求不存在
|
||||||
|
case 404: {
|
||||||
|
errorMessage = $t('fallback.http.notFound');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 408: {
|
||||||
|
errorMessage = $t('fallback.http.requestTimeout');
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
errorMessage = $t('fallback.http.internalServerError');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
makeErrorMessage?.(errorMessage);
|
||||||
|
return Promise.reject(error);
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private setupInterceptors() {
|
private setupInterceptors() {
|
||||||
// 默认拦截器
|
// 默认拦截器
|
||||||
this.setupAuthorizationInterceptor();
|
this.setupAuthorizationInterceptor();
|
||||||
|
this.setupDefaultResponseInterceptor();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -7,18 +7,41 @@ type RequestContentType =
|
||||||
| 'multipart/form-data;charset=utf-8';
|
| 'multipart/form-data;charset=utf-8';
|
||||||
|
|
||||||
interface MakeAuthorization {
|
interface MakeAuthorization {
|
||||||
handler: () => { refreshToken: string; token: string } | null;
|
|
||||||
key?: string;
|
key?: string;
|
||||||
|
tokenHandler: () => { refreshToken: string; token: string } | null;
|
||||||
|
unAuthorizedHandler?: () => Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
type MakeAuthorizationFn = (
|
type MakeAuthorizationFn = (
|
||||||
config?: InternalAxiosRequestConfig,
|
config?: InternalAxiosRequestConfig,
|
||||||
) => MakeAuthorization;
|
) => MakeAuthorization;
|
||||||
|
|
||||||
|
type ErrorMessageFn = (message: string) => void;
|
||||||
|
|
||||||
interface RequestClientOptions extends CreateAxiosDefaults {
|
interface RequestClientOptions extends CreateAxiosDefaults {
|
||||||
/**
|
/**
|
||||||
* 用于生成Authorization
|
* 用于生成Authorization
|
||||||
*/
|
*/
|
||||||
makeAuthorization?: MakeAuthorizationFn;
|
makeAuthorization?: MakeAuthorizationFn;
|
||||||
|
/**
|
||||||
|
* 用于生成错误消息
|
||||||
|
*/
|
||||||
|
makeErrorMessage?: ErrorMessageFn;
|
||||||
}
|
}
|
||||||
export type { MakeAuthorizationFn, RequestClientOptions, RequestContentType };
|
|
||||||
|
interface HttpResponse<T = any> {
|
||||||
|
/**
|
||||||
|
* 0 表示成功 其他表示失败
|
||||||
|
* 0 means success, others means fail
|
||||||
|
*/
|
||||||
|
code: number;
|
||||||
|
data: T;
|
||||||
|
message: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type {
|
||||||
|
HttpResponse,
|
||||||
|
MakeAuthorizationFn,
|
||||||
|
RequestClientOptions,
|
||||||
|
RequestContentType,
|
||||||
|
};
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
import axios from 'axios';
|
|
||||||
import { describe, expect, it } from 'vitest';
|
|
||||||
|
|
||||||
import { isCancelError } from './util';
|
|
||||||
|
|
||||||
describe('isCancelError', () => {
|
|
||||||
const source = axios.CancelToken.source();
|
|
||||||
source.cancel('Operation canceled by the user.');
|
|
||||||
|
|
||||||
it('should detect cancellation', () => {
|
|
||||||
const error = new axios.Cancel('Operation canceled by the user.');
|
|
||||||
|
|
||||||
const result = isCancelError(error);
|
|
||||||
|
|
||||||
expect(result).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not detect cancellation on regular errors', () => {
|
|
||||||
const error = new Error('Regular error');
|
|
||||||
|
|
||||||
const result = isCancelError(error);
|
|
||||||
|
|
||||||
expect(result).toBe(false);
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,7 +0,0 @@
|
||||||
import axios from 'axios';
|
|
||||||
|
|
||||||
function isCancelError(error: any) {
|
|
||||||
return axios.isCancel(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
export { isCancelError };
|
|
|
@ -39,7 +39,16 @@
|
||||||
"offline": "Offline Page",
|
"offline": "Offline Page",
|
||||||
"offlineError": "Oops! Network Error",
|
"offlineError": "Oops! Network Error",
|
||||||
"offlineErrorDesc": "Sorry, can't connect to the internet. Check your connection.",
|
"offlineErrorDesc": "Sorry, can't connect to the internet. Check your connection.",
|
||||||
"coming-soon": "Coming Soon"
|
"comingSoon": "Coming Soon",
|
||||||
|
"http": {
|
||||||
|
"requestTimeout": "The request timed out. Please try again later.",
|
||||||
|
"networkError": "A network error occurred. Please check your internet connection and try again.",
|
||||||
|
"badRequest": "Bad Request. Please check your input and try again.",
|
||||||
|
"unauthorized": "Unauthorized. Please log in to continue.",
|
||||||
|
"forbidden": "Forbidden. You do not have permission to access this resource.",
|
||||||
|
"notFound": "Not Found. The requested resource could not be found.",
|
||||||
|
"internalServerError": "Internal Server Error. Something went wrong on our end. Please try again later."
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"widgets": {
|
"widgets": {
|
||||||
"document": "Document",
|
"document": "Document",
|
||||||
|
@ -104,6 +113,8 @@
|
||||||
"sendCode": "Get Security code",
|
"sendCode": "Get Security code",
|
||||||
"sendText": "Resend in {0}s",
|
"sendText": "Resend in {0}s",
|
||||||
"thirdPartyLogin": "Or continue with",
|
"thirdPartyLogin": "Or continue with",
|
||||||
|
"loginAgainTitle": "Please Log In Again",
|
||||||
|
"loginAgainSubTitle": "Your login session has expired. Please log in again to continue.",
|
||||||
"layout": {
|
"layout": {
|
||||||
"center": "Align Center",
|
"center": "Align Center",
|
||||||
"alignLeft": "Align Left",
|
"alignLeft": "Align Left",
|
||||||
|
|
|
@ -39,7 +39,16 @@
|
||||||
"offline": "离线页面",
|
"offline": "离线页面",
|
||||||
"offlineError": "哎呀!网络错误",
|
"offlineError": "哎呀!网络错误",
|
||||||
"offlineErrorDesc": "抱歉,无法连接到互联网,请检查您的网络连接并重试。",
|
"offlineErrorDesc": "抱歉,无法连接到互联网,请检查您的网络连接并重试。",
|
||||||
"coming-soon": "即将推出"
|
"comingSoon": "即将推出",
|
||||||
|
"http": {
|
||||||
|
"requestTimeout": "请求超时,请稍后再试。",
|
||||||
|
"networkError": "网络异常,请检查您的网络连接后重试。",
|
||||||
|
"badRequest": "请求错误。请检查您的输入并重试。",
|
||||||
|
"unauthorized": "未授权。请登录以继续。",
|
||||||
|
"forbidden": "禁止访问, 您没有权限访问此资源。",
|
||||||
|
"notFound": "未找到, 请求的资源不存在。",
|
||||||
|
"internalServerError": "内部服务器错误,请稍后再试。"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"widgets": {
|
"widgets": {
|
||||||
"document": "文档",
|
"document": "文档",
|
||||||
|
@ -104,6 +113,8 @@
|
||||||
"sendCode": "获取验证码",
|
"sendCode": "获取验证码",
|
||||||
"sendText": "{0}秒后重新获取",
|
"sendText": "{0}秒后重新获取",
|
||||||
"thirdPartyLogin": "其他登录方式",
|
"thirdPartyLogin": "其他登录方式",
|
||||||
|
"loginAgainTitle": "请重新登录",
|
||||||
|
"loginAgainSubTitle": "您的登录状态已过期,请重新登录以继续。",
|
||||||
"layout": {
|
"layout": {
|
||||||
"center": "居中",
|
"center": "居中",
|
||||||
"alignLeft": "居左",
|
"alignLeft": "居左",
|
||||||
|
|
|
@ -14,13 +14,19 @@ import {
|
||||||
useForwardPropsEmits,
|
useForwardPropsEmits,
|
||||||
} from 'radix-vue';
|
} from 'radix-vue';
|
||||||
|
|
||||||
const props = defineProps<
|
const props = withDefaults(
|
||||||
{ class?: HTMLAttributes['class'] } & DialogContentProps
|
defineProps<
|
||||||
>();
|
{
|
||||||
|
class?: HTMLAttributes['class'];
|
||||||
|
showClose?: boolean;
|
||||||
|
} & DialogContentProps
|
||||||
|
>(),
|
||||||
|
{ showClose: true },
|
||||||
|
);
|
||||||
const emits = defineEmits<{ close: [] } & DialogContentEmits>();
|
const emits = defineEmits<{ close: [] } & DialogContentEmits>();
|
||||||
|
|
||||||
const delegatedProps = computed(() => {
|
const delegatedProps = computed(() => {
|
||||||
const { class: _, ...delegated } = props;
|
const { class: _, showClose: __, ...delegated } = props;
|
||||||
|
|
||||||
return delegated;
|
return delegated;
|
||||||
});
|
});
|
||||||
|
@ -46,6 +52,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
|
|
||||||
<DialogClose
|
<DialogClose
|
||||||
|
v-if="showClose"
|
||||||
class="data-[state=open]:bg-accent data-[state=open]:text-muted-foreground hover:bg-accent hover:text-accent-foreground text-foreground/80 flex-center absolute right-3 top-3 h-6 w-6 rounded-full px-1 text-lg opacity-70 transition-opacity hover:opacity-100 focus:outline-none disabled:pointer-events-none"
|
class="data-[state=open]:bg-accent data-[state=open]:text-muted-foreground hover:bg-accent hover:text-accent-foreground text-foreground/80 flex-center absolute right-3 top-3 h-6 w-6 rounded-full px-1 text-lg opacity-70 transition-opacity hover:opacity-100 focus:outline-none disabled:pointer-events-none"
|
||||||
@click="() => emits('close')"
|
@click="() => emits('close')"
|
||||||
>
|
>
|
||||||
|
|
|
@ -2,6 +2,7 @@ import './styles/index.css';
|
||||||
|
|
||||||
export * from './components';
|
export * from './components';
|
||||||
export {
|
export {
|
||||||
|
VisuallyHidden,
|
||||||
useEmitAsProps,
|
useEmitAsProps,
|
||||||
useForwardExpose,
|
useForwardExpose,
|
||||||
useForwardProps,
|
useForwardProps,
|
||||||
|
|
|
@ -48,7 +48,6 @@
|
||||||
"@vben-core/stores": "workspace:*",
|
"@vben-core/stores": "workspace:*",
|
||||||
"@vben-core/tabs-ui": "workspace:*",
|
"@vben-core/tabs-ui": "workspace:*",
|
||||||
"@vben-core/toolkit": "workspace:*",
|
"@vben-core/toolkit": "workspace:*",
|
||||||
"@vben/universal-ui": "workspace:*",
|
|
||||||
"@vueuse/core": "^10.11.0",
|
"@vueuse/core": "^10.11.0",
|
||||||
"vue": "^3.4.31",
|
"vue": "^3.4.31",
|
||||||
"vue-router": "^4.4.0"
|
"vue-router": "^4.4.0"
|
||||||
|
|
|
@ -4,7 +4,6 @@ export { default as CozeAssistant } from './coze-assistant.vue';
|
||||||
export * from './global-search';
|
export * from './global-search';
|
||||||
export { default as LanguageToggle } from './language-toggle.vue';
|
export { default as LanguageToggle } from './language-toggle.vue';
|
||||||
export { default as AuthenticationLayoutToggle } from './layout-toggle.vue';
|
export { default as AuthenticationLayoutToggle } from './layout-toggle.vue';
|
||||||
export * from './login-dialog';
|
|
||||||
export * from './notification';
|
export * from './notification';
|
||||||
export * from './preferences';
|
export * from './preferences';
|
||||||
export * from './theme-toggle';
|
export * from './theme-toggle';
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
export { default as LoginDialog } from './login-dialog.vue';
|
|
|
@ -1,48 +0,0 @@
|
||||||
<script setup lang="ts">
|
|
||||||
import { computed } from 'vue';
|
|
||||||
|
|
||||||
import {
|
|
||||||
AuthenticationLogin,
|
|
||||||
AuthenticationProps,
|
|
||||||
LoginAndRegisterParams,
|
|
||||||
} from '@vben/universal-ui';
|
|
||||||
import { Dialog, DialogContent } from '@vben-core/shadcn-ui';
|
|
||||||
|
|
||||||
interface Props extends AuthenticationProps {
|
|
||||||
open: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
defineOptions({
|
|
||||||
name: 'LoginDialog',
|
|
||||||
});
|
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
|
||||||
open: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
const emit = defineEmits<{
|
|
||||||
login: [LoginAndRegisterParams];
|
|
||||||
}>();
|
|
||||||
|
|
||||||
const loginProps = computed(() => {
|
|
||||||
const { open: _, ...rest } = props;
|
|
||||||
return rest;
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<Dialog :open="open" class="flex items-center justify-center">
|
|
||||||
<DialogContent
|
|
||||||
class="top-[50%] w-full translate-y-[-50%] border-none p-0 shadow-xl sm:w-[600px] sm:rounded-2xl"
|
|
||||||
>
|
|
||||||
<div class="p-4">
|
|
||||||
<AuthenticationLogin
|
|
||||||
v-bind="loginProps"
|
|
||||||
@submit="(e) => emit('login', e)"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</DialogContent>
|
|
||||||
</Dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
|
@ -399,22 +399,22 @@ async function handleReset() {
|
||||||
:disabled="!diffPreference"
|
:disabled="!diffPreference"
|
||||||
class="mx-4 w-full"
|
class="mx-4 w-full"
|
||||||
size="sm"
|
size="sm"
|
||||||
variant="outline"
|
|
||||||
@click="handleClearCache"
|
|
||||||
>
|
|
||||||
<IcRoundRestartAlt class="mr-2 size-4" />
|
|
||||||
{{ $t('preferences.clearAndLogout') }}
|
|
||||||
</VbenButton>
|
|
||||||
<VbenButton
|
|
||||||
:disabled="!diffPreference"
|
|
||||||
class="mr-4 w-full"
|
|
||||||
size="sm"
|
|
||||||
variant="default"
|
variant="default"
|
||||||
@click="handleCopy"
|
@click="handleCopy"
|
||||||
>
|
>
|
||||||
<IcRoundFolderCopy class="mr-2 size-3" />
|
<IcRoundFolderCopy class="mr-2 size-3" />
|
||||||
{{ $t('preferences.copyPreferences') }}
|
{{ $t('preferences.copyPreferences') }}
|
||||||
</VbenButton>
|
</VbenButton>
|
||||||
|
<VbenButton
|
||||||
|
:disabled="!diffPreference"
|
||||||
|
class="mr-4 w-full"
|
||||||
|
size="sm"
|
||||||
|
variant="ghost"
|
||||||
|
@click="handleClearCache"
|
||||||
|
>
|
||||||
|
<IcRoundRestartAlt class="mr-2 size-4" />
|
||||||
|
{{ $t('preferences.clearAndLogout') }}
|
||||||
|
</VbenButton>
|
||||||
</template>
|
</template>
|
||||||
</VbenSheet>
|
</VbenSheet>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
export { default as AuthenticationCodeLogin } from './code-login.vue';
|
export { default as AuthenticationCodeLogin } from './code-login.vue';
|
||||||
export { default as AuthenticationForgetPassword } from './forget-password.vue';
|
export { default as AuthenticationForgetPassword } from './forget-password.vue';
|
||||||
export { default as AuthenticationLogin } from './login.vue';
|
export { default as AuthenticationLogin } from './login.vue';
|
||||||
|
export { default as AuthenticationLoginExpiredModal } from './login-expired-modal.vue';
|
||||||
export { default as AuthenticationQrCodeLogin } from './qrcode-login.vue';
|
export { default as AuthenticationQrCodeLogin } from './qrcode-login.vue';
|
||||||
export { default as AuthenticationRegister } from './register.vue';
|
export { default as AuthenticationRegister } from './register.vue';
|
||||||
export type {
|
export type {
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogDescription,
|
||||||
|
DialogTitle,
|
||||||
|
VisuallyHidden,
|
||||||
|
useForwardPropsEmits,
|
||||||
|
} from '@vben-core/shadcn-ui';
|
||||||
|
|
||||||
|
import AuthenticationLogin from './login.vue';
|
||||||
|
import { AuthenticationProps, LoginAndRegisterParams } from './typings';
|
||||||
|
|
||||||
|
interface Props extends AuthenticationProps {}
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: 'LoginExpiredModal',
|
||||||
|
});
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<Props>(), {});
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
submit: [LoginAndRegisterParams];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const open = defineModel<boolean>('open');
|
||||||
|
|
||||||
|
const forwarded = useForwardPropsEmits(props, emit);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<Dialog v-model:open="open">
|
||||||
|
<DialogContent
|
||||||
|
:show-close="false"
|
||||||
|
class="top-1/2 h-full w-full translate-y-[-50%] border-none p-4 py-12 text-center shadow-xl sm:w-[600px] sm:rounded-2xl md:h-[unset] md:px-14 md:pt-12"
|
||||||
|
@escape-key-down="(e) => e.preventDefault()"
|
||||||
|
@interact-outside="(e) => e.preventDefault()"
|
||||||
|
>
|
||||||
|
<VisuallyHidden>
|
||||||
|
<DialogTitle />
|
||||||
|
<DialogDescription />
|
||||||
|
</VisuallyHidden>
|
||||||
|
<AuthenticationLogin
|
||||||
|
v-bind="forwarded"
|
||||||
|
:show-forget-password="false"
|
||||||
|
:show-register="false"
|
||||||
|
:show-remember-me="false"
|
||||||
|
:sub-title="$t('authentication.loginAgainSubTitle')"
|
||||||
|
:title="$t('authentication.loginAgainTitle')"
|
||||||
|
/>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
|
@ -31,7 +31,10 @@ withDefaults(defineProps<Props>(), {
|
||||||
showForgetPassword: true,
|
showForgetPassword: true,
|
||||||
showQrcodeLogin: true,
|
showQrcodeLogin: true,
|
||||||
showRegister: true,
|
showRegister: true,
|
||||||
|
showRememberMe: true,
|
||||||
showThirdPartyLogin: true,
|
showThirdPartyLogin: true,
|
||||||
|
subTitle: '',
|
||||||
|
title: '',
|
||||||
usernamePlaceholder: '',
|
usernamePlaceholder: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -89,10 +92,10 @@ function handleGo(path: string) {
|
||||||
<template>
|
<template>
|
||||||
<div @keypress.enter.prevent="handleSubmit">
|
<div @keypress.enter.prevent="handleSubmit">
|
||||||
<Title>
|
<Title>
|
||||||
{{ $t('authentication.welcomeBack') }} 👋🏻
|
{{ title || `${$t('authentication.welcomeBack')} 👋🏻` }}
|
||||||
<template #desc>
|
<template #desc>
|
||||||
<span class="text-muted-foreground">
|
<span class="text-muted-foreground">
|
||||||
{{ $t('authentication.loginSubtitle') }}
|
{{ subTitle || $t('authentication.loginSubtitle') }}
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</Title>
|
</Title>
|
||||||
|
@ -120,7 +123,7 @@ function handleGo(path: string) {
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="mb-6 mt-4 flex justify-between">
|
<div class="mb-6 mt-4 flex justify-between">
|
||||||
<div class="flex-center flex">
|
<div v-if="showRememberMe" class="flex-center">
|
||||||
<VbenCheckbox v-model:checked="formState.rememberMe" name="rememberMe">
|
<VbenCheckbox v-model:checked="formState.rememberMe" name="rememberMe">
|
||||||
{{ $t('authentication.rememberMe') }}
|
{{ $t('authentication.rememberMe') }}
|
||||||
</VbenCheckbox>
|
</VbenCheckbox>
|
||||||
|
@ -133,10 +136,6 @@ function handleGo(path: string) {
|
||||||
>
|
>
|
||||||
{{ $t('authentication.forgetPassword') }}
|
{{ $t('authentication.forgetPassword') }}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<!-- <VbenButton variant="ghost" @click="handleGo('/auth/forget-password')">
|
|
||||||
忘记密码?
|
|
||||||
</VbenButton> -->
|
|
||||||
</div>
|
</div>
|
||||||
<VbenButton :loading="loading" class="w-full" @click="handleSubmit">
|
<VbenButton :loading="loading" class="w-full" @click="handleSubmit">
|
||||||
{{ $t('common.login') }}
|
{{ $t('common.login') }}
|
||||||
|
@ -159,14 +158,6 @@ function handleGo(path: string) {
|
||||||
>
|
>
|
||||||
{{ $t('authentication.qrcodeLogin') }}
|
{{ $t('authentication.qrcodeLogin') }}
|
||||||
</VbenButton>
|
</VbenButton>
|
||||||
<!-- <VbenButton
|
|
||||||
:loading="loading"
|
|
||||||
variant="outline"
|
|
||||||
class="w-1/3"
|
|
||||||
@click="handleGo('/auth/register')"
|
|
||||||
>
|
|
||||||
创建账号
|
|
||||||
</VbenButton> -->
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 第三方登录 -->
|
<!-- 第三方登录 -->
|
||||||
|
|
|
@ -3,7 +3,6 @@ interface AuthenticationProps {
|
||||||
* @zh_CN 验证码登录路径
|
* @zh_CN 验证码登录路径
|
||||||
*/
|
*/
|
||||||
codeLoginPath?: string;
|
codeLoginPath?: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @zh_CN 忘记密码路径
|
* @zh_CN 忘记密码路径
|
||||||
*/
|
*/
|
||||||
|
@ -33,7 +32,6 @@ interface AuthenticationProps {
|
||||||
* @zh_CN 是否显示验证码登录
|
* @zh_CN 是否显示验证码登录
|
||||||
*/
|
*/
|
||||||
showCodeLogin?: boolean;
|
showCodeLogin?: boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @zh_CN 是否显示忘记密码
|
* @zh_CN 是否显示忘记密码
|
||||||
*/
|
*/
|
||||||
|
@ -49,11 +47,26 @@ interface AuthenticationProps {
|
||||||
*/
|
*/
|
||||||
showRegister?: boolean;
|
showRegister?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh_CN 是否显示记住账号
|
||||||
|
*/
|
||||||
|
showRememberMe?: boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @zh_CN 是否显示第三方登录
|
* @zh_CN 是否显示第三方登录
|
||||||
*/
|
*/
|
||||||
showThirdPartyLogin?: boolean;
|
showThirdPartyLogin?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh_CN 登录框子标题
|
||||||
|
*/
|
||||||
|
subTitle?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh_CN 登录框标题
|
||||||
|
*/
|
||||||
|
title?: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @zh_CN 用户名占位符
|
* @zh_CN 用户名占位符
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -52,7 +52,7 @@ const titleText = computed(() => {
|
||||||
return $t('fallback.offlineError');
|
return $t('fallback.offlineError');
|
||||||
}
|
}
|
||||||
case 'comming-soon': {
|
case 'comming-soon': {
|
||||||
return $t('fallback.coming-soon');
|
return $t('fallback.comingSoon');
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
return '';
|
return '';
|
||||||
|
|
207
pnpm-lock.yaml
207
pnpm-lock.yaml
|
@ -75,8 +75,8 @@ importers:
|
||||||
specifier: ^24.1.0
|
specifier: ^24.1.0
|
||||||
version: 24.1.0
|
version: 24.1.0
|
||||||
rimraf:
|
rimraf:
|
||||||
specifier: ^6.0.0
|
specifier: ^6.0.1
|
||||||
version: 6.0.0
|
version: 6.0.1
|
||||||
turbo:
|
turbo:
|
||||||
specifier: ^2.0.6
|
specifier: ^2.0.6
|
||||||
version: 2.0.6
|
version: 2.0.6
|
||||||
|
@ -90,8 +90,8 @@ importers:
|
||||||
specifier: ^5.3.3
|
specifier: ^5.3.3
|
||||||
version: 5.3.3(@types/node@20.14.10)(sass@1.77.7)(terser@5.31.2)
|
version: 5.3.3(@types/node@20.14.10)(sass@1.77.7)(terser@5.31.2)
|
||||||
vitest:
|
vitest:
|
||||||
specifier: ^2.0.1
|
specifier: ^2.0.2
|
||||||
version: 2.0.1(@types/node@20.14.10)(jsdom@24.1.0)(sass@1.77.7)(terser@5.31.2)
|
version: 2.0.2(@types/node@20.14.10)(jsdom@24.1.0)(sass@1.77.7)(terser@5.31.2)
|
||||||
vue-tsc:
|
vue-tsc:
|
||||||
specifier: ^2.0.26
|
specifier: ^2.0.26
|
||||||
version: 2.0.26(typescript@5.5.3)
|
version: 2.0.26(typescript@5.5.3)
|
||||||
|
@ -293,8 +293,8 @@ importers:
|
||||||
specifier: ^2.29.1
|
specifier: ^2.29.1
|
||||||
version: 2.29.1(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)
|
version: 2.29.1(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)
|
||||||
eslint-plugin-jsdoc:
|
eslint-plugin-jsdoc:
|
||||||
specifier: ^48.6.0
|
specifier: ^48.7.0
|
||||||
version: 48.6.0(eslint@8.57.0)
|
version: 48.7.0(eslint@8.57.0)
|
||||||
eslint-plugin-jsonc:
|
eslint-plugin-jsonc:
|
||||||
specifier: ^2.16.0
|
specifier: ^2.16.0
|
||||||
version: 2.16.0(eslint@8.57.0)
|
version: 2.16.0(eslint@8.57.0)
|
||||||
|
@ -321,7 +321,7 @@ importers:
|
||||||
version: 4.0.0(@typescript-eslint/eslint-plugin@7.16.0(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)
|
version: 4.0.0(@typescript-eslint/eslint-plugin@7.16.0(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)
|
||||||
eslint-plugin-vitest:
|
eslint-plugin-vitest:
|
||||||
specifier: ^0.5.4
|
specifier: ^0.5.4
|
||||||
version: 0.5.4(@typescript-eslint/eslint-plugin@7.16.0(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3)(vitest@2.0.1(@types/node@20.14.10)(jsdom@24.1.0)(sass@1.77.7)(terser@5.31.2))
|
version: 0.5.4(@typescript-eslint/eslint-plugin@7.16.0(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3)(vitest@2.0.2(@types/node@20.14.10)(jsdom@24.1.0)(sass@1.77.7)(terser@5.31.2))
|
||||||
eslint-plugin-vue:
|
eslint-plugin-vue:
|
||||||
specifier: ^9.27.0
|
specifier: ^9.27.0
|
||||||
version: 9.27.0(eslint@8.57.0)
|
version: 9.27.0(eslint@8.57.0)
|
||||||
|
@ -423,8 +423,8 @@ importers:
|
||||||
specifier: ^3.3.2
|
specifier: ^3.3.2
|
||||||
version: 3.3.2
|
version: 3.3.2
|
||||||
rimraf:
|
rimraf:
|
||||||
specifier: ^6.0.0
|
specifier: ^6.0.1
|
||||||
version: 6.0.0
|
version: 6.0.1
|
||||||
zx:
|
zx:
|
||||||
specifier: ^7.2.3
|
specifier: ^7.2.3
|
||||||
version: 7.2.3
|
version: 7.2.3
|
||||||
|
@ -589,6 +589,9 @@ importers:
|
||||||
|
|
||||||
packages/@core/forward/request:
|
packages/@core/forward/request:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
'@vben-core/locales':
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../../locales
|
||||||
'@vben-core/toolkit':
|
'@vben-core/toolkit':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../../shared/toolkit
|
version: link:../../shared/toolkit
|
||||||
|
@ -878,9 +881,6 @@ importers:
|
||||||
'@vben-core/toolkit':
|
'@vben-core/toolkit':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../../@core/shared/toolkit
|
version: link:../../@core/shared/toolkit
|
||||||
'@vben/universal-ui':
|
|
||||||
specifier: workspace:*
|
|
||||||
version: link:../universal-ui
|
|
||||||
'@vueuse/core':
|
'@vueuse/core':
|
||||||
specifier: ^10.11.0
|
specifier: ^10.11.0
|
||||||
version: 10.11.0(vue@3.4.31(typescript@5.5.3))
|
version: 10.11.0(vue@3.4.31(typescript@5.5.3))
|
||||||
|
@ -2438,8 +2438,8 @@ packages:
|
||||||
resolution: {integrity: sha512-I238eDtOolvCuvtxrnqtlBaw0BwdQuYqK7eA6XIonicMdOOOb75mqdIzkGDUbS04+1Di007rgm9snFRNeVrOog==}
|
resolution: {integrity: sha512-I238eDtOolvCuvtxrnqtlBaw0BwdQuYqK7eA6XIonicMdOOOb75mqdIzkGDUbS04+1Di007rgm9snFRNeVrOog==}
|
||||||
engines: {node: '>=16'}
|
engines: {node: '>=16'}
|
||||||
|
|
||||||
'@es-joy/jsdoccomment@0.45.0':
|
'@es-joy/jsdoccomment@0.46.0':
|
||||||
resolution: {integrity: sha512-U8T5eXLkP78Sr12rR91494GhlEgp8jqs7OaUHbdUffADxU1JQmKjZm5uSyAEGv2oolDMJ+wce7yylfnnwOevtA==}
|
resolution: {integrity: sha512-C3Axuq1xd/9VqFZpW4YAzOx5O9q/LP46uIQy/iNDpHG3fmPa6TBtvfglMCs3RBiBxAIi0Go97r8+jvTt55XMyQ==}
|
||||||
engines: {node: '>=16'}
|
engines: {node: '>=16'}
|
||||||
|
|
||||||
'@esbuild/aix-ppc64@0.19.12':
|
'@esbuild/aix-ppc64@0.19.12':
|
||||||
|
@ -2985,10 +2985,6 @@ packages:
|
||||||
resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
|
resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
'@jest/schemas@29.6.3':
|
|
||||||
resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==}
|
|
||||||
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
|
||||||
|
|
||||||
'@jridgewell/gen-mapping@0.3.5':
|
'@jridgewell/gen-mapping@0.3.5':
|
||||||
resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==}
|
resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==}
|
||||||
engines: {node: '>=6.0.0'}
|
engines: {node: '>=6.0.0'}
|
||||||
|
@ -3399,9 +3395,6 @@ packages:
|
||||||
'@simonwep/pickr@1.8.2':
|
'@simonwep/pickr@1.8.2':
|
||||||
resolution: {integrity: sha512-/l5w8BIkrpP6n1xsetx9MWPWlU6OblN5YgZZphxan0Tq4BByTCETL6lyIeY8lagalS2Nbt4F2W034KHLIiunKA==}
|
resolution: {integrity: sha512-/l5w8BIkrpP6n1xsetx9MWPWlU6OblN5YgZZphxan0Tq4BByTCETL6lyIeY8lagalS2Nbt4F2W034KHLIiunKA==}
|
||||||
|
|
||||||
'@sinclair/typebox@0.27.8':
|
|
||||||
resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==}
|
|
||||||
|
|
||||||
'@sindresorhus/is@5.6.0':
|
'@sindresorhus/is@5.6.0':
|
||||||
resolution: {integrity: sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==}
|
resolution: {integrity: sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==}
|
||||||
engines: {node: '>=14.16'}
|
engines: {node: '>=14.16'}
|
||||||
|
@ -3694,20 +3687,23 @@ packages:
|
||||||
vite: ^5.0.0
|
vite: ^5.0.0
|
||||||
vue: ^3.4.31
|
vue: ^3.4.31
|
||||||
|
|
||||||
'@vitest/expect@2.0.1':
|
'@vitest/expect@2.0.2':
|
||||||
resolution: {integrity: sha512-yw70WL3ZwzbI2O3MOXYP2Shf4vqVkS3q5FckLJ6lhT9VMMtDyWdofD53COZcoeuHwsBymdOZp99r5bOr5g+oeA==}
|
resolution: {integrity: sha512-nKAvxBYqcDugYZ4nJvnm5OR8eDJdgWjk4XM9owQKUjzW70q0icGV2HVnQOyYsp906xJaBDUXw0+9EHw2T8e0mQ==}
|
||||||
|
|
||||||
'@vitest/runner@2.0.1':
|
'@vitest/pretty-format@2.0.2':
|
||||||
resolution: {integrity: sha512-XfcSXOGGxgR2dQ466ZYqf0ZtDLLDx9mZeQcKjQDLQ9y6Cmk2Wl7wxMuhiYK4Fo1VxCtLcFEGW2XpcfMuiD1Maw==}
|
resolution: {integrity: sha512-SBCyOXfGVvddRd9r2PwoVR0fonQjh9BMIcBMlSzbcNwFfGr6ZhOhvBzurjvi2F4ryut2HcqiFhNeDVGwru8tLg==}
|
||||||
|
|
||||||
'@vitest/snapshot@2.0.1':
|
'@vitest/runner@2.0.2':
|
||||||
resolution: {integrity: sha512-rst79a4Q+J5vrvHRapdfK4BdqpMH0eF58jVY1vYeBo/1be+nkyenGI5SCSohmjf6MkCkI20/yo5oG+0R8qrAnA==}
|
resolution: {integrity: sha512-OCh437Vi8Wdbif1e0OvQcbfM3sW4s2lpmOjAE7qfLrpzJX2M7J1IQlNvEcb/fu6kaIB9n9n35wS0G2Q3en5kHg==}
|
||||||
|
|
||||||
'@vitest/spy@2.0.1':
|
'@vitest/snapshot@2.0.2':
|
||||||
resolution: {integrity: sha512-NLkdxbSefAtJN56GtCNcB4GiHFb5i9q1uh4V229lrlTZt2fnwsTyjLuWIli1xwK2fQspJJmHXHyWx0Of3KTXWA==}
|
resolution: {integrity: sha512-Yc2ewhhZhx+0f9cSUdfzPRcsM6PhIb+S43wxE7OG0kTxqgqzo8tHkXFuFlndXeDMp09G3sY/X5OAo/RfYydf1g==}
|
||||||
|
|
||||||
'@vitest/utils@2.0.1':
|
'@vitest/spy@2.0.2':
|
||||||
resolution: {integrity: sha512-STH+2fHZxlveh1mpU4tKzNgRk7RZJyr6kFGJYCI5vocdfqfPsQrgVC6k7dBWHfin5QNB4TLvRS0Ckly3Dt1uWw==}
|
resolution: {integrity: sha512-MgwJ4AZtCgqyp2d7WcQVE8aNG5vQ9zu9qMPYQHjsld/QVsrvg78beNrXdO4HYkP0lDahCO3P4F27aagIag+SGQ==}
|
||||||
|
|
||||||
|
'@vitest/utils@2.0.2':
|
||||||
|
resolution: {integrity: sha512-pxCY1v7kmOCWYWjzc0zfjGTA3Wmn8PKnlPvSrsA643P1NHl1fOyXj2Q9SaNlrlFE+ivCsxM80Ov3AR82RmHCWQ==}
|
||||||
|
|
||||||
'@volar/language-core@1.11.1':
|
'@volar/language-core@1.11.1':
|
||||||
resolution: {integrity: sha512-dOcNn3i9GgZAcJt43wuaEykSluAuOkQgzni1cuxLxTV0nJKanQztp7FxyswdRILaKH+P2XZMPRp2S4MV/pElCw==}
|
resolution: {integrity: sha512-dOcNn3i9GgZAcJt43wuaEykSluAuOkQgzni1cuxLxTV0nJKanQztp7FxyswdRILaKH+P2XZMPRp2S4MV/pElCw==}
|
||||||
|
@ -4012,10 +4008,6 @@ packages:
|
||||||
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
|
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
ansi-styles@5.2.0:
|
|
||||||
resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
|
|
||||||
ansi-styles@6.2.1:
|
ansi-styles@6.2.1:
|
||||||
resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==}
|
resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
|
@ -4922,10 +4914,6 @@ packages:
|
||||||
didyoumean@1.2.2:
|
didyoumean@1.2.2:
|
||||||
resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==}
|
resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==}
|
||||||
|
|
||||||
diff-sequences@29.6.3:
|
|
||||||
resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==}
|
|
||||||
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
|
||||||
|
|
||||||
diff@4.0.2:
|
diff@4.0.2:
|
||||||
resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==}
|
resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==}
|
||||||
engines: {node: '>=0.3.1'}
|
engines: {node: '>=0.3.1'}
|
||||||
|
@ -5029,8 +5017,8 @@ packages:
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
electron-to-chromium@1.4.823:
|
electron-to-chromium@1.4.824:
|
||||||
resolution: {integrity: sha512-4h+oPeAiGQOHFyUJOqpoEcPj/xxlicxBzOErVeYVMMmAiXUXsGpsFd0QXBMaUUbnD8hhSfLf9uw+MlsoIA7j5w==}
|
resolution: {integrity: sha512-GTQnZOP1v0wCuoWzKOxL8rurg9T13QRYISkoICGaZzskBf9laC3V8g9BHTpJv+j9vBRcKOulbGXwMzuzNdVrAA==}
|
||||||
|
|
||||||
emoji-regex@10.3.0:
|
emoji-regex@10.3.0:
|
||||||
resolution: {integrity: sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==}
|
resolution: {integrity: sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==}
|
||||||
|
@ -5213,8 +5201,8 @@ packages:
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
eslint: ^7.2.0 || ^8
|
eslint: ^7.2.0 || ^8
|
||||||
|
|
||||||
eslint-plugin-jsdoc@48.6.0:
|
eslint-plugin-jsdoc@48.7.0:
|
||||||
resolution: {integrity: sha512-UsOdFYWeyYaiGW1OzJaKvRpb88JPF0HGpDkmMDvhfWbTGu3B4TYKhGH3cPGiRjMDxKPA3fJ/+tL823argNxOkA==}
|
resolution: {integrity: sha512-5oiVf7Y+ZxGYQTlLq81X72n+S+hjvS/u0upAdbpPEeaIZILK3MKN8lm/6QqKioBjm/qZ0B5XpMQUtc2fUkqXAg==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
eslint: ^7.0.0 || ^8.0.0 || ^9.0.0
|
eslint: ^7.0.0 || ^8.0.0 || ^9.0.0
|
||||||
|
@ -6209,9 +6197,8 @@ packages:
|
||||||
resolution: {integrity: sha512-RKYVTCjAnRthyJes037NX/IiqeidgN1xc3j1RjFfECFp28A1GVwK9nA+i0rJPaHqSZwygLzRnFlzUuHFoWWy+Q==}
|
resolution: {integrity: sha512-RKYVTCjAnRthyJes037NX/IiqeidgN1xc3j1RjFfECFp28A1GVwK9nA+i0rJPaHqSZwygLzRnFlzUuHFoWWy+Q==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
|
|
||||||
jackspeak@3.4.2:
|
jackspeak@3.4.3:
|
||||||
resolution: {integrity: sha512-qH3nOSj8q/8+Eg8LUPOq3C+6HWkpUioIjDsq1+D4zY91oZvpPttw8GwtF1nReRYKXl+1AORyFqtm2f5Q1SB6/Q==}
|
resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==}
|
||||||
engines: {node: 14 >=14.21 || 16 >=16.20 || >=18}
|
|
||||||
|
|
||||||
jackspeak@4.0.1:
|
jackspeak@4.0.1:
|
||||||
resolution: {integrity: sha512-cub8rahkh0Q/bw1+GxP7aeSe29hHHn2V4m29nnDlvCdlgU+3UGxkZp7Z53jLUdpX3jdTO0nJZUDl3xvbWc2Xog==}
|
resolution: {integrity: sha512-cub8rahkh0Q/bw1+GxP7aeSe29hHHn2V4m29nnDlvCdlgU+3UGxkZp7Z53jLUdpX3jdTO0nJZUDl3xvbWc2Xog==}
|
||||||
|
@ -6902,8 +6889,8 @@ packages:
|
||||||
nth-check@2.1.1:
|
nth-check@2.1.1:
|
||||||
resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==}
|
resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==}
|
||||||
|
|
||||||
nwsapi@2.2.10:
|
nwsapi@2.2.12:
|
||||||
resolution: {integrity: sha512-QK0sRs7MKv0tKe1+5uZIQk/C8XGza4DAnztJG8iD+TpJIORARrCxczA738awHrZoHeTjSSoHqao2teO0dC/gFQ==}
|
resolution: {integrity: sha512-qXDmcVlZV4XRtKFzddidpfVP4oMSGhga+xdMc25mv8kaLUHtgzCDhUxkrN8exkGdTlLNaXj7CV3GtON7zuGZ+w==}
|
||||||
|
|
||||||
object-assign@4.1.1:
|
object-assign@4.1.1:
|
||||||
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
|
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
|
||||||
|
@ -7697,10 +7684,6 @@ packages:
|
||||||
resolution: {integrity: sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==}
|
resolution: {integrity: sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==}
|
||||||
engines: {node: ^14.13.1 || >=16.0.0}
|
engines: {node: ^14.13.1 || >=16.0.0}
|
||||||
|
|
||||||
pretty-format@29.7.0:
|
|
||||||
resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==}
|
|
||||||
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
|
||||||
|
|
||||||
process-nextick-args@2.0.1:
|
process-nextick-args@2.0.1:
|
||||||
resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==}
|
resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==}
|
||||||
|
|
||||||
|
@ -7795,9 +7778,6 @@ packages:
|
||||||
resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==}
|
resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
react-is@18.3.1:
|
|
||||||
resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==}
|
|
||||||
|
|
||||||
read-cache@1.0.0:
|
read-cache@1.0.0:
|
||||||
resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==}
|
resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==}
|
||||||
|
|
||||||
|
@ -7961,8 +7941,8 @@ packages:
|
||||||
deprecated: Rimraf versions prior to v4 are no longer supported
|
deprecated: Rimraf versions prior to v4 are no longer supported
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
rimraf@6.0.0:
|
rimraf@6.0.1:
|
||||||
resolution: {integrity: sha512-u+yqhM92LW+89cxUQK0SRyvXYQmyuKHx0jkx4W7KfwLGLqJnQM5031Uv1trE4gB9XEXBM/s6MxKlfW95IidqaA==}
|
resolution: {integrity: sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==}
|
||||||
engines: {node: 20 || >=22}
|
engines: {node: 20 || >=22}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
@ -8592,6 +8572,10 @@ packages:
|
||||||
resolution: {integrity: sha512-KIKExllK7jp3uvrNtvRBYBWBOAXSX8ZvoaD8T+7KB/QHIuoJW3Pmr60zucywjAlMb5TeXUkcs/MWeWLu0qvuAQ==}
|
resolution: {integrity: sha512-KIKExllK7jp3uvrNtvRBYBWBOAXSX8ZvoaD8T+7KB/QHIuoJW3Pmr60zucywjAlMb5TeXUkcs/MWeWLu0qvuAQ==}
|
||||||
engines: {node: ^18.0.0 || >=20.0.0}
|
engines: {node: ^18.0.0 || >=20.0.0}
|
||||||
|
|
||||||
|
tinyrainbow@1.2.0:
|
||||||
|
resolution: {integrity: sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==}
|
||||||
|
engines: {node: '>=14.0.0'}
|
||||||
|
|
||||||
tinyspy@3.0.0:
|
tinyspy@3.0.0:
|
||||||
resolution: {integrity: sha512-q5nmENpTHgiPVd1cJDDc9cVoYN5x4vCvwT3FMilvKPKneCBZAxn2YWQjDF0UMcE9k0Cay1gBiDfTMU0g+mPMQA==}
|
resolution: {integrity: sha512-q5nmENpTHgiPVd1cJDDc9cVoYN5x4vCvwT3FMilvKPKneCBZAxn2YWQjDF0UMcE9k0Cay1gBiDfTMU0g+mPMQA==}
|
||||||
engines: {node: '>=14.0.0'}
|
engines: {node: '>=14.0.0'}
|
||||||
|
@ -8946,8 +8930,8 @@ packages:
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
vite: ^2.6.0 || ^3.0.0 || ^4.0.0 || ^5.0.0-0
|
vite: ^2.6.0 || ^3.0.0 || ^4.0.0 || ^5.0.0-0
|
||||||
|
|
||||||
vite-node@2.0.1:
|
vite-node@2.0.2:
|
||||||
resolution: {integrity: sha512-nVd6kyhPAql0s+xIVJzuF+RSRH8ZimNrm6U8ZvTA4MXv8CHI17TFaQwRaFiK75YX6XeFqZD4IoAaAfi9OR1XvQ==}
|
resolution: {integrity: sha512-w4vkSz1Wo+NIQg8pjlEn0jQbcM/0D+xVaYjhw3cvarTanLLBh54oNiRbsT8PNK5GfuST0IlVXjsNRoNlqvY/fw==}
|
||||||
engines: {node: ^18.0.0 || >=20.0.0}
|
engines: {node: ^18.0.0 || >=20.0.0}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
@ -9049,15 +9033,15 @@ packages:
|
||||||
postcss:
|
postcss:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
vitest@2.0.1:
|
vitest@2.0.2:
|
||||||
resolution: {integrity: sha512-PBPvNXRJiywtI9NmbnEqHIhcXlk8mB0aKf6REQIaYGY4JtWF1Pg8Am+N0vAuxdg/wUSlxPSVJr8QdjwcVxc2Hg==}
|
resolution: {integrity: sha512-WlpZ9neRIjNBIOQwBYfBSr0+of5ZCbxT2TVGKW4Lv0c8+srCFIiRdsP7U009t8mMn821HQ4XKgkx5dVWpyoyLw==}
|
||||||
engines: {node: ^18.0.0 || >=20.0.0}
|
engines: {node: ^18.0.0 || >=20.0.0}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@edge-runtime/vm': '*'
|
'@edge-runtime/vm': '*'
|
||||||
'@types/node': ^18.0.0 || >=20.0.0
|
'@types/node': ^18.0.0 || >=20.0.0
|
||||||
'@vitest/browser': 2.0.1
|
'@vitest/browser': 2.0.2
|
||||||
'@vitest/ui': 2.0.1
|
'@vitest/ui': 2.0.2
|
||||||
happy-dom: '*'
|
happy-dom: '*'
|
||||||
jsdom: '*'
|
jsdom: '*'
|
||||||
peerDependenciesMeta:
|
peerDependenciesMeta:
|
||||||
|
@ -11250,10 +11234,8 @@ snapshots:
|
||||||
esquery: 1.6.0
|
esquery: 1.6.0
|
||||||
jsdoc-type-pratt-parser: 4.0.0
|
jsdoc-type-pratt-parser: 4.0.0
|
||||||
|
|
||||||
'@es-joy/jsdoccomment@0.45.0':
|
'@es-joy/jsdoccomment@0.46.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/eslint': 8.56.10
|
|
||||||
'@types/estree': 1.0.5
|
|
||||||
comment-parser: 1.4.1
|
comment-parser: 1.4.1
|
||||||
esquery: 1.6.0
|
esquery: 1.6.0
|
||||||
jsdoc-type-pratt-parser: 4.0.0
|
jsdoc-type-pratt-parser: 4.0.0
|
||||||
|
@ -11626,10 +11608,6 @@ snapshots:
|
||||||
wrap-ansi: 8.1.0
|
wrap-ansi: 8.1.0
|
||||||
wrap-ansi-cjs: wrap-ansi@7.0.0
|
wrap-ansi-cjs: wrap-ansi@7.0.0
|
||||||
|
|
||||||
'@jest/schemas@29.6.3':
|
|
||||||
dependencies:
|
|
||||||
'@sinclair/typebox': 0.27.8
|
|
||||||
|
|
||||||
'@jridgewell/gen-mapping@0.3.5':
|
'@jridgewell/gen-mapping@0.3.5':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@jridgewell/set-array': 1.2.1
|
'@jridgewell/set-array': 1.2.1
|
||||||
|
@ -12122,8 +12100,6 @@ snapshots:
|
||||||
core-js: 3.37.1
|
core-js: 3.37.1
|
||||||
nanopop: 2.4.2
|
nanopop: 2.4.2
|
||||||
|
|
||||||
'@sinclair/typebox@0.27.8': {}
|
|
||||||
|
|
||||||
'@sindresorhus/is@5.6.0': {}
|
'@sindresorhus/is@5.6.0': {}
|
||||||
|
|
||||||
'@sindresorhus/merge-streams@2.3.0': {}
|
'@sindresorhus/merge-streams@2.3.0': {}
|
||||||
|
@ -12445,33 +12421,38 @@ snapshots:
|
||||||
vite: 5.3.3(@types/node@20.14.10)(sass@1.77.7)(terser@5.31.2)
|
vite: 5.3.3(@types/node@20.14.10)(sass@1.77.7)(terser@5.31.2)
|
||||||
vue: 3.4.31(typescript@5.5.3)
|
vue: 3.4.31(typescript@5.5.3)
|
||||||
|
|
||||||
'@vitest/expect@2.0.1':
|
'@vitest/expect@2.0.2':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@vitest/spy': 2.0.1
|
'@vitest/spy': 2.0.2
|
||||||
'@vitest/utils': 2.0.1
|
'@vitest/utils': 2.0.2
|
||||||
chai: 5.1.1
|
chai: 5.1.1
|
||||||
|
tinyrainbow: 1.2.0
|
||||||
|
|
||||||
'@vitest/runner@2.0.1':
|
'@vitest/pretty-format@2.0.2':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@vitest/utils': 2.0.1
|
tinyrainbow: 1.2.0
|
||||||
|
|
||||||
|
'@vitest/runner@2.0.2':
|
||||||
|
dependencies:
|
||||||
|
'@vitest/utils': 2.0.2
|
||||||
pathe: 1.1.2
|
pathe: 1.1.2
|
||||||
|
|
||||||
'@vitest/snapshot@2.0.1':
|
'@vitest/snapshot@2.0.2':
|
||||||
dependencies:
|
dependencies:
|
||||||
|
'@vitest/pretty-format': 2.0.2
|
||||||
magic-string: 0.30.10
|
magic-string: 0.30.10
|
||||||
pathe: 1.1.2
|
pathe: 1.1.2
|
||||||
pretty-format: 29.7.0
|
|
||||||
|
|
||||||
'@vitest/spy@2.0.1':
|
'@vitest/spy@2.0.2':
|
||||||
dependencies:
|
dependencies:
|
||||||
tinyspy: 3.0.0
|
tinyspy: 3.0.0
|
||||||
|
|
||||||
'@vitest/utils@2.0.1':
|
'@vitest/utils@2.0.2':
|
||||||
dependencies:
|
dependencies:
|
||||||
diff-sequences: 29.6.3
|
'@vitest/pretty-format': 2.0.2
|
||||||
estree-walker: 3.0.3
|
estree-walker: 3.0.3
|
||||||
loupe: 3.1.1
|
loupe: 3.1.1
|
||||||
pretty-format: 29.7.0
|
tinyrainbow: 1.2.0
|
||||||
|
|
||||||
'@volar/language-core@1.11.1':
|
'@volar/language-core@1.11.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -12877,8 +12858,6 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
color-convert: 2.0.1
|
color-convert: 2.0.1
|
||||||
|
|
||||||
ansi-styles@5.2.0: {}
|
|
||||||
|
|
||||||
ansi-styles@6.2.1: {}
|
ansi-styles@6.2.1: {}
|
||||||
|
|
||||||
ant-design-vue@4.2.3(vue@3.4.31(typescript@5.5.3)):
|
ant-design-vue@4.2.3(vue@3.4.31(typescript@5.5.3)):
|
||||||
|
@ -13101,7 +13080,7 @@ snapshots:
|
||||||
browserslist@4.23.2:
|
browserslist@4.23.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
caniuse-lite: 1.0.30001641
|
caniuse-lite: 1.0.30001641
|
||||||
electron-to-chromium: 1.4.823
|
electron-to-chromium: 1.4.824
|
||||||
node-releases: 2.0.14
|
node-releases: 2.0.14
|
||||||
update-browserslist-db: 1.1.0(browserslist@4.23.2)
|
update-browserslist-db: 1.1.0(browserslist@4.23.2)
|
||||||
|
|
||||||
|
@ -13903,8 +13882,6 @@ snapshots:
|
||||||
|
|
||||||
didyoumean@1.2.2: {}
|
didyoumean@1.2.2: {}
|
||||||
|
|
||||||
diff-sequences@29.6.3: {}
|
|
||||||
|
|
||||||
diff@4.0.2: {}
|
diff@4.0.2: {}
|
||||||
|
|
||||||
dijkstrajs@1.0.3: {}
|
dijkstrajs@1.0.3: {}
|
||||||
|
@ -14006,7 +13983,7 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
jake: 10.9.1
|
jake: 10.9.1
|
||||||
|
|
||||||
electron-to-chromium@1.4.823: {}
|
electron-to-chromium@1.4.824: {}
|
||||||
|
|
||||||
emoji-regex@10.3.0: {}
|
emoji-regex@10.3.0: {}
|
||||||
|
|
||||||
|
@ -14287,9 +14264,9 @@ snapshots:
|
||||||
- eslint-import-resolver-webpack
|
- eslint-import-resolver-webpack
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
eslint-plugin-jsdoc@48.6.0(eslint@8.57.0):
|
eslint-plugin-jsdoc@48.7.0(eslint@8.57.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@es-joy/jsdoccomment': 0.45.0
|
'@es-joy/jsdoccomment': 0.46.0
|
||||||
are-docs-informative: 0.0.2
|
are-docs-informative: 0.0.2
|
||||||
comment-parser: 1.4.1
|
comment-parser: 1.4.1
|
||||||
debug: 4.3.5(supports-color@5.5.0)
|
debug: 4.3.5(supports-color@5.5.0)
|
||||||
|
@ -14395,13 +14372,13 @@ snapshots:
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@typescript-eslint/eslint-plugin': 7.16.0(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3)
|
'@typescript-eslint/eslint-plugin': 7.16.0(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3)
|
||||||
|
|
||||||
eslint-plugin-vitest@0.5.4(@typescript-eslint/eslint-plugin@7.16.0(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3)(vitest@2.0.1(@types/node@20.14.10)(jsdom@24.1.0)(sass@1.77.7)(terser@5.31.2)):
|
eslint-plugin-vitest@0.5.4(@typescript-eslint/eslint-plugin@7.16.0(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3)(vitest@2.0.2(@types/node@20.14.10)(jsdom@24.1.0)(sass@1.77.7)(terser@5.31.2)):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/utils': 7.16.0(eslint@8.57.0)(typescript@5.5.3)
|
'@typescript-eslint/utils': 7.16.0(eslint@8.57.0)(typescript@5.5.3)
|
||||||
eslint: 8.57.0
|
eslint: 8.57.0
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@typescript-eslint/eslint-plugin': 7.16.0(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3)
|
'@typescript-eslint/eslint-plugin': 7.16.0(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3)
|
||||||
vitest: 2.0.1(@types/node@20.14.10)(jsdom@24.1.0)(sass@1.77.7)(terser@5.31.2)
|
vitest: 2.0.2(@types/node@20.14.10)(jsdom@24.1.0)(sass@1.77.7)(terser@5.31.2)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
- typescript
|
- typescript
|
||||||
|
@ -14872,7 +14849,7 @@ snapshots:
|
||||||
glob@10.4.2:
|
glob@10.4.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
foreground-child: 3.2.1
|
foreground-child: 3.2.1
|
||||||
jackspeak: 3.4.2
|
jackspeak: 3.4.3
|
||||||
minimatch: 9.0.5
|
minimatch: 9.0.5
|
||||||
minipass: 7.1.2
|
minipass: 7.1.2
|
||||||
package-json-from-dist: 1.0.0
|
package-json-from-dist: 1.0.0
|
||||||
|
@ -14881,7 +14858,7 @@ snapshots:
|
||||||
glob@10.4.5:
|
glob@10.4.5:
|
||||||
dependencies:
|
dependencies:
|
||||||
foreground-child: 3.2.1
|
foreground-child: 3.2.1
|
||||||
jackspeak: 3.4.2
|
jackspeak: 3.4.3
|
||||||
minimatch: 9.0.5
|
minimatch: 9.0.5
|
||||||
minipass: 7.1.2
|
minipass: 7.1.2
|
||||||
package-json-from-dist: 1.0.0
|
package-json-from-dist: 1.0.0
|
||||||
|
@ -15423,7 +15400,7 @@ snapshots:
|
||||||
|
|
||||||
iterare@1.2.1: {}
|
iterare@1.2.1: {}
|
||||||
|
|
||||||
jackspeak@3.4.2:
|
jackspeak@3.4.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@isaacs/cliui': 8.0.2
|
'@isaacs/cliui': 8.0.2
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
|
@ -15497,7 +15474,7 @@ snapshots:
|
||||||
http-proxy-agent: 7.0.2
|
http-proxy-agent: 7.0.2
|
||||||
https-proxy-agent: 7.0.5
|
https-proxy-agent: 7.0.5
|
||||||
is-potential-custom-element-name: 1.0.1
|
is-potential-custom-element-name: 1.0.1
|
||||||
nwsapi: 2.2.10
|
nwsapi: 2.2.12
|
||||||
parse5: 7.1.2
|
parse5: 7.1.2
|
||||||
rrweb-cssom: 0.7.1
|
rrweb-cssom: 0.7.1
|
||||||
saxes: 6.0.0
|
saxes: 6.0.0
|
||||||
|
@ -16106,7 +16083,7 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
boolbase: 1.0.0
|
boolbase: 1.0.0
|
||||||
|
|
||||||
nwsapi@2.2.10: {}
|
nwsapi@2.2.12: {}
|
||||||
|
|
||||||
object-assign@4.1.1: {}
|
object-assign@4.1.1: {}
|
||||||
|
|
||||||
|
@ -16850,12 +16827,6 @@ snapshots:
|
||||||
|
|
||||||
pretty-bytes@6.1.1: {}
|
pretty-bytes@6.1.1: {}
|
||||||
|
|
||||||
pretty-format@29.7.0:
|
|
||||||
dependencies:
|
|
||||||
'@jest/schemas': 29.6.3
|
|
||||||
ansi-styles: 5.2.0
|
|
||||||
react-is: 18.3.1
|
|
||||||
|
|
||||||
process-nextick-args@2.0.1: {}
|
process-nextick-args@2.0.1: {}
|
||||||
|
|
||||||
promise-inflight@1.0.1: {}
|
promise-inflight@1.0.1: {}
|
||||||
|
@ -16952,8 +16923,6 @@ snapshots:
|
||||||
minimist: 1.2.8
|
minimist: 1.2.8
|
||||||
strip-json-comments: 2.0.1
|
strip-json-comments: 2.0.1
|
||||||
|
|
||||||
react-is@18.3.1: {}
|
|
||||||
|
|
||||||
read-cache@1.0.0:
|
read-cache@1.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
pify: 2.3.0
|
pify: 2.3.0
|
||||||
|
@ -17121,9 +17090,10 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
glob: 7.2.3
|
glob: 7.2.3
|
||||||
|
|
||||||
rimraf@6.0.0:
|
rimraf@6.0.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
glob: 11.0.0
|
glob: 11.0.0
|
||||||
|
package-json-from-dist: 1.0.0
|
||||||
|
|
||||||
rollup-plugin-dts@6.1.1(rollup@3.29.4)(typescript@5.5.3):
|
rollup-plugin-dts@6.1.1(rollup@3.29.4)(typescript@5.5.3):
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -17853,6 +17823,8 @@ snapshots:
|
||||||
|
|
||||||
tinypool@1.0.0: {}
|
tinypool@1.0.0: {}
|
||||||
|
|
||||||
|
tinyrainbow@1.2.0: {}
|
||||||
|
|
||||||
tinyspy@3.0.0: {}
|
tinyspy@3.0.0: {}
|
||||||
|
|
||||||
tmp@0.0.33:
|
tmp@0.0.33:
|
||||||
|
@ -18210,12 +18182,12 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
vite: 5.3.3(@types/node@20.14.10)(sass@1.77.7)(terser@5.31.2)
|
vite: 5.3.3(@types/node@20.14.10)(sass@1.77.7)(terser@5.31.2)
|
||||||
|
|
||||||
vite-node@2.0.1(@types/node@20.14.10)(sass@1.77.7)(terser@5.31.2):
|
vite-node@2.0.2(@types/node@20.14.10)(sass@1.77.7)(terser@5.31.2):
|
||||||
dependencies:
|
dependencies:
|
||||||
cac: 6.7.14
|
cac: 6.7.14
|
||||||
debug: 4.3.5(supports-color@5.5.0)
|
debug: 4.3.5(supports-color@5.5.0)
|
||||||
pathe: 1.1.2
|
pathe: 1.1.2
|
||||||
picocolors: 1.0.1
|
tinyrainbow: 1.2.0
|
||||||
vite: 5.3.3(@types/node@20.14.10)(sass@1.77.7)(terser@5.31.2)
|
vite: 5.3.3(@types/node@20.14.10)(sass@1.77.7)(terser@5.31.2)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@types/node'
|
- '@types/node'
|
||||||
|
@ -18392,25 +18364,26 @@ snapshots:
|
||||||
- typescript
|
- typescript
|
||||||
- universal-cookie
|
- universal-cookie
|
||||||
|
|
||||||
vitest@2.0.1(@types/node@20.14.10)(jsdom@24.1.0)(sass@1.77.7)(terser@5.31.2):
|
vitest@2.0.2(@types/node@20.14.10)(jsdom@24.1.0)(sass@1.77.7)(terser@5.31.2):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@ampproject/remapping': 2.3.0
|
'@ampproject/remapping': 2.3.0
|
||||||
'@vitest/expect': 2.0.1
|
'@vitest/expect': 2.0.2
|
||||||
'@vitest/runner': 2.0.1
|
'@vitest/pretty-format': 2.0.2
|
||||||
'@vitest/snapshot': 2.0.1
|
'@vitest/runner': 2.0.2
|
||||||
'@vitest/spy': 2.0.1
|
'@vitest/snapshot': 2.0.2
|
||||||
'@vitest/utils': 2.0.1
|
'@vitest/spy': 2.0.2
|
||||||
|
'@vitest/utils': 2.0.2
|
||||||
chai: 5.1.1
|
chai: 5.1.1
|
||||||
debug: 4.3.5(supports-color@5.5.0)
|
debug: 4.3.5(supports-color@5.5.0)
|
||||||
execa: 8.0.1
|
execa: 8.0.1
|
||||||
magic-string: 0.30.10
|
magic-string: 0.30.10
|
||||||
pathe: 1.1.2
|
pathe: 1.1.2
|
||||||
picocolors: 1.0.1
|
|
||||||
std-env: 3.7.0
|
std-env: 3.7.0
|
||||||
tinybench: 2.8.0
|
tinybench: 2.8.0
|
||||||
tinypool: 1.0.0
|
tinypool: 1.0.0
|
||||||
|
tinyrainbow: 1.2.0
|
||||||
vite: 5.3.3(@types/node@20.14.10)(sass@1.77.7)(terser@5.31.2)
|
vite: 5.3.3(@types/node@20.14.10)(sass@1.77.7)(terser@5.31.2)
|
||||||
vite-node: 2.0.1(@types/node@20.14.10)(sass@1.77.7)(terser@5.31.2)
|
vite-node: 2.0.2(@types/node@20.14.10)(sass@1.77.7)(terser@5.31.2)
|
||||||
why-is-node-running: 2.3.0
|
why-is-node-running: 2.3.0
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@types/node': 20.14.10
|
'@types/node': 20.14.10
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"#build": "pnpm unbuild",
|
|
||||||
"stub": "pnpm unbuild --stub"
|
"stub": "pnpm unbuild --stub"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
|
|
Loading…
Reference in New Issue