Browse Source

feat(components): 接入vextable组件

pull/768/head
cKey 4 years ago
parent
commit
87a72b37a0
  1. 3
      apps/vue/build/vite/plugin/styleImport.ts
  2. 5
      apps/vue/package.json
  3. 12
      apps/vue/src/components/VxeTable/index.ts
  4. 108
      apps/vue/src/components/VxeTable/src/VxeBasicTable.tsx
  5. 59
      apps/vue/src/components/VxeTable/src/componentMap.ts
  6. 22
      apps/vue/src/components/VxeTable/src/componentType.ts
  7. 20
      apps/vue/src/components/VxeTable/src/components/AApiSelect.tsx
  8. 16
      apps/vue/src/components/VxeTable/src/components/AAutoComplete.tsx
  9. 120
      apps/vue/src/components/VxeTable/src/components/AButton.tsx
  10. 59
      apps/vue/src/components/VxeTable/src/components/AButtonGroup.tsx
  11. 42
      apps/vue/src/components/VxeTable/src/components/ACascader.tsx
  12. 5
      apps/vue/src/components/VxeTable/src/components/ACheckboxGroup.tsx
  13. 33
      apps/vue/src/components/VxeTable/src/components/ADatePicker.tsx
  14. 27
      apps/vue/src/components/VxeTable/src/components/AEmpty.tsx
  15. 16
      apps/vue/src/components/VxeTable/src/components/AInput.tsx
  16. 16
      apps/vue/src/components/VxeTable/src/components/AInputNumber.tsx
  17. 17
      apps/vue/src/components/VxeTable/src/components/AInputSearch.tsx
  18. 18
      apps/vue/src/components/VxeTable/src/components/AMonthPicker.tsx
  19. 5
      apps/vue/src/components/VxeTable/src/components/ARadioGroup.tsx
  20. 30
      apps/vue/src/components/VxeTable/src/components/ARangePicker.tsx
  21. 15
      apps/vue/src/components/VxeTable/src/components/ARate.tsx
  22. 271
      apps/vue/src/components/VxeTable/src/components/ASelect.tsx
  23. 53
      apps/vue/src/components/VxeTable/src/components/ASwitch.tsx
  24. 18
      apps/vue/src/components/VxeTable/src/components/ATimePicker.tsx
  25. 35
      apps/vue/src/components/VxeTable/src/components/ATreeSelect.tsx
  26. 18
      apps/vue/src/components/VxeTable/src/components/AWeekPicker.tsx
  27. 18
      apps/vue/src/components/VxeTable/src/components/AYearPicker.tsx
  28. 427
      apps/vue/src/components/VxeTable/src/components/common.tsx
  29. 112
      apps/vue/src/components/VxeTable/src/components/index.tsx
  30. 4
      apps/vue/src/components/VxeTable/src/const.ts
  31. 8
      apps/vue/src/components/VxeTable/src/css/common.scss
  32. 105
      apps/vue/src/components/VxeTable/src/css/component.scss
  33. 6
      apps/vue/src/components/VxeTable/src/css/index.scss
  34. 24
      apps/vue/src/components/VxeTable/src/css/scrollbar.scss
  35. 30
      apps/vue/src/components/VxeTable/src/css/toolbar.scss
  36. 6
      apps/vue/src/components/VxeTable/src/css/variable.scss
  37. 17
      apps/vue/src/components/VxeTable/src/emits.ts
  38. 19
      apps/vue/src/components/VxeTable/src/helper.ts
  39. 131
      apps/vue/src/components/VxeTable/src/methods.ts
  40. 52
      apps/vue/src/components/VxeTable/src/props.ts
  41. 4
      apps/vue/src/components/VxeTable/src/setting.ts
  42. 7
      apps/vue/src/components/VxeTable/src/types.ts
  43. 3
      apps/vue/src/components/registerGlobComp.ts
  44. 1
      apps/vue/src/main.ts
  45. 46
      apps/vue/src/settings/componentSetting.ts

3
apps/vue/build/vite/plugin/styleImport.ts

@ -2,7 +2,7 @@
* Introduces component library styles on demand. * Introduces component library styles on demand.
* https://github.com/anncwb/vite-plugin-style-import * https://github.com/anncwb/vite-plugin-style-import
*/ */
import { createStyleImportPlugin } from 'vite-plugin-style-import'; import { createStyleImportPlugin, VxeTableResolve } from 'vite-plugin-style-import';
export function configStyleImportPlugin(_isBuild: boolean) { export function configStyleImportPlugin(_isBuild: boolean) {
// if (!isBuild) { // if (!isBuild) {
@ -77,6 +77,7 @@ export function configStyleImportPlugin(_isBuild: boolean) {
}, },
}, },
], ],
resolves: [VxeTableResolve()],
}); });
return styleImportPlugin; return styleImportPlugin;
} }

5
apps/vue/package.json

