This commit is contained in:
dap
2024-09-20 08:06:53 +08:00
69 changed files with 2200 additions and 1218 deletions

View File

@@ -34,8 +34,8 @@
}
},
"dependencies": {
"@iconify/vue": "^4.1.2",
"lucide-vue-next": "^0.441.0",
"vue": "^3.5.6"
"@iconify/vue": "catalog:",
"lucide-vue-next": "catalog:",
"vue": "catalog:"
}
}

View File

@@ -69,19 +69,19 @@
}
},
"dependencies": {
"@ctrl/tinycolor": "^4.1.0",
"@tanstack/vue-store": "^0.5.5",
"@vue/reactivity": "^3.5.6",
"@vue/shared": "^3.5.6",
"clsx": "^2.1.1",
"defu": "^6.1.4",
"lodash.clonedeep": "^4.5.0",
"nprogress": "^0.2.0",
"tailwind-merge": "^2.5.2",
"theme-colors": "^0.1.0"
"@ctrl/tinycolor": "catalog:",
"@tanstack/vue-store": "catalog:",
"@vue/reactivity": "catalog:",
"@vue/shared": "catalog:",
"clsx": "catalog:",
"defu": "catalog:",
"lodash.clonedeep": "catalog:",
"nprogress": "catalog:",
"tailwind-merge": "catalog:",
"theme-colors": "catalog:"
},
"devDependencies": {
"@types/lodash.clonedeep": "^4.5.9",
"@types/nprogress": "^0.2.3"
"@types/lodash.clonedeep": "catalog:",
"@types/nprogress": "catalog:"
}
}

View File

@@ -69,3 +69,19 @@ export function getScrollbarWidth() {
scrollDiv.remove();
return scrollbarWidth;
}
export function needsScrollbar() {
const doc = document.documentElement;
const body = document.body;
// 检查 body 的 overflow-y 样式
const overflowY = window.getComputedStyle(body).overflowY;
// 如果明确设置了需要滚动条的样式
if (overflowY === 'scroll' || overflowY === 'auto') {
return doc.scrollHeight > window.innerHeight;
}
// 在其他情况下,根据 scrollHeight 和 innerHeight 比较判断
return doc.scrollHeight > window.innerHeight;
}

View File

@@ -38,7 +38,7 @@
}
},
"dependencies": {
"vue": "^3.5.6",
"vue-router": "^4.4.5"
"vue": "catalog:",
"vue-router": "catalog:"
}
}

View File

@@ -36,12 +36,12 @@
},
"dependencies": {
"@vben-core/shared": "workspace:*",
"@vueuse/core": "^11.1.0",
"radix-vue": "^1.9.5",
"sortablejs": "^1.15.3",
"vue": "^3.5.6"
"@vueuse/core": "catalog:",
"radix-vue": "catalog:",
"sortablejs": "catalog:",
"vue": "catalog:"
},
"devDependencies": {
"@types/sortablejs": "^1.15.8"
"@types/sortablejs": "catalog:"
}
}

View File

