Skip to content

Commit

Permalink
feat: add vxe-table component (#4563)
Browse files Browse the repository at this point in the history
* chore: wip vxe-table

* feat: add table demo

* chore: follow ci recommendations to adjust details

* chore: add custom-cell demo

* feat: add custom-cell table demo

* feat: add table from demo
  • Loading branch information
anncwb authored Oct 4, 2024
1 parent 46540a7 commit 4173264
Show file tree
Hide file tree
Showing 80 changed files with 2,426 additions and 80 deletions.
48 changes: 48 additions & 0 deletions apps/backend-mock/api/table/list.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { faker } from '@faker-js/faker';
import { verifyAccessToken } from '~/utils/jwt-utils';
import { unAuthorizedResponse } from '~/utils/response';

function generateMockDataList(count: number) {
const dataList = [];

for (let i = 0; i < count; i++) {
const dataItem = {
id: faker.string.uuid(),
imageUrl: faker.image.avatar(),
imageUrl2: faker.image.avatar(),
open: faker.datatype.boolean(),
status: faker.helpers.arrayElement(['success', 'error', 'warning']),
productName: faker.commerce.productName(),
price: faker.commerce.price(),
currency: faker.finance.currencyCode(),
quantity: faker.number.int({ min: 1, max: 100 }),
available: faker.datatype.boolean(),
category: faker.commerce.department(),
releaseDate: faker.date.past(),
rating: faker.number.float({ min: 1, max: 5 }),
description: faker.commerce.productDescription(),
weight: faker.number.float({ min: 0.1, max: 10 }),
color: faker.color.human(),
inProduction: faker.datatype.boolean(),
tags: Array.from({ length: 3 }, () => faker.commerce.productAdjective()),
};

dataList.push(dataItem);
}

return dataList;
}

const mockData = generateMockDataList(100);

export default eventHandler(async (event) => {
const userinfo = verifyAccessToken(event);
if (!userinfo) {
return unAuthorizedResponse(event);
}

await sleep(600);

const { page, pageSize } = getQuery(event);
return usePageResponseSuccess(page as string, pageSize as string, mockData);
});
1 change: 1 addition & 0 deletions apps/backend-mock/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"start": "nitro dev"
},
"dependencies": {
"@faker-js/faker": "catalog:",
"jsonwebtoken": "catalog:",
"nitropack": "catalog:"
},
Expand Down
36 changes: 36 additions & 0 deletions apps/backend-mock/utils/response.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,27 @@ export function useResponseSuccess<T = any>(data: T) {
};
}

export function usePageResponseSuccess<T = any>(
page: number | string,
pageSize: number | string,
list: T[],
{ message = 'ok' } = {},
) {
const pageData = pagination(
Number.parseInt(`${page}`),
Number.parseInt(`${pageSize}`),
list,
);

return {
...useResponseSuccess({
items: pageData,
total: list.length,
}),
message,
};
}

export function useResponseError(message: string, error: any = null) {
return {
code: -1,
Expand All @@ -27,3 +48,18 @@ export function unAuthorizedResponse(event: H3Event<EventHandlerRequest>) {
setResponseStatus(event, 401);
return useResponseError('UnauthorizedException', 'Unauthorized Exception');
}

export function sleep(ms: number) {
return new Promise((resolve) => setTimeout(resolve, ms));
}

export function pagination<T = any>(
pageNo: number,
pageSize: number,
array: T[],
): T[] {
const offset = (pageNo - 1) * Number(pageSize);
return offset + Number(pageSize) >= array.length
? array.slice(offset)
: array.slice(offset, offset + Number(pageSize));
}
1 change: 1 addition & 0 deletions apps/web-antd/src/adapter/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './form';
export * from './vxe-table';
59 changes: 59 additions & 0 deletions apps/web-antd/src/adapter/vxe-table.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
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: true,
minHeight: 180,
proxyConfig: {
autoLoad: true,
response: {
result: 'items',
total: 'total',
list: 'items',
},
showActiveMsg: true,
showResponseMsg: false,
},
round: true,
size: 'small',
},
});