@ -53,6 +53,7 @@
"czg": "^1.3.9", "czg": "^1.3.9",
"dayjs": "^1.11.1", "dayjs": "^1.11.1",
"echarts": "^5.3.2", "echarts": "^5.3.2",
"exceljs": "^4.3.0",
"intro.js": "^5.1.0", "intro.js": "^5.1.0",
"lodash-es": "^4.17.21", "lodash-es": "^4.17.21",
"mockjs": "^1.1.0", "mockjs": "^1.1.0",
@ -76,6 +77,9 @@
"vue-router": "^4.0.14", "vue-router": "^4.0.14",
"vue-types": "^4.1.1", "vue-types": "^4.1.1",
"vue3-colorpicker": "^2.0.4", "vue3-colorpicker": "^2.0.4",
"vxe-table": "^4.3.9",
"vxe-table-plugin-export-xlsx": "^3.0.4",
"xe-utils": "^3.5.7",
"xlsx": "^0.18.5" "xlsx": "^0.18.5"
}, },
"devDependencies": { "devDependencies": {
@ -127,6 +131,7 @@
"rimraf": "^3.0.2", "rimraf": "^3.0.2",
"rollup": "^2.70.2", "rollup": "^2.70.2",
"rollup-plugin-visualizer": "^5.6.0", "rollup-plugin-visualizer": "^5.6.0",
"sass": "^1.57.1",
"stylelint": "^14.7.1", "stylelint": "^14.7.1",
"stylelint-config-prettier": "^9.0.3", "stylelint-config-prettier": "^9.0.3",
"stylelint-config-recommended": "^7.0.0", "stylelint-config-recommended": "^7.0.0",

12
apps/vue/src/components/VxeTable/index.ts

@ -0,0 +1,12 @@
import { withInstall } from '/@/utils';
import vxeBasicTable from './src/VxeBasicTable';
import { VXETable } from 'vxe-table';
import VXETablePluginAntd from './src/components';
import VXETablePluginExportXLSX from 'vxe-table-plugin-export-xlsx';
import './src/setting';
export const VxeBasicTable = withInstall(vxeBasicTable);
export * from 'vxe-table';
export * from './src/types';
VXETable.use(VXETablePluginAntd).use(VXETablePluginExportXLSX);

108
apps/vue/src/components/VxeTable/src/VxeBasicTable.tsx

@ -0,0 +1,108 @@
import { defineComponent } from 'vue';
import { computed, ref } from 'vue';
import { BasicTableProps } from './types';
import { omit } from 'lodash';
import { basicProps } from './props';
import { ignorePropKeys } from './const';
import { basicEmits } from './emits';
import XEUtils from 'xe-utils';
import type { VxeGridInstance, VxeGridEventProps, GridMethods, TableMethods } from 'vxe-table';
import { Grid as VxeGrid } from 'vxe-table';
import { extendSlots } from '/@/utils/helper/tsxHelper';
import { gridComponentMethodKeys } from './methods';
export default defineComponent({
name: 'VxeBasicTable',
props: basicProps,
emits: basicEmits,
setup(props, { emit, attrs }) {
const tableElRef = ref<VxeGridInstance>();
const emitEvents: VxeGridEventProps = {};
const extendTableMethods = (methodKeys) => {
const funcs: any = {};
methodKeys.forEach((name) => {
funcs[name] = (...args: any[]) => {
const $vxegrid: any = tableElRef.value;
if ($vxegrid && $vxegrid[name]) {
return $vxegrid[name](...args);
}
};
});
return funcs;
};
const gridExtendTableMethods = extendTableMethods(gridComponentMethodKeys) as GridMethods &
TableMethods;
basicEmits.forEach((name) => {
const type = XEUtils.camelCase(`on-${name}`) as keyof VxeGridEventProps;
emitEvents[type] = (...args: any[]) => emit(name, ...args);
});
/**
* @description: 二次封装需要的所有属性
* 1.部分属性需要和全局属性进行合并
*/
const getBindValues = computed<BasicTableProps>(() => {
const propsData: BasicTableProps = {
...attrs,
...props,
};
return propsData;
});
/**
* @description: Table 所有属性
*/
const getBindGridValues = computed(() => {
const omitProps = omit(getBindValues.value, ignorePropKeys);
return {
...omitProps,
...getBindGridEvent,
};
});
/**
* @description: 组件外层class
*/
const getWrapperClass = computed(() => {
return [attrs.class];
});
/**
* @description: 重写Vxe-table 方法
*/
const getBindGridEvent: VxeGridEventProps = {
...emitEvents,
};
return {
getWrapperClass,
getBindGridValues,
tableElRef,
...gridExtendTableMethods,
};
},
render() {
const { tableClass, tableStyle } = this.$props;
return (
<div class={`h-full flex flex-col bg-white ${this.getWrapperClass}`}>
<VxeGrid
ref="tableElRef"
class={`vxe-grid_scrollbar px-6 py-4 ${tableClass}`}
style={tableStyle}
{...this.getBindGridValues}
>
{extendSlots(this.$slots)}
</VxeGrid>
</div>
);
},
});

59
apps/vue/src/components/VxeTable/src/componentMap.ts

@ -0,0 +1,59 @@
import type { Component } from 'vue';
import type { ComponentType } from './componentType';
import { ApiSelect, ApiTreeSelect } from '/@/components/Form';
import {
Input,
Select,
Radio,
Checkbox,
AutoComplete,
Cascader,
DatePicker,
InputNumber,
Switch,
TimePicker,
TreeSelect,
Rate,
Button,
Empty,
} from 'ant-design-vue';
const componentMap = new Map<ComponentType, Component>();
componentMap.set('AButton', Button);
componentMap.set('AInput', Input);
componentMap.set('AInputSearch', Input.Search);
componentMap.set('AInputNumber', InputNumber);
componentMap.set('AAutoComplete', AutoComplete);
componentMap.set('ASelect', Select);
componentMap.set('ATreeSelect', TreeSelect);
componentMap.set('ASwitch', Switch);
componentMap.set('ARadioGroup', Radio.Group);
componentMap.set('ACheckboxGroup', Checkbox.Group);
componentMap.set('ACascader', Cascader);
componentMap.set('ARate', Rate);
componentMap.set('ADatePicker', DatePicker);
componentMap.set('AMonthPicker', DatePicker.MonthPicker);
componentMap.set('ARangePicker', DatePicker.RangePicker);
componentMap.set('AWeekPicker', DatePicker.WeekPicker);
componentMap.set('AYearPicker', DatePicker.YearPicker);
componentMap.set('ATimePicker', TimePicker);
componentMap.set('AApiSelect', ApiSelect);
componentMap.set('AApiTreeSelect', ApiTreeSelect);
componentMap.set('AEmpty', Empty);
export function add(compName: ComponentType, component: Component) {
componentMap.set(compName, component);
}
export function del(compName: ComponentType) {
componentMap.delete(compName);
}
export { componentMap };

22
apps/vue/src/components/VxeTable/src/componentType.ts

@ -0,0 +1,22 @@
export type ComponentType =
| 'AInput'
| 'AInputNumber'
| 'ASelect'
| 'AApiSelect'
| 'ATreeSelect'
| 'AApiTreeSelect'
| 'ARadioGroup'
| 'ACheckboxGroup'
| 'AAutoComplete'
| 'ACascader'
| 'ADatePicker'
| 'AMonthPicker'
| 'ARangePicker'
| 'AWeekPicker'
| 'ATimePicker'
| 'AYearPicker'
| 'ASwitch'
| 'ARate'
| 'AInputSearch'
| 'AButton'
| 'AEmpty';

20
apps/vue/src/components/VxeTable/src/components/AApiSelect.tsx

@ -0,0 +1,20 @@
import XEUtils from 'xe-utils';
import { createDefaultRender, createEditRender, createFormItemRender } from './common';
export default {
renderDefault: createDefaultRender({}, (_, params) => {
return {
params: XEUtils.get(params, 'row'),
};
}),
renderEdit: createEditRender({}, (_, params) => {
return {
params: XEUtils.get(params, 'row'),
};
}),
renderItemContent: createFormItemRender({}, (_, params) => {
return {
params: XEUtils.get(params, 'row'),
};
}),
};

16
apps/vue/src/components/VxeTable/src/components/AAutoComplete.tsx

@ -0,0 +1,16 @@
import {
createEditRender,
createDefaultRender,
createFilterRender,
createDefaultFilterRender,
createFormItemRender,
} from './common';
export default {
autofocus: 'input.ant-input',
renderDefault: createDefaultRender(),
renderEdit: createEditRender(),
renderFilter: createFilterRender(),
defaultFilterMethod: createDefaultFilterRender(),
renderItemContent: createFormItemRender(),
};

120
apps/vue/src/components/VxeTable/src/components/AButton.tsx

@ -0,0 +1,120 @@
import { h } from 'vue';
import {
FormItemContentRenderParams,
FormItemRenderOptions,
VxeGlobalRendererHandles,
} from 'vxe-table';
import XEUtils from 'xe-utils';
import { cellText, createEvents, createProps, getComponent } from './common';
const COMPONENT_NAME = 'AButton';
export function createEditRender() {
return function (
renderOpts: VxeGlobalRendererHandles.RenderEditOptions,
params: VxeGlobalRendererHandles.RenderEditParams,
) {
const { attrs } = renderOpts;
const Component = getComponent(COMPONENT_NAME);
return [
h(Component, {
...attrs,
...createProps(renderOpts, null),
...createEvents(renderOpts, params),
}),
];
};
}
export function createDefaultRender() {
return function (
renderOpts: VxeGlobalRendererHandles.RenderEditOptions,
params: VxeGlobalRendererHandles.RenderEditParams,
) {
const { attrs } = renderOpts;
const Component = getComponent(COMPONENT_NAME);
return [
h(
Component,
{
...attrs,
...createProps(renderOpts, null),
...createEvents(renderOpts, params),
},
cellText(renderOpts.content),
),
];
};
}
export function createFormItemRender() {
return function (renderOpts: FormItemRenderOptions, params: FormItemContentRenderParams) {
const { attrs, content } = renderOpts;
const { property, $form, data } = params;
const props = createProps(renderOpts, null);
const Component = getComponent(COMPONENT_NAME);
return [
h(
Component,
{
...attrs,
...props,
...createEvents(
renderOpts,
params,
(value: any) => {
// 处理 model 值双向绑定
XEUtils.set(data, property, value);
},
() => {
// 处理 change 事件相关逻辑
$form.updateStatus({
...params,
field: property,
});
},
),
},
{
default: () => cellText(content || props.content),
},
),
];
};
}
function createToolbarButtonRender() {
return function (
renderOpts: VxeGlobalRendererHandles.RenderToolOptions,
params: VxeGlobalRendererHandles.RenderButtonParams,
) {
const { attrs } = renderOpts;
const { button } = params;
const props = createProps(renderOpts, null);
const Component = getComponent(COMPONENT_NAME);
return [
h(
Component,
{
...attrs,
...props,
...createEvents(renderOpts, params),
},
{
default: () => cellText(button?.content || props.content),
},
),
];
};
}
export default {
renderEdit: createEditRender(),
renderDefault: createDefaultRender(),
renderItemContent: createFormItemRender(),
renderToolbarButton: createToolbarButtonRender(),
};

59
apps/vue/src/components/VxeTable/src/components/AButtonGroup.tsx

@ -0,0 +1,59 @@
import {
FormItemContentRenderParams,
FormItemRenderOptions,
VxeGlobalRendererHandles,
} from 'vxe-table';
import { createDefaultRender, createEditRender, createFormItemRender } from './AButton';
function createEditButtonRender() {
return function (
renderOpts: VxeGlobalRendererHandles.RenderEditOptions,
params: VxeGlobalRendererHandles.RenderEditParams,
) {
const buttonEditRender = createEditRender();
const { children } = renderOpts;
if (children) {
return children.map(
(childRenderOpts: VxeGlobalRendererHandles.RenderEditOptions) =>
buttonEditRender(childRenderOpts, params)[0],
);
}
return [];
};
}
function createDefaultButtonRender() {
return function (
renderOpts: VxeGlobalRendererHandles.RenderDefaultOptions,
params: VxeGlobalRendererHandles.RenderDefaultParams,
) {
const buttonDefaultRender = createDefaultRender();
const { children } = renderOpts;
if (children) {
return children.map(
(childRenderOpts: VxeGlobalRendererHandles.RenderDefaultOptions) =>
buttonDefaultRender(childRenderOpts, params)[0],
);
}
return [];
};
}
function createButtonItemRender() {
return function (renderOpts: FormItemRenderOptions, params: FormItemContentRenderParams) {
const buttonItemRender = createFormItemRender();
const { children } = renderOpts;
if (children) {
return children.map(
(childRenderOpts: FormItemRenderOptions) => buttonItemRender(childRenderOpts, params)[0],
);
}
return [];
};
}
export default {
renderEdit: createEditButtonRender(),
renderDefault: createDefaultButtonRender(),
renderItemContent: createButtonItemRender(),
};

42
apps/vue/src/components/VxeTable/src/components/ACascader.tsx

@ -0,0 +1,42 @@
import { VxeGlobalRendererHandles } from 'vxe-table';
import XEUtils from 'xe-utils';
import {
createEditRender,
createCellRender,
createFormItemRender,
createExportMethod,
} from './common';
function matchCascaderData(index: number, list: any[], values: any[], labels: any[]) {
const val = values[index];
if (list && values.length > index) {
XEUtils.each(list, (item) => {
if (item.value === val) {
labels.push(item.label);
matchCascaderData(++index, item.children, values, labels);
}
});
}
}
function getCascaderCellValue(
renderOpts: VxeGlobalRendererHandles.RenderOptions,
params: VxeGlobalRendererHandles.RenderCellParams,
) {
const { props = {} } = renderOpts;
const { row, column } = params;
const cellValue = XEUtils.get(row, column.field as string);
const values = cellValue || [];
const labels: Array<any> = [];
matchCascaderData(0, props.options, values, labels);
return (
props.showAllLevels === false ? labels.slice(labels.length - 1, labels.length) : labels
).join(` ${props.separator || '/'} `);
}
export default {
renderEdit: createEditRender(),
renderCell: createCellRender(getCascaderCellValue),
renderItemContent: createFormItemRender(),
exportMethod: createExportMethod(getCascaderCellValue),
};

5
apps/vue/src/components/VxeTable/src/components/ACheckboxGroup.tsx

@ -0,0 +1,5 @@
import { createFormItemRender } from './common';
export default {
renderItemContent: createFormItemRender(),
};

33
apps/vue/src/components/VxeTable/src/components/ADatePicker.tsx

@ -0,0 +1,33 @@
import { VxeGlobalRendererHandles } from 'vxe-table';
import XEUtils from 'xe-utils';
import {
createCellRender,
createEditRender,
createExportMethod,
createFormItemRender,
} from './common';
export function getDatePickerCellValue(
renderOpts: VxeGlobalRendererHandles.RenderOptions,
params: VxeGlobalRendererHandles.RenderCellParams | VxeGlobalRendererHandles.ExportMethodParams,
defaultFormat: string,
) {
const { props = {} } = renderOpts;
const { row, column } = params;
let cellValue = XEUtils.get(row, column.field as string);
if (cellValue) {
cellValue = cellValue.format(props.format || defaultFormat);
}
return cellValue;
}
export default {
renderEdit: createEditRender(),
renderCell: createCellRender(getDatePickerCellValue, () => {
return ['YYYY-MM-DD'];
}),
renderItemContent: createFormItemRender(),
exportMethod: createExportMethod(getDatePickerCellValue, () => {
return ['YYYY-MM-DD'];
}),
};

27
apps/vue/src/components/VxeTable/src/components/AEmpty.tsx

@ -0,0 +1,27 @@
import { h } from 'vue';
import { VxeGlobalRendererHandles } from 'vxe-table';
import { getComponent } from './common';
function createEmptyRender() {
return function (renderOpts: VxeGlobalRendererHandles.RenderEmptyOptions) {
const { name, attrs, props } = renderOpts;
const Component = getComponent(name);
return [
h(
'div',
{
class: 'flex items-center justify-center',
},
h(Component, {
...attrs,
...props,
}),
),
];
};
}
export default {
renderEmpty: createEmptyRender(),
};

16
apps/vue/src/components/VxeTable/src/components/AInput.tsx

@ -0,0 +1,16 @@
import {
createEditRender,
createDefaultRender,
createFilterRender,
createDefaultFilterRender,
createFormItemRender,
} from './common';
export default {
autofocus: 'input.ant-input',
renderDefault: createDefaultRender(),
renderEdit: createEditRender(),
renderFilter: createFilterRender(),
defaultFilterMethod: createDefaultFilterRender(),
renderItemContent: createFormItemRender(),
};

16
apps/vue/src/components/VxeTable/src/components/AInputNumber.tsx

@ -0,0 +1,16 @@
import {
createEditRender,
createFilterRender,
createFormItemRender,
createDefaultFilterRender,
createDefaultRender,
} from './common';
export default {
autofocus: 'input.ant-input-number-input',
renderDefault: createDefaultRender(),
renderEdit: createEditRender(),
renderFilter: createFilterRender(),
defaultFilterMethod: createDefaultFilterRender(),
renderItemContent: createFormItemRender(),
};

17
apps/vue/src/components/VxeTable/src/components/AInputSearch.tsx

@ -0,0 +1,17 @@
import {
createEditRender,
createDefaultRender,
createFilterRender,
createDefaultFilterRender,
createFormItemRender,
createToolbarToolRender,
} from './common';
export default {
renderDefault: createDefaultRender(),
renderEdit: createEditRender(),
renderFilter: createFilterRender(),
defaultFilterMethod: createDefaultFilterRender(),
renderItemContent: createFormItemRender(),
renderToolbarTool: createToolbarToolRender(),
};

18
apps/vue/src/components/VxeTable/src/components/AMonthPicker.tsx

@ -0,0 +1,18 @@
import { getDatePickerCellValue } from './ADatePicker';
import {
createCellRender,
createEditRender,
createExportMethod,
createFormItemRender,
} from './common';
export default {
renderEdit: createEditRender(),
renderCell: createCellRender(getDatePickerCellValue, () => {
return ['YYYY-MM'];
}),
renderItemContent: createFormItemRender(),
exportMethod: createExportMethod(getDatePickerCellValue, () => {
return ['YYYY-MM'];
}),
};

5
apps/vue/src/components/VxeTable/src/components/ARadioGroup.tsx

@ -0,0 +1,5 @@
import { createFormItemRender } from './common';
export default {
renderItemContent: createFormItemRender(),
};

30
apps/vue/src/components/VxeTable/src/components/ARangePicker.tsx

@ -0,0 +1,30 @@
import { VxeColumnPropTypes, VxeGlobalRendererHandles } from 'vxe-table';
import XEUtils from 'xe-utils';
import {
createCellRender,
createEditRender,
createExportMethod,
createFormItemRender,
} from './common';
function getRangePickerCellValue(
renderOpts: VxeColumnPropTypes.EditRender,
params: VxeGlobalRendererHandles.RenderCellParams | VxeGlobalRendererHandles.ExportMethodParams,
) {
const { props = {} } = renderOpts;
const { row, column } = params;
let cellValue = XEUtils.get(row, column.field as string);
if (cellValue) {
cellValue = XEUtils.map(cellValue, (date: any) =>
date.format(props.format || 'YYYY-MM-DD'),
).join(' ~ ');
}
return cellValue;
}
export default {
renderEdit: createEditRender(),
renderCell: createCellRender(getRangePickerCellValue),
renderItemContent: createFormItemRender(),
exportMethod: createExportMethod(getRangePickerCellValue),
};

15
apps/vue/src/components/VxeTable/src/components/ARate.tsx

@ -0,0 +1,15 @@
import {
createEditRender,
createDefaultRender,
createFilterRender,
createDefaultFilterRender,
createFormItemRender,
} from './common';
export default {
renderDefault: createDefaultRender(),
renderEdit: createEditRender(),
renderFilter: createFilterRender(),
defaultFilterMethod: createDefaultFilterRender(),
renderItemContent: createFormItemRender(),
};

271
apps/vue/src/components/VxeTable/src/components/ASelect.tsx

@ -0,0 +1,271 @@
import { ComponentOptions, h, resolveComponent } from 'vue';
import { VxeColumnPropTypes, VxeGlobalRendererHandles } from 'vxe-table';
import XEUtils from 'xe-utils';
import {
cellText,
createCellRender,
createEvents,
createProps,
isEmptyValue,
createExportMethod,
createFormItemRender,
} from './common';
function renderOptions(options: any[], optionProps: VxeGlobalRendererHandles.RenderOptionProps) {
const labelProp = optionProps.label || 'label';
const valueProp = optionProps.value || 'value';
return XEUtils.map(options, (item, oIndex) => {
return h(
resolveComponent('a-select-option') as ComponentOptions,
{
key: oIndex,
value: item[valueProp],
disabled: item.disabled,
},
{
default: () => cellText(item[labelProp]),
},
);
});
}
function createEditRender() {
return function (
renderOpts: VxeColumnPropTypes.EditRender,
params: VxeGlobalRendererHandles.RenderEditParams,
) {
const { options = [], optionGroups, optionProps = {}, optionGroupProps = {} } = renderOpts;
const { row, column, $table } = params;
const { attrs } = renderOpts;
const cellValue = XEUtils.get(row, column.field as string);
const props = createProps(renderOpts, cellValue);
const ons = createEvents(
renderOpts,
params,
(value: any) => {
// 处理 model 值双向绑定
XEUtils.set(row, column.field as string, value);
},
() => {
// 处理 change 事件相关逻辑
$table.updateStatus(params);
},
);
if (optionGroups) {
const groupOptions = optionGroupProps.options || 'options';
const groupLabel = optionGroupProps.label || 'label';
return [
h(
resolveComponent('a-select') as ComponentOptions,
{
...attrs,
...props,
...ons,
},
{
default: () => {
return XEUtils.map(optionGroups, (group, gIndex) => {
return h(
resolveComponent('a-select-opt-group') as ComponentOptions,
{
key: gIndex,
},
{
label: () => {
return h('span', {}, group[groupLabel]);
},
default: () => renderOptions(group[groupOptions], optionProps),
},
);
});
},
},
),
];
}
return [
h(
resolveComponent('a-select') as ComponentOptions,
{
...props,
...attrs,
...ons,
},
{
default: () => renderOptions(options, optionProps),
},
),
];
};
}
function getSelectCellValue(
renderOpts: VxeGlobalRendererHandles.RenderCellOptions,
params: VxeGlobalRendererHandles.RenderCellParams,
) {
const {
options = [],
optionGroups,
props = {},
optionProps = {},
optionGroupProps = {},
} = renderOpts;
const { row, column } = params;
const labelProp = optionProps.label || 'label';
const valueProp = optionProps.value || 'value';
const groupOptions = optionGroupProps.options || 'options';
const cellValue = XEUtils.get(row, column.field as string);
if (!isEmptyValue(cellValue)) {
return XEUtils.map(
props.mode === 'multiple' ? cellValue : [cellValue],
optionGroups
? (value) => {
let selectItem;
for (let index = 0; index < optionGroups.length; index++) {
selectItem = XEUtils.find(
optionGroups[index][groupOptions],
(item) => item[valueProp] === value,
);
if (selectItem) {
break;
}
}
return selectItem ? selectItem[labelProp] : value;
}
: (value) => {
const selectItem = XEUtils.find(options, (item) => item[valueProp] === value);
return selectItem ? selectItem[labelProp] : value;
},
).join(', ');
}
return '';
}
function createFilterRender() {
return function (
renderOpts: VxeColumnPropTypes.FilterRender,
params: VxeGlobalRendererHandles.RenderFilterParams,
) {
const { options = [], optionGroups, optionProps = {}, optionGroupProps = {} } = renderOpts;
const groupOptions = optionGroupProps.options || 'options';
const groupLabel = optionGroupProps.label || 'label';
const { column } = params;
const { attrs } = renderOpts;
return [
h(
'div',
{
class: 'vxe-table--filter-antd-wrapper',
},
optionGroups
? column.filters.map((option, oIndex) => {
const optionValue = option.data;
const props = createProps(renderOpts, optionValue);
return h(
resolveComponent('a-select') as ComponentOptions,
{
key: oIndex,
...attrs,
...props,
...createEvents(
renderOpts,
params,
(value: any) => {
// 处理 model 值双向绑定
option.data = value;
},
() => {
// 处理 change 事件相关逻辑
const { $panel } = params;
$panel.changeOption(
null,
props.mode === 'multiple'
? option.data && option.data.length > 0
: !XEUtils.eqNull(option.data),
option,
);
},
),
},
{
default: () => {
return XEUtils.map(optionGroups, (group, gIndex) => {
return h(
resolveComponent('a-select-opt-group') as ComponentOptions,
{
key: gIndex,
},
{
label: () => {
return h('span', {}, group[groupLabel]);
},
default: () => renderOptions(group[groupOptions], optionProps),
},
);
});
},
},
);
})
: column.filters.map((option, oIndex) => {
const optionValue = option.data;
const props = createProps(renderOpts, optionValue);
return h(
resolveComponent('a-select') as ComponentOptions,
{
key: oIndex,
...attrs,
...props,
...createEvents(
renderOpts,
params,
(value: any) => {
// 处理 model 值双向绑定
option.data = value;
},
() => {
// 处理 change 事件相关逻辑
const { $panel } = params;
$panel.changeOption(
null,
props.mode === 'multiple'
? option.data && option.data.length > 0
: !XEUtils.eqNull(option.data),
option,
);
},
),
},
{
default: () => renderOptions(options, optionProps),
},
);
}),
),
];
};
}
export default {
renderEdit: createEditRender(),
renderCell: createCellRender(getSelectCellValue),
renderFilter: createFilterRender(),
defaultFilterMethod(params) {
const { option, row, column } = params;
const { data } = option;
const { field, filterRender: renderOpts } = column;
const { props = {} } = renderOpts;
const cellValue = XEUtils.get(row, field);
if (props.mode === 'multiple') {
if (XEUtils.isArray(cellValue)) {
return XEUtils.includeArrays(cellValue, data);
}
return data.indexOf(cellValue) > -1;
}
return cellValue == data;
},
renderItemContent: createFormItemRender(),
exportMethod: createExportMethod(getSelectCellValue),
};

53
apps/vue/src/components/VxeTable/src/components/ASwitch.tsx

@ -0,0 +1,53 @@
import { h } from 'vue';
import XEUtils from 'xe-utils';
import {
createEditRender,
createDefaultRender,
createProps,
createEvents,
createDefaultFilterRender,
createFormItemRender,
getComponent,
} from './common';
export default {
renderDefault: createDefaultRender(),
renderEdit: createEditRender(),
renderFilter(renderOpts, params) {
const { column } = params;
const { name, attrs } = renderOpts;
const Component = getComponent(name);
return [
h(
'div',
{
class: 'vxe-table--filter-antd-wrapper',
},
column.filters.map((option, oIndex) => {
const optionValue = option.data;
return h(Component, {
key: oIndex,
...attrs,
...createProps(renderOpts, optionValue),
...createEvents(
renderOpts,
params,
(value: any) => {
// 处理 model 值双向绑定
option.data = value;
},
() => {
// 处理 change 事件相关逻辑
const { $panel } = params;
$panel.changeOption(null, XEUtils.isBoolean(option.data), option);
},
),
});
}),
),
];
},
defaultFilterMethod: createDefaultFilterRender(),
renderItemContent: createFormItemRender(),
};

18
apps/vue/src/components/VxeTable/src/components/ATimePicker.tsx

@ -0,0 +1,18 @@
import { getDatePickerCellValue } from './ADatePicker';
import {
createEditRender,
createCellRender,
createFormItemRender,
createExportMethod,
} from './common';
export default {
renderEdit: createEditRender(),
renderCell: createCellRender(getDatePickerCellValue, () => {
return ['HH:mm:ss'];
}),
renderItemContent: createFormItemRender(),
exportMethod: createExportMethod(getDatePickerCellValue, () => {
return ['HH:mm:ss'];
}),
};

35
apps/vue/src/components/VxeTable/src/components/ATreeSelect.tsx

@ -0,0 +1,35 @@
import { VxeGlobalRendererHandles } from 'vxe-table';
import XEUtils from 'xe-utils';
import {
createEditRender,
createCellRender,
isEmptyValue,
createFormItemRender,
createExportMethod,
} from './common';
function getTreeSelectCellValue(
renderOpts: VxeGlobalRendererHandles.RenderOptions,
params: VxeGlobalRendererHandles.RenderCellParams | VxeGlobalRendererHandles.ExportMethodParams,
) {
const { props = {} } = renderOpts;
const { treeData, treeCheckable } = props;
const { row, column } = params;
const cellValue = XEUtils.get(row, column.field as string);
if (!isEmptyValue(cellValue)) {
return XEUtils.map(treeCheckable ? cellValue : [cellValue], (value) => {
const matchObj = XEUtils.findTree(treeData, (item: any) => item.value === value, {
children: 'children',
});
return matchObj ? matchObj.item.title : value;
}).join(', ');
}
return cellValue;
}
export default {
renderEdit: createEditRender(),
renderCell: createCellRender(getTreeSelectCellValue),
renderItemContent: createFormItemRender(),
exportMethod: createExportMethod(getTreeSelectCellValue),
};

18
apps/vue/src/components/VxeTable/src/components/AWeekPicker.tsx

@ -0,0 +1,18 @@
import { getDatePickerCellValue } from './ADatePicker';
import {
createEditRender,
createCellRender,
createFormItemRender,
createExportMethod,
} from './common';
export default {
renderEdit: createEditRender(),
renderCell: createCellRender(getDatePickerCellValue, () => {
return ['YYYY-WW周'];
}),
renderItemContent: createFormItemRender(),
exportMethod: createExportMethod(getDatePickerCellValue, () => {
return ['YYYY-WW周'];
}),
};

18
apps/vue/src/components/VxeTable/src/components/AYearPicker.tsx

@ -0,0 +1,18 @@
import { getDatePickerCellValue } from './ADatePicker';
import {
createEditRender,
createCellRender,
createFormItemRender,
createExportMethod,
} from './common';
export default {
renderEdit: createEditRender(),
renderCell: createCellRender(getDatePickerCellValue, () => {
return ['YYYY'];
}),
renderItemContent: createFormItemRender(),
exportMethod: createExportMethod(getDatePickerCellValue, () => {
return ['YYYY'];
}),
};

427
apps/vue/src/components/VxeTable/src/components/common.tsx

@ -0,0 +1,427 @@
import { ComponentOptions, h } from 'vue';
import {
FormItemContentRenderParams,
FormItemRenderOptions,
VxeGlobalRendererHandles,
} from 'vxe-table';
import XEUtils from 'xe-utils';
import { componentMap } from '../componentMap';
import { ComponentType } from '../componentType';
import { createPlaceholderMessage } from '../helper';
/**
* @description: 获取组件
*/
export function getComponent(componentName) {
const Component = componentMap.get(componentName as ComponentType);
if (!Component) throw `您还没注册此组件 ${componentName}`;
return Component as ComponentOptions;
}
export function isEmptyValue(cellValue: any) {
return cellValue === null || cellValue === undefined || cellValue === '';
}
export function formatText(cellValue: any) {
return '' + (isEmptyValue(cellValue) ? '' : cellValue);
}
export function cellText(cellValue: any): string[] {
return [formatText(cellValue)];
}
/**
* @description: 方法名转换
*/
export function getOnName(type: string) {
return 'on' + type.substring(0, 1).toLocaleUpperCase() + type.substring(1);
}
/**
* @description: 获取组件传值所接受的属性
*/
function getModelKey(renderOpts: VxeGlobalRendererHandles.RenderOptions) {
let prop = 'value';
switch (renderOpts.name) {
case 'ASwitch':
prop = 'checked';
break;
}
return prop;
}
/**
* @description: 回去双向更新的方法
*/
function getModelEvent(renderOpts: VxeGlobalRendererHandles.RenderOptions) {
let type = 'update:value';
switch (renderOpts.name) {
case 'ASwitch':
type = 'update:checked';
break;
}
return type;
}
/**
* @description: chang值改变方法
* @param {}
* @return {*}
* @author: *
*/
function getChangeEvent() {
return 'change';
}
function getClickEvent() {
return 'click';
}
/**
* @description: 获取方法
* @param {}
* @return {*}
* @author: *
*/
export function createEvents(
renderOpts: VxeGlobalRendererHandles.RenderOptions,
params: VxeGlobalRendererHandles.RenderParams,
inputFunc?: Function,
changeFunc?: Function,
clickFunc?: Function,
) {
const { events } = renderOpts;
const modelEvent = getModelEvent(renderOpts);
const changeEvent = getChangeEvent();
const clickEvent = getClickEvent();
const isSameEvent = changeEvent === modelEvent;
const ons: { [type: string]: Function } = {};
XEUtils.objectEach(events, (func: Function, key: string) => {
ons[getOnName(key)] = function (...args: any[]) {
func(params, ...args);
};
});
if (inputFunc) {
ons[getOnName(modelEvent)] = function (targetEvnt: any) {
inputFunc(targetEvnt);
if (events && events[modelEvent]) {
events[modelEvent](params, targetEvnt);
}
if (isSameEvent && changeFunc) {
changeFunc(targetEvnt);
}
};
}
if (!isSameEvent && changeFunc) {
ons[getOnName(changeEvent)] = function (...args: any[]) {
changeFunc(...args);
if (events && events[changeEvent]) {
events[changeEvent](params, ...args);
}
};
}
if (clickFunc) {
ons[getOnName(clickEvent)] = function (...args: any[]) {
clickFunc(...args);
if (events && events[clickEvent]) {
events[clickEvent](params, ...args);
}
};
}
return ons;
}
/**
* @description: 获取属性
*/
export function createProps(
renderOpts: VxeGlobalRendererHandles.RenderOptions,
value: any,
defaultProps?: { [prop: string]: any },
) {
const name = renderOpts.name as ComponentType;
return XEUtils.assign(
{
placeholder: createPlaceholderMessage(name),
allowClear: true,
},
defaultProps,
renderOpts.props,
{
[getModelKey(renderOpts)]: value,
},
);
}
/**
* @description: 创建单元格默认显示内容
*/
export function createDefaultRender(
defaultProps?: { [key: string]: any },
callBack?: (
renderOpts: VxeGlobalRendererHandles.RenderDefaultOptions,
params: VxeGlobalRendererHandles.RenderDefaultParams,
) => Record<string, any>,
) {
return function (
renderOpts: VxeGlobalRendererHandles.RenderDefaultOptions,
params: VxeGlobalRendererHandles.RenderDefaultParams,
) {
const { row, column, $table } = params;
const { name, attrs } = renderOpts;
const cellValue = XEUtils.get(row, column.field as string);
const args = (callBack && callBack(renderOpts, params)) ?? {};
const Component = getComponent(name);
return [
h(Component, {
...attrs,
...createProps(renderOpts, cellValue, defaultProps),
...args,
...createEvents(
renderOpts,
params,
(value: any) => XEUtils.set(row, column.field as string, value),
() => $table.updateStatus(params),
),
}),
];
};
}
/**
* @description: 创建编辑单元格
*/
export function createEditRender(
defaultProps?: { [key: string]: any },
callBack?: (
renderOpts: VxeGlobalRendererHandles.RenderEditOptions,
params: VxeGlobalRendererHandles.RenderEditParams,
) => Record<string, any>,
) {
return function (
renderOpts: VxeGlobalRendererHandles.RenderEditOptions,
params: VxeGlobalRendererHandles.RenderEditParams,
) {
const { row, column, $table } = params;
const { name, attrs } = renderOpts;
const cellValue = XEUtils.get(row, column.field as string);
const args = (callBack && callBack(renderOpts, params)) ?? {};
const Component = getComponent(name);
return [
h(Component, {
...attrs,
...createProps(renderOpts, cellValue, defaultProps),
...args,
...createEvents(
renderOpts,
params,
(value: any) => XEUtils.set(row, column.field as string, value),
() => $table.updateStatus(params),
),
}),
];
};
}
/**
* @description: 创建筛选渲染内容
*/
export function createFilterRender(
defaultProps?: { [key: string]: any },
callBack?: (
renderOpts: VxeGlobalRendererHandles.RenderFilterOptions,
params: VxeGlobalRendererHandles.RenderFilterParams,
) => Record<string, any>,
) {
return function (
renderOpts: VxeGlobalRendererHandles.RenderFilterOptions,
params: VxeGlobalRendererHandles.RenderFilterParams,
) {
const { column } = params;
const { name, attrs } = renderOpts;
const args = (callBack && callBack(renderOpts, params)) ?? {};
const Component = getComponent(name);
return [
h(
'div',
{
class: 'vxe-table--filter-antd-wrapper',
},
column.filters.map((option, oIndex) => {
const optionValue = option.data;
const checked = !!option.data;
return h(Component, {
key: oIndex,
...attrs,
...createProps(renderOpts, optionValue, defaultProps),
...args,
...createEvents(
renderOpts,
params,
(value: any) => {
// 处理 model 值双向绑定
option.data = value;
},
() => {
// 处理 change 事件相关逻辑
const { $panel } = params;
$panel.changeOption(null, checked, option);
},
),
});
}),
),
];
};
}
/**
* @description: 默认过滤
* @param {}
* @return {*}
* @author: *
*/
export function createDefaultFilterRender() {
return function (params: VxeGlobalRendererHandles.FilterMethodParams) {
const { option, row, column } = params;
const { data } = option;
const cellValue = XEUtils.get(row, column.field as string);
return cellValue === data;
};
}
/**
* @description: 创建 form表单渲染
*/
export function createFormItemRender(
defaultProps?: { [key: string]: any },
callBack?: (
renderOpts: FormItemRenderOptions,
params: FormItemContentRenderParams,
) => Record<string, any>,
) {
return function (renderOpts: FormItemRenderOptions, params: FormItemContentRenderParams) {
const args = (callBack && callBack(renderOpts, params)) ?? {};
const { data, property, $form } = params;
const { name } = renderOpts;
const { attrs } = renderOpts;
const itemValue = XEUtils.get(data, property);
const Component = getComponent(name);
return [
h(Component, {
...attrs,
...createProps(renderOpts, itemValue, defaultProps),
...args,
...createEvents(
renderOpts,
params,
(value: any) => {
// 处理 model 值双向绑定
XEUtils.set(data, property, value);
},
() => {
// 处理 change 事件相关逻辑
$form.updateStatus({
...params,
field: property,
});
},
),
}),
];
};
}
/**
* @description: cell渲染
*/
export function createCellRender(
getSelectCellValue: Function,
callBack?: (
renderOpts: VxeGlobalRendererHandles.RenderCellOptions,
params: VxeGlobalRendererHandles.RenderCellParams,
) => Array<any>,
) {
return function (
renderOpts: VxeGlobalRendererHandles.RenderCellOptions,
params: VxeGlobalRendererHandles.RenderCellParams,
) {
const args = (callBack && callBack(renderOpts, params)) ?? [];
const cellLabel = getSelectCellValue && getSelectCellValue(renderOpts, params, ...args);
const { placeholder } = renderOpts;
return [
h(
'span',
{
class: 'vxe-cell--label',
},
placeholder && isEmptyValue(cellLabel)
? [
h(
'span',
{
class: 'vxe-cell--placeholder',
},
formatText(placeholder),
),
]
: formatText(cellLabel),
),
];
};
}
/**
* @description: 创建 导出渲染
* @param {}
* @return {*}
* @author: *
*/
export function createExportMethod(
getExportCellValue: Function,
callBack?: (params: VxeGlobalRendererHandles.ExportMethodParams) => Array<any>,
) {
return function (params: VxeGlobalRendererHandles.ExportMethodParams) {
const { row, column, options } = params;
const args = (callBack && callBack(params)) ?? [];
return options && options.original
? XEUtils.get(row, column.field as string)
: getExportCellValue(column.editRender || column.cellRender, params, ...args);
};
}
/**
* @description: 创建单元格默认显示内容
*/
export function createToolbarToolRender(
defaultProps?: { [key: string]: any },
callBack?: (
renderOpts: VxeGlobalRendererHandles.RenderToolOptions,
params: VxeGlobalRendererHandles.RenderToolParams,
) => Record<string, any>,
) {
return function (
renderOpts: VxeGlobalRendererHandles.RenderToolOptions,
params: VxeGlobalRendererHandles.RenderToolParams,
) {
const { name, attrs } = renderOpts;
const args = (callBack && callBack(renderOpts, params)) ?? {};
const Component = getComponent(name);
return [
h(Component, {
...attrs,
...createProps(renderOpts, null, defaultProps),
...args,
...createEvents(renderOpts, params),
}),
];
};
}

112
apps/vue/src/components/VxeTable/src/components/index.tsx

@ -0,0 +1,112 @@
import { VXETableCore, VxeGlobalInterceptorHandles } from 'vxe-table';
import AAutoComplete from './AAutoComplete';
import AInput from './AInput';
import AInputNumber from './AInputNumber';
import ASelect from './ASelect';
import ACascader from './ACascader';
import ADatePicker from './ADatePicker';
import AMonthPicker from './AMonthPicker';
import ARangePicker from './ARangePicker';
import AWeekPicker from './AWeekPicker';
import ATreeSelect from './ATreeSelect';
import ATimePicker from './ATimePicker';
import ARate from './ARate';
import ASwitch from './ASwitch';
import ARadioGroup from './ARadioGroup';
import ACheckboxGroup from './ACheckboxGroup';
import AButton from './AButton';
import AButtonGroup from './AButtonGroup';
import AApiSelect from './AApiSelect';
import AEmpty from './AEmpty';
import AInputSearch from './AInputSearch';
import AYearPicker from './AYearPicker';
/**
* 检查触发源是否属于目标节点
*/
function getEventTargetNode(evnt: any, container: HTMLElement, className: string) {
let targetElem;
let target = evnt.target;
while (target && target.nodeType && target !== document) {
if (
className &&
target.className &&
target.className.split &&
target.className.split(' ').indexOf(className) > -1
) {
targetElem = target;
} else if (target === container) {
return { flag: className ? !!targetElem : true, container, targetElem: targetElem };
}
target = target.parentNode;
}
return { flag: false };
}
/**
* 事件兼容性处理
*/
function handleClearEvent(
params:
| VxeGlobalInterceptorHandles.InterceptorClearFilterParams
| VxeGlobalInterceptorHandles.InterceptorClearActivedParams
| VxeGlobalInterceptorHandles.InterceptorClearAreasParams,
) {
const { $event } = params;
const bodyElem = document.body;
if (
// 下拉框
getEventTargetNode($event, bodyElem, 'ant-select-dropdown').flag ||
// 级联
getEventTargetNode($event, bodyElem, 'ant-cascader-menus').flag ||
// 日期
getEventTargetNode($event, bodyElem, 'ant-calendar-picker-container').flag ||
// 时间选择
getEventTargetNode($event, bodyElem, 'ant-time-picker-panel').flag
) {
return false;
}
}
/**
* 基于 vxe-table 表格的适配插件,用于兼容 ant-design-vue 组件库
*/
export const VXETablePluginAntd = {
install(vxetablecore: VXETableCore) {
const { interceptor, renderer } = vxetablecore;
renderer.mixin({
AAutoComplete,
AInput,
AInputNumber,
ASelect,
ACascader,
ADatePicker,
AMonthPicker,
ARangePicker,
AWeekPicker,
ATimePicker,
ATreeSelect,
ARate,
ASwitch,
ARadioGroup,
ACheckboxGroup,
AButton,
AButtonGroup,
AApiSelect,
AEmpty,
AInputSearch,
AYearPicker,
});
interceptor.add('event.clearFilter', handleClearEvent);
interceptor.add('event.clearActived', handleClearEvent);
interceptor.add('event.clearAreas', handleClearEvent);
},
};
if (typeof window !== 'undefined' && window.VXETable && window.VXETable.use) {
window.VXETable.use(VXETablePluginAntd);
}
export default VXETablePluginAntd;

4
apps/vue/src/components/VxeTable/src/const.ts

@ -0,0 +1,4 @@
/**
* @description: 传给vxe-table 时需要忽略的prop
*/
export const ignorePropKeys = ['tableClass', 'tableStyle'];

8
apps/vue/src/components/VxeTable/src/css/common.scss

@ -0,0 +1,8 @@
*,
::before,
::after {
box-sizing: border-box;
border-width: 0;
border-style: solid;
border-color: initial;
}

105
apps/vue/src/components/VxeTable/src/css/component.scss

@ -0,0 +1,105 @@
%ResetBorder {
border: 0;
box-shadow: none;
}
%CompWidth {
& > .ant-input,
& > .ant-input-number,
& > .ant-select,
& > .ant-cascader-picker,
& > .ant-calendar-picker,
& > .ant-time-picker {
width: 100%;
}
}
.vxe-form {
.vxe-form--item-content {
@extend %CompWidth;
}
}
.vxe-table--filter-antd-wrapper {
& > .ant-input,
& > .ant-input-number,
& > .ant-select,
& > .ant-rate {
width: 180px;
}
}
.vxe-cell,
.vxe-tree-cell {
@extend %CompWidth;
& > .ant-rate {
vertical-align: bottom;
.anticon-star {
display: block;
}
}
}
.col--valid-error {
& > .vxe-cell,
& > .vxe-tree-cell {
& > .ant-input,
& > .ant-select .ant-input,
& > .ant-select .ant-select-selection,
& > .ant-input-number,
& > .ant-cascader-picker .ant-cascader-input,
& > .ant-calendar-picker .ant-calendar-picker-input {
// border-color: $vxe-table-validate-error-color;
box-shadow: none;
}
}
}
.vxe-table.cell--highlight {
.vxe-cell,
.vxe-tree-cell {
& > .ant-input,
& > .ant-input-number {
padding: 0;
@extend %ResetBorder;
}
& > .ant-select {
.ant-input {
padding: 0;
@extend %ResetBorder;
}
}
& > .ant-input-number {
.ant-input-number-input {
padding: 0;
}
.ant-input-number-handler-wrap,
.ant-input-number-handler-down {
@extend %ResetBorder;
}
}
& > .ant-select {
.ant-select-selection {
@extend %ResetBorder;
.ant-select-selection__rendered {
margin: 0;
}
}
}
& > .ant-cascader-picker {
.ant-input {
@extend %ResetBorder;
}
.ant-cascader-picker-label {
padding: 0;
}
}
& > .ant-calendar-picker {
.ant-calendar-picker-input {
padding: 0;
@extend %ResetBorder;
}
}
& > .ant-time-picker {
.ant-time-picker-input {
padding: 0;
@extend %ResetBorder;
}
}
}
}

6
apps/vue/src/components/VxeTable/src/css/index.scss

@ -0,0 +1,6 @@
@import './common.scss';
@import './variable.scss';
@import './scrollbar.scss';
@import './toolbar.scss';
@import './component.scss';
@import 'vxe-table/styles/index.scss';

24
apps/vue/src/components/VxeTable/src/css/scrollbar.scss

@ -0,0 +1,24 @@
.vxe-grid_scrollbar {
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-track {
background-color: #ffffff;
}
::-webkit-scrollbar-thumb {
background-color: rgba(0, 0, 0, 0.1);
border-radius: 5px;
border: 1px solid #f1f1f1;
box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
}
::-webkit-scrollbar-thumb:hover {
background-color: #a8a8a8;
}
::-webkit-scrollbar-thumb:active {
background-color: #a8a8a8;
}
::-webkit-scrollbar-corner {
background-color: #ffffff;
}
}

30
apps/vue/src/components/VxeTable/src/css/toolbar.scss

@ -0,0 +1,30 @@
.vxe-toolbar .vxe-custom--option-wrapper .vxe-custom--footer {
display: flex;
}
.vxe-toolbar .vxe-tools--wrapper,
.vxe-toolbar .vxe-tools--operate button:first-child {
margin: 0;
}
.vxe-toolbar .vxe-tools--wrapper,
.vxe-toolbar .vxe-tools--operate .vxe-button {
margin-left: 1px;
border-radius: 0 !important;
}
.vxe-toolbar .vxe-tools--wrapper,
.vxe-toolbar .vxe-tools--operate button:first-child {
margin-left: 10px;
}
.vxe-toolbar .vxe-tools--wrapper,
.vxe-toolbar .vxe-tools--operate .vxe-custom--wrapper {
margin-left: 1px;
border-radius: 0 !important;
}
.vxe-toolbar .vxe-tools--wrapper,
.vxe-toolbar .vxe-tools--operate .vxe-custom--wrapper .vxe-button {
margin-left: 1px;
}

6
apps/vue/src/components/VxeTable/src/css/variable.scss

@ -0,0 +1,6 @@
$vxe-primary-color: rgb(9, 96, 189) !default;
$vxe-table-row-current-background-color: rgba(9, 96, 189, 0.3);
$vxe-table-row-hover-current-background-color: rgba(9, 96, 189, 0.2);
$vxe-table-column-hover-background-color: rgba(9, 96, 189, 0.3);
$vxe-table-column-current-background-color: rgba(9, 96, 189, 0.2);
$vxe-table-validate-error-color: #f56c6c;

17
apps/vue/src/components/VxeTable/src/emits.ts

@ -0,0 +1,17 @@
import tableEmits from 'vxe-table/es/table/src/emits';
export const basicEmits = [
...tableEmits,
'page-change',
'form-submit',
'form-submit-invalid',
'form-reset',
'form-collapse',
'form-toggle-collapse',
'toolbar-button-click',
'toolbar-tool-click',
'zoom',
//... 如有缺少在此处追加
// xxx
];

19
apps/vue/src/components/VxeTable/src/helper.ts

@ -0,0 +1,19 @@
import { ComponentType } from './componentType';
import { useI18n } from '/@/hooks/web/useI18n';
const { t } = useI18n();
/**
* @description: 生成placeholder
*/
export function createPlaceholderMessage(component: ComponentType) {
if (!component) return;
if (component.includes('RangePicker')) {
return [t('common.chooseText'), t('common.chooseText')];
}
if (component.includes('Input') || component.includes('Complete') || component.includes('Rate')) {
return t('common.inputText');
} else {
return t('common.chooseText');
}
}

131
apps/vue/src/components/VxeTable/src/methods.ts

@ -0,0 +1,131 @@
import { GridMethods, TableMethods } from 'vxe-table';
export const gridComponentMethodKeys: (keyof GridMethods | keyof TableMethods)[] = [
// vxe-grid 部分
'dispatchEvent',
'commitProxy',
'getFormItems',
'getPendingRecords',
'zoom',
'isMaximized',
'maximize',
'revert',
'getProxyInfo',
// vxe-table和vxe-grid公共部分
'clearAll',
'syncData',
'updateData',
'loadData',
'reloadData',
'reloadRow',
'loadColumn',
'reloadColumn',
'getRowNode',
'getColumnNode',
'getRowIndex',
'getVTRowIndex',
'getVMRowIndex',
'getColumnIndex',
'getVTColumnIndex',
'getVMColumnIndex',
'createData',
'createRow',
'revertData',
'clearData',
'isInsertByRow',
'isUpdateByRow',
'getColumns',
'getColumnById',
'getColumnByField',
'getTableColumn',
'getData',
'getCheckboxRecords',
'getParentRow',
'getRowSeq',
'getRowById',
'getRowid',
'getTableData',
'hideColumn',
'showColumn',
'resetColumn',
'refreshColumn',
'refreshScroll',
'recalculate',
'closeTooltip',
'isAllCheckboxChecked',
'isAllCheckboxIndeterminate',
'getCheckboxIndeterminateRecords',
'setCheckboxRow',
'isCheckedByCheckboxRow',
'isIndeterminateByCheckboxRow',
'toggleCheckboxRow',
'setAllCheckboxRow',
'getRadioReserveRecord',
'clearRadioReserve',
'getCheckboxReserveRecords',
'clearCheckboxReserve',
'toggleAllCheckboxRow',
'clearCheckboxRow',
'setCurrentRow',
'isCheckedByRadioRow',
'setRadioRow',
'clearCurrentRow',
'clearRadioRow',
'getCurrentRecord',
'getRadioRecord',
'getCurrentColumn',
'setCurrentColumn',
'clearCurrentColumn',
'sort',
'clearSort',
'isSort',
'getSortColumns',
'closeFilter',
'isFilter',
'isRowExpandLoaded',
'clearRowExpandLoaded',
'reloadRowExpand',
'reloadRowExpand',
'toggleRowExpand',
'setAllRowExpand',
'setRowExpand',
'isExpandByRow',
'clearRowExpand',
'clearRowExpandReserve',
'getRowExpandRecords',
'getTreeExpandRecords',
'isTreeExpandLoaded',
'clearTreeExpandLoaded',
'reloadTreeExpand',
'reloadTreeChilds',
'toggleTreeExpand',
'setAllTreeExpand',
'setTreeExpand',
'isTreeExpandByRow',
'clearTreeExpand',
'clearTreeExpandReserve',
'getScroll',
'scrollTo',
'scrollToRow',
'scrollToColumn',
'clearScroll',
'updateFooter',
'updateStatus',
'setMergeCells',
'removeInsertRow',
'removeMergeCells',
'getMergeCells',
'clearMergeCells',
'setMergeFooterItems',
'removeMergeFooterItems',
'getMergeFooterItems',
'clearMergeFooterItems',
'openTooltip',
'focus',
'blur',
'connect',
//... 如有缺少在此处追加
// xxx
];

52
apps/vue/src/components/VxeTable/src/props.ts

@ -0,0 +1,52 @@
import { VxeGridPropTypes, VxeTablePropTypes } from 'vxe-table';
import tableProps from 'vxe-table/es/table/src/props';
import { CSSProperties } from 'vue';
/**
* @description: table二次开发需要后,需要接受的所有prop属性
*/
export const basicProps = {
...tableProps,
columns: Array as PropType<VxeGridPropTypes.Columns>,
pagerConfig: {
type: Object as PropType<VxeGridPropTypes.PagerConfig>,
default: () => ({}),
},
proxyConfig: {
type: Object as PropType<VxeGridPropTypes.ProxyConfig>,
default: () => ({}),
},
toolbarConfig: {
type: Object as PropType<VxeGridPropTypes.ToolbarConfig>,
default: () => ({}),
},
formConfig: {
type: Object as PropType<VxeGridPropTypes.FormConfig>,
default: () => ({}),
},
zoomConfig: {
type: Object as PropType<VxeGridPropTypes.ZoomConfig>,
default: () => ({}),
},
printConfig: {
type: Object as PropType<VxeTablePropTypes.PrintConfig>,
default: () => ({}),
},
exportConfig: {
type: Object as PropType<VxeTablePropTypes.ExportConfig>,
default: () => ({}),
},
importConfig: {
type: Object as PropType<VxeTablePropTypes.ImportConfig>,
default: () => ({}),
},
size: String as PropType<VxeGridPropTypes.Size>,
tableClass: {
type: String,
default: '',
},
tableStyle: {
type: Object as PropType<CSSProperties>,
default: () => ({}),
},
};

4
apps/vue/src/components/VxeTable/src/setting.ts

@ -0,0 +1,4 @@
import { VXETable } from '..';
import componentSetting from '/@/settings/componentSetting';
VXETable.setup(componentSetting.vxeTable);

7
apps/vue/src/components/VxeTable/src/types.ts

@ -0,0 +1,7 @@
import { CSSProperties } from 'vue';
import { VxeGridProps } from 'vxe-table';
export type BasicTableProps = VxeGridProps & {
tableClass?: string;
tableStyle?: CSSProperties;
};

3
apps/vue/src/components/registerGlobComp.ts

@ -56,6 +56,7 @@ import {
Input as AInput, Input as AInput,
InputNumber as AInputNumber, InputNumber as AInputNumber,
} from 'ant-design-vue'; } from 'ant-design-vue';
import VXETable from 'vxe-table';
const compList = [ const compList = [
Affix, Affix,
@ -157,5 +158,5 @@ export function registerGlobComp(app: App) {
app.component(comp.name || comp.displayName, comp); app.component(comp.name || comp.displayName, comp);
}); });
app.use(Input).use(Button).use(Layout); app.use(Input).use(Button).use(Layout).use(VXETable);
} }

1
apps/vue/src/main.ts

@ -1,6 +1,7 @@
import 'virtual:windi-base.css'; import 'virtual:windi-base.css';
import 'virtual:windi-components.css'; import 'virtual:windi-components.css';
import '/@/design/index.less'; import '/@/design/index.less';
import '/@/components/VxeTable/src/css/index.scss';
import 'virtual:windi-utilities.css'; import 'virtual:windi-utilities.css';
// Register icon sprite // Register icon sprite
import 'virtual:svg-icons-register'; import 'virtual:svg-icons-register';

46
apps/vue/src/settings/componentSetting.ts

@ -52,6 +52,52 @@ export default {
return data; return data;
}, },
}, },
vxeTable: {
table: {
border: true,
stripe: true,
columnConfig: {
resizable: true,
isCurrent: true,
isHover: true,
},
rowConfig: {
isCurrent: true,
isHover: true,
},
emptyRender: {
name: 'AEmpty',
},
printConfig: {},
exportConfig: {},
customConfig: {
storage: true,
},
},
grid: {
toolbarConfig: {
enabled: true,
export: true,
zoom: true,
print: true,
refresh: true,
custom: true,
},
pagerConfig: {
pageSizes: [20, 50, 100, 500],
pageSize: 20,
autoHidden: true,
},
proxyConfig: {
form: true,
props: {
result: 'items',
total: 'total',
},
},
zoomConfig: {},
},
},
// scrollbar setting // scrollbar setting
scrollbar: { scrollbar: {
// Whether to use native scroll bar // Whether to use native scroll bar

Loading…
Cancel
Save