@@ -1,4 +1,4 @@
import { getScrollbarWidth } from '@vben-core/shared/utils';
import { getScrollbarWidth, needsScrollbar } from '@vben-core/shared/utils';
import {
useScrollLock as _useScrollLock,
@@ -13,6 +13,9 @@ export function useScrollLock() {
const scrollbarWidth = getScrollbarWidth();
tryOnBeforeMount(() => {
if (!needsScrollbar()) {
return;
}
document.body.style.paddingRight = `${scrollbarWidth}px`;
const layoutFixedNodes = document.querySelectorAll<HTMLElement>(
@@ -30,6 +33,9 @@ export function useScrollLock() {
});
tryOnBeforeUnmount(() => {
if (!needsScrollbar()) {
return;
}
isLocked.value = false;
const layoutFixedNodes = document.querySelectorAll<HTMLElement>(
`.${SCROLL_FIXED_CLASS}`,

View File

@@ -0,0 +1,114 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`defaultPreferences immutability test > should not modify the config object 1`] = `
{
"app": {
"accessMode": "frontend",
"authPageLayout": "panel-right",
"checkUpdatesInterval": 1,
"colorGrayMode": false,
"colorWeakMode": false,
"compact": false,
"contentCompact": "wide",
"defaultAvatar": "https://unpkg.com/@vbenjs/static-source@0.1.6/source/avatar-v1.webp",
"dynamicTitle": true,
"enableCheckUpdates": true,
"enablePreferences": true,
"enableRefreshToken": false,
"isMobile": false,
"layout": "sidebar-nav",
"locale": "zh-CN",
"loginExpiredMode": "page",
"name": "Vben Admin",
"preferencesButtonPosition": "auto",
"watermark": false,
},
"breadcrumb": {
"enable": true,
"hideOnlyOne": false,
"showHome": false,
"showIcon": true,
"styleType": "normal",
},
"copyright": {
"companyName": "Vben",
"companySiteLink": "https://www.vben.pro",
"date": "2024",
"enable": true,
"icp": "",
"icpLink": "",
},
"footer": {
"enable": true,
"fixed": false,
},
"header": {
"enable": true,
"hidden": false,
"mode": "fixed",
},
"logo": {
"enable": true,
"source": "https://unpkg.com/@vbenjs/static-source@0.1.6/source/logo-v1.webp",
},
"navigation": {
"accordion": true,
"split": true,
"styleType": "rounded",
},
"shortcutKeys": {
"enable": true,
"globalLockScreen": true,
"globalLogout": true,
"globalPreferences": true,
"globalSearch": true,
},
"sidebar": {
"collapsed": false,
"collapsedShowTitle": false,
"enable": true,
"expandOnHover": true,
"extraCollapse": true,
"hidden": false,
"width": 224,
},
"tabbar": {
"dragable": true,
"enable": true,
"height": 38,
"keepAlive": true,
"persist": true,
"showIcon": true,
"showMaximize": true,
"showMore": true,
"showRefresh": true,
"styleType": "chrome",
},
"theme": {
"builtinType": "default",
"colorDestructive": "hsl(348 100% 61%)",
"colorPrimary": "hsl(212 100% 45%)",
"colorSuccess": "hsl(144 57% 58%)",
"colorWarning": "hsl(42 84% 61%)",
"mode": "dark",
"radius": "0.5",
"semiDarkHeader": false,
"semiDarkSidebar": true,
},
"transition": {
"enable": true,
"loading": true,
"name": "fade-slide",
"progress": true,
},
"widget": {
"fullscreen": true,
"globalSearch": true,
"languageToggle": true,
"lockScreen": true,
"notification": true,
"sidebarToggle": true,
"themeToggle": true,
},
}
`;

View File

@@ -0,0 +1,10 @@
import { describe, expect, it } from 'vitest';
import { defaultPreferences } from '../src/config';
describe('defaultPreferences immutability test', () => {
// 创建快照,确保默认配置对象不被修改
it('should not modify the config object', () => {
expect(defaultPreferences).toMatchSnapshot();
});
});

View File

@@ -1,8 +1,8 @@
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { defaultPreferences } from './config';
import { PreferenceManager } from './preferences';
import { isDarkTheme } from './update-css-variables';
import { defaultPreferences } from '../src/config';
import { PreferenceManager } from '../src/preferences';
import { isDarkTheme } from '../src/update-css-variables';
describe('preferences', () => {
let preferenceManager: PreferenceManager;

View File

@@ -31,7 +31,7 @@
"dependencies": {
"@vben-core/shared": "workspace:*",
"@vben-core/typings": "workspace:*",
"@vueuse/core": "^11.1.0",
"vue": "^3.5.6"
"@vueuse/core": "catalog:",
"vue": "catalog:"
}
}

View File

@@ -1,6 +1,6 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "@vben/tsconfig/web.json",
"include": ["src"],
"include": ["src", "__tests__"],
"exclude": ["node_modules"]
}

View File

@@ -0,0 +1,146 @@
// 假设这个文件为 FormApi.ts
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { FormApi } from '../src/form-api';
vi.mock('@vben-core/shared/utils', () => ({
bindMethods: vi.fn(),
createMerge: vi.fn((mergeFn) => {
return (stateOrFn, prev) => {
mergeFn(prev, 'key', stateOrFn);
return { ...prev, ...stateOrFn };
};
}),
isFunction: (fn: any) => typeof fn === 'function',
StateHandler: vi.fn().mockImplementation(() => ({
reset: vi.fn(),
setConditionTrue: vi.fn(),
waitForCondition: vi.fn().mockResolvedValue(true),
})),
}));
describe('formApi', () => {
let formApi: FormApi;
beforeEach(() => {
formApi = new FormApi();
});
it('should initialize with default state', () => {
expect(formApi.state).toEqual(
expect.objectContaining({
actionWrapperClass: '',
collapsed: false,
collapsedRows: 1,
commonConfig: {},
handleReset: undefined,
handleSubmit: undefined,
layout: 'horizontal',
resetButtonOptions: {},
schema: [],
showCollapseButton: false,
showDefaultActions: true,
submitButtonOptions: {},
wrapperClass: 'grid-cols-1',
}),
);
expect(formApi.isMounted).toBe(false);
});
it('should mount form actions', async () => {
const formActions: any = {
meta: {},
resetForm: vi.fn(),
setFieldValue: vi.fn(),
setValues: vi.fn(),
submitForm: vi.fn(),
validate: vi.fn(),
values: { name: 'test' },
};
await formApi.mount(formActions);
expect(formApi.isMounted).toBe(true);
expect(formApi.form).toEqual(formActions);
});
it('should get values from form', async () => {
const formActions: any = {
meta: {},
values: { name: 'test' },
};
await formApi.mount(formActions);
const values = await formApi.getValues();
expect(values).toEqual({ name: 'test' });
});
it('should set field value', async () => {
const setFieldValueMock = vi.fn();
const formActions: any = {
meta: {},
setFieldValue: setFieldValueMock,
values: { name: 'test' },
};
await formApi.mount(formActions);
await formApi.setFieldValue('name', 'new value');
expect(setFieldValueMock).toHaveBeenCalledWith(
'name',
'new value',
undefined,
);
});
it('should reset form', async () => {
const resetFormMock = vi.fn();
const formActions: any = {
meta: {},
resetForm: resetFormMock,
values: { name: 'test' },
};
await formApi.mount(formActions);
await formApi.resetForm();
expect(resetFormMock).toHaveBeenCalled();
});
it('should call handleSubmit on submit', async () => {
const handleSubmitMock = vi.fn();
const formActions: any = {
meta: {},
submitForm: vi.fn().mockResolvedValue(true),
values: { name: 'test' },
};
const state = {
handleSubmit: handleSubmitMock,
};
formApi.setState(state);
await formApi.mount(formActions);
const result = await formApi.submitForm();
expect(formActions.submitForm).toHaveBeenCalled();
expect(handleSubmitMock).toHaveBeenCalledWith({ name: 'test' });
expect(result).toEqual({ name: 'test' });
});
it('should unmount form and reset state', () => {
formApi.unmounted();
expect(formApi.isMounted).toBe(false);
expect(formApi.stateHandler.reset).toHaveBeenCalled();
});
it('should validate form', async () => {
const validateMock = vi.fn().mockResolvedValue(true);
const formActions: any = {
meta: {},
validate: validateMock,
};
await formApi.mount(formActions);
const isValid = await formApi.validate();
expect(validateMock).toHaveBeenCalled();
expect(isValid).toBe(true);
});
});

View File

@@ -40,11 +40,11 @@
"@vben-core/composables": "workspace:*",
"@vben-core/shadcn-ui": "workspace:*",
"@vben-core/shared": "workspace:*",
"@vee-validate/zod": "^4.13.2",
"@vueuse/core": "^11.1.0",
"vee-validate": "^4.13.2",
"vue": "^3.5.6",
"zod": "^3.23.8",
"zod-defaults": "^0.1.3"
"@vee-validate/zod": "catalog:",
"@vueuse/core": "catalog:",
"vee-validate": "catalog:",
"vue": "catalog:",
"zod": "catalog:",
"zod-defaults": "catalog:"
}
}

View File

@@ -43,13 +43,13 @@ function getDefaultState(): VbenFormProps {
}
export class FormApi {
// private prevState!: ModalState;
private state: null | VbenFormProps = null;
// private api: Pick<VbenFormProps, 'handleReset' | 'handleSubmit'>;
public form = {} as FormActions;
isMounted = false;
// private prevState!: ModalState;
public state: null | VbenFormProps = null;
stateHandler: StateHandler;
public store: Store<VbenFormProps>;
@@ -92,6 +92,10 @@ export class FormApi {
this.store.batch(cb);
}
getState() {
return this.state;
}
async getValues() {
const form = await this.getForm();
return form.values;

View File

@@ -1,6 +1,6 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "@vben/tsconfig/web.json",
"include": ["src"],
"include": ["src", "__tests__"],
"exclude": ["node_modules"]
}

View File

@@ -41,7 +41,7 @@
"@vben-core/icons": "workspace:*",
"@vben-core/shadcn-ui": "workspace:*",
"@vben-core/typings": "workspace:*",
"@vueuse/core": "^11.1.0",
"vue": "^3.5.6"
"@vueuse/core": "catalog:",
"vue": "catalog:"
}
}

View File

@@ -42,7 +42,7 @@
"@vben-core/shadcn-ui": "workspace:*",
"@vben-core/shared": "workspace:*",
"@vben-core/typings": "workspace:*",
"@vueuse/core": "^11.1.0",
"vue": "^3.5.6"
"@vueuse/core": "catalog:",
"vue": "catalog:"
}
}

View File

@@ -41,7 +41,7 @@
"@vben-core/icons": "workspace:*",
"@vben-core/shadcn-ui": "workspace:*",
"@vben-core/shared": "workspace:*",
"@vueuse/core": "^11.1.0",
"vue": "^3.5.6"
"@vueuse/core": "catalog:",
"vue": "catalog:"
}
}

