Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into offline-icon
This commit is contained in:
commit
1aefdc27af
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
@ -160,6 +160,7 @@
|
|||||||
"stylelint.enable": true,
|
"stylelint.enable": true,
|
||||||
"stylelint.packageManager": "pnpm",
|
"stylelint.packageManager": "pnpm",
|
||||||
"stylelint.validate": ["css", "less", "postcss", "scss", "vue"],
|
"stylelint.validate": ["css", "less", "postcss", "scss", "vue"],
|
||||||
|
"stylelint.customSyntax": "postcss-html",
|
||||||
"stylelint.snippet": ["css", "less", "postcss", "scss", "vue"],
|
"stylelint.snippet": ["css", "less", "postcss", "scss", "vue"],
|
||||||
|
|
||||||
"typescript.inlayHints.enumMemberValues.enabled": true,
|
"typescript.inlayHints.enumMemberValues.enabled": true,
|
||||||
|
@ -77,7 +77,7 @@ setupVbenVxeTable({
|
|||||||
|
|
||||||
// 表格配置项可以用 cellRender: { name: 'CellImage' },
|
// 表格配置项可以用 cellRender: { name: 'CellImage' },
|
||||||
vxeUI.renderer.add('CellImage', {
|
vxeUI.renderer.add('CellImage', {
|
||||||
renderDefault(_renderOpts, params) {
|
renderTableDefault(_renderOpts, params) {
|
||||||
const { column, row } = params;
|
const { column, row } = params;
|
||||||
return h(Image, { src: row[column.field] });
|
return h(Image, { src: row[column.field] });
|
||||||
},
|
},
|
||||||
@ -85,7 +85,7 @@ setupVbenVxeTable({
|
|||||||
|
|
||||||
// 表格配置项可以用 cellRender: { name: 'CellLink' },
|
// 表格配置项可以用 cellRender: { name: 'CellLink' },
|
||||||
vxeUI.renderer.add('CellLink', {
|
vxeUI.renderer.add('CellLink', {
|
||||||
renderDefault(renderOpts) {
|
renderTableDefault(renderOpts) {
|
||||||
const { props } = renderOpts;
|
const { props } = renderOpts;
|
||||||
return h(
|
return h(
|
||||||
Button,
|
Button,
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
import { createApp } from 'vue';
|
import { createApp, watchEffect } from 'vue';
|
||||||
|
|
||||||
import { registerAccessDirective } from '@vben/access';
|
import { registerAccessDirective } from '@vben/access';
|
||||||
|
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/antd';
|
||||||
|
|
||||||
|
import { useTitle } from '@vueuse/core';
|
||||||
|
|
||||||
import { setupGlobalComponent } from '#/components/global';
|
import { setupGlobalComponent } from '#/components/global';
|
||||||
import { setupI18n } from '#/locales';
|
import { $t, setupI18n } from '#/locales';
|
||||||
|
|
||||||
import { initComponentAdapter } from './adapter/component';
|
import { initComponentAdapter } from './adapter/component';
|
||||||
import App from './app.vue';
|
import App from './app.vue';
|
||||||
@ -33,6 +36,16 @@ async function bootstrap(namespace: string) {
|
|||||||
// 配置路由及路由守卫
|
// 配置路由及路由守卫
|
||||||
app.use(router);
|
app.use(router);
|
||||||
|
|
||||||
|
// 动态更新标题
|
||||||
|
watchEffect(() => {
|
||||||
|
if (preferences.app.dynamicTitle) {
|
||||||
|
const routeTitle = router.currentRoute.value.meta?.title;
|
||||||
|
const pageTitle =
|
||||||
|
(routeTitle ? `${$t(routeTitle)} - ` : '') + preferences.app.name;
|
||||||
|
useTitle(pageTitle);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
app.mount('#app');
|
app.mount('#app');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ import { defineOverridesPreferences } from '@vben/preferences';
|
|||||||
/**
|
/**
|
||||||
* @description 项目配置文件
|
* @description 项目配置文件
|
||||||
* 只需要覆盖项目中的一部分配置,不需要的配置不用覆盖,会自动使用默认配置
|
* 只需要覆盖项目中的一部分配置,不需要的配置不用覆盖,会自动使用默认配置
|
||||||
|
* !!! 更改配置后请清空缓存,否则可能不生效
|
||||||
*/
|
*/
|
||||||
export const overridesPreferences = defineOverridesPreferences({
|
export const overridesPreferences = defineOverridesPreferences({
|
||||||
// overrides
|
// overrides
|
||||||
|
@ -5,9 +5,6 @@ import { preferences } from '@vben/preferences';
|
|||||||
import { useAccessStore, useUserStore } from '@vben/stores';
|
import { useAccessStore, useUserStore } from '@vben/stores';
|
||||||
import { startProgress, stopProgress } from '@vben/utils';
|
import { startProgress, stopProgress } from '@vben/utils';
|
||||||
|
|
||||||
import { useTitle } from '@vueuse/core';
|
|
||||||
|
|
||||||
import { $t } from '#/locales';
|
|
||||||
import { accessRoutes, coreRouteNames } from '#/router/routes';
|
import { accessRoutes, coreRouteNames } from '#/router/routes';
|
||||||
import { useAuthStore } from '#/store';
|
import { useAuthStore } from '#/store';
|
||||||
|
|
||||||
@ -40,13 +37,6 @@ function setupCommonGuard(router: Router) {
|
|||||||
if (preferences.transition.progress) {
|
if (preferences.transition.progress) {
|
||||||
stopProgress();
|
stopProgress();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 动态修改标题
|
|
||||||
if (preferences.app.dynamicTitle) {
|
|
||||||
const { title } = to.meta;
|
|
||||||
// useTitle(`${$t(title)} - ${preferences.app.name}`);
|
|
||||||
useTitle(`${$t(title)} - ${preferences.app.name}`);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ setupVbenVxeTable({
|
|||||||
|
|
||||||
// 表格配置项可以用 cellRender: { name: 'CellImage' },
|
// 表格配置项可以用 cellRender: { name: 'CellImage' },
|
||||||
vxeUI.renderer.add('CellImage', {
|
vxeUI.renderer.add('CellImage', {
|
||||||
renderDefault(_renderOpts, params) {
|
renderTableDefault(_renderOpts, params) {
|
||||||
const { column, row } = params;
|
const { column, row } = params;
|
||||||
const src = row[column.field];
|
const src = row[column.field];
|
||||||
return h(ElImage, { src, previewSrcList: [src] });
|
return h(ElImage, { src, previewSrcList: [src] });
|
||||||
@ -47,7 +47,7 @@ setupVbenVxeTable({
|
|||||||
|
|
||||||
// 表格配置项可以用 cellRender: { name: 'CellLink' },
|
// 表格配置项可以用 cellRender: { name: 'CellLink' },
|
||||||
vxeUI.renderer.add('CellLink', {
|
vxeUI.renderer.add('CellLink', {
|
||||||
renderDefault(renderOpts) {
|
renderTableDefault(renderOpts) {
|
||||||
const { props } = renderOpts;
|
const { props } = renderOpts;
|
||||||
return h(
|
return h(
|
||||||
ElButton,
|
ElButton,
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
import { createApp } from 'vue';
|
import { createApp, watchEffect } from 'vue';
|
||||||
|
|
||||||
import { registerAccessDirective } from '@vben/access';
|
import { registerAccessDirective } from '@vben/access';
|
||||||
|
import { preferences } from '@vben/preferences';
|
||||||
import { initStores } from '@vben/stores';
|
import { initStores } from '@vben/stores';
|
||||||
import '@vben/styles';
|
import '@vben/styles';
|
||||||
import '@vben/styles/ele';
|
import '@vben/styles/ele';
|
||||||
|
|
||||||
import { setupI18n } from '#/locales';
|
import { useTitle } from '@vueuse/core';
|
||||||
|
|
||||||
|
import { $t, setupI18n } from '#/locales';
|
||||||
|
|
||||||
import { initComponentAdapter } from './adapter/component';
|
import { initComponentAdapter } from './adapter/component';
|
||||||
import App from './app.vue';
|
import App from './app.vue';
|
||||||
@ -28,6 +31,16 @@ async function bootstrap(namespace: string) {
|
|||||||
// 配置路由及路由守卫
|
// 配置路由及路由守卫
|
||||||
app.use(router);
|
app.use(router);
|
||||||
|
|
||||||
|
// 动态更新标题
|
||||||
|
watchEffect(() => {
|
||||||
|
if (preferences.app.dynamicTitle) {
|
||||||
|
const routeTitle = router.currentRoute.value.meta?.title;
|
||||||
|
const pageTitle =
|
||||||
|
(routeTitle ? `${$t(routeTitle)} - ` : '') + preferences.app.name;
|
||||||
|
useTitle(pageTitle);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
app.mount('#app');
|
app.mount('#app');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ import { defineOverridesPreferences } from '@vben/preferences';
|
|||||||
/**
|
/**
|
||||||
* @description 项目配置文件
|
* @description 项目配置文件
|
||||||
* 只需要覆盖项目中的一部分配置,不需要的配置不用覆盖,会自动使用默认配置
|
* 只需要覆盖项目中的一部分配置,不需要的配置不用覆盖,会自动使用默认配置
|
||||||
|
* !!! 更改配置后请清空缓存,否则可能不生效
|
||||||
*/
|
*/
|
||||||
export const overridesPreferences = defineOverridesPreferences({
|
export const overridesPreferences = defineOverridesPreferences({
|
||||||
// overrides
|
// overrides
|
||||||
|
@ -5,9 +5,6 @@ import { preferences } from '@vben/preferences';
|
|||||||
import { useAccessStore, useUserStore } from '@vben/stores';
|
import { useAccessStore, useUserStore } from '@vben/stores';
|
||||||
import { startProgress, stopProgress } from '@vben/utils';
|
import { startProgress, stopProgress } from '@vben/utils';
|
||||||
|
|
||||||
import { useTitle } from '@vueuse/core';
|
|
||||||
|
|
||||||
import { $t } from '#/locales';
|
|
||||||
import { accessRoutes, coreRouteNames } from '#/router/routes';
|
import { accessRoutes, coreRouteNames } from '#/router/routes';
|
||||||
import { useAuthStore } from '#/store';
|
import { useAuthStore } from '#/store';
|
||||||
|
|
||||||
@ -40,13 +37,6 @@ function setupCommonGuard(router: Router) {
|
|||||||
if (preferences.transition.progress) {
|
if (preferences.transition.progress) {
|
||||||
stopProgress();
|
stopProgress();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 动态修改标题
|
|
||||||
if (preferences.app.dynamicTitle) {
|
|
||||||
const { title } = to.meta;
|
|
||||||
// useTitle(`${$t(title)} - ${preferences.app.name}`);
|
|
||||||
useTitle(`${$t(title)} - ${preferences.app.name}`);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ setupVbenVxeTable({
|
|||||||
|
|
||||||
// 表格配置项可以用 cellRender: { name: 'CellImage' },
|
// 表格配置项可以用 cellRender: { name: 'CellImage' },
|
||||||
vxeUI.renderer.add('CellImage', {
|
vxeUI.renderer.add('CellImage', {
|
||||||
renderDefault(_renderOpts, params) {
|
renderTableDefault(_renderOpts, params) {
|
||||||
const { column, row } = params;
|
const { column, row } = params;
|
||||||
return h(NImage, { src: row[column.field] });
|
return h(NImage, { src: row[column.field] });
|
||||||
},
|
},
|
||||||
@ -46,7 +46,7 @@ setupVbenVxeTable({
|
|||||||
|
|
||||||
// 表格配置项可以用 cellRender: { name: 'CellLink' },
|
// 表格配置项可以用 cellRender: { name: 'CellLink' },
|
||||||
vxeUI.renderer.add('CellLink', {
|
vxeUI.renderer.add('CellLink', {
|
||||||
renderDefault(renderOpts) {
|
renderTableDefault(renderOpts) {
|
||||||
const { props } = renderOpts;
|
const { props } = renderOpts;
|
||||||
return h(
|
return h(
|
||||||
NButton,
|
NButton,
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
import { createApp } from 'vue';
|
import { createApp, watchEffect } from 'vue';
|
||||||
|
|
||||||
import { registerAccessDirective } from '@vben/access';
|
import { registerAccessDirective } from '@vben/access';
|
||||||
|
import { preferences } from '@vben/preferences';
|
||||||
import { initStores } from '@vben/stores';
|
import { initStores } from '@vben/stores';
|
||||||
import '@vben/styles';
|
import '@vben/styles';
|
||||||
|
|
||||||
import { setupI18n } from '#/locales';
|
import { useTitle } from '@vueuse/core';
|
||||||
|
|
||||||
|
import { $t, setupI18n } from '#/locales';
|
||||||
|
|
||||||
import { initComponentAdapter } from './adapter/component';
|
import { initComponentAdapter } from './adapter/component';
|
||||||
import App from './app.vue';
|
import App from './app.vue';
|
||||||
@ -27,6 +30,16 @@ async function bootstrap(namespace: string) {
|
|||||||
// 配置路由及路由守卫
|
// 配置路由及路由守卫
|
||||||
app.use(router);
|
app.use(router);
|
||||||
|
|
||||||
|
// 动态更新标题
|
||||||
|
watchEffect(() => {
|
||||||
|
if (preferences.app.dynamicTitle) {
|
||||||
|
const routeTitle = router.currentRoute.value.meta?.title;
|
||||||
|
const pageTitle =
|
||||||
|
(routeTitle ? `${$t(routeTitle)} - ` : '') + preferences.app.name;
|
||||||
|
useTitle(pageTitle);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
app.mount('#app');
|
app.mount('#app');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ import { defineOverridesPreferences } from '@vben/preferences';
|
|||||||
/**
|
/**
|
||||||
* @description 项目配置文件
|
* @description 项目配置文件
|
||||||
* 只需要覆盖项目中的一部分配置,不需要的配置不用覆盖,会自动使用默认配置
|
* 只需要覆盖项目中的一部分配置,不需要的配置不用覆盖,会自动使用默认配置
|
||||||
|
* !!! 更改配置后请清空缓存,否则可能不生效
|
||||||
*/
|
*/
|
||||||
export const overridesPreferences = defineOverridesPreferences({
|
export const overridesPreferences = defineOverridesPreferences({
|
||||||
// overrides
|
// overrides
|
||||||
|
@ -5,9 +5,6 @@ import { preferences } from '@vben/preferences';
|
|||||||
import { useAccessStore, useUserStore } from '@vben/stores';
|
import { useAccessStore, useUserStore } from '@vben/stores';
|
||||||
import { startProgress, stopProgress } from '@vben/utils';
|
import { startProgress, stopProgress } from '@vben/utils';
|
||||||
|
|
||||||
import { useTitle } from '@vueuse/core';
|
|
||||||
|
|
||||||
import { $t } from '#/locales';
|
|
||||||
import { accessRoutes, coreRouteNames } from '#/router/routes';
|
import { accessRoutes, coreRouteNames } from '#/router/routes';
|
||||||
import { useAuthStore } from '#/store';
|
import { useAuthStore } from '#/store';
|
||||||
|
|
||||||
@ -40,13 +37,6 @@ function setupCommonGuard(router: Router) {
|
|||||||
if (preferences.transition.progress) {
|
if (preferences.transition.progress) {
|
||||||
stopProgress();
|
stopProgress();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 动态修改标题
|
|
||||||
if (preferences.app.dynamicTitle) {
|
|
||||||
const { title } = to.meta;
|
|
||||||
// useTitle(`${$t(title)} - ${preferences.app.name}`);
|
|
||||||
useTitle(`${$t(title)} - ${preferences.app.name}`);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,10 @@ import type { HeadConfig } from 'vitepress';
|
|||||||
|
|
||||||
import { resolve } from 'node:path';
|
import { resolve } from 'node:path';
|
||||||
|
|
||||||
import { viteArchiverPlugin } from '@vben/vite-config';
|
import {
|
||||||
|
viteArchiverPlugin,
|
||||||
|
viteVxeTableImportsPlugin,
|
||||||
|
} from '@vben/vite-config';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
GitChangelog,
|
GitChangelog,
|
||||||
@ -85,6 +88,7 @@ export const shared = defineConfig({
|
|||||||
GitChangelogMarkdownSection(),
|
GitChangelogMarkdownSection(),
|
||||||
viteArchiverPlugin({ outputDir: '.vitepress' }),
|
viteArchiverPlugin({ outputDir: '.vitepress' }),
|
||||||
groupIconVitePlugin(),
|
groupIconVitePlugin(),
|
||||||
|
await viteVxeTableImportsPlugin(),
|
||||||
],
|
],
|
||||||
server: {
|
server: {
|
||||||
fs: {
|
fs: {
|
||||||
@ -156,6 +160,7 @@ function pwa(): PwaOptions {
|
|||||||
registerType: 'autoUpdate',
|
registerType: 'autoUpdate',
|
||||||
workbox: {
|
workbox: {
|
||||||
globPatterns: ['**/*.{css,js,html,svg,png,ico,txt,woff2}'],
|
globPatterns: ['**/*.{css,js,html,svg,png,ico,txt,woff2}'],
|
||||||
|
maximumFileSizeToCacheInBytes: 5 * 1024 * 1024,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -15,11 +15,12 @@ import 'virtual:group-icons.css';
|
|||||||
import '@nolebase/vitepress-plugin-git-changelog/client/style.css';
|
import '@nolebase/vitepress-plugin-git-changelog/client/style.css';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
enhanceApp(ctx: EnhanceAppContext) {
|
async enhanceApp(ctx: EnhanceAppContext) {
|
||||||
const { app } = ctx;
|
const { app } = ctx;
|
||||||
app.component('VbenContributors', VbenContributors);
|
app.component('VbenContributors', VbenContributors);
|
||||||
app.component('DemoPreview', DemoPreview);
|
app.component('DemoPreview', DemoPreview);
|
||||||
app.use(NolebaseGitChangelogPlugin);
|
app.use(NolebaseGitChangelogPlugin);
|
||||||
|
|
||||||
// 百度统计
|
// 百度统计
|
||||||
initHmPlugin();
|
initHmPlugin();
|
||||||
},
|
},
|
||||||
|
@ -8,12 +8,16 @@
|
|||||||
"docs:preview": "vitepress preview"
|
"docs:preview": "vitepress preview"
|
||||||
},
|
},
|
||||||
"imports": {
|
"imports": {
|
||||||
"#/*": "./src/_env/*"
|
"#/*": {
|
||||||
|
"node": "./src/_env/node/*",
|
||||||
|
"default": "./src/_env/*"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vben-core/shadcn-ui": "workspace:*",
|
"@vben-core/shadcn-ui": "workspace:*",
|
||||||
"@vben/common-ui": "workspace:*",
|
"@vben/common-ui": "workspace:*",
|
||||||
"@vben/locales": "workspace:*",
|
"@vben/locales": "workspace:*",
|
||||||
|
"@vben/plugins": "workspace:*",
|
||||||
"@vben/styles": "workspace:*",
|
"@vben/styles": "workspace:*",
|
||||||
"ant-design-vue": "catalog:",
|
"ant-design-vue": "catalog:",
|
||||||
"lucide-vue-next": "catalog:",
|
"lucide-vue-next": "catalog:",
|
||||||
|
@ -1 +0,0 @@
|
|||||||
export * from './form';
|
|
70
docs/src/_env/adapter/vxe-table.ts
Normal file
70
docs/src/_env/adapter/vxe-table.ts
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
import { h } from 'vue';
|
||||||
|
|
||||||
|
import { setupVbenVxeTable, useVbenVxeGrid } from '@vben/plugins/vxe-table';
|
||||||
|
|
||||||
|
import { Button, Image } from 'ant-design-vue';
|
||||||
|
|
||||||
|
import { useVbenForm } from './form';
|
||||||
|
|
||||||
|
if (!import.meta.env.SSR) {
|
||||||
|
setupVbenVxeTable({
|
||||||
|
configVxeTable: (vxeUI) => {
|
||||||
|
vxeUI.setConfig({
|
||||||
|
grid: {
|
||||||
|
align: 'center',
|
||||||
|
border: false,
|
||||||
|
columnConfig: {
|
||||||
|
resizable: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
formConfig: {
|
||||||
|
// 全局禁用vxe-table的表单配置,使用formOptions
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
minHeight: 180,
|
||||||
|
proxyConfig: {
|
||||||
|
autoLoad: true,
|
||||||
|
response: {
|
||||||
|
result: 'items',
|
||||||
|
total: 'total',
|
||||||
|
list: 'items',
|
||||||
|
},
|
||||||
|
showActiveMsg: true,
|
||||||
|
showResponseMsg: false,
|
||||||
|
},
|
||||||
|
round: true,
|
||||||
|
showOverflow: true,
|
||||||
|
size: 'small',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 表格配置项可以用 cellRender: { name: 'CellImage' },
|
||||||
|
vxeUI.renderer.add('CellImage', {
|
||||||
|
renderTableDefault(_renderOpts, params) {
|
||||||
|
const { column, row } = params;
|
||||||
|
return h(Image, { src: row[column.field] });
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 表格配置项可以用 cellRender: { name: 'CellLink' },
|
||||||
|
vxeUI.renderer.add('CellLink', {
|
||||||
|
renderTableDefault(renderOpts) {
|
||||||
|
const { props } = renderOpts;
|
||||||
|
return h(
|
||||||
|
Button,
|
||||||
|
{ size: 'small', type: 'link' },
|
||||||
|
{ default: () => props?.text },
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 这里可以自行扩展 vxe-table 的全局配置,比如自定义格式化
|
||||||
|
// vxeUI.formats.add
|
||||||
|
},
|
||||||
|
useVbenForm,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export { useVbenVxeGrid };
|
||||||
|
|
||||||
|
export type * from '@vben/plugins/vxe-table';
|
4
docs/src/_env/node/adapter/form.ts
Normal file
4
docs/src/_env/node/adapter/form.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export const useVbenForm = () => {};
|
||||||
|
export const z = {};
|
||||||
|
export type VbenFormSchema = any;
|
||||||
|
export type VbenFormProps = any;
|
3
docs/src/_env/node/adapter/vxe-table.ts
Normal file
3
docs/src/_env/node/adapter/vxe-table.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export type * from '@vben/plugins/vxe-table';
|
||||||
|
|
||||||
|
export const useVbenVxeGrid = () => {};
|
@ -4,4 +4,237 @@ outline: deep
|
|||||||
|
|
||||||
# Vben Vxe Table 表格
|
# Vben Vxe Table 表格
|
||||||
|
|
||||||
文档待补充,如果需要使用,可先行查看 vxe-table 文档和 示例代码,内部有部分注释。
|
框架提供的Table 列表组件基于 [vxe-table](https://vxetable.cn/v4/#/grid/api?apiKey=grid),结合`Vben Form 表单`进行了二次封装。
|
||||||
|
|
||||||
|
其中,表头的 **表单搜索** 部分采用了`Vben Form表单`,表格主体部分使用了`vxe-grid`组件,支持表格的分页、排序、筛选等功能。
|
||||||
|
|
||||||
|
> 如果文档内没有参数说明,可以尝试在在线示例或者在 [vxe-grid 官方API 文档](https://vxetable.cn/v4/#/grid/api?apiKey=grid) 内寻找
|
||||||
|
|
||||||
|
::: info 写在前面
|
||||||
|
|
||||||
|
如果你觉得现有组件的封装不够理想,或者不完全符合你的需求,大可以直接使用原生组件,亦或亲手封装一个适合的组件。框架提供的组件并非束缚,使用与否,完全取决于你的需求与自由。
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
## 适配器
|
||||||
|
|
||||||
|
表格底层使用 [vxe-table](https://vxetable.cn/#/start/install) 进行实现,所以你可以使用 `vxe-table` 的所有功能。对于不同的 UI 框架,我们提供了适配器,以便更好的适配不同的 UI 框架。
|
||||||
|
|
||||||
|
### 适配器说明
|
||||||
|
|
||||||
|
每个应用都可以自己配置`vxe-table`的适配器,你可以根据自己的需求。下面是一个简单的配置示例:
|
||||||
|
|
||||||
|
::: details vxe-table 表格适配器
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { h } from 'vue';
|
||||||
|
|
||||||
|
import { setupVbenVxeTable, useVbenVxeGrid } from '@vben/plugins/vxe-table';
|
||||||
|
|
||||||
|
import { Button, Image } from 'ant-design-vue';
|
||||||
|
|
||||||
|
import { useVbenForm } from './form';
|
||||||
|
|
||||||
|
setupVbenVxeTable({
|
||||||
|
configVxeTable: (vxeUI) => {
|
||||||
|
vxeUI.setConfig({
|
||||||
|
grid: {
|
||||||
|
align: 'center',
|
||||||
|
border: false,
|
||||||
|
columnConfig: {
|
||||||
|
resizable: true,
|
||||||
|
},
|
||||||
|
minHeight: 180,
|
||||||
|
formConfig: {
|
||||||
|
// 全局禁用vxe-table的表单配置,使用formOptions
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
proxyConfig: {
|
||||||
|
autoLoad: true,
|
||||||
|
response: {
|
||||||
|
result: 'items',
|
||||||
|
total: 'total',
|
||||||
|
list: 'items',
|
||||||
|
},
|
||||||
|
showActiveMsg: true,
|
||||||
|
showResponseMsg: false,
|
||||||
|
},
|
||||||
|
round: true,
|
||||||
|
showOverflow: true,
|
||||||
|
size: 'small',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 表格配置项可以用 cellRender: { name: 'CellImage' },
|
||||||
|
vxeUI.renderer.add('CellImage', {
|
||||||
|
renderTableDefault(_renderOpts, params) {
|
||||||
|
const { column, row } = params;
|
||||||
|
return h(Image, { src: row[column.field] });
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 表格配置项可以用 cellRender: { name: 'CellLink' },
|
||||||
|
vxeUI.renderer.add('CellLink', {
|
||||||
|
renderTableDefault(renderOpts) {
|
||||||
|
const { props } = renderOpts;
|
||||||
|
return h(
|
||||||
|
Button,
|
||||||
|
{ size: 'small', type: 'link' },
|
||||||
|
{ default: () => props?.text },
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 这里可以自行扩展 vxe-table 的全局配置,比如自定义格式化
|
||||||
|
// vxeUI.formats.add
|
||||||
|
},
|
||||||
|
useVbenForm,
|
||||||
|
});
|
||||||
|
|
||||||
|
export { useVbenVxeGrid };
|
||||||
|
|
||||||
|
export type * from '@vben/plugins/vxe-table';
|
||||||
|
```
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
## 基础表格
|
||||||
|
|
||||||
|
使用 `useVbenVxeGrid` 创建最基础的表格。
|
||||||
|
|
||||||
|
<DemoPreview dir="demos/vben-vxe-table/basic" />
|
||||||
|
|
||||||
|
## 远程加载
|
||||||
|
|
||||||
|
通过指定 `proxyConfig.ajax` 的 `query` 方法,可以实现远程加载数据。
|
||||||
|
|
||||||
|
<DemoPreview dir="demos/vben-vxe-table/remote" />
|
||||||
|
|
||||||
|
## 树形表格
|
||||||
|
|
||||||
|
树形表格,的数据源为扁平结构,可以指定`treeConfig`配置项,实现树形表格。
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
treeConfig: {
|
||||||
|
transform: true, // 指定表格为树形表格
|
||||||
|
parentField: 'parentId', // 父节点字段名
|
||||||
|
rowField: 'id', // 行数据字段名
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
<DemoPreview dir="demos/vben-vxe-table/tree" />
|
||||||
|
|
||||||
|
## 固定表头/列
|
||||||
|
|
||||||
|
列固定可选参数: `'left' | 'right' | '' | null`
|
||||||
|
|
||||||
|
<DemoPreview dir="demos/vben-vxe-table/fixed" />
|
||||||
|
|
||||||
|
## 自定义单元格
|
||||||
|
|
||||||
|
自定义单元格有两种实现方式
|
||||||
|
|
||||||
|
- 通过 `slots` 插槽
|
||||||
|
- 通过 `customCell` 自定义单元格,但是要先添加渲染器
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// 表格配置项可以用 cellRender: { name: 'CellImage' },
|
||||||
|
vxeUI.renderer.add('CellImage', {
|
||||||
|
renderDefault(_renderOpts, params) {
|
||||||
|
const { column, row } = params;
|
||||||
|
return h(Image, { src: row[column.field] } as any); // 注意此处的Image 组件,来源于Antd,需要自行引入,否则会使用js的Image类
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 表格配置项可以用 cellRender: { name: 'CellLink' },
|
||||||
|
vxeUI.renderer.add('CellLink', {
|
||||||
|
renderDefault(renderOpts) {
|
||||||
|
const { props } = renderOpts;
|
||||||
|
return h(
|
||||||
|
Button,
|
||||||
|
{ size: 'small', type: 'link' },
|
||||||
|
{ default: () => props?.text },
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
<DemoPreview dir="demos/vben-vxe-table/custom-cell" />
|
||||||
|
|
||||||
|
## 搜索表单
|
||||||
|
|
||||||
|
**表单搜索** 部分采用了`Vben Form 表单`,参考 [Vben Form 表单文档](/components/common-ui/vben-form)。
|
||||||
|
|
||||||
|
<DemoPreview dir="demos/vben-vxe-table/form" />
|
||||||
|
|
||||||
|
## 单元格编辑
|
||||||
|
|
||||||
|
通过指定`editConfig.mode`为`cell`,可以实现单元格编辑。
|
||||||
|
|
||||||
|
<DemoPreview dir="demos/vben-vxe-table/edit-cell" />
|
||||||
|
|
||||||
|
## 行编辑
|
||||||
|
|
||||||
|
通过指定`editConfig.mode`为`row`,可以实现行编辑。
|
||||||
|
|
||||||
|
<DemoPreview dir="demos/vben-vxe-table/edit-row" />
|
||||||
|
|
||||||
|
## 虚拟滚动
|
||||||
|
|
||||||
|
通过 scroll-y.enabled 与 scroll-y.gt 组合开启,其中 enabled 为总开关,gt 是指当总行数大于指定行数时自动开启。
|
||||||
|
|
||||||
|
> 参考 [vxe-table 官方文档 - 虚拟滚动](https://vxetable.cn/v4/#/component/grid/scroll/vertical)。
|
||||||
|
|
||||||
|
<DemoPreview dir="demos/vben-vxe-table/virtual" />
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
`useVbenVxeGrid` 返回一个数组,第一个元素是表格组件,第二个元素是表格的方法。
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
|
|
||||||
|
// Grid 为表格组件
|
||||||
|
// gridApi 为表格的方法
|
||||||
|
const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
|
gridOptions: {},
|
||||||
|
formOptions: {},
|
||||||
|
gridEvents: {},
|
||||||
|
// 属性
|
||||||
|
// 事件
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Grid />
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
|
### GridApi
|
||||||
|
|
||||||
|
useVbenVxeGrid 返回的第二个参数,是一个对象,包含了一些表单的方法。
|
||||||
|
|
||||||
|
| 方法名 | 描述 | 类型 |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| setLoading | 设置loading状态 | `(loading)=>void` |
|
||||||
|
| setGridOptions | 设置vxe-table grid组件参数 | `(options: Partial<VxeGridProps['gridOptions'])=>void` |
|
||||||
|
| reload | 重载表格,会进行初始化 | `(params:any)=>void` |
|
||||||
|
| query | 重载表格,会保留当前分页 | `(params:any)=>void` |
|
||||||
|
| grid | vxe-table grid实例 | `VxeGridInstance` |
|
||||||
|
| formApi | vbenForm api实例 | `FormApi` |
|
||||||
|
|
||||||
|
### Props
|
||||||
|
|
||||||
|
## Props
|
||||||
|
|
||||||
|
所有属性都可以传入 `useVbenVxeGrid` 的第一个参数中。
|
||||||
|
|
||||||
|
| 属性名 | 描述 | 类型 |
|
||||||
|
| -------------- | ------------------ | ------------------- |
|
||||||
|
| tableTitle | 表格标题 | `string` |
|
||||||
|
| tableTitleHelp | 表格标题帮助信息 | `string` |
|
||||||
|
| gridClass | grid组件的class | `string` |
|
||||||
|
| gridOptions | grid组件的参数 | `VxeTableGridProps` |
|
||||||
|
| gridEvents | grid组件的触发的⌚️ | `VxeGridListeners` |
|
||||||
|
| formOptions | 表单参数 | `VbenFormProps` |
|
||||||
|
85
docs/src/demos/vben-vxe-table/basic/index.vue
Normal file
85
docs/src/demos/vben-vxe-table/basic/index.vue
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import type { VxeGridListeners, VxeGridProps } from '#/adapter/vxe-table';
|
||||||
|
|
||||||
|
import { Button, message } from 'ant-design-vue';
|
||||||
|
|
||||||
|
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
|
|
||||||
|
import { MOCK_TABLE_DATA } from '../table-data';
|
||||||
|
|
||||||
|
interface RowType {
|
||||||
|
address: string;
|
||||||
|
age: number;
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
nickname: string;
|
||||||
|
role: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const gridOptions: VxeGridProps<RowType> = {
|
||||||
|
columns: [
|
||||||
|
{ title: '序号', type: 'seq', width: 50 },
|
||||||
|
{ field: 'name', title: 'Name' },
|
||||||
|
{ field: 'age', sortable: true, title: 'Age' },
|
||||||
|
{ field: 'nickname', title: 'Nickname' },
|
||||||
|
{ field: 'role', title: 'Role' },
|
||||||
|
{ field: 'address', showOverflow: true, title: 'Address' },
|
||||||
|
],
|
||||||
|
data: MOCK_TABLE_DATA,
|
||||||
|
pagerConfig: {
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
sortConfig: {
|
||||||
|
multiple: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const gridEvents: VxeGridListeners<RowType> = {
|
||||||
|
cellClick: ({ row }) => {
|
||||||
|
message.info(`cell-click: ${row.name}`);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const [Grid, gridApi] = useVbenVxeGrid({ gridEvents, gridOptions });
|
||||||
|
|
||||||
|
const showBorder = gridApi.useStore((state) => state.gridOptions?.border);
|
||||||
|
const showStripe = gridApi.useStore((state) => state.gridOptions?.stripe);
|
||||||
|
|
||||||
|
function changeBorder() {
|
||||||
|
gridApi.setGridOptions({
|
||||||
|
border: !showBorder.value,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeStripe() {
|
||||||
|
gridApi.setGridOptions({
|
||||||
|
stripe: !showStripe.value,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeLoading() {
|
||||||
|
gridApi.setLoading(true);
|
||||||
|
setTimeout(() => {
|
||||||
|
gridApi.setLoading(false);
|
||||||
|
}, 2000);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<!-- 此处的`vp-raw` 是为了适配文档的展示效果,实际使用时不需要 -->
|
||||||
|
<div class="vp-raw w-full">
|
||||||
|
<Grid>
|
||||||
|
<template #toolbar-tools>
|
||||||
|
<Button class="mr-2" type="primary" @click="changeBorder">
|
||||||
|
{{ showBorder ? '隐藏' : '显示' }}边框
|
||||||
|
</Button>
|
||||||
|
<Button class="mr-2" type="primary" @click="changeLoading">
|
||||||
|
显示loading
|
||||||
|
</Button>
|
||||||
|
<Button class="mr-2" type="primary" @click="changeStripe">
|
||||||
|
{{ showStripe ? '隐藏' : '显示' }}斑马纹
|
||||||
|
</Button>
|
||||||
|
</template>
|
||||||
|
</Grid>
|
||||||
|
</div>
|
||||||
|
</template>
|
105
docs/src/demos/vben-vxe-table/custom-cell/index.vue
Normal file
105
docs/src/demos/vben-vxe-table/custom-cell/index.vue
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import type { VxeGridProps } from '#/adapter/vxe-table';
|
||||||
|
|
||||||
|
import { Button, Image, Switch, Tag } from 'ant-design-vue';
|
||||||
|
|
||||||
|
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
|
|
||||||
|
import { getExampleTableApi } from '../mock-api';
|
||||||
|
|
||||||
|
interface RowType {
|
||||||
|
category: string;
|
||||||
|
color: string;
|
||||||
|
id: string;
|
||||||
|
imageUrl: string;
|
||||||
|
open: boolean;
|
||||||
|
price: string;
|
||||||
|
productName: string;
|
||||||
|
releaseDate: string;
|
||||||
|
status: 'error' | 'success' | 'warning';
|
||||||
|
}
|
||||||
|
|
||||||
|
const gridOptions: VxeGridProps<RowType> = {
|
||||||
|
checkboxConfig: {
|
||||||
|
highlight: true,
|
||||||
|
labelField: 'name',
|
||||||
|
},
|
||||||
|
columns: [
|
||||||
|
{ title: '序号', type: 'seq', width: 50 },
|
||||||
|
{ field: 'category', title: 'Category', width: 100 },
|
||||||
|
{
|
||||||
|
field: 'imageUrl',
|
||||||
|
slots: { default: 'image-url' },
|
||||||
|
title: 'Image',
|
||||||
|
width: 100,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cellRender: { name: 'CellImage' },
|
||||||
|
field: 'imageUrl2',
|
||||||
|
title: 'Render Image',
|
||||||
|
width: 130,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'open',
|
||||||
|
slots: { default: 'open' },
|
||||||
|
title: 'Open',
|
||||||
|
width: 100,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'status',
|
||||||
|
slots: { default: 'status' },
|
||||||
|
title: 'Status',
|
||||||
|
width: 100,
|
||||||
|
},
|
||||||
|
{ field: 'color', title: 'Color', width: 100 },
|
||||||
|
{ field: 'productName', title: 'Product Name', width: 200 },
|
||||||
|
{ field: 'price', title: 'Price', width: 100 },
|
||||||
|
{
|
||||||
|
field: 'releaseDate',
|
||||||
|
formatter: 'formatDateTime',
|
||||||
|
title: 'Date',
|
||||||
|
width: 200,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cellRender: { name: 'CellLink', props: { text: '编辑' } },
|
||||||
|
field: 'action',
|
||||||
|
fixed: 'right',
|
||||||
|
title: '操作',
|
||||||
|
width: 120,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
keepSource: true,
|
||||||
|
pagerConfig: {},
|
||||||
|
proxyConfig: {
|
||||||
|
ajax: {
|
||||||
|
query: async ({ page }) => {
|
||||||
|
return await getExampleTableApi({
|
||||||
|
page: page.currentPage,
|
||||||
|
pageSize: page.pageSize,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const [Grid] = useVbenVxeGrid({ gridOptions });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="vp-raw w-full">
|
||||||
|
<Grid>
|
||||||
|
<template #image-url="{ row }">
|
||||||
|
<Image :src="row.imageUrl" height="30" width="30" />
|
||||||
|
</template>
|
||||||
|
<template #open="{ row }">
|
||||||
|
<Switch v-model:checked="row.open" />
|
||||||
|
</template>
|
||||||
|
<template #status="{ row }">
|
||||||
|
<Tag :color="row.color">{{ row.status }}</Tag>
|
||||||
|
</template>
|
||||||
|
<template #action>
|
||||||
|
<Button type="link">编辑</Button>
|
||||||
|
</template>
|
||||||
|
</Grid>
|
||||||
|
</div>
|
||||||
|
</template>
|
55
docs/src/demos/vben-vxe-table/edit-cell/index.vue
Normal file
55
docs/src/demos/vben-vxe-table/edit-cell/index.vue
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import type { VxeGridProps } from '#/adapter/vxe-table';
|
||||||
|
|
||||||
|
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
|
|
||||||
|
import { getExampleTableApi } from '../mock-api';
|
||||||
|
|
||||||
|
interface RowType {
|
||||||
|
category: string;
|
||||||
|
color: string;
|
||||||
|
id: string;
|
||||||
|
price: string;
|
||||||
|
productName: string;
|
||||||
|
releaseDate: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const gridOptions: VxeGridProps<RowType> = {
|
||||||
|
columns: [
|
||||||
|
{ title: '序号', type: 'seq', width: 50 },
|
||||||
|
{ editRender: { name: 'input' }, field: 'category', title: 'Category' },
|
||||||
|
{ editRender: { name: 'input' }, field: 'color', title: 'Color' },
|
||||||
|
{
|
||||||
|
editRender: { name: 'input' },
|
||||||
|
field: 'productName',
|
||||||
|
title: 'Product Name',
|
||||||
|
},
|
||||||
|
{ field: 'price', title: 'Price' },
|
||||||
|
{ field: 'releaseDate', formatter: 'formatDateTime', title: 'Date' },
|
||||||
|
],
|
||||||
|
editConfig: {
|
||||||
|
mode: 'cell',
|
||||||
|
trigger: 'click',
|
||||||
|
},
|
||||||
|
pagerConfig: {},
|
||||||
|
proxyConfig: {
|
||||||
|
ajax: {
|
||||||
|
query: async ({ page }) => {
|
||||||
|
return await getExampleTableApi({
|
||||||
|
page: page.currentPage,
|
||||||
|
pageSize: page.pageSize,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
showOverflow: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
const [Grid] = useVbenVxeGrid({ gridOptions });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="vp-raw w-full">
|
||||||
|
<Grid />
|
||||||
|
</div>
|
||||||
|
</template>
|
92
docs/src/demos/vben-vxe-table/edit-row/index.vue
Normal file
92
docs/src/demos/vben-vxe-table/edit-row/index.vue
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import type { VxeGridProps } from '#/adapter/vxe-table';
|
||||||
|
|
||||||
|
import { Button, message } from 'ant-design-vue';
|
||||||
|
|
||||||
|
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
|
|
||||||
|
import { getExampleTableApi } from '../mock-api';
|
||||||
|
|
||||||
|
interface RowType {
|
||||||
|
category: string;
|
||||||
|
color: string;
|
||||||
|
id: string;
|
||||||
|
price: string;
|
||||||
|
productName: string;
|
||||||
|
releaseDate: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const gridOptions: VxeGridProps<RowType> = {
|
||||||
|
columns: [
|
||||||
|
{ title: '序号', type: 'seq', width: 50 },
|
||||||
|
{ editRender: { name: 'input' }, field: 'category', title: 'Category' },
|
||||||
|
{ editRender: { name: 'input' }, field: 'color', title: 'Color' },
|
||||||
|
{
|
||||||
|
editRender: { name: 'input' },
|
||||||
|
field: 'productName',
|
||||||
|
title: 'Product Name',
|
||||||
|
},
|
||||||
|
{ field: 'price', title: 'Price' },
|
||||||
|
{ field: 'releaseDate', formatter: 'formatDateTime', title: 'Date' },
|
||||||
|
{ slots: { default: 'action' }, title: '操作' },
|
||||||
|
],
|
||||||
|
editConfig: {
|
||||||
|
mode: 'row',
|
||||||
|
trigger: 'click',
|
||||||
|
},
|
||||||
|
pagerConfig: {},
|
||||||
|
proxyConfig: {
|
||||||
|
ajax: {
|
||||||
|
query: async ({ page }) => {
|
||||||
|
return await getExampleTableApi({
|
||||||
|
page: page.currentPage,
|
||||||
|
pageSize: page.pageSize,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
showOverflow: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
const [Grid, gridApi] = useVbenVxeGrid({ gridOptions });
|
||||||
|
|
||||||
|
function hasEditStatus(row: RowType) {
|
||||||
|
return gridApi.grid?.isEditByRow(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
function editRowEvent(row: RowType) {
|
||||||
|
gridApi.grid?.setEditRow(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function saveRowEvent(row: RowType) {
|
||||||
|
await gridApi.grid?.clearEdit();
|
||||||
|
|
||||||
|
gridApi.setLoading(true);
|
||||||
|
setTimeout(() => {
|
||||||
|
gridApi.setLoading(false);
|
||||||
|
message.success({
|
||||||
|
content: `保存成功!category=${row.category}`,
|
||||||
|
});
|
||||||
|
}, 600);
|
||||||
|
}
|
||||||
|
|
||||||
|
const cancelRowEvent = (_row: RowType) => {
|
||||||
|
gridApi.grid?.clearEdit();
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="vp-raw w-full">
|
||||||
|
<Grid>
|
||||||
|
<template #action="{ row }">
|
||||||
|
<template v-if="hasEditStatus(row)">
|
||||||
|
<Button type="link" @click="saveRowEvent(row)">保存</Button>
|
||||||
|
<Button type="link" @click="cancelRowEvent(row)">取消</Button>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<Button type="link" @click="editRowEvent(row)">编辑</Button>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</Grid>
|
||||||
|
</div>
|
||||||
|
</template>
|
67
docs/src/demos/vben-vxe-table/fixed/index.vue
Normal file
67
docs/src/demos/vben-vxe-table/fixed/index.vue
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import type { VxeGridProps } from '#/adapter/vxe-table';
|
||||||
|
|
||||||
|
import { Button } from 'ant-design-vue';
|
||||||
|
|
||||||
|
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
|
|
||||||
|
import { getExampleTableApi } from '../mock-api';
|
||||||
|
|
||||||
|
interface RowType {
|
||||||
|
category: string;
|
||||||
|
color: string;
|
||||||
|
id: string;
|
||||||
|
price: string;
|
||||||
|
productName: string;
|
||||||
|
releaseDate: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const gridOptions: VxeGridProps<RowType> = {
|
||||||
|
columns: [
|
||||||
|
{ fixed: 'left', title: '序号', type: 'seq', width: 50 },
|
||||||
|
{ field: 'category', title: 'Category', width: 300 },
|
||||||
|
{ field: 'color', title: 'Color', width: 300 },
|
||||||
|
{ field: 'productName', title: 'Product Name', width: 300 },
|
||||||
|
{ field: 'price', title: 'Price', width: 300 },
|
||||||
|
{
|
||||||
|
field: 'releaseDate',
|
||||||
|
formatter: 'formatDateTime',
|
||||||
|
title: 'DateTime',
|
||||||
|
width: 500,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'action',
|
||||||
|
fixed: 'right',
|
||||||
|
slots: { default: 'action' },
|
||||||
|
title: '操作',
|
||||||
|
width: 120,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
pagerConfig: {},
|
||||||
|
proxyConfig: {
|
||||||
|
ajax: {
|
||||||
|
query: async ({ page }) => {
|
||||||
|
return await getExampleTableApi({
|
||||||
|
page: page.currentPage,
|
||||||
|
pageSize: page.pageSize,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rowConfig: {
|
||||||
|
isHover: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const [Grid] = useVbenVxeGrid({ gridOptions });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="vp-raw w-full">
|
||||||
|
<Grid>
|
||||||
|
<template #action>
|
||||||
|
<Button type="link">编辑</Button>
|
||||||
|
</template>
|
||||||
|
</Grid>
|
||||||
|
</div>
|
||||||
|
</template>
|
120
docs/src/demos/vben-vxe-table/form/index.vue
Normal file
120
docs/src/demos/vben-vxe-table/form/index.vue
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import type { VbenFormProps } from '#/adapter/form';
|
||||||
|
import type { VxeGridProps } from '#/adapter/vxe-table';
|
||||||
|
|
||||||
|
import { message } from 'ant-design-vue';
|
||||||
|
|
||||||
|
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
|
|
||||||
|
import { getExampleTableApi } from '../mock-api';
|
||||||
|
|
||||||
|
interface RowType {
|
||||||
|
category: string;
|
||||||
|
color: string;
|
||||||
|
id: string;
|
||||||
|
price: string;
|
||||||
|
productName: string;
|
||||||
|
releaseDate: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const formOptions: VbenFormProps = {
|
||||||
|
// 默认展开
|
||||||
|
collapsed: false,
|
||||||
|
schema: [
|
||||||
|
{
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: 'Please enter category',
|
||||||
|
},
|
||||||
|
defaultValue: '1',
|
||||||
|
fieldName: 'category',
|
||||||
|
label: 'Category',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: 'Please enter productName',
|
||||||
|
},
|
||||||
|
fieldName: 'productName',
|
||||||
|
label: 'ProductName',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: 'Please enter price',
|
||||||
|
},
|
||||||
|
fieldName: 'price',
|
||||||
|
label: 'Price',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'Select',
|
||||||
|
componentProps: {
|
||||||
|
allowClear: true,
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
label: 'Color1',
|
||||||
|
value: '1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Color2',
|
||||||
|
value: '2',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
placeholder: '请选择',
|
||||||
|
},
|
||||||
|
fieldName: 'color',
|
||||||
|
label: 'Color',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'DatePicker',
|
||||||
|
fieldName: 'datePicker',
|
||||||
|
label: 'Date',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
// 控制表单是否显示折叠按钮
|
||||||
|
showCollapseButton: true,
|
||||||
|
submitButtonOptions: {
|
||||||
|
content: '查询',
|
||||||
|
},
|
||||||
|
// 按下回车时是否提交表单
|
||||||
|
submitOnEnter: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
const gridOptions: VxeGridProps<RowType> = {
|
||||||
|
checkboxConfig: {
|
||||||
|
highlight: true,
|
||||||
|
labelField: 'name',
|
||||||
|
},
|
||||||
|
columns: [
|
||||||
|
{ title: '序号', type: 'seq', width: 50 },
|
||||||
|
{ align: 'left', title: 'Name', type: 'checkbox', width: 100 },
|
||||||
|
{ field: 'category', title: 'Category' },
|
||||||
|
{ field: 'color', title: 'Color' },
|
||||||
|
{ field: 'productName', title: 'Product Name' },
|
||||||
|
{ field: 'price', title: 'Price' },
|
||||||
|
{ field: 'releaseDate', formatter: 'formatDateTime', title: 'Date' },
|
||||||
|
],
|
||||||
|
keepSource: true,
|
||||||
|
pagerConfig: {},
|
||||||
|
proxyConfig: {
|
||||||
|
ajax: {
|
||||||
|
query: async ({ page }, formValues) => {
|
||||||
|
message.success(`Query params: ${JSON.stringify(formValues)}`);
|
||||||
|
return await getExampleTableApi({
|
||||||
|
page: page.currentPage,
|
||||||
|
pageSize: page.pageSize,
|
||||||
|
...formValues,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const [Grid] = useVbenVxeGrid({ formOptions, gridOptions });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="vp-raw w-full">
|
||||||
|
<Grid />
|
||||||
|
</div>
|
||||||
|
</template>
|
36
docs/src/demos/vben-vxe-table/mock-api.ts
Normal file
36
docs/src/demos/vben-vxe-table/mock-api.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import { MOCK_API_DATA } from './table-data';
|
||||||
|
|
||||||
|
export namespace DemoTableApi {
|
||||||
|
export interface PageFetchParams {
|
||||||
|
[key: string]: any;
|
||||||
|
page: number;
|
||||||
|
pageSize: number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function sleep(time = 1000) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
resolve(true);
|
||||||
|
}, time);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取示例表格数据
|
||||||
|
*/
|
||||||
|
async function getExampleTableApi(params: DemoTableApi.PageFetchParams) {
|
||||||
|
return new Promise<{ items: any; total: number }>((resolve) => {
|
||||||
|
const { page, pageSize } = params;
|
||||||
|
const items = MOCK_API_DATA.slice((page - 1) * pageSize, page * pageSize);
|
||||||
|
|
||||||
|
sleep(1000).then(() => {
|
||||||
|
resolve({
|
||||||
|
total: items.length,
|
||||||
|
items,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export { getExampleTableApi };
|
112
docs/src/demos/vben-vxe-table/remote/index.vue
Normal file
112
docs/src/demos/vben-vxe-table/remote/index.vue
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import type { DemoTableApi } from '../mock-api';
|
||||||
|
|
||||||
|
import type { VxeGridProps } from '#/adapter/vxe-table';
|
||||||
|
|
||||||
|
import { Button } from 'ant-design-vue';
|
||||||
|
|
||||||
|
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
|
|
||||||
|
import { MOCK_API_DATA } from '../table-data';
|
||||||
|
|
||||||
|
interface RowType {
|
||||||
|
category: string;
|
||||||
|
color: string;
|
||||||
|
id: string;
|
||||||
|
price: string;
|
||||||
|
productName: string;
|
||||||
|
releaseDate: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 数据实例
|
||||||
|
// const MOCK_TREE_TABLE_DATA = [
|
||||||
|
// {
|
||||||
|
// date: '2020-08-01',
|
||||||
|
// id: 10_000,
|
||||||
|
// name: 'Test1',
|
||||||
|
// parentId: null,
|
||||||
|
// size: 1024,
|
||||||
|
// type: 'mp3',
|
||||||
|
// },
|
||||||
|
// ]
|
||||||
|
|
||||||
|
const sleep = (time = 1000) => {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
resolve(true);
|
||||||
|
}, time);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取示例表格数据
|
||||||
|
*/
|
||||||
|
async function getExampleTableApi(params: DemoTableApi.PageFetchParams) {
|
||||||
|
return new Promise<{ items: any; total: number }>((resolve) => {
|
||||||
|
const { page, pageSize } = params;
|
||||||
|
const items = MOCK_API_DATA.slice((page - 1) * pageSize, page * pageSize);
|
||||||
|
|
||||||
|
sleep(1000).then(() => {
|
||||||
|
resolve({
|
||||||
|
total: items.length,
|
||||||
|
items,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const gridOptions: VxeGridProps<RowType> = {
|
||||||
|
checkboxConfig: {
|
||||||
|
highlight: true,
|
||||||
|
labelField: 'name',
|
||||||
|
},
|
||||||
|
columns: [
|
||||||
|
{ title: '序号', type: 'seq', width: 50 },
|
||||||
|
{ align: 'left', title: 'Name', type: 'checkbox', width: 100 },
|
||||||
|
{ field: 'category', title: 'Category' },
|
||||||
|
{ field: 'color', title: 'Color' },
|
||||||
|
{ field: 'productName', title: 'Product Name' },
|
||||||
|
{ field: 'price', title: 'Price' },
|
||||||
|
{ field: 'releaseDate', formatter: 'formatDateTime', title: 'DateTime' },
|
||||||
|
],
|
||||||
|
exportConfig: {},
|
||||||
|
// height: 'auto', // 如果设置为 auto,则必须确保存在父节点且不允许存在相邻元素,否则会出现高度闪动问题
|
||||||
|
keepSource: true,
|
||||||
|
proxyConfig: {
|
||||||
|
ajax: {
|
||||||
|
query: async ({ page }) => {
|
||||||
|
return await getExampleTableApi({
|
||||||
|
page: page.currentPage,
|
||||||
|
pageSize: page.pageSize,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
toolbarConfig: {
|
||||||
|
custom: true,
|
||||||
|
export: true,
|
||||||
|
// import: true,
|
||||||
|
refresh: true,
|
||||||
|
zoom: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
|
gridOptions,
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="vp-raw w-full">
|
||||||
|
<Grid>
|
||||||
|
<template #toolbar-tools>
|
||||||
|
<Button class="mr-2" type="primary" @click="() => gridApi.query()">
|
||||||
|
刷新当前页面
|
||||||
|
</Button>
|
||||||
|
<Button type="primary" @click="() => gridApi.reload()">
|
||||||
|
刷新并返回第一页
|
||||||
|
</Button>
|
||||||
|
</template>
|
||||||
|
</Grid>
|
||||||
|
</div>
|
||||||
|
</template>
|
384
docs/src/demos/vben-vxe-table/table-data.ts
Normal file
384
docs/src/demos/vben-vxe-table/table-data.ts
Normal file
@ -0,0 +1,384 @@
|
|||||||
|
interface TableRowData {
|
||||||
|
address: string;
|
||||||
|
age: number;
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
nickname: string;
|
||||||
|
role: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const roles = ['User', 'Admin', 'Manager', 'Guest'];
|
||||||
|
|
||||||
|
export const MOCK_TABLE_DATA: TableRowData[] = (() => {
|
||||||
|
const data: TableRowData[] = [];
|
||||||
|
for (let i = 0; i < 10; i++) {
|
||||||
|
data.push({
|
||||||
|
address: `New York${i}`,
|
||||||
|
age: i + 1,
|
||||||
|
id: i,
|
||||||
|
name: `Test${i}`,
|
||||||
|
nickname: `Test${i}`,
|
||||||
|
role: roles[Math.floor(Math.random() * roles.length)] as string,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
})();
|
||||||
|
|
||||||
|
export const MOCK_TREE_TABLE_DATA = [
|
||||||
|
{
|
||||||
|
date: '2020-08-01',
|
||||||
|
id: 10_000,
|
||||||
|
name: 'Test1',
|
||||||
|
parentId: null,
|
||||||
|
size: 1024,
|
||||||
|
type: 'mp3',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2021-04-01',
|
||||||
|
id: 10_050,
|
||||||
|
name: 'Test2',
|
||||||
|
parentId: null,
|
||||||
|
size: 0,
|
||||||
|
type: 'mp4',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2020-03-01',
|
||||||
|
id: 24_300,
|
||||||
|
name: 'Test3',
|
||||||
|
parentId: 10_050,
|
||||||
|
size: 1024,
|
||||||
|
type: 'avi',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2021-04-01',
|
||||||
|
id: 20_045,
|
||||||
|
name: 'Test4',
|
||||||
|
parentId: 24_300,
|
||||||
|
size: 600,
|
||||||
|
type: 'html',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2021-04-01',
|
||||||
|
id: 10_053,
|
||||||
|
name: 'Test5',
|
||||||
|
parentId: 24_300,
|
||||||
|
size: 0,
|
||||||
|
type: 'avi',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2021-10-01',
|
||||||
|
id: 24_330,
|
||||||
|
name: 'Test6',
|
||||||
|
parentId: 10_053,
|
||||||
|
size: 25,
|
||||||
|
type: 'txt',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2020-01-01',
|
||||||
|
id: 21_011,
|
||||||
|
name: 'Test7',
|
||||||
|
parentId: 10_053,
|
||||||
|
size: 512,
|
||||||
|
type: 'pdf',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2021-06-01',
|
||||||
|
id: 22_200,
|
||||||
|
name: 'Test8',
|
||||||
|
parentId: 10_053,
|
||||||
|
size: 1024,
|
||||||
|
type: 'js',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2020-11-01',
|
||||||
|
id: 23_666,
|
||||||
|
name: 'Test9',
|
||||||
|
parentId: null,
|
||||||
|
size: 2048,
|
||||||
|
type: 'xlsx',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2021-06-01',
|
||||||
|
id: 23_677,
|
||||||
|
name: 'Test10',
|
||||||
|
parentId: 23_666,
|
||||||
|
size: 1024,
|
||||||
|
type: 'js',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2021-06-01',
|
||||||
|
id: 23_671,
|
||||||
|
name: 'Test11',
|
||||||
|
parentId: 23_677,
|
||||||
|
size: 1024,
|
||||||
|
type: 'js',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2021-06-01',
|
||||||
|
id: 23_672,
|
||||||
|
name: 'Test12',
|
||||||
|
parentId: 23_677,
|
||||||
|
size: 1024,
|
||||||
|
type: 'js',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2021-06-01',
|
||||||
|
id: 23_688,
|
||||||
|
name: 'Test13',
|
||||||
|
parentId: 23_666,
|
||||||
|
size: 1024,
|
||||||
|
type: 'js',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2021-06-01',
|
||||||
|
id: 23_681,
|
||||||
|
name: 'Test14',
|
||||||
|
parentId: 23_688,
|
||||||
|
size: 1024,
|
||||||
|
type: 'js',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2021-06-01',
|
||||||
|
id: 23_682,
|
||||||
|
name: 'Test15',
|
||||||
|
parentId: 23_688,
|
||||||
|
size: 1024,
|
||||||
|
type: 'js',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2020-10-01',
|
||||||
|
id: 24_555,
|
||||||
|
name: 'Test16',
|
||||||
|
parentId: null,
|
||||||
|
size: 224,
|
||||||
|
type: 'avi',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2021-06-01',
|
||||||
|
id: 24_566,
|
||||||
|
name: 'Test17',
|
||||||
|
parentId: 24_555,
|
||||||
|
size: 1024,
|
||||||
|
type: 'js',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2021-06-01',
|
||||||
|
id: 24_577,
|
||||||
|
name: 'Test18',
|
||||||
|
parentId: 24_555,
|
||||||
|
size: 1024,
|
||||||
|
type: 'js',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const MOCK_API_DATA = [
|
||||||
|
{
|
||||||
|
available: true,
|
||||||
|
category: 'Computers',
|
||||||
|
color: 'purple',
|
||||||
|
currency: 'NAD',
|
||||||
|
description:
|
||||||
|
'Ergonomic executive chair upholstered in bonded black leather and PVC padded seat and back for all-day comfort and support',
|
||||||
|
id: '45a613df-227a-4907-a89f-4a7f1252ca0c',
|
||||||
|
imageUrl: 'https://avatars.githubusercontent.com/u/62715097',
|
||||||
|
imageUrl2: 'https://avatars.githubusercontent.com/u/75395683',
|
||||||
|
inProduction: false,
|
||||||
|
open: true,
|
||||||
|
price: '48.89',
|
||||||
|
productName: 'Handcrafted Steel Salad',
|
||||||
|
quantity: 70,
|
||||||
|
rating: 3.780_582_329_574_367,
|
||||||
|
releaseDate: '2024-09-09T04:06:57.793Z',
|
||||||
|
status: 'error',
|
||||||
|
tags: ['Bespoke', 'Handmade', 'Luxurious'],
|
||||||
|
weight: 1.031_015_671_912_002_5,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
available: true,
|
||||||
|
category: 'Toys',
|
||||||
|
color: 'green',
|
||||||
|
currency: 'CZK',
|
||||||
|
description:
|
||||||
|
'The Nagasaki Lander is the trademarked name of several series of Nagasaki sport bikes, that started with the 1984 ABC800J',
|
||||||
|
id: 'd02e5ee9-bc98-4de2-98fa-25a6567ecc19',
|
||||||
|
imageUrl: 'https://avatars.githubusercontent.com/u/51512330',
|
||||||
|
imageUrl2: 'https://avatars.githubusercontent.com/u/58698113',
|
||||||
|
inProduction: false,
|
||||||
|
open: false,
|
||||||
|
price: '68.15',
|
||||||
|
productName: 'Generic Cotton Gloves',
|
||||||
|
quantity: 3,
|
||||||
|
rating: 1.681_749_367_682_703_3,
|
||||||
|
releaseDate: '2024-06-16T09:00:36.806Z',
|
||||||
|
status: 'warning',
|
||||||
|
tags: ['Rustic', 'Handcrafted', 'Recycled'],
|
||||||
|
weight: 9.601_076_149_300_575,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
available: true,
|
||||||
|
category: 'Beauty',
|
||||||
|
color: 'teal',
|
||||||
|
currency: 'OMR',
|
||||||
|
description:
|
||||||
|
'The Apollotech B340 is an affordable wireless mouse with reliable connectivity, 12 months battery life and modern design',
|
||||||
|
id: '2b72521c-225c-4e64-8030-611b76b10b37',
|
||||||
|
imageUrl: 'https://avatars.githubusercontent.com/u/50300075',
|
||||||
|
imageUrl2: 'https://avatars.githubusercontent.com/u/36541691',
|
||||||
|
inProduction: true,
|
||||||
|
open: true,
|
||||||
|
price: '696.94',
|
||||||
|
productName: 'Gorgeous Soft Ball',
|
||||||
|
quantity: 50,
|
||||||
|
rating: 2.361_581_777_372_057_5,
|
||||||
|
releaseDate: '2024-06-03T13:24:19.809Z',
|
||||||
|
status: 'warning',
|
||||||
|
tags: ['Gorgeous', 'Ergonomic', 'Licensed'],
|
||||||
|
weight: 8.882_340_049_286_19,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
available: true,
|
||||||
|
category: 'Games',
|
||||||
|
color: 'silver',
|
||||||
|
currency: 'SOS',
|
||||||
|
description:
|
||||||
|
'Carbonite web goalkeeper gloves are ergonomically designed to give easy fit',
|
||||||
|
id: 'bafab694-3801-452c-b102-9eb519bd1143',
|
||||||
|
imageUrl: 'https://avatars.githubusercontent.com/u/89827115',
|
||||||
|
imageUrl2: 'https://avatars.githubusercontent.com/u/55952747',
|
||||||
|
inProduction: false,
|
||||||
|
open: false,
|
||||||
|
price: '553.84',
|
||||||
|
productName: 'Bespoke Soft Computer',
|
||||||
|
quantity: 29,
|
||||||
|
rating: 2.176_412_873_760_271_7,
|
||||||
|
releaseDate: '2024-09-17T12:16:27.034Z',
|
||||||
|
status: 'error',
|
||||||
|
tags: ['Elegant', 'Rustic', 'Recycled'],
|
||||||
|
weight: 9.653_285_869_978_038,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
available: true,
|
||||||
|
category: 'Toys',
|
||||||
|
color: 'indigo',
|
||||||
|
currency: 'BIF',
|
||||||
|
description:
|
||||||
|
'Andy shoes are designed to keeping in mind durability as well as trends, the most stylish range of shoes & sandals',
|
||||||
|
id: 'bf6dea6b-2a55-441d-8773-937e03d99389',
|
||||||
|
imageUrl: 'https://avatars.githubusercontent.com/u/21431092',
|
||||||
|
imageUrl2: 'https://avatars.githubusercontent.com/u/3771350',
|
||||||
|
inProduction: true,
|
||||||
|
open: true,
|
||||||
|
price: '237.39',
|
||||||
|
productName: 'Handcrafted Cotton Mouse',
|
||||||
|
quantity: 54,
|
||||||
|
rating: 4.363_265_388_265_461,
|
||||||
|
releaseDate: '2023-10-23T13:42:34.947Z',
|
||||||
|
status: 'error',
|
||||||
|
tags: ['Unbranded', 'Handmade', 'Generic'],
|
||||||
|
weight: 9.513_203_612_535_571,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
available: false,
|
||||||
|
category: 'Tools',
|
||||||
|
color: 'violet',
|
||||||
|
currency: 'TZS',
|
||||||
|
description:
|
||||||
|
'New ABC 13 9370, 13.3, 5th Gen CoreA5-8250U, 8GB RAM, 256GB SSD, power UHD Graphics, OS 10 Home, OS Office A & J 2016',
|
||||||
|
id: '135ba6ab-32ee-4989-8189-5cfa658ef970',
|
||||||
|
imageUrl: 'https://avatars.githubusercontent.com/u/29946092',
|
||||||
|
imageUrl2: 'https://avatars.githubusercontent.com/u/23842994',
|
||||||
|
inProduction: false,
|
||||||
|
open: false,
|
||||||
|
price: '825.25',
|
||||||
|
productName: 'Awesome Bronze Ball',
|
||||||
|
quantity: 94,
|
||||||
|
rating: 4.251_159_804_726_753,
|
||||||
|
releaseDate: '2023-12-30T07:31:43.464Z',
|
||||||
|
status: 'warning',
|
||||||
|
tags: ['Handmade', 'Elegant', 'Unbranded'],
|
||||||
|
weight: 2.247_473_385_732_636_8,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
available: true,
|
||||||
|
category: 'Automotive',
|
||||||
|
color: 'teal',
|
||||||
|
currency: 'BOB',
|
||||||
|
description: 'The Football Is Good For Training And Recreational Purposes',
|
||||||
|
id: '652ef256-7d4e-48b7-976c-7afaa781ea92',
|
||||||
|
imageUrl: 'https://avatars.githubusercontent.com/u/2531904',
|
||||||
|
imageUrl2: 'https://avatars.githubusercontent.com/u/15215990',
|
||||||
|
inProduction: false,
|
||||||
|
open: false,
|
||||||
|
price: '780.49',
|
||||||
|
productName: 'Oriental Rubber Pants',
|
||||||
|
quantity: 70,
|
||||||
|
rating: 2.636_323_417_377_916,
|
||||||
|
releaseDate: '2024-02-23T23:30:49.628Z',
|
||||||
|
status: 'success',
|
||||||
|
tags: ['Unbranded', 'Elegant', 'Unbranded'],
|
||||||
|
weight: 4.812_965_858_018_838,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
available: false,
|
||||||
|
category: 'Garden',
|
||||||
|
color: 'plum',
|
||||||
|
currency: 'LRD',
|
||||||
|
description:
|
||||||
|
'The slim & simple Maple Gaming Keyboard from Dev Byte comes with a sleek body and 7- Color RGB LED Back-lighting for smart functionality',
|
||||||
|
id: '3ea24798-6589-40cc-85f0-ab78752244a0',
|
||||||
|
imageUrl: 'https://avatars.githubusercontent.com/u/23165285',
|
||||||
|
imageUrl2: 'https://avatars.githubusercontent.com/u/14595665',
|
||||||
|
inProduction: false,
|
||||||
|
open: true,
|
||||||
|
price: '583.85',
|
||||||
|
productName: 'Handcrafted Concrete Hat',
|
||||||
|
quantity: 15,
|
||||||
|
rating: 1.371_600_527_752_802_7,
|
||||||
|
releaseDate: '2024-03-02T19:40:50.255Z',
|
||||||
|
status: 'error',
|
||||||
|
tags: ['Rustic', 'Sleek', 'Ergonomic'],
|
||||||
|
weight: 4.926_949_366_405_728_4,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
available: false,
|
||||||
|
category: 'Industrial',
|
||||||
|
color: 'salmon',
|
||||||
|
currency: 'AUD',
|
||||||
|
description:
|
||||||
|
'The Apollotech B340 is an affordable wireless mouse with reliable connectivity, 12 months battery life and modern design',
|
||||||
|
id: '997113dd-f6e4-4acc-9790-ef554c7498d1',
|
||||||
|
imageUrl: 'https://avatars.githubusercontent.com/u/49021914',
|
||||||
|
imageUrl2: 'https://avatars.githubusercontent.com/u/4690621',
|
||||||
|
inProduction: true,
|
||||||
|
open: false,
|
||||||
|
price: '67.99',
|
||||||
|
productName: 'Generic Rubber Bacon',
|
||||||
|
quantity: 68,
|
||||||
|
rating: 4.129_840_682_128_08,
|
||||||
|
releaseDate: '2023-12-17T01:40:25.415Z',
|
||||||
|
status: 'error',
|
||||||
|
tags: ['Oriental', 'Small', 'Handcrafted'],
|
||||||
|
weight: 1.080_114_331_801_906_4,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
available: false,
|
||||||
|
category: 'Tools',
|
||||||
|
color: 'sky blue',
|
||||||
|
currency: 'NOK',
|
||||||
|
description:
|
||||||
|
'The Nagasaki Lander is the trademarked name of several series of Nagasaki sport bikes, that started with the 1984 ABC800J',
|
||||||
|
id: 'f697a250-6cb2-46c8-b0f7-871ab1f2fa8d',
|
||||||
|
imageUrl: 'https://avatars.githubusercontent.com/u/95928385',
|
||||||
|
imageUrl2: 'https://avatars.githubusercontent.com/u/47588244',
|
||||||
|
inProduction: false,
|
||||||
|
open: false,
|
||||||
|
price: '613.89',
|
||||||
|
productName: 'Gorgeous Frozen Ball',
|
||||||
|
quantity: 55,
|
||||||
|
rating: 1.646_947_205_998_534_6,
|
||||||
|
releaseDate: '2024-10-13T12:31:04.929Z',
|
||||||
|
status: 'warning',
|
||||||
|
tags: ['Handmade', 'Unbranded', 'Unbranded'],
|
||||||
|
weight: 9.430_690_557_758_114,
|
||||||
|
},
|
||||||
|
];
|
80
docs/src/demos/vben-vxe-table/tree/index.vue
Normal file
80
docs/src/demos/vben-vxe-table/tree/index.vue
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import type { VxeGridProps } from '#/adapter/vxe-table';
|
||||||
|
|
||||||
|
import { Button } from 'ant-design-vue';
|
||||||
|
|
||||||
|
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
|
|
||||||
|
import { MOCK_TREE_TABLE_DATA } from '../table-data';
|
||||||
|
|
||||||
|
interface RowType {
|
||||||
|
date: string;
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
parentId: null | number;
|
||||||
|
size: number;
|
||||||
|
type: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 数据实例
|
||||||
|
// const MOCK_TREE_TABLE_DATA = [
|
||||||
|
// {
|
||||||
|
// date: '2020-08-01',
|
||||||
|
// id: 10_000,
|
||||||
|
// name: 'Test1',
|
||||||
|
// parentId: null,
|
||||||
|
// size: 1024,
|
||||||
|
// type: 'mp3',
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// date: '2021-04-01',
|
||||||
|
// id: 10_050,
|
||||||
|
// name: 'Test2',
|
||||||
|
// parentId: 10_000,
|
||||||
|
// size: 0,
|
||||||
|
// type: 'mp4',
|
||||||
|
// },
|
||||||
|
// ];
|
||||||
|
|
||||||
|
const gridOptions: VxeGridProps<RowType> = {
|
||||||
|
columns: [
|
||||||
|
{ type: 'seq', width: 70 },
|
||||||
|
{ field: 'name', minWidth: 300, title: 'Name', treeNode: true },
|
||||||
|
{ field: 'size', title: 'Size' },
|
||||||
|
{ field: 'type', title: 'Type' },
|
||||||
|
{ field: 'date', title: 'Date' },
|
||||||
|
],
|
||||||
|
data: MOCK_TREE_TABLE_DATA,
|
||||||
|
pagerConfig: {
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
treeConfig: {
|
||||||
|
parentField: 'parentId',
|
||||||
|
rowField: 'id',
|
||||||
|
transform: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const [Grid, gridApi] = useVbenVxeGrid({ gridOptions });
|
||||||
|
|
||||||
|
const expandAll = () => {
|
||||||
|
gridApi.grid?.setAllTreeExpand(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const collapseAll = () => {
|
||||||
|
gridApi.grid?.setAllTreeExpand(false);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="vp-raw h-[300px] w-full">
|
||||||
|
<Grid>
|
||||||
|
<template #toolbar-tools>
|
||||||
|
<Button class="mr-2" type="primary" @click="expandAll">
|
||||||
|
展开全部
|
||||||
|
</Button>
|
||||||
|
<Button type="primary" @click="collapseAll"> 折叠全部 </Button>
|
||||||
|
</template>
|
||||||
|
</Grid>
|
||||||
|
</div>
|
||||||
|
</template>
|
64
docs/src/demos/vben-vxe-table/virtual/index.vue
Normal file
64
docs/src/demos/vben-vxe-table/virtual/index.vue
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import type { VxeGridProps } from '#/adapter/vxe-table';
|
||||||
|
|
||||||
|
import { onMounted } from 'vue';
|
||||||
|
|
||||||
|
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
|
|
||||||
|
interface RowType {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
role: string;
|
||||||
|
sex: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const gridOptions: VxeGridProps<RowType> = {
|
||||||
|
columns: [
|
||||||
|
{ type: 'seq', width: 70 },
|
||||||
|
{ field: 'name', title: 'Name' },
|
||||||
|
{ field: 'role', title: 'Role' },
|
||||||
|
{ field: 'sex', title: 'Sex' },
|
||||||
|
],
|
||||||
|
data: [],
|
||||||
|
height: 'auto',
|
||||||
|
pagerConfig: {
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
scrollY: {
|
||||||
|
enabled: true,
|
||||||
|
gt: 0,
|
||||||
|
},
|
||||||
|
showOverflow: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
const [Grid, gridApi] = useVbenVxeGrid({ gridOptions });
|
||||||
|
|
||||||
|
// 模拟行数据
|
||||||
|
const loadList = (size = 200) => {
|
||||||
|
try {
|
||||||
|
const dataList: RowType[] = [];
|
||||||
|
for (let i = 0; i < size; i++) {
|
||||||
|
dataList.push({
|
||||||
|
id: 10_000 + i,
|
||||||
|
name: `Test${i}`,
|
||||||
|
role: 'Developer',
|
||||||
|
sex: '男',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
gridApi.setGridOptions({ data: dataList });
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to load data:', error);
|
||||||
|
// Implement user-friendly error handling
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
loadList(1000);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="vp-raw h-[500px] w-full">
|
||||||
|
<Grid />
|
||||||
|
</div>
|
||||||
|
</template>
|
@ -164,6 +164,7 @@ import { defineOverridesPreferences } from '@vben/preferences';
|
|||||||
/**
|
/**
|
||||||
* @description 项目配置文件
|
* @description 项目配置文件
|
||||||
* 只需要覆盖项目中的一部分配置,不需要的配置不用覆盖,会自动使用默认配置
|
* 只需要覆盖项目中的一部分配置,不需要的配置不用覆盖,会自动使用默认配置
|
||||||
|
* !!! 更改配置后请清空缓存,否则可能不生效
|
||||||
*/
|
*/
|
||||||
export const overridesPreferences = defineOverridesPreferences({
|
export const overridesPreferences = defineOverridesPreferences({
|
||||||
// overrides
|
// overrides
|
||||||
@ -536,5 +537,4 @@ interface Preferences {
|
|||||||
|
|
||||||
- `overridesPreferences`方法只需要覆盖项目中的一部分配置,不需要的配置不用覆盖,会自动使用默认配置。
|
- `overridesPreferences`方法只需要覆盖项目中的一部分配置,不需要的配置不用覆盖,会自动使用默认配置。
|
||||||
- 任何配置项都可以覆盖,只需要在`overridesPreferences`方法内覆盖即可,不要修改默认配置文件。
|
- 任何配置项都可以覆盖,只需要在`overridesPreferences`方法内覆盖即可,不要修改默认配置文件。
|
||||||
|
- 更改配置后请清空缓存,否则可能不生效。:::
|
||||||
:::
|
|
||||||
|
@ -66,7 +66,9 @@ pnpm install
|
|||||||
|
|
||||||
::: tip 注意
|
::: tip 注意
|
||||||
|
|
||||||
项目只支持使用 `pnpm` 进行依赖安装,默认会使用 `corepack` 来安装指定版本的 `pnpm`。:
|
- 项目只支持使用 `pnpm` 进行依赖安装,默认会使用 `corepack` 来安装指定版本的 `pnpm`。:
|
||||||
|
- 如果你的网络环境无法访问npm源,你可以设置系统的环境变量`COREPACK_REGISTRY=https://registry.npmmirror.com`,然后再执行`pnpm install`。
|
||||||
|
- 如果你不想使用`corepack`,你需要禁用`corepack`,然后使用你自己的`pnpm`进行安装。
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
@ -243,4 +243,5 @@ export {
|
|||||||
viteDtsPlugin,
|
viteDtsPlugin,
|
||||||
viteHtmlPlugin,
|
viteHtmlPlugin,
|
||||||
viteVisualizerPlugin,
|
viteVisualizerPlugin,
|
||||||
|
viteVxeTableImportsPlugin,
|
||||||
};
|
};
|
||||||
|
@ -4,6 +4,35 @@ import { lazyImport, VxeResolver } from 'vite-plugin-lazy-import';
|
|||||||
|
|
||||||
async function viteVxeTableImportsPlugin(): Promise<PluginOption> {
|
async function viteVxeTableImportsPlugin(): Promise<PluginOption> {
|
||||||
return [
|
return [
|
||||||
|
// {
|
||||||
|
// config() {
|
||||||
|
// return {
|
||||||
|
// optimizeDeps: {
|
||||||
|
// include: [
|
||||||
|
// 'vxe-pc-ui/es/vxe-button/index.js',
|
||||||
|
// 'vxe-pc-ui/es/vxe-checkbox/index.js',
|
||||||
|
// 'vxe-pc-ui/es/vxe-icon/index.js',
|
||||||
|
// 'vxe-pc-ui/es/vxe-input/index.js',
|
||||||
|
// 'vxe-pc-ui/es/vxe-loading/index.js',
|
||||||
|
// 'vxe-pc-ui/es/vxe-modal/index.js',
|
||||||
|
// 'vxe-pc-ui/es/vxe-pager/index.js',
|
||||||
|
// 'vxe-pc-ui/es/vxe-radio-group/index.js',
|
||||||
|
// 'vxe-pc-ui/es/vxe-select/index.js',
|
||||||
|
// 'vxe-pc-ui/es/vxe-tooltip/index.js',
|
||||||
|
// 'vxe-pc-ui/es/vxe-ui/index.js',
|
||||||
|
// 'vxe-pc-ui/es/vxe-upload/index.js',
|
||||||
|
// 'vxe-table/es/vxe-colgroup/index.js',
|
||||||
|
// 'vxe-table/es/vxe-column/index.js',
|
||||||
|
// 'vxe-table/es/vxe-grid/index.js',
|
||||||
|
// 'vxe-table/es/vxe-table/index.js',
|
||||||
|
// 'vxe-table/es/vxe-toolbar/index.js',
|
||||||
|
// 'vxe-table/es/vxe-ui/index.js',
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
// };
|
||||||
|
// },
|
||||||
|
// name: 'vxe-table-adapter',
|
||||||
|
// },
|
||||||
lazyImport({
|
lazyImport({
|
||||||
resolvers: [
|
resolvers: [
|
||||||
VxeResolver({
|
VxeResolver({
|
||||||
|
@ -97,7 +97,7 @@
|
|||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=20.10.0",
|
"node": ">=20.10.0",
|
||||||
"pnpm": ">=9.5.0"
|
"pnpm": ">=9.12.0"
|
||||||
},
|
},
|
||||||
"packageManager": "pnpm@9.12.3",
|
"packageManager": "pnpm@9.12.3",
|
||||||
"pnpm": {
|
"pnpm": {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
:root {
|
:root .vxe-grid {
|
||||||
--vxe-ui-font-color: hsl(var(--foreground));
|
--vxe-ui-font-color: hsl(var(--foreground));
|
||||||
--vxe-ui-font-primary-color: hsl(var(--primary));
|
--vxe-ui-font-primary-color: hsl(var(--primary));
|
||||||
|
|
||||||
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
/* layout */
|
/* layout */
|
||||||
--vxe-ui-layout-background-color: hsl(var(--background));
|
--vxe-ui-layout-background-color: hsl(var(--background));
|
||||||
--vxe-ui-table-resizable-line-color: hsl(var(--border));
|
--vxe-ui-table-resizable-line-color: hsl(var(--heavy));
|
||||||
|
|
||||||
/* --vxe-ui-table-fixed-left-scrolling-box-shadow: 8px 0px 10px -5px hsl(var(--accent));
|
/* --vxe-ui-table-fixed-left-scrolling-box-shadow: 8px 0px 10px -5px hsl(var(--accent));
|
||||||
--vxe-ui-table-fixed-right-scrolling-box-shadow: -8px 0px 10px -5px hsl(var(--accent)); */
|
--vxe-ui-table-fixed-right-scrolling-box-shadow: -8px 0px 10px -5px hsl(var(--accent)); */
|
||||||
@ -66,16 +66,14 @@
|
|||||||
box-shadow: 0 0 0 1px hsl(var(--border));
|
box-shadow: 0 0 0 1px hsl(var(--border));
|
||||||
}
|
}
|
||||||
|
|
||||||
.vxe-pager {
|
.vxe-pager--wrapper {
|
||||||
&--wrapper {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
&--sizes {
|
.vxe-pager--sizes {
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.vxe-pager--wrapper {
|
.vxe-pager--wrapper {
|
||||||
|
@ -41,3 +41,5 @@ export function useVbenVxeGrid(options: VxeGridProps) {
|
|||||||
|
|
||||||
return [Grid, extendedApi] as const;
|
return [Grid, extendedApi] as const;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type UseVbenVxeGrid = typeof useVbenVxeGrid;
|
||||||
|
@ -39,7 +39,7 @@ setupVbenVxeTable({
|
|||||||
|
|
||||||
// 表格配置项可以用 cellRender: { name: 'CellImage' },
|
// 表格配置项可以用 cellRender: { name: 'CellImage' },
|
||||||
vxeUI.renderer.add('CellImage', {
|
vxeUI.renderer.add('CellImage', {
|
||||||
renderDefault(_renderOpts, params) {
|
renderTableDefault(_renderOpts, params) {
|
||||||
const { column, row } = params;
|
const { column, row } = params;
|
||||||
return h(Image, { src: row[column.field] });
|
return h(Image, { src: row[column.field] });
|
||||||
},
|
},
|
||||||
@ -47,7 +47,7 @@ setupVbenVxeTable({
|
|||||||
|
|
||||||
// 表格配置项可以用 cellRender: { name: 'CellLink' },
|
// 表格配置项可以用 cellRender: { name: 'CellLink' },
|
||||||
vxeUI.renderer.add('CellLink', {
|
vxeUI.renderer.add('CellLink', {
|
||||||
renderDefault(renderOpts) {
|
renderTableDefault(renderOpts) {
|
||||||
const { props } = renderOpts;
|
const { props } = renderOpts;
|
||||||
return h(
|
return h(
|
||||||
Button,
|
Button,
|
||||||
|
@ -1,17 +1,19 @@
|
|||||||
import { createApp } from 'vue';
|
import { createApp, watchEffect } from 'vue';
|
||||||
|
|
||||||
import { registerAccessDirective } from '@vben/access';
|
import { registerAccessDirective } from '@vben/access';
|
||||||
|
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/antd';
|
||||||
|
|
||||||
import { VueQueryPlugin } from '@tanstack/vue-query';
|
import { VueQueryPlugin } from '@tanstack/vue-query';
|
||||||
|
import { useTitle } from '@vueuse/core';
|
||||||
|
|
||||||
import { setupI18n } from '#/locales';
|
import { $t, setupI18n } from '#/locales';
|
||||||
|
import { router } from '#/router';
|
||||||
|
|
||||||
import { initComponentAdapter } from './adapter/component';
|
import { initComponentAdapter } from './adapter/component';
|
||||||
import App from './app.vue';
|
import App from './app.vue';
|
||||||
import { router } from './router';
|
|
||||||
|
|
||||||
async function bootstrap(namespace: string) {
|
async function bootstrap(namespace: string) {
|
||||||
// 初始化组件适配器
|
// 初始化组件适配器
|
||||||
@ -34,6 +36,16 @@ async function bootstrap(namespace: string) {
|
|||||||
// 配置@tanstack/vue-query
|
// 配置@tanstack/vue-query
|
||||||
app.use(VueQueryPlugin);
|
app.use(VueQueryPlugin);
|
||||||
|
|
||||||
|
// 动态更新标题
|
||||||
|
watchEffect(() => {
|
||||||
|
if (preferences.app.dynamicTitle) {
|
||||||
|
const routeTitle = router.currentRoute.value.meta?.title;
|
||||||
|
const pageTitle =
|
||||||
|
(routeTitle ? `${$t(routeTitle)} - ` : '') + preferences.app.name;
|
||||||
|
useTitle(pageTitle);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
app.mount('#app');
|
app.mount('#app');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ import { defineOverridesPreferences } from '@vben/preferences';
|
|||||||
/**
|
/**
|
||||||
* @description 项目配置文件
|
* @description 项目配置文件
|
||||||
* 只需要覆盖项目中的一部分配置,不需要的配置不用覆盖,会自动使用默认配置
|
* 只需要覆盖项目中的一部分配置,不需要的配置不用覆盖,会自动使用默认配置
|
||||||
|
* !!! 更改配置后请清空缓存,否则可能不生效
|
||||||
*/
|
*/
|
||||||
export const overridesPreferences = defineOverridesPreferences({
|
export const overridesPreferences = defineOverridesPreferences({
|
||||||
// overrides
|
// overrides
|
||||||
|
@ -5,9 +5,6 @@ import { preferences } from '@vben/preferences';
|
|||||||
import { useAccessStore, useUserStore } from '@vben/stores';
|
import { useAccessStore, useUserStore } from '@vben/stores';
|
||||||
import { startProgress, stopProgress } from '@vben/utils';
|
import { startProgress, stopProgress } from '@vben/utils';
|
||||||
|
|
||||||
import { useTitle } from '@vueuse/core';
|
|
||||||
|
|
||||||
import { $t } from '#/locales';
|
|
||||||
import { accessRoutes, coreRouteNames } from '#/router/routes';
|
import { accessRoutes, coreRouteNames } from '#/router/routes';
|
||||||
import { useAuthStore } from '#/store';
|
import { useAuthStore } from '#/store';
|
||||||
|
|
||||||
@ -39,13 +36,6 @@ function setupCommonGuard(router: Router) {
|
|||||||
if (preferences.transition.progress) {
|
if (preferences.transition.progress) {
|
||||||
stopProgress();
|
stopProgress();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 动态修改标题
|
|
||||||
if (preferences.app.dynamicTitle) {
|
|
||||||
const { title } = to.meta;
|
|
||||||
// useTitle(`${$t(title)} - ${preferences.app.name}`);
|
|
||||||
useTitle(`${$t(title)} - ${preferences.app.name}`);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ catalog:
|
|||||||
'@ctrl/tinycolor': ^4.1.0
|
'@ctrl/tinycolor': ^4.1.0
|
||||||
'@eslint/js': ^9.14.0
|
'@eslint/js': ^9.14.0
|
||||||
'@faker-js/faker': ^9.2.0
|
'@faker-js/faker': ^9.2.0
|
||||||
'@iconify/json': ^2.2.267
|
'@iconify/json': ^2.2.268
|
||||||
'@iconify/tailwind': ^1.1.3
|
'@iconify/tailwind': ^1.1.3
|
||||||
'@iconify/vue': ^4.1.2
|
'@iconify/vue': ^4.1.2
|
||||||
'@intlify/core-base': ^10.0.4
|
'@intlify/core-base': ^10.0.4
|
||||||
@ -44,13 +44,13 @@ catalog:
|
|||||||
'@types/jsonwebtoken': ^9.0.7
|
'@types/jsonwebtoken': ^9.0.7
|
||||||
'@types/lodash.clonedeep': ^4.5.9
|
'@types/lodash.clonedeep': ^4.5.9
|
||||||
'@types/lodash.get': ^4.4.9
|
'@types/lodash.get': ^4.4.9
|
||||||
'@types/node': ^22.8.7
|
'@types/node': ^22.9.0
|
||||||
'@types/nprogress': ^0.2.3
|
'@types/nprogress': ^0.2.3
|
||||||
'@types/postcss-import': ^14.0.3
|
'@types/postcss-import': ^14.0.3
|
||||||
'@types/qrcode': ^1.5.5
|
'@types/qrcode': ^1.5.5
|
||||||
'@types/sortablejs': ^1.15.8
|
'@types/sortablejs': ^1.15.8
|
||||||
'@typescript-eslint/eslint-plugin': ^8.12.2
|
'@typescript-eslint/eslint-plugin': ^8.13.0
|
||||||
'@typescript-eslint/parser': ^8.12.2
|
'@typescript-eslint/parser': ^8.13.0
|
||||||
'@vee-validate/zod': ^4.14.6
|
'@vee-validate/zod': ^4.14.6
|
||||||
'@vite-pwa/vitepress': ^0.5.3
|
'@vite-pwa/vitepress': ^0.5.3
|
||||||
'@vitejs/plugin-vue': ^5.1.4
|
'@vitejs/plugin-vue': ^5.1.4
|
||||||
@ -71,7 +71,7 @@ catalog:
|
|||||||
circular-dependency-scanner: ^2.3.0
|
circular-dependency-scanner: ^2.3.0
|
||||||
class-variance-authority: ^0.7.0
|
class-variance-authority: ^0.7.0
|
||||||
clsx: ^2.1.1
|
clsx: ^2.1.1
|
||||||
commitlint-plugin-function-rules: ^4.0.0
|
commitlint-plugin-function-rules: ^4.0.1
|
||||||
consola: ^3.2.3
|
consola: ^3.2.3
|
||||||
cross-env: ^7.0.3
|
cross-env: ^7.0.3
|
||||||
cspell: ^8.15.7
|
cspell: ^8.15.7
|
||||||
@ -105,7 +105,7 @@ catalog:
|
|||||||
get-port: ^7.1.0
|
get-port: ^7.1.0
|
||||||
globals: ^15.12.0
|
globals: ^15.12.0
|
||||||
h3: ^1.13.0
|
h3: ^1.13.0
|
||||||
happy-dom: ^15.8.3
|
happy-dom: ^15.10.1
|
||||||
html-minifier-terser: ^7.2.0
|
html-minifier-terser: ^7.2.0
|
||||||
husky: ^9.1.6
|
husky: ^9.1.6
|
||||||
is-ci: ^3.0.1
|
is-ci: ^3.0.1
|
||||||
@ -117,7 +117,7 @@ catalog:
|
|||||||
lucide-vue-next: ^0.454.0
|
lucide-vue-next: ^0.454.0
|
||||||
medium-zoom: ^1.1.0
|
medium-zoom: ^1.1.0
|
||||||
naive-ui: ^2.40.1
|
naive-ui: ^2.40.1
|
||||||
nitropack: ^2.10.2
|
nitropack: ^2.10.3
|
||||||
nprogress: ^0.2.0
|
nprogress: ^0.2.0
|
||||||
ora: ^8.1.1
|
ora: ^8.1.1
|
||||||
pinia: 2.2.2
|
pinia: 2.2.2
|
||||||
@ -139,7 +139,7 @@ catalog:
|
|||||||
rimraf: ^6.0.1
|
rimraf: ^6.0.1
|
||||||
rollup: ^4.24.4
|
rollup: ^4.24.4
|
||||||
rollup-plugin-visualizer: ^5.12.0
|
rollup-plugin-visualizer: ^5.12.0
|
||||||
sass: 1.79.5
|
sass: 1.80.6
|
||||||
sortablejs: ^1.15.3
|
sortablejs: ^1.15.3
|
||||||
stylelint: ^16.10.0
|
stylelint: ^16.10.0
|
||||||
stylelint-config-recess-order: ^5.1.1
|
stylelint-config-recess-order: ^5.1.1
|
||||||
@ -165,8 +165,8 @@ catalog:
|
|||||||
vite-plugin-html: ^3.2.2
|
vite-plugin-html: ^3.2.2
|
||||||
vite-plugin-lazy-import: ^1.0.7
|
vite-plugin-lazy-import: ^1.0.7
|
||||||
vite-plugin-pwa: ^0.20.5
|
vite-plugin-pwa: ^0.20.5
|
||||||
vite-plugin-vue-devtools: ^7.6.2
|
vite-plugin-vue-devtools: ^7.6.3
|
||||||
vitepress: ^1.4.5
|
vitepress: ^1.5.0
|
||||||
vitepress-plugin-group-icons: ^1.3.0
|
vitepress-plugin-group-icons: ^1.3.0
|
||||||
vitest: ^2.1.4
|
vitest: ^2.1.4
|
||||||
vue: ^3.5.12
|
vue: ^3.5.12
|
||||||
@ -174,8 +174,8 @@ catalog:
|
|||||||
vue-i18n: ^10.0.4
|
vue-i18n: ^10.0.4
|
||||||
vue-router: ^4.4.5
|
vue-router: ^4.4.5
|
||||||
vue-tsc: ^2.1.10
|
vue-tsc: ^2.1.10
|
||||||
vxe-pc-ui: ^4.2.40
|
vxe-pc-ui: ^4.2.42
|
||||||
vxe-table: ^4.8.0
|
vxe-table: ^4.8.1
|
||||||
watermark-js-plus: ^1.5.7
|
watermark-js-plus: ^1.5.7
|
||||||
zod: ^3.23.8
|
zod: ^3.23.8
|
||||||
zod-defaults: ^0.1.3
|
zod-defaults: ^0.1.3
|
||||||
|
Loading…
Reference in New Issue
Block a user