diff --git a/.changeset/element-plus-theme-switch.md b/.changeset/element-plus-theme-switch.md deleted file mode 100644 index 65d7c4e9f..000000000 --- a/.changeset/element-plus-theme-switch.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@vben/layouts': patch ---- - -fix: update primary color when toggling dark/light mode with custom theme diff --git a/.changeset/page-auto-content-height.md b/.changeset/page-auto-content-height.md deleted file mode 100644 index 6abed73f2..000000000 --- a/.changeset/page-auto-content-height.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@vben/common-ui': patch ---- - -fix: skip fixed footer height in auto-content-height calculation diff --git a/.changeset/small-moons-hunt.md b/.changeset/small-moons-hunt.md deleted file mode 100644 index ba7311e01..000000000 --- a/.changeset/small-moons-hunt.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@vben/icons': patch ---- - -fix: guard svg icon loading during docs SSR diff --git a/.changeset/tree-default-value.md b/.changeset/tree-default-value.md deleted file mode 100644 index a2eeed44b..000000000 --- a/.changeset/tree-default-value.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@vben-core/shadcn-ui': patch ---- - -fix: preserve tree default value when treeData starts empty diff --git a/.npmrc b/.npmrc index 6d28fabf4..7549542d7 100644 --- a/.npmrc +++ b/.npmrc @@ -1,13 +1 @@ registry=https://registry.npmmirror.com -public-hoist-pattern[]=lefthook -public-hoist-pattern[]=eslint -public-hoist-pattern[]=oxfmt -public-hoist-pattern[]=oxlint -public-hoist-pattern[]=stylelint -public-hoist-pattern[]=*postcss* -public-hoist-pattern[]=@commitlint/* -public-hoist-pattern[]=czg - -strict-peer-dependencies=false -auto-install-peers=true -dedupe-peer-dependents=true diff --git a/.vscode/settings.json b/.vscode/settings.json index 993b52039..ff13cfa9c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -38,7 +38,7 @@ // lint && format "oxc.enable": true, - "oxc.typeAware": true, + "oxc.typeAware": false, "oxc.configPath": "oxlint.config.ts", "oxc.fmt.configPath": "oxfmt.config.ts", "eslint.useFlatConfig": true, diff --git a/apps/backend-mock/api/system/user/list.ts b/apps/backend-mock/api/system/user/list.ts new file mode 100644 index 000000000..21d44c8ba --- /dev/null +++ b/apps/backend-mock/api/system/user/list.ts @@ -0,0 +1,85 @@ +import { faker } from '@faker-js/faker'; +import { eventHandler, getQuery } from 'h3'; +import { verifyAccessToken } from '~/utils/jwt-utils'; +import { unAuthorizedResponse, usePageResponseSuccess } from '~/utils/response'; + +const formatterCN = new Intl.DateTimeFormat('zh-CN', { + timeZone: 'Asia/Shanghai', + year: 'numeric', + month: '2-digit', + day: '2-digit', + hour: '2-digit', + minute: '2-digit', + second: '2-digit', +}); + +function generateMockDataList(count: number) { + const dataList = []; + + for (let i = 0; i < count; i++) { + const dataItem: Record = { + id: faker.string.uuid(), + name: faker.commerce.product(), + status: faker.helpers.arrayElement([0, 1]), + createTime: formatterCN.format( + faker.date.between({ from: '2022-01-01', to: '2025-01-01' }), + ), + deptId: faker.string.uuid(), + remark: faker.lorem.sentence(), + }; + + dataList.push(dataItem); + } + + return dataList; +} + +const mockData = generateMockDataList(100); + +export default eventHandler(async (event) => { + const userinfo = verifyAccessToken(event); + if (!userinfo) { + return unAuthorizedResponse(event); + } + + const { + page = 1, + pageSize = 20, + name, + id, + remark, + startTime, + endTime, + deptId, + status, + } = getQuery(event); + let listData = structuredClone(mockData); + if (name) { + listData = listData.filter((item) => + item.name.toLowerCase().includes(String(name).toLowerCase()), + ); + } + if (id) { + listData = listData.filter((item) => + item.id.toLowerCase().includes(String(id).toLowerCase()), + ); + } + if (remark) { + listData = listData.filter((item) => + item.remark?.toLowerCase()?.includes(String(remark).toLowerCase()), + ); + } + if (startTime) { + listData = listData.filter((item) => item.createTime >= startTime); + } + if (endTime) { + listData = listData.filter((item) => item.createTime <= endTime); + } + if (['0', '1'].includes(status as string)) { + listData = listData.filter((item) => item.status === Number(status)); + } + if (deptId) { + listData = listData.filter((item) => item.deptId === deptId); + } + return usePageResponseSuccess(page as string, pageSize as string, listData); +}); diff --git a/apps/web-antd/src/adapter/component/index.ts b/apps/web-antd/src/adapter/component/index.ts index bf34ba767..81b6e8fa3 100644 --- a/apps/web-antd/src/adapter/component/index.ts +++ b/apps/web-antd/src/adapter/component/index.ts @@ -131,8 +131,8 @@ const PreviewGroup = defineAsyncComponent(() => import('ant-design-vue/es/image').then((res) => res.ImagePreviewGroup), ); -const withDefaultPlaceholder = ( - component: T, +const withDefaultPlaceholder = ( + component: Component, type: 'input' | 'select', componentProps: Recordable = {}, ) => { @@ -702,7 +702,9 @@ async function initComponentAdapter() { modelValueProp: 'value', }), Input: withDefaultPlaceholder(Input, 'input'), - InputNumber: withDefaultPlaceholder(InputNumber, 'input'), + InputNumber: withDefaultPlaceholder(InputNumber, 'input', { + style: { width: '100%' }, + }), InputPassword: withDefaultPlaceholder(InputPassword, 'input'), Mentions: withDefaultPlaceholder(Mentions, 'input'), // 自定义主要按钮 diff --git a/apps/web-antdv-next/src/adapter/component/index.ts b/apps/web-antdv-next/src/adapter/component/index.ts index 1099d67a9..e87411d16 100644 --- a/apps/web-antdv-next/src/adapter/component/index.ts +++ b/apps/web-antdv-next/src/adapter/component/index.ts @@ -136,8 +136,8 @@ const PreviewGroup = defineAsyncComponent(() => import('antdv-next/dist/image/index').then((res) => res.ImagePreviewGroup), ); -const withDefaultPlaceholder = ( - component: T, +const withDefaultPlaceholder = ( + component: Component, type: 'input' | 'select', componentProps: Recordable = {}, ) => { @@ -633,7 +633,9 @@ async function initComponentAdapter() { modelValueProp: 'value', }), Input: withDefaultPlaceholder(Input, 'input'), - InputNumber: withDefaultPlaceholder(InputNumber, 'input'), + InputNumber: withDefaultPlaceholder(InputNumber, 'input', { + style: { width: '100%' }, + }), InputPassword: withDefaultPlaceholder(InputPassword, 'input'), Mentions: withDefaultPlaceholder(Mentions, 'input'), // 自定义主要按钮 diff --git a/apps/web-ele/src/adapter/component/index.ts b/apps/web-ele/src/adapter/component/index.ts index b27ca9afa..28d87c568 100644 --- a/apps/web-ele/src/adapter/component/index.ts +++ b/apps/web-ele/src/adapter/component/index.ts @@ -141,8 +141,8 @@ const ElUpload = defineAsyncComponent(() => ]).then(([res]) => res.ElUpload), ); -const withDefaultPlaceholder = ( - component: T, +const withDefaultPlaceholder = ( + component: Component, type: 'input' | 'select', componentProps: Recordable = {}, ) => { @@ -284,7 +284,9 @@ async function initComponentAdapter() { inputComponent: ElInput, }), Input: withDefaultPlaceholder(ElInput, 'input'), - InputNumber: withDefaultPlaceholder(ElInputNumber, 'input'), + InputNumber: withDefaultPlaceholder(ElInputNumber, 'input', { + style: { width: '100%' }, + }), RadioGroup: (props, { attrs, slots }) => { let defaultSlot; if (Reflect.has(slots, 'default')) { diff --git a/apps/web-naive/src/adapter/component/index.ts b/apps/web-naive/src/adapter/component/index.ts index 81fc97027..9ee677f80 100644 --- a/apps/web-naive/src/adapter/component/index.ts +++ b/apps/web-naive/src/adapter/component/index.ts @@ -84,8 +84,8 @@ const NUpload = defineAsyncComponent(() => import('naive-ui/es/upload').then((res) => res.NUpload), ); -const withDefaultPlaceholder = ( - component: T, +const withDefaultPlaceholder = ( + component: Component, type: 'input' | 'select', componentProps: Recordable = {}, ) => { @@ -225,7 +225,9 @@ async function initComponentAdapter() { inputComponent: NInput, }), Input: withDefaultPlaceholder(NInput, 'input'), - InputNumber: withDefaultPlaceholder(NInputNumber, 'input'), + InputNumber: withDefaultPlaceholder(NInputNumber, 'input', { + style: { width: '100%' }, + }), RadioGroup: (props, { attrs, slots }) => { let defaultSlot; if (Reflect.has(slots, 'default')) { diff --git a/apps/web-tdesign/src/adapter/component/index.ts b/apps/web-tdesign/src/adapter/component/index.ts index 54617f84c..37a3055e7 100644 --- a/apps/web-tdesign/src/adapter/component/index.ts +++ b/apps/web-tdesign/src/adapter/component/index.ts @@ -89,8 +89,8 @@ const TreeSelect = defineAsyncComponent( ); const Upload = defineAsyncComponent(() => import('tdesign-vue-next/es/upload')); -const withDefaultPlaceholder = ( - component: T, +const withDefaultPlaceholder = ( + component: Component, type: 'input' | 'select', componentProps: Recordable = {}, ) => { @@ -239,7 +239,9 @@ async function initComponentAdapter() { modelValueProp: 'value', }), Input: withDefaultPlaceholder(Input, 'input'), - InputNumber: withDefaultPlaceholder(InputNumber, 'input'), + InputNumber: withDefaultPlaceholder(InputNumber, 'input', { + style: { width: '100%' }, + }), // InputPassword: withDefaultPlaceholder(InputPassword, 'input'), // Mentions: withDefaultPlaceholder(Mentions, 'input'), // 自定义主要按钮 diff --git a/docs/.vitepress/build/dayjs-loader.mjs b/docs/.vitepress/build/dayjs-loader.mjs new file mode 100644 index 000000000..623c394ff --- /dev/null +++ b/docs/.vitepress/build/dayjs-loader.mjs @@ -0,0 +1,2 @@ +import { register } from 'node:module'; +register('./dayjs-resolve-hook.mjs', import.meta.url); diff --git a/docs/.vitepress/build/dayjs-resolve-hook.mjs b/docs/.vitepress/build/dayjs-resolve-hook.mjs new file mode 100644 index 000000000..f8989044a --- /dev/null +++ b/docs/.vitepress/build/dayjs-resolve-hook.mjs @@ -0,0 +1,10 @@ +const DAYJS_SUBPATH_RE = /^dayjs\/(plugin|locale)\/([^./]+)$/; + +/** @type {import('node:module').ResolveHook} */ +export async function resolve(specifier, context, nextResolve) { + const match = specifier.match(DAYJS_SUBPATH_RE); + if (match) { + return nextResolve(`${specifier}.js`, context); + } + return nextResolve(specifier, context); +} diff --git a/docs/.vitepress/config/index.mts b/docs/.vitepress/config/index.mts index 6b8cb81d8..e966a8c1a 100644 --- a/docs/.vitepress/config/index.mts +++ b/docs/.vitepress/config/index.mts @@ -1,12 +1,12 @@ import { withPwa } from '@vite-pwa/vitepress'; -import { defineConfigWithTheme } from 'vitepress'; +import { defineConfig } from 'vitepress'; import { en } from './en.mts'; import { shared } from './shared.mts'; import { zh } from './zh.mts'; export default withPwa( - defineConfigWithTheme({ + defineConfig({ ...shared, locales: { en: { diff --git a/docs/.vitepress/config/shared.mts b/docs/.vitepress/config/shared.mts index cdfb0b779..30b99d691 100644 --- a/docs/.vitepress/config/shared.mts +++ b/docs/.vitepress/config/shared.mts @@ -5,6 +5,7 @@ import { resolve } from 'node:path'; import { viteArchiverPlugin, + viteDayjsPlugin, viteVxeTableImportsPlugin, } from '@vben/vite-config'; @@ -61,7 +62,7 @@ export const shared = defineConfig({ }, preprocessorOptions: { scss: { - api: 'modern', + // api: 'modern', }, }, }, @@ -69,6 +70,7 @@ export const shared = defineConfig({ stringify: true, }, plugins: [ + viteDayjsPlugin(), tailwindcss(), GitChangelog({ mapAuthors: [ @@ -85,9 +87,23 @@ export const shared = defineConfig({ name: 'Li Kui', username: 'likui628', }, + { + mapByNameAliases: ['Jin Mao', 'jinmao'], + name: 'Jin Mao', + username: 'jinmao88', + }, + { + name: 'Netfan', + username: 'mynetfan', + }, + { + mapByNameAliases: ['xingyu4j', 'xingyu'], + name: 'xingyu4j', + username: 'xingyu4j', + }, ], repoURL: () => 'https://github.com/vbenjs/vue-vben-admin', - }), + }) as any, GitChangelogMarkdownSection(), viteArchiverPlugin({ outputDir: '.vitepress' }), groupIconVitePlugin(), @@ -103,6 +119,7 @@ export const shared = defineConfig({ ssr: { external: ['@vue/repl'], + noExternal: ['@v-c/picker'], }, }, }); @@ -113,7 +130,7 @@ function head(): HeadConfig[] { [ 'meta', { - content: 'vben, vitejs, vite, shacdn-ui, vue', + content: 'vben, vitejs, vite, shadcn-ui, vue', name: 'keywords', }, ], diff --git a/docs/.vitepress/config/zh.mts b/docs/.vitepress/config/zh.mts index 140e4626a..c90418b8d 100644 --- a/docs/.vitepress/config/zh.mts +++ b/docs/.vitepress/config/zh.mts @@ -337,8 +337,8 @@ export const search: DefaultTheme.AlgoliaSearchOptions['locales'] = { footer: { closeText: '关闭', navigateText: '切换', - searchByText: '搜索提供者', selectText: '选择', + poweredByText: '搜索提供者', }, noResultsScreen: { noResultsText: '无法找到相关结果', @@ -347,10 +347,10 @@ export const search: DefaultTheme.AlgoliaSearchOptions['locales'] = { suggestedQueryText: '你可以尝试查询', }, searchBox: { - cancelButtonAriaLabel: '取消', - cancelButtonText: '取消', - resetButtonAriaLabel: '清除查询条件', - resetButtonTitle: '清除查询条件', + closeButtonAriaLabel: '取消', + closeButtonText: '取消', + clearButtonAriaLabel: '清除查询条件', + clearButtonTitle: '清除查询条件', }, startScreen: { favoriteSearchesTitle: '收藏', diff --git a/docs/.vitepress/theme/components/site-layout.vue b/docs/.vitepress/theme/components/site-layout.vue index 96427d055..8b40ed3f7 100644 --- a/docs/.vitepress/theme/components/site-layout.vue +++ b/docs/.vitepress/theme/components/site-layout.vue @@ -10,7 +10,7 @@ import { // import { useAntdDesignTokens } from '@vben/hooks'; // import { initPreferences } from '@vben/preferences'; -import { ConfigProvider, theme } from 'ant-design-vue'; +import { ConfigProvider, theme } from 'antdv-next'; import mediumZoom from 'medium-zoom'; import { useRoute } from 'vitepress'; import DefaultTheme from 'vitepress/theme'; diff --git a/docs/package.json b/docs/package.json index c418d797f..400fb2a6b 100644 --- a/docs/package.json +++ b/docs/package.json @@ -2,8 +2,9 @@ "name": "@vben/docs", "version": "5.7.0", "private": true, + "type": "module", "scripts": { - "build": "vitepress build", + "build": "cross-env NODE_OPTIONS=\"--import ./.vitepress/build/dayjs-loader.mjs\" vitepress build", "dev": "vitepress dev", "docs:preview": "vitepress preview" }, @@ -19,7 +20,7 @@ "@vben/locales": "workspace:*", "@vben/plugins": "workspace:*", "@vben/styles": "workspace:*", - "ant-design-vue": "catalog:", + "antdv-next": "catalog:", "lucide-vue-next": "catalog:", "medium-zoom": "catalog:", "reka-ui": "catalog:", diff --git a/docs/src/_env/adapter/component.ts b/docs/src/_env/adapter/component.ts index ec3d0196c..0fa10f3ff 100644 --- a/docs/src/_env/adapter/component.ts +++ b/docs/src/_env/adapter/component.ts @@ -26,16 +26,15 @@ import { notification, Radio, RadioGroup, - RangePicker, Rate, Select, Space, Switch, - Textarea, + TextArea, TimePicker, TreeSelect, Upload, -} from 'ant-design-vue'; +} from 'antdv-next'; const withDefaultPlaceholder = ( component: T, @@ -98,12 +97,12 @@ async function initComponentAdapter() { }, Radio, RadioGroup, - RangePicker, + RangePicker: withDefaultPlaceholder(DatePicker.RangePicker, 'select'), Rate, Select: withDefaultPlaceholder(Select, 'select'), Space, Switch, - Textarea: withDefaultPlaceholder(Textarea, 'input'), + Textarea: withDefaultPlaceholder(TextArea, 'input'), TimePicker, TreeSelect: withDefaultPlaceholder(TreeSelect, 'select'), Upload, @@ -118,7 +117,7 @@ async function initComponentAdapter() { copyPreferencesSuccess: (title, content) => { notification.success({ description: content, - message: title, + title, placement: 'bottomRight', }); }, diff --git a/docs/src/_env/adapter/vxe-table.ts b/docs/src/_env/adapter/vxe-table.ts index 7bc27056e..6d9ed6449 100644 --- a/docs/src/_env/adapter/vxe-table.ts +++ b/docs/src/_env/adapter/vxe-table.ts @@ -2,7 +2,7 @@ import { h } from 'vue'; import { setupVbenVxeTable, useVbenVxeGrid } from '@vben/plugins/vxe-table'; -import { Button, Image } from 'ant-design-vue'; +import { Button, Image } from 'antdv-next'; import { useVbenForm } from './form'; diff --git a/docs/src/components/common-ui/vben-api-component.md b/docs/src/components/common-ui/vben-api-component.md index 5465f1516..b14e07258 100644 --- a/docs/src/components/common-ui/vben-api-component.md +++ b/docs/src/components/common-ui/vben-api-component.md @@ -22,7 +22,7 @@ outline: deep