View File

@@ -40,16 +40,16 @@
}
},
"dependencies": {
"@radix-icons/vue": "^1.0.0",
"@radix-icons/vue": "catalog:",
"@vben-core/composables": "workspace:*",
"@vben-core/icons": "workspace:*",
"@vben-core/shared": "workspace:*",
"@vben-core/typings": "workspace:*",
"@vueuse/core": "^11.1.0",
"class-variance-authority": "^0.7.0",
"lucide-vue-next": "^0.441.0",
"radix-vue": "^1.9.5",
"vee-validate": "^4.13.2",
"vue": "^3.5.6"
"@vueuse/core": "catalog:",
"class-variance-authority": "catalog:",
"lucide-vue-next": "catalog:",
"radix-vue": "catalog:",
"vee-validate": "catalog:",
"vue": "catalog:"
}
}

View File

@@ -42,7 +42,7 @@
"@vben-core/shadcn-ui": "workspace:*",
"@vben-core/shared": "workspace:*",
"@vben-core/typings": "workspace:*",
"@vueuse/core": "^11.1.0",
"vue": "^3.5.6"
"@vueuse/core": "catalog:",
"vue": "catalog:"
}
}

View File

@@ -24,6 +24,6 @@
"@vben/stores": "workspace:*",
"@vben/types": "workspace:*",
"@vben/utils": "workspace:*",
"vue": "^3.5.6"
"vue": "catalog:"
}
}

