├── style
├── table.css
├── table-column.css
├── editable.css
└── editable-column.css
├── postcss.config.js
├── docs
├── favicon.ico
├── static
│ └── fonts
│ │ ├── element-icons.535877f5.woff
│ │ └── element-icons.732389de.ttf
└── index.html
├── public
├── favicon.ico
└── index.html
├── examples
├── mock
│ ├── api
│ │ ├── conf
│ │ │ ├── languages.json
│ │ │ ├── sex.json
│ │ │ └── columns.json
│ │ ├── role
│ │ │ └── list.json
│ │ ├── user
│ │ │ └── list.json
│ │ ├── i18n
│ │ │ └── list.json
│ │ ├── file
│ │ │ └── list.json
│ │ ├── column
│ │ │ └── list.json
│ │ └── index.js
│ ├── index.js
│ ├── setup.js
│ └── error.js
├── plugins
│ ├── element.js
│ └── element-extends.js
├── main.js
└── views
│ ├── table
│ ├── Base1.vue
│ ├── Base9.vue
│ ├── Scroll2.vue
│ ├── Scroll1.vue
│ ├── Base4.vue
│ ├── Base3.vue
│ ├── Base6.vue
│ ├── Base7.vue
│ ├── Base5.vue
│ ├── Base8.vue
│ ├── Base2.vue
│ ├── Custom1.vue
│ ├── Custom3.vue
│ └── Custom2.vue
│ └── editable
│ ├── Excel1.vue
│ ├── Click1.vue
│ ├── Dblclick1.vue
│ ├── BigScroll3.vue
│ ├── BigScroll2.vue
│ ├── BigScroll4.vue
│ ├── Excel2.vue
│ ├── Dblclick8.vue
│ ├── Click11.vue
│ ├── Click8.vue
│ ├── BigScroll1.vue
│ ├── Manual1.vue
│ └── Excel4.vue
├── types
└── index.d.ts
├── packages
├── table
│ ├── index.js
│ └── src
│ │ └── table-column.vue
├── editable
│ ├── index.js
│ └── src
│ │ ├── event.js
│ │ ├── props.js
│ │ ├── tool.js
│ │ └── scroll.js
├── table-column
│ └── index.js
└── editable-column
│ └── index.js
├── lib
├── demo.html
└── index.css
├── babel.config.js
├── .gitignore
├── .github
└── ISSUE_TEMPLATE
│ ├── help.md
│ ├── feature_request.md
│ └── bug_report.md
├── .eslintrc.js
├── scripts
└── postinstall.js
├── src
└── index.js
├── LICENSE
├── vue.config.js
└── package.json
/style/table.css:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/style/table-column.css:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | autoprefixer: {}
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/docs/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xuliangzhan/vue-element-extends/HEAD/docs/favicon.ico
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xuliangzhan/vue-element-extends/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/docs/static/fonts/element-icons.535877f5.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xuliangzhan/vue-element-extends/HEAD/docs/static/fonts/element-icons.535877f5.woff
--------------------------------------------------------------------------------
/docs/static/fonts/element-icons.732389de.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xuliangzhan/vue-element-extends/HEAD/docs/static/fonts/element-icons.732389de.ttf
--------------------------------------------------------------------------------
/examples/mock/api/conf/languages.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "label": "中文",
4 | "value": "zh_CN"
5 | },
6 | {
7 | "label": "English",
8 | "value": "en_US"
9 | }
10 | ]
--------------------------------------------------------------------------------
/examples/plugins/element.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Element from 'element-ui'
3 | import 'element-ui/lib/theme-chalk/index.css'
4 |
5 | // Vue.use(Element, { size: 'small', zIndex: 3000 })
6 | Vue.use(Element)
7 |
--------------------------------------------------------------------------------
/examples/mock/index.js:
--------------------------------------------------------------------------------
1 | import XEAjax from 'xe-ajax'
2 | import XEAjaxMock from 'xe-ajax-mock'
3 |
4 | // import mock api
5 | import './setup'
6 | import './api'
7 | import './error'
8 |
9 | XEAjax.use(XEAjaxMock)
10 |
--------------------------------------------------------------------------------
/types/index.d.ts:
--------------------------------------------------------------------------------
1 | export interface ElxMethods {
2 |
3 | }
4 |
5 | /**
6 | * Extension component based on ElementUI 2.x.
7 | */
8 | declare var VueElementExtends: ElxMethods;
9 |
10 | export default VueElementExtends;
--------------------------------------------------------------------------------
/packages/table/index.js:
--------------------------------------------------------------------------------
1 | import ElxTable from '../table/src/table'
2 |
3 | ElxTable.install = function (Vue) {
4 | Vue.component(ElxTable.name, ElxTable)
5 | }
6 |
7 | export const Table = ElxTable
8 | export default ElxTable
9 |
--------------------------------------------------------------------------------
/examples/plugins/element-extends.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import { Table, TableColumn, Editable, EditableColumn } from '../../src'
3 |
4 | Vue.use(Table)
5 | Vue.use(TableColumn)
6 | Vue.use(Editable)
7 | Vue.use(EditableColumn)
8 |
--------------------------------------------------------------------------------
/lib/demo.html:
--------------------------------------------------------------------------------
1 |
2 |
index demo
3 |
4 |
5 |
6 |
7 |
8 |
11 |
--------------------------------------------------------------------------------
/examples/mock/setup.js:
--------------------------------------------------------------------------------
1 | import XEAjaxMock from 'xe-ajax-mock'
2 |
3 | // mock defaults
4 | XEAjaxMock.setup({
5 | template: true,
6 | pathVariable: 'auto',
7 | timeout: '40-300',
8 | error: true,
9 | log: true
10 | })
11 |
--------------------------------------------------------------------------------
/packages/editable/index.js:
--------------------------------------------------------------------------------
1 | import ElxEditable from './src/editable'
2 |
3 | ElxEditable.install = function (Vue) {
4 | Vue.component(ElxEditable.name, ElxEditable)
5 | }
6 |
7 | export const Editable = ElxEditable
8 | export default ElxEditable
9 |
--------------------------------------------------------------------------------
/examples/mock/error.js:
--------------------------------------------------------------------------------
1 | // import { GET, POST } from 'xe-ajax-mock'
2 |
3 | // // error api
4 | // GET('api/**', { status: 404, body: { message: 'Services does not exist.' } })
5 | // POST('api/**', { status: 404, body: { message: 'Services does not exist.' } })
6 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | 'presets': [
3 | ['@vue/app', {
4 | polyfills: [
5 | 'es6.promise',
6 | 'es6.symbol',
7 | 'es6.array.iterator',
8 | 'es6.object.assign'
9 | ]
10 | }]
11 | ]
12 | }
13 |
--------------------------------------------------------------------------------
/packages/table-column/index.js:
--------------------------------------------------------------------------------
1 | import ElxTableColumn from '../table/src/table-column'
2 |
3 | ElxTableColumn.install = function (Vue) {
4 | Vue.component(ElxTableColumn.name, ElxTableColumn)
5 | }
6 |
7 | export const TableColumn = ElxTableColumn
8 | export default ElxTableColumn
9 |
--------------------------------------------------------------------------------
/examples/mock/api/conf/sex.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "label": "男",
4 | "spell": "nan",
5 | "value": "1",
6 | "value2": 1,
7 | "val": "x"
8 | },
9 | {
10 | "label": "女",
11 | "spell": "nv",
12 | "value": "0",
13 | "value2": 0,
14 | "val": "o"
15 | }
16 | ]
--------------------------------------------------------------------------------
/packages/editable-column/index.js:
--------------------------------------------------------------------------------
1 | import ElxEditableColumn from '../editable/src/editable-column'
2 |
3 | ElxEditableColumn.install = function (Vue) {
4 | Vue.component(ElxEditableColumn.name, ElxEditableColumn)
5 | }
6 |
7 | export const EditableColumn = ElxEditableColumn
8 | export default ElxEditableColumn
9 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | package-lock.json
4 |
5 | # local env files
6 | .env.local
7 | .env.*.local
8 |
9 | # Log files
10 | npm-debug.log*
11 | yarn-debug.log*
12 | yarn-error.log*
13 |
14 | # Editor directories and files
15 | .idea
16 | .vscode
17 | *.suo
18 | *.ntvs*
19 | *.njsproj
20 | *.sln
21 | *.sw*
22 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/help.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Help
3 | about: 遇到问题
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **描述 Describe**
11 |
12 |
13 | **请提供能重现问题的链接(jsfiddle、jsrun) Expected behavior**
14 |
15 |
16 |
17 | **请填写以下版本信息 please complete the following information**
18 | vue: ?
19 | element-ui: ?
20 | vue-element-extends: ?
21 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: {
4 | node: true
5 | },
6 | 'extends': [
7 | 'plugin:vue/essential',
8 | 'standard'
9 | ],
10 | rules: {
11 | 'no-console': 'off',
12 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
13 | },
14 | parserOptions: {
15 | parser: 'babel-eslint'
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: 功能需求
4 | title: ''
5 | labels: 需求
6 | assignees: ''
7 |
8 | ---
9 |
10 | **这个新特性和一个问题相关吗?简单描述下,比如我什么场景下,需要解决什么问题,发现表格不支持这个功能 Is your feature request related to a problem? Please describe.**
11 |
12 |
13 | **描述下,你希望得到的什么解决方案 Describe the solution you'd like**
14 |
15 |
16 | **是否有不错的替代方案 Describe alternatives you've considered**
17 |
--------------------------------------------------------------------------------
/scripts/postinstall.js:
--------------------------------------------------------------------------------
1 | const env = process.env
2 | const ADBLOCK = is(env.ADBLOCK)
3 | const CI = is(env.CI)
4 | const DISABLE_OPENCOLLECTIVE = is(env.DISABLE_OPENCOLLECTIVE)
5 |
6 | function is (it) {
7 | return !!it && it !== '0' && it !== 'false'
8 | }
9 |
10 | if (!ADBLOCK && !CI && !DISABLE_OPENCOLLECTIVE) {
11 | console.log('\n\x1B[91m>\x1B[91m 注: 该组件 vue-element-extends 已废弃不再维护,不再建议使用!')
12 | console.log('\x1B[93m>\x1B[92m 推荐使用: https://xuliangzhan_admin.gitee.io/vxe-table/\n')
13 | }
14 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: 提 Bug
4 | title: ''
5 | labels: bug
6 | assignees: ''
7 |
8 | ---
9 |
10 | **问题描述 Describe the bug**
11 |
12 |
13 | **重现问题的步骤 To Reproduce**
14 |
15 |
16 | **请提供能重现问题的链接(jsfiddle、jsrun) Expected behavior**
17 |
18 |
19 | **报错信息或截图 Error message or screenshots**
20 |
21 |
22 | **期望的结果 Expected behavior**
23 |
24 |
25 | **请填写以下版本信息 please complete the following information**
26 | - vue: ?
27 | - element-ui: ?
28 | - vue-element-extends: ?
29 |
--------------------------------------------------------------------------------
/examples/mock/api/role/list.json:
--------------------------------------------------------------------------------
1 | {
2 | "!return|array(5-50)": {
3 | "id|number": "{{ $index+1 }}",
4 | "name": "{{ random.repeat(['前端', '后端', '测试', '项目经理', '设计'],1) }}_{{ $index }}",
5 | "describe": "{{ random.repeat('角色描述',4,50) }}",
6 | "seq|number": "{{ $index }}",
7 | "createTime|number": "{{ random.time('2019-01-01 00:00:00','2019-02-20 23:59:59', 'yyyy-MM-dd HH:mm:ss') }}",
8 | "updateTime|number": "{{ random.time('2019-01-01 00:00:00','2019-02-20 23:59:59', 'yyyy-MM-dd HH:mm:ss') }}"
9 | }
10 | }
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | <%= htmlWebpackPlugin.options.title %>
9 |
10 |
11 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import Table from '../packages/table'
2 | import TableColumn from '../packages/table-column'
3 | import Editable from '../packages/editable'
4 | import EditableColumn from '../packages/editable-column'
5 |
6 | const components = [
7 | Table,
8 | TableColumn,
9 | Editable,
10 | EditableColumn
11 | ]
12 |
13 | const install = function (Vue) {
14 | if (!install.installed) {
15 | components.map(component => Vue.component(component.name, component))
16 | }
17 | }
18 |
19 | if (typeof window !== 'undefined' && window.Vue) {
20 | install(window.Vue)
21 | }
22 |
23 | export * from '../packages/table'
24 | export * from '../packages/table-column'
25 | export * from '../packages/editable'
26 | export * from '../packages/editable-column'
27 | export default {
28 | install,
29 | Table,
30 | TableColumn,
31 | Editable,
32 | EditableColumn
33 | }
34 |
--------------------------------------------------------------------------------
/packages/editable/src/event.js:
--------------------------------------------------------------------------------
1 | import XEUtils from 'xe-utils'
2 |
3 | // 监听全局事件
4 | const wheelName = /Firefox/i.test(navigator.userAgent) ? 'DOMMouseScroll' : 'mousewheel'
5 | const eventStore = []
6 | const GlobalEvent = {
7 | on (comp, type, cb) {
8 | eventStore.push({ comp, type, cb })
9 | },
10 | off (comp, type) {
11 | XEUtils.remove(eventStore, item => item.comp === comp && item.type === type)
12 | },
13 | trigger (evnt) {
14 | eventStore.forEach(({ comp, type, cb }) => {
15 | if (type === evnt.type || (type === 'mousewheel' && evnt.type === wheelName)) {
16 | cb.call(comp, evnt)
17 | }
18 | })
19 | }
20 | }
21 |
22 | document.addEventListener('keydown', GlobalEvent.trigger, false)
23 | document.addEventListener('contextmenu', GlobalEvent.trigger, false)
24 | window.addEventListener('click', GlobalEvent.trigger, false)
25 | window.addEventListener(wheelName, GlobalEvent.trigger, false)
26 |
27 | export default GlobalEvent
28 |
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 | ElementUI 2.X components extends.
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 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.
--------------------------------------------------------------------------------
/examples/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './App.vue'
3 | import router from './router'
4 |
5 | import './plugins/element.js'
6 | import './plugins/element-extends.js'
7 | import './mock'
8 |
9 | Vue.config.productionTip = false
10 |
11 | // 后台异步生成70万数据,为了避免大量运算卡主页面,生成大约需要15秒左右
12 | var list = window.CACHE_DATA_LIST = []
13 | var currTime = Date.now()
14 | var fullIndex = 0
15 | var size = 700000
16 | function mockData () {
17 | for (var index = 0; index < 1500; index++) {
18 | currTime += 5000
19 | fullIndex++
20 | list.push({
21 | id: fullIndex,
22 | name: 'name_' + fullIndex,
23 | date: currTime,
24 | sex: index % 3 ? '0' : '1',
25 | age: index % 4 === 0 ? 30 : index % 3 === 0 ? 28 : index % 2 === 0 ? 26 : 24,
26 | region: index % 4 === 0 ? [19, 199, 1773] : index % 3 === 0 ? [9, 73, 719] : [1, 1, 5],
27 | rate: index % 4 === 0 ? 4 : index % 3 === 0 ? 3 : index % 2 === 0 ? 2 : 1,
28 | updateTime: currTime,
29 | createTime: currTime
30 | })
31 | }
32 | if (fullIndex < size) {
33 | setTimeout(mockData, 30)
34 | }
35 | }
36 |
37 | mockData()
38 |
39 | new Vue({
40 | router,
41 | render: h => h(App)
42 | }).$mount('#app')
43 |
--------------------------------------------------------------------------------
/examples/mock/api/conf/columns.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "prop": "name",
4 | "label": "名称",
5 | "visible": true
6 | },
7 | {
8 | "prop": "nickname",
9 | "label": "昵称",
10 | "visible": true
11 | },
12 | {
13 | "prop": "sex",
14 | "label": "性别",
15 | "visible": true
16 | },
17 | {
18 | "prop": "age",
19 | "label": "年龄",
20 | "visible": true
21 | },
22 | {
23 | "prop": "phone",
24 | "label": "手机",
25 | "visible": true
26 | },
27 | {
28 | "prop": "region",
29 | "label": "地区",
30 | "visible": true
31 | },
32 | {
33 | "prop": "date",
34 | "label": "日期",
35 | "visible": true
36 | },
37 | {
38 | "prop": "rate",
39 | "label": "评分",
40 | "visible": true
41 | },
42 | {
43 | "prop": "attr1",
44 | "label": "属性1",
45 | "visible": false
46 | },
47 | {
48 | "prop": "attr2",
49 | "label": "属性2",
50 | "visible": false
51 | },
52 | {
53 | "prop": "attr3",
54 | "label": "属性3",
55 | "visible": false
56 | },
57 | {
58 | "prop": "attr4",
59 | "label": "属性4",
60 | "visible": false
61 | },
62 | {
63 | "prop": "attr5",
64 | "label": "属性5",
65 | "visible": false
66 | }
67 | ]
--------------------------------------------------------------------------------
/vue.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 |
3 | function resolve (dir) {
4 | return path.join(__dirname, '.', dir)
5 | }
6 |
7 | module.exports = {
8 | publicPath: process.env.NODE_ENV === 'production' ? '/vue-element-extends/' : '/',
9 | outputDir: 'docs',
10 | assetsDir: 'static',
11 | productionSourceMap: false,
12 | configureWebpack: {
13 | performance: {
14 | hints: false
15 | }
16 | },
17 | pages: {
18 | index: {
19 | entry: 'examples/main.js',
20 | template: 'public/index.html',
21 | filename: 'index.html',
22 | title: 'ElementUI 2.X components extends.'
23 | }
24 | },
25 | chainWebpack (config) {
26 | config.resolve.alias
27 | .set('@', resolve('examples'))
28 | config.output
29 | .set('libraryExport', 'default')
30 | .set('library', 'VueElementExtends')
31 | if (process.env.npm_lifecycle_event.indexOf('lib') === 0) {
32 | let XEUtils = {
33 | root: 'XEUtils',
34 | commonjs: 'xe-utils',
35 | commonjs2: 'xe-utils',
36 | amd: 'xe-utils'
37 | }
38 | if (config.has('externals')) {
39 | config.externals
40 | .set('xe-utils', XEUtils)
41 | } else {
42 | config
43 | .set('externals', {
44 | 'xe-utils': XEUtils
45 | })
46 | }
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/examples/mock/api/user/list.json:
--------------------------------------------------------------------------------
1 | {
2 | "!return|array(50-500)": {
3 | "id|number": "{{ $index+1 }}",
4 | "name": "{{ random.repeat(['name', 'test'],1) }}_{{ $index }}",
5 | "nickname": "{{ random.repeat(['昵称', '名字'],1) }}_{{ $index }}",
6 | "password": "{{ random.repeat('abcdefgABCDEFG',6,12) }}",
7 | "sex|random(1)": [null, "0", "1"],
8 | "sexs|random(1)": [[], ["0"], ["1"], ["0", "1"]],
9 | "role|random(1)": ["前端", "后端", "测试", "设计", "项目经理"],
10 | "region|random(1)": [[1, 1, 5], [19, 199, 1773], [9, 73, 719]],
11 | "email": "{{ random.repeat('abcdefg',5,20) }}@{{ random.repeat(['qq','163'],1) }}.{{ random.repeat(['com','net'],1) }}",
12 | "age|number": "{{ random.num(18,30) }}",
13 | "rate|number": "{{ random.num(0,5) }}",
14 | "flag|boolean": "{{ random.num(0,1) }}",
15 | "phone": "136{{ random.num(10000000,99999999) }}",
16 | "describe": "{{ random.repeat('用户信息',2,6) }}",
17 | "describe2": "{{ random.repeat('用户信息',4,10) }}",
18 | "describe3": "{{ random.repeat('用户信息',6,20) }}",
19 | "seq|number": "{{ $index }}",
20 | "date|number": "{{ random.time('2019-01-01 00:00:00','2019-02-20 23:59:59', 'yyyy-MM-dd HH:mm:ss') }}",
21 | "createTime|number": "{{ random.time('2019-01-01 00:00:00','2019-02-20 23:59:59', 'yyyy-MM-dd HH:mm:ss') }}",
22 | "updateTime|number": "{{ random.time('2019-01-01 00:00:00','2019-02-20 23:59:59', 'yyyy-MM-dd HH:mm:ss') }}",
23 | "attr1": null,
24 | "attr2": null,
25 | "attr3": null,
26 | "attr4": null,
27 | "attr5": null,
28 | "attr6": null
29 | }
30 | }
--------------------------------------------------------------------------------
/examples/mock/api/i18n/list.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": 100,
4 | "key": "home.label.name",
5 | "name": "名字",
6 | "language": "zh_CN",
7 | "createTime": 1550923830095,
8 | "updateTime": 1552923830095
9 | },
10 | {
11 | "id": 101,
12 | "key": "home.label.name",
13 | "name": "Name",
14 | "language": "en_US",
15 | "createTime": 1550923830095,
16 | "updateTime": 1552923830095
17 | },
18 | {
19 | "id": 102,
20 | "key": "home.label.age",
21 | "name": "年龄",
22 | "language": "zh_CN",
23 | "createTime": 1550923830095,
24 | "updateTime": 1552923830095
25 | },
26 | {
27 | "id": 103,
28 | "key": "home.label.age",
29 | "name": "Age",
30 | "language": "en_US",
31 | "createTime": 1550923830095,
32 | "updateTime": 1552923830095
33 | },
34 | {
35 | "id": 104,
36 | "key": "home.label.role",
37 | "name": "Role",
38 | "language": "en_US",
39 | "createTime": 1550923830095,
40 | "updateTime": 1552923830095
41 | },
42 | {
43 | "id": 105,
44 | "key": "comm.label.cancel",
45 | "name": "取消",
46 | "language": "zh_CN",
47 | "createTime": 1550923830095,
48 | "updateTime": 1552923830095
49 | },
50 | {
51 | "id": 106,
52 | "key": "comm.label.cancel",
53 | "name": "Cancel",
54 | "language": "en_US",
55 | "createTime": 1550923830095,
56 | "updateTime": 1552923830095
57 | },
58 | {
59 | "id": 107,
60 | "key": "home.label.phone",
61 | "name": "手机",
62 | "language": "zh_CN",
63 | "createTime": 1550923830095,
64 | "updateTime": 1552923830095
65 | },
66 | {
67 | "id": 108,
68 | "key": "comm.label.confirm",
69 | "name": "确认",
70 | "language": "zh_CN",
71 | "createTime": 1550923830095,
72 | "updateTime": 1552923830095
73 | }
74 | ]
--------------------------------------------------------------------------------
/examples/mock/api/file/list.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": 100,
4 | "parentId": null,
5 | "name": "一级目录",
6 | "size": null,
7 | "type": "0",
8 | "createTime": 1550923830095,
9 | "updateTime": 1551923830095
10 | },
11 | {
12 | "id": 101,
13 | "parentId": 100,
14 | "name": "二级目录",
15 | "size": null,
16 | "type": "0",
17 | "createTime": 1550923830095,
18 | "updateTime": 1552923830095
19 | },
20 | {
21 | "id": 10100,
22 | "parentId": 101,
23 | "name": "文件10100.pdf",
24 | "size": 218,
25 | "type": "1",
26 | "createTime": 1550923830095,
27 | "updateTime": 1553924830095
28 | },
29 | {
30 | "id": 10101,
31 | "parentId": 101,
32 | "name": "文件10101.excel",
33 | "size": 512,
34 | "type": "1",
35 | "createTime": 1550923830095,
36 | "updateTime": 1550925830095
37 | },
38 | {
39 | "id": 102,
40 | "parentId": 100,
41 | "name": "文件102.word",
42 | "size": 101024,
43 | "type": "1",
44 | "createTime": 1550923830095,
45 | "updateTime": 1550963830095
46 | },
47 | {
48 | "id": 200,
49 | "parentId": null,
50 | "name": "我的文件",
51 | "size": null,
52 | "type": "0",
53 | "createTime": 1550923830095,
54 | "updateTime": 1550983830095
55 | },
56 | {
57 | "id": 201,
58 | "parentId": 200,
59 | "name": "文件201.zip",
60 | "size": 1024,
61 | "type": "1",
62 | "createTime": 1550923830095,
63 | "updateTime": 1550927830095
64 | },
65 | {
66 | "id": 202,
67 | "parentId": 200,
68 | "name": "文件202.text",
69 | "size": 4096,
70 | "type": "1",
71 | "createTime": 1550923830095,
72 | "updateTime": 1550926830095
73 | },
74 | {
75 | "id": 301,
76 | "parentId": null,
77 | "name": "文件301.zip",
78 | "size": 4024,
79 | "type": "1",
80 | "createTime": 1550923830095,
81 | "updateTime": 1550823830095
82 | }
83 | ]
--------------------------------------------------------------------------------
/examples/mock/api/column/list.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": 1,
4 | "key": "name",
5 | "name": "名字",
6 | "readonly": false,
7 | "required": true,
8 | "validator": "",
9 | "validMsg": "",
10 | "visible": true,
11 | "width": null,
12 | "align": "",
13 | "type": "ElInput",
14 | "seq": 1,
15 | "describe": "",
16 | "createTime": 1550923830095,
17 | "updateTime": 1550105830095
18 | },
19 | {
20 | "id": 2,
21 | "key": "age",
22 | "name": "年龄",
23 | "readonly": false,
24 | "required": false,
25 | "validator": "",
26 | "validMsg": "",
27 | "visible": true,
28 | "width": "140",
29 | "align": "center",
30 | "type": "ElInputNumber",
31 | "seq": 2,
32 | "describe": "",
33 | "createTime": 1550923830095,
34 | "updateTime": 1550205830095
35 | },
36 | {
37 | "id": 3,
38 | "key": "date",
39 | "name": "日期",
40 | "readonly": false,
41 | "required": false,
42 | "validator": "",
43 | "validMsg": "",
44 | "visible": true,
45 | "width": "200",
46 | "align": "",
47 | "type": "ElDatePicker",
48 | "seq": 3,
49 | "describe": "",
50 | "createTime": 1550923830095,
51 | "updateTime": 1550305830095
52 | },
53 | {
54 | "id": 4,
55 | "key": "phone",
56 | "name": "手机",
57 | "readonly": false,
58 | "required": false,
59 | "validator": "^1[34578][0-9]{9}$",
60 | "validMsg": "手机格式输入错误",
61 | "visible": true,
62 | "width": null,
63 | "align": "",
64 | "type": "ElInput",
65 | "seq": 4,
66 | "describe": "",
67 | "createTime": 1550923830095,
68 | "updateTime": 1550405830095
69 | },
70 | {
71 | "id": 5,
72 | "key": "role",
73 | "name": "角色",
74 | "readonly": false,
75 | "required": false,
76 | "validator": "",
77 | "validMsg": "",
78 | "visible": false,
79 | "width": null,
80 | "align": "",
81 | "type": "ElInput",
82 | "seq": 5,
83 | "describe": "",
84 | "createTime": 1550923830095,
85 | "updateTime": 1550505830095
86 | }
87 | ]
--------------------------------------------------------------------------------
/packages/editable/src/props.js:
--------------------------------------------------------------------------------
1 | const PropsStatic = {
2 | table: {
3 | data: Array,
4 | height: [String, Number],
5 | maxHeight: [String, Number],
6 | stripe: Boolean,
7 | border: Boolean,
8 | size: String,
9 | fit: { type: Boolean, default: true },
10 | showHeader: { type: Boolean, default: true },
11 | highlightCurrentRow: Boolean,
12 | currentRowKey: [String, Number],
13 | lazy: Boolean,
14 | indent: Number,
15 | rowClassName: [Function, String],
16 | rowStyle: [Function, Object],
17 | cellClassName: [Function, String],
18 | cellStyle: [Function, Object],
19 | headerRowClassName: [Function, String],
20 | headerRowStyle: [Function, Object],
21 | headerCellClassName: [Function, String],
22 | headerCellStyle: [Function, Object],
23 | rowKey: [Function, String],
24 | emptyText: String,
25 | defaultExpandAll: Boolean,
26 | expandRowKeys: Array,
27 | defaultSort: Object,
28 | tooltipEffect: { type: String, default: 'dark' },
29 | showSummary: Boolean,
30 | sumText: String,
31 | summaryMethod: Function,
32 | selectOnIndeterminate: { type: Boolean, default: true },
33 | spanMethod: Function,
34 | load: Function
35 | },
36 | tableColumn: {
37 | index: [Number, Function],
38 | type: String,
39 | label: String,
40 | columnKey: String,
41 | prop: String,
42 | width: String,
43 | minWidth: String,
44 | fixed: [Boolean, String],
45 | sortable: [Boolean, String],
46 | sortMethod: Function,
47 | sortBy: [String, Array, Function],
48 | sortOrders: Array,
49 | resizable: { type: Boolean, default: true },
50 | formatter: Function,
51 | showOverflowTooltip: Boolean,
52 | align: { type: String, default: 'left' },
53 | headerAlign: String,
54 | className: { type: String, default: '' },
55 | labelClassName: String,
56 | selectable: Function,
57 | reserveSelection: Boolean,
58 | filters: Array,
59 | filterPlacement: String,
60 | filterMultiple: { type: Boolean, default: true },
61 | filterMethod: Function,
62 | filteredValue: Array
63 | }
64 | }
65 |
66 | export default PropsStatic
67 |
--------------------------------------------------------------------------------
/examples/views/table/Base1.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 导出
6 |
7 |
8 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | -- slot append --
26 |
27 |
28 |
29 |
30 |
31 |
64 |
65 |
70 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-element-extends",
3 | "version": "1.2.29",
4 | "description": "Extension component based on ElementUI 2.x",
5 | "scripts": {
6 | "serve": "vue-cli-service serve",
7 | "build": "vue-cli-service build",
8 | "lint": "vue-cli-service lint",
9 | "lib": "vue-cli-service build --target lib --name index --dest lib src/index.js",
10 | "postinstall": "node scripts/postinstall || echo \"ignore\""
11 | },
12 | "files": [
13 | "lib",
14 | "packages",
15 | "style",
16 | "types",
17 | "scripts",
18 | "src"
19 | ],
20 | "main": "lib/index.common.js",
21 | "style": "lib/index.css",
22 | "unpkg": "lib/index.umd.js",
23 | "jsdelivr": "lib/index.umd.js",
24 | "typings": "types/index.d.ts",
25 | "devDependencies": {
26 | "@vue/cli-plugin-babel": "^3.6.0",
27 | "@vue/cli-plugin-eslint": "^3.6.0",
28 | "@vue/cli-service": "^3.6.0",
29 | "@vue/eslint-config-standard": "^4.0.0",
30 | "babel-eslint": "^10.0.1",
31 | "babel-plugin-component": "^1.1.1",
32 | "core-js": "^2.6.5",
33 | "element-ui": "^2.11.1",
34 | "eslint": "^5.16.0",
35 | "eslint-plugin-vue": "^5.0.0",
36 | "font-awesome": "^4.7.0",
37 | "node-sass": "^4.9.0",
38 | "sass-loader": "^7.1.0",
39 | "sortablejs": "^1.10.0-rc3",
40 | "vue": "^2.6.10",
41 | "vue-router": "^3.0.3",
42 | "vue-template-compiler": "^2.6.10",
43 | "xe-ajax": "^3.6.0",
44 | "xe-ajax-mock": "^1.7.10",
45 | "xe-clipboard": "^1.6.0",
46 | "xe-utils": "^1.9.7",
47 | "xlsx": "^0.14.3"
48 | },
49 | "peerDependencies": {
50 | "vue": "^2.6.0",
51 | "element-ui": "^2.1.0"
52 | },
53 | "postcss": {
54 | "plugins": {
55 | "autoprefixer": {}
56 | }
57 | },
58 | "repository": {
59 | "type": "git",
60 | "url": "git+https://github.com/xuliangzhan/vue-element-extends.git"
61 | },
62 | "keywords": [
63 | "vue-element-extends",
64 | "elx-editable",
65 | "vue editable",
66 | "el-editable"
67 | ],
68 | "author": {
69 | "name": "Xu Liangzhan",
70 | "email": "xu_liangzhan@163.com"
71 | },
72 | "license": "MIT",
73 | "bugs": {
74 | "url": "https://github.com/xuliangzhan/vue-element-extends/issues"
75 | },
76 | "homepage": "https://github.com/xuliangzhan/vue-element-extends#readme",
77 | "browserslist": [
78 | "> 1%",
79 | "last 2 versions",
80 | "not ie <= 8"
81 | ]
82 | }
83 |
--------------------------------------------------------------------------------
/examples/views/table/Base9.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
树形
4 |
5 |
6 | 导出
7 |
8 |
9 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
74 |
75 |
80 |
--------------------------------------------------------------------------------
/examples/views/table/Scroll2.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
启用滚动渲染,设置 render='scroll' 可以流畅的支撑海量数据
8 |
影响性能的参数:data、rowKey、fixed
9 |
兼容性:不支持动态行高;不支持树结构;不支持多选
10 |
11 |
12 | 导出
13 |
14 |
15 |
21 |
22 |
23 |
24 | 名字
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
84 |
85 |
94 |
--------------------------------------------------------------------------------
/style/editable.css:
--------------------------------------------------------------------------------
1 | /* el tooltip */
2 | .el-tooltip__popper.elx-valid_tooltip {
3 | background: #f56c6c;
4 | }
5 | .el-tooltip__popper.elx-valid_tooltip[x-placement^=top] .popper__arrow,
6 | .el-tooltip__popper.elx-valid_tooltip[x-placement^=top] .popper__arrow::after {
7 | border-top-color: #f56c6c;
8 | }
9 | .el-tooltip__popper.elx-valid_tooltip[x-placement^=bottom] .popper__arrow,
10 | .el-tooltip__popper.elx-valid_tooltip[x-placement^=bottom] .popper__arrow::after {
11 | border-bottom-color: #f56c6c;
12 | }
13 | .el-tooltip__popper.elx-valid_tooltip[x-placement^=left] .popper__arrow,
14 | .el-tooltip__popper.elx-valid_tooltip[x-placement^=left] .popper__arrow::after {
15 | border-left-color: #f56c6c;
16 | }
17 | .el-tooltip__popper.elx-valid_tooltip[x-placement^=right] .popper__arrow,
18 | .el-tooltip__popper.elx-valid_tooltip[x-placement^=right] .popper__arrow::after {
19 | border-right-color: #f56c6c;
20 | }
21 | .elx-contextmenu,
22 | .elx-contextmenu .ctx-menu_child-wrapper {
23 | position: absolute;
24 | top: 0;
25 | left: 0;
26 | z-index: 88;
27 | font-size: 12px;
28 | color: #000;
29 | background: #FFF;
30 | border: 1px solid #C6C6C6;
31 | box-shadow: 2px 2px 4px -2px #666;
32 | padding: 0 1px;
33 | font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;
34 | -webkit-font-smoothing: antialiased;
35 | -moz-osx-font-smoothing: grayscale;
36 | -webkit-user-select: none;
37 | -moz-user-select: none;
38 | -ms-user-select: none;
39 | user-select: none;
40 | }
41 | .elx-contextmenu > .ctx-menu_wrapper,
42 | .elx-contextmenu > .ctx-menu_wrapper .ctx-menu_child-wrapper {
43 | margin: 0;
44 | padding: 0;
45 | list-style-type: none;
46 | border-bottom: 1px solid #E8EAED;
47 | }
48 | .elx-contextmenu > .ctx-menu_wrapper li {
49 | position: relative;
50 | margin: 1px 0;
51 | border: 1px solid transparent;
52 | }
53 | .elx-contextmenu > .ctx-menu_wrapper li:last-child {
54 | border: 0;
55 | }
56 | .elx-contextmenu > .ctx-menu_wrapper li.active {
57 | color: #2B2B2B;
58 | background-color: #C5C5C5;
59 | border-color:#C5C5C5;
60 | }
61 | .elx-contextmenu > .ctx-menu_wrapper li.disabled {
62 | color: #B1B1B1;
63 | }
64 | .elx-contextmenu > .ctx-menu_wrapper li.disabled.active {
65 | border-color:#C0C1C2;
66 | background-color: #EEEEEE;
67 | }
68 | .elx-contextmenu > .ctx-menu_wrapper li.disabled.active:hover {
69 | background-color: inherit;
70 | }
71 | .elx-contextmenu > .ctx-menu_wrapper .ctx-menu_link {
72 | display: block;
73 | padding: 0 30px;
74 | width: 100px;
75 | line-height: 26px;
76 | }
77 | .elx-contextmenu > .ctx-menu_wrapper .ctx-prefix-icon,
78 | .elx-contextmenu > .ctx-menu_wrapper .ctx-suffix-icon {
79 | position: absolute;
80 | top: 5px;
81 | margin-right: 5px;
82 | font-size: 16px;
83 | }
84 | .elx-contextmenu > .ctx-menu_wrapper .ctx-prefix-icon {
85 | left: 5px;
86 | }
87 | .elx-contextmenu > .ctx-menu_wrapper .ctx-suffix-icon {
88 | right: 5px;
89 | }
90 | .elx-contextmenu > .ctx-menu_wrapper .content {
91 | display: block;
92 | overflow: hidden;
93 | text-overflow: ellipsis;
94 | white-space: nowrap;
95 | }
96 | .elx-contextmenu .ctx-menu_child-wrapper {
97 | display: none;
98 | z-index: 99;
99 | top: 0;
100 | left: 100%;
101 | }
102 | .elx-contextmenu .ctx-menu_child-wrapper.show {
103 | display: block;
104 | }
105 |
--------------------------------------------------------------------------------
/examples/views/table/Scroll1.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
启用滚动渲染,设置 render='scroll' 可以流畅的支撑海量数据
8 |
影响性能的参数:data、rowKey、fixed
9 |
兼容性:不兼容动态行高;不支持树结构;不支持多选
10 |
11 |
12 | 导出
13 |
14 |
15 |
22 |
23 |
24 |
25 | 名字
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | {{ scope.row.name }}
34 |
35 |
36 |
37 |
38 |
39 |
40 |
96 |
97 |
106 |
--------------------------------------------------------------------------------
/packages/editable/src/tool.js:
--------------------------------------------------------------------------------
1 | import XEUtils from 'xe-utils'
2 |
3 | const browse = XEUtils.browse()
4 | const UtilHandle = {
5 | browse,
6 | addClass (cell, clss) {
7 | let classList = cell.className.split(' ')
8 | clss.forEach(name => {
9 | if (classList.indexOf(name) === -1) {
10 | classList.push(name)
11 | }
12 | })
13 | cell.className = classList.join(' ')
14 | },
15 | hasClass (cell, cls) {
16 | return cell && cell.className && cell.className.split && cell.className.split(' ').indexOf(cls) > -1
17 | },
18 | removeClass (cell, clss) {
19 | let classList = []
20 | cell.className.split(' ').forEach(name => {
21 | if (clss.indexOf(name) === -1) {
22 | classList.push(name)
23 | }
24 | })
25 | cell.className = classList.join(' ')
26 | },
27 | getCsvUrl (opts, content) {
28 | if (window.Blob && window.URL && window.URL.createObjectURL && !browse.safari) {
29 | return URL.createObjectURL(new Blob([content], { type: 'text/csv' }))
30 | }
31 | return `data:attachment/csv;charset=utf-8,${encodeURIComponent(content)}`
32 | },
33 | getCsvLabelData (columns, oData, tableElem) {
34 | let trElemList = tableElem.querySelectorAll('.el-table__body-wrapper .el-table__row')
35 | return Array.from(trElemList).map((trElem, rowIndex) => {
36 | let item = {}
37 | let row = oData[rowIndex]
38 | columns.forEach(column => {
39 | let cell = trElem.querySelector(`.${column.id}`)
40 | item[column.id] = cell ? cell.innerText.trim() : (row ? XEUtils.get(row, column.property) : '')
41 | })
42 | return item
43 | })
44 | },
45 | getCsvData (opts, oData, oColumns, tableElem) {
46 | let isOriginal = opts.original
47 | let columns = opts.columns ? opts.columns : oColumns
48 | if (opts.columnFilterMethod) {
49 | columns = columns.filter(opts.columnFilterMethod)
50 | }
51 | let datas = opts.data ? opts.data : (isOriginal ? oData : UtilHandle.getCsvLabelData(columns, oData, tableElem))
52 | if (opts.dataFilterMethod) {
53 | datas = datas.filter(opts.dataFilterMethod)
54 | }
55 | return { columns, datas }
56 | },
57 | getCsvContent (opts, oData, oColumns, tableElem) {
58 | let isOriginal = opts.original
59 | let { columns, datas } = UtilHandle.getCsvData(opts, oData, oColumns, tableElem)
60 | let content = '\ufeff'
61 | if (opts.isHeader) {
62 | content += columns.map(column => column.label).join(',') + '\n'
63 | }
64 | datas.forEach((record, rowIndex) => {
65 | if (isOriginal) {
66 | content += columns.map(column => {
67 | if (column.type === 'index') {
68 | return `"${column.index ? column.index(rowIndex) : rowIndex + 1}"`
69 | }
70 | return `"${XEUtils.get(record, column.property) || ''}"`
71 | }).join(',') + '\n'
72 | } else {
73 | content += columns.map(column => `"${record[column.id]}"`).join(',') + '\n'
74 | }
75 | })
76 | return content
77 | },
78 | downloadCsc (opts, content) {
79 | if (!opts.download) {
80 | return Promise.resolve(content)
81 | }
82 | if (navigator.msSaveBlob && window.Blob) {
83 | navigator.msSaveBlob(new Blob([content], { type: 'text/csv' }), opts.filename)
84 | } else if (browse['-ms']) {
85 | var win = window.top.open('about:blank', '_blank')
86 | win.document.charset = 'utf-8'
87 | win.document.write(content)
88 | win.document.close()
89 | win.document.execCommand('SaveAs', opts.filename)
90 | win.close()
91 | } else {
92 | var linkElem = document.createElement('a')
93 | linkElem.target = '_blank'
94 | linkElem.download = opts.filename
95 | linkElem.href = UtilHandle.getCsvUrl(opts, content)
96 | document.body.appendChild(linkElem)
97 | linkElem.click()
98 | document.body.removeChild(linkElem)
99 | }
100 | }
101 | }
102 |
103 | export default UtilHandle
104 |
--------------------------------------------------------------------------------
/examples/views/table/Base4.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
表尾合计行
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | 查询
14 | 重置
15 |
16 |
17 |
18 |
19 | 导出
20 |
21 |
22 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
51 |
52 |
53 |
54 |
111 |
112 |
121 |
--------------------------------------------------------------------------------
/packages/table/src/table-column.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | #
8 |
9 |
10 | {{ formatRowIndex(scope) }}
11 |
12 |
13 |
14 |
15 | {{ scope.column.label }}
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | {{ scope.column.label }}
24 |
25 |
26 | {{ formatColumnLabel(scope) }}
27 |
28 |
29 |
30 |
31 |
117 |
118 |
119 |
--------------------------------------------------------------------------------
/examples/views/editable/Excel1.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
渲染成 Excel 表格
4 |
5 |
6 | 新增
7 | 获取新增
8 | 获取改动
9 | 获取有值数据
10 |
11 |
12 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
84 |
85 |
127 |
--------------------------------------------------------------------------------
/examples/views/table/Base3.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
多级表头
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | 查询
14 | 重置
15 |
16 |
17 |
18 |
19 | 导出
20 |
21 |
22 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
56 |
57 |
58 |
59 |
116 |
117 |
126 |
--------------------------------------------------------------------------------
/examples/views/table/Base6.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
排序;服务端排序
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | 查询
14 | 重置
15 |
16 |
17 |
18 |
19 | 导出
20 |
21 |
22 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
52 |
53 |
54 |
55 |
117 |
118 |
127 |
--------------------------------------------------------------------------------
/style/editable-column.css:
--------------------------------------------------------------------------------
1 | .elx-editable .editable-required-icon:before {
2 | content: "*";
3 | color: #f56c6c;
4 | }
5 | .elx-editable.el-table--mini .elx-editable-column {
6 | height: 36px;
7 | }
8 | .elx-editable.el-table--small .elx-editable-column {
9 | height: 40px;
10 | }
11 | .elx-editable.el-table--medium .elx-editable-column {
12 | height: 44px;
13 | }
14 | .elx-editable .elx-editable-column,
15 | .elx-editable.el-table--large .elx-editable-column {
16 | height: 48px;
17 | padding: 0;
18 | }
19 | .elx-editable .elx-editable-column.elx_dirty {
20 | position: relative;
21 | }
22 | .elx-editable .elx-editable-column.elx_dirty:before {
23 | content: '';
24 | top: -5px;
25 | left: -5px;
26 | position: absolute;
27 | border: 5px solid;
28 | border-color: transparent #f56c6c transparent transparent;
29 | -webkit-transform: rotate(45deg);
30 | -moz-transform: rotate(45deg);
31 | -ms-transform: rotate(45deg);
32 | transform: rotate(45deg);
33 | }
34 | .elx-editable .elx-editable-column .cell > .edit-input,
35 | .elx-editable .elx-editable-column .cell > .el-cascader,
36 | .elx-editable .elx-editable-column .cell > .el-autocomplete,
37 | .elx-editable .elx-editable-column .cell > .el-input-number,
38 | .elx-editable .elx-editable-column .cell > .el-date-editor,
39 | .elx-editable .elx-editable-column .cell > .el-select {
40 | width: 100%;
41 | }
42 | .elx-editable .elx-editable-row.elx_disabled,
43 | .elx-editable .elx-editable-column.elx_edit.elx_disabled {
44 | cursor: not-allowed;
45 | }
46 | .elx-editable .elx-editable-column.elx_edit.elx_active .cell {
47 | line-height: inherit;
48 | overflow: inherit;
49 | position: relative;
50 | }
51 | .elx-editable.editable_click .elx-editable-column.elx_edit,
52 | .elx-editable.editable_dblclick .elx-editable-column.elx_edit {
53 | -webkit-user-select: none;
54 | -moz-user-select: none;
55 | -ms-user-select: none;
56 | user-select: none;
57 | }
58 | .elx-editable .elx-editable-column.valid-error .el-input__inner,
59 | .elx-editable .elx-editable-column.valid-error .el-input__inner:focus,
60 | .elx-editable .elx-editable-column.valid-error .el-textarea__inner,
61 | .elx-editable .elx-editable-column.valid-error .el-textarea__inner:focus {
62 | border-color: #f56c6c;
63 | }
64 | /* default tip */
65 | .elx-editable .elx-editable-column .editable-valid_error {
66 | display: none;
67 | text-align: left;
68 | }
69 | .elx-editable .elx-editable-column.valid-error .el-input__inner,
70 | .elx-editable .elx-editable-column.valid-error .el-input__inner:focus,
71 | .elx-editable .elx-editable-column.valid-error .el-textarea__inner,
72 | .elx-editable .elx-editable-column.valid-error .el-textarea__inner:focus {
73 | border-color: #f56c6c;
74 | }
75 | .elx-editable .editable-row:last-child .elx-editable-column.valid-error .editable-valid_error {
76 | top: auto;
77 | bottom: -moz-calc(100% + 10px);
78 | bottom: -webkit-calc(100% + 10px);
79 | bottom: calc(100% + 10px);
80 | }
81 | .elx-editable .editable-row:last-child .elx-editable-column.valid-error .editable-valid_error:before {
82 | top: auto;
83 | bottom: -12px;
84 | border-color: #f56c6c transparent transparent transparent;
85 | }
86 | .elx-editable .elx-editable-column.valid-error .editable-valid_error,
87 | .elx-editable .editable-row:first-child .elx-editable-column.valid-error .editable-valid_error {
88 | display: block;
89 | position: absolute;
90 | top: -moz-calc(100% + 10px);
91 | top: -webkit-calc(100% + 10px);
92 | top: calc(100% + 10px);
93 | left: 10px;
94 | bottom: auto;
95 | z-index: 2;
96 | min-width: 300px;
97 | }
98 | .elx-editable .elx-editable-column.valid-error .editable-valid_error>.valid-message,
99 | .elx-editable .editable-row:first-child .elx-editable-column.valid-error .editable-valid_error>.valid-message {
100 | display: inline-block;
101 | padding: 8px 10px;
102 | line-height: 1.5;
103 | color: #fff;
104 | background-color: #f56c6c;
105 | border-radius: 4px;
106 | font-size: 12px;
107 | word-wrap: break-word;
108 | }
109 | .elx-editable .elx-editable-column .editable-valid_error:before,
110 | .elx-editable .editable-row:first-child .elx-editable-column.valid-error .editable-valid_error:before {
111 | content: "";
112 | position: absolute;
113 | top: -12px;
114 | left: 20px;
115 | bottom: auto;
116 | border: 6px solid;
117 | border-color: transparent transparent #f56c6c transparent;
118 | }
119 | .elx-editable .elx-editable-column .editable-valid_wrapper {
120 | display: block;
121 | width: 100%;
122 | height: 100%;
123 | top: 0;
124 | left: 0;
125 | position: absolute;
126 | z-index: -1;
127 | }
128 |
--------------------------------------------------------------------------------
/examples/views/table/Base7.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
筛选
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | 查询
14 | 重置
15 |
16 |
17 |
18 |
19 | 导出
20 |
21 |
22 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
41 |
42 |
43 |
44 |
45 |
46 |
56 |
57 |
58 |
59 |
119 |
120 |
129 |
--------------------------------------------------------------------------------
/examples/views/table/Base5.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
合并行或列
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | 查询
14 | 重置
15 |
16 |
17 |
18 |
19 | 导出
20 |
21 |
22 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
52 |
53 |
54 |
55 |
127 |
128 |
137 |
--------------------------------------------------------------------------------
/examples/views/table/Base8.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
展开行
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | 查询
14 | 重置
15 |
16 |
17 |
18 |
19 | 导出
20 |
21 |
22 |
27 |
28 |
29 |
30 |
31 | {{ props.row.name }}
32 |
33 |
34 | {{ props.row.age }}
35 |
36 |
37 | {{ props.row.role }}
38 |
39 |
40 | {{ props.row.describe }}
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
66 |
67 |
68 |
69 |
126 |
127 |
132 |
--------------------------------------------------------------------------------
/examples/mock/api/index.js:
--------------------------------------------------------------------------------
1 | import { DELETE, POST, GET } from 'xe-ajax-mock'
2 | import Helper from './helper'
3 |
4 | GET('/api/conf/region/list', require('./conf/region.json'))
5 | GET('/api/conf/sex/list', require('./conf/sex.json'))
6 | GET('/api/conf/columns/list', require('./conf/columns.json'))
7 | GET('/api/conf/languages/list', require('./conf/languages.json'))
8 |
9 | class RoleVO {
10 | constructor (data) {
11 | this.id = data.id
12 | this.name = data.name
13 | this.describe = data.describe
14 | this.createTime = data.createTime
15 | this.updateTime = data.updateTime
16 | }
17 | }
18 | const roleHelper = new Helper(require('./role/list.json'), RoleVO)
19 | DELETE('/api/role/delete/{id}', roleHelper.deleteByPathVariable())
20 | POST('/api/role/add', roleHelper.insertByBody())
21 | POST('/api/role/update', roleHelper.updateByBody())
22 | POST('/api/role/save', roleHelper.saveListByBody())
23 | GET('/api/role/list', roleHelper.findList({ max: 10 }))
24 | GET('/api/role/page/list/{pageSize}/{currentPage}', roleHelper.findPageList())
25 |
26 | class UserVO {
27 | constructor (data) {
28 | this.id = data.id
29 | this.name = data.name
30 | this.password = data.password
31 | this.sex = data.sex
32 | this.role = data.role
33 | this.region = data.region
34 | this.email = data.email
35 | this.age = data.age
36 | this.rate = data.rate
37 | this.flag = data.flag
38 | this.phone = data.phone
39 | this.describe = data.describe
40 | this.describe2 = data.describe2
41 | this.describe3 = data.describe3
42 | this.attr1 = data.attr1
43 | this.attr2 = data.attr2
44 | this.attr3 = data.attr3
45 | this.attr4 = data.attr4
46 | this.attr5 = data.attr5
47 | this.attr6 = data.attr6
48 | this.createTime = data.createTime
49 | this.updateTime = data.updateTime
50 | }
51 | }
52 | const userHelper = new Helper(require('./user/list.json'), UserVO)
53 | DELETE('/api/user/delete/{id}', userHelper.deleteByPathVariable())
54 | POST('/api/user/add', userHelper.insertByBody())
55 | POST('/api/user/update', userHelper.updateByBody())
56 | POST('/api/user/save', userHelper.saveListByBody())
57 | GET('/api/user/list', userHelper.findList({ max: 10 }))
58 | GET('/api/user/page/list/{pageSize}/{currentPage}', userHelper.findPageList())
59 |
60 | class FileVO {
61 | constructor (data) {
62 | this.id = data.id
63 | this.parentId = data.parentId
64 | this.name = data.name
65 | this.size = data.size
66 | this.type = data.type
67 | this.createTime = data.createTime
68 | this.updateTime = data.updateTime
69 | }
70 | }
71 | const fileHelper = new Helper(require('./file/list.json'), FileVO)
72 | DELETE('/api/file/delete/{id}', fileHelper.deleteByPathVariable())
73 | POST('/api/file/add', fileHelper.insertByBody())
74 | POST('/api/file/update', fileHelper.updateByBody())
75 | POST('/api/file/save', fileHelper.saveTreeListByBody())
76 | GET('/api/file/list', fileHelper.findList())
77 | GET('/api/file/node/list', fileHelper.findTreeNodeList())
78 | GET('/api/file/page/list/{pageSize}/{currentPage}', fileHelper.findPageList())
79 |
80 | class ColumnVO {
81 | constructor (data) {
82 | this.id = data.id
83 | this.key = data.key
84 | this.name = data.name
85 | this.readonly = data.readonly
86 | this.required = data.required
87 | this.validator = data.validator
88 | this.validMsg = data.validMsg
89 | this.visible = data.visible
90 | this.width = data.width
91 | this.describe = data.describe
92 | this.createTime = data.createTime
93 | this.updateTime = data.updateTime
94 | }
95 | }
96 | const columnHelper = new Helper(require('./column/list.json'), ColumnVO)
97 | DELETE('/api/column/delete/{id}', columnHelper.deleteByPathVariable())
98 | POST('/api/column/add', columnHelper.insertByBody())
99 | POST('/api/column/update', columnHelper.updateByBody())
100 | POST('/api/column/save', columnHelper.saveListByBody())
101 | GET('/api/column/list', columnHelper.findList())
102 | GET('/api/column/page/list/{pageSize}/{currentPage}', columnHelper.findPageList())
103 |
104 | class i18nVO {
105 | constructor (data) {
106 | this.id = data.id
107 | this.key = data.key
108 | this.name = data.name
109 | this.language = data.language
110 | this.createTime = data.createTime
111 | this.updateTime = data.updateTime
112 | }
113 | }
114 | const i18nHelper = new Helper(require('./i18n/list.json'), i18nVO)
115 | DELETE('/api/i18n/delete/{id}', i18nHelper.deleteByPathVariable())
116 | POST('/api/i18n/add', i18nHelper.insertByBody())
117 | POST('/api/i18n/update', i18nHelper.updateByBody())
118 | POST('/api/i18n/save', i18nHelper.saveListByBody())
119 | GET('/api/i18n/list', i18nHelper.findList())
120 | GET('/api/i18n/page/list/{pageSize}/{currentPage}', i18nHelper.findPageList({ sort: ['key'], order: 'asc' }))
121 |
--------------------------------------------------------------------------------
/examples/views/editable/Click1.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
如果是单击模式会在点击后激活列编辑
4 |
5 |
6 | 新增
7 | 保存
8 | 导出
9 |
10 |
11 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | 删除
25 |
26 |
27 |
28 | -- slot append --
29 |
30 |
31 |
32 |
33 |
34 |
129 |
130 |
139 |
--------------------------------------------------------------------------------
/examples/views/editable/Dblclick1.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
如果是双击模式会在双击后激活列编辑
4 |
5 |
6 | 新增
7 | 保存
8 | 导出
9 |
10 |
11 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | 删除
26 |
27 |
28 |
29 | -- slot append --
30 |
31 |
32 |
33 |
34 |
35 |
130 |
131 |
140 |
--------------------------------------------------------------------------------
/examples/views/table/Base2.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
浮动列
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | 查询
14 | 重置
15 |
16 |
17 |
18 |
19 | 导出
20 |
21 |
22 |
28 |
29 |
30 |
31 |
32 | 名字
33 |
34 |
35 |
36 |
37 | {{ scope.row.age }}
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 | 打开链接
49 |
50 |
51 |
52 |
53 | 移除
54 |
55 |
56 |
57 |
58 |
68 |
69 |
70 |
71 |
128 |
129 |
138 |
--------------------------------------------------------------------------------
/examples/views/table/Custom1.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
动态显示、隐藏列
4 |
通过配置 custom-columns 参数初始化列,设置 visible 可以设置显示隐藏
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | 查询
15 | 重置
16 |
17 |
18 |
19 |
20 | 导出
21 |
22 |
23 |
24 | {{ item.label }}
25 |
26 |
27 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
68 |
69 |
70 |
71 |
146 |
147 |
159 |
--------------------------------------------------------------------------------
/lib/index.css:
--------------------------------------------------------------------------------
1 | .el-tooltip__popper.elx-valid_tooltip{background:#f56c6c}.el-tooltip__popper.elx-valid_tooltip[x-placement^=top] .popper__arrow,.el-tooltip__popper.elx-valid_tooltip[x-placement^=top] .popper__arrow:after{border-top-color:#f56c6c}.el-tooltip__popper.elx-valid_tooltip[x-placement^=bottom] .popper__arrow,.el-tooltip__popper.elx-valid_tooltip[x-placement^=bottom] .popper__arrow:after{border-bottom-color:#f56c6c}.el-tooltip__popper.elx-valid_tooltip[x-placement^=left] .popper__arrow,.el-tooltip__popper.elx-valid_tooltip[x-placement^=left] .popper__arrow:after{border-left-color:#f56c6c}.el-tooltip__popper.elx-valid_tooltip[x-placement^=right] .popper__arrow,.el-tooltip__popper.elx-valid_tooltip[x-placement^=right] .popper__arrow:after{border-right-color:#f56c6c}.elx-contextmenu,.elx-contextmenu .ctx-menu_child-wrapper{position:absolute;top:0;left:0;z-index:88;font-size:12px;color:#000;background:#fff;border:1px solid #c6c6c6;-webkit-box-shadow:2px 2px 4px -2px #666;box-shadow:2px 2px 4px -2px #666;padding:0 1px;font-family:Source Sans Pro,Helvetica Neue,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.elx-contextmenu>.ctx-menu_wrapper,.elx-contextmenu>.ctx-menu_wrapper .ctx-menu_child-wrapper{margin:0;padding:0;list-style-type:none;border-bottom:1px solid #e8eaed}.elx-contextmenu>.ctx-menu_wrapper li{position:relative;margin:1px 0;border:1px solid transparent}.elx-contextmenu>.ctx-menu_wrapper li:last-child{border:0}.elx-contextmenu>.ctx-menu_wrapper li.active{color:#2b2b2b;background-color:#c5c5c5;border-color:#c5c5c5}.elx-contextmenu>.ctx-menu_wrapper li.disabled{color:#b1b1b1}.elx-contextmenu>.ctx-menu_wrapper li.disabled.active{border-color:#c0c1c2;background-color:#eee}.elx-contextmenu>.ctx-menu_wrapper li.disabled.active:hover{background-color:inherit}.elx-contextmenu>.ctx-menu_wrapper .ctx-menu_link{display:block;padding:0 30px;width:100px;line-height:26px}.elx-contextmenu>.ctx-menu_wrapper .ctx-prefix-icon,.elx-contextmenu>.ctx-menu_wrapper .ctx-suffix-icon{position:absolute;top:5px;margin-right:5px;font-size:16px}.elx-contextmenu>.ctx-menu_wrapper .ctx-prefix-icon{left:5px}.elx-contextmenu>.ctx-menu_wrapper .ctx-suffix-icon{right:5px}.elx-contextmenu>.ctx-menu_wrapper .content{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.elx-contextmenu .ctx-menu_child-wrapper{display:none;z-index:99;top:0;left:100%}.elx-contextmenu .ctx-menu_child-wrapper.show{display:block}.elx-editable .editable-required-icon:before{content:"*";color:#f56c6c}.elx-editable.el-table--mini .elx-editable-column{height:36px}.elx-editable.el-table--small .elx-editable-column{height:40px}.elx-editable.el-table--medium .elx-editable-column{height:44px}.elx-editable.el-table--large .elx-editable-column,.elx-editable .elx-editable-column{height:48px;padding:0}.elx-editable .elx-editable-column.elx_dirty{position:relative}.elx-editable .elx-editable-column.elx_dirty:before{content:"";top:-5px;left:-5px;position:absolute;border:5px solid;border-color:transparent #f56c6c transparent transparent;-webkit-transform:rotate(45deg);transform:rotate(45deg)}.elx-editable .elx-editable-column .cell>.edit-input,.elx-editable .elx-editable-column .cell>.el-autocomplete,.elx-editable .elx-editable-column .cell>.el-cascader,.elx-editable .elx-editable-column .cell>.el-date-editor,.elx-editable .elx-editable-column .cell>.el-input-number,.elx-editable .elx-editable-column .cell>.el-select{width:100%}.elx-editable .elx-editable-column.elx_edit.elx_disabled,.elx-editable .elx-editable-row.elx_disabled{cursor:not-allowed}.elx-editable .elx-editable-column.elx_edit.elx_active .cell{line-height:inherit;overflow:inherit;position:relative}.elx-editable.editable_click .elx-editable-column.elx_edit,.elx-editable.editable_dblclick .elx-editable-column.elx_edit{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.elx-editable .elx-editable-column .editable-valid_error{display:none;text-align:left}.elx-editable .elx-editable-column.valid-error .el-input__inner,.elx-editable .elx-editable-column.valid-error .el-input__inner:focus,.elx-editable .elx-editable-column.valid-error .el-textarea__inner,.elx-editable .elx-editable-column.valid-error .el-textarea__inner:focus{border-color:#f56c6c}.elx-editable .editable-row:last-child .elx-editable-column.valid-error .editable-valid_error{top:auto;bottom:calc(100% + 10px)}.elx-editable .editable-row:last-child .elx-editable-column.valid-error .editable-valid_error:before{top:auto;bottom:-12px;border-color:#f56c6c transparent transparent transparent}.elx-editable .editable-row:first-child .elx-editable-column.valid-error .editable-valid_error,.elx-editable .elx-editable-column.valid-error .editable-valid_error{display:block;position:absolute;top:calc(100% + 10px);left:10px;bottom:auto;z-index:2;min-width:300px}.elx-editable .editable-row:first-child .elx-editable-column.valid-error .editable-valid_error>.valid-message,.elx-editable .elx-editable-column.valid-error .editable-valid_error>.valid-message{display:inline-block;padding:8px 10px;line-height:1.5;color:#fff;background-color:#f56c6c;border-radius:4px;font-size:12px;word-wrap:break-word}.elx-editable .editable-row:first-child .elx-editable-column.valid-error .editable-valid_error:before,.elx-editable .elx-editable-column .editable-valid_error:before{content:"";position:absolute;top:-12px;left:20px;bottom:auto;border:6px solid;border-color:transparent transparent #f56c6c transparent}.elx-editable .elx-editable-column .editable-valid_wrapper{display:block;width:100%;height:100%;top:0;left:0;position:absolute;z-index:-1}
--------------------------------------------------------------------------------
/examples/views/editable/BigScroll3.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
单击模式、行编辑
8 |
影响性能的参数:data、rowKey、fixed
9 |
兼容性:不兼容动态行高;不支持树结构
10 |
11 |
12 | 新增
13 | 导出
14 |
15 |
16 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 | 删除
40 |
41 |
42 |
43 |
44 |
45 |
46 |
137 |
138 |
147 |
--------------------------------------------------------------------------------
/examples/views/editable/BigScroll2.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
单击模式、列编辑、自定义索引
8 |
影响性能的参数:data、rowKey、fixed
9 |
兼容性:不兼容动态行高;不支持树结构
10 |
11 |
12 | 新增
13 | 导出
14 |
15 |
16 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 | 删除
40 |
41 |
42 |
43 |
44 |
45 |
46 |
140 |
141 |
150 |
--------------------------------------------------------------------------------
/examples/views/table/Custom3.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
动态显示、隐藏列
4 |
使用 localStorage 保存自定义列
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | 查询
15 | 重置
16 |
17 |
18 |
19 |
20 | 导出
21 |
22 |
23 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
68 |
69 |
70 |
75 |
80 |
81 |
82 |
83 |
84 |
176 |
177 |
186 |
--------------------------------------------------------------------------------
/examples/views/table/Custom2.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
动态显示、隐藏列
4 |
通过配置 custom-columns 参数初始化列,设置 visible 可以设置显示隐藏
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | 查询
15 | 重置
16 |
17 |
18 |
19 |
20 | 导出
21 |
22 |
23 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
68 |
69 |
70 |
75 |
80 |
81 |
82 |
83 |
84 |
181 |
182 |
191 |
--------------------------------------------------------------------------------
/examples/views/editable/BigScroll4.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
双击模式、列编辑
8 |
影响性能的参数:data、rowKey、fixed
9 |
兼容性:不兼容动态行高;不支持树结构
10 |
11 |
12 | 新增
13 | 导出
14 |
15 |
16 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 | 删除
46 |
47 |
48 |
49 |
50 |
51 |
52 |
196 |
197 |
206 |
--------------------------------------------------------------------------------
/examples/views/editable/Excel2.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
A字段(校验数值)B字段(校验汉字)C字段(校验字母)D字段(校验整数)E字段(校验小数)
4 |
5 |
6 | 新增
7 | 清空筛选条件
8 | 清空排序条件
9 | 获取所有
10 | 获取改动
11 | 获取有值数据
12 |
13 |
14 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
145 |
146 |
191 |
--------------------------------------------------------------------------------
/examples/views/editable/Dblclick8.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
懒加载树表格:只支持小部分功能
4 |
5 |
6 | 标记/取消删除
7 | 删除选中
8 | 保存
9 | 导出
10 |
11 |
12 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
204 |
205 |
214 |
--------------------------------------------------------------------------------
/packages/editable/src/scroll.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 滚动渲染,以优化的方式渲染表格
3 | * 计算规则:
4 | * top --> Space
5 | * --> visibleStart
6 | * --> renderSize
7 | * --> offsetSize
8 | * table --> visibleIndex
9 | * --> offsetSize
10 | * bottom --> Space
11 | */
12 | const ScrollHandle = {
13 | reload () {
14 | return function (isReload) {
15 | return this.$nextTick().then(() => {
16 | // 如果重新加载表格,索引重新初始化
17 | if (!isReload) {
18 | this.visibleIndex = 0
19 | this.visibleStart = 0
20 | this._computeScroll(isReload)
21 | }
22 | this.datas = this._fullData.slice(this.visibleStart, this.visibleStart + this.renderSize)
23 | return this.$nextTick().then(() => {
24 | this._computeScroll(isReload)
25 | // 如果重新加载表格,滚动位置重新初始化
26 | if (!isReload) {
27 | updateScroll(this.elemStore)
28 | }
29 | })
30 | })
31 | }
32 | },
33 | bind () {
34 | return function () {
35 | // 绑定事件,生成对应元素
36 | return this.$nextTick().then(() => {
37 | let elTableElem = this.$refs.refElTable.$el
38 | let bodyWrapper = elTableElem.querySelector('.el-table__body-wrapper')
39 | let fixedLeftWrapper = elTableElem.querySelector('.el-table__fixed .el-table__fixed-body-wrapper')
40 | let fixedRightWrapper = elTableElem.querySelector('.el-table__fixed-right .el-table__fixed-body-wrapper')
41 | let elemStore = createScrollElem(elTableElem, bodyWrapper, '.el-table__header-wrapper', '.el-table__body')
42 | if (fixedLeftWrapper) {
43 | elemStore.fixedLeft = createScrollElem(elTableElem, fixedLeftWrapper, 0, 'table')
44 | }
45 | if (fixedRightWrapper) {
46 | elemStore.fixedRight = createScrollElem(elTableElem, fixedRightWrapper, 0, 'table')
47 | }
48 | bodyWrapper.addEventListener('scroll', this._scrollEvent, false)
49 | this.elemStore = elemStore
50 | })
51 | }
52 | },
53 | unbind () {
54 | return function () {
55 | // 事件解绑
56 | unbindSpace(this.elemStore)
57 | this.elemStore.bodyWrapper.removeEventListener('scroll', this._scrollEvent)
58 | }
59 | },
60 | scroll () {
61 | return function (evnt) {
62 | let isRender
63 | let { bodyWrapper } = this.elemStore
64 | let fullData = this._fullData
65 | let len = fullData.length
66 | let renderSize = this.renderSize
67 | let scrollTop = bodyWrapper.scrollTop
68 | let isTop = scrollTop < this.scrollTop
69 | let visibleStart = this.visibleStart
70 | let visibleSize = this.visibleSize
71 | let offsetSize = this.offsetSize
72 | let rowHeight = this.rowHeight
73 | let toVisibleIndex = Math.ceil(scrollTop / rowHeight)
74 | if (isTop) {
75 | // 如果向上滚动
76 | if (visibleStart > 0 && (toVisibleIndex - offsetSize <= visibleStart)) {
77 | isRender = true
78 | }
79 | } else {
80 | // 如果向下滚动
81 | if (visibleStart < len - renderSize && (toVisibleIndex + visibleSize + offsetSize >= visibleStart + renderSize)) {
82 | isRender = true
83 | }
84 | }
85 | if (isRender) {
86 | // 超过阈值重新渲染
87 | let toVisibleStart = toVisibleIndex - Math.floor(isTop ? renderSize / 2 : visibleSize)
88 | if (toVisibleStart < 0) {
89 | toVisibleStart = 0
90 | } else if (toVisibleStart + renderSize >= len) {
91 | toVisibleStart = len - renderSize
92 | }
93 | if (toVisibleStart !== visibleStart) {
94 | this.visibleStart = toVisibleStart
95 | // 渲染指定位置的数据
96 | this.datas = fullData.slice(toVisibleStart, toVisibleStart + renderSize)
97 | // 重新计算顶部空间和底部空间,支撑滚动条
98 | this._setScrollSpace(toVisibleStart * rowHeight, (len - renderSize - toVisibleStart) * rowHeight)
99 | // 渲染完成复原最后位置,保持滚动位置不变
100 | this.$nextTick(() => {
101 | bodyWrapper.scrollTop = scrollTop
102 | })
103 | }
104 | }
105 | this.scrollTop = scrollTop
106 | this.visibleIndex = toVisibleIndex
107 | }
108 | },
109 | space () {
110 | return function (topHeight, bottomHeight) {
111 | let { topSpace, bottomSpace, fixedLeft, fixedRight } = this.elemStore
112 | topSpace.style.height = `${topHeight}px`
113 | bottomSpace.style.height = `${bottomHeight}px`
114 | if (fixedLeft) {
115 | fixedLeft.topSpace.style.height = `${topHeight}px`
116 | fixedLeft.bottomSpace.style.height = `${bottomHeight}px`
117 | }
118 | if (fixedRight) {
119 | fixedRight.topSpace.style.height = `${topHeight}px`
120 | fixedRight.bottomSpace.style.height = `${bottomHeight}px`
121 | }
122 | }
123 | },
124 | compute (size) {
125 | return function (isReload) {
126 | if (this.scrollLoad) {
127 | let { headerWrapper, bodyWrapper, table } = this.elemStore
128 | let fullData = this._fullData
129 | let firstTrElem = table.querySelector('tbody>tr')
130 | if (!firstTrElem) {
131 | firstTrElem = headerWrapper.querySelector('thead>tr')
132 | }
133 | if (firstTrElem) {
134 | this.rowHeight = firstTrElem.clientHeight
135 | }
136 | let visibleSize = Math.ceil(bodyWrapper.clientHeight / this.rowHeight)
137 | let renderSize = getRenderSize(this.configs, this.elemStore, visibleSize, size)
138 | this.offsetSize = getOffsetSize(this.configs, renderSize, visibleSize)
139 | this.visibleSize = visibleSize
140 | this.renderSize = renderSize
141 | if (!isReload) {
142 | this._setScrollSpace(0, fullData.length > renderSize ? (fullData.length - renderSize) * this.rowHeight : 0)
143 | }
144 | }
145 | }
146 | }
147 | }
148 |
149 | function updateScroll ({ bodyWrapper, fixedLeft, fixedRight }, scrollTop, scrollLeft) {
150 | bodyWrapper.scrollTop = scrollTop
151 | bodyWrapper.scrollLeft = scrollLeft
152 | if (fixedLeft) {
153 | updateScroll(fixedLeft, scrollTop, scrollLeft)
154 | }
155 | if (fixedRight) {
156 | updateScroll(fixedRight, scrollTop, scrollLeft)
157 | }
158 | }
159 |
160 | function unbindSpace ({ bodyWrapper, topSpace, bottomSpace, fixedLeft, fixedRight }) {
161 | bodyWrapper.removeChild(topSpace)
162 | bodyWrapper.removeChild(bottomSpace)
163 | if (fixedLeft) {
164 | unbindSpace(fixedLeft)
165 | }
166 | if (fixedRight) {
167 | unbindSpace(fixedRight)
168 | }
169 | }
170 |
171 | function createScrollElem (elTableElem, bodyWrapper, queryHeaderWrapper, queryTable) {
172 | let table = bodyWrapper.querySelector(queryTable)
173 | let topSpace = document.createElement('div')
174 | let bottomSpace = document.createElement('div')
175 | topSpace.className = 'elx-scroll_top-space'
176 | bottomSpace.className = 'elx-scroll_bottom-space'
177 | bodyWrapper.insertBefore(topSpace, table)
178 | bodyWrapper.insertBefore(bottomSpace, table.nextSibling)
179 | return {
180 | headerWrapper: queryHeaderWrapper && elTableElem.querySelector(queryHeaderWrapper),
181 | bodyWrapper,
182 | table,
183 | topSpace,
184 | bottomSpace
185 | }
186 | }
187 |
188 | /**
189 | * renderSize 不应该低于 visibleSize 的3倍
190 | */
191 | function getRenderSize (configs, elemStore, visibleSize, defSize) {
192 | if (configs.renderSize) {
193 | return configs.renderSize
194 | }
195 | if (elemStore.fixedLeft || elemStore.fixedRight) {
196 | return visibleSize * Math.max(Math.floor(defSize / 2), 3)
197 | }
198 | return visibleSize * defSize
199 | }
200 |
201 | /**
202 | * offsetSize 不应该低于 visibleSize 的一半
203 | */
204 | function getOffsetSize (configs, renderSize, visibleSize) {
205 | let offsetSize = 0
206 | if (configs.offsetSize) {
207 | return configs.offsetSize
208 | }
209 | if (renderSize > visibleSize * 4) {
210 | offsetSize = visibleSize * 2
211 | } else if (renderSize > visibleSize * 3) {
212 | offsetSize = visibleSize
213 | }
214 | return Math.max(offsetSize, Math.ceil(visibleSize / 2))
215 | }
216 |
217 | export default ScrollHandle
218 |
--------------------------------------------------------------------------------
/examples/views/editable/Click11.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
拖动排序
4 |
5 |
6 | 保存
7 | 导出
8 |
9 |
10 |
20 |
21 |
22 |
23 |
24 | 按住后可以上下拖动排序,
完成后点击保存即可!
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 | {{ scope.row.name }}
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 | {{ getSelectLabel(scope.row.sex, 'value', 'label', sexList) }}
46 |
47 |
48 |
49 |
50 |
51 | {{ scope.row.age }}
52 |
53 |
54 |
55 |
56 |
57 | {{ getCascaderLabel(scope.row.region, regionList) }}
58 |
59 |
60 |
61 |
62 |
63 | {{ getDatePicker(scope.row.date) }}
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
185 |
186 |
211 |
--------------------------------------------------------------------------------
/examples/views/editable/Click8.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
合并行或列
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | 查询
19 | 重置
20 |
21 |
22 |
23 |
24 | 新增
25 | 标记/取消删除
26 | 保存
27 | 导出
28 |
29 |
30 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
60 |
61 |
62 |
63 |
227 |
228 |
245 |
--------------------------------------------------------------------------------
/examples/views/editable/BigScroll1.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
启用滚动渲染,设置 render='scroll' 可以流畅的支撑海量数据
8 |
影响性能的参数:data、rowKey、fixed
9 |
兼容性:不兼容动态行高;不支持树结构
10 |
11 |
12 | 新增
13 | 导出
14 |
15 |
16 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 | 保存
38 | 取消
39 |
40 |
41 | 编辑
42 | 删除
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
215 |
216 |
225 |
--------------------------------------------------------------------------------
/examples/views/editable/Manual1.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
如果是手动模式会自动关闭触发激活
4 |
5 |
6 | 新增
7 | 导出
8 |
9 |
10 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | 保存
26 | 取消
27 |
28 |
29 | 编辑
30 | 删除
31 |
32 |
33 |
34 |
35 | -- slot append --
36 |
37 |
38 |
39 |
40 |
41 |
236 |
237 |
246 |
--------------------------------------------------------------------------------
/examples/views/editable/Excel4.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
上下左右方向键切换列、Tab 键切换列、选中后可直接输入值覆盖旧值
4 |
A字段(校验数值)B字段(校验汉字)C字段(校验字母)D字段(校验整数)E字段(校验小数)
5 |
6 |
7 | 新增
8 | 清空筛选条件
9 | 清空排序条件
10 | 获取所有
11 | 获取改动
12 | 获取有值数据
13 | 导出数据
14 |
15 |
16 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
42 |
47 |
48 |
49 |
50 |
51 |
190 |
191 |
240 |
--------------------------------------------------------------------------------