├── img ├── editGif.gif ├── canEdit2.png ├── canEdit4.png ├── canedit3.png └── canEditGrid@2x.png ├── component ├── index.js ├── SvgIcon.vue ├── EditTable │ ├── DatePickerYear.vue │ ├── DatePickerMonth.vue │ ├── InputNumber.vue │ ├── DatePicker.vue │ ├── DatePickerRange.vue │ ├── DatePickerMonthRange.vue │ ├── TableInput.vue │ ├── TableSelect.vue │ ├── TableTreeSelect.vue │ ├── tableJson.js │ ├── DragSpan.vue │ ├── EditSub.vue │ └── CanEditTable.vue ├── scrollable.js └── ScrollBar.vue ├── App.vue ├── .gitignore ├── main.js ├── router.js ├── index.js ├── package.json ├── view ├── empEditData.js ├── EditTableJson.js └── EditTableTest.vue └── README.md /img/editGif.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhjing1019/CanEditGrid/HEAD/img/editGif.gif -------------------------------------------------------------------------------- /img/canEdit2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhjing1019/CanEditGrid/HEAD/img/canEdit2.png -------------------------------------------------------------------------------- /img/canEdit4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhjing1019/CanEditGrid/HEAD/img/canEdit4.png -------------------------------------------------------------------------------- /img/canedit3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhjing1019/CanEditGrid/HEAD/img/canedit3.png -------------------------------------------------------------------------------- /img/canEditGrid@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhjing1019/CanEditGrid/HEAD/img/canEditGrid@2x.png -------------------------------------------------------------------------------- /component/index.js: -------------------------------------------------------------------------------- 1 | import CanEditTable from "./EditTable/CanEditTable.vue"; 2 | 3 | // 为组件添加 install 方法,用于按需引入 4 | CanEditTable.install = function(Vue) { 5 | Vue.component(CanEditTable.name, CanEditTable); 6 | }; 7 | 8 | export default CanEditTable; 9 | -------------------------------------------------------------------------------- /App.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 12 | 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 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 | -------------------------------------------------------------------------------- /main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import ElementUI from 'element-ui' 3 | import 'element-ui/lib/theme-chalk/index.css' 4 | import App from './App.vue' 5 | import ElTreeSelect from 'el-tree-select'; 6 | import EditTable from './index.js' 7 | Vue.use(ElTreeSelect); 8 | Vue.use(EditTable); 9 | 10 | Vue.use(ElementUI) 11 | 12 | new Vue({ 13 | el: '#app', 14 | render: h => h(App) 15 | }) 16 | 17 | -------------------------------------------------------------------------------- /router.js: -------------------------------------------------------------------------------- 1 | import Vue from "vue"; 2 | import Router from "vue-router"; 3 | import EditTableTest from "./view/EditTableTest.vue" 4 | 5 | 6 | Vue.use(Router); 7 | 8 | export default new Router({ 9 | routes: [ 10 | { 11 | path: "/", 12 | name: "EditTableTest", 13 | component: EditTableTest 14 | }, 15 | // { 16 | // path: "/EditTable", 17 | // name: "EditTable", 18 | // component: EditTable 19 | // }, 20 | // { 21 | // path: "/CutImages", 22 | // name: "CutImages", 23 | // component: CutImages 24 | // } 25 | ] 26 | }); 27 | -------------------------------------------------------------------------------- /component/SvgIcon.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 35 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | // 导入单个组件 2 | import CanEditTable from "./component/index.js"; 3 | 4 | 5 | 6 | const components = [ 7 | CanEditTable, 8 | ]; 9 | 10 | const install = function(Vue) { 11 | if (install.installed) return; 12 | install.installed = true; 13 | 14 | components.map(component => { 15 | Vue.component(component.name, component); 16 | }); 17 | }; 18 | 19 | // const EgAdapter = {}; 20 | 21 | // EgAdapter.install = Vue => { 22 | // if (EgAdapter.install.installed) return; 23 | // components.map(component => { 24 | // Vue.component(component.name, component); 25 | // }); 26 | // Vue.prototype.$EgMessage = EgMessage; 27 | // }; 28 | 29 | if (typeof window !== "undefined" && window.Vue) { 30 | install(window.Vue); 31 | } 32 | 33 | // if (typeof window !== "undefined" && window.Vue) { 34 | // EgAdapter.install(window.Vue); 35 | // } 36 | 37 | // 这里可以用es6的解构语法导入组件 大概就是这个意思 毕竟没有用插件 38 | export { 39 | CanEditTable, 40 | }; 41 | export default { 42 | install 43 | }; 44 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "can-edit-table", 3 | "version": "1.0.7", 4 | "description": "1、下载依赖包 `npm install` 2、启动项目 `vue serve` ## 项目概览 ![图片名称](https://github.com/zhjing1019/CanEditGrid/blob/master/img/editGif.gif) 基于vue和element的可拖拽赋值的可编辑表格,支持表格实时校验,联动校验。 ![图片名称](https://github.com/zhjing1019/CanEditGrid/blob/master/img/canEditGrid%402x.png) 支持input、datepicker、select、selctTree等等。可以自定义td的内容,支持slot插槽。", 5 | "main": "index.js", 6 | "dependencies": { 7 | "element-ui": "^2.10.1", 8 | "el-tree-select": "^3.1.3", 9 | "node-sass": "^4.12.0", 10 | "sass-loader": "^7.1.0" 11 | }, 12 | "devDependencies": {}, 13 | "scripts": { 14 | "test": "echo \"Error: no test specified\" && exit 1" 15 | }, 16 | "repository": { 17 | "type": "git", 18 | "url": "git+https://github.com/zhjing1019/CanEditGrid.git" 19 | }, 20 | "author": "zhjing1019 <954740056@qq.com> (http://example.com)", 21 | "license": "ISC", 22 | "bugs": { 23 | "url": "https://github.com/zhjing1019/CanEditGrid/issues" 24 | }, 25 | "homepage": "https://github.com/zhjing1019/CanEditGrid#readme" 26 | } 27 | -------------------------------------------------------------------------------- /component/EditTable/DatePickerYear.vue: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /component/EditTable/DatePickerMonth.vue: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /component/EditTable/InputNumber.vue: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /component/EditTable/DatePicker.vue: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /component/EditTable/DatePickerRange.vue: -------------------------------------------------------------------------------- 1 | 2 | 19 | 20 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /component/EditTable/DatePickerMonthRange.vue: -------------------------------------------------------------------------------- 1 | 2 | 19 | 20 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /component/EditTable/TableInput.vue: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /component/EditTable/TableSelect.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /component/EditTable/TableTreeSelect.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 62 | 63 | 85 | -------------------------------------------------------------------------------- /component/scrollable.js: -------------------------------------------------------------------------------- 1 | import { addResizeListener, removeResizeListener } from "element-ui/lib/utils/resize-event"; 2 | 3 | export default { 4 | data() { 5 | return { 6 | scrollX: 0, 7 | scrollY: 0, 8 | clientWidth: 0, 9 | clientHeight: 0 10 | }; 11 | }, 12 | computed: { 13 | actualHeight() { 14 | return 100; 15 | }, 16 | actualWidth() { 17 | return 100; 18 | }, 19 | // 水平方向移动百分比 20 | hMove() { 21 | return (this.scrollX * 100) / this.clientWidth; 22 | }, 23 | // 垂直方向移动百分比 24 | vMove() { 25 | return (this.scrollY * 100) / this.clientHeight; 26 | }, 27 | hBarSize() { 28 | return (this.clientWidth * 100) / this.actualWidth; 29 | }, 30 | vBarSize() { 31 | return (this.clientHeight * 100) / this.actualHeight; 32 | }, 33 | scrollXMax() { 34 | const result = this.actualWidth - this.clientWidth; 35 | return result > 0 ? result : 0; 36 | }, 37 | scrollYMax() { 38 | const result = this.actualHeight - this.clientHeight; 39 | return result > 0 ? result : 0; 40 | } 41 | }, 42 | mounted() { 43 | addResizeListener(this.$el, this.sizeChanged); 44 | }, 45 | beforeDestroy() { 46 | removeResizeListener(this.$el, this.sizeChanged); 47 | }, 48 | methods: { 49 | sizeChanged() { 50 | this.clientWidth = this.$el.clientWidth; 51 | this.clientHeight = this.$el.clientHeight; 52 | this.$nextTick(() => { 53 | if (this.scrollX > this.scrollXMax) this.scrollX = this.scrollXMax; 54 | if (this.scrollY > this.scrollYMax) this.scrollY = this.scrollYMax; 55 | }); 56 | }, 57 | vScroll(percent) { 58 | this.scrollY = (this.actualHeight * percent) / 100; 59 | }, 60 | hScroll(percent) { 61 | this.scrollX = (this.actualWidth * percent) / 100; 62 | }, 63 | wheel(e) { 64 | e.preventDefault(); 65 | if (e.deltaX) { 66 | let x = this.scrollX + e.deltaX; 67 | if (x < 0) x = 0; 68 | if (x > this.scrollXMax) x = this.scrollXMax; 69 | if (this.scrollX != x) this.scrollX = x; 70 | } 71 | if (e.deltaY) { 72 | let y = this.scrollY + e.deltaY; 73 | if (y < 0) y = 0; 74 | if (y > this.scrollYMax) y = this.scrollYMax; 75 | if (this.scrollY != y) this.scrollY = y; 76 | } 77 | } 78 | } 79 | }; 80 | -------------------------------------------------------------------------------- /view/empEditData.js: -------------------------------------------------------------------------------- 1 | 2 | export default { 3 | //表格类型 4 | fixCols: 1, 5 | tableHeaderHeight: 40, 6 | tableTdHeight: 40, 7 | ref: "tableEdit2", 8 | editTable: { 9 | editTableType: "del", 10 | rules: { 11 | zzsj: [{ type: "date", required: true, message: "请选择时间", trigger: "change" }], 12 | zzlb: [{ required: true, message: "请选择类别", trigger: "change" }], 13 | } 14 | }, 15 | //表头数据 16 | headers: [ 17 | { 18 | name: "zzry", 19 | title: "测试1", 20 | width: 350, 21 | slot: true 22 | }, 23 | { 24 | name: "zzsj", 25 | width: 200, 26 | title: "测试时间", 27 | editType: "date", 28 | pickerOptions: true, 29 | }, 30 | { 31 | name: "sfz", 32 | width: 200, 33 | title: "身份证(slot内容、自定义校验规则)", 34 | slot: true 35 | }, 36 | { 37 | name: "zzlb", 38 | width: 200, 39 | title: "测试类别", 40 | editType: "select", 41 | label: "code", 42 | value: "id", 43 | list: [ 44 | { 45 | code: "测试code1", 46 | id: "1" 47 | }, 48 | { 49 | code: "测试code2", 50 | id: "2" 51 | }, 52 | { 53 | code: "测试code3", 54 | id: "3" 55 | }, 56 | { 57 | code: "测试code4", 58 | id: "4" 59 | } 60 | ] 61 | }, 62 | { 63 | name: "khqk", 64 | width: 200, 65 | title: "测试(只展示数据)", 66 | editType: "none" 67 | }, 68 | { 69 | name: "zzsm", 70 | title: "测试三", 71 | width: 200, 72 | editType: "input" 73 | } 74 | ], 75 | data: [ 76 | { 77 | zzry: { 78 | name: "测试", 79 | sex: "男", 80 | bus: "测试部门", 81 | pos: "测试", 82 | emp: "测试", 83 | auth: "测试", 84 | num: "测试" 85 | }, 86 | zzsj: "", 87 | zzlb: "", 88 | khqk: "测试", 89 | zzsm: "测试", 90 | sfz: "" 91 | }, 92 | { 93 | zzry: { 94 | name: "测试", 95 | sex: "测试", 96 | bus: "测试", 97 | pos: "测试", 98 | emp: "测试", 99 | auth: "测试", 100 | num: "测试" 101 | }, 102 | zzsj: "", 103 | zzlb: "", 104 | khqk: "测试", 105 | zzsm: "测试", 106 | sfz: "" 107 | } 108 | ] 109 | }; 110 | -------------------------------------------------------------------------------- /component/ScrollBar.vue: -------------------------------------------------------------------------------- 1 | 6 | 96 | 145 | -------------------------------------------------------------------------------- /view/EditTableJson.js: -------------------------------------------------------------------------------- 1 | export default { 2 | //表格类型 3 | //(editTableType: 'del'表示可以删除的表格,'clear'表示可以清空的表格) 4 | //typeIcon: 序号处hover之后icon的名字 5 | fixCols: 1, 6 | tableHeaderHeight: 40, 7 | tableTdHeight: 40, 8 | ref: "tableEdit1", 9 | editTable: { 10 | rules: { 11 | input: [ 12 | { required: true, message: "请输入活动名称ceshi", trigger: "change" }, 13 | { min: 1, max: 3, message: "长度在 1 到 3 个字符", trigger: "change" } 14 | ], 15 | newPost: [ 16 | { required: true, message: "请输入活动名称", trigger: "change" }, 17 | { min: 1, max: 5, message: "长度在 1 到 5 个字符", trigger: "change" } 18 | ], 19 | time: { 20 | type: "date", 21 | required: true, 22 | message: "请选择日期", 23 | trigger: "change" 24 | }, 25 | newDepartment: [{ required: true, message: "请选择部门", trigger: "change" }], 26 | treeSelect: [{ required: true, message: "请选择部门", trigger: "change" }], 27 | timeRange: [{ type: "date", required: true, message: "请选择时间", trigger: "change" }], 28 | dateMonth: [{ type: "date", required: true, message: "请选择时间", trigger: "change" }], 29 | dateYear: [{ type: "date", required: true, message: "请选择时间", trigger: "change" }], 30 | dateMonthRange: [{ type: "date", required: true, message: "请选择时间", trigger: "change" }], 31 | inputNumber: [{ type: "number", required: true, message: "请输入数字输入框", trigger: "change" }], 32 | inputNumber1: [{ type: "number", required: true, message: "请输入数字输入框", trigger: "change" }], 33 | selectPerson1: [{ type: "string", required: true, message: "请选择人", trigger: "change" }], 34 | select: [{ type: "string", required: true, message: "请选择code", trigger: "change" }] 35 | } 36 | }, 37 | 38 | //表头数据 39 | headers: [ 40 | { 41 | name: "fixedCol", 42 | title: "固定的列", 43 | width: 100, 44 | slot: true 45 | }, 46 | { 47 | name: "selectPerson", 48 | width: 200, 49 | title: "测试选择组织机构组件", 50 | slot: true 51 | }, 52 | { 53 | name: "treeSelect", 54 | title: "选择树机构", 55 | width: 200, 56 | // slot: true, 57 | editType: "treeSelect", 58 | disabled: false, 59 | treeParams: { 60 | clickParent: true, 61 | filterable: false, 62 | "check-strictly": true, 63 | "default-expand-all": false, 64 | "expand-on-click-node": false, 65 | data: [ 66 | { 67 | id: "1", 68 | name: "哎哎哎", 69 | children: [{ id: "3", name: "啊啊啊啊" }] 70 | }, 71 | { 72 | id: "2", 73 | name: "发生的" 74 | } 75 | ], 76 | props: { 77 | children: "children", 78 | label: "name", 79 | value: "id" 80 | } 81 | }, 82 | selectParams: { 83 | multiple: false, 84 | clearable: true, 85 | placeholder: "请输入内容" 86 | }, 87 | list: [] 88 | }, 89 | { 90 | name: "input", 91 | title: "input输入框", 92 | width: 100, 93 | editType: "input", 94 | list: [] 95 | }, 96 | { 97 | name: "select", 98 | title: "select选择框", 99 | width: 100, 100 | multiple: false, 101 | editType: "select", 102 | label: "code", 103 | value: "id", 104 | list: [ 105 | { 106 | code: "测试code1", 107 | id: "1" 108 | }, 109 | { 110 | code: "测试code2", 111 | id: "2" 112 | }, 113 | { 114 | code: "测试code3", 115 | id: "3" 116 | }, 117 | { 118 | code: "测试code4", 119 | id: "4" 120 | } 121 | ] 122 | }, 123 | { 124 | name: "time", 125 | title: "年月日时间选择框", 126 | width: 150, 127 | editType: "date", 128 | // generalDate: "2019-06-03", 129 | list: [] 130 | }, 131 | { 132 | name: "dateRange", 133 | title: "年月日时间范围", 134 | width: 300, 135 | editType: "dateRange", 136 | list: [] 137 | }, 138 | { 139 | name: "dateMonth", 140 | title: "年月时间选择框", 141 | width: 150, 142 | editType: "dateMonth", 143 | list: [] 144 | }, 145 | { 146 | name: "dateMonthRange", 147 | title: "年月时间选择框", 148 | width: 300, 149 | editType: "dateMonthRange", 150 | list: [] 151 | }, 152 | { 153 | name: "dateYear", 154 | title: "年度选择框", 155 | width: 150, 156 | editType: "dateYear", 157 | list: [] 158 | }, 159 | { 160 | name: "inputNumber", 161 | title: "数字输入框", 162 | width: 150, 163 | editType: "inputNumber", 164 | list: [] 165 | }, 166 | { 167 | name: "inputNumber1", 168 | title: "数字输入框", 169 | width: 150, 170 | editType: "inputNumber", 171 | list: [] 172 | }, 173 | 174 | { 175 | name: "text", 176 | title: "显示文本值", 177 | width: 100, 178 | editType: "none", 179 | list: [] 180 | } 181 | ], 182 | data: [ 183 | { 184 | fixedCol: "第一列", 185 | selectPerson: "", 186 | selectPerson1: { 187 | id: "", 188 | name: "" 189 | }, 190 | treeSelect: "", 191 | input: "", 192 | select: [], 193 | newPost: "", 194 | time: "", 195 | timeRange: [], 196 | dateMonth: "", 197 | dateMonthRange: [], 198 | dateYear: "", 199 | inputNumber: "", 200 | inputNumber1: "", 201 | text: "测试测试" 202 | } 203 | ] 204 | }; 205 | -------------------------------------------------------------------------------- /component/EditTable/tableJson.js: -------------------------------------------------------------------------------- 1 | export default { 2 | editTable: { 3 | ref: "tableEdit", 4 | fixCols: 1, 5 | tableHeaderHeight: 40, 6 | tableTdHeight: 32, 7 | rules: { 8 | oldPost: [ 9 | { required: true, message: "请输入活动名称ceshi", trigger: "change" }, 10 | { min: 1, max: 3, message: "长度在 1 到 3 个字符", trigger: "change" } 11 | ], 12 | newPost: [ 13 | { required: true, message: "请输入活动名称", trigger: "change" }, 14 | { min: 1, max: 5, message: "长度在 1 到 5 个字符", trigger: "change" } 15 | ], 16 | time: [ 17 | { 18 | type: "date", 19 | required: true, 20 | message: "请选择日期", 21 | trigger: "change" 22 | } 23 | ], 24 | newDepartment: [{ required: true, message: "请选择部门", trigger: "change" }] 25 | } 26 | }, 27 | 28 | //表头数据 29 | headers: [ 30 | { 31 | name: "name", 32 | title: "姓名", 33 | width: 100, 34 | editType: "none", 35 | list: [] 36 | }, 37 | { 38 | name: "oldDepartment", 39 | title: "原部门", 40 | width: 100, 41 | editType: "none", 42 | list: [] 43 | }, 44 | { 45 | name: "oldPost", 46 | title: "原岗位", 47 | width: 100, 48 | editType: "input", 49 | list: [] 50 | }, 51 | { 52 | name: "newDepartment", 53 | title: "新部门", 54 | width: 100, 55 | editType: "select", 56 | list: [ 57 | { 58 | label: "测试1", 59 | value: "1" 60 | }, 61 | { 62 | label: "测试2", 63 | value: "2" 64 | }, 65 | { 66 | label: "测试3", 67 | value: "3" 68 | }, 69 | { 70 | label: "测试4", 71 | value: "4" 72 | } 73 | ] 74 | }, 75 | { 76 | name: "newPost", 77 | title: "新岗位", 78 | width: 100, 79 | editType: "input", 80 | list: [] 81 | }, 82 | { 83 | name: "time", 84 | title: "时间", 85 | width: 150, 86 | editType: "date", 87 | list: [] 88 | }, 89 | { 90 | name: "test", 91 | title: "测试", 92 | width: 100, 93 | editType: "none", 94 | list: [] 95 | } 96 | ], 97 | data: [ 98 | { 99 | key: "0", 100 | name: "李四", 101 | oldDepartment: "产品部", 102 | oldPost: "", 103 | newDepartment: "2", 104 | newPost: "测试岗位", 105 | time: "2018-10-26", 106 | test: "测试测试" 107 | }, 108 | { 109 | key: "0", 110 | name: "张三", 111 | oldDepartment: "研发部", 112 | oldPost: "", 113 | newDepartment: "1", 114 | newPost: "UI", 115 | time: "2018-10-22", 116 | test: "测试" 117 | }, 118 | { 119 | key: "0", 120 | name: "张三", 121 | oldDepartment: "研发部", 122 | oldPost: "", 123 | newDepartment: "1", 124 | newPost: "UI", 125 | time: "", 126 | test: "测试" 127 | }, 128 | { 129 | key: "0", 130 | name: "张三", 131 | oldDepartment: "研发部", 132 | oldPost: "", 133 | newDepartment: "1", 134 | newPost: "UI", 135 | time: "", 136 | test: "测试" 137 | }, 138 | { 139 | key: "0", 140 | name: "张三", 141 | oldDepartment: "研发部", 142 | oldPost: "", 143 | newDepartment: "1", 144 | newPost: "UI", 145 | time: "2018-10-22", 146 | test: "测试" 147 | }, 148 | { 149 | key: "0", 150 | name: "张三", 151 | oldDepartment: "研发部", 152 | oldPost: "", 153 | newDepartment: "1", 154 | newPost: "UI", 155 | time: "2018-10-22", 156 | test: "测试" 157 | }, 158 | { 159 | key: "0", 160 | name: "张三", 161 | oldDepartment: "研发部", 162 | oldPost: "", 163 | newDepartment: "1", 164 | newPost: "UI", 165 | time: "2018-10-22", 166 | test: "测试" 167 | }, 168 | { 169 | key: "0", 170 | name: "张三", 171 | oldDepartment: "研发部", 172 | oldPost: "", 173 | newDepartment: "1", 174 | newPost: "UI", 175 | time: "2018-10-22", 176 | test: "测试" 177 | }, 178 | { 179 | key: "0", 180 | name: "张三", 181 | oldDepartment: "研发部", 182 | oldPost: "", 183 | newDepartment: "1", 184 | newPost: "UI", 185 | time: "2018-10-22", 186 | test: "测试" 187 | }, 188 | { 189 | key: "0", 190 | name: "张三", 191 | oldDepartment: "研发部", 192 | oldPost: "", 193 | newDepartment: "1", 194 | newPost: "UI", 195 | time: "2018-10-22", 196 | test: "测试" 197 | }, 198 | { 199 | key: "0", 200 | name: "张三", 201 | oldDepartment: "研发部", 202 | oldPost: "", 203 | newDepartment: "1", 204 | newPost: "UI", 205 | time: "2018-10-22", 206 | test: "测试" 207 | }, 208 | { 209 | key: "0", 210 | name: "张三", 211 | oldDepartment: "研发部", 212 | oldPost: "", 213 | newDepartment: "1", 214 | newPost: "UI", 215 | time: "2018-10-22", 216 | test: "测试" 217 | }, 218 | { 219 | key: "0", 220 | name: "张三", 221 | oldDepartment: "研发部", 222 | oldPost: "", 223 | newDepartment: "1", 224 | newPost: "UI", 225 | time: "2018-10-22", 226 | test: "测试" 227 | }, 228 | { 229 | key: "0", 230 | name: "张三", 231 | oldDepartment: "研发部", 232 | oldPost: "", 233 | newDepartment: "1", 234 | newPost: "UI", 235 | time: "2018-10-22", 236 | test: "测试" 237 | }, 238 | { 239 | key: "0", 240 | name: "张三", 241 | oldDepartment: "研发部", 242 | oldPost: "", 243 | newDepartment: "1", 244 | newPost: "UI", 245 | time: "2018-10-22", 246 | test: "测试" 247 | }, 248 | { 249 | key: "0", 250 | name: "张三", 251 | oldDepartment: "研发部", 252 | oldPost: "", 253 | newDepartment: "1", 254 | newPost: "UI", 255 | time: "2018-10-22", 256 | test: "测试" 257 | }, 258 | { 259 | key: "0", 260 | name: "张三", 261 | oldDepartment: "研发部", 262 | oldPost: "", 263 | newDepartment: "1", 264 | newPost: "UI", 265 | time: "2018-10-22", 266 | test: "测试" 267 | } 268 | ] 269 | }; 270 | -------------------------------------------------------------------------------- /view/EditTableTest.vue: -------------------------------------------------------------------------------- 1 | 93 | 94 | 169 | 170 | 195 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 启动 2 | 1、使用此组件 3 | `npm install can-edit-table` 4 | 2、启动项目 5 | `npm install` 6 | `vue serve` 7 | ## 项目概览 8 | ![图片名称](https://github.com/zhjing1019/CanEditGrid/blob/master/img/editGif.gif) 9 | 基于vue和element的可拖拽赋值的可编辑表格,支持表格实时校验,联动校验。 10 | ![图片名称](https://github.com/zhjing1019/CanEditGrid/blob/master/img/canEditGrid%402x.png) 11 | 支持input、datepicker、select、selctTree等等。可以自定义td的内容,支持slot插槽。 12 | 13 | ![图片名称](https://github.com/zhjing1019/CanEditGrid/blob/master/img/canEdit2.png) 14 | 15 | ![图片名称](https://github.com/zhjing1019/CanEditGrid/blob/master/img/canedit3.png) 16 | 支持拖拽赋值,类似于excel的拖拽赋值功能 17 | 18 | ![图片名称](https://github.com/zhjing1019/CanEditGrid/blob/master/img/canEdit4.png) 19 | 支持表格的实时校验 20 | ## 组件的使用 21 | ##### 组件下载 22 | `npm install can-edit-table` 23 | ##### 引用组件 24 | `import CanEditTable from "can-edit-table"` 25 | ##### 注册组件 26 | `components: {editTable},` 27 | ##### 组件demo 28 | https://github.com/zhjing1019/canEditDemo.git 29 | ##### 组件源码 30 | https://github.com/zhjing1019/CanEditGrid 31 | 32 | ### 1、组件 33 | ``` 34 | 48 | 49 | ``` 50 | ### 2、表头的数据 51 | ``` 52 | [ 53 | { 54 | name: "zzry", 55 | title: "测试1", 56 | width: 350, 57 | slot: true 58 | }, 59 | { 60 | name: "zzsj", 61 | width: 200, 62 | title: "测试时间", 63 | editType: "date" 64 | }, 65 | { 66 | name: "sfz", 67 | width: 200, 68 | title: "身份证(slot内容、自定义校验规则)", 69 | slot: true 70 | }, 71 | { 72 | name: "zzlb", 73 | width: 200, 74 | title: "测试类别", 75 | editType: "select", 76 | label: "code", 77 | value: "id", 78 | list: [ 79 | { 80 | code: "测试code1", 81 | id: "1" 82 | }, 83 | { 84 | code: "测试code2", 85 | id: "2" 86 | }, 87 | { 88 | code: "测试code3", 89 | id: "3" 90 | }, 91 | { 92 | code: "测试code4", 93 | id: "4" 94 | } 95 | ] 96 | }, 97 | { 98 | name: "khqk", 99 | width: 200, 100 | title: "测试(只展示数据)", 101 | editType: "none" 102 | }, 103 | { 104 | name: "zzsm", 105 | title: "测试三", 106 | width: 200, 107 | editType: "input" 108 | } 109 | ] 110 | ``` 111 | ### 4、data数据 112 | ``` 113 | data: [ 114 | { 115 | zzry: { 116 | name: "测试", 117 | sex: "男", 118 | bus: "测试部门", 119 | pos: "测试", 120 | emp: "测试", 121 | auth: "测试", 122 | num: "测试" 123 | }, 124 | zzsj: "", 125 | zzlb: "", 126 | khqk: "测试", 127 | zzsm: "测试", 128 | sfz: "" 129 | }, 130 | { 131 | zzry: { 132 | name: "测试", 133 | sex: "测试", 134 | bus: "测试", 135 | pos: "测试", 136 | emp: "测试", 137 | auth: "测试", 138 | num: "测试" 139 | }, 140 | zzsj: "", 141 | zzlb: "", 142 | khqk: "测试", 143 | zzsm: "测试", 144 | sfz: "" 145 | } 146 | ] 147 | ``` 148 | ### 5、校验规则 149 | ``` 150 | editTable: { 151 | rules: { 152 | input: [ 153 | { required: true, message: "请输入活动名称ceshi", trigger: "change" }, 154 | { min: 1, max: 3, message: "长度在 1 到 3 个字符", trigger: "change" } 155 | ], 156 | newPost: [ 157 | { required: true, message: "请输入活动名称", trigger: "change" }, 158 | { min: 1, max: 5, message: "长度在 1 到 5 个字符", trigger: "change" } 159 | ], 160 | time: { 161 | type: "date", 162 | required: true, 163 | message: "请选择日期", 164 | trigger: "change" 165 | }, 166 | newDepartment: [{ required: true, message: "请选择部门", trigger: "change" }], 167 | treeSelect: [{ required: true, message: "请选择部门", trigger: "change" }], 168 | timeRange: [{ type: "date", required: true, message: "请选择时间", trigger: "change" }], 169 | dateMonth: [{ type: "date", required: true, message: "请选择时间", trigger: "change" }], 170 | dateYear: [{ type: "date", required: true, message: "请选择时间", trigger: "change" }], 171 | dateMonthRange: [{ type: "date", required: true, message: "请选择时间", trigger: "change" }], 172 | inputNumber: [{ type: "number", required: true, message: "请输入数字输入框", trigger: "change" }], 173 | inputNumber1: [{ type: "number", required: true, message: "请输入数字输入框", trigger: "change" }], 174 | selectPerson1: [{ type: "string", required: true, message: "请选择人", trigger: "change" }], 175 | select: [{ type: "string", required: true, message: "请选择code", trigger: "change" }] 176 | } 177 | } 178 | ``` 179 | ### 6、表头配置 180 | 1、width, 表示此列的宽度 181 | 2、name,表示此列的id 182 | 3、title, 表示此列的字段名 183 | 4、slot, 表示此列是否自定义 184 | 5、editType, 表示此列的编辑类型( 185 | 1、editType = "treeSelect" 选择机构树 186 | ``` 187 | { 188 | name: "treeSelect", 189 | title: "选择树机构", 190 | width: 200, 191 | // slot: true, 192 | editType: "treeSelect", 193 | disabled: false, 194 | treeParams: { 195 | clickParent: true, 196 | filterable: false, 197 | "check-strictly": true, 198 | "default-expand-all": false, 199 | "expand-on-click-node": false, 200 | data: [ 201 | { 202 | id: "1", 203 | name: "哎哎哎", 204 | children: [{ id: "3", name: "啊啊啊啊" }] 205 | }, 206 | { 207 | id: "2", 208 | name: "发生的" 209 | } 210 | ], 211 | props: { 212 | children: "children", 213 | label: "name", 214 | value: "id" 215 | } 216 | }, 217 | selectParams: { 218 | multiple: false, 219 | clearable: true, 220 | placeholder: "请输入内容" 221 | }, 222 | list: [] 223 | }, 224 | ``` 225 | 2、editType: "input", input输入框 226 | 3、editType: "select", select选择框 227 | ``` 228 | { 229 | name: "select", 230 | title: "select选择框", 231 | width: 100, 232 | multiple: true, 233 | editType: "select", 234 | label: "code", 235 | value: "id", 236 | list: [ 237 | { 238 | code: "测试code1", 239 | id: "1" 240 | }, 241 | { 242 | code: "测试code2", 243 | id: "2" 244 | }, 245 | { 246 | code: "测试code3", 247 | id: "3" 248 | }, 249 | { 250 | code: "测试code4", 251 | id: "4" 252 | } 253 | ] 254 | }, 255 | ``` 256 | 4、editType: "date",年月日时间选择框 257 | 5、editType: "dateRange",年月日时间范围 258 | 6、editType: "none",显示文本值 259 | ) 260 | ### 7、自定义表格 261 | ``` 262 | 284 | 291 | 296 | 297 | ``` 298 | 1、slot与表头的name字段对应 299 | 2、slot-scope="field" 300 | field.field.rowData 从底层传出的rowData,当前行的数据 301 | field.field.field 从底层传出的field,当前行的数据的表头字段 302 | field.field.colIndex 从底层传出的colIndex,当前行的数据的列数 303 | field.field.rowIndex 从底层传出的rowIndex,当前行的数据的行数 304 | ### 8、表格触发的事件 305 | change:数据发生改变时触发 306 | data-change:可编辑表格中td发生变化时触发的事件(slot的td除外) 307 | editDragEnd:拖拽赋值结束后触发的事件(currentColIndex, selectArr, name, value,返回四个数据,) 308 | 309 | this.$refs[ref].submitForm():提交表单 310 | 311 | this.$refs[ref].clearAll():清空表格 312 | 313 | this.$refs[ref].resetAll():重置表格 314 | 315 | 如果有任何问题可以关注我的个人技术公众号javascript艺术,或者添加我微信反馈 316 | ![image](https://user-images.githubusercontent.com/29360917/115189574-3cb9dc80-a119-11eb-8e88-d98aed4a3476.png) 317 | ![image](https://user-images.githubusercontent.com/29360917/115189133-9372e680-a118-11eb-9570-eae1b8662869.png) 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | -------------------------------------------------------------------------------- /component/EditTable/DragSpan.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 319 | 320 | 356 | -------------------------------------------------------------------------------- /component/EditTable/EditSub.vue: -------------------------------------------------------------------------------- 1 | 554 | 571 | -------------------------------------------------------------------------------- /component/EditTable/CanEditTable.vue: -------------------------------------------------------------------------------- 1 | 69 | 611 | 828 | --------------------------------------------------------------------------------