View File

@@ -35,15 +35,15 @@
"@vben/locales": "workspace:*",
"@vben/preferences": "workspace:*",
"@vben/types": "workspace:*",
"@vueuse/integrations": "^11.1.0",
"@vueuse/integrations": "catalog:",
"codemirror": "^6.0.1",
"qrcode": "^1.5.4",
"vue": "^3.5.6",
"qrcode": "catalog:",
"vue": "catalog:",
"vue-codemirror6": "^1.3.4",
"vue-json-pretty": "^2.4.0",
"vue-router": "^4.4.5"
"vue-router": "catalog:"
},
"devDependencies": {
"@types/qrcode": "^1.5.5"
"@types/qrcode": "catalog:"
}
}

View File

@@ -5,7 +5,7 @@ import { RotateCw } from '@vben/icons';
import { $t } from '@vben/locales';
import { VbenButton, VbenIconButton } from '@vben-core/shadcn-ui';
import { CaptchaCard } from '.';
import CaptchaCard from './captcha-card.vue';
import { useCaptchaPoints } from './hooks/useCaptchaPoints';
const props = withDefaults(defineProps<PointSelectionCaptchaProps>(), {

View File

@@ -25,8 +25,8 @@
"@vben/stores": "workspace:*",
"@vben/types": "workspace:*",
"@vben/utils": "workspace:*",
"vue": "^3.5.6",
"vue-router": "^4.4.5",
"watermark-js-plus": "^1.5.6"
"vue": "catalog:",
"vue-router": "catalog:",
"watermark-js-plus": "catalog:"
}
}

View File