// 表格配置项可以用 cellRender: { name: 'CellImage' },
vxeUI.renderer.add('CellImage', {
renderDefault(_renderOpts, params) {
const { column, row } = params;
return h(Image, { src: row[column.field] });
},
});

// 表格配置项可以用 cellRender: { name: 'CellLink' },
vxeUI.renderer.add('CellLink', {
renderDefault(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';
1 change: 1 addition & 0 deletions apps/web-ele/src/adapter/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './form';
export * from './vxe-table';
60 changes: 60 additions & 0 deletions apps/web-ele/src/adapter/vxe-table.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { h } from 'vue';

import { setupVbenVxeTable, useVbenVxeGrid } from '@vben/plugins/vxe-table';

import { ElButton, ElImage } from 'element-plus';

import { useVbenForm } from './form';

setupVbenVxeTable({
configVxeTable: (vxeUI) => {
vxeUI.setConfig({
grid: {
align: 'center',
border: true,
minHeight: 180,
proxyConfig: {
autoLoad: true,
response: {
result: 'items',
total: 'total',
list: 'items',
},
showActiveMsg: true,
showResponseMsg: false,
},
round: true,
size: 'small',
},
});

// 表格配置项可以用 cellRender: { name: 'CellImage' },
vxeUI.renderer.add('CellImage', {
renderDefault(_renderOpts, params) {
const { column, row } = params;
const src = row[column.field];
return h(ElImage, { src, previewSrcList: [src] });
},
});

// 表格配置项可以用 cellRender: { name: 'CellLink' },
vxeUI.renderer.add('CellLink', {
renderDefault(renderOpts) {
const { props } = renderOpts;
return h(
ElButton,
{ size: 'small', link: true },
{ default: () => props?.text },
);
},
});

// 这里可以自行扩展 vxe-table 的全局配置,比如自定义格式化
// vxeUI.formats.add
},
useVbenForm,
});

export { useVbenVxeGrid };

export type * from '@vben/plugins/vxe-table';
1 change: 1 addition & 0 deletions apps/web-naive/src/adapter/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './form';
export * from './naive';
export * from './vxe-table';
59 changes: 59 additions & 0 deletions apps/web-naive/src/adapter/vxe-table.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { h } from 'vue';

import { setupVbenVxeTable, useVbenVxeGrid } from '@vben/plugins/vxe-table';

import { NButton, NImage } from 'naive-ui';

import { useVbenForm } from './form';

setupVbenVxeTable({
configVxeTable: (vxeUI) => {
vxeUI.setConfig({
grid: {
align: 'center',
border: true,
minHeight: 180,
proxyConfig: {
autoLoad: true,
response: {
result: 'items',
total: 'total',
list: 'items',
},
showActiveMsg: true,
showResponseMsg: false,
},
round: true,
size: 'small',
},
});

// 表格配置项可以用 cellRender: { name: 'CellImage' },
vxeUI.renderer.add('CellImage', {
renderDefault(_renderOpts, params) {
const { column, row } = params;
return h(NImage, { src: row[column.field] });
},
});

// 表格配置项可以用 cellRender: { name: 'CellLink' },
vxeUI.renderer.add('CellLink', {
renderDefault(renderOpts) {
const { props } = renderOpts;
return h(
NButton,
{ size: 'small', type: 'primary', quaternary: true },
{ default: () => props?.text },
);
},
});

// 这里可以自行扩展 vxe-table 的全局配置,比如自定义格式化
// vxeUI.formats.add
},
useVbenForm,
});

export { useVbenVxeGrid };

export type * from '@vben/plugins/vxe-table';
1 change: 1 addition & 0 deletions cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"intlify",
"mkdist",
"mockjs",
"vitejs",
"noopener",
"noreferrer",
"nprogress",
Expand Down
2 changes: 0 additions & 2 deletions docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@
"dependencies": {
"@vben-core/shadcn-ui": "workspace:*",
"@vben/common-ui": "workspace:*",
"@vben/hooks": "workspace:*",
"@vben/locales": "workspace:*",
"@vben/preferences": "workspace:*",
"@vben/styles": "workspace:*",
"ant-design-vue": "catalog:",
"lucide-vue-next": "catalog:",
Expand Down
1 change: 1 addition & 0 deletions docs/src/components/common-ui/vben-form.md
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ useVbenForm 返回的第二个参数,是一个对象,包含了一些表单
| submitButtonOptions | 提交按钮组件参数 | `ActionButtonOptions` | - |
| showDefaultActions | 是否显示默认操作按钮 | `boolean` | `true` |
| collapsed | 是否折叠,在`是否展开,在showCollapseButton=true`时生效 | `boolean` | `false` |
| collapseTriggerResize | 折叠时,触发`resize`事件 | `boolean` | `false` |
| collapsedRows | 折叠时保持的行数 | `number` | `1` |
| commonConfig | 表单项的通用配置,每个配置都会传递到每个表单项,表单项可覆盖 | `FormCommonConfig` | - |
| schema | 表单项的每一项配置 | `FormSchema` | - |
Expand Down
5 changes: 4 additions & 1 deletion internal/tailwind-config/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,10 @@ const customColors = {
main: {
DEFAULT: 'hsl(var(--main))',
},
overlay: 'hsl(var(--overlay))',
overlay: {
content: 'hsl(var(--overlay-content))',
DEFAULT: 'hsl(var(--overlay))',
},
red: {
...createColorsPalette('red'),
foreground: 'hsl(var(--destructive-foreground))',
Expand Down
3 changes: 2 additions & 1 deletion internal/vite-config/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
"vite": "catalog:",
"vite-plugin-compression": "catalog:",
"vite-plugin-dts": "catalog:",
"vite-plugin-html": "catalog:"
"vite-plugin-html": "catalog:",
"vite-plugin-lazy-import": "catalog:"
}
}
1 change: 1 addition & 0 deletions internal/vite-config/src/config/application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ function defineApplicationConfig(userConfigPromise?: DefineApplicationOptions) {
},
pwa: true,
pwaOptions: getDefaultPwaOptions(appTitle),
vxeTableLazyImport: true,
...envConfig,
...application,
});
Expand Down
8 changes: 8 additions & 0 deletions internal/vite-config/src/plugins/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { viteMetadataPlugin } from './inject-metadata';
import { viteLicensePlugin } from './license';
import { viteNitroMockPlugin } from './nitro-mock';
import { vitePrintPlugin } from './print';
import { viteVxeTableImportsPlugin } from './vxe-table';

/**
* 获取条件成立的 vite 插件
Expand Down Expand Up @@ -110,6 +111,7 @@ async function loadApplicationPlugins(
printInfoMap,
pwa,
pwaOptions,
vxeTableLazyImport,
...commonOptions
} = options;

Expand All @@ -135,6 +137,12 @@ async function loadApplicationPlugins(
return [await vitePrintPlugin({ infoMap: printInfoMap })];
},
},
{
condition: vxeTableLazyImport,
plugins: async () => {
return [await viteVxeTableImportsPlugin()];
},
},
{
condition: nitroMock,
plugins: async () => {
Expand Down
20 changes: 20 additions & 0 deletions internal/vite-config/src/plugins/vxe-table.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import type { PluginOption } from 'vite';

import { lazyImport, VxeResolver } from 'vite-plugin-lazy-import';

async function viteVxeTableImportsPlugin(): Promise<PluginOption> {
return [
lazyImport({
resolvers: [
VxeResolver({
libraryName: 'vxe-table',
}),
VxeResolver({
libraryName: 'vxe-pc-ui',
}),
],
}),
];
}

export { viteVxeTableImportsPlugin };
Loading

0 comments on commit 4173264

Please sign in to comment.