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
|
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
|
// lint && format
|
||||||
"oxc.enable": true,
|
"oxc.enable": true,
|
||||||
"oxc.typeAware": true,
|
"oxc.typeAware": false,
|
||||||
"oxc.configPath": "oxlint.config.ts",
|
"oxc.configPath": "oxlint.config.ts",
|
||||||
"oxc.fmt.configPath": "oxfmt.config.ts",
|
"oxc.fmt.configPath": "oxfmt.config.ts",
|
||||||
"eslint.useFlatConfig": true,
|
"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),
|
import('ant-design-vue/es/image').then((res) => res.ImagePreviewGroup),
|
||||||
);
|
);
|
||||||
|
|
||||||
const withDefaultPlaceholder = <T extends Component>(
|
const withDefaultPlaceholder = (
|
||||||
component: T,
|
component: Component,
|
||||||
type: 'input' | 'select',
|
type: 'input' | 'select',
|
||||||
componentProps: Recordable<any> = {},
|
componentProps: Recordable<any> = {},
|
||||||
) => {
|
) => {
|
||||||
|
|
@ -702,7 +702,9 @@ async function initComponentAdapter() {
|
||||||
modelValueProp: 'value',
|
modelValueProp: 'value',
|
||||||
}),
|
}),
|
||||||
Input: withDefaultPlaceholder(Input, 'input'),
|
Input: withDefaultPlaceholder(Input, 'input'),
|
||||||
InputNumber: withDefaultPlaceholder(InputNumber, 'input'),
|
InputNumber: withDefaultPlaceholder(InputNumber, 'input', {
|
||||||
|
style: { width: '100%' },
|
||||||
|
}),
|
||||||
InputPassword: withDefaultPlaceholder(InputPassword, 'input'),
|
InputPassword: withDefaultPlaceholder(InputPassword, 'input'),
|
||||||
Mentions: withDefaultPlaceholder(Mentions, 'input'),
|
Mentions: withDefaultPlaceholder(Mentions, 'input'),
|
||||||
// 自定义主要按钮
|
// 自定义主要按钮
|
||||||
|
|
|
||||||
|
|
@ -136,8 +136,8 @@ const PreviewGroup = defineAsyncComponent(() =>
|
||||||
import('antdv-next/dist/image/index').then((res) => res.ImagePreviewGroup),
|
import('antdv-next/dist/image/index').then((res) => res.ImagePreviewGroup),
|
||||||
);
|
);
|
||||||
|
|
||||||
const withDefaultPlaceholder = <T extends Component>(
|
const withDefaultPlaceholder = (
|
||||||
component: T,
|
component: Component,
|
||||||
type: 'input' | 'select',
|
type: 'input' | 'select',
|
||||||
componentProps: Recordable<any> = {},
|
componentProps: Recordable<any> = {},
|
||||||
) => {
|
) => {
|
||||||
|
|
@ -633,7 +633,9 @@ async function initComponentAdapter() {
|
||||||
modelValueProp: 'value',
|
modelValueProp: 'value',
|
||||||
}),
|
}),
|
||||||
Input: withDefaultPlaceholder(Input, 'input'),
|
Input: withDefaultPlaceholder(Input, 'input'),
|
||||||
InputNumber: withDefaultPlaceholder(InputNumber, 'input'),
|
InputNumber: withDefaultPlaceholder(InputNumber, 'input', {
|
||||||
|
style: { width: '100%' },
|
||||||
|
}),
|
||||||
InputPassword: withDefaultPlaceholder(InputPassword, 'input'),
|
InputPassword: withDefaultPlaceholder(InputPassword, 'input'),
|
||||||
Mentions: withDefaultPlaceholder(Mentions, 'input'),
|
Mentions: withDefaultPlaceholder(Mentions, 'input'),
|
||||||
// 自定义主要按钮
|
// 自定义主要按钮
|
||||||
|
|
|
||||||
|
|
@ -141,8 +141,8 @@ const ElUpload = defineAsyncComponent(() =>
|
||||||
]).then(([res]) => res.ElUpload),
|
]).then(([res]) => res.ElUpload),
|
||||||
);
|
);
|
||||||
|
|
||||||
const withDefaultPlaceholder = <T extends Component>(
|
const withDefaultPlaceholder = (
|
||||||
component: T,
|
component: Component,
|
||||||
type: 'input' | 'select',
|
type: 'input' | 'select',
|
||||||
componentProps: Recordable<any> = {},
|
componentProps: Recordable<any> = {},
|
||||||
) => {
|
) => {
|
||||||
|
|
@ -284,7 +284,9 @@ async function initComponentAdapter() {
|
||||||
inputComponent: ElInput,
|
inputComponent: ElInput,
|
||||||
}),
|
}),
|
||||||
Input: withDefaultPlaceholder(ElInput, 'input'),
|
Input: withDefaultPlaceholder(ElInput, 'input'),
|
||||||
InputNumber: withDefaultPlaceholder(ElInputNumber, 'input'),
|
InputNumber: withDefaultPlaceholder(ElInputNumber, 'input', {
|
||||||
|
style: { width: '100%' },
|
||||||
|
}),
|
||||||
RadioGroup: (props, { attrs, slots }) => {
|
RadioGroup: (props, { attrs, slots }) => {
|
||||||
let defaultSlot;
|
let defaultSlot;
|
||||||
if (Reflect.has(slots, 'default')) {
|
if (Reflect.has(slots, 'default')) {
|
||||||
|
|
|
||||||
|
|
@ -84,8 +84,8 @@ const NUpload = defineAsyncComponent(() =>
|
||||||
import('naive-ui/es/upload').then((res) => res.NUpload),
|
import('naive-ui/es/upload').then((res) => res.NUpload),
|
||||||
);
|
);
|
||||||
|
|
||||||
const withDefaultPlaceholder = <T extends Component>(
|
const withDefaultPlaceholder = (
|
||||||
component: T,
|
component: Component,
|
||||||
type: 'input' | 'select',
|
type: 'input' | 'select',
|
||||||
componentProps: Recordable<any> = {},
|
componentProps: Recordable<any> = {},
|
||||||
) => {
|
) => {
|
||||||
|
|
@ -225,7 +225,9 @@ async function initComponentAdapter() {
|
||||||
inputComponent: NInput,
|
inputComponent: NInput,
|
||||||
}),
|
}),
|
||||||
Input: withDefaultPlaceholder(NInput, 'input'),
|
Input: withDefaultPlaceholder(NInput, 'input'),
|
||||||
InputNumber: withDefaultPlaceholder(NInputNumber, 'input'),
|
InputNumber: withDefaultPlaceholder(NInputNumber, 'input', {
|
||||||
|
style: { width: '100%' },
|
||||||
|
}),
|
||||||
RadioGroup: (props, { attrs, slots }) => {
|
RadioGroup: (props, { attrs, slots }) => {
|
||||||
let defaultSlot;
|
let defaultSlot;
|
||||||
if (Reflect.has(slots, 'default')) {
|
if (Reflect.has(slots, 'default')) {
|
||||||
|
|
|
||||||
|
|
@ -89,8 +89,8 @@ const TreeSelect = defineAsyncComponent(
|
||||||
);
|
);
|
||||||
const Upload = defineAsyncComponent(() => import('tdesign-vue-next/es/upload'));
|
const Upload = defineAsyncComponent(() => import('tdesign-vue-next/es/upload'));
|
||||||
|
|
||||||
const withDefaultPlaceholder = <T extends Component>(
|
const withDefaultPlaceholder = (
|
||||||
component: T,
|
component: Component,
|
||||||
type: 'input' | 'select',
|
type: 'input' | 'select',
|
||||||
componentProps: Recordable<any> = {},
|
componentProps: Recordable<any> = {},
|
||||||
) => {
|
) => {
|
||||||
|
|
@ -239,7 +239,9 @@ async function initComponentAdapter() {
|
||||||
modelValueProp: 'value',
|
modelValueProp: 'value',
|
||||||
}),
|
}),
|
||||||
Input: withDefaultPlaceholder(Input, 'input'),
|
Input: withDefaultPlaceholder(Input, 'input'),
|
||||||
InputNumber: withDefaultPlaceholder(InputNumber, 'input'),
|
InputNumber: withDefaultPlaceholder(InputNumber, 'input', {
|
||||||
|
style: { width: '100%' },
|
||||||
|
}),
|
||||||
// InputPassword: withDefaultPlaceholder(InputPassword, 'input'),
|
// InputPassword: withDefaultPlaceholder(InputPassword, 'input'),
|
||||||
// Mentions: withDefaultPlaceholder(Mentions, '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 { withPwa } from '@vite-pwa/vitepress';
|
||||||
import { defineConfigWithTheme } from 'vitepress';
|
import { defineConfig } from 'vitepress';
|
||||||
|
|
||||||
import { en } from './en.mts';
|
import { en } from './en.mts';
|
||||||
import { shared } from './shared.mts';
|
import { shared } from './shared.mts';
|
||||||
import { zh } from './zh.mts';
|
import { zh } from './zh.mts';
|
||||||
|
|
||||||
export default withPwa(
|
export default withPwa(
|
||||||
defineConfigWithTheme({
|
defineConfig({
|
||||||
...shared,
|
...shared,
|
||||||
locales: {
|
locales: {
|
||||||
en: {
|
en: {
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import { resolve } from 'node:path';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
viteArchiverPlugin,
|
viteArchiverPlugin,
|
||||||
|
viteDayjsPlugin,
|
||||||
viteVxeTableImportsPlugin,
|
viteVxeTableImportsPlugin,
|
||||||
} from '@vben/vite-config';
|
} from '@vben/vite-config';
|
||||||
|
|
||||||
|
|
@ -61,7 +62,7 @@ export const shared = defineConfig({
|
||||||
},
|
},
|
||||||
preprocessorOptions: {
|
preprocessorOptions: {
|
||||||
scss: {
|
scss: {
|
||||||
api: 'modern',
|
// api: 'modern',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -69,6 +70,7 @@ export const shared = defineConfig({
|
||||||
stringify: true,
|
stringify: true,
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
|
viteDayjsPlugin(),
|
||||||
tailwindcss(),
|
tailwindcss(),
|
||||||
GitChangelog({
|
GitChangelog({
|
||||||
mapAuthors: [
|
mapAuthors: [
|
||||||
|
|
@ -85,9 +87,23 @@ export const shared = defineConfig({
|
||||||
name: 'Li Kui',
|
name: 'Li Kui',
|
||||||
username: 'likui628',
|
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',
|
repoURL: () => 'https://github.com/vbenjs/vue-vben-admin',
|
||||||
}),
|
}) as any,
|
||||||
GitChangelogMarkdownSection(),
|
GitChangelogMarkdownSection(),
|
||||||
viteArchiverPlugin({ outputDir: '.vitepress' }),
|
viteArchiverPlugin({ outputDir: '.vitepress' }),
|
||||||
groupIconVitePlugin(),
|
groupIconVitePlugin(),
|
||||||
|
|
@ -103,6 +119,7 @@ export const shared = defineConfig({
|
||||||
|
|
||||||
ssr: {
|
ssr: {
|
||||||
external: ['@vue/repl'],
|
external: ['@vue/repl'],
|
||||||
|
noExternal: ['@v-c/picker'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
@ -113,7 +130,7 @@ function head(): HeadConfig[] {
|
||||||
[
|
[
|
||||||
'meta',
|
'meta',
|
||||||
{
|
{
|
||||||
content: 'vben, vitejs, vite, shacdn-ui, vue',
|
content: 'vben, vitejs, vite, shadcn-ui, vue',
|
||||||
name: 'keywords',
|
name: 'keywords',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -337,8 +337,8 @@ export const search: DefaultTheme.AlgoliaSearchOptions['locales'] = {
|
||||||
footer: {
|
footer: {
|
||||||
closeText: '关闭',
|
closeText: '关闭',
|
||||||
navigateText: '切换',
|
navigateText: '切换',
|
||||||
searchByText: '搜索提供者',
|
|
||||||
selectText: '选择',
|
selectText: '选择',
|
||||||
|
poweredByText: '搜索提供者',
|
||||||
},
|
},
|
||||||
noResultsScreen: {
|
noResultsScreen: {
|
||||||
noResultsText: '无法找到相关结果',
|
noResultsText: '无法找到相关结果',
|
||||||
|
|
@ -347,10 +347,10 @@ export const search: DefaultTheme.AlgoliaSearchOptions['locales'] = {
|
||||||
suggestedQueryText: '你可以尝试查询',
|
suggestedQueryText: '你可以尝试查询',
|
||||||
},
|
},
|
||||||
searchBox: {
|
searchBox: {
|
||||||
cancelButtonAriaLabel: '取消',
|
closeButtonAriaLabel: '取消',
|
||||||
cancelButtonText: '取消',
|
closeButtonText: '取消',
|
||||||
resetButtonAriaLabel: '清除查询条件',
|
clearButtonAriaLabel: '清除查询条件',
|
||||||
resetButtonTitle: '清除查询条件',
|
clearButtonTitle: '清除查询条件',
|
||||||
},
|
},
|
||||||
startScreen: {
|
startScreen: {
|
||||||
favoriteSearchesTitle: '收藏',
|
favoriteSearchesTitle: '收藏',
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import {
|
||||||
|
|
||||||
// import { useAntdDesignTokens } from '@vben/hooks';
|
// import { useAntdDesignTokens } from '@vben/hooks';
|
||||||
// import { initPreferences } from '@vben/preferences';
|
// import { initPreferences } from '@vben/preferences';
|
||||||
import { ConfigProvider, theme } from 'ant-design-vue';
|
import { ConfigProvider, theme } from 'antdv-next';
|
||||||
import mediumZoom from 'medium-zoom';
|
import mediumZoom from 'medium-zoom';
|
||||||
import { useRoute } from 'vitepress';
|
import { useRoute } from 'vitepress';
|
||||||
import DefaultTheme from 'vitepress/theme';
|
import DefaultTheme from 'vitepress/theme';
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,9 @@
|
||||||
"name": "@vben/docs",
|
"name": "@vben/docs",
|
||||||
"version": "5.7.0",
|
"version": "5.7.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "vitepress build",
|
"build": "cross-env NODE_OPTIONS=\"--import ./.vitepress/build/dayjs-loader.mjs\" vitepress build",
|
||||||
"dev": "vitepress dev",
|
"dev": "vitepress dev",
|
||||||
"docs:preview": "vitepress preview"
|
"docs:preview": "vitepress preview"
|
||||||
},
|
},
|
||||||
|
|
@ -19,7 +20,7 @@
|
||||||
"@vben/locales": "workspace:*",
|
"@vben/locales": "workspace:*",
|
||||||
"@vben/plugins": "workspace:*",
|
"@vben/plugins": "workspace:*",
|
||||||
"@vben/styles": "workspace:*",
|
"@vben/styles": "workspace:*",
|
||||||
"ant-design-vue": "catalog:",
|
"antdv-next": "catalog:",
|
||||||
"lucide-vue-next": "catalog:",
|
"lucide-vue-next": "catalog:",
|
||||||
"medium-zoom": "catalog:",
|
"medium-zoom": "catalog:",
|
||||||
"reka-ui": "catalog:",
|
"reka-ui": "catalog:",
|
||||||
|
|
|
||||||
|
|
@ -26,16 +26,15 @@ import {
|
||||||
notification,
|
notification,
|
||||||
Radio,
|
Radio,
|
||||||
RadioGroup,
|
RadioGroup,
|
||||||
RangePicker,
|
|
||||||
Rate,
|
Rate,
|
||||||
Select,
|
Select,
|
||||||
Space,
|
Space,
|
||||||
Switch,
|
Switch,
|
||||||
Textarea,
|
TextArea,
|
||||||
TimePicker,
|
TimePicker,
|
||||||
TreeSelect,
|
TreeSelect,
|
||||||
Upload,
|
Upload,
|
||||||
} from 'ant-design-vue';
|
} from 'antdv-next';
|
||||||
|
|
||||||
const withDefaultPlaceholder = <T extends Component>(
|
const withDefaultPlaceholder = <T extends Component>(
|
||||||
component: T,
|
component: T,
|
||||||
|
|
@ -98,12 +97,12 @@ async function initComponentAdapter() {
|
||||||
},
|
},
|
||||||
Radio,
|
Radio,
|
||||||
RadioGroup,
|
RadioGroup,
|
||||||
RangePicker,
|
RangePicker: withDefaultPlaceholder(DatePicker.RangePicker, 'select'),
|
||||||
Rate,
|
Rate,
|
||||||
Select: withDefaultPlaceholder(Select, 'select'),
|
Select: withDefaultPlaceholder(Select, 'select'),
|
||||||
Space,
|
Space,
|
||||||
Switch,
|
Switch,
|
||||||
Textarea: withDefaultPlaceholder(Textarea, 'input'),
|
Textarea: withDefaultPlaceholder(TextArea, 'input'),
|
||||||
TimePicker,
|
TimePicker,
|
||||||
TreeSelect: withDefaultPlaceholder(TreeSelect, 'select'),
|
TreeSelect: withDefaultPlaceholder(TreeSelect, 'select'),
|
||||||
Upload,
|
Upload,
|
||||||
|
|
@ -118,7 +117,7 @@ async function initComponentAdapter() {
|
||||||
copyPreferencesSuccess: (title, content) => {
|
copyPreferencesSuccess: (title, content) => {
|
||||||
notification.success({
|
notification.success({
|
||||||
description: content,
|
description: content,
|
||||||
message: title,
|
title,
|
||||||
placement: 'bottomRight',
|
placement: 'bottomRight',
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { h } from 'vue';
|
||||||
|
|
||||||
import { setupVbenVxeTable, useVbenVxeGrid } from '@vben/plugins/vxe-table';
|
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';
|
import { useVbenForm } from './form';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ outline: deep
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ApiComponent } from '@vben/common-ui';
|
import { ApiComponent } from '@vben/common-ui';
|
||||||
|
|
||||||
import { Cascader } from 'ant-design-vue';
|
import { Cascader } from 'antdv-next';
|
||||||
|
|
||||||
const treeData: Record<string, any> = [
|
const treeData: Record<string, any> = [
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,7 @@ import {
|
||||||
TimePicker,
|
TimePicker,
|
||||||
TreeSelect,
|
TreeSelect,
|
||||||
Upload,
|
Upload,
|
||||||
} from 'ant-design-vue';
|
} from 'antdv-next';
|
||||||
|
|
||||||
const withDefaultPlaceholder = <T extends Component>(
|
const withDefaultPlaceholder = <T extends Component>(
|
||||||
component: T,
|
component: T,
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ import { h } from 'vue';
|
||||||
|
|
||||||
import { setupVbenVxeTable, useVbenVxeGrid } from '@vben/plugins/vxe-table';
|
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';
|
import { useVbenForm } from './form';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { h } from 'vue';
|
||||||
|
|
||||||
import { alert, VbenButton } from '@vben/common-ui';
|
import { alert, VbenButton } from '@vben/common-ui';
|
||||||
|
|
||||||
import { Result } from 'ant-design-vue';
|
import { Result } from 'antdv-next';
|
||||||
|
|
||||||
function showAlert() {
|
function showAlert() {
|
||||||
alert('This is an alert message');
|
alert('This is an alert message');
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { h, ref } from 'vue';
|
||||||
|
|
||||||
import { alert, confirm, VbenButton } from '@vben/common-ui';
|
import { alert, confirm, VbenButton } from '@vben/common-ui';
|
||||||
|
|
||||||
import { Checkbox, message } from 'ant-design-vue';
|
import { Checkbox, message } from 'antdv-next';
|
||||||
|
|
||||||
function showConfirm() {
|
function showConfirm() {
|
||||||
confirm('This is an alert message')
|
confirm('This is an alert message')
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { h } from 'vue';
|
||||||
|
|
||||||
import { alert, prompt, useAlertContext, VbenButton } from '@vben/common-ui';
|
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';
|
import { BadgeJapaneseYen } from 'lucide-vue-next';
|
||||||
|
|
||||||
function showPrompt() {
|
function showPrompt() {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ApiComponent } from '@vben/common-ui';
|
import { ApiComponent } from '@vben/common-ui';
|
||||||
|
|
||||||
import { Cascader } from 'ant-design-vue';
|
import { Cascader } from 'antdv-next';
|
||||||
|
|
||||||
const treeData: Record<string, any> = [
|
const treeData: Record<string, any> = [
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { Button, message, Space } from 'ant-design-vue';
|
import { Button, message, Space } from 'antdv-next';
|
||||||
|
|
||||||
import { useVbenForm } from '#/adapter/form';
|
import { useVbenForm } from '#/adapter/form';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { message } from 'ant-design-vue';
|
import { message } from 'antdv-next';
|
||||||
|
|
||||||
import { useVbenForm } from '#/adapter/form';
|
import { useVbenForm } from '#/adapter/form';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { h } from 'vue';
|
import { h } from 'vue';
|
||||||
|
|
||||||
import { Input, message } from 'ant-design-vue';
|
import { Input, message } from 'antdv-next';
|
||||||
|
|
||||||
import { useVbenForm } from '#/adapter/form';
|
import { useVbenForm } from '#/adapter/form';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { message } from 'ant-design-vue';
|
import { message } from 'antdv-next';
|
||||||
|
|
||||||
import { useVbenForm } from '#/adapter/form';
|
import { useVbenForm } from '#/adapter/form';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { message } from 'ant-design-vue';
|
import { message } from 'antdv-next';
|
||||||
|
|
||||||
import { useVbenForm } from '#/adapter/form';
|
import { useVbenForm } from '#/adapter/form';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { message } from 'ant-design-vue';
|
import { message } from 'antdv-next';
|
||||||
|
|
||||||
import { useVbenForm, z } from '#/adapter/form';
|
import { useVbenForm, z } from '#/adapter/form';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, nextTick, onMounted, ref, watch } from 'vue';
|
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';
|
import { useVbenForm } from '#/adapter/form';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { VxeGridListeners, VxeGridProps } from '#/adapter/vxe-table';
|
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';
|
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { VxeGridProps } from '#/adapter/vxe-table';
|
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';
|
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { VxeGridProps } from '#/adapter/vxe-table';
|
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';
|
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { VxeGridProps } from '#/adapter/vxe-table';
|
import type { VxeGridProps } from '#/adapter/vxe-table';
|
||||||
|
|
||||||
import { Button } from 'ant-design-vue';
|
import { Button } from 'antdv-next';
|
||||||
|
|
||||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
import type { VbenFormProps } from '#/adapter/form';
|
import type { VbenFormProps } from '#/adapter/form';
|
||||||
import type { VxeGridProps } from '#/adapter/vxe-table';
|
import type { VxeGridProps } from '#/adapter/vxe-table';
|
||||||
|
|
||||||
import { message } from 'ant-design-vue';
|
import { message } from 'antdv-next';
|
||||||
|
|
||||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import type { DemoTableApi } from '../mock-api';
|
||||||
|
|
||||||
import type { VxeGridProps } from '#/adapter/vxe-table';
|
import type { VxeGridProps } from '#/adapter/vxe-table';
|
||||||
|
|
||||||
import { Button } from 'ant-design-vue';
|
import { Button } from 'antdv-next';
|
||||||
|
|
||||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { VxeGridProps } from '#/adapter/vxe-table';
|
import type { VxeGridProps } from '#/adapter/vxe-table';
|
||||||
|
|
||||||
import { Button } from 'ant-design-vue';
|
import { Button } from 'antdv-next';
|
||||||
|
|
||||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ The current wrapper flow is:
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ApiComponent } from '@vben/common-ui';
|
import { ApiComponent } from '@vben/common-ui';
|
||||||
|
|
||||||
import { Cascader } from 'ant-design-vue';
|
import { Cascader } from 'antdv-next';
|
||||||
|
|
||||||
function fetchApi() {
|
function fetchApi() {
|
||||||
return Promise.resolve([
|
return Promise.resolve([
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,7 @@ import {
|
||||||
TimePicker,
|
TimePicker,
|
||||||
TreeSelect,
|
TreeSelect,
|
||||||
Upload,
|
Upload,
|
||||||
} from 'ant-design-vue';
|
} from 'antdv-next';
|
||||||
|
|
||||||
const withDefaultPlaceholder = <T extends Component>(
|
const withDefaultPlaceholder = <T extends Component>(
|
||||||
component: T,
|
component: T,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# External Modules
|
# 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
|
## Installing Dependencies
|
||||||
|
|
||||||
|
|
@ -13,7 +13,7 @@ In addition to the external modules that are included by default in the project,
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# cd /path/to/your/package
|
# cd /path/to/your/package
|
||||||
pnpm add ant-design-vue
|
pnpm add antdv-next
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
@ -22,9 +22,9 @@ pnpm add ant-design-vue
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { createApp } from 'vue';
|
import { createApp } from 'vue';
|
||||||
import Antd from 'ant-design-vue';
|
import Antd from 'antdv-next';
|
||||||
import App from './App';
|
import App from './App';
|
||||||
import 'ant-design-vue/dist/reset.css';
|
import 'antdv-next/dist/reset.css';
|
||||||
|
|
||||||
const app = createApp(App);
|
const app = createApp(App);
|
||||||
|
|
||||||
|
|
@ -43,7 +43,7 @@ app.use(Antd).mount('#app');
|
||||||
|
|
||||||
```vue
|
```vue
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Button } from 'ant-design-vue';
|
import { Button } from 'antdv-next';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
||||||
|
|
@ -174,7 +174,7 @@ import {
|
||||||
} from '@vben/request';
|
} from '@vben/request';
|
||||||
import { useAccessStore } from '@vben/stores';
|
import { useAccessStore } from '@vben/stores';
|
||||||
|
|
||||||
import { message } from 'ant-design-vue';
|
import { message } from 'antdv-next';
|
||||||
|
|
||||||
import { useAuthStore } from '#/store';
|
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:
|
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
|
```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
|
## 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
|
```bash
|
||||||
# cd /path/to/your/package
|
# cd /path/to/your/package
|
||||||
pnpm add ant-design-vue
|
pnpm add antdv-next
|
||||||
```
|
```
|
||||||
|
|
||||||
## 使用
|
## 使用
|
||||||
|
|
@ -22,9 +22,9 @@ pnpm add ant-design-vue
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { createApp } from 'vue';
|
import { createApp } from 'vue';
|
||||||
import Antd from 'ant-design-vue';
|
import Antd from 'antdv-next';
|
||||||
import App from './App';
|
import App from './App';
|
||||||
import 'ant-design-vue/dist/reset.css';
|
import 'antdv-next/dist/reset.css';
|
||||||
|
|
||||||
const app = createApp(App);
|
const app = createApp(App);
|
||||||
|
|
||||||
|
|
@ -43,7 +43,7 @@ app.use(Antd).mount('#app');
|
||||||
|
|
||||||
```vue
|
```vue
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Button } from 'ant-design-vue';
|
import { Button } from 'antdv-next';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
||||||
|
|
@ -204,7 +204,7 @@ import {
|
||||||
} from '@vben/request';
|
} from '@vben/request';
|
||||||
import { useAccessStore } from '@vben/stores';
|
import { useAccessStore } from '@vben/stores';
|
||||||
|
|
||||||
import { message } from 'ant-design-vue';
|
import { message } from 'antdv-next';
|
||||||
|
|
||||||
import { useAuthStore } from '#/store';
|
import { useAuthStore } from '#/store';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ pnpm add version-polling
|
||||||
```ts
|
```ts
|
||||||
import { h } from 'vue';
|
import { h } from 'vue';
|
||||||
|
|
||||||
import { Button, notification } from 'ant-design-vue';
|
import { Button, notification } from 'antdv-next';
|
||||||
import { createVersionPolling } from 'version-polling';
|
import { createVersionPolling } from 'version-polling';
|
||||||
|
|
||||||
createVersionPolling({
|
createVersionPolling({
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,7 @@ registry = https://registry.npmmirror.com/
|
||||||
如果出现类似以下错误,请检查项目全路径(包含所有父级路径)不能出现中文、日文、韩文。否则将会出现路径访问 404 导致以下问题
|
如果出现类似以下错误,请检查项目全路径(包含所有父级路径)不能出现中文、日文、韩文。否则将会出现路径访问 404 导致以下问题
|
||||||
|
|
||||||
```ts
|
```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: {
|
rules: {
|
||||||
|
'eslint/no-underscore-dangle': 'off',
|
||||||
'eslint-comments/no-aggregating-enable': 'error',
|
'eslint-comments/no-aggregating-enable': 'error',
|
||||||
'eslint-comments/no-duplicate-disable': 'error',
|
'eslint-comments/no-duplicate-disable': 'error',
|
||||||
'eslint-comments/no-unlimited-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 viteVueDevTools from 'vite-plugin-vue-devtools';
|
||||||
|
|
||||||
import { viteArchiverPlugin } from './archiver';
|
import { viteArchiverPlugin } from './archiver';
|
||||||
|
import { viteDayjsPlugin } from './dayjs';
|
||||||
import { viteExtraAppConfigPlugin } from './extra-app-config';
|
import { viteExtraAppConfigPlugin } from './extra-app-config';
|
||||||
import { viteHtmlPlugin } from './html';
|
import { viteHtmlPlugin } from './html';
|
||||||
import { viteImportMapPlugin } from './importmap';
|
import { viteImportMapPlugin } from './importmap';
|
||||||
|
|
@ -105,6 +106,7 @@ async function loadApplicationPlugins(
|
||||||
compressTypes,
|
compressTypes,
|
||||||
extraAppConfig,
|
extraAppConfig,
|
||||||
html,
|
html,
|
||||||
|
dayjs,
|
||||||
i18n,
|
i18n,
|
||||||
importmap,
|
importmap,
|
||||||
importmapOptions,
|
importmapOptions,
|
||||||
|
|
@ -219,6 +221,10 @@ async function loadApplicationPlugins(
|
||||||
return [await viteArchiverPlugin(archiverPluginOptions)];
|
return [await viteArchiverPlugin(archiverPluginOptions)];
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
condition: dayjs,
|
||||||
|
plugins: () => [viteDayjsPlugin()],
|
||||||
|
},
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -247,6 +253,7 @@ export {
|
||||||
loadLibraryPlugins,
|
loadLibraryPlugins,
|
||||||
viteArchiverPlugin,
|
viteArchiverPlugin,
|
||||||
viteCompressPlugin,
|
viteCompressPlugin,
|
||||||
|
viteDayjsPlugin,
|
||||||
viteDtsPlugin,
|
viteDtsPlugin,
|
||||||
viteHtmlPlugin,
|
viteHtmlPlugin,
|
||||||
viteVisualizerPlugin,
|
viteVisualizerPlugin,
|
||||||
|
|
|
||||||
|
|
@ -214,6 +214,11 @@ interface ApplicationPluginOptions extends CommonPluginOptions {
|
||||||
* @description 可选的压缩类型
|
* @description 可选的压缩类型
|
||||||
*/
|
*/
|
||||||
compressTypes?: ('brotli' | 'gzip')[];
|
compressTypes?: ('brotli' | 'gzip')[];
|
||||||
|
/**
|
||||||
|
* 是否开启 dayjs 插件
|
||||||
|
* @default true
|
||||||
|
*/
|
||||||
|
dayjs?: boolean;
|
||||||
/**
|
/**
|
||||||
* 是否抽离配置文件
|
* 是否抽离配置文件
|
||||||
* @default false
|
* @default false
|
||||||
|
|
|
||||||
|
|
@ -102,8 +102,8 @@
|
||||||
"vue-tsc": "catalog:"
|
"vue-tsc": "catalog:"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^20.19.0 || ^22.18.0 || ^24.0.0",
|
"node": "^22.18.0 || ^24.0.0",
|
||||||
"pnpm": ">=10.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();
|
const db = await this.getDB();
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const tx = db.transaction(this.storeName, 'readwrite');
|
const tx = db.transaction(this.storeName, 'readwrite');
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ class LocalStorageDriver implements IStorageDriver {
|
||||||
this.storage.removeItem(key);
|
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));
|
this.storage.setItem(key, JSON.stringify(value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ class MemoryStorageDriver implements IStorageDriver {
|
||||||
this.store.delete(key);
|
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);
|
this.store.set(key, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -106,10 +106,10 @@ class StorageManager {
|
||||||
* @param value 值
|
* @param value 值
|
||||||
* @param ttl 存活时间(毫秒)
|
* @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 fullKey = this.getFullKey(key);
|
||||||
const expiry = ttl ? Date.now() + ttl : undefined;
|
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);
|
await this.driver.setItem(fullKey, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ interface IStorageDriver {
|
||||||
removeItem(key: string): Promise<void>;
|
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);
|
}, 10);
|
||||||
|
|
||||||
// 等待过程中,期望 Promise 被 reject
|
// 等待过程中,期望 Promise 被 reject
|
||||||
await expect(handler.waitForCondition()).rejects.toThrow();
|
await expect(handler.waitForCondition()).rejects.toThrow(
|
||||||
|
'Condition was set to false',
|
||||||
|
);
|
||||||
expect(handler.isConditionTrue()).toBe(false);
|
expect(handler.isConditionTrue()).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -138,8 +138,10 @@ describe('getNestedValue', () => {
|
||||||
expect(result).toBe(2);
|
expect(result).toBe(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return the entire object if path is empty', () => {
|
it('should throw if path is empty', () => {
|
||||||
expect(() => getNestedValue(data, '')()).toThrow();
|
expect(() => getNestedValue(data, '')).toThrow(
|
||||||
|
'Path must be a non-empty string',
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle paths with array indexes', () => {
|
it('should handle paths with array indexes', () => {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
export class StateHandler {
|
export class StateHandler {
|
||||||
private condition: boolean = false;
|
private condition: boolean = false;
|
||||||
private rejectCondition: (() => void) | null = null;
|
private rejectCondition: ((reason?: Error) => void) | null = null;
|
||||||
private resolveCondition: (() => void) | null = null;
|
private resolveCondition: (() => void) | null = null;
|
||||||
|
|
||||||
isConditionTrue(): boolean {
|
isConditionTrue(): boolean {
|
||||||
|
|
@ -16,7 +16,7 @@ export class StateHandler {
|
||||||
setConditionFalse() {
|
setConditionFalse() {
|
||||||
this.condition = false;
|
this.condition = false;
|
||||||
if (this.rejectCondition) {
|
if (this.rejectCondition) {
|
||||||
this.rejectCondition();
|
this.rejectCondition(new Error('Condition was set to false'));
|
||||||
this.clearPromises();
|
this.clearPromises();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -180,11 +180,7 @@ class PreferenceManager {
|
||||||
* 更新扩展偏好设置
|
* 更新扩展偏好设置
|
||||||
* @param updates - 要更新的扩展偏好设置
|
* @param updates - 要更新的扩展偏好设置
|
||||||
*/
|
*/
|
||||||
updateCustomPreferences = <
|
updateCustomPreferences = (updates: DeepPartial<object>) => {
|
||||||
TCustomPreferences extends object = CustomPreferencesRecord,
|
|
||||||
>(
|
|
||||||
updates: DeepPartial<TCustomPreferences>,
|
|
||||||
) => {
|
|
||||||
if (!this.customPreferencesExtension) {
|
if (!this.customPreferencesExtension) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,7 @@ function findPlaceholderPos(doc: ProseMirrorNode, blobUrl: string): number {
|
||||||
found = offset;
|
found = offset;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* eslint-disable unicorn/no-nested-ternary */
|
||||||
import type { VxeGridProps as VxeTableGridProps } from 'vxe-table';
|
import type { VxeGridProps as VxeTableGridProps } from 'vxe-table';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
|
|
@ -182,13 +183,11 @@ export function useViewedRow<T = any>(
|
||||||
options: ViewedRowOptions<T> & { keyField: string },
|
options: ViewedRowOptions<T> & { keyField: string },
|
||||||
) {
|
) {
|
||||||
// ========== 解析持久化配置 ==========
|
// ========== 解析持久化配置 ==========
|
||||||
let persistOpts: null | ViewedRowPersistOptions = null;
|
const persistOpts: null | ViewedRowPersistOptions = options.persist
|
||||||
if (options.persist) {
|
? typeof options.persist === 'string'
|
||||||
persistOpts =
|
|
||||||
typeof options.persist === 'string'
|
|
||||||
? { key: options.persist, type: 'localStorage' }
|
? { key: options.persist, type: 'localStorage' }
|
||||||
: options.persist;
|
: options.persist
|
||||||
}
|
: null;
|
||||||
|
|
||||||
const adapter = createStorageAdapter(options.persist);
|
const adapter = createStorageAdapter(options.persist);
|
||||||
const maxSize = persistOpts?.maxSize ?? 100;
|
const maxSize = persistOpts?.maxSize ?? 100;
|
||||||
|
|
@ -521,12 +520,12 @@ export function applyViewedRowOptions(
|
||||||
};
|
};
|
||||||
|
|
||||||
// 拦截 CellOperation columns
|
// 拦截 CellOperation columns
|
||||||
let actionCodes: string[] = [];
|
const actionCodes =
|
||||||
if (!isBoolean(viewedRowConfig) && viewedRowConfig.actionCodes) {
|
!isBoolean(viewedRowConfig) && viewedRowConfig.actionCodes
|
||||||
actionCodes = Array.isArray(viewedRowConfig.actionCodes)
|
? Array.isArray(viewedRowConfig.actionCodes)
|
||||||
? viewedRowConfig.actionCodes
|
? viewedRowConfig.actionCodes
|
||||||
: [viewedRowConfig.actionCodes];
|
: [viewedRowConfig.actionCodes]
|
||||||
}
|
: [];
|
||||||
|
|
||||||
if (actionCodes.length > 0 && Array.isArray(mergedOptions.columns)) {
|
if (actionCodes.length > 0 && Array.isArray(mergedOptions.columns)) {
|
||||||
mergedOptions.columns = wrapColumnsForViewedRow(
|
mergedOptions.columns = wrapColumnsForViewedRow(
|
||||||
|
|
|
||||||
|
|
@ -50,24 +50,18 @@ describe('requestClient', () => {
|
||||||
|
|
||||||
it('should handle network errors', async () => {
|
it('should handle network errors', async () => {
|
||||||
mock.onGet('/test/error').networkError();
|
mock.onGet('/test/error').networkError();
|
||||||
try {
|
await expect(requestClient.get('/test/error')).rejects.toMatchObject({
|
||||||
await requestClient.get('/test/error');
|
isAxiosError: true,
|
||||||
expect(true).toBe(false);
|
message: 'Network Error',
|
||||||
} catch (error: any) {
|
});
|
||||||
expect(error.isAxiosError).toBe(true);
|
|
||||||
expect(error.message).toBe('Network Error');
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle timeout', async () => {
|
it('should handle timeout', async () => {
|
||||||
mock.onGet('/test/timeout').timeout();
|
mock.onGet('/test/timeout').timeout();
|
||||||
try {
|
await expect(requestClient.get('/test/timeout')).rejects.toMatchObject({
|
||||||
await requestClient.get('/test/timeout');
|
isAxiosError: true,
|
||||||
expect(true).toBe(false);
|
code: 'ECONNABORTED',
|
||||||
} catch (error: any) {
|
});
|
||||||
expect(error.isAxiosError).toBe(true);
|
|
||||||
expect(error.code).toBe('ECONNABORTED');
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should successfully upload a file', async () => {
|
it('should successfully upload a file', async () => {
|
||||||
|
|
@ -92,7 +86,7 @@ describe('requestClient', () => {
|
||||||
|
|
||||||
mock.onGet('/test/download').reply(200, mockFileContent);
|
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);
|
expect(res.data).toBeInstanceOf(Blob);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@
|
||||||
"@vben/types": "workspace:*",
|
"@vben/types": "workspace:*",
|
||||||
"@vben/utils": "workspace:*",
|
"@vben/utils": "workspace:*",
|
||||||
"@vueuse/core": "catalog:",
|
"@vueuse/core": "catalog:",
|
||||||
"ant-design-vue": "catalog:",
|
"antdv-next": "catalog:",
|
||||||
"dayjs": "catalog:",
|
"dayjs": "catalog:",
|
||||||
"json-bigint": "catalog:",
|
"json-bigint": "catalog:",
|
||||||
"pinia": "catalog:",
|
"pinia": "catalog:",
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ import type {
|
||||||
MentionsProps,
|
MentionsProps,
|
||||||
RadioGroupProps,
|
RadioGroupProps,
|
||||||
RadioProps,
|
RadioProps,
|
||||||
|
RangePickerProps,
|
||||||
RateProps,
|
RateProps,
|
||||||
SelectProps,
|
SelectProps,
|
||||||
SpaceProps,
|
SpaceProps,
|
||||||
|
|
@ -28,8 +29,7 @@ import type {
|
||||||
UploadChangeParam,
|
UploadChangeParam,
|
||||||
UploadFile,
|
UploadFile,
|
||||||
UploadProps,
|
UploadProps,
|
||||||
} from 'ant-design-vue';
|
} from 'antdv-next';
|
||||||
import type { RangePickerProps } from 'ant-design-vue/es/date-picker';
|
|
||||||
|
|
||||||
import type { Component, Ref } from 'vue';
|
import type { Component, Ref } from 'vue';
|
||||||
|
|
||||||
|
|
@ -72,7 +72,7 @@ import { isEmpty } from '@vben/utils';
|
||||||
|
|
||||||
import { VbenCollapsibleParams } from '@vben-core/shadcn-ui';
|
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';
|
import { upload_file } from '#/api/examples/upload';
|
||||||
type AdapterUploadProps = UploadProps & {
|
type AdapterUploadProps = UploadProps & {
|
||||||
|
|
@ -86,60 +86,72 @@ type AdapterUploadProps = UploadProps & {
|
||||||
};
|
};
|
||||||
|
|
||||||
const AutoComplete = defineAsyncComponent(
|
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(
|
const Checkbox = defineAsyncComponent(
|
||||||
() => import('ant-design-vue/es/checkbox'),
|
() => import('antdv-next/dist/checkbox/index'),
|
||||||
);
|
);
|
||||||
const CheckboxGroup = defineAsyncComponent(() =>
|
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(
|
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 Divider = defineAsyncComponent(
|
||||||
const Input = defineAsyncComponent(() => import('ant-design-vue/es/input'));
|
() => import('antdv-next/dist/divider/index'),
|
||||||
|
);
|
||||||
|
const Input = defineAsyncComponent(() => import('antdv-next/dist/input/index'));
|
||||||
const InputNumber = defineAsyncComponent(
|
const InputNumber = defineAsyncComponent(
|
||||||
() => import('ant-design-vue/es/input-number'),
|
() => import('antdv-next/dist/input-number/index'),
|
||||||
);
|
);
|
||||||
const InputPassword = defineAsyncComponent(() =>
|
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(
|
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(() =>
|
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(() =>
|
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 Rate = defineAsyncComponent(() => import('antdv-next/dist/rate/index'));
|
||||||
const Select = defineAsyncComponent(() => import('ant-design-vue/es/select'));
|
const Select = defineAsyncComponent(
|
||||||
const Space = defineAsyncComponent(() => import('ant-design-vue/es/space'));
|
() => import('antdv-next/dist/select/index'),
|
||||||
const Switch = defineAsyncComponent(() => import('ant-design-vue/es/switch'));
|
);
|
||||||
const Textarea = defineAsyncComponent(() =>
|
const Space = defineAsyncComponent(() => import('antdv-next/dist/space/index'));
|
||||||
import('ant-design-vue/es/input').then((res) => res.Textarea),
|
const Switch = defineAsyncComponent(
|
||||||
|
() => import('antdv-next/dist/switch/index'),
|
||||||
|
);
|
||||||
|
const Textarea = defineAsyncComponent(
|
||||||
|
() => import('antdv-next/dist/input/TextArea'),
|
||||||
);
|
);
|
||||||
const TimePicker = defineAsyncComponent(
|
const TimePicker = defineAsyncComponent(
|
||||||
() => import('ant-design-vue/es/time-picker'),
|
() => import('antdv-next/dist/time-picker/index'),
|
||||||
);
|
);
|
||||||
const TreeSelect = defineAsyncComponent(
|
const TreeSelect = defineAsyncComponent(
|
||||||
() => import('ant-design-vue/es/tree-select'),
|
() => import('antdv-next/dist/tree-select/index'),
|
||||||
);
|
);
|
||||||
const Cascader = defineAsyncComponent(
|
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 Upload = defineAsyncComponent(
|
||||||
const Image = defineAsyncComponent(() => import('ant-design-vue/es/image'));
|
() => import('antdv-next/dist/upload/index'),
|
||||||
|
);
|
||||||
|
const Image = defineAsyncComponent(() => import('antdv-next/dist/image/index'));
|
||||||
const PreviewGroup = defineAsyncComponent(() =>
|
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>(
|
const withDefaultPlaceholder = (
|
||||||
component: T,
|
component: Component,
|
||||||
type: 'input' | 'select',
|
type: 'input' | 'select',
|
||||||
componentProps: Recordable<any> = {},
|
componentProps: Recordable<any> = {},
|
||||||
) => {
|
) => {
|
||||||
|
|
@ -242,7 +254,7 @@ function getBase64(file: File): Promise<string> {
|
||||||
*/
|
*/
|
||||||
async function previewImage(
|
async function previewImage(
|
||||||
file: UploadFile,
|
file: UploadFile,
|
||||||
visible: Ref<boolean>,
|
open: Ref<boolean>,
|
||||||
fileList: Ref<UploadProps['fileList']>,
|
fileList: Ref<UploadProps['fileList']>,
|
||||||
) {
|
) {
|
||||||
// 非图片文件直接打开链接
|
// 非图片文件直接打开链接
|
||||||
|
|
@ -250,6 +262,8 @@ async function previewImage(
|
||||||
const url = file.url || file.preview;
|
const url = file.url || file.preview;
|
||||||
if (url) {
|
if (url) {
|
||||||
window.open(url, '_blank');
|
window.open(url, '_blank');
|
||||||
|
} else if (file.preview) {
|
||||||
|
window.open(file.preview, '_blank');
|
||||||
} else {
|
} else {
|
||||||
message.error($t('ui.formRules.previewWarning'));
|
message.error($t('ui.formRules.previewWarning'));
|
||||||
}
|
}
|
||||||
|
|
@ -285,10 +299,10 @@ async function previewImage(
|
||||||
{
|
{
|
||||||
class: 'hidden',
|
class: 'hidden',
|
||||||
preview: {
|
preview: {
|
||||||
visible: visible.value,
|
open: open.value,
|
||||||
current: currentIndex,
|
current: currentIndex,
|
||||||
onVisibleChange: (value: boolean) => {
|
onOpenChange: (value: boolean) => {
|
||||||
visible.value = value;
|
open.value = value;
|
||||||
if (!value) {
|
if (!value) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (!isUnmounted && container) {
|
if (!isUnmounted && container) {
|
||||||
|
|
@ -330,7 +344,7 @@ function cropImage(file: File, aspectRatio: string | undefined) {
|
||||||
const open = ref<boolean>(true);
|
const open = ref<boolean>(true);
|
||||||
const cropperRef = ref<InstanceType<typeof VCropper> | null>(null);
|
const cropperRef = ref<InstanceType<typeof VCropper> | null>(null);
|
||||||
|
|
||||||
const closeModal = () => {
|
function closeModal() {
|
||||||
open.value = false;
|
open.value = false;
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (!isUnmounted && container) {
|
if (!isUnmounted && container) {
|
||||||
|
|
@ -342,7 +356,7 @@ function cropImage(file: File, aspectRatio: string | undefined) {
|
||||||
container.remove();
|
container.remove();
|
||||||
}
|
}
|
||||||
}, 300);
|
}, 300);
|
||||||
};
|
}
|
||||||
|
|
||||||
const CropperWrapper = {
|
const CropperWrapper = {
|
||||||
setup() {
|
setup() {
|
||||||
|
|
@ -372,7 +386,7 @@ function cropImage(file: File, aspectRatio: string | undefined) {
|
||||||
closable: false,
|
closable: false,
|
||||||
cancelText: $t('common.cancel'),
|
cancelText: $t('common.cancel'),
|
||||||
okText: $t('ui.crop.confirm'),
|
okText: $t('ui.crop.confirm'),
|
||||||
destroyOnClose: true,
|
destroyOnHidden: true,
|
||||||
onOk: async () => {
|
onOk: async () => {
|
||||||
const cropper = cropperRef.value;
|
const cropper = cropperRef.value;
|
||||||
if (!cropper) {
|
if (!cropper) {
|
||||||
|
|
@ -416,7 +430,7 @@ function cropImage(file: File, aspectRatio: string | undefined) {
|
||||||
/**
|
/**
|
||||||
* 带预览功能的上传组件
|
* 带预览功能的上传组件
|
||||||
*/
|
*/
|
||||||
const withPreviewUpload = () => {
|
function withPreviewUpload() {
|
||||||
return defineComponent({
|
return defineComponent({
|
||||||
name: Upload.name,
|
name: Upload.name,
|
||||||
emits: ['update:modelValue'],
|
emits: ['update:modelValue'],
|
||||||
|
|
@ -436,10 +450,10 @@ const withPreviewUpload = () => {
|
||||||
() => attrs?.aspectRatio ?? attrs?.['aspect-ratio'],
|
() => attrs?.aspectRatio ?? attrs?.['aspect-ratio'],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleBeforeUpload = async (
|
async function handleBeforeUpload(
|
||||||
file: UploadFile,
|
file: UploadFile,
|
||||||
originFileList: Array<File>,
|
originFileList: Array<File>,
|
||||||
) => {
|
) {
|
||||||
// 文件大小限制
|
// 文件大小限制
|
||||||
if (maxSize.value && (file.size || 0) / 1024 / 1024 > maxSize.value) {
|
if (maxSize.value && (file.size || 0) / 1024 / 1024 > maxSize.value) {
|
||||||
message.error($t('ui.formRules.sizeLimit', [maxSize.value]));
|
message.error($t('ui.formRules.sizeLimit', [maxSize.value]));
|
||||||
|
|
@ -463,9 +477,9 @@ const withPreviewUpload = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
return attrs.beforeUpload?.(file) ?? true;
|
return attrs.beforeUpload?.(file) ?? true;
|
||||||
};
|
}
|
||||||
|
|
||||||
const handleChange = (event: UploadChangeParam) => {
|
function handleChange(event: UploadChangeParam) {
|
||||||
try {
|
try {
|
||||||
attrs.handleChange?.(event);
|
attrs.handleChange?.(event);
|
||||||
attrs.onHandleChange?.(event);
|
attrs.onHandleChange?.(event);
|
||||||
|
|
@ -479,19 +493,19 @@ const withPreviewUpload = () => {
|
||||||
'update:modelValue',
|
'update:modelValue',
|
||||||
event.fileList?.length ? fileList.value : undefined,
|
event.fileList?.length ? fileList.value : undefined,
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
|
||||||
const handlePreview = async (file: UploadFile) => {
|
function handlePreview(file: UploadFile) {
|
||||||
previewVisible.value = true;
|
previewVisible.value = true;
|
||||||
await previewImage(file, previewVisible, fileList);
|
return previewImage(file, previewVisible, fileList);
|
||||||
};
|
}
|
||||||
|
|
||||||
const renderUploadButton = () => {
|
function renderUploadButton() {
|
||||||
if (attrs.disabled) return null;
|
if (attrs.disabled) return null;
|
||||||
return isEmpty(slots)
|
return isEmpty(slots)
|
||||||
? createDefaultUploadSlots(listType, placeholder)
|
? createDefaultUploadSlots(listType, placeholder)
|
||||||
: slots;
|
: slots;
|
||||||
};
|
}
|
||||||
|
|
||||||
// 拖拽排序
|
// 拖拽排序
|
||||||
const draggable = computed(
|
const draggable = computed(
|
||||||
|
|
@ -600,7 +614,7 @@ const withPreviewUpload = () => {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
// 这里需要自行根据业务组件库进行适配,需要用到的组件都需要在这里类型说明
|
// 这里需要自行根据业务组件库进行适配,需要用到的组件都需要在这里类型说明
|
||||||
export type ComponentType =
|
export type ComponentType =
|
||||||
|
|
@ -681,13 +695,13 @@ async function initComponentAdapter() {
|
||||||
fieldNames: { label: 'label', value: 'value', children: 'children' },
|
fieldNames: { label: 'label', value: 'value', children: 'children' },
|
||||||
loadingSlot: 'suffixIcon',
|
loadingSlot: 'suffixIcon',
|
||||||
modelPropName: 'value',
|
modelPropName: 'value',
|
||||||
visibleEvent: 'onVisibleChange',
|
visibleEvent: 'onOpenChange',
|
||||||
}),
|
}),
|
||||||
ApiSelect: withDefaultPlaceholder(ApiComponent, 'select', {
|
ApiSelect: withDefaultPlaceholder(ApiComponent, 'select', {
|
||||||
component: Select,
|
component: Select,
|
||||||
loadingSlot: 'suffixIcon',
|
loadingSlot: 'suffixIcon',
|
||||||
modelPropName: 'value',
|
modelPropName: 'value',
|
||||||
visibleEvent: 'onVisibleChange',
|
visibleEvent: 'onOpenChange',
|
||||||
}),
|
}),
|
||||||
ApiTreeSelect: withDefaultPlaceholder(ApiComponent, 'select', {
|
ApiTreeSelect: withDefaultPlaceholder(ApiComponent, 'select', {
|
||||||
component: TreeSelect,
|
component: TreeSelect,
|
||||||
|
|
@ -695,7 +709,7 @@ async function initComponentAdapter() {
|
||||||
loadingSlot: 'suffixIcon',
|
loadingSlot: 'suffixIcon',
|
||||||
modelPropName: 'value',
|
modelPropName: 'value',
|
||||||
optionsPropName: 'treeData',
|
optionsPropName: 'treeData',
|
||||||
visibleEvent: 'onVisibleChange',
|
visibleEvent: 'onOpenChange',
|
||||||
}),
|
}),
|
||||||
AutoComplete,
|
AutoComplete,
|
||||||
Cascader,
|
Cascader,
|
||||||
|
|
@ -713,7 +727,9 @@ async function initComponentAdapter() {
|
||||||
modelValueProp: 'value',
|
modelValueProp: 'value',
|
||||||
}),
|
}),
|
||||||
Input: withDefaultPlaceholder(Input, 'input'),
|
Input: withDefaultPlaceholder(Input, 'input'),
|
||||||
InputNumber: withDefaultPlaceholder(InputNumber, 'input'),
|
InputNumber: withDefaultPlaceholder(InputNumber, 'input', {
|
||||||
|
style: { width: '100%' },
|
||||||
|
}),
|
||||||
InputPassword: withDefaultPlaceholder(InputPassword, 'input'),
|
InputPassword: withDefaultPlaceholder(InputPassword, 'input'),
|
||||||
Mentions: withDefaultPlaceholder(Mentions, 'input'),
|
Mentions: withDefaultPlaceholder(Mentions, 'input'),
|
||||||
// 自定义主要按钮
|
// 自定义主要按钮
|
||||||
|
|
@ -764,7 +780,7 @@ async function initComponentAdapter() {
|
||||||
copyPreferencesSuccess: (title, content) => {
|
copyPreferencesSuccess: (title, content) => {
|
||||||
notification.success({
|
notification.success({
|
||||||
description: content,
|
description: content,
|
||||||
message: title,
|
title,
|
||||||
placement: 'bottomRight',
|
placement: 'bottomRight',
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ import {
|
||||||
import { get, isFunction, isString } from '@vben/utils';
|
import { get, isFunction, isString } from '@vben/utils';
|
||||||
|
|
||||||
import { objectOmit } from '@vueuse/core';
|
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';
|
import { $t } from '#/locales';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ import {
|
||||||
import { useAccessStore } from '@vben/stores';
|
import { useAccessStore } from '@vben/stores';
|
||||||
import { cloneDeep } from '@vben/utils';
|
import { cloneDeep } from '@vben/utils';
|
||||||
|
|
||||||
import { message } from 'ant-design-vue';
|
import { message } from 'antdv-next';
|
||||||
import JSONBigInt from 'json-bigint';
|
import JSONBigInt from 'json-bigint';
|
||||||
|
|
||||||
import { useAuthStore } from '#/store';
|
import { useAuthStore } from '#/store';
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
export * from './dept';
|
export * from './dept';
|
||||||
export * from './menu';
|
export * from './menu';
|
||||||
export * from './role';
|
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>
|
<script lang="ts" setup>
|
||||||
import { computed } from 'vue';
|
import { computed, watch } from 'vue';
|
||||||
|
|
||||||
import { useAntdDesignTokens } from '@vben/hooks';
|
import { useAntdDesignTokens } from '@vben/hooks';
|
||||||
import { preferences, usePreferences } from '@vben/preferences';
|
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';
|
import { antdLocale } from '#/locales';
|
||||||
|
|
||||||
|
|
@ -28,6 +28,14 @@ const tokenTheme = computed(() => {
|
||||||
token: tokens,
|
token: tokens,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
watch(
|
||||||
|
tokenTheme,
|
||||||
|
(themeConfig) => {
|
||||||
|
ConfigProvider.config({ theme: themeConfig });
|
||||||
|
},
|
||||||
|
{ immediate: true },
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import { providePluginsOptions } from '@vben/plugins';
|
||||||
import { preferences } from '@vben/preferences';
|
import { preferences } from '@vben/preferences';
|
||||||
import { initStores } from '@vben/stores';
|
import { initStores } from '@vben/stores';
|
||||||
import '@vben/styles';
|
import '@vben/styles';
|
||||||
import '@vben/styles/antd';
|
import '@vben/styles/antdv-next';
|
||||||
|
|
||||||
import { useTitle } from '@vueuse/core';
|
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';
|
import type { App } from 'vue';
|
||||||
|
|
||||||
|
|
@ -13,8 +13,8 @@ import {
|
||||||
} from '@vben/locales';
|
} from '@vben/locales';
|
||||||
import { preferences } from '@vben/preferences';
|
import { preferences } from '@vben/preferences';
|
||||||
|
|
||||||
import antdEnLocale from 'ant-design-vue/es/locale/en_US';
|
import antdEnLocale from 'antdv-next/dist/locale/en_US';
|
||||||
import antdDefaultLocale from 'ant-design-vue/es/locale/zh_CN';
|
import antdDefaultLocale from 'antdv-next/dist/locale/zh_CN';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
const antdLocale = ref<Locale>(antdDefaultLocale);
|
const antdLocale = ref<Locale>(antdDefaultLocale);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,18 @@
|
||||||
{
|
{
|
||||||
"title": "System Management",
|
"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": {
|
"dept": {
|
||||||
"name": "Department",
|
"name": "Department",
|
||||||
"title": "Department Management",
|
"title": "Department Management",
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,18 @@
|
||||||
{
|
{
|
||||||
"title": "系统管理",
|
"title": "系统管理",
|
||||||
|
"user": {
|
||||||
|
"title": "用户管理",
|
||||||
|
"list": "用户列表",
|
||||||
|
"name": "用户名",
|
||||||
|
"userName": "用户名称",
|
||||||
|
"id": "用户ID",
|
||||||
|
"dept": "部门",
|
||||||
|
"status": "状态",
|
||||||
|
"remark": "备注",
|
||||||
|
"createTime": "创建时间",
|
||||||
|
"operation": "操作",
|
||||||
|
"placeholder": "搜索部门..."
|
||||||
|
},
|
||||||
"dept": {
|
"dept": {
|
||||||
"list": "部门列表",
|
"list": "部门列表",
|
||||||
"createTime": "创建时间",
|
"createTime": "创建时间",
|
||||||
|
|
|
||||||
|
|
@ -29,4 +29,4 @@ async function initApplication() {
|
||||||
unmountGlobalLoading();
|
unmountGlobalLoading();
|
||||||
}
|
}
|
||||||
|
|
||||||
initApplication();
|
void initApplication();
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import type {
|
||||||
import { generateAccessible } from '@vben/access';
|
import { generateAccessible } from '@vben/access';
|
||||||
import { preferences } from '@vben/preferences';
|
import { preferences } from '@vben/preferences';
|
||||||
|
|
||||||
import { message } from 'ant-design-vue';
|
import { message } from 'antdv-next';
|
||||||
|
|
||||||
import { getAllMenusApi } from '#/api';
|
import { getAllMenusApi } from '#/api';
|
||||||
import { BasicLayout, IFrameView } from '#/layouts';
|
import { BasicLayout, IFrameView } from '#/layouts';
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,15 @@ const routes: RouteRecordRaw[] = [
|
||||||
name: 'System',
|
name: 'System',
|
||||||
path: '/system',
|
path: '/system',
|
||||||
children: [
|
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',
|
path: '/system/role',
|
||||||
name: 'SystemRole',
|
name: 'SystemRole',
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import { LOGIN_PATH } from '@vben/constants';
|
||||||
import { preferences } from '@vben/preferences';
|
import { preferences } from '@vben/preferences';
|
||||||
import { resetAllStores, useAccessStore, useUserStore } from '@vben/stores';
|
import { resetAllStores, useAccessStore, useUserStore } from '@vben/stores';
|
||||||
|
|
||||||
import { notification } from 'ant-design-vue';
|
import { notification } from 'antdv-next';
|
||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
|
|
||||||
import { getAccessCodesApi, getUserInfoApi, loginApi, logoutApi } from '#/api';
|
import { getAccessCodesApi, getUserInfoApi, loginApi, logoutApi } from '#/api';
|
||||||
|
|
@ -65,7 +65,7 @@ export const useAuthStore = defineStore('auth', () => {
|
||||||
notification.success({
|
notification.success({
|
||||||
description: `${$t('authentication.loginSuccessDesc')}:${userInfo?.realName}`,
|
description: `${$t('authentication.loginSuccessDesc')}:${userInfo?.realName}`,
|
||||||
duration: 3,
|
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 { AuthenticationCodeLogin, z } from '@vben/common-ui';
|
||||||
import { $t } from '@vben/locales';
|
import { $t } from '@vben/locales';
|
||||||
|
|
||||||
import { message } from 'ant-design-vue';
|
import { message } from 'antdv-next';
|
||||||
|
|
||||||
defineOptions({ name: 'CodeLogin' });
|
defineOptions({ name: 'CodeLogin' });
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import { computed } from 'vue';
|
||||||
|
|
||||||
import { ProfilePasswordSetting, z } from '@vben/common-ui';
|
import { ProfilePasswordSetting, z } from '@vben/common-ui';
|
||||||
|
|
||||||
import { message } from 'ant-design-vue';
|
import { message } from 'antdv-next';
|
||||||
|
|
||||||
const formSchema = computed((): VbenFormSchema[] => {
|
const formSchema = computed((): VbenFormSchema[] => {
|
||||||
return [
|
return [
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import { AccessControl, useAccess } from '@vben/access';
|
||||||
import { Page } from '@vben/common-ui';
|
import { Page } from '@vben/common-ui';
|
||||||
import { resetAllStores, useUserStore } from '@vben/stores';
|
import { resetAllStores, useUserStore } from '@vben/stores';
|
||||||
|
|
||||||
import { Button, Card } from 'ant-design-vue';
|
import { Button, Card } from 'antdv-next';
|
||||||
|
|
||||||
import { useAuthStore } from '#/store';
|
import { useAuthStore } from '#/store';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import { useAccess } from '@vben/access';
|
||||||
import { Page } from '@vben/common-ui';
|
import { Page } from '@vben/common-ui';
|
||||||
import { resetAllStores, useUserStore } from '@vben/stores';
|
import { resetAllStores, useUserStore } from '@vben/stores';
|
||||||
|
|
||||||
import { Button, Card } from 'ant-design-vue';
|
import { Button, Card } from 'antdv-next';
|
||||||
|
|
||||||
import { useAuthStore } from '#/store';
|
import { useAuthStore } from '#/store';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import { useAccessStore } from '@vben/stores';
|
||||||
|
|
||||||
import { MenuBadge } from '@vben-core/menu-ui';
|
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';
|
import { useVbenForm } from '#/adapter/form';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { useRouter } from 'vue-router';
|
||||||
|
|
||||||
import { Fallback } from '@vben/common-ui';
|
import { Fallback } from '@vben/common-ui';
|
||||||
|
|
||||||
import { Button } from 'ant-design-vue';
|
import { Button } from 'antdv-next';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { useRouter } from 'vue-router';
|
||||||
|
|
||||||
import { Fallback } from '@vben/common-ui';
|
import { Fallback } from '@vben/common-ui';
|
||||||
|
|
||||||
import { Button } from 'ant-design-vue';
|
import { Button } from 'antdv-next';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { ref } from 'vue';
|
||||||
import { Page } from '@vben/common-ui';
|
import { Page } from '@vben/common-ui';
|
||||||
|
|
||||||
import { useClipboard } from '@vueuse/core';
|
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 source = ref('Hello');
|
||||||
const { copy, text } = useClipboard({ legacy: true, source });
|
const { copy, text } = useClipboard({ legacy: true, source });
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import {
|
||||||
downloadFileFromUrl,
|
downloadFileFromUrl,
|
||||||
} from '@vben/utils';
|
} from '@vben/utils';
|
||||||
|
|
||||||
import { Button, Card } from 'ant-design-vue';
|
import { Button, Card } from 'antdv-next';
|
||||||
|
|
||||||
import { downloadFile1, downloadFile2 } from '#/api/examples/download';
|
import { downloadFile1, downloadFile2 } from '#/api/examples/download';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { ref } from 'vue';
|
||||||
import { Page } from '@vben/common-ui';
|
import { Page } from '@vben/common-ui';
|
||||||
|
|
||||||
import { useFullscreen } from '@vueuse/core';
|
import { useFullscreen } from '@vueuse/core';
|
||||||
import { Button, Card } from 'ant-design-vue';
|
import { Button, Card } from 'antdv-next';
|
||||||
|
|
||||||
const domRef = ref<HTMLElement>();
|
const domRef = ref<HTMLElement>();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ import {
|
||||||
SvgWeChatIcon,
|
SvgWeChatIcon,
|
||||||
} from '@vben/icons';
|
} from '@vben/icons';
|
||||||
|
|
||||||
import { Card, Input } from 'ant-design-vue';
|
import { Card, Input } from 'antdv-next';
|
||||||
|
|
||||||
const iconValue1 = ref('ant-design:trademark-outlined');
|
const iconValue1 = ref('ant-design:trademark-outlined');
|
||||||
const iconValue2 = ref('svg:avatar-1');
|
const iconValue2 = ref('svg:avatar-1');
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { ref } from 'vue';
|
||||||
|
|
||||||
import { Page } from '@vben/common-ui';
|
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';
|
import { getBigIntData } from '#/api/examples/json-bigint';
|
||||||
|
|
||||||
|
|
@ -21,7 +21,7 @@ function fetchData() {
|
||||||
>
|
>
|
||||||
<Card>
|
<Card>
|
||||||
<Alert>
|
<Alert>
|
||||||
<template #message>
|
<template #title>
|
||||||
有些后端接口返回的ID是长整数,但javascript原生的JSON解析是不支持超过2^53-1的长整数的。
|
有些后端接口返回的ID是长整数,但javascript原生的JSON解析是不支持超过2^53-1的长整数的。
|
||||||
这种情况可以建议后端返回数据前将长整数转换为字符串类型。如果后端不接受我们的建议😡……
|
这种情况可以建议后端返回数据前将长整数转换为字符串类型。如果后端不接受我们的建议😡……
|
||||||
<br />
|
<br />
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import type { LoginExpiredModeType } from '@vben/types';
|
||||||
import { Page } from '@vben/common-ui';
|
import { Page } from '@vben/common-ui';
|
||||||
import { preferences, updatePreferences } from '@vben/preferences';
|
import { preferences, updatePreferences } from '@vben/preferences';
|
||||||
|
|
||||||
import { Button, Card } from 'ant-design-vue';
|
import { Button, Card } from 'antdv-next';
|
||||||
|
|
||||||
import { getMockStatusApi } from '#/api';
|
import { getMockStatusApi } from '#/api';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import {
|
||||||
updateCustomPreferences,
|
updateCustomPreferences,
|
||||||
} from '@vben/preferences';
|
} 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';
|
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']) {
|
function getPriorityColor(priority: DemoTaskItem['priority']) {
|
||||||
|
|
@ -136,7 +136,7 @@ function getPriorityColor(priority: DemoTaskItem['priority']) {
|
||||||
:title="$t('demos.preferencesExtensionDemo.currentConfig')"
|
:title="$t('demos.preferencesExtensionDemo.currentConfig')"
|
||||||
>
|
>
|
||||||
<Alert :type="toneConfig.alertType" show-icon>
|
<Alert :type="toneConfig.alertType" show-icon>
|
||||||
<template #message>
|
<template #title>
|
||||||
{{
|
{{
|
||||||
$t('demos.preferencesExtensionDemo.currentTitle', {
|
$t('demos.preferencesExtensionDemo.currentTitle', {
|
||||||
title: playgroundPreferences.reportTitle,
|
title: playgroundPreferences.reportTitle,
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { computed, ref, watchEffect } from 'vue';
|
||||||
|
|
||||||
import { Page } from '@vben/common-ui';
|
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';
|
import { getParamsData } from '#/api/examples/params';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import { useRouter } from 'vue-router';
|
||||||
import { Page } from '@vben/common-ui';
|
import { Page } from '@vben/common-ui';
|
||||||
import { useTabs } from '@vben/hooks';
|
import { useTabs } from '@vben/hooks';
|
||||||
|
|
||||||
import { Button, Card, Input } from 'ant-design-vue';
|
import { Button, Card, Input } from 'antdv-next';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const newTabTitle = ref('');
|
const newTabTitle = ref('');
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
import { Page } from '@vben/common-ui';
|
import { Page } from '@vben/common-ui';
|
||||||
|
|
||||||
import { refAutoReset } from '@vueuse/core';
|
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 ConcurrencyCaching from './concurrency-caching.vue';
|
||||||
import InfiniteQueries from './infinite-queries.vue';
|
import InfiniteQueries from './infinite-queries.vue';
|
||||||
|
|
@ -27,7 +27,7 @@ const showCaching = refAutoReset(true, 1000);
|
||||||
<Card
|
<Card
|
||||||
title="并发和缓存"
|
title="并发和缓存"
|
||||||
v-spinning="!showCaching"
|
v-spinning="!showCaching"
|
||||||
:body-style="{ minHeight: '330px' }"
|
:styles="{ body: { minHeight: '330px' } }"
|
||||||
>
|
>
|
||||||
<template #extra>
|
<template #extra>
|
||||||
<Button @click="showCaching = false">重新加载</Button>
|
<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