@@ -185,6 +185,7 @@ export function useElementPlusDesignTokens() {
'--el-bg-color-page': getCssVariableValue('--background-deep'),
'--el-border-color': border,
'--el-border-color-dark': border,
'--el-border-color-extra-light': border,
'--el-border-color-hover': accent,
'--el-border-color-light': border,
'--el-border-color-lighter': border,
@@ -195,26 +196,36 @@ export function useElementPlusDesignTokens() {
'--el-color-danger-light-3': getCssVariableValue('--destructive-400'),
'--el-color-danger-light-5': getCssVariableValue('--destructive-300'),
'--el-color-danger-light-7': getCssVariableValue('--destructive-200'),
'--el-color-danger-light-8': getCssVariableValue('--destructive-100'),
'--el-color-danger-light-8': isDark.value
? border
: getCssVariableValue('--destructive-100'),
'--el-color-danger-light-9': isDark.value
? accent
: getCssVariableValue('--destructive-50'),
'--el-color-danger-light-9': getCssVariableValue('--destructive-50'),
'--el-color-error': getCssVariableValue('--destructive-500'),
'--el-color-error-dark-2': getCssVariableValue('--destructive'),
'--el-color-error-light-3': getCssVariableValue('--destructive-400'),
'--el-color-error-light-5': getCssVariableValue('--destructive-300'),
'--el-color-error-light-7': getCssVariableValue('--destructive-200'),
'--el-color-error-light-8': getCssVariableValue('--destructive-100'),
'--el-color-error-light-8': isDark.value
? border
: getCssVariableValue('--destructive-100'),
'--el-color-error-light-9': isDark.value
? accent
: getCssVariableValue('--destructive-50'),
'--el-color-error-light-9': getCssVariableValue('--destructive-50'),
'--el-color-info-light-8': border,
'--el-color-info-light-9': background,
'--el-color-primary': getCssVariableValue('--primary-500'),
'--el-color-primary-dark-2': getCssVariableValue('--primary'),
'--el-color-primary-light-3': getCssVariableValue('--primary-400'),
'--el-color-primary-light-5': getCssVariableValue('--primary-300'),
'--el-color-primary-light-7': getCssVariableValue('--primary-200'),
'--el-color-primary-light-8': getCssVariableValue('--primary-100'),
'--el-color-primary-light-8': isDark.value
? border
: getCssVariableValue('--primary-100'),
'--el-color-primary-light-9': isDark.value
? accent
: getCssVariableValue('--primary-50'),
@@ -224,17 +235,26 @@ export function useElementPlusDesignTokens() {
'--el-color-success-light-3': getCssVariableValue('--success-400'),
'--el-color-success-light-5': getCssVariableValue('--success-300'),
'--el-color-success-light-7': getCssVariableValue('--success-200'),
'--el-color-success-light-8': getCssVariableValue('--success-100'),
'--el-color-success-light-8': isDark.value
? border
: getCssVariableValue('--success-100'),
'--el-color-success-light-9': isDark.value
? accent
: getCssVariableValue('--success-50'),
'--el-color-success-light-9': getCssVariableValue('--success-50'),
'--el-color-warning': getCssVariableValue('--warning-500'),
'--el-color-warning-dark-2': getCssVariableValue('--warning'),
'--el-color-warning-light-3': getCssVariableValue('--warning-400'),
'--el-color-warning-light-5': getCssVariableValue('--warning-300'),
'--el-color-warning-light-7': getCssVariableValue('--warning-200'),
'--el-color-warning-light-8': getCssVariableValue('--warning-100'),
'--el-color-warning-light-8': isDark.value
? border
: getCssVariableValue('--warning-100'),
'--el-color-warning-light-9': isDark.value
? accent
: getCssVariableValue('--warning-50'),
'--el-color-warning-light-9': getCssVariableValue('--warning-50'),
'--el-fill-color': getCssVariableValue('--accent'),
'--el-fill-color-blank': background,
'--el-fill-color-light': getCssVariableValue('--accent'),
'--el-text-color-primary': getCssVariableValue('--foreground'),

View File

@@ -35,8 +35,8 @@
"@vben/stores": "workspace:*",
"@vben/types": "workspace:*",
"@vben/utils": "workspace:*",
"@vueuse/core": "^11.1.0",
"vue": "^3.5.6",
"vue-router": "^4.4.5"
"@vueuse/core": "catalog:",
"vue": "catalog:",
"vue-router": "catalog:"
}
}

View File

@@ -21,8 +21,8 @@
},
"dependencies": {
"@vben/preferences": "workspace:*",
"@vueuse/core": "^11.1.0",
"echarts": "^5.5.1",
"vue": "^3.5.6"
"@vueuse/core": "catalog:",
"echarts": "catalog:",
"vue": "catalog:"
}
}

View File

