pull/53/MERGE
xingyu4j 2024-11-28 10:34:44 +08:00
commit a0131fa8a8
18 changed files with 775 additions and 701 deletions

View File

@ -65,7 +65,7 @@ async function initComponentAdapter() {
Checkbox: ElCheckbox, Checkbox: ElCheckbox,
CheckboxGroup: ElCheckboxGroup, CheckboxGroup: ElCheckboxGroup,
// 自定义默认按钮 // 自定义默认按钮
DefaulButton: (props, { attrs, slots }) => { DefaultButton: (props, { attrs, slots }) => {
return h(ElButton, { ...props, attrs, type: 'info' }, slots); return h(ElButton, { ...props, attrs, type: 'info' }, slots);
}, },
// 自定义主要按钮 // 自定义主要按钮

View File

@ -88,6 +88,7 @@ const [Drawer, drawerApi] = useVbenDrawer({
| closeOnPressEscape | esc 关闭弹窗 | `boolean` | `true` | | closeOnPressEscape | esc 关闭弹窗 | `boolean` | `true` |
| confirmText | 确认按钮文本 | `string\|slot` | `确认` | | confirmText | 确认按钮文本 | `string\|slot` | `确认` |
| cancelText | 取消按钮文本 | `string\|slot` | `取消` | | cancelText | 取消按钮文本 | `string\|slot` | `取消` |
| placement | 抽屉弹出位置 | `'left'\|'right'\|'top'\|'bottom'` | `right` |
| showCancelButton | 显示取消按钮 | `boolean` | `true` | | showCancelButton | 显示取消按钮 | `boolean` | `true` |
| showConfirmButton | 显示确认按钮文本 | `boolean` | `true` | | showConfirmButton | 显示确认按钮文本 | `boolean` | `true` |
| class | modal的class宽度通过这个配置 | `string` | - | | class | modal的class宽度通过这个配置 | `string` | - |

View File

@ -93,13 +93,14 @@ const [Modal, modalApi] = useVbenModal({
| modal | 显示遮罩 | `boolean` | `true` | | modal | 显示遮罩 | `boolean` | `true` |
| header | 显示header | `boolean` | `true` | | header | 显示header | `boolean` | `true` |
| footer | 显示footer | `boolean\|slot` | `true` | | footer | 显示footer | `boolean\|slot` | `true` |
| confirmDisabled | 禁用确认按钮 | `boolean` | `false` |
| confirmLoading | 确认按钮loading状态 | `boolean` | `false` | | confirmLoading | 确认按钮loading状态 | `boolean` | `false` |
| closeOnClickModal | 点击遮罩关闭弹窗 | `boolean` | `true` | | closeOnClickModal | 点击遮罩关闭弹窗 | `boolean` | `true` |
| closeOnPressEscape | esc 关闭弹窗 | `boolean` | `true` | | closeOnPressEscape | esc 关闭弹窗 | `boolean` | `true` |
| confirmText | 确认按钮文本 | `string\|slot` | `确认` | | confirmText | 确认按钮文本 | `string\|slot` | `确认` |
| cancelText | 取消按钮文本 | `string\|slot` | `取消` | | cancelText | 取消按钮文本 | `string\|slot` | `取消` |
| showCancelButton | 显示取消按钮 | `boolean` | `true` | | showCancelButton | 显示取消按钮 | `boolean` | `true` |
| showConfirmButton | 显示确认按钮文本 | `boolean` | `true` | | showConfirmButton | 显示确认按钮 | `boolean` | `true` |
| class | modal的class宽度通过这个配置 | `string` | - | | class | modal的class宽度通过这个配置 | `string` | - |
| contentClass | modal内容区域的class | `string` | - | | contentClass | modal内容区域的class | `string` | - |
| footerClass | modal底部区域的class | `string` | - | | footerClass | modal底部区域的class | `string` | - |

View File

@ -28,7 +28,7 @@
".": { ".": {
"types": "./src/index.ts", "types": "./src/index.ts",
"development": "./src/index.ts", "development": "./src/index.ts",
"default": "./dist/style.css" "default": "./dist/design.css"
} }
}, },
"publishConfig": { "publishConfig": {

View File

@ -41,6 +41,7 @@ export class DrawerApi {
loading: false, loading: false,
modal: true, modal: true,
openAutoFocus: false, openAutoFocus: false,
placement: 'right',
showCancelButton: true, showCancelButton: true,
showConfirmButton: true, showConfirmButton: true,
title: '', title: '',

View File

@ -4,6 +4,8 @@ import type { DrawerApi } from './drawer-api';
import type { Component, Ref } from 'vue'; import type { Component, Ref } from 'vue';
export type DrawerPlacement = 'bottom' | 'left' | 'right' | 'top';
export interface DrawerProps { export interface DrawerProps {
/** /**
* *
@ -72,6 +74,12 @@ export interface DrawerProps {
* *
*/ */
openAutoFocus?: boolean; openAutoFocus?: boolean;
/**
*
* @default right
*/
placement?: DrawerPlacement;
/** /**
* *
* @default true * @default true

View File

@ -62,6 +62,7 @@ const {
loading: showLoading, loading: showLoading,
modal, modal,
openAutoFocus, openAutoFocus,
placement,
showCancelButton, showCancelButton,
showConfirmButton, showConfirmButton,
title, title,
@ -119,11 +120,13 @@ function handleFocusOutside(e: Event) {
<SheetContent <SheetContent
:class=" :class="
cn('flex w-[520px] flex-col', drawerClass, { cn('flex w-[520px] flex-col', drawerClass, {
'!w-full': isMobile, '!w-full': isMobile || placement === 'bottom' || placement === 'top',
'max-h-[100vh]': placement === 'bottom' || placement === 'top',
}) })
" "
:modal="modal" :modal="modal"
:open="state?.isOpen" :open="state?.isOpen"
:side="placement"
@close-auto-focus="handleFocusOutside" @close-auto-focus="handleFocusOutside"
@escape-key-down="escapeKeyDown" @escape-key-down="escapeKeyDown"
@focus-outside="handleFocusOutside" @focus-outside="handleFocusOutside"

View File

@ -41,6 +41,7 @@ export class ModalApi {
class: '', class: '',
closeOnClickModal: true, closeOnClickModal: true,
closeOnPressEscape: true, closeOnPressEscape: true,
confirmDisabled: false,
confirmLoading: false, confirmLoading: false,
contentClass: '', contentClass: '',
draggable: false, draggable: false,

View File

@ -35,6 +35,10 @@ export interface ModalProps {
* @default true * @default true
*/ */
closeOnPressEscape?: boolean; closeOnPressEscape?: boolean;
/**
*
*/
confirmDisabled?: boolean;
/** /**
* loading * loading
* @default false * @default false

View File

@ -59,6 +59,7 @@ const {
closable, closable,
closeOnClickModal, closeOnClickModal,
closeOnPressEscape, closeOnPressEscape,
confirmDisabled,
confirmLoading, confirmLoading,
confirmText, confirmText,
contentClass, contentClass,
@ -285,6 +286,7 @@ function handleFocusOutside(e: Event) {
<component <component
:is="components.PrimaryButton || VbenButton" :is="components.PrimaryButton || VbenButton"
v-if="showConfirmButton" v-if="showConfirmButton"
:disabled="confirmDisabled"
:loading="confirmLoading" :loading="confirmLoading"
@click="() => modalApi?.onConfirm()" @click="() => modalApi?.onConfirm()"
> >

View File

@ -32,8 +32,8 @@ const style = computed(() => {
.dark .vben-spine-text { .dark .vben-spine-text {
background: background:
radial-gradient(circle at center, rgb(24 24 26 / 80%), transparent) -200% 50% / radial-gradient(circle at center, rgb(24 24 26 / 80%), transparent) -200%
200% 100% no-repeat, 50% / 200% 100% no-repeat,
#f4f4f4; #f4f4f4;
} }

View File

@ -1,46 +0,0 @@
import { mount } from '@vue/test-utils';
import { describe, expect, it } from 'vitest';
import { EllipsisText } from '..';
describe('ellipsis-text.vue', () => {
it('renders the correct content and truncates text', async () => {
const wrapper = mount(EllipsisText, {
props: {
line: 1,
title: 'Test Title',
},
slots: {
default: 'This is a very long text that should be truncated.',
},
});
expect(wrapper.text()).toContain('This is a very long text');
// 检查 ellipsis 是否应用了正确的 class
const ellipsis = wrapper.find('.truncate');
expect(ellipsis.exists()).toBe(true);
});
it('expands text on click if expand is true', async () => {
const wrapper = mount(EllipsisText, {
props: {
expand: true,
line: 1,
},
slots: {
default: 'This is a very long text that should be truncated.',
},
});
const ellipsis = wrapper.find('.truncate');
// 点击 ellipsis应该触发 expandChange参数为 false
await ellipsis.trigger('click');
expect(wrapper.emitted('expandChange')).toBeTruthy();
expect(wrapper.emitted('expandChange')?.[0]).toEqual([true]);
// 再次点击,应该触发 expandChange参数为 false
await ellipsis.trigger('click');
expect(wrapper.emitted('expandChange')?.length).toBe(2);
expect(wrapper.emitted('expandChange')?.[1]).toEqual([false]);
});
});

View File

@ -156,6 +156,18 @@ const routes: RouteRecordRaw[] = [
title: $t('demos.features.hideChildrenInMenu'), title: $t('demos.features.hideChildrenInMenu'),
}, },
children: [ children: [
{
name: 'HideChildrenInMenuDemo',
path: '',
component: () =>
import(
'#/views/demos/features/hide-menu-children/children.vue'
),
meta: {
hideInMenu: true,
title: $t('demos.features.hideChildrenInMenu'),
},
},
{ {
name: 'HideChildrenInMenuChildrenDemo', name: 'HideChildrenInMenuChildrenDemo',
path: '/demos/features/hide-menu-children/children', path: '/demos/features/hide-menu-children/children',

View File

@ -81,17 +81,17 @@ async function changeAccount(role: string) {
<Card class="mb-5" title="组件形式控制 - 权限码"> <Card class="mb-5" title="组件形式控制 - 权限码">
<AccessControl :codes="['AC_100100']" type="code"> <AccessControl :codes="['AC_100100']" type="code">
<Button class="mr-4"> Super 账号可见 ["AC_1000001"] </Button> <Button class="mr-4"> Super 账号可见 ["AC_100100"] </Button>
</AccessControl> </AccessControl>
<AccessControl :codes="['AC_100030']" type="code"> <AccessControl :codes="['AC_100030']" type="code">
<Button class="mr-4"> Admin 账号可见 ["AC_100010"] </Button> <Button class="mr-4"> Admin 账号可见 ["AC_100030"] </Button>
</AccessControl> </AccessControl>
<AccessControl :codes="['AC_1000001']" type="code"> <AccessControl :codes="['AC_1000001']" type="code">
<Button class="mr-4"> User 账号可见 ["AC_1000001"] </Button> <Button class="mr-4"> User 账号可见 ["AC_1000001"] </Button>
</AccessControl> </AccessControl>
<AccessControl :codes="['AC_100100', 'AC_100010']" type="code"> <AccessControl :codes="['AC_100100', 'AC_100030']" type="code">
<Button class="mr-4"> <Button class="mr-4">
Super & Admin 账号可见 ["AC_100100","AC_1000001"] Super & Admin 账号可见 ["AC_100100","AC_100030"]
</Button> </Button>
</AccessControl> </AccessControl>
</Card> </Card>
@ -117,35 +117,35 @@ async function changeAccount(role: string) {
<Card class="mb-5" title="函数形式控制"> <Card class="mb-5" title="函数形式控制">
<Button v-if="hasAccessByCodes(['AC_100100'])" class="mr-4"> <Button v-if="hasAccessByCodes(['AC_100100'])" class="mr-4">
Super 账号可见 ["AC_1000001"] Super 账号可见 ["AC_100100"]
</Button> </Button>
<Button v-if="hasAccessByCodes(['AC_100030'])" class="mr-4"> <Button v-if="hasAccessByCodes(['AC_100030'])" class="mr-4">
Admin 账号可见 ["AC_100010"] Admin 账号可见 ["AC_100030"]
</Button> </Button>
<Button v-if="hasAccessByCodes(['AC_1000001'])" class="mr-4"> <Button v-if="hasAccessByCodes(['AC_1000001'])" class="mr-4">
User 账号可见 ["AC_1000001"] User 账号可见 ["AC_1000001"]
</Button> </Button>
<Button v-if="hasAccessByCodes(['AC_100100', 'AC_1000001'])" class="mr-4"> <Button v-if="hasAccessByCodes(['AC_100100', 'AC_100030'])" class="mr-4">
Super & Admin 账号可见 ["AC_100100","AC_1000001"] Super & Admin 账号可见 ["AC_100100","AC_100030"]
</Button> </Button>
</Card> </Card>
<Card class="mb-5" title="指令方式 - 权限码"> <Card class="mb-5" title="指令方式 - 权限码">
<Button class="mr-4" v-access:code="['AC_100100']"> <Button class="mr-4" v-access:code="['AC_100100']">
Super 账号可见 ["AC_1000001"] Super 账号可见 ["AC_100100"]
</Button> </Button>
<Button class="mr-4" v-access:code="['AC_100030']"> <Button class="mr-4" v-access:code="['AC_100030']">
Admin 账号可见 ["AC_100010"] Admin 账号可见 ["AC_100030"]
</Button> </Button>
<Button class="mr-4" v-access:code="['AC_1000001']"> <Button class="mr-4" v-access:code="['AC_1000001']">
User 账号可见 ["AC_1000001"] User 账号可见 ["AC_1000001"]
</Button> </Button>
<Button class="mr-4" v-access:code="['AC_100100', 'AC_1000001']"> <Button class="mr-4" v-access:code="['AC_100100', 'AC_100030']">
Super & Admin 账号可见 ["AC_100100","AC_1000001"] Super & Admin 账号可见 ["AC_100100","AC_100030"]
</Button> </Button>
</Card> </Card>
<Card class="mb-5" title="指令方式 - 角色"> <Card v-if="accessMode === 'frontend'" class="mb-5" title="指令方式 - 角色">
<Button class="mr-4" v-access:role="['super']"> Super 角色可见 </Button> <Button class="mr-4" v-access:role="['super']"> Super 角色可见 </Button>
<Button class="mr-4" v-access:role="['admin']"> Admin 角色可见 </Button> <Button class="mr-4" v-access:role="['admin']"> Admin 角色可见 </Button>
<Button class="mr-4" v-access:role="['user']"> User 角色可见 </Button> <Button class="mr-4" v-access:role="['user']"> User 角色可见 </Button>

View File

@ -1,5 +1,5 @@
<script lang="ts" setup> <script lang="ts" setup>
import { Page, useVbenDrawer } from '@vben/common-ui'; import { type DrawerPlacement, Page, useVbenDrawer } from '@vben/common-ui';
import { Button, Card } from 'ant-design-vue'; import { Button, Card } from 'ant-design-vue';
@ -13,6 +13,7 @@ import SharedDataDemo from './shared-data-demo.vue';
const [BaseDrawer, baseDrawerApi] = useVbenDrawer({ const [BaseDrawer, baseDrawerApi] = useVbenDrawer({
// //
connectedComponent: BaseDemo, connectedComponent: BaseDemo,
// placement: 'left',
}); });
const [AutoHeightDrawer, autoHeightDrawerApi] = useVbenDrawer({ const [AutoHeightDrawer, autoHeightDrawerApi] = useVbenDrawer({
@ -31,7 +32,8 @@ const [FormDrawer, formDrawerApi] = useVbenDrawer({
connectedComponent: FormDrawerDemo, connectedComponent: FormDrawerDemo,
}); });
function openBaseDrawer() { function openBaseDrawer(placement: DrawerPlacement = 'right') {
baseDrawerApi.setState({ placement });
baseDrawerApi.open(); baseDrawerApi.open();
} }
@ -81,7 +83,16 @@ function openFormDrawer() {
<Card class="mb-4" title="基本使用"> <Card class="mb-4" title="基本使用">
<p class="mb-3">一个基础的抽屉示例</p> <p class="mb-3">一个基础的抽屉示例</p>
<Button type="primary" @click="openBaseDrawer"></Button> <Button type="primary" @click="openBaseDrawer('right')"></Button>
<Button class="ml-2" type="primary" @click="openBaseDrawer('bottom')">
底部打开
</Button>
<Button class="ml-2" type="primary" @click="openBaseDrawer('left')">
左侧打开
</Button>
<Button class="ml-2" type="primary" @click="openBaseDrawer('top')">
顶部打开
</Button>
</Card> </Card>
<Card class="mb-4" title="内容高度自适应滚动"> <Card class="mb-4" title="内容高度自适应滚动">

View File

@ -22,10 +22,10 @@ const [Modal, modalApi] = useVbenModal({
}); });
function handleUpdate(len: number) { function handleUpdate(len: number) {
modalApi.setState({ loading: true }); modalApi.setState({ confirmDisabled: true, loading: true });
setTimeout(() => { setTimeout(() => {
list.value = Array.from({ length: len }, (_v, k) => k + 1); list.value = Array.from({ length: len }, (_v, k) => k + 1);
modalApi.setState({ loading: false }); modalApi.setState({ confirmDisabled: false, loading: false });
}, 2000); }, 2000);
} }
</script> </script>

File diff suppressed because it is too large Load Diff

View File

@ -13,7 +13,7 @@ packages:
- docs - docs
- playground - playground
catalog: catalog:
'@ast-grep/napi': ^0.30.0 '@ast-grep/napi': ^0.30.1
'@changesets/changelog-github': ^0.5.0 '@changesets/changelog-github': ^0.5.0
'@changesets/cli': ^2.27.10 '@changesets/cli': ^2.27.10
'@changesets/git': ^3.0.2 '@changesets/git': ^3.0.2
@ -23,7 +23,7 @@ catalog:
'@ctrl/tinycolor': ^4.1.0 '@ctrl/tinycolor': ^4.1.0
'@eslint/js': ^9.15.0 '@eslint/js': ^9.15.0
'@faker-js/faker': ^9.2.0 '@faker-js/faker': ^9.2.0
'@iconify/json': ^2.2.275 '@iconify/json': ^2.2.276
'@iconify/tailwind': ^1.1.3 '@iconify/tailwind': ^1.1.3
'@iconify/vue': ^4.1.2 '@iconify/vue': ^4.1.2
'@intlify/core-base': ^10.0.4 '@intlify/core-base': ^10.0.4
@ -36,26 +36,26 @@ catalog:
'@stylistic/stylelint-plugin': ^3.1.1 '@stylistic/stylelint-plugin': ^3.1.1
'@tailwindcss/nesting': 0.0.0-insiders.565cd3e '@tailwindcss/nesting': 0.0.0-insiders.565cd3e
'@tailwindcss/typography': ^0.5.15 '@tailwindcss/typography': ^0.5.15
'@tanstack/vue-query': ^5.61.3 '@tanstack/vue-query': ^5.61.4
'@tanstack/vue-store': ^0.5.7 '@tanstack/vue-store': ^0.6.0
'@types/archiver': ^6.0.3 '@types/archiver': ^6.0.3
'@types/crypto-js': ^4.2.2 '@types/crypto-js': ^4.2.2
'@types/eslint': ^9.6.1 '@types/eslint': ^9.6.1
'@types/html-minifier-terser': ^7.0.2 '@types/html-minifier-terser': ^7.0.2
'@types/jsonwebtoken': ^9.0.7 '@types/jsonwebtoken': ^9.0.7
'@types/lodash.clonedeep': ^4.5.9 '@types/lodash.clonedeep': ^4.5.9
'@types/node': ^22.9.3 '@types/node': ^22.10.0
'@types/nprogress': ^0.2.3 '@types/nprogress': ^0.2.3
'@types/postcss-import': ^14.0.3 '@types/postcss-import': ^14.0.3
'@types/qrcode': ^1.5.5 '@types/qrcode': ^1.5.5
'@types/qs': ^6.9.17 '@types/qs': ^6.9.17
'@types/sortablejs': ^1.15.8 '@types/sortablejs': ^1.15.8
'@typescript-eslint/eslint-plugin': ^8.15.0 '@typescript-eslint/eslint-plugin': ^8.16.0
'@typescript-eslint/parser': ^8.15.0 '@typescript-eslint/parser': ^8.16.0
'@vee-validate/zod': ^4.14.7 '@vee-validate/zod': ^4.14.7
'@vite-pwa/vitepress': ^0.5.3 '@vite-pwa/vitepress': ^0.5.3
'@vitejs/plugin-vue': ^5.2.0 '@vitejs/plugin-vue': ^5.2.1
'@vitejs/plugin-vue-jsx': ^4.1.0 '@vitejs/plugin-vue-jsx': ^4.1.1
'@vue/reactivity': ^3.5.13 '@vue/reactivity': ^3.5.13
'@vue/shared': ^3.5.13 '@vue/shared': ^3.5.13
'@vue/test-utils': ^2.4.6 '@vue/test-utils': ^2.4.6
@ -64,19 +64,19 @@ catalog:
ant-design-vue: ^4.2.6 ant-design-vue: ^4.2.6
archiver: ^7.0.1 archiver: ^7.0.1
autoprefixer: ^10.4.20 autoprefixer: ^10.4.20
axios: ^1.7.7 axios: ^1.7.8
axios-mock-adapter: ^2.1.0 axios-mock-adapter: ^2.1.0
cac: ^6.7.14 cac: ^6.7.14
chalk: ^5.3.0 chalk: ^5.3.0
cheerio: 1.0.0 cheerio: 1.0.0
circular-dependency-scanner: ^2.3.0 circular-dependency-scanner: ^2.3.0
class-variance-authority: ^0.7.0 class-variance-authority: ^0.7.1
clsx: ^2.1.1 clsx: ^2.1.1
commitlint-plugin-function-rules: ^4.0.1 commitlint-plugin-function-rules: ^4.0.1
consola: ^3.2.3 consola: ^3.2.3
cross-env: ^7.0.3 cross-env: ^7.0.3
crypto-js: ^4.2.0 crypto-js: ^4.2.0
cspell: ^8.16.0 cspell: ^8.16.1
cssnano: ^7.0.6 cssnano: ^7.0.6
cz-git: ^1.11.0 cz-git: ^1.11.0
czg: ^1.11.0 czg: ^1.11.0
@ -87,11 +87,11 @@ catalog:
echarts: ^5.5.1 echarts: ^5.5.1
element-plus: ^2.8.8 element-plus: ^2.8.8
eslint: ^9.15.0 eslint: ^9.15.0
eslint-config-turbo: ^2.3.1 eslint-config-turbo: ^2.3.3
eslint-plugin-command: ^0.2.6 eslint-plugin-command: ^0.2.6
eslint-plugin-eslint-comments: ^3.2.0 eslint-plugin-eslint-comments: ^3.2.0
eslint-plugin-import-x: ^4.4.3 eslint-plugin-import-x: ^4.4.3
eslint-plugin-jsdoc: ^50.5.0 eslint-plugin-jsdoc: ^50.6.0
eslint-plugin-jsonc: ^2.18.2 eslint-plugin-jsonc: ^2.18.2
eslint-plugin-n: ^17.14.0 eslint-plugin-n: ^17.14.0
eslint-plugin-no-only-tests: ^3.3.0 eslint-plugin-no-only-tests: ^3.3.0
@ -115,9 +115,9 @@ catalog:
jsonwebtoken: ^9.0.2 jsonwebtoken: ^9.0.2
lint-staged: ^15.2.10 lint-staged: ^15.2.10
lodash.clonedeep: ^4.5.0 lodash.clonedeep: ^4.5.0
lucide-vue-next: ^0.460.0 lucide-vue-next: ^0.461.0
medium-zoom: ^1.1.0 medium-zoom: ^1.1.0
naive-ui: ^2.40.1 naive-ui: ^2.40.2
nitropack: ^2.10.4 nitropack: ^2.10.4
nprogress: ^0.2.0 nprogress: ^0.2.0
ora: ^8.1.1 ora: ^8.1.1
@ -131,7 +131,7 @@ catalog:
postcss-import: ^16.1.0 postcss-import: ^16.1.0
postcss-preset-env: ^10.1.1 postcss-preset-env: ^10.1.1
postcss-scss: ^4.0.9 postcss-scss: ^4.0.9
prettier: ^3.3.3 prettier: ^3.4.1
prettier-plugin-tailwindcss: ^0.6.9 prettier-plugin-tailwindcss: ^0.6.9
publint: ^0.2.12 publint: ^0.2.12
qrcode: ^1.5.4 qrcode: ^1.5.4
@ -152,16 +152,16 @@ catalog:
stylelint-order: ^6.0.4 stylelint-order: ^6.0.4
stylelint-prettier: ^5.0.2 stylelint-prettier: ^5.0.2
stylelint-scss: ^6.10.0 stylelint-scss: ^6.10.0
tailwind-merge: ^2.5.4 tailwind-merge: ^2.5.5
tailwindcss: ^3.4.15 tailwindcss: ^3.4.15
tailwindcss-animate: ^1.0.7 tailwindcss-animate: ^1.0.7
theme-colors: ^0.1.0 theme-colors: ^0.1.0
turbo: ^2.3.1 turbo: ^2.3.3
typescript: 5.6.3 typescript: 5.6.3
unbuild: ^3.0.0-rc.11 unbuild: ^3.0.0-rc.11
unplugin-element-plus: ^0.8.0 unplugin-element-plus: ^0.8.0
vee-validate: ^4.14.7 vee-validate: ^4.14.7
vite: ^5.4.11 vite: ^6.0.1
vite-plugin-compression: ^0.5.1 vite-plugin-compression: ^0.5.1
vite-plugin-dts: 4.2.1 vite-plugin-dts: 4.2.1
vite-plugin-html: ^3.2.2 vite-plugin-html: ^3.2.2
@ -170,14 +170,14 @@ catalog:
vite-plugin-vue-devtools: ^7.6.4 vite-plugin-vue-devtools: ^7.6.4
vitepress: ^1.5.0 vitepress: ^1.5.0
vitepress-plugin-group-icons: ^1.3.0 vitepress-plugin-group-icons: ^1.3.0
vitest: ^2.1.5 vitest: ^2.1.6
vue: ^3.5.13 vue: ^3.5.13
vue-eslint-parser: ^9.4.3 vue-eslint-parser: ^9.4.3
vue-i18n: ^10.0.4 vue-i18n: ^10.0.4
vue-router: ^4.4.5 vue-router: ^4.5.0
vue-tsc: ^2.1.10 vue-tsc: ^2.1.10
vxe-pc-ui: ^4.3.4 vxe-pc-ui: ^4.3.6
vxe-table: ^4.9.5 vxe-table: ^4.9.8
watermark-js-plus: ^1.5.7 watermark-js-plus: ^1.5.7
zod: ^3.23.8 zod: ^3.23.8
zod-defaults: ^0.1.3 zod-defaults: ^0.1.3