mirror of
https://github.com/vbenjs/vue-vben-admin.git
synced 2025-08-26 00:26:20 +08:00
Compare commits
13 Commits
dependabot
...
alova
Author | SHA1 | Date | |
---|---|---|---|
![]() |
382918b8f0 | ||
![]() |
b0d7b177be | ||
![]() |
566d3bdf7c | ||
![]() |
adbf793e79 | ||
![]() |
962141b778 | ||
![]() |
625837d9f7 | ||
![]() |
679231dbc8 | ||
![]() |
9b3cc2deb5 | ||
![]() |
63ccda1bbc | ||
![]() |
34c73b73d9 | ||
![]() |
0b6b4e00ef | ||
![]() |
2a06d3aa06 | ||
![]() |
d6a0ddea4c |
@@ -6,7 +6,7 @@ import {
|
||||
} from '~/utils/cookie-utils';
|
||||
import { generateAccessToken, verifyRefreshToken } from '~/utils/jwt-utils';
|
||||
import { MOCK_USERS } from '~/utils/mock-data';
|
||||
import { forbiddenResponse } from '~/utils/response';
|
||||
import { forbiddenResponse, useResponseSuccess } from '~/utils/response';
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
const refreshToken = getRefreshTokenFromCookie(event);
|
||||
@@ -30,6 +30,7 @@ export default defineEventHandler(async (event) => {
|
||||
const accessToken = generateAccessToken(findUser);
|
||||
|
||||
setRefreshTokenCookie(event, refreshToken);
|
||||
|
||||
return accessToken;
|
||||
return useResponseSuccess({
|
||||
accessToken,
|
||||
});
|
||||
});
|
||||
|
@@ -82,7 +82,7 @@ defineExpose({
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Teleport :to="appendTo">
|
||||
<Teleport defer :to="appendTo">
|
||||
<Transition name="fade">
|
||||
<DialogOverlay
|
||||
v-if="open && modal"
|
||||
|
@@ -73,7 +73,7 @@ function onAnimationEnd(event: AnimationEvent) {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Teleport :to="appendTo">
|
||||
<Teleport defer :to="appendTo">
|
||||
<Transition name="fade">
|
||||
<SheetOverlay
|
||||
v-if="open && modal"
|
||||
|
@@ -103,10 +103,15 @@ function updateTreeValue() {
|
||||
treeValue.value = undefined;
|
||||
} else {
|
||||
if (Array.isArray(val)) {
|
||||
const filteredValues = val.filter((v) => {
|
||||
let filteredValues = val.filter((v) => {
|
||||
const item = getItemByValue(v);
|
||||
return item && !get(item, props.disabledField);
|
||||
});
|
||||
|
||||
if (!props.checkStrictly && props.autoCheckParent) {
|
||||
filteredValues = processParentSelection(filteredValues);
|
||||
}
|
||||
|
||||
treeValue.value = filteredValues.map((v) => getItemByValue(v));
|
||||
|
||||
if (filteredValues.length !== val.length) {
|
||||
@@ -123,7 +128,35 @@ function updateTreeValue() {
|
||||
}
|
||||
}
|
||||
}
|
||||
function processParentSelection(
|
||||
selectedValues: Array<number | string>,
|
||||
): Array<number | string> {
|
||||
if (props.checkStrictly) return selectedValues;
|
||||
|
||||
const result = [...selectedValues];
|
||||
|
||||
for (let i = result.length - 1; i >= 0; i--) {
|
||||
const currentValue = result[i];
|
||||
if (currentValue === undefined) continue;
|
||||
const currentItem = getItemByValue(currentValue);
|
||||
|
||||
if (!currentItem) continue;
|
||||
|
||||
const children = get(currentItem, props.childrenField);
|
||||
if (Array.isArray(children) && children.length > 0) {
|
||||
const hasSelectedChildren = children.some((child) => {
|
||||
const childValue = get(child, props.valueField);
|
||||
return result.includes(childValue);
|
||||
});
|
||||
|
||||
if (!hasSelectedChildren) {
|
||||
result.splice(i, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
function updateModelValue(val: Arrayable<Recordable<any>>) {
|
||||
if (Array.isArray(val)) {
|
||||
const filteredVal = val.filter((v) => !get(v, props.disabledField));
|
||||
|
@@ -104,7 +104,7 @@ function selectColor() {
|
||||
|
||||
watch(
|
||||
() => [modelValue.value, props.isDark] as [BuiltinThemeType, boolean],
|
||||
([themeType, isDark]) => {
|
||||
([themeType, isDark], [_, isDarkPrev]) => {
|
||||
const theme = builtinThemePresets.value.find(
|
||||
(item) => item.type === themeType,
|
||||
);
|
||||
@@ -113,7 +113,9 @@ watch(
|
||||
? theme.darkPrimaryColor || theme.primaryColor
|
||||
: theme.primaryColor;
|
||||
|
||||
themeColorPrimary.value = primaryColor || theme.color;
|
||||
if (!(theme.type === 'custom' && isDark !== isDarkPrev)) {
|
||||
themeColorPrimary.value = primaryColor || theme.color;
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
|
@@ -25,6 +25,10 @@
|
||||
"./motion": {
|
||||
"types": "./src/motion/index.ts",
|
||||
"default": "./src/motion/index.ts"
|
||||
},
|
||||
"./alova": {
|
||||
"types": "./src/alova/index.ts",
|
||||
"default": "./src/alova/index.ts"
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
@@ -41,6 +45,7 @@
|
||||
"@vueuse/motion": "catalog:",
|
||||
"echarts": "catalog:",
|
||||
"vue": "catalog:",
|
||||
"alova": "catalog:",
|
||||
"vxe-pc-ui": "catalog:",
|
||||
"vxe-table": "catalog:"
|
||||
}
|
||||
|
254
packages/effects/plugins/src/alova/index.ts
Normal file
254
packages/effects/plugins/src/alova/index.ts
Normal file
@@ -0,0 +1,254 @@
|
||||
import type {
|
||||
Alova,
|
||||
AlovaGenerics,
|
||||
AlovaMethodCommonConfig,
|
||||
AlovaMethodCreateConfig,
|
||||
AlovaOptions,
|
||||
Method,
|
||||
RequestBody,
|
||||
RespondedAlovaGenerics,
|
||||
ResponseCompleteHandler,
|
||||
ResponseErrorHandler,
|
||||
ResponseSuccessHandler,
|
||||
StatesHook,
|
||||
} from 'alova';
|
||||
import type {
|
||||
AlovaRequestAdapterUnified,
|
||||
TokenAuthenticationResult,
|
||||
} from 'alova/client';
|
||||
|
||||
import { createAlova } from 'alova';
|
||||
import adapterFetch from 'alova/fetch';
|
||||
import VueHook from 'alova/vue';
|
||||
|
||||
/**
|
||||
* 请求拦截器方法类型
|
||||
*/
|
||||
type RequestMethod<T extends AlovaGenerics = AlovaGenerics> = (
|
||||
method: Method<T>,
|
||||
) => Promise<void> | void;
|
||||
|
||||
/**
|
||||
* Alova HTTP客户端封装类
|
||||
* @template T 泛型参数,继承自AlovaGenerics
|
||||
*/
|
||||
class AlovaClient<T extends AlovaGenerics = AlovaGenerics> {
|
||||
public readonly instance: Alova<T>;
|
||||
|
||||
/**
|
||||
* 请求拦截器数组
|
||||
*/
|
||||
public requestInterceptor: RequestMethod<T>[] = [];
|
||||
|
||||
/**
|
||||
* 请求完成拦截器数组
|
||||
*/
|
||||
public responseCompleteInterceptor: ResponseCompleteHandler<T>[] = [];
|
||||
|
||||
/**
|
||||
* 请求错误拦截器数组
|
||||
*/
|
||||
public responseErrorInterceptor: ResponseErrorHandler<T>[] = [];
|
||||
|
||||
/**
|
||||
* 请求成功拦截器数组
|
||||
*/
|
||||
public responseSuccessInterceptor: ResponseSuccessHandler<T>[] = [];
|
||||
/**
|
||||
* 构造函数
|
||||
* @param options Alova配置选项
|
||||
* @param authOptions 认证选项
|
||||
*/
|
||||
constructor(
|
||||
options: AlovaOptions<T>,
|
||||
authOptions?: TokenAuthenticationResult<
|
||||
StatesHook<any>,
|
||||
AlovaRequestAdapterUnified
|
||||
>,
|
||||
) {
|
||||
const { onAuthRequired, onResponseRefreshToken } = authOptions || {};
|
||||
const beforeRequest = async (method: Method<T>) => {
|
||||
for (const interceptor of this.requestInterceptor) {
|
||||
await interceptor(method);
|
||||
}
|
||||
};
|
||||
const responded = {
|
||||
// 请求成功的拦截器
|
||||
// 当使用 `alova/fetch` 请求适配器时,第一个参数接收Response对象
|
||||
// 第二个参数为当前请求的method实例,你可以用它同步请求前后的配置信息
|
||||
onSuccess: async (response: Response, method: Method<T>) => {
|
||||
let result: any = null;
|
||||
for (const interceptor of this.responseSuccessInterceptor) {
|
||||
result = await interceptor(response, method);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onError: async (err: Error, method: Method<T>) => {
|
||||
for (const interceptor of this.responseErrorInterceptor) {
|
||||
await interceptor(err, method);
|
||||
}
|
||||
},
|
||||
|
||||
// 请求完成的拦截器
|
||||
// 当你需要在请求不论是成功、失败、还是命中缓存都需要执行的逻辑时,可以在创建alova实例时指定全局的`onComplete`拦截器,例如关闭请求 loading 状态。
|
||||
// 接收当前请求的method实例
|
||||
onComplete: async (method: Method<T>) => {
|
||||
// 处理请求完成逻辑
|
||||
for (const interceptor of this.responseCompleteInterceptor) {
|
||||
await interceptor(method);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
this.instance = createAlova({
|
||||
requestAdapter: adapterFetch(),
|
||||
statesHook: VueHook,
|
||||
beforeRequest: onAuthRequired
|
||||
? onAuthRequired(beforeRequest)
|
||||
: beforeRequest,
|
||||
// 使用 responded 对象分别指定请求成功的拦截器和请求失败的拦截器
|
||||
responded: onResponseRefreshToken
|
||||
? onResponseRefreshToken(responded)
|
||||
: responded,
|
||||
...options,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 添加请求拦截器
|
||||
* @param method 拦截器方法
|
||||
*/
|
||||
public addRequestInterceptor(method: RequestMethod<T>) {
|
||||
this.requestInterceptor.push(method);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加请求完成拦截器
|
||||
* @param method 拦截器方法
|
||||
*/
|
||||
public addResponseCompleteInterceptor(method: ResponseCompleteHandler<T>) {
|
||||
this.responseCompleteInterceptor.push(method);
|
||||
}
|
||||
/**
|
||||
* 添加请求错误拦截器
|
||||
* @param method 拦截器方法
|
||||
*/
|
||||
public addResponseErrorInterceptor(method: ResponseErrorHandler<T>) {
|
||||
this.responseErrorInterceptor.push(method);
|
||||
}
|
||||
/**
|
||||
* 添加请求成功拦截器
|
||||
* @param method 拦截器方法
|
||||
*/
|
||||
public addResponseSuccessInterceptor(method: ResponseSuccessMethod) {
|
||||
this.responseSuccessInterceptor.push(method);
|
||||
}
|
||||
/**
|
||||
* 发送DELETE请求
|
||||
* @param url 请求地址
|
||||
* @param data 请求数据
|
||||
* @param config 请求配置
|
||||
* @returns Method实例
|
||||
*/
|
||||
public delete<Responded = unknown, Transformed = unknown>(
|
||||
url: string,
|
||||
data?: RequestBody,
|
||||
config?: AlovaMethodCreateConfig<T, Responded, Transformed>,
|
||||
): Method<RespondedAlovaGenerics<T, Responded, Transformed>> {
|
||||
return this.instance.Delete(url, config, data);
|
||||
}
|
||||
/**
|
||||
* 发送GET请求
|
||||
* @param url 请求地址
|
||||
* @param config 请求配置
|
||||
* @returns Method实例
|
||||
*/
|
||||
public get<Responded = unknown, Transformed = unknown>(
|
||||
url: string,
|
||||
config?: AlovaMethodCreateConfig<T, Responded, Transformed>,
|
||||
): Method<RespondedAlovaGenerics<T, Responded, Transformed>> {
|
||||
return this.instance.Get(url, config);
|
||||
}
|
||||
/**
|
||||
* 发送HEAD请求
|
||||
* @param url 请求地址
|
||||
* @param config 请求配置
|
||||
* @returns Method实例
|
||||
*/
|
||||
public head<Responded = unknown, Transformed = unknown>(
|
||||
url: string,
|
||||
config?: AlovaMethodCreateConfig<T, Responded, Transformed>,
|
||||
): Method<RespondedAlovaGenerics<T, Responded, Transformed>> {
|
||||
return this.instance.Head(url, config);
|
||||
}
|
||||
/**
|
||||
* 发送OPTIONS请求
|
||||
* @param url 请求地址
|
||||
* @param config 请求配置
|
||||
* @returns Method实例
|
||||
*/
|
||||
public options<Responded = unknown, Transformed = unknown>(
|
||||
url: string,
|
||||
config?: AlovaMethodCreateConfig<T, Responded, Transformed>,
|
||||
): Method<RespondedAlovaGenerics<T, Responded, Transformed>> {
|
||||
return this.instance.Options(url, config);
|
||||
}
|
||||
/**
|
||||
* 发送PATCH请求
|
||||
* @param url 请求地址
|
||||
* @param data 请求数据
|
||||
* @param config 请求配置
|
||||
* @returns Method实例
|
||||
*/
|
||||
public patch<Responded = unknown, Transformed = unknown>(
|
||||
url: string,
|
||||
data?: RequestBody,
|
||||
config?: AlovaMethodCreateConfig<T, Responded, Transformed>,
|
||||
): Method<RespondedAlovaGenerics<T, Responded, Transformed>> {
|
||||
return this.instance.Patch(url, data, config);
|
||||
}
|
||||
/**
|
||||
* 发送POST请求
|
||||
* @param url 请求地址
|
||||
* @param data 请求数据
|
||||
* @param config 请求配置
|
||||
* @returns Method实例
|
||||
*/
|
||||
public post<Responded = unknown, Transformed = unknown>(
|
||||
url: string,
|
||||
data?: RequestBody,
|
||||
config?: AlovaMethodCreateConfig<T, Responded, Transformed>,
|
||||
): Method<RespondedAlovaGenerics<T, Responded, Transformed>> {
|
||||
return this.instance.Post(url, data, config);
|
||||
}
|
||||
/**
|
||||
* 发送PUT请求
|
||||
* @param url 请求地址
|
||||
* @param data 请求数据
|
||||
* @param config 请求配置
|
||||
* @returns Method实例
|
||||
*/
|
||||
public put<Responded = unknown, Transformed = unknown>(
|
||||
url: string,
|
||||
data?: RequestBody,
|
||||
config?: AlovaMethodCreateConfig<T, Responded, Transformed>,
|
||||
): Method<RespondedAlovaGenerics<T, Responded, Transformed>> {
|
||||
return this.instance.Put(url, data, config);
|
||||
}
|
||||
/**
|
||||
* 发送自定义请求
|
||||
* @param config 请求配置
|
||||
* @returns Method实例
|
||||
*/
|
||||
public request<Responded = unknown, Transformed = unknown>(
|
||||
config: AlovaMethodCommonConfig<T, Responded, Transformed>,
|
||||
): Method<RespondedAlovaGenerics<T, Responded, Transformed>> {
|
||||
return this.instance.Request(config);
|
||||
}
|
||||
}
|
||||
|
||||
export { AlovaClient, VueHook };
|
||||
export * from 'alova';
|
||||
export * from 'alova/client';
|
@@ -1,4 +1,4 @@
|
||||
import { baseRequestClient, requestClient } from '#/api/request';
|
||||
import { client, requestClient } from '#/api/request';
|
||||
|
||||
export namespace AuthApi {
|
||||
/** 登录接口参数 */
|
||||
@@ -21,32 +21,54 @@ export namespace AuthApi {
|
||||
/**
|
||||
* 登录
|
||||
*/
|
||||
export async function loginApi(data: AuthApi.LoginParams) {
|
||||
return requestClient.post<AuthApi.LoginResult>('/auth/login', data, {
|
||||
withCredentials: true,
|
||||
});
|
||||
// export async function loginApi(data: AuthApi.LoginParams) {
|
||||
// return requestClient.post<AuthApi.LoginResult>('/auth/login', data, {
|
||||
// withCredentials: true,
|
||||
// });
|
||||
// }
|
||||
export async function loginApi(params: AuthApi.LoginParams) {
|
||||
const method = client.post<AuthApi.LoginResult>('/auth/login', params);
|
||||
method.meta = {
|
||||
authRole: 'login',
|
||||
};
|
||||
return method;
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新accessToken
|
||||
*/
|
||||
// export async function refreshTokenApi() {
|
||||
// return baseRequestClient.post<AuthApi.RefreshTokenResult>(
|
||||
// '/auth/refresh',
|
||||
// null,
|
||||
// {
|
||||
// withCredentials: true,
|
||||
// },
|
||||
// );
|
||||
// }
|
||||
export async function refreshTokenApi() {
|
||||
return baseRequestClient.post<AuthApi.RefreshTokenResult>(
|
||||
'/auth/refresh',
|
||||
null,
|
||||
{
|
||||
withCredentials: true,
|
||||
},
|
||||
);
|
||||
const method = client.post<AuthApi.RefreshTokenResult>('/auth/refresh');
|
||||
method.meta = {
|
||||
authRole: 'refreshToken',
|
||||
};
|
||||
return method;
|
||||
}
|
||||
|
||||
/**
|
||||
* 退出登录
|
||||
*/
|
||||
// export async function logoutApi() {
|
||||
// return baseRequestClient.post('/auth/logout', null, {
|
||||
// withCredentials: true,
|
||||
// });
|
||||
// }
|
||||
|
||||
export async function logoutApi() {
|
||||
return baseRequestClient.post('/auth/logout', null, {
|
||||
withCredentials: true,
|
||||
});
|
||||
const method = client.post('/auth/logout');
|
||||
method.meta = {
|
||||
authRole: 'logout',
|
||||
};
|
||||
return method;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -1,10 +1,13 @@
|
||||
import type { UserInfo } from '@vben/types';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
import { client } from '#/api/request';
|
||||
|
||||
/**
|
||||
* 获取用户信息
|
||||
*/
|
||||
// export async function getUserInfoApi() {
|
||||
// return requestClient.get<UserInfo>('/user/info');
|
||||
// }
|
||||
export async function getUserInfoApi() {
|
||||
return requestClient.get<UserInfo>('/user/info');
|
||||
return client.get<UserInfo>('/user/info');
|
||||
}
|
||||
|
@@ -4,6 +4,11 @@
|
||||
import type { AxiosResponseHeaders, RequestClientOptions } from '@vben/request';
|
||||
|
||||
import { useAppConfig } from '@vben/hooks';
|
||||
import {
|
||||
AlovaClient,
|
||||
createServerTokenAuthentication,
|
||||
VueHook,
|
||||
} from '@vben/plugins/alova';
|
||||
import { preferences } from '@vben/preferences';
|
||||
import {
|
||||
authenticateResponseInterceptor,
|
||||
@@ -127,3 +132,76 @@ export interface PageFetchParams {
|
||||
pageNo?: number;
|
||||
pageSize?: number;
|
||||
}
|
||||
|
||||
let count = 0;
|
||||
interface ResponseData<T = unknown> {
|
||||
[key: string]: unknown;
|
||||
code?: number;
|
||||
data?: T;
|
||||
message?: string;
|
||||
}
|
||||
const { onAuthRequired, onResponseRefreshToken } =
|
||||
createServerTokenAuthentication<typeof VueHook>({
|
||||
async login(response) {
|
||||
// const accessStore = useAccessStore();
|
||||
if (response.status >= 400) {
|
||||
throw new Error(response.statusText);
|
||||
}
|
||||
const json = await response.clone().json();
|
||||
if (json.code !== 0) {
|
||||
throw new Error(json.message);
|
||||
}
|
||||
// accessStore.setAccessToken(json.access_token);
|
||||
},
|
||||
assignToken: (method) => {
|
||||
const accessStore = useAccessStore();
|
||||
const accessToken = accessStore.accessToken;
|
||||
method.config.headers['Accept-Language'] = preferences.app.locale;
|
||||
method.config.headers.Authorization = accessToken
|
||||
? `Bearer ${accessToken}`
|
||||
: null;
|
||||
},
|
||||
logout(response, method) {
|
||||
console.log(response, method);
|
||||
},
|
||||
refreshTokenOnSuccess: {
|
||||
// 在请求前触发,将接收到method参数,并返回boolean表示token是否过期
|
||||
isExpired: (response) => {
|
||||
if (count > 5) {
|
||||
return false;
|
||||
}
|
||||
count++;
|
||||
return response.status === 401;
|
||||
},
|
||||
|
||||
// 当token过期时触发,在此函数中触发刷新token
|
||||
handler: async (method) => {
|
||||
try {
|
||||
const accessStore = useAccessStore();
|
||||
const { accessToken } = await refreshTokenApi();
|
||||
accessStore.setAccessToken(accessToken);
|
||||
} catch (error) {
|
||||
// token刷新失败,跳转回登录页
|
||||
location.href = '/login';
|
||||
// 并抛出错误
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
export const client = new AlovaClient<ResponseData>(
|
||||
{ baseURL: apiURL },
|
||||
{ onAuthRequired, onResponseRefreshToken },
|
||||
);
|
||||
|
||||
client.addResponseSuccessInterceptor(async (response, method) => {
|
||||
if (response.status >= 400) {
|
||||
throw new Error(response.statusText);
|
||||
}
|
||||
const json = await response.clone().json();
|
||||
|
||||
if (json.code !== 0) {
|
||||
throw new Error(json.message);
|
||||
}
|
||||
return json.data;
|
||||
});
|
||||
|
@@ -38,7 +38,7 @@ export const useAuthStore = defineStore('auth', () => {
|
||||
|
||||
// 如果成功获取到 accessToken
|
||||
if (accessToken) {
|
||||
accessStore.setAccessToken(accessToken);
|
||||
// accessStore.setAccessToken(accessToken);
|
||||
|
||||
// 获取用户信息并存储到 accessStore 中
|
||||
const [fetchUserInfoResult, accessCodes] = await Promise.all([
|
||||
|
4095
pnpm-lock.yaml
generated
4095
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -14,31 +14,31 @@ packages:
|
||||
- playground
|
||||
|
||||
catalog:
|
||||
'@ast-grep/napi': ^0.39.4
|
||||
'@ast-grep/napi': ^0.37.0
|
||||
'@changesets/changelog-github': ^0.5.1
|
||||
'@changesets/cli': ^2.29.6
|
||||
'@changesets/cli': ^2.29.5
|
||||
'@changesets/git': ^3.0.4
|
||||
'@clack/prompts': ^0.11.0
|
||||
'@clack/prompts': ^0.10.1
|
||||
'@commitlint/cli': ^19.8.1
|
||||
'@commitlint/config-conventional': ^19.8.1
|
||||
'@ctrl/tinycolor': ^4.1.0
|
||||
'@eslint/js': ^9.33.0
|
||||
'@eslint/js': ^9.30.1
|
||||
'@faker-js/faker': ^9.9.0
|
||||
'@iconify/json': ^2.2.377
|
||||
'@iconify/json': ^2.2.354
|
||||
'@iconify/tailwind': ^1.2.0
|
||||
'@iconify/vue': ^5.0.0
|
||||
'@intlify/core-base': ^11.1.11
|
||||
'@intlify/core-base': ^11.1.7
|
||||
'@intlify/unplugin-vue-i18n': ^6.0.8
|
||||
'@jspm/generator': ^2.6.3
|
||||
'@jspm/generator': ^2.6.2
|
||||
'@manypkg/get-packages': ^3.0.0
|
||||
'@nolebase/vitepress-plugin-git-changelog': ^2.18.2
|
||||
'@playwright/test': ^1.55.0
|
||||
'@pnpm/workspace.read-manifest': ^1000.2.2
|
||||
'@nolebase/vitepress-plugin-git-changelog': ^2.18.0
|
||||
'@playwright/test': ^1.53.2
|
||||
'@pnpm/workspace.read-manifest': ^1000.2.0
|
||||
'@stylistic/stylelint-plugin': ^3.1.3
|
||||
'@tailwindcss/nesting': 0.0.0-insiders.565cd3e
|
||||
'@tailwindcss/typography': ^0.5.16
|
||||
'@tanstack/vue-query': ^5.85.5
|
||||
'@tanstack/vue-store': ^0.7.4
|
||||
'@tanstack/vue-query': ^5.81.5
|
||||
'@tanstack/vue-store': ^0.7.1
|
||||
'@types/archiver': ^6.0.3
|
||||
'@types/eslint': ^9.6.1
|
||||
'@types/html-minifier-terser': ^7.0.2
|
||||
@@ -54,14 +54,14 @@ catalog:
|
||||
'@types/qrcode': ^1.5.5
|
||||
'@types/qs': ^6.14.0
|
||||
'@types/sortablejs': ^1.15.8
|
||||
'@typescript-eslint/eslint-plugin': ^8.40.0
|
||||
'@typescript-eslint/parser': ^8.40.0
|
||||
'@typescript-eslint/eslint-plugin': ^8.35.1
|
||||
'@typescript-eslint/parser': ^8.35.1
|
||||
'@vee-validate/zod': ^4.15.1
|
||||
'@vite-pwa/vitepress': ^1.0.0
|
||||
'@vitejs/plugin-vue': ^6.0.1
|
||||
'@vitejs/plugin-vue-jsx': ^5.0.1
|
||||
'@vue/reactivity': ^3.5.17
|
||||
'@vue/shared': ^3.5.19
|
||||
'@vue/shared': ^3.5.17
|
||||
'@vue/test-utils': ^2.4.6
|
||||
'@vueuse/core': ^13.4.0
|
||||
'@vueuse/integrations': ^13.4.0
|
||||
@@ -69,11 +69,12 @@ catalog:
|
||||
ant-design-vue: ^4.2.6
|
||||
archiver: ^7.0.1
|
||||
autoprefixer: ^10.4.21
|
||||
axios: ^1.11.0
|
||||
axios: ^1.10.0
|
||||
axios-mock-adapter: ^2.1.0
|
||||
cac: ^6.7.14
|
||||
chalk: ^5.4.1
|
||||
cheerio: ^1.1.2
|
||||
alova: ^3.3.4
|
||||
cheerio: ^1.1.0
|
||||
circular-dependency-scanner: ^2.3.0
|
||||
class-variance-authority: ^0.7.1
|
||||
clsx: ^2.1.1
|
||||
@@ -81,57 +82,57 @@ catalog:
|
||||
consola: ^3.4.2
|
||||
cross-env: ^7.0.3
|
||||
cspell: ^8.19.4
|
||||
cssnano: ^7.1.1
|
||||
cz-git: ^1.12.0
|
||||
czg: ^1.12.0
|
||||
cssnano: ^7.0.7
|
||||
cz-git: ^1.11.2
|
||||
czg: ^1.11.1
|
||||
dayjs: ^1.11.13
|
||||
defu: ^6.1.4
|
||||
depcheck: ^1.4.7
|
||||
dotenv: ^16.6.1
|
||||
echarts: ^5.6.0
|
||||
element-plus: ^2.11.0
|
||||
eslint: ^9.33.0
|
||||
eslint-config-turbo: ^2.5.6
|
||||
element-plus: ^2.10.2
|
||||
eslint: ^9.30.1
|
||||
eslint-config-turbo: ^2.5.4
|
||||
eslint-plugin-command: ^3.3.1
|
||||
eslint-plugin-eslint-comments: ^3.2.0
|
||||
eslint-plugin-import-x: ^4.16.1
|
||||
eslint-plugin-jsdoc: ^50.8.0
|
||||
eslint-plugin-jsonc: ^2.20.1
|
||||
eslint-plugin-n: ^17.21.3
|
||||
eslint-plugin-n: ^17.20.0
|
||||
eslint-plugin-no-only-tests: ^3.3.0
|
||||
eslint-plugin-perfectionist: ^4.15.0
|
||||
eslint-plugin-prettier: ^5.5.4
|
||||
eslint-plugin-regexp: ^2.10.0
|
||||
eslint-plugin-prettier: ^5.5.1
|
||||
eslint-plugin-regexp: ^2.9.0
|
||||
eslint-plugin-unicorn: ^59.0.1
|
||||
eslint-plugin-unused-imports: ^4.2.0
|
||||
eslint-plugin-unused-imports: ^4.1.4
|
||||
eslint-plugin-vitest: ^0.5.4
|
||||
eslint-plugin-vue: ^10.4.0
|
||||
eslint-plugin-vue: ^10.2.0
|
||||
execa: ^9.6.0
|
||||
find-up: ^7.0.0
|
||||
get-port: ^7.1.0
|
||||
globals: ^16.3.0
|
||||
h3: ^1.15.4
|
||||
h3: ^1.15.3
|
||||
happy-dom: ^17.6.3
|
||||
html-minifier-terser: ^7.2.0
|
||||
is-ci: ^4.1.0
|
||||
json-bigint: ^1.0.0
|
||||
jsonc-eslint-parser: ^2.4.0
|
||||
jsonwebtoken: ^9.0.2
|
||||
lefthook: ^1.12.3
|
||||
lefthook: ^1.11.14
|
||||
lodash.clonedeep: ^4.5.0
|
||||
lodash.get: ^4.4.2
|
||||
lodash.isequal: ^4.5.0
|
||||
lodash.set: ^4.3.2
|
||||
lucide-vue-next: ^0.541.0
|
||||
lucide-vue-next: ^0.507.0
|
||||
medium-zoom: ^1.1.0
|
||||
naive-ui: ^2.42.0
|
||||
nitropack: ^2.12.4
|
||||
nitropack: ^2.11.13
|
||||
nprogress: ^0.2.0
|
||||
ora: ^8.2.0
|
||||
pinia: ^3.0.3
|
||||
pinia-plugin-persistedstate: ^4.5.0
|
||||
pinia-plugin-persistedstate: ^4.4.1
|
||||
pkg-types: ^2.2.0
|
||||
playwright: ^1.55.0
|
||||
playwright: ^1.53.2
|
||||
postcss: ^8.5.6
|
||||
postcss-antd-fixes: ^0.2.0
|
||||
postcss-html: ^1.8.0
|
||||
@@ -139,7 +140,7 @@ catalog:
|
||||
postcss-preset-env: ^10.2.4
|
||||
postcss-scss: ^4.0.9
|
||||
prettier: ^3.6.2
|
||||
prettier-plugin-tailwindcss: ^0.6.14
|
||||
prettier-plugin-tailwindcss: ^0.6.13
|
||||
publint: ^0.3.12
|
||||
qrcode: ^1.5.4
|
||||
qs: ^6.14.0
|
||||
@@ -148,10 +149,10 @@ catalog:
|
||||
rimraf: ^6.0.1
|
||||
rollup: ^4.44.1
|
||||
rollup-plugin-visualizer: ^5.14.0
|
||||
sass: ^1.90.0
|
||||
sass: ^1.89.2
|
||||
secure-ls: ^2.0.0
|
||||
sortablejs: ^1.15.6
|
||||
stylelint: ^16.23.1
|
||||
stylelint: ^16.21.0
|
||||
stylelint-config-recess-order: ^6.1.0
|
||||
stylelint-config-recommended: ^16.0.0
|
||||
stylelint-config-recommended-scss: ^14.1.0
|
||||
@@ -165,8 +166,8 @@ catalog:
|
||||
tailwindcss-animate: ^1.0.7
|
||||
theme-colors: ^0.1.0
|
||||
tippy.js: ^6.3.7
|
||||
turbo: ^2.5.6
|
||||
typescript: ^5.9.2
|
||||
turbo: ^2.5.4
|
||||
typescript: ^5.8.3
|
||||
unbuild: ^3.6.1
|
||||
unplugin-element-plus: ^0.10.0
|
||||
vee-validate: ^4.15.1
|
||||
@@ -175,20 +176,20 @@ catalog:
|
||||
vite-plugin-dts: ^4.5.4
|
||||
vite-plugin-html: ^3.2.2
|
||||
vite-plugin-lazy-import: ^1.0.7
|
||||
vite-plugin-pwa: ^1.0.3
|
||||
vite-plugin-pwa: ^1.0.1
|
||||
vite-plugin-vue-devtools: ^7.7.7
|
||||
vitepress: ^1.6.4
|
||||
vitepress-plugin-group-icons: ^1.6.3
|
||||
vitepress: ^1.6.3
|
||||
vitepress-plugin-group-icons: ^1.6.1
|
||||
vitest: ^3.2.4
|
||||
vue: ^3.5.19
|
||||
vue: ^3.5.17
|
||||
vue-eslint-parser: ^10.2.0
|
||||
vue-i18n: ^11.1.11
|
||||
vue-i18n: ^11.1.7
|
||||
vue-json-viewer: ^3.0.4
|
||||
vue-router: ^4.5.1
|
||||
vue-tippy: ^6.7.1
|
||||
vue-tsc: 2.2.10
|
||||
vxe-pc-ui: ^4.8.24
|
||||
vxe-table: ^4.15.10
|
||||
watermark-js-plus: ^1.6.3
|
||||
vxe-pc-ui: ^4.7.12
|
||||
vxe-table: ^4.14.4
|
||||
watermark-js-plus: ^1.6.2
|
||||
zod: ^3.25.67
|
||||
zod-defaults: ^0.1.3
|
||||
|
Reference in New Issue
Block a user