Merge branch 'fork/xingyu4j/antdv-next'
commit
76cfcda2e9
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
'@vben/layouts': patch
|
||||
---
|
||||
|
||||
fix: update primary color when toggling dark/light mode with custom theme
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
'@vben/common-ui': patch
|
||||
---
|
||||
|
||||
fix: skip fixed footer height in auto-content-height calculation
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
'@vben/icons': patch
|
||||
---
|
||||
|
||||
fix: guard svg icon loading during docs SSR
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
'@vben-core/shadcn-ui': patch
|
||||
---
|
||||
|
||||
fix: preserve tree default value when treeData starts empty
|
||||
12
.npmrc
12
.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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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<string, any> = {
|
||||
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);
|
||||
});
|
||||
|
|
@ -131,8 +131,8 @@ const PreviewGroup = defineAsyncComponent(() =>
|
|||
import('ant-design-vue/es/image').then((res) => res.ImagePreviewGroup),
|
||||
);
|
||||
|
||||
const withDefaultPlaceholder = <T extends Component>(
|
||||
component: T,
|
||||
const withDefaultPlaceholder = (
|
||||
component: Component,
|
||||
type: 'input' | 'select',
|
||||
componentProps: Recordable<any> = {},
|
||||
) => {
|
||||
|
|
@ -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'),
|
||||
// 自定义主要按钮
|
||||
|
|
|
|||
|
|
@ -136,8 +136,8 @@ const PreviewGroup = defineAsyncComponent(() =>
|
|||
import('antdv-next/dist/image/index').then((res) => res.ImagePreviewGroup),
|
||||
);
|
||||
|
||||
const withDefaultPlaceholder = <T extends Component>(
|
||||
component: T,
|
||||
const withDefaultPlaceholder = (
|
||||
component: Component,
|
||||
type: 'input' | 'select',
|
||||
componentProps: Recordable<any> = {},
|
||||
) => {
|
||||
|
|
@ -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'),
|
||||
// 自定义主要按钮
|
||||
|
|
|
|||
|
|
@ -141,8 +141,8 @@ const ElUpload = defineAsyncComponent(() =>
|
|||
]).then(([res]) => res.ElUpload),
|
||||
);
|
||||
|
||||
const withDefaultPlaceholder = <T extends Component>(
|
||||
component: T,
|
||||
const withDefaultPlaceholder = (
|
||||
component: Component,
|
||||
type: 'input' | 'select',
|
||||
componentProps: Recordable<any> = {},
|
||||
) => {
|
||||
|
|
@ -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')) {
|
||||
|
|
|
|||
|
|
@ -84,8 +84,8 @@ const NUpload = defineAsyncComponent(() =>
|
|||
import('naive-ui/es/upload').then((res) => res.NUpload),
|
||||
);
|
||||
|
||||
const withDefaultPlaceholder = <T extends Component>(
|
||||
component: T,
|
||||
const withDefaultPlaceholder = (
|
||||
component: Component,
|
||||
type: 'input' | 'select',
|
||||
componentProps: Recordable<any> = {},
|
||||
) => {
|
||||
|
|
@ -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')) {
|
||||
|
|
|
|||
|
|
@ -89,8 +89,8 @@ const TreeSelect = defineAsyncComponent(
|
|||
);
|
||||
const Upload = defineAsyncComponent(() => import('tdesign-vue-next/es/upload'));
|
||||
|
||||
const withDefaultPlaceholder = <T extends Component>(
|
||||
component: T,
|
||||
const withDefaultPlaceholder = (
|
||||
component: Component,
|
||||
type: 'input' | 'select',
|
||||
componentProps: Recordable<any> = {},
|
||||
) => {
|
||||
|
|
@ -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'),
|
||||
// 自定义主要按钮
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
import { register } from 'node:module';
|
||||
register('./dayjs-resolve-hook.mjs', import.meta.url);
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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: {
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
},
|
||||
],
|
||||
|
|
|
|||
|
|
@ -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: '收藏',
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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:",
|
||||
|
|
|
|||
|
|
@ -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 = <T extends Component>(
|
||||
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',
|
||||
});
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ outline: deep
|
|||
<script lang="ts" setup>
|
||||
import { ApiComponent } from '@vben/common-ui';
|
||||
|
||||
import { Cascader } from 'ant-design-vue';
|
||||
import { Cascader } from 'antdv-next';
|
||||
|
||||
const treeData: Record<string, any> = [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ import {
|
|||
TimePicker,
|
||||
TreeSelect,
|
||||
Upload,
|
||||
} from 'ant-design-vue';
|
||||
} from 'antdv-next';
|
||||
|
||||
const withDefaultPlaceholder = <T extends Component>(
|
||||
component: T,
|
||||
|
|
|
|||
|
|
@ -25,7 +25,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';
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { h } from 'vue';
|
|||
|
||||
import { alert, VbenButton } from '@vben/common-ui';
|
||||
|
||||
import { Result } from 'ant-design-vue';
|
||||
import { Result } from 'antdv-next';
|
||||
|
||||
function showAlert() {
|
||||
alert('This is an alert message');
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { h, ref } from 'vue';
|
|||
|
||||
import { alert, confirm, VbenButton } from '@vben/common-ui';
|
||||
|
||||
import { Checkbox, message } from 'ant-design-vue';
|
||||
import { Checkbox, message } from 'antdv-next';
|
||||
|
||||
function showConfirm() {
|
||||
confirm('This is an alert message')
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { h } from 'vue';
|
|||
|
||||
import { alert, prompt, useAlertContext, VbenButton } from '@vben/common-ui';
|
||||
|
||||
import { Input, RadioGroup, Select } from 'ant-design-vue';
|
||||
import { Input, RadioGroup, Select } from 'antdv-next';
|
||||
import { BadgeJapaneseYen } from 'lucide-vue-next';
|
||||
|
||||
function showPrompt() {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts" setup>
|
||||
import { ApiComponent } from '@vben/common-ui';
|
||||
|
||||
import { Cascader } from 'ant-design-vue';
|
||||
import { Cascader } from 'antdv-next';
|
||||
|
||||
const treeData: Record<string, any> = [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts" setup>
|
||||
import { Button, message, Space } from 'ant-design-vue';
|
||||
import { Button, message, Space } from 'antdv-next';
|
||||
|
||||
import { useVbenForm } from '#/adapter/form';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts" setup>
|
||||
import { message } from 'ant-design-vue';
|
||||
import { message } from 'antdv-next';
|
||||
|
||||
import { useVbenForm } from '#/adapter/form';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts" setup>
|
||||
import { h } from 'vue';
|
||||
|
||||
import { Input, message } from 'ant-design-vue';
|
||||
import { Input, message } from 'antdv-next';
|
||||
|
||||
import { useVbenForm } from '#/adapter/form';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts" setup>
|
||||
import { message } from 'ant-design-vue';
|
||||
import { message } from 'antdv-next';
|
||||
|
||||
import { useVbenForm } from '#/adapter/form';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts" setup>
|
||||
import { message } from 'ant-design-vue';
|
||||
import { message } from 'antdv-next';
|
||||
|
||||
import { useVbenForm } from '#/adapter/form';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts" setup>
|
||||
import { message } from 'ant-design-vue';
|
||||
import { message } from 'antdv-next';
|
||||
|
||||
import { useVbenForm, z } from '#/adapter/form';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts" setup>
|
||||
import { computed, nextTick, onMounted, ref, watch } from 'vue';
|
||||
|
||||
import { Button, Card, message, Space, Tag } from 'ant-design-vue';
|
||||
import { Button, Card, message, Space, Tag } from 'antdv-next';
|
||||
|
||||
import { useVbenForm } from '#/adapter/form';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts" setup>
|
||||
import type { VxeGridListeners, VxeGridProps } from '#/adapter/vxe-table';
|
||||
|
||||
import { Button, message } from 'ant-design-vue';
|
||||
import { Button, message } from 'antdv-next';
|
||||
|
||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts" setup>
|
||||
import type { VxeGridProps } from '#/adapter/vxe-table';
|
||||
|
||||
import { Button, Image, Switch, Tag } from 'ant-design-vue';
|
||||
import { Button, Image, Switch, Tag } from 'antdv-next';
|
||||
|
||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts" setup>
|
||||
import type { VxeGridProps } from '#/adapter/vxe-table';
|
||||
|
||||
import { Button, message } from 'ant-design-vue';
|
||||
import { Button, message } from 'antdv-next';
|
||||
|
||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts" setup>
|
||||
import type { VxeGridProps } from '#/adapter/vxe-table';
|
||||
|
||||
import { Button } from 'ant-design-vue';
|
||||
import { Button } from 'antdv-next';
|
||||
|
||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
import type { VbenFormProps } from '#/adapter/form';
|
||||
import type { VxeGridProps } from '#/adapter/vxe-table';
|
||||
|
||||
import { message } from 'ant-design-vue';
|
||||
import { message } from 'antdv-next';
|
||||
|
||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import type { DemoTableApi } from '../mock-api';
|
|||
|
||||
import type { VxeGridProps } from '#/adapter/vxe-table';
|
||||
|
||||
import { Button } from 'ant-design-vue';
|
||||
import { Button } from 'antdv-next';
|
||||
|
||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts" setup>
|
||||
import type { VxeGridProps } from '#/adapter/vxe-table';
|
||||
|
||||
import { Button } from 'ant-design-vue';
|
||||
import { Button } from 'antdv-next';
|
||||
|
||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ The current wrapper flow is:
|
|||
<script lang="ts" setup>
|
||||
import { ApiComponent } from '@vben/common-ui';
|
||||
|
||||
import { Cascader } from 'ant-design-vue';
|
||||
import { Cascader } from 'antdv-next';
|
||||
|
||||
function fetchApi() {
|
||||
return Promise.resolve([
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ import {
|
|||
TimePicker,
|
||||
TreeSelect,
|
||||
Upload,
|
||||
} from 'ant-design-vue';
|
||||
} from 'antdv-next';
|
||||
|
||||
const withDefaultPlaceholder = <T extends Component>(
|
||||
component: T,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# External Modules
|
||||
|
||||
In addition to the external modules that are included by default in the project, sometimes we need to import other external modules. Let's take [ant-design-vue](https://antdv.com/components/overview) as an example:
|
||||
In addition to the external modules that are included by default in the project, sometimes we need to import other external modules. Let's take [antdv-next](https://antdv.com/components/overview) as an example:
|
||||
|
||||
## Installing Dependencies
|
||||
|
||||
|
|
@ -13,7 +13,7 @@ In addition to the external modules that are included by default in the project,
|
|||
|
||||
```bash
|
||||
# cd /path/to/your/package
|
||||
pnpm add ant-design-vue
|
||||
pnpm add antdv-next
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
|
@ -22,9 +22,9 @@ pnpm add ant-design-vue
|
|||
|
||||
```ts
|
||||
import { createApp } from 'vue';
|
||||
import Antd from 'ant-design-vue';
|
||||
import Antd from 'antdv-next';
|
||||
import App from './App';
|
||||
import 'ant-design-vue/dist/reset.css';
|
||||
import 'antdv-next/dist/reset.css';
|
||||
|
||||
const app = createApp(App);
|
||||
|
||||
|
|
@ -43,7 +43,7 @@ app.use(Antd).mount('#app');
|
|||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import { Button } from 'ant-design-vue';
|
||||
import { Button } from 'antdv-next';
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
|||
|
|
@ -174,7 +174,7 @@ import {
|
|||
} from '@vben/request';
|
||||
import { useAccessStore } from '@vben/stores';
|
||||
|
||||
import { message } from 'ant-design-vue';
|
||||
import { message } from 'antdv-next';
|
||||
|
||||
import { useAuthStore } from '#/store';
|
||||
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ registry = https://registry.npmmirror.com/
|
|||
If you encounter errors similar to the following, please check that the full project path (including all parent paths) does not contain Chinese, Japanese, or Korean characters. Otherwise, you will encounter a 404 error for the path, leading to the following issue:
|
||||
|
||||
```ts
|
||||
[vite] Failed to resolve module import "ant-design-vue/dist/antd.css-vben-adminode_modulesant-design-vuedistantd.css". (imported by /@/setup/ant-design-vue/index.ts)
|
||||
[vite] Failed to resolve module import "antdv-next/dist/antd.css-vben-adminode_modulesantdv-nextdistantd.css". (imported by /@/setup/antdv-next/index.ts)
|
||||
```
|
||||
|
||||
## Console Route Warning Issue
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# 外部模块
|
||||
|
||||
除了项目默认引入的外部模块,有时我们还需要引入其他外部模块。我们以 [ant-design-vue](https://antdv.com/components/overview) 为例:
|
||||
除了项目默认引入的外部模块,有时我们还需要引入其他外部模块。我们以 [antdv-next](https://antdv.com/components/overview) 为例:
|
||||
|
||||
## 安装依赖
|
||||
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
```bash
|
||||
# cd /path/to/your/package
|
||||
pnpm add ant-design-vue
|
||||
pnpm add antdv-next
|
||||
```
|
||||
|
||||
## 使用
|
||||
|
|
@ -22,9 +22,9 @@ pnpm add ant-design-vue
|
|||
|
||||
```ts
|
||||
import { createApp } from 'vue';
|
||||
import Antd from 'ant-design-vue';
|
||||
import Antd from 'antdv-next';
|
||||
import App from './App';
|
||||
import 'ant-design-vue/dist/reset.css';
|
||||
import 'antdv-next/dist/reset.css';
|
||||
|
||||
const app = createApp(App);
|
||||
|
||||
|
|
@ -43,7 +43,7 @@ app.use(Antd).mount('#app');
|
|||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import { Button } from 'ant-design-vue';
|
||||
import { Button } from 'antdv-next';
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
|||
|
|
@ -204,7 +204,7 @@ import {
|
|||
} from '@vben/request';
|
||||
import { useAccessStore } from '@vben/stores';
|
||||
|
||||
import { message } from 'ant-design-vue';
|
||||
import { message } from 'antdv-next';
|
||||
|
||||
import { useAuthStore } from '#/store';
|
||||
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ pnpm add version-polling
|
|||
```ts
|
||||
import { h } from 'vue';
|
||||
|
||||
import { Button, notification } from 'ant-design-vue';
|
||||
import { Button, notification } from 'antdv-next';
|
||||
import { createVersionPolling } from 'version-polling';
|
||||
|
||||
createVersionPolling({
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ registry = https://registry.npmmirror.com/
|
|||
如果出现类似以下错误,请检查项目全路径(包含所有父级路径)不能出现中文、日文、韩文。否则将会出现路径访问 404 导致以下问题
|
||||
|
||||
```ts
|
||||
[vite] Failed to resolve module import "ant-design-vue/dist/antd.css-vben-adminode_modulesant-design-vuedistantd.css". (imported by /@/setup/ant-design-vue/index.ts)
|
||||
[vite] Failed to resolve module import "antdv-next/dist/antd.css-vben-adminode_modulesantdv-nextdistantd.css". (imported by /@/setup/antdv-next/index.ts)
|
||||
```
|
||||
|
||||
## 控制台路由警告问题
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ const comments: OxlintConfig = {
|
|||
},
|
||||
],
|
||||
rules: {
|
||||
'eslint/no-underscore-dangle': 'off',
|
||||
'eslint-comments/no-aggregating-enable': 'error',
|
||||
'eslint-comments/no-duplicate-disable': 'error',
|
||||
'eslint-comments/no-unlimited-disable': 'error',
|
||||
|
|
|
|||
|
|
@ -0,0 +1,70 @@
|
|||
import type { Plugin } from 'vite';
|
||||
|
||||
function viteDayjsPlugin(): Plugin {
|
||||
return {
|
||||
name: 'vite-dayjs-plugin',
|
||||
enforce: 'pre',
|
||||
async resolveId(source, importer, options) {
|
||||
// 1) 已经使用了 dayjs/esm 的不处理
|
||||
if (source.startsWith('dayjs/esm')) return null;
|
||||
|
||||
// 2) 根入口:dayjs -> dayjs/esm
|
||||
if (source === 'dayjs') {
|
||||
return await this.resolve('dayjs/esm', importer, {
|
||||
skipSelf: true,
|
||||
...options,
|
||||
});
|
||||
}
|
||||
|
||||
// 3) 插件入口的多种写法
|
||||
// - dayjs/plugin/xxx.js -> dayjs/esm/plugin/xxx/index.js
|
||||
// - dayjs/plugin/xxx -> dayjs/esm/plugin/xxx
|
||||
const pluginWithJs = source.match(/^dayjs\/plugin\/([^/]+)\.js$/);
|
||||
if (pluginWithJs) {
|
||||
const target = `dayjs/esm/plugin/${pluginWithJs[1]}/index.js`;
|
||||
return await this.resolve(target, importer, {
|
||||
skipSelf: true,
|
||||
...options,
|
||||
});
|
||||
}
|
||||
|
||||
const pluginBare = source.match(/^dayjs\/plugin\/([^/]+)$/);
|
||||
if (pluginBare) {
|
||||
const target = `dayjs/esm/plugin/${pluginBare[1]}`;
|
||||
return await this.resolve(target, importer, {
|
||||
skipSelf: true,
|
||||
...options,
|
||||
});
|
||||
}
|
||||
|
||||
// 4) 处理多语言包
|
||||
// - dayjs/locale/xxx.js -> dayjs/esm/locale/xxx.js
|
||||
const localeWithJs = source.match(/^dayjs\/locale\/([^/]+)\.js$/);
|
||||
if (localeWithJs) {
|
||||
const target = `dayjs/esm/locale/${localeWithJs[1]}.js`;
|
||||
return await this.resolve(target, importer, {
|
||||
skipSelf: true,
|
||||
...options,
|
||||
});
|
||||
}
|
||||
const localeBare = source.match(/^dayjs\/locale\/([^/]+)$/);
|
||||
if (localeBare) {
|
||||
const target = `dayjs/esm/locale/${localeBare[1]}`;
|
||||
return await this.resolve(target, importer, {
|
||||
skipSelf: true,
|
||||
...options,
|
||||
});
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
config() {
|
||||
return {
|
||||
optimizeDeps: {
|
||||
exclude: ['dayjs'],
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
}
|
||||
export { viteDayjsPlugin };
|
||||
|
|
@ -18,6 +18,7 @@ import { VitePWA } from 'vite-plugin-pwa';
|
|||
import viteVueDevTools from 'vite-plugin-vue-devtools';
|
||||
|
||||
import { viteArchiverPlugin } from './archiver';
|
||||
import { viteDayjsPlugin } from './dayjs';
|
||||
import { viteExtraAppConfigPlugin } from './extra-app-config';
|
||||
import { viteHtmlPlugin } from './html';
|
||||
import { viteImportMapPlugin } from './importmap';
|
||||
|
|
@ -105,6 +106,7 @@ async function loadApplicationPlugins(
|
|||
compressTypes,
|
||||
extraAppConfig,
|
||||
html,
|
||||
dayjs,
|
||||
i18n,
|
||||
importmap,
|
||||
importmapOptions,
|
||||
|
|
@ -219,6 +221,10 @@ async function loadApplicationPlugins(
|
|||
return [await viteArchiverPlugin(archiverPluginOptions)];
|
||||
},
|
||||
},
|
||||
{
|
||||
condition: dayjs,
|
||||
plugins: () => [viteDayjsPlugin()],
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
@ -247,6 +253,7 @@ export {
|
|||
loadLibraryPlugins,
|
||||
viteArchiverPlugin,
|
||||
viteCompressPlugin,
|
||||
viteDayjsPlugin,
|
||||
viteDtsPlugin,
|
||||
viteHtmlPlugin,
|
||||
viteVisualizerPlugin,
|
||||
|
|
|
|||
|
|
@ -214,6 +214,11 @@ interface ApplicationPluginOptions extends CommonPluginOptions {
|
|||
* @description 可选的压缩类型
|
||||
*/
|
||||
compressTypes?: ('brotli' | 'gzip')[];
|
||||
/**
|
||||
* 是否开启 dayjs 插件
|
||||
* @default true
|
||||
*/
|
||||
dayjs?: boolean;
|
||||
/**
|
||||
* 是否抽离配置文件
|
||||
* @default false
|
||||
|
|
|
|||
|
|
@ -102,8 +102,8 @@
|
|||
"vue-tsc": "catalog:"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^20.19.0 || ^22.18.0 || ^24.0.0",
|
||||
"node": "^22.18.0 || ^24.0.0",
|
||||
"pnpm": ">=10.0.0"
|
||||
},
|
||||
"packageManager": "pnpm@10.33.0"
|
||||
"packageManager": "pnpm@10.33.4"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ class IndexedDBDriver implements IStorageDriver {
|
|||
});
|
||||
}
|
||||
|
||||
async setItem<T>(key: string, value: T): Promise<void> {
|
||||
async setItem(key: string, value: unknown): Promise<void> {
|
||||
const db = await this.getDB();
|
||||
return new Promise((resolve, reject) => {
|
||||
const tx = db.transaction(this.storeName, 'readwrite');
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ class LocalStorageDriver implements IStorageDriver {
|
|||
this.storage.removeItem(key);
|
||||
}
|
||||
|
||||
async setItem<T>(key: string, value: T): Promise<void> {
|
||||
async setItem(key: string, value: unknown): Promise<void> {
|
||||
this.storage.setItem(key, JSON.stringify(value));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ class MemoryStorageDriver implements IStorageDriver {
|
|||
this.store.delete(key);
|
||||
}
|
||||
|
||||
async setItem<T>(key: string, value: T): Promise<void> {
|
||||
async setItem(key: string, value: unknown): Promise<void> {
|
||||
this.store.set(key, value);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -106,10 +106,10 @@ class StorageManager {
|
|||
* @param value 值
|
||||
* @param ttl 存活时间(毫秒)
|
||||
*/
|
||||
async setItem<T>(key: string, value: T, ttl?: number): Promise<void> {
|
||||
async setItem(key: string, value: unknown, ttl?: number): Promise<void> {
|
||||
const fullKey = this.getFullKey(key);
|
||||
const expiry = ttl ? Date.now() + ttl : undefined;
|
||||
const item: StorageItem<T> = { expiry, value };
|
||||
const item: StorageItem<unknown> = { expiry, value };
|
||||
await this.driver.setItem(fullKey, item);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ interface IStorageDriver {
|
|||
removeItem(key: string): Promise<void>;
|
||||
|
||||
/** 设置存储项 */
|
||||
setItem<T>(key: string, value: T): Promise<void>;
|
||||
setItem(key: string, value: unknown): Promise<void>;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -34,7 +34,9 @@ describe('stateHandler', () => {
|
|||
}, 10);
|
||||
|
||||
// 等待过程中,期望 Promise 被 reject
|
||||
await expect(handler.waitForCondition()).rejects.toThrow();
|
||||
await expect(handler.waitForCondition()).rejects.toThrow(
|
||||
'Condition was set to false',
|
||||
);
|
||||
expect(handler.isConditionTrue()).toBe(false);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -138,8 +138,10 @@ describe('getNestedValue', () => {
|
|||
expect(result).toBe(2);
|
||||
});
|
||||
|
||||
it('should return the entire object if path is empty', () => {
|
||||
expect(() => getNestedValue(data, '')()).toThrow();
|
||||
it('should throw if path is empty', () => {
|
||||
expect(() => getNestedValue(data, '')).toThrow(
|
||||
'Path must be a non-empty string',
|
||||
);
|
||||
});
|
||||
|
||||
it('should handle paths with array indexes', () => {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
export class StateHandler {
|
||||
private condition: boolean = false;
|
||||
private rejectCondition: (() => void) | null = null;
|
||||
private rejectCondition: ((reason?: Error) => void) | null = null;
|
||||
private resolveCondition: (() => void) | null = null;
|
||||
|
||||
isConditionTrue(): boolean {
|
||||
|
|
@ -16,7 +16,7 @@ export class StateHandler {
|
|||
setConditionFalse() {
|
||||
this.condition = false;
|
||||
if (this.rejectCondition) {
|
||||
this.rejectCondition();
|
||||
this.rejectCondition(new Error('Condition was set to false'));
|
||||
this.clearPromises();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -180,11 +180,7 @@ class PreferenceManager {
|
|||
* 更新扩展偏好设置
|
||||
* @param updates - 要更新的扩展偏好设置
|
||||
*/
|
||||
updateCustomPreferences = <
|
||||
TCustomPreferences extends object = CustomPreferencesRecord,
|
||||
>(
|
||||
updates: DeepPartial<TCustomPreferences>,
|
||||
) => {
|
||||
updateCustomPreferences = (updates: DeepPartial<object>) => {
|
||||
if (!this.customPreferencesExtension) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ function findPlaceholderPos(doc: ProseMirrorNode, blobUrl: string): number {
|
|||
found = offset;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
return found;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* eslint-disable unicorn/no-nested-ternary */
|
||||
import type { VxeGridProps as VxeTableGridProps } from 'vxe-table';
|
||||
|
||||
import type {
|
||||
|
|
@ -182,13 +183,11 @@ export function useViewedRow<T = any>(
|
|||
options: ViewedRowOptions<T> & { keyField: string },
|
||||
) {
|
||||
// ========== 解析持久化配置 ==========
|
||||
let persistOpts: null | ViewedRowPersistOptions = null;
|
||||
if (options.persist) {
|
||||
persistOpts =
|
||||
typeof options.persist === 'string'
|
||||
const persistOpts: null | ViewedRowPersistOptions = options.persist
|
||||
? typeof options.persist === 'string'
|
||||
? { key: options.persist, type: 'localStorage' }
|
||||
: options.persist;
|
||||
}
|
||||
: options.persist
|
||||
: null;
|
||||
|
||||
const adapter = createStorageAdapter(options.persist);
|
||||
const maxSize = persistOpts?.maxSize ?? 100;
|
||||
|
|
@ -521,12 +520,12 @@ export function applyViewedRowOptions(
|
|||
};
|
||||
|
||||
// 拦截 CellOperation columns
|
||||
let actionCodes: string[] = [];
|
||||
if (!isBoolean(viewedRowConfig) && viewedRowConfig.actionCodes) {
|
||||
actionCodes = Array.isArray(viewedRowConfig.actionCodes)
|
||||
const actionCodes =
|
||||
!isBoolean(viewedRowConfig) && viewedRowConfig.actionCodes
|
||||
? Array.isArray(viewedRowConfig.actionCodes)
|
||||
? viewedRowConfig.actionCodes
|
||||
: [viewedRowConfig.actionCodes];
|
||||
}
|
||||
: [viewedRowConfig.actionCodes]
|
||||
: [];
|
||||
|
||||
if (actionCodes.length > 0 && Array.isArray(mergedOptions.columns)) {
|
||||
mergedOptions.columns = wrapColumnsForViewedRow(
|
||||
|
|
|
|||
|
|
@ -50,24 +50,18 @@ describe('requestClient', () => {
|
|||
|
||||
it('should handle network errors', async () => {
|
||||
mock.onGet('/test/error').networkError();
|
||||
try {
|
||||
await requestClient.get('/test/error');
|
||||
expect(true).toBe(false);
|
||||
} catch (error: any) {
|
||||
expect(error.isAxiosError).toBe(true);
|
||||
expect(error.message).toBe('Network Error');
|
||||
}
|
||||
await expect(requestClient.get('/test/error')).rejects.toMatchObject({
|
||||
isAxiosError: true,
|
||||
message: 'Network Error',
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle timeout', async () => {
|
||||
mock.onGet('/test/timeout').timeout();
|
||||
try {
|
||||
await requestClient.get('/test/timeout');
|
||||
expect(true).toBe(false);
|
||||
} catch (error: any) {
|
||||
expect(error.isAxiosError).toBe(true);
|
||||
expect(error.code).toBe('ECONNABORTED');
|
||||
}
|
||||
await expect(requestClient.get('/test/timeout')).rejects.toMatchObject({
|
||||
isAxiosError: true,
|
||||
code: 'ECONNABORTED',
|
||||
});
|
||||
});
|
||||
|
||||
it('should successfully upload a file', async () => {
|
||||
|
|
@ -92,7 +86,7 @@ describe('requestClient', () => {
|
|||
|
||||
mock.onGet('/test/download').reply(200, mockFileContent);
|
||||
|
||||
const res = await requestClient.download('/test/download');
|
||||
const res = await requestClient.download<any>('/test/download');
|
||||
|
||||
expect(res.data).toBeInstanceOf(Blob);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@
|
|||
"@vben/types": "workspace:*",
|
||||
"@vben/utils": "workspace:*",
|
||||
"@vueuse/core": "catalog:",
|
||||
"ant-design-vue": "catalog:",
|
||||
"antdv-next": "catalog:",
|
||||
"dayjs": "catalog:",
|
||||
"json-bigint": "catalog:",
|
||||
"pinia": "catalog:",
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import type {
|
|||
MentionsProps,
|
||||
RadioGroupProps,
|
||||
RadioProps,
|
||||
RangePickerProps,
|
||||
RateProps,
|
||||
SelectProps,
|
||||
SpaceProps,
|
||||
|
|
@ -28,8 +29,7 @@ import type {
|
|||
UploadChangeParam,
|
||||
UploadFile,
|
||||
UploadProps,
|
||||
} from 'ant-design-vue';
|
||||
import type { RangePickerProps } from 'ant-design-vue/es/date-picker';
|
||||
} from 'antdv-next';
|
||||
|
||||
import type { Component, Ref } from 'vue';
|
||||
|
||||
|
|
@ -72,7 +72,7 @@ import { isEmpty } from '@vben/utils';
|
|||
|
||||
import { VbenCollapsibleParams } from '@vben-core/shadcn-ui';
|
||||
|
||||
import { message, Modal, notification } from 'ant-design-vue';
|
||||
import { message, Modal, notification } from 'antdv-next';
|
||||
|
||||
import { upload_file } from '#/api/examples/upload';
|
||||
type AdapterUploadProps = UploadProps & {
|
||||
|
|
@ -86,60 +86,72 @@ type AdapterUploadProps = UploadProps & {
|
|||
};
|
||||
|
||||
const AutoComplete = defineAsyncComponent(
|
||||
() => import('ant-design-vue/es/auto-complete'),
|
||||
() => import('antdv-next/dist/auto-complete/index'),
|
||||
);
|
||||
const Button = defineAsyncComponent(
|
||||
() => import('antdv-next/dist/button/index'),
|
||||
);
|
||||
const Button = defineAsyncComponent(() => import('ant-design-vue/es/button'));
|
||||
const Checkbox = defineAsyncComponent(
|
||||
() => import('ant-design-vue/es/checkbox'),
|
||||
() => import('antdv-next/dist/checkbox/index'),
|
||||
);
|
||||
const CheckboxGroup = defineAsyncComponent(() =>
|
||||
import('ant-design-vue/es/checkbox').then((res) => res.CheckboxGroup),
|
||||
import('antdv-next/dist/checkbox/index').then((res) => res.CheckboxGroup),
|
||||
);
|
||||
const DatePicker = defineAsyncComponent(
|
||||
() => import('ant-design-vue/es/date-picker'),
|
||||
() => import('antdv-next/dist/date-picker/index'),
|
||||
);
|
||||
const Divider = defineAsyncComponent(() => import('ant-design-vue/es/divider'));
|
||||
const Input = defineAsyncComponent(() => import('ant-design-vue/es/input'));
|
||||
const Divider = defineAsyncComponent(
|
||||
() => import('antdv-next/dist/divider/index'),
|
||||
);
|
||||
const Input = defineAsyncComponent(() => import('antdv-next/dist/input/index'));
|
||||
const InputNumber = defineAsyncComponent(
|
||||
() => import('ant-design-vue/es/input-number'),
|
||||
() => import('antdv-next/dist/input-number/index'),
|
||||
);
|
||||
const InputPassword = defineAsyncComponent(() =>
|
||||
import('ant-design-vue/es/input').then((res) => res.InputPassword),
|
||||
import('antdv-next/dist/input/index').then((res) => res.InputPassword),
|
||||
);
|
||||
const Mentions = defineAsyncComponent(
|
||||
() => import('ant-design-vue/es/mentions'),
|
||||
() => import('antdv-next/dist/mentions/index'),
|
||||
);
|
||||
const Radio = defineAsyncComponent(() => import('ant-design-vue/es/radio'));
|
||||
const Radio = defineAsyncComponent(() => import('antdv-next/dist/radio/index'));
|
||||
const RadioGroup = defineAsyncComponent(() =>
|
||||
import('ant-design-vue/es/radio').then((res) => res.RadioGroup),
|
||||
import('antdv-next/dist/radio/index').then((res) => res.RadioGroup),
|
||||
);
|
||||
const RangePicker = defineAsyncComponent(() =>
|
||||
import('ant-design-vue/es/date-picker').then((res) => res.RangePicker),
|
||||
import('antdv-next/dist/date-picker/index').then(
|
||||
(res) => res.DateRangePicker,
|
||||
),
|
||||
);
|
||||
const Rate = defineAsyncComponent(() => import('ant-design-vue/es/rate'));
|
||||
const Select = defineAsyncComponent(() => import('ant-design-vue/es/select'));
|
||||
const Space = defineAsyncComponent(() => import('ant-design-vue/es/space'));
|
||||
const Switch = defineAsyncComponent(() => import('ant-design-vue/es/switch'));
|
||||
const Textarea = defineAsyncComponent(() =>
|
||||
import('ant-design-vue/es/input').then((res) => res.Textarea),
|
||||
const Rate = defineAsyncComponent(() => import('antdv-next/dist/rate/index'));
|
||||
const Select = defineAsyncComponent(
|
||||
() => import('antdv-next/dist/select/index'),
|
||||
);
|
||||
const Space = defineAsyncComponent(() => import('antdv-next/dist/space/index'));
|
||||
const Switch = defineAsyncComponent(
|
||||
() => import('antdv-next/dist/switch/index'),
|
||||
);
|
||||
const Textarea = defineAsyncComponent(
|
||||
() => import('antdv-next/dist/input/TextArea'),
|
||||
);
|
||||
const TimePicker = defineAsyncComponent(
|
||||
() => import('ant-design-vue/es/time-picker'),
|
||||
() => import('antdv-next/dist/time-picker/index'),
|
||||
);
|
||||
const TreeSelect = defineAsyncComponent(
|
||||
() => import('ant-design-vue/es/tree-select'),
|
||||
() => import('antdv-next/dist/tree-select/index'),
|
||||
);
|
||||
const Cascader = defineAsyncComponent(
|
||||
() => import('ant-design-vue/es/cascader'),
|
||||
() => import('antdv-next/dist/cascader/index'),
|
||||
);
|
||||
const Upload = defineAsyncComponent(() => import('ant-design-vue/es/upload'));
|
||||
const Image = defineAsyncComponent(() => import('ant-design-vue/es/image'));
|
||||
const Upload = defineAsyncComponent(
|
||||
() => import('antdv-next/dist/upload/index'),
|
||||
);
|
||||
const Image = defineAsyncComponent(() => import('antdv-next/dist/image/index'));
|
||||
const PreviewGroup = defineAsyncComponent(() =>
|
||||
import('ant-design-vue/es/image').then((res) => res.ImagePreviewGroup),
|
||||
import('antdv-next/dist/image/index').then((res) => res.ImagePreviewGroup),
|
||||
);
|
||||
|
||||
const withDefaultPlaceholder = <T extends Component>(
|
||||
component: T,
|
||||
const withDefaultPlaceholder = (
|
||||
component: Component,
|
||||
type: 'input' | 'select',
|
||||
componentProps: Recordable<any> = {},
|
||||
) => {
|
||||
|
|
@ -242,7 +254,7 @@ function getBase64(file: File): Promise<string> {
|
|||
*/
|
||||
async function previewImage(
|
||||
file: UploadFile,
|
||||
visible: Ref<boolean>,
|
||||
open: Ref<boolean>,
|
||||
fileList: Ref<UploadProps['fileList']>,
|
||||
) {
|
||||
// 非图片文件直接打开链接
|
||||
|
|
@ -250,6 +262,8 @@ async function previewImage(
|
|||
const url = file.url || file.preview;
|
||||
if (url) {
|
||||
window.open(url, '_blank');
|
||||
} else if (file.preview) {
|
||||
window.open(file.preview, '_blank');
|
||||
} else {
|
||||
message.error($t('ui.formRules.previewWarning'));
|
||||
}
|
||||
|
|
@ -285,10 +299,10 @@ async function previewImage(
|
|||
{
|
||||
class: 'hidden',
|
||||
preview: {
|
||||
visible: visible.value,
|
||||
open: open.value,
|
||||
current: currentIndex,
|
||||
onVisibleChange: (value: boolean) => {
|
||||
visible.value = value;
|
||||
onOpenChange: (value: boolean) => {
|
||||
open.value = value;
|
||||
if (!value) {
|
||||
setTimeout(() => {
|
||||
if (!isUnmounted && container) {
|
||||
|
|
@ -330,7 +344,7 @@ function cropImage(file: File, aspectRatio: string | undefined) {
|
|||
const open = ref<boolean>(true);
|
||||
const cropperRef = ref<InstanceType<typeof VCropper> | null>(null);
|
||||
|
||||
const closeModal = () => {
|
||||
function closeModal() {
|
||||
open.value = false;
|
||||
setTimeout(() => {
|
||||
if (!isUnmounted && container) {
|
||||
|
|
@ -342,7 +356,7 @@ function cropImage(file: File, aspectRatio: string | undefined) {
|
|||
container.remove();
|
||||
}
|
||||
}, 300);
|
||||
};
|
||||
}
|
||||
|
||||
const CropperWrapper = {
|
||||
setup() {
|
||||
|
|
@ -372,7 +386,7 @@ function cropImage(file: File, aspectRatio: string | undefined) {
|
|||
closable: false,
|
||||
cancelText: $t('common.cancel'),
|
||||
okText: $t('ui.crop.confirm'),
|
||||
destroyOnClose: true,
|
||||
destroyOnHidden: true,
|
||||
onOk: async () => {
|
||||
const cropper = cropperRef.value;
|
||||
if (!cropper) {
|
||||
|
|
@ -416,7 +430,7 @@ function cropImage(file: File, aspectRatio: string | undefined) {
|
|||
/**
|
||||
* 带预览功能的上传组件
|
||||
*/
|
||||
const withPreviewUpload = () => {
|
||||
function withPreviewUpload() {
|
||||
return defineComponent({
|
||||
name: Upload.name,
|
||||
emits: ['update:modelValue'],
|
||||
|
|
@ -436,10 +450,10 @@ const withPreviewUpload = () => {
|
|||
() => attrs?.aspectRatio ?? attrs?.['aspect-ratio'],
|
||||
);
|
||||
|
||||
const handleBeforeUpload = async (
|
||||
async function handleBeforeUpload(
|
||||
file: UploadFile,
|
||||
originFileList: Array<File>,
|
||||
) => {
|
||||
) {
|
||||
// 文件大小限制
|
||||
if (maxSize.value && (file.size || 0) / 1024 / 1024 > maxSize.value) {
|
||||
message.error($t('ui.formRules.sizeLimit', [maxSize.value]));
|
||||
|
|
@ -463,9 +477,9 @@ const withPreviewUpload = () => {
|
|||
}
|
||||
|
||||
return attrs.beforeUpload?.(file) ?? true;
|
||||
};
|
||||
}
|
||||
|
||||
const handleChange = (event: UploadChangeParam) => {
|
||||
function handleChange(event: UploadChangeParam) {
|
||||
try {
|
||||
attrs.handleChange?.(event);
|
||||
attrs.onHandleChange?.(event);
|
||||
|
|
@ -479,19 +493,19 @@ const withPreviewUpload = () => {
|
|||
'update:modelValue',
|
||||
event.fileList?.length ? fileList.value : undefined,
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
const handlePreview = async (file: UploadFile) => {
|
||||
function handlePreview(file: UploadFile) {
|
||||
previewVisible.value = true;
|
||||
await previewImage(file, previewVisible, fileList);
|
||||
};
|
||||
return previewImage(file, previewVisible, fileList);
|
||||
}
|
||||
|
||||
const renderUploadButton = () => {
|
||||
function renderUploadButton() {
|
||||
if (attrs.disabled) return null;
|
||||
return isEmpty(slots)
|
||||
? createDefaultUploadSlots(listType, placeholder)
|
||||
: slots;
|
||||
};
|
||||
}
|
||||
|
||||
// 拖拽排序
|
||||
const draggable = computed(
|
||||
|
|
@ -600,7 +614,7 @@ const withPreviewUpload = () => {
|
|||
);
|
||||
},
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
// 这里需要自行根据业务组件库进行适配,需要用到的组件都需要在这里类型说明
|
||||
export type ComponentType =
|
||||
|
|
@ -681,13 +695,13 @@ async function initComponentAdapter() {
|
|||
fieldNames: { label: 'label', value: 'value', children: 'children' },
|
||||
loadingSlot: 'suffixIcon',
|
||||
modelPropName: 'value',
|
||||
visibleEvent: 'onVisibleChange',
|
||||
visibleEvent: 'onOpenChange',
|
||||
}),
|
||||
ApiSelect: withDefaultPlaceholder(ApiComponent, 'select', {
|
||||
component: Select,
|
||||
loadingSlot: 'suffixIcon',
|
||||
modelPropName: 'value',
|
||||
visibleEvent: 'onVisibleChange',
|
||||
visibleEvent: 'onOpenChange',
|
||||
}),
|
||||
ApiTreeSelect: withDefaultPlaceholder(ApiComponent, 'select', {
|
||||
component: TreeSelect,
|
||||
|
|
@ -695,7 +709,7 @@ async function initComponentAdapter() {
|
|||
loadingSlot: 'suffixIcon',
|
||||
modelPropName: 'value',
|
||||
optionsPropName: 'treeData',
|
||||
visibleEvent: 'onVisibleChange',
|
||||
visibleEvent: 'onOpenChange',
|
||||
}),
|
||||
AutoComplete,
|
||||
Cascader,
|
||||
|
|
@ -713,7 +727,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'),
|
||||
// 自定义主要按钮
|
||||
|
|
@ -764,7 +780,7 @@ async function initComponentAdapter() {
|
|||
copyPreferencesSuccess: (title, content) => {
|
||||
notification.success({
|
||||
description: content,
|
||||
message: title,
|
||||
title,
|
||||
placement: 'bottomRight',
|
||||
});
|
||||
},
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import {
|
|||
import { get, isFunction, isString } from '@vben/utils';
|
||||
|
||||
import { objectOmit } from '@vueuse/core';
|
||||
import { Button, Image, Popconfirm, Switch, Tag } from 'ant-design-vue';
|
||||
import { Button, Image, Popconfirm, Switch, Tag } from 'antdv-next';
|
||||
|
||||
import { $t } from '#/locales';
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import {
|
|||
import { useAccessStore } from '@vben/stores';
|
||||
import { cloneDeep } from '@vben/utils';
|
||||
|
||||
import { message } from 'ant-design-vue';
|
||||
import { message } from 'antdv-next';
|
||||
import JSONBigInt from 'json-bigint';
|
||||
|
||||
import { useAuthStore } from '#/store';
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
export * from './dept';
|
||||
export * from './menu';
|
||||
export * from './role';
|
||||
export * from './user';
|
||||
|
|
|
|||
|
|
@ -0,0 +1,55 @@
|
|||
import type { Recordable } from '@vben/types';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace SystemUserApi {
|
||||
export interface SystemUser {
|
||||
[key: string]: any;
|
||||
id: string;
|
||||
name: string;
|
||||
permissions: string[];
|
||||
remark?: string;
|
||||
status: 0 | 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户列表数据
|
||||
*/
|
||||
async function getUserList(params: Recordable<any>) {
|
||||
return requestClient.get<Array<SystemUserApi.SystemUser>>(
|
||||
'/system/user/list',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建用户
|
||||
* @param data 用户数据
|
||||
*/
|
||||
async function createUser(data: Omit<SystemUserApi.SystemUser, 'id'>) {
|
||||
return requestClient.post('/system/user', data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新用户
|
||||
*
|
||||
* @param id 用户 ID
|
||||
* @param data 用户数据
|
||||
*/
|
||||
async function updateUser(
|
||||
id: string,
|
||||
data: Omit<SystemUserApi.SystemUser, 'id'>,
|
||||
) {
|
||||
return requestClient.put(`/system/user/${id}`, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除用户
|
||||
* @param id 用户 ID
|
||||
*/
|
||||
async function deleteUser(id: string) {
|
||||
return requestClient.delete(`/system/user/${id}`);
|
||||
}
|
||||
|
||||
export { createUser, deleteUser, getUserList, updateUser };
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
<script lang="ts" setup>
|
||||
import { computed } from 'vue';
|
||||
import { computed, watch } from 'vue';
|
||||
|
||||
import { useAntdDesignTokens } from '@vben/hooks';
|
||||
import { preferences, usePreferences } from '@vben/preferences';
|
||||
|
||||
import { App, ConfigProvider, theme } from 'ant-design-vue';
|
||||
import { App, ConfigProvider, theme } from 'antdv-next';
|
||||
|
||||
import { antdLocale } from '#/locales';
|
||||
|
||||
|
|
@ -28,6 +28,14 @@ const tokenTheme = computed(() => {
|
|||
token: tokens,
|
||||
};
|
||||
});
|
||||
|
||||
watch(
|
||||
tokenTheme,
|
||||
(themeConfig) => {
|
||||
ConfigProvider.config({ theme: themeConfig });
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import { providePluginsOptions } from '@vben/plugins';
|
|||
import { preferences } from '@vben/preferences';
|
||||
import { initStores } from '@vben/stores';
|
||||
import '@vben/styles';
|
||||
import '@vben/styles/antd';
|
||||
import '@vben/styles/antdv-next';
|
||||
|
||||
import { useTitle } from '@vueuse/core';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type { Locale } from 'ant-design-vue/es/locale';
|
||||
import type { Locale } from 'antdv-next/dist/locale/index';
|
||||
|
||||
import type { App } from 'vue';
|
||||
|
||||
|
|
@ -13,8 +13,8 @@ import {
|
|||
} from '@vben/locales';
|
||||
import { preferences } from '@vben/preferences';
|
||||
|
||||
import antdEnLocale from 'ant-design-vue/es/locale/en_US';
|
||||
import antdDefaultLocale from 'ant-design-vue/es/locale/zh_CN';
|
||||
import antdEnLocale from 'antdv-next/dist/locale/en_US';
|
||||
import antdDefaultLocale from 'antdv-next/dist/locale/zh_CN';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
const antdLocale = ref<Locale>(antdDefaultLocale);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,18 @@
|
|||
{
|
||||
"title": "System Management",
|
||||
"user": {
|
||||
"title": "User Management",
|
||||
"list": "User List",
|
||||
"name": "User",
|
||||
"userName": "User Name",
|
||||
"id": "User ID",
|
||||
"dept": "Department",
|
||||
"status": "Status",
|
||||
"remark": "Remark",
|
||||
"createTime": "Creation Time",
|
||||
"operation": "Operation",
|
||||
"placeholder": "Search Department..."
|
||||
},
|
||||
"dept": {
|
||||
"name": "Department",
|
||||
"title": "Department Management",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,18 @@
|
|||
{
|
||||
"title": "系统管理",
|
||||
"user": {
|
||||
"title": "用户管理",
|
||||
"list": "用户列表",
|
||||
"name": "用户名",
|
||||
"userName": "用户名称",
|
||||
"id": "用户ID",
|
||||
"dept": "部门",
|
||||
"status": "状态",
|
||||
"remark": "备注",
|
||||
"createTime": "创建时间",
|
||||
"operation": "操作",
|
||||
"placeholder": "搜索部门..."
|
||||
},
|
||||
"dept": {
|
||||
"list": "部门列表",
|
||||
"createTime": "创建时间",
|
||||
|
|
|
|||
|
|
@ -29,4 +29,4 @@ async function initApplication() {
|
|||
unmountGlobalLoading();
|
||||
}
|
||||
|
||||
initApplication();
|
||||
void initApplication();
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import type {
|
|||
import { generateAccessible } from '@vben/access';
|
||||
import { preferences } from '@vben/preferences';
|
||||
|
||||
import { message } from 'ant-design-vue';
|
||||
import { message } from 'antdv-next';
|
||||
|
||||
import { getAllMenusApi } from '#/api';
|
||||
import { BasicLayout, IFrameView } from '#/layouts';
|
||||
|
|
|
|||
|
|
@ -12,6 +12,15 @@ const routes: RouteRecordRaw[] = [
|
|||
name: 'System',
|
||||
path: '/system',
|
||||
children: [
|
||||
{
|
||||
path: '/system/user',
|
||||
name: 'SystemUser',
|
||||
meta: {
|
||||
icon: 'mdi:user',
|
||||
title: $t('system.user.title'),
|
||||
},
|
||||
component: () => import('#/views/system/user/list.vue'),
|
||||
},
|
||||
{
|
||||
path: '/system/role',
|
||||
name: 'SystemRole',
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import { LOGIN_PATH } from '@vben/constants';
|
|||
import { preferences } from '@vben/preferences';
|
||||
import { resetAllStores, useAccessStore, useUserStore } from '@vben/stores';
|
||||
|
||||
import { notification } from 'ant-design-vue';
|
||||
import { notification } from 'antdv-next';
|
||||
import { defineStore } from 'pinia';
|
||||
|
||||
import { getAccessCodesApi, getUserInfoApi, loginApi, logoutApi } from '#/api';
|
||||
|
|
@ -65,7 +65,7 @@ export const useAuthStore = defineStore('auth', () => {
|
|||
notification.success({
|
||||
description: `${$t('authentication.loginSuccessDesc')}:${userInfo?.realName}`,
|
||||
duration: 3,
|
||||
message: $t('authentication.loginSuccess'),
|
||||
title: $t('authentication.loginSuccess'),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import { computed, ref, useTemplateRef } from 'vue';
|
|||
import { AuthenticationCodeLogin, z } from '@vben/common-ui';
|
||||
import { $t } from '@vben/locales';
|
||||
|
||||
import { message } from 'ant-design-vue';
|
||||
import { message } from 'antdv-next';
|
||||
|
||||
defineOptions({ name: 'CodeLogin' });
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { computed } from 'vue';
|
|||
|
||||
import { ProfilePasswordSetting, z } from '@vben/common-ui';
|
||||
|
||||
import { message } from 'ant-design-vue';
|
||||
import { message } from 'antdv-next';
|
||||
|
||||
const formSchema = computed((): VbenFormSchema[] => {
|
||||
return [
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import { AccessControl, useAccess } from '@vben/access';
|
|||
import { Page } from '@vben/common-ui';
|
||||
import { resetAllStores, useUserStore } from '@vben/stores';
|
||||
|
||||
import { Button, Card } from 'ant-design-vue';
|
||||
import { Button, Card } from 'antdv-next';
|
||||
|
||||
import { useAuthStore } from '#/store';
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import { useAccess } from '@vben/access';
|
|||
import { Page } from '@vben/common-ui';
|
||||
import { resetAllStores, useUserStore } from '@vben/stores';
|
||||
|
||||
import { Button, Card } from 'ant-design-vue';
|
||||
import { Button, Card } from 'antdv-next';
|
||||
|
||||
import { useAuthStore } from '#/store';
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import { useAccessStore } from '@vben/stores';
|
|||
|
||||
import { MenuBadge } from '@vben-core/menu-ui';
|
||||
|
||||
import { Button, Card, Radio, RadioGroup } from 'ant-design-vue';
|
||||
import { Button, Card, Radio, RadioGroup } from 'antdv-next';
|
||||
|
||||
import { useVbenForm } from '#/adapter/form';
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { useRouter } from 'vue-router';
|
|||
|
||||
import { Fallback } from '@vben/common-ui';
|
||||
|
||||
import { Button } from 'ant-design-vue';
|
||||
import { Button } from 'antdv-next';
|
||||
|
||||
const router = useRouter();
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { useRouter } from 'vue-router';
|
|||
|
||||
import { Fallback } from '@vben/common-ui';
|
||||
|
||||
import { Button } from 'ant-design-vue';
|
||||
import { Button } from 'antdv-next';
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { ref } from 'vue';
|
|||
import { Page } from '@vben/common-ui';
|
||||
|
||||
import { useClipboard } from '@vueuse/core';
|
||||
import { Button, Card, Input } from 'ant-design-vue';
|
||||
import { Button, Card, Input } from 'antdv-next';
|
||||
|
||||
const source = ref('Hello');
|
||||
const { copy, text } = useClipboard({ legacy: true, source });
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import {
|
|||
downloadFileFromUrl,
|
||||
} from '@vben/utils';
|
||||
|
||||
import { Button, Card } from 'ant-design-vue';
|
||||
import { Button, Card } from 'antdv-next';
|
||||
|
||||
import { downloadFile1, downloadFile2 } from '#/api/examples/download';
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { ref } from 'vue';
|
|||
import { Page } from '@vben/common-ui';
|
||||
|
||||
import { useFullscreen } from '@vueuse/core';
|
||||
import { Button, Card } from 'ant-design-vue';
|
||||
import { Button, Card } from 'antdv-next';
|
||||
|
||||
const domRef = ref<HTMLElement>();
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import {
|
|||
SvgWeChatIcon,
|
||||
} from '@vben/icons';
|
||||
|
||||
import { Card, Input } from 'ant-design-vue';
|
||||
import { Card, Input } from 'antdv-next';
|
||||
|
||||
const iconValue1 = ref('ant-design:trademark-outlined');
|
||||
const iconValue2 = ref('svg:avatar-1');
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { ref } from 'vue';
|
|||
|
||||
import { Page } from '@vben/common-ui';
|
||||
|
||||
import { Alert, Button, Card } from 'ant-design-vue';
|
||||
import { Alert, Button, Card } from 'antdv-next';
|
||||
|
||||
import { getBigIntData } from '#/api/examples/json-bigint';
|
||||
|
||||
|
|
@ -21,7 +21,7 @@ function fetchData() {
|
|||
>
|
||||
<Card>
|
||||
<Alert>
|
||||
<template #message>
|
||||
<template #title>
|
||||
有些后端接口返回的ID是长整数,但javascript原生的JSON解析是不支持超过2^53-1的长整数的。
|
||||
这种情况可以建议后端返回数据前将长整数转换为字符串类型。如果后端不接受我们的建议😡……
|
||||
<br />
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import type { LoginExpiredModeType } from '@vben/types';
|
|||
import { Page } from '@vben/common-ui';
|
||||
import { preferences, updatePreferences } from '@vben/preferences';
|
||||
|
||||
import { Button, Card } from 'ant-design-vue';
|
||||
import { Button, Card } from 'antdv-next';
|
||||
|
||||
import { getMockStatusApi } from '#/api';
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import {
|
|||
updateCustomPreferences,
|
||||
} from '@vben/preferences';
|
||||
|
||||
import { Alert, Button, Card, Space, Tag } from 'ant-design-vue';
|
||||
import { Alert, Button, Card, Space, Tag } from 'antdv-next';
|
||||
|
||||
import { $t } from '#/locales';
|
||||
|
||||
|
|
@ -105,7 +105,7 @@ function applyPreset(type: 'compact' | 'focus' | 'review') {
|
|||
},
|
||||
};
|
||||
|
||||
updateCustomPreferences<PlaygroundPreferencesExtension>(presetMap[type]);
|
||||
updateCustomPreferences(presetMap[type]);
|
||||
}
|
||||
|
||||
function getPriorityColor(priority: DemoTaskItem['priority']) {
|
||||
|
|
@ -136,7 +136,7 @@ function getPriorityColor(priority: DemoTaskItem['priority']) {
|
|||
:title="$t('demos.preferencesExtensionDemo.currentConfig')"
|
||||
>
|
||||
<Alert :type="toneConfig.alertType" show-icon>
|
||||
<template #message>
|
||||
<template #title>
|
||||
{{
|
||||
$t('demos.preferencesExtensionDemo.currentTitle', {
|
||||
title: playgroundPreferences.reportTitle,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { computed, ref, watchEffect } from 'vue';
|
|||
|
||||
import { Page } from '@vben/common-ui';
|
||||
|
||||
import { Card, Radio, RadioGroup } from 'ant-design-vue';
|
||||
import { Card, Radio, RadioGroup } from 'antdv-next';
|
||||
|
||||
import { getParamsData } from '#/api/examples/params';
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { useRouter } from 'vue-router';
|
|||
import { Page } from '@vben/common-ui';
|
||||
import { useTabs } from '@vben/hooks';
|
||||
|
||||
import { Button, Card, Input } from 'ant-design-vue';
|
||||
import { Button, Card, Input } from 'antdv-next';
|
||||
|
||||
const router = useRouter();
|
||||
const newTabTitle = ref('');
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
import { Page } from '@vben/common-ui';
|
||||
|
||||
import { refAutoReset } from '@vueuse/core';
|
||||
import { Button, Card, Empty } from 'ant-design-vue';
|
||||
import { Button, Card, Empty } from 'antdv-next';
|
||||
|
||||
import ConcurrencyCaching from './concurrency-caching.vue';
|
||||
import InfiniteQueries from './infinite-queries.vue';
|
||||
|
|
@ -27,7 +27,7 @@ const showCaching = refAutoReset(true, 1000);
|
|||
<Card
|
||||
title="并发和缓存"
|
||||
v-spinning="!showCaching"
|
||||
:body-style="{ minHeight: '330px' }"
|
||||
:styles="{ body: { minHeight: '330px' } }"
|
||||
>
|
||||
<template #extra>
|
||||
<Button @click="showCaching = false">重新加载</Button>
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue