├── .eslintrc.js ├── .gitee ├── ISSUE_TEMPLATE.en.md ├── ISSUE_TEMPLATE.md └── ISSUE_TEMPLATE.zh-TW.md ├── .github └── ISSUE_TEMPLATE │ ├── bug_report.yml │ └── feature_request.yml ├── .gitignore ├── LICENSE ├── README.md ├── gulpfile.js ├── index.ts ├── package.json ├── style.scss ├── tsconfig.json └── types └── index.d.ts /.eslintrc.js: -------------------------------------------------------------------------------- 1 | // https://eslint.org/docs/user-guide/configuring 2 | 3 | module.exports = { 4 | root: true, 5 | parser: '@typescript-eslint/parser', 6 | parserOptions: { 7 | ecmaVersion: 6, 8 | sourceType: 'module', 9 | ecmaFeatures: { 10 | impliedStrict: true, 11 | objectLiteralDuplicateProperties: false 12 | } 13 | }, 14 | env: { 15 | amd: true, 16 | browser: true, 17 | node: true 18 | }, 19 | plugins: [ 20 | '@typescript-eslint' 21 | ], 22 | extends: [ 23 | 'prettier/@typescript-eslint', 24 | 'standard' 25 | ], 26 | rules: { 27 | 'array-bracket-spacing': ['error', 'never'], 28 | 'no-debugger': ['error'], 29 | 'keyword-spacing': ['error'] 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /.gitee/ISSUE_TEMPLATE.en.md: -------------------------------------------------------------------------------- 1 | **(Required) Describe the bug or screenshots:** 2 | ? 3 | 4 | **(Required) Reproduction link:** 5 | ? 6 | 7 | **(Required) Expected behavior:** 8 | ? 9 | 10 | **(Required) Please fill in the version information:** 11 | 12 | - OS: ? 13 | - Browser: ? 14 | - vue: ? 15 | - vxe-table: ? 16 | -------------------------------------------------------------------------------- /.gitee/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | **(必填)请填写问题描述或截图:** 2 | ? 3 | 4 | **(必填)请填重在线链接:** 5 | ? 6 | 7 | **(必填)请填写期望的结果:** 8 | ? 9 | 10 | **(必填)请填写以下信息:** 11 | 12 | - OS: ? 13 | - Browser: ? 14 | - vue: ? 15 | - vxe-table: ? 16 | -------------------------------------------------------------------------------- /.gitee/ISSUE_TEMPLATE.zh-TW.md: -------------------------------------------------------------------------------- 1 | **(必填)請填寫問題描述或截圖:** 2 | ? 3 | 4 | **(必填)請填重線上連結:** 5 | ? 6 | 7 | **(必填)請填寫期望的結果:** 8 | ? 9 | 10 | **(必填)請填寫以下資訊:** 11 | 12 | - OS: ? 13 | - Browser: ? 14 | - vue: ? 15 | - vxe-table: ? 16 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: Bug report 2 | description: 反馈问题 3 | labels: bug 4 | body: 5 | - type: input 6 | id: issue_link 7 | attributes: 8 | label: "可复现的链接:" 9 | description: "一个最小化的重现示例能让我们精确地定位问题,从而快速解决问题。如何创建,点击 v3:[codesandbox](https://codesandbox.io/s/vue-template-916h0)、[jsfiddle](https://jsfiddle.net/86p7Ltny/)、[jsrun](https://jsrun.net/vIyKp/edit) 或 v4:[codesandbox](https://codesandbox.io/s/vxe-table-wentiyanshi-forked-54v2j)、[jsfiddle](https://jsfiddle.net/9qoghkbj/)、[jsrun](https://jsrun.net/K5IKp/edit),将代码示例编辑后保存。" 10 | validations: 11 | required: true 12 | - type: textarea 13 | id: issue_describe 14 | attributes: 15 | label: "问题描述与截图:" 16 | validations: 17 | required: true 18 | - type: markdown 19 | attributes: 20 | value: "在发布问题之前,请仔细阅读所填写的步骤,以确保是详细和清晰的。" 21 | - type: input 22 | id: issue_expect 23 | attributes: 24 | label: "期望的结果:" 25 | - type: input 26 | id: issue_os_version 27 | attributes: 28 | label: "操作系统:" 29 | placeholder: "例如:window10" 30 | validations: 31 | required: true 32 | - type: input 33 | id: issue_browser_version 34 | attributes: 35 | label: "浏览器版本:" 36 | placeholder: "例如:chrome 95.0.4638.69" 37 | validations: 38 | required: true 39 | - type: input 40 | id: issue_vue_version 41 | attributes: 42 | label: "vue 版本:" 43 | placeholder: "例如:2.6.0" 44 | validations: 45 | required: true 46 | - type: input 47 | id: issue_vxe_version 48 | attributes: 49 | label: "vxe-table 版本:" 50 | placeholder: "例如:3.4.0" 51 | validations: 52 | required: true 53 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.yml: -------------------------------------------------------------------------------- 1 | name: Feature request 2 | description: 功能需求 3 | labels: enhancement 4 | body: 5 | - type: textarea 6 | id: issue_describe 7 | attributes: 8 | label: "这个需求解决了什么问题:" 9 | validations: 10 | required: true 11 | - type: markdown 12 | attributes: 13 | value: "请先查看[最新文档](https://xuliangzhan_admin.gitee.io/vxe-table/#/table/api),确定该功能是否已有实现" 14 | - type: textarea 15 | id: issue_api_describe 16 | attributes: 17 | label: "建议的 API 是什么样的:" 18 | - type: markdown 19 | attributes: 20 | value: "描述一下希望该功能如何调用" 21 | - type: textarea 22 | id: issue_alternative_solution 23 | attributes: 24 | label: "是否已有其他不错的替代方案:" 25 | - type: markdown 26 | attributes: 27 | value: "如果有其他已实现的方案,可以通过链接或截图描述一下" 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .history 3 | node_modules 4 | /dist 5 | package-lock.json 6 | yarn.lock 7 | 8 | # local env files 9 | .env.local 10 | .env.*.local 11 | 12 | # Log files 13 | npm-debug.log* 14 | yarn-debug.log* 15 | yarn-error.log* 16 | 17 | # Editor directories and files 18 | .idea 19 | .vscode 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Xu Liangzhan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vxe-table-plugin-element 2 | 3 | [![gitee star](https://gitee.com/x-extends/vxe-table-plugin-element/badge/star.svg?theme=dark)](https://gitee.com/x-extends/vxe-table-plugin-element/stargazers) 4 | [![npm version](https://img.shields.io/npm/v/vxe-table-plugin-element.svg?style=flat-square)](https://www.npmjs.com/package/vxe-table-plugin-element) 5 | [![npm downloads](https://img.shields.io/npm/dm/vxe-table-plugin-element.svg?style=flat-square)](http://npm-stat.com/charts.html?package=vxe-table-plugin-element) 6 | [![npm license](https://img.shields.io/github/license/mashape/apistatus.svg)](LICENSE) 7 | 8 | 基于 [vxe-table](https://www.npmjs.com/package/vxe-table) 表格的适配插件,用于兼容 [element-plus](https://github.com/element-plus/element-plus) 组件库 9 | 10 | ## Compatibility 11 | 12 | 对应 vxe-table v4 版本 13 | 如果您使用的是 vxe-table 4.7+ 最新版本,建议使用更强大的 [@vxe-ui/plugin-render-element](https://vxeui.com/other4/#/plugin-render-element/grid/edit/el-input) 适配器,代码完全兼容 14 | 15 | ## Installing 16 | 17 | ```shell 18 | npm install vxe-table@next vxe-table-plugin-element@next element-plus 19 | ``` 20 | 21 | ```javascript 22 | // ... 23 | import VXETable from 'vxe-table' 24 | import VXETablePluginElement from 'vxe-table-plugin-element' 25 | import 'vxe-table-plugin-element/dist/style.css' 26 | // ... 27 | 28 | VXETable.use(VXETablePluginElement) 29 | ``` 30 | 31 | ## API 32 | 33 | ### cell-render 默认的渲染配置项说明 34 | 35 | | 属性 | 描述 | 类型 | 可选值 | 默认值 | 36 | |------|------|-----|-----|-----| 37 | | name | 支持的渲染组件 | String | ElInput, ElAutocomplete, ElInputNumber, ElSwitch, ElRate, ElSlider, ElButton, ElButtons | — | 38 | | attrs | 渲染组件附加属性,参数请查看被渲染的 Component attrs | Object | — | {} | 39 | | props | 渲染组件附加属性,参数请查看被渲染的 Component props | Object | — | {} | 40 | | options | 只对 name=ElSelect 有效,下拉组件选项列表 | Array | — | [] | 41 | | optionProps | 只对 name=ElSelect 有效,下拉组件选项属性参数配置 | Object | — | { value: 'value', label: 'label' } | 42 | | optionGroups | 只对 name=ElSelect 有效,下拉组件分组选项列表 | Array | — | [] | 43 | | optionGroupProps | 只对 name=ElSelect 有效,下拉组件分组选项属性参数配置 | Object | — | { options: 'options', label: 'label' } | 44 | | events | 渲染组件附加事件,参数为 ( {row,rowIndex,column,columnIndex}, ...Component arguments ) | Object | — | — | 45 | | nativeEvents | 渲染组件附加事件,参数为 ( {row,rowIndex,column,columnIndex}, ...Component arguments ) | Object | — | — | 46 | 47 | ### edit-render 可编辑渲染器配置项说明 48 | 49 | | 属性 | 描述 | 类型 | 可选值 | 默认值 | 50 | |------|------|-----|-----|-----| 51 | | name | 支持的渲染组件 | String | ElInput, ElAutocomplete, ElInputNumber, ElSelect, ElCascader, ElTimeSelect, ElTimePicker, ElDatePicker, ElSwitch, ElRate, ElSlider, ElButton, ElButtons | — | 52 | | attrs | 渲染组件附加属性,参数请查看被渲染的 Component attrs | Object | — | {} | 53 | | props | 渲染组件附加属性,参数请查看被渲染的 Component props | Object | — | {} | 54 | | options | 只对 name=ElSelect 有效,下拉组件选项列表 | Array | — | [] | 55 | | optionProps | 只对 name=ElSelect 有效,下拉组件选项属性参数配置 | Object | — | { value: 'value', label: 'label' } | 56 | | optionGroups | 只对 name=ElSelect 有效,下拉组件分组选项列表 | Array | — | [] | 57 | | optionGroupProps | 只对 name=ElSelect 有效,下拉组件分组选项属性参数配置 | Object | — | { options: 'options', label: 'label' } | 58 | | events | 渲染组件附加事件,参数为 ( {row,rowIndex,column,columnIndex}, ...Component arguments ) | Object | — | — | 59 | | nativeEvents | 渲染组件附加事件,参数为 ( {row,rowIndex,column,columnIndex}, ...Component arguments ) | Object | — | — | 60 | 61 | ### filter-render 筛选渲染器配置项说明 62 | 63 | | 属性 | 描述 | 类型 | 可选值 | 默认值 | 64 | |------|------|-----|-----|-----| 65 | | name | 支持的渲染组件 | String | ElInput, ElInputNumber, ElAutocomplete, ElSelect, ElDatePicker, ElSwitch, ElRate, ElSlider | — | 66 | | attrs | 渲染组件附加属性,参数请查看被渲染的 Component attrs | Object | — | {} | 67 | | props | 渲染组件附加属性,参数请查看被渲染的 Component props | Object | — | {} | 68 | | options | 只对 name=ElSelect 有效,下拉组件选项列表 | Array | — | [] | 69 | | optionProps | 只对 name=ElSelect 有效,下拉组件选项属性参数配置 | Object | — | { value: 'value', label: 'label' } | 70 | | optionGroups | 只对 name=ElSelect 有效,下拉组件分组选项列表 | Array | — | [] | 71 | | optionGroupProps | 只对 name=ElSelect 有效,下拉组件分组选项属性参数配置 | Object | — | { options: 'options', label: 'label' } | 72 | | events | 渲染组件附加事件,参数为 ( {}, ...Component arguments ) | Object | — | — | 73 | | nativeEvents | 渲染组件附加事件,参数为 ( {}, ...Component arguments ) | Object | — | — | 74 | 75 | ### item-render 表单-项渲染器配置项说明 76 | 77 | | 属性 | 描述 | 类型 | 可选值 | 默认值 | 78 | |------|------|-----|-----|-----| 79 | | name | 支持的渲染组件 | String | ElInput, ElInputNumber, ElAutocomplete, ElSelect, ElDatePicker, ElSwitch, ElRate, ElSlider, ElRadio, ElCheckbox, ElButton, ElButtons | — | 80 | | attrs | 渲染组件附加属性,参数请查看被渲染的 Component attrs | Object | — | {} | 81 | | props | 渲染组件附加属性,参数请查看被渲染的 Component props | Object | — | {} | 82 | | options | 只对 name=ElSelect 有效,下拉组件选项列表 | Array | — | [] | 83 | | optionProps | 只对 name=ElSelect 有效,下拉组件选项属性参数配置 | Object | — | { value: 'value', label: 'label' } | 84 | | optionGroups | 只对 name=ElSelect 有效,下拉组件分组选项列表 | Array | — | [] | 85 | | optionGroupProps | 只对 name=ElSelect 有效,下拉组件分组选项属性参数配置 | Object | — | { options: 'options', label: 'label' } | 86 | | events | 渲染组件附加事件,参数为 ( {}, ...Component arguments ) | Object | — | — | 87 | | nativeEvents | 渲染组件附加事件,参数为 ( {}, ...Component arguments ) | Object | — | — | 88 | 89 | ## Cell demo 90 | 91 | ```html 92 | 96 | 97 | 100 | 101 | 102 | 105 | 106 | 107 | 110 | 111 | 112 | ``` 113 | 114 | ```javascript 115 | export default { 116 | data () { 117 | return { 118 | tableData: [ 119 | { id: 100, name: 'test0', age: 28, sex: '1', date: null }, 120 | { id: 101, name: 'test1', age: 32, sex: '0', date: null }, 121 | { id: 102, name: 'test2', age: 36, sex: '1', date: null } 122 | ] 123 | } 124 | } 125 | } 126 | ``` 127 | 128 | ## Filter demo 129 | 130 | ```html 131 | 134 | 135 | 136 | 137 | 140 | 141 | 142 | ``` 143 | 144 | ```javascript 145 | import { defineComponent } from 'vue' 146 | 147 | export default defineComponent({ 148 | setup () { 149 | return { 150 | tableData: [ 151 | { id: 100, name: 'test0', age: 28, date: null }, 152 | { id: 101, name: 'test1', age: 32, date: null }, 153 | { id: 102, name: 'test2', age: 36, date: null } 154 | ] 155 | } 156 | } 157 | }) 158 | ``` 159 | 160 | ## License 161 | 162 | [MIT](LICENSE) © 2019-present, Xu Liangzhan 163 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp') 2 | const del = require('del') 3 | const uglify = require('gulp-uglify') 4 | const babel = require('gulp-babel') 5 | const rename = require('gulp-rename') 6 | // const replace = require('gulp-replace') 7 | const dartSass = require('sass') 8 | const gulpSass = require('gulp-sass') 9 | const sass = gulpSass(dartSass) 10 | const cleanCSS = require('gulp-clean-css') 11 | const prefixer = require('gulp-autoprefixer') 12 | const sourcemaps = require('gulp-sourcemaps') 13 | const ts = require('gulp-typescript') 14 | const pack = require('./package.json') 15 | const tsconfig = require('./tsconfig.json') 16 | 17 | const exportModuleName = 'VXETablePluginElement' 18 | 19 | gulp.task('build_style', function () { 20 | return gulp.src('style.scss') 21 | .pipe(sass()) 22 | .pipe(prefixer({ 23 | borwsers: ['last 1 version', '> 1%', 'not ie <= 8'], 24 | cascade: true, 25 | remove: true 26 | })) 27 | .pipe(gulp.dest('dist')) 28 | .pipe(cleanCSS()) 29 | .pipe(rename({ 30 | extname: '.min.css' 31 | })) 32 | .pipe(gulp.dest('dist')) 33 | }) 34 | 35 | gulp.task('build_commonjs', function () { 36 | return gulp.src(['index.ts']) 37 | // .pipe(sourcemaps.init()) 38 | .pipe(ts(tsconfig.compilerOptions)) 39 | .pipe(babel({ 40 | presets: ['@babel/env'] 41 | })) 42 | .pipe(rename({ 43 | basename: 'index', 44 | extname: '.common.js' 45 | })) 46 | // .pipe(sourcemaps.write()) 47 | .pipe(gulp.dest('dist')) 48 | }) 49 | 50 | gulp.task('build_umd', function () { 51 | return gulp.src(['index.ts']) 52 | .pipe(ts(tsconfig.compilerOptions)) 53 | .pipe(babel({ 54 | moduleId: pack.name, 55 | presets: ['@babel/env'], 56 | plugins: [['@babel/transform-modules-umd', { 57 | globals: { 58 | [pack.name]: exportModuleName, 59 | vue: 'Vue', 60 | 'vxe-table': 'VXETable', 61 | 'xe-utils': 'XEUtils', 62 | dayjs: 'dayjs' 63 | }, 64 | exactGlobals: true 65 | }]] 66 | })) 67 | .pipe(rename({ 68 | basename: 'index', 69 | suffix: '.umd', 70 | extname: '.js' 71 | })) 72 | .pipe(gulp.dest('dist')) 73 | .pipe(uglify()) 74 | .pipe(rename({ 75 | basename: 'index', 76 | suffix: '.umd.min', 77 | extname: '.js' 78 | })) 79 | .pipe(gulp.dest('dist')) 80 | }) 81 | 82 | gulp.task('clear', () => { 83 | return del([ 84 | 'dist/depend.*' 85 | ]) 86 | }) 87 | 88 | gulp.task('build', gulp.series(gulp.parallel('build_commonjs', 'build_umd', 'build_style'), 'clear')) 89 | -------------------------------------------------------------------------------- /index.ts: -------------------------------------------------------------------------------- 1 | import { h, resolveComponent, ComponentOptions } from 'vue' 2 | import XEUtils from 'xe-utils' 3 | import { VXETableCore, VxeTableDefines, VxeColumnPropTypes, VxeGlobalRendererHandles, VxeGlobalInterceptorHandles } from 'vxe-table' 4 | 5 | import dayjs from 'dayjs' 6 | 7 | let vxetable: VXETableCore 8 | 9 | function isEmptyValue (cellValue: any) { 10 | return cellValue === null || cellValue === undefined || cellValue === '' 11 | } 12 | 13 | function getOnName (type: string) { 14 | return 'on' + type.substring(0, 1).toLocaleUpperCase() + type.substring(1) 15 | } 16 | 17 | function getModelProp (renderOpts: VxeGlobalRendererHandles.RenderOptions) { 18 | return 'modelValue' 19 | } 20 | 21 | function getModelEvent (renderOpts: VxeGlobalRendererHandles.RenderOptions) { 22 | return 'update:modelValue' 23 | } 24 | 25 | function getChangeEvent (renderOpts: VxeGlobalRendererHandles.RenderOptions) { 26 | let type = 'change' 27 | switch (renderOpts.name) { 28 | case 'ElAutocomplete': 29 | type = 'select' 30 | break 31 | case 'ElInput': 32 | case 'ElInputNumber': 33 | type = 'input' 34 | break 35 | } 36 | return type 37 | } 38 | 39 | function toDayStringDate (value: any, format: string) { 40 | return dayjs(value, format).date 41 | } 42 | 43 | function toDayDateString (date: any, format: string) { 44 | return dayjs(date).format(format) 45 | } 46 | 47 | function parseDate (value: any, props: { [key: string]: any }) { 48 | return value && props.valueFormat ? toDayStringDate(value, props.valueFormat) : value 49 | } 50 | 51 | function getFormatDate (value: any, props: { [key: string]: any }, defaultFormat: string) { 52 | return value ? toDayDateString(parseDate(value, props), props.format || defaultFormat) : value 53 | } 54 | 55 | function getFormatDates (values: any[], props: { [key: string]: any }, separator: string, defaultFormat: string) { 56 | return XEUtils.map(values, (date: any) => getFormatDate(date, props, defaultFormat)).join(separator) 57 | } 58 | 59 | function equalDaterange (cellValue: any, data: any, props: { [key: string]: any }, defaultFormat: string) { 60 | cellValue = getFormatDate(cellValue, props, defaultFormat) 61 | return cellValue >= getFormatDate(data[0], props, defaultFormat) && cellValue <= getFormatDate(data[1], props, defaultFormat) 62 | } 63 | 64 | function getCellEditFilterProps (renderOpts: any, params: VxeGlobalRendererHandles.RenderEditParams | VxeGlobalRendererHandles.RenderFilterParams, value: any, defaultProps?: { [prop: string]: any }) { 65 | return XEUtils.assign({}, defaultProps, renderOpts.props, { [getModelProp(renderOpts)]: value }) 66 | } 67 | 68 | function getItemProps (renderOpts: VxeGlobalRendererHandles.RenderOptions, params: any, value: any, defaultProps?: { [prop: string]: any }) { 69 | return XEUtils.assign({}, defaultProps, renderOpts.props, { [getModelProp(renderOpts)]: value }) 70 | } 71 | 72 | function formatText (cellValue: any) { 73 | return '' + (isEmptyValue(cellValue) ? '' : cellValue) 74 | } 75 | 76 | function getCellLabelVNs (renderOpts: VxeColumnPropTypes.EditRender, params: VxeGlobalRendererHandles.RenderCellParams, cellLabel: any) { 77 | const { placeholder } = renderOpts 78 | return [ 79 | h('span', { 80 | class: 'vxe-cell--label' 81 | }, placeholder && isEmptyValue(cellLabel) 82 | ? [ 83 | h('span', { 84 | class: 'vxe-cell--placeholder' 85 | }, formatText(vxetable._t(placeholder))) 86 | ] 87 | : formatText(cellLabel)) 88 | ] 89 | } 90 | 91 | function getOns (renderOpts: VxeGlobalRendererHandles.RenderOptions, params: VxeGlobalRendererHandles.RenderParams, inputFunc?: Function, changeFunc?: Function) { 92 | const { events } = renderOpts 93 | const modelEvent = getModelEvent(renderOpts) 94 | const changeEvent = getChangeEvent(renderOpts) 95 | const isSameEvent = changeEvent === modelEvent 96 | const ons: { [type: string]: Function } = {} 97 | XEUtils.objectEach(events, (func: Function, key: string) => { 98 | ons[getOnName(key)] = function (...args: any[]) { 99 | func(params, ...args) 100 | } 101 | }) 102 | if (inputFunc) { 103 | ons[getOnName(modelEvent)] = function (targetEvnt: any) { 104 | inputFunc(targetEvnt) 105 | if (events && events[modelEvent]) { 106 | events[modelEvent](params, targetEvnt) 107 | } 108 | if (isSameEvent && changeFunc) { 109 | changeFunc(targetEvnt) 110 | } 111 | } 112 | } 113 | if (!isSameEvent && changeFunc) { 114 | ons[getOnName(changeEvent)] = function (...args: any[]) { 115 | changeFunc(...args) 116 | if (events && events[changeEvent]) { 117 | events[changeEvent](params, ...args) 118 | } 119 | } 120 | } 121 | return ons 122 | } 123 | 124 | function getEditOns (renderOpts: VxeGlobalRendererHandles.RenderOptions, params: VxeGlobalRendererHandles.RenderEditParams) { 125 | const { $table, row, column } = params 126 | return getOns(renderOpts, params, (value: any) => { 127 | // 处理 model 值双向绑定 128 | XEUtils.set(row, column.field, value) 129 | }, () => { 130 | // 处理 change 事件相关逻辑 131 | $table.updateStatus(params) 132 | }) 133 | } 134 | 135 | function getFilterOns (renderOpts: any, params: VxeGlobalRendererHandles.RenderFilterParams, option: VxeTableDefines.FilterOption, changeFunc: Function) { 136 | return getOns(renderOpts, params, (value: any) => { 137 | // 处理 model 值双向绑定 138 | option.data = value 139 | }, changeFunc) 140 | } 141 | 142 | function getItemOns (renderOpts: VxeGlobalRendererHandles.RenderOptions, params: any) { 143 | const { $form, data, field } = params 144 | return getOns(renderOpts, params, (value: any) => { 145 | // 处理 model 值双向绑定 146 | XEUtils.set(data, field, value) 147 | }, () => { 148 | // 处理 change 事件相关逻辑 149 | $form.updateStatus(params) 150 | }) 151 | } 152 | 153 | function matchCascaderData (index: number, list: any[], values: any[], labels: any[]) { 154 | const val = values[index] 155 | if (list && values.length > index) { 156 | XEUtils.each(list, (item) => { 157 | if (item.value === val) { 158 | labels.push(item.label) 159 | matchCascaderData(++index, item.children, values, labels) 160 | } 161 | }) 162 | } 163 | } 164 | 165 | function getSelectCellValue (renderOpts: VxeColumnPropTypes.EditRender, params: VxeGlobalRendererHandles.RenderCellParams) { 166 | const { options = [], optionGroups, props = {}, optionProps = {}, optionGroupProps = {} } = renderOpts 167 | const { $table, rowid, row, column } = params 168 | const { filterable, multiple } = props 169 | const labelProp = optionProps.label || 'label' 170 | const valueProp = optionProps.value || 'value' 171 | const groupOptions = optionGroupProps.options || 'options' 172 | const cellValue = XEUtils.get(row, column.field) 173 | const colid = column.id 174 | let cellData: any 175 | if (filterable) { 176 | const { internalData } = $table 177 | const { fullAllDataRowIdData } = internalData 178 | const rest: any = fullAllDataRowIdData[rowid] 179 | if (rest) { 180 | cellData = rest.cellData 181 | if (!cellData) { 182 | cellData = rest.cellData = {} 183 | } 184 | } 185 | if (rest && cellData[colid] && cellData[colid].value === cellValue) { 186 | return cellData[colid].label 187 | } 188 | } 189 | if (!isEmptyValue(cellValue)) { 190 | const selectlabel = XEUtils.map(multiple ? cellValue : [cellValue], optionGroups 191 | ? (value) => { 192 | let selectItem: any 193 | for (let index = 0; index < optionGroups.length; index++) { 194 | selectItem = XEUtils.find(optionGroups[index][groupOptions], (item) => item[valueProp] === value) 195 | if (selectItem) { 196 | break 197 | } 198 | } 199 | return selectItem ? selectItem[labelProp] : value 200 | } 201 | : (value) => { 202 | const selectItem = XEUtils.find(options, (item) => item[valueProp] === value) 203 | return selectItem ? selectItem[labelProp] : value 204 | }).join(', ') 205 | if (cellData && options && options.length) { 206 | cellData[colid] = { value: cellValue, label: selectlabel } 207 | } 208 | return selectlabel 209 | } 210 | return '' 211 | } 212 | 213 | function getCascaderCellValue (renderOpts: VxeGlobalRendererHandles.RenderOptions, params: VxeGlobalRendererHandles.RenderCellParams) { 214 | const { props = {} } = renderOpts 215 | const { row, column } = params 216 | const cellValue = XEUtils.get(row, column.field) 217 | const values: any[] = cellValue || [] 218 | const labels: any[] = [] 219 | matchCascaderData(0, props.options, values, labels) 220 | return (props.showAllLevels === false ? labels.slice(labels.length - 1, labels.length) : labels).join(` ${props.separator || '/'} `) 221 | } 222 | 223 | function getDatePickerCellValue (renderOpts: VxeGlobalRendererHandles.RenderOptions, params: VxeGlobalRendererHandles.RenderCellParams | VxeGlobalRendererHandles.ExportMethodParams) { 224 | const { props = {} } = renderOpts 225 | const { row, column } = params 226 | const { rangeSeparator = '-' } = props 227 | let cellValue = XEUtils.get(row, column.field) 228 | switch (props.type) { 229 | case 'week': 230 | cellValue = getFormatDate(cellValue, props, 'YYYYwWW') 231 | break 232 | case 'month': 233 | cellValue = getFormatDate(cellValue, props, 'YYYY-MM') 234 | break 235 | case 'year': 236 | cellValue = getFormatDate(cellValue, props, 'YYYY') 237 | break 238 | case 'dates': 239 | cellValue = getFormatDates(cellValue, props, ', ', 'YYYY-MM-DD') 240 | break 241 | case 'daterange': 242 | cellValue = getFormatDates(cellValue, props, ` ${rangeSeparator} `, 'YYYY-MM-DD') 243 | break 244 | case 'datetimerange': 245 | cellValue = getFormatDates(cellValue, props, ` ${rangeSeparator} `, 'YYYY-MM-DD HH:ss:mm') 246 | break 247 | case 'monthrange': 248 | cellValue = getFormatDates(cellValue, props, ` ${rangeSeparator} `, 'YYYY-MM') 249 | break 250 | default: 251 | cellValue = getFormatDate(cellValue, props, 'YYYY-MM-DD') 252 | } 253 | return cellValue 254 | } 255 | 256 | function getTimePickerCellValue (renderOpts: VxeGlobalRendererHandles.RenderOptions, params: VxeGlobalRendererHandles.RenderCellParams | VxeGlobalRendererHandles.RenderEditParams) { 257 | const { props = {} } = renderOpts 258 | const { row, column } = params 259 | const { isRange, format = 'hh:mm:ss', rangeSeparator = '-' } = props 260 | let cellValue = XEUtils.get(row, column.field) 261 | if (cellValue && isRange) { 262 | cellValue = XEUtils.map(cellValue, (date) => toDayDateString(parseDate(date, props), format)).join(` ${rangeSeparator} `) 263 | } 264 | return toDayDateString(parseDate(cellValue, props), format) 265 | } 266 | 267 | function createEditRender (defaultProps?: { [key: string]: any }) { 268 | return function (renderOpts: VxeColumnPropTypes.EditRender & { name: string }, params: VxeGlobalRendererHandles.RenderEditParams) { 269 | const { row, column } = params 270 | const { name, attrs } = renderOpts 271 | const cellValue = XEUtils.get(row, column.field) 272 | return [ 273 | h(resolveComponent(name), { 274 | ...attrs, 275 | ...getCellEditFilterProps(renderOpts, params, cellValue, defaultProps), 276 | ...getEditOns(renderOpts, params) 277 | }) 278 | ] 279 | } 280 | } 281 | 282 | function defaultButtonEditRender (renderOpts: VxeColumnPropTypes.EditRender, params: VxeGlobalRendererHandles.RenderEditParams) { 283 | const { attrs } = renderOpts 284 | return [ 285 | h(resolveComponent('el-button'), { 286 | ...attrs, 287 | ...getCellEditFilterProps(renderOpts, params, null), 288 | ...getOns(renderOpts, params) 289 | }, cellText(renderOpts.content)) 290 | ] 291 | } 292 | 293 | function defaultButtonsEditRender (renderOpts: VxeColumnPropTypes.EditRender, params: VxeGlobalRendererHandles.RenderEditParams) { 294 | const { children } = renderOpts 295 | if (children) { 296 | return children.map((childRenderOpts: VxeColumnPropTypes.EditRender) => defaultButtonEditRender(childRenderOpts, params)[0]) 297 | } 298 | return [] 299 | } 300 | 301 | function createFilterRender (defaultProps?: { [key: string]: any }) { 302 | return function (renderOpts: VxeColumnPropTypes.FilterRender & { name: string }, params: VxeGlobalRendererHandles.RenderFilterParams) { 303 | const { column } = params 304 | const { name, attrs } = renderOpts 305 | return [ 306 | h('div', { 307 | class: 'vxe-table--filter-element-wrapper' 308 | }, column.filters.map((option, oIndex) => { 309 | const optionValue = option.data 310 | return h(resolveComponent(name), { 311 | key: oIndex, 312 | ...attrs, 313 | ...getCellEditFilterProps(renderOpts, params, optionValue, defaultProps), 314 | ...getFilterOns(renderOpts, params, option, () => { 315 | // 处理 change 事件相关逻辑 316 | handleConfirmFilter(params, !!option.data, option) 317 | }) 318 | }) 319 | })) 320 | ] 321 | } 322 | } 323 | 324 | function handleConfirmFilter (params: VxeGlobalRendererHandles.RenderFilterParams, checked: boolean, option: VxeTableDefines.FilterOption) { 325 | const { $panel } = params 326 | $panel.changeOption(null, checked, option) 327 | } 328 | 329 | /** 330 | * 模糊匹配 331 | * @param params 332 | */ 333 | function defaultFuzzyFilterMethod (params: VxeGlobalRendererHandles.FilterMethodParams) { 334 | const { option, row, column } = params 335 | const { data } = option 336 | const cellValue = XEUtils.get(row, column.field) 337 | return XEUtils.toValueString(cellValue).indexOf(data) > -1 338 | } 339 | 340 | /** 341 | * 精确匹配 342 | * @param params 343 | */ 344 | function defaultExactFilterMethod (params: VxeGlobalRendererHandles.FilterMethodParams) { 345 | const { option, row, column } = params 346 | const { data } = option 347 | const cellValue = XEUtils.get(row, column.field) 348 | /* eslint-disable eqeqeq */ 349 | return cellValue === data 350 | } 351 | 352 | function renderOptions (options: any[], optionProps: VxeGlobalRendererHandles.RenderOptionProps) { 353 | const labelProp = optionProps.label || 'label' 354 | const valueProp = optionProps.value || 'value' 355 | return XEUtils.map(options, (item, oIndex) => { 356 | return h(resolveComponent('el-option'), { 357 | key: oIndex, 358 | value: item[valueProp], 359 | label: item[labelProp], 360 | disabled: item.disabled 361 | }) 362 | }) 363 | } 364 | 365 | function cellText (cellValue: any): string[] { 366 | return [formatText(cellValue)] 367 | } 368 | 369 | function createFormItemRender (defaultProps?: { [key: string]: any }) { 370 | return function (renderOpts: VxeGlobalRendererHandles.RenderItemContentOptions & { name: string }, params: any) { 371 | const { data, field } = params 372 | const { name } = renderOpts 373 | const { attrs } = renderOpts 374 | const itemValue = XEUtils.get(data, field) 375 | return [ 376 | h(resolveComponent(name), { 377 | ...attrs, 378 | ...getItemProps(renderOpts, params, itemValue, defaultProps), 379 | ...getItemOns(renderOpts, params) 380 | }) 381 | ] 382 | } 383 | } 384 | 385 | function defaultButtonItemRender (renderOpts: VxeGlobalRendererHandles.RenderItemContentOptions, params: any) { 386 | const { attrs } = renderOpts 387 | const props = getItemProps(renderOpts, params, null) 388 | return [ 389 | h(resolveComponent('el-button') as ComponentOptions, { 390 | ...attrs, 391 | ...props, 392 | ...getOns(renderOpts, params) 393 | }, { 394 | default: () => cellText(renderOpts.content || props.content) 395 | }) 396 | ] 397 | } 398 | 399 | function defaultButtonsItemRender (renderOpts: VxeGlobalRendererHandles.RenderItemContentOptions, params: any) { 400 | const { children } = renderOpts 401 | if (children) { 402 | return children.map((childRenderOpts: VxeGlobalRendererHandles.RenderItemContentOptions) => defaultButtonItemRender(childRenderOpts, params)[0]) 403 | } 404 | return [] 405 | } 406 | 407 | function createExportMethod (getExportCellValue: Function) { 408 | return function (params: VxeGlobalRendererHandles.ExportMethodParams) { 409 | const { row, column, options } = params 410 | return options && options.original ? XEUtils.get(row, column.field) : getExportCellValue(column.editRender || column.cellRender, params) 411 | } 412 | } 413 | 414 | function createFormItemRadioAndCheckboxRender () { 415 | return function (renderOpts: VxeGlobalRendererHandles.RenderItemContentOptions & { name: string }, params: any) { 416 | const { name, options = [], optionProps = {}, attrs } = renderOpts 417 | const { data, field } = params 418 | const labelProp = optionProps.label || 'label' 419 | const valueProp = optionProps.value || 'value' 420 | const itemValue = XEUtils.get(data, field) 421 | return [ 422 | h(resolveComponent(`${name}Group`) as ComponentOptions, { 423 | ...attrs, 424 | ...getItemProps(renderOpts, params, itemValue), 425 | ...getItemOns(renderOpts, params) 426 | }, { 427 | default: () => { 428 | return options.map((option, oIndex) => { 429 | return h(resolveComponent(name) as ComponentOptions, { 430 | key: oIndex, 431 | label: option[valueProp], 432 | disabled: option.disabled 433 | }, { 434 | default: () => cellText(option[labelProp]) 435 | }) 436 | }) 437 | } 438 | }) 439 | ] 440 | } 441 | } 442 | 443 | /** 444 | * 检查触发源是否属于目标节点 445 | */ 446 | function getEventTargetNode (evnt: any, container: HTMLElement, className: string) { 447 | let targetElem 448 | let target = evnt.target 449 | while (target && target.nodeType && target !== document) { 450 | if (className && target.className && target.className.split && target.className.split(' ').indexOf(className) > -1) { 451 | targetElem = target 452 | } else if (target === container) { 453 | return { flag: className ? !!targetElem : true, container, targetElem: targetElem } 454 | } 455 | target = target.parentNode 456 | } 457 | return { flag: false } 458 | } 459 | 460 | /** 461 | * 事件兼容性处理 462 | */ 463 | function handleClearEvent (params: VxeGlobalInterceptorHandles.InterceptorClearFilterParams | VxeGlobalInterceptorHandles.InterceptorClearEditParams | VxeGlobalInterceptorHandles.InterceptorClearAreasParams) { 464 | const { $event } = params 465 | const bodyElem = document.body 466 | if ( 467 | // 远程搜索 468 | getEventTargetNode($event, bodyElem, 'el-autocomplete-suggestion').flag || 469 | // 下拉框 470 | getEventTargetNode($event, bodyElem, 'el-select-dropdown').flag || 471 | // 级联 472 | getEventTargetNode($event, bodyElem, 'el-cascader__dropdown').flag || 473 | getEventTargetNode($event, bodyElem, 'el-cascader-menus').flag || 474 | // 日期 475 | getEventTargetNode($event, bodyElem, 'el-time-panel').flag || 476 | getEventTargetNode($event, bodyElem, 'el-picker-panel').flag || 477 | // 颜色 478 | getEventTargetNode($event, bodyElem, 'el-color-dropdown').flag 479 | ) { 480 | return false 481 | } 482 | } 483 | 484 | /** 485 | * 基于 vxe-table 的表格适配插件,用于兼容 element-ui 组件库 486 | */ 487 | export const VXETablePluginElement = { 488 | install (vxetable: VXETableCore) { 489 | // 检查版本 490 | if (!/^(4)\./.test(vxetable.version) && !/v4/i.test((vxetable as any).v)) { 491 | console.error('[vxe-table-plugin-element 4.x] Version vxe-table 4.x is required') 492 | } 493 | 494 | vxetable.renderer.mixin({ 495 | ElAutocomplete: { 496 | autofocus: 'input.el-input__inner', 497 | renderDefault: createEditRender(), 498 | renderEdit: createEditRender(), 499 | renderFilter: createFilterRender(), 500 | defaultFilterMethod: defaultExactFilterMethod, 501 | renderItemContent: createFormItemRender() 502 | }, 503 | ElInput: { 504 | autofocus: 'input.el-input__inner', 505 | renderDefault: createEditRender(), 506 | renderEdit: createEditRender(), 507 | renderFilter: createFilterRender(), 508 | defaultFilterMethod: defaultFuzzyFilterMethod, 509 | renderItemContent: createFormItemRender() 510 | }, 511 | ElInputNumber: { 512 | autofocus: 'input.el-input__inner', 513 | renderDefault: createEditRender(), 514 | renderEdit: createEditRender(), 515 | renderFilter: createFilterRender(), 516 | defaultFilterMethod: defaultFuzzyFilterMethod, 517 | renderItemContent: createFormItemRender() 518 | }, 519 | ElSelect: { 520 | renderEdit (renderOpts, params) { 521 | const { options = [], optionGroups, optionProps = {}, optionGroupProps = {} } = renderOpts 522 | const { row, column } = params 523 | const { attrs } = renderOpts 524 | const cellValue = XEUtils.get(row, column.field) 525 | const props = getCellEditFilterProps(renderOpts, params, cellValue) 526 | const ons = getEditOns(renderOpts, params) 527 | if (optionGroups) { 528 | const groupOptions = optionGroupProps.options || 'options' 529 | const groupLabel = optionGroupProps.label || 'label' 530 | return [ 531 | h(resolveComponent('el-select') as ComponentOptions, { 532 | ...attrs, 533 | ...props, 534 | ...ons 535 | }, { 536 | default: () => { 537 | return XEUtils.map(optionGroups, (group, gIndex) => { 538 | return h(resolveComponent('el-option-group') as ComponentOptions, { 539 | key: gIndex, 540 | label: group[groupLabel] 541 | }, { 542 | default: () => renderOptions(group[groupOptions], optionProps) 543 | }) 544 | }) 545 | } 546 | }) 547 | ] 548 | } 549 | return [ 550 | h(resolveComponent('el-select') as ComponentOptions, { 551 | ...props, 552 | ...attrs, 553 | ...ons 554 | }, { 555 | default: () => renderOptions(options, optionProps) 556 | }) 557 | ] 558 | }, 559 | renderCell (renderOpts, params) { 560 | return getCellLabelVNs(renderOpts, params, getSelectCellValue(renderOpts, params)) 561 | }, 562 | renderFilter (renderOpts, params) { 563 | const { options = [], optionGroups, optionProps = {}, optionGroupProps = {} } = renderOpts 564 | const groupOptions = optionGroupProps.options || 'options' 565 | const groupLabel = optionGroupProps.label || 'label' 566 | const { column } = params 567 | const { attrs } = renderOpts 568 | return [ 569 | h('div', { 570 | class: 'vxe-table--filter-element-wrapper' 571 | }, optionGroups 572 | ? column.filters.map((option, oIndex) => { 573 | const optionValue = option.data 574 | const props = getCellEditFilterProps(renderOpts, params, optionValue) 575 | return h(resolveComponent('el-select') as ComponentOptions, { 576 | key: oIndex, 577 | ...attrs, 578 | ...props, 579 | ...getFilterOns(renderOpts, params, option, () => { 580 | // 处理 change 事件相关逻辑 581 | handleConfirmFilter(params, props.multiple ? (option.data && option.data.length > 0) : !XEUtils.eqNull(option.data), option) 582 | }) 583 | }, { 584 | default: () => { 585 | return XEUtils.map(optionGroups, (group, gIndex) => { 586 | return h(resolveComponent('el-option-group') as ComponentOptions, { 587 | key: gIndex, 588 | label: group[groupLabel] 589 | }, { 590 | default: () => renderOptions(group[groupOptions], optionProps) 591 | }) 592 | }) 593 | } 594 | }) 595 | }) 596 | : column.filters.map((option, oIndex) => { 597 | const optionValue = option.data 598 | const props = getCellEditFilterProps(renderOpts, params, optionValue) 599 | return h(resolveComponent('el-select') as ComponentOptions, { 600 | key: oIndex, 601 | ...attrs, 602 | ...props, 603 | ...getFilterOns(renderOpts, params, option, () => { 604 | // 处理 change 事件相关逻辑 605 | handleConfirmFilter(params, props.multiple ? (option.data && option.data.length > 0) : !XEUtils.eqNull(option.data), option) 606 | }) 607 | }, { 608 | default: () => renderOptions(options, optionProps) 609 | }) 610 | })) 611 | ] 612 | }, 613 | defaultFilterMethod (params) { 614 | const { option, row, column } = params 615 | const { data } = option 616 | const { field, filterRender: renderOpts } = column 617 | const { props = {} } = renderOpts 618 | const cellValue = XEUtils.get(row, field) 619 | if (props.multiple) { 620 | if (XEUtils.isArray(cellValue)) { 621 | return XEUtils.includeArrays(cellValue, data) 622 | } 623 | return data.indexOf(cellValue) > -1 624 | } 625 | /* eslint-disable eqeqeq */ 626 | return cellValue == data 627 | }, 628 | renderItemContent (renderOpts, params) { 629 | const { options = [], optionGroups, optionProps = {}, optionGroupProps = {} } = renderOpts 630 | const { data, field } = params 631 | const { attrs } = renderOpts 632 | const itemValue = XEUtils.get(data, field) 633 | const props = getItemProps(renderOpts, params, itemValue) 634 | const ons = getItemOns(renderOpts, params) 635 | if (optionGroups) { 636 | const groupOptions = optionGroupProps.options || 'options' 637 | const groupLabel = optionGroupProps.label || 'label' 638 | return [ 639 | h(resolveComponent('el-select') as ComponentOptions, { 640 | ...attrs, 641 | ...props, 642 | ...ons 643 | }, { 644 | default: () => { 645 | return XEUtils.map(optionGroups, (group, gIndex) => { 646 | return h(resolveComponent('el-option-group') as ComponentOptions, { 647 | label: group[groupLabel], 648 | key: gIndex 649 | }, { 650 | default: () => renderOptions(group[groupOptions], optionProps) 651 | }) 652 | }) 653 | } 654 | }) 655 | ] 656 | } 657 | return [ 658 | h(resolveComponent('el-select') as ComponentOptions, { 659 | ...attrs, 660 | ...props, 661 | ...ons 662 | }, { 663 | default: () => renderOptions(options, optionProps) 664 | }) 665 | ] 666 | }, 667 | exportMethod: createExportMethod(getSelectCellValue) 668 | }, 669 | ElCascader: { 670 | renderEdit: createEditRender(), 671 | renderCell (renderOpts, params) { 672 | return getCellLabelVNs(renderOpts, params, getCascaderCellValue(renderOpts, params)) 673 | }, 674 | renderItemContent: createFormItemRender(), 675 | exportMethod: createExportMethod(getCascaderCellValue) 676 | }, 677 | ElDatePicker: { 678 | renderEdit: createEditRender(), 679 | renderCell (renderOpts, params) { 680 | return getCellLabelVNs(renderOpts, params, getDatePickerCellValue(renderOpts, params)) 681 | }, 682 | renderFilter (renderOpts, params) { 683 | const { column } = params 684 | const { name, attrs } = renderOpts 685 | return [ 686 | h('div', { 687 | class: 'vxe-table--filter-element-wrapper' 688 | }, column.filters.map((option, oIndex) => { 689 | const optionValue = option.data 690 | return h(resolveComponent(name as string), { 691 | key: oIndex, 692 | ...attrs, 693 | ...getCellEditFilterProps(renderOpts, params, optionValue), 694 | ...getFilterOns(renderOpts, params, option, () => { 695 | // 处理 change 事件相关逻辑 696 | handleConfirmFilter(params, !!option.data, option) 697 | }) 698 | }) 699 | })) 700 | ] 701 | }, 702 | defaultFilterMethod (params) { 703 | const { option, row, column } = params 704 | const { data } = option 705 | const { filterRender: renderOpts } = column 706 | const { props = {} } = renderOpts 707 | const cellValue = XEUtils.get(row, column.field) 708 | if (data) { 709 | switch (props.type) { 710 | case 'daterange': 711 | return equalDaterange(cellValue, data, props, 'YYYY-MM-DD') 712 | case 'datetimerange': 713 | return equalDaterange(cellValue, data, props, 'YYYY-MM-DD HH:ss:mm') 714 | case 'monthrange': 715 | return equalDaterange(cellValue, data, props, 'YYYY-MM') 716 | default: 717 | return cellValue === data 718 | } 719 | } 720 | return false 721 | }, 722 | renderItemContent: createFormItemRender(), 723 | exportMethod: createExportMethod(getDatePickerCellValue) 724 | }, 725 | ElTimePicker: { 726 | renderEdit: createEditRender(), 727 | renderCell (renderOpts, params) { 728 | return getCellLabelVNs(renderOpts, params, getTimePickerCellValue(renderOpts, params)) 729 | }, 730 | renderItemContent: createFormItemRender(), 731 | exportMethod: createExportMethod(getTimePickerCellValue) 732 | }, 733 | ElTimeSelect: { 734 | renderEdit: createEditRender(), 735 | renderItemContent: createFormItemRender() 736 | }, 737 | ElRate: { 738 | renderDefault: createEditRender(), 739 | renderEdit: createEditRender(), 740 | renderFilter: createFilterRender(), 741 | defaultFilterMethod: defaultExactFilterMethod, 742 | renderItemContent: createFormItemRender() 743 | }, 744 | ElSwitch: { 745 | renderDefault: createEditRender(), 746 | renderEdit: createEditRender(), 747 | renderFilter (renderOpts, params) { 748 | const { column } = params 749 | const { name, attrs } = renderOpts 750 | return [ 751 | h('div', { 752 | class: 'vxe-table--filter-element-wrapper' 753 | }, column.filters.map((option, oIndex) => { 754 | const optionValue = option.data 755 | return h(resolveComponent(name as string), { 756 | key: oIndex, 757 | ...attrs, 758 | ...getCellEditFilterProps(renderOpts, params, optionValue), 759 | ...getFilterOns(renderOpts, params, option, () => { 760 | // 处理 change 事件相关逻辑 761 | handleConfirmFilter(params, XEUtils.isBoolean(option.data), option) 762 | }) 763 | }) 764 | })) 765 | ] 766 | }, 767 | defaultFilterMethod: defaultExactFilterMethod, 768 | renderItemContent: createFormItemRender() 769 | }, 770 | ElSlider: { 771 | renderDefault: createEditRender(), 772 | renderEdit: createEditRender(), 773 | renderFilter: createFilterRender(), 774 | defaultFilterMethod: defaultExactFilterMethod, 775 | renderItemContent: createFormItemRender() 776 | }, 777 | ElRadio: { 778 | renderItemContent: createFormItemRadioAndCheckboxRender() 779 | }, 780 | ElCheckbox: { 781 | renderItemContent: createFormItemRadioAndCheckboxRender() 782 | }, 783 | ElButton: { 784 | renderDefault: defaultButtonEditRender, 785 | renderItemContent: defaultButtonItemRender 786 | }, 787 | ElButtons: { 788 | renderDefault: defaultButtonsEditRender, 789 | renderItemContent: defaultButtonsItemRender 790 | } 791 | }) 792 | 793 | vxetable.interceptor.add('event.clearFilter', handleClearEvent) 794 | vxetable.interceptor.add('event.clearEdit', handleClearEvent) 795 | vxetable.interceptor.add('event.clearAreas', handleClearEvent) 796 | // 兼容老版本 797 | vxetable.interceptor.add('event.clearActived', handleClearEvent) 798 | } 799 | } 800 | 801 | if (typeof window !== 'undefined' && window.VXETable && window.VXETable.use) { 802 | window.VXETable.use(VXETablePluginElement) 803 | } 804 | 805 | export default VXETablePluginElement 806 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vxe-table-plugin-element", 3 | "version": "4.0.4", 4 | "description": "基于 vxe-table 的表格适配插件,用于兼容 element-ui 组件库", 5 | "scripts": { 6 | "lib": "gulp build" 7 | }, 8 | "files": [ 9 | "types", 10 | "dist", 11 | "*.ts", 12 | "*.d.ts", 13 | "style.scss" 14 | ], 15 | "main": "dist/index.common.js", 16 | "unpkg": "dist/index.umd.js", 17 | "jsdelivr": "dist/index.umd.js", 18 | "style": "dist/style.css", 19 | "typings": "types/index.d.ts", 20 | "devDependencies": { 21 | "@babel/core": "^7.12.3", 22 | "@babel/plugin-transform-runtime": "^7.12.1", 23 | "@babel/preset-env": "^7.12.1", 24 | "@babel/runtime": "^7.12.5", 25 | "@typescript-eslint/eslint-plugin": "^4.6.1", 26 | "@typescript-eslint/parser": "^4.6.1", 27 | "dayjs": "^1.11.5", 28 | "del": "^6.0.0", 29 | "eslint": "^7.13.0", 30 | "eslint-config-prettier": "^6.15.0", 31 | "eslint-config-standard": "^16.0.1", 32 | "eslint-friendly-formatter": "^4.0.1", 33 | "eslint-plugin-import": "^2.22.1", 34 | "eslint-plugin-node": "^11.1.0", 35 | "eslint-plugin-prettier": "^3.1.4", 36 | "eslint-plugin-promise": "^4.2.1", 37 | "eslint-plugin-standard": "^4.0.2", 38 | "eslint-plugin-typescript": "^0.14.0", 39 | "gulp": "^4.0.2", 40 | "gulp-autoprefixer": "^8.0.0", 41 | "gulp-babel": "^8.0.0", 42 | "gulp-clean-css": "^4.3.0", 43 | "gulp-concat": "^2.6.1", 44 | "gulp-rename": "^2.0.0", 45 | "gulp-replace": "^1.1.3", 46 | "gulp-sass": "^5.1.0", 47 | "gulp-sourcemaps": "^3.0.0", 48 | "gulp-typescript": "^5.0.1", 49 | "gulp-uglify": "^3.0.2", 50 | "markdown-doctest": "^1.1.0", 51 | "prettier": "^2.1.2", 52 | "sass": "^1.55.0", 53 | "typescript": "^4.6.4", 54 | "vue": "^3.4.27", 55 | "vxe-table": "~4.6.25" 56 | }, 57 | "peerDependencies": { 58 | "vxe-table": "^4.5.0" 59 | }, 60 | "repository": { 61 | "type": "git", 62 | "url": "git+https://github.com/x-extends/vxe-table-plugin-element.git" 63 | }, 64 | "keywords": [ 65 | "vxe-table", 66 | "vxe-table plugins" 67 | ], 68 | "author": { 69 | "name": "Xu Liangzhan", 70 | "email": "xu_liangzhan@163.com" 71 | }, 72 | "license": "MIT", 73 | "bugs": { 74 | "url": "https://github.com/x-extends/vxe-table-plugin-element/issues" 75 | }, 76 | "homepage": "https://github.com/x-extends/vxe-table-plugin-element#readme" 77 | } 78 | -------------------------------------------------------------------------------- /style.scss: -------------------------------------------------------------------------------- 1 | $vxe-table-validate-error-color: #f56c6c; 2 | 3 | %ResetBorder { 4 | border: 0; 5 | } 6 | 7 | %SliderStyle { 8 | .el-slider__runway { 9 | margin: 8px 0; 10 | .el-slider__button-wrapper { 11 | z-index: auto; 12 | } 13 | } 14 | } 15 | 16 | %CompWidth { 17 | & > .el-input, 18 | & > .el-autocomplete, 19 | & > .el-input-number, 20 | & > .el-select, 21 | & > .el-cascader, 22 | & > .el-date-editor, 23 | & > .el-slider { 24 | width: 100%; 25 | } 26 | & > .el-color-picker { 27 | vertical-align: middle; 28 | } 29 | } 30 | .vxe-form { 31 | .vxe-form--item-content { 32 | @extend %CompWidth; 33 | } 34 | } 35 | .vxe-table--filter-element-wrapper { 36 | padding: 0.8em 1em; 37 | & > .el-input, 38 | & > .el-input-number, 39 | & > .el-autocomplete, 40 | & > .el-select, 41 | & > .el-rate, 42 | & > .el-slider { 43 | width: 180px; 44 | } 45 | & > .el-slider { 46 | @extend %SliderStyle; 47 | } 48 | } 49 | .vxe-table { 50 | .vxe-cell, 51 | .vxe-tree-cell { 52 | @extend %CompWidth; 53 | & > .el-slider { 54 | @extend %SliderStyle; 55 | } 56 | } 57 | } 58 | .col--valid-error { 59 | & > .vxe-cell, 60 | & > .vxe-tree-cell { 61 | & > .el-input .el-input__inner, 62 | & > .el-autocomplete .el-input__inner, 63 | & > .el-input-number .el-input__inner, 64 | & > .el-select .el-input__inner, 65 | & > .el-cascader .el-input__inner, 66 | & > .el-date-picker .el-input__inner { 67 | border-color: $vxe-table-validate-error-color; 68 | } 69 | } 70 | } 71 | .vxe-table.cell--highlight { 72 | .vxe-cell, 73 | .vxe-tree-cell { 74 | & > .el-input:not(.el-date-editor), 75 | & > .el-autocomplete, 76 | & > .el-select, 77 | & > .el-cascader { 78 | .el-input__inner { 79 | padding: 0; 80 | @extend %ResetBorder; 81 | } 82 | } 83 | & > .el-input-number { 84 | .el-input-number__decrease, 85 | .el-input-number__increase { 86 | @extend %ResetBorder; 87 | } 88 | .el-input__inner { 89 | @extend %ResetBorder; 90 | } 91 | } 92 | & > .el-date-editor { 93 | .el-input__inner { 94 | @extend %ResetBorder; 95 | } 96 | } 97 | } 98 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | "index.ts" 4 | ], 5 | "compilerOptions": { 6 | "strict": true, 7 | "moduleResolution": "node", 8 | "noImplicitAny": true, 9 | "allowSyntheticDefaultImports": true, 10 | "target": "esnext", 11 | "lib": [ 12 | "esnext", 13 | "dom", 14 | "dom.iterable" 15 | ] 16 | } 17 | } -------------------------------------------------------------------------------- /types/index.d.ts: -------------------------------------------------------------------------------- 1 | import { VXETableCore } from 'vxe-table' 2 | 3 | /** 4 | * 基于 vxe-table 的表格适配插件,用于兼容 element-plus 组件库 5 | */ 6 | export declare const VXETablePluginElement: { 7 | install (vxetable: VXETableCore): void 8 | } 9 | 10 | export default VXETablePluginElement 11 | --------------------------------------------------------------------------------