@@ -22,9 +22,9 @@
"dependencies": {
"@vben/locales": "workspace:*",
"@vben/utils": "workspace:*",
"axios": "^1.7.7"
"axios": "catalog:"
},
"devDependencies": {
"axios-mock-adapter": "^2.0.0"
"axios-mock-adapter": "catalog:"
}
}

View File

@@ -34,7 +34,7 @@ describe('fileUploader', () => {
mockAxiosInstance.post as unknown as ReturnType<typeof vi.fn>
).mockResolvedValueOnce(mockResponse);
const result = await fileUploader.upload(url, file);
const result = await fileUploader.upload(url, { file });
expect(result).toEqual(mockResponse);
expect(mockAxiosInstance.post).toHaveBeenCalledWith(
url,
@@ -66,7 +66,7 @@ describe('fileUploader', () => {
headers: { 'Custom-Header': 'value' },
};
const result = await fileUploader.upload(url, file, customConfig);
const result = await fileUploader.upload(url, { file }, customConfig);
expect(result).toEqual(mockResponse);
expect(mockAxiosInstance.post).toHaveBeenCalledWith(
url,
@@ -87,7 +87,7 @@ describe('fileUploader', () => {
mockAxiosInstance.post as unknown as ReturnType<typeof vi.fn>
).mockRejectedValueOnce(new Error('Network Error'));
await expect(fileUploader.upload(url, file)).rejects.toThrow(
await expect(fileUploader.upload(url, { file })).rejects.toThrow(
'Network Error',
);
});
@@ -99,7 +99,7 @@ describe('fileUploader', () => {
mockAxiosInstance.post as unknown as ReturnType<typeof vi.fn>
).mockRejectedValueOnce(new Error('Request failed with status code 404'));
await expect(fileUploader.upload(url, file)).rejects.toThrow(
await expect(fileUploader.upload(url, { file })).rejects.toThrow(
'Request failed with status code 404',
);
});
@@ -111,7 +111,7 @@ describe('fileUploader', () => {
mockAxiosInstance.post as unknown as ReturnType<typeof vi.fn>
).mockRejectedValueOnce(new Error('Request failed with status code 404'));
await expect(fileUploader.upload(url, file)).rejects.toThrow(
await expect(fileUploader.upload(url, { file })).rejects.toThrow(
'Request failed with status code 404',
);
});

View File

@@ -11,11 +11,14 @@ class FileUploader {
public async upload(
url: string,
file: Blob | File,
data: { file: Blob | File } & Record<string, any>,
config?: AxiosRequestConfig,
): Promise<AxiosResponse> {
const formData = new FormData();
formData.append('file', file);
Object.entries(data).forEach(([key, value]) => {
formData.append(key, value);
});
const finalConfig: AxiosRequestConfig = {
...config,

View File

@@ -79,7 +79,9 @@ describe('requestClient', () => {
: [400, { error: 'Bad Request' }];
});
const response = await requestClient.upload('/test/upload', fileData);
const response = await requestClient.upload('/test/upload', {
file: fileData,
});
expect(response.data).toEqual({ data: 'file uploaded' });
});

View File

@@ -20,9 +20,9 @@
}
},
"dependencies": {
"@intlify/core-base": "^10.0.1",
"@intlify/core-base": "catalog:",
"@vben-core/composables": "workspace:*",
"vue": "^3.5.6",
"vue-i18n": "^10.0.1"
"vue": "catalog:",
"vue-i18n": "catalog:"
}
}

View File

@@ -22,9 +22,9 @@
"dependencies": {
"@vben-core/shared": "workspace:*",
"@vben-core/typings": "workspace:*",
"pinia": "2.2.2",
"pinia-plugin-persistedstate": "^4.0.2",
"vue": "^3.5.6",
"vue-router": "^4.4.5"
"pinia": "catalog:",
"pinia-plugin-persistedstate": "catalog:",
"vue": "catalog:",
"vue-router": "catalog:"
}
}

View File

@@ -21,7 +21,7 @@
},
"dependencies": {
"@vben-core/typings": "workspace:*",
"vue": "^3.5.6",
"vue-router": "^4.4.5"
"vue": "catalog:",
"vue-router": "catalog:"
}
}

View File

@@ -24,6 +24,6 @@
"dependencies": {
"@vben-core/shared": "workspace:*",
"@vben-core/typings": "workspace:*",
"vue-router": "^4.4.5"
"vue-router": "catalog:"
}
}