Commit 004eaf476b3e0714f377588fc27957ebae30727a
1 parent
86a49e4b
Exists in
master
and in
1 other branch
新式表格分离可编辑组件
Showing
4 changed files
with
342 additions
and
183 deletions
Show diff stats
examples/views/page/other.vue
examples/views/page/table-new/cell-editable.vue
| ... | ... | @@ -63,6 +63,7 @@ export default { |
| 63 | 63 | if (val) { |
| 64 | 64 | this.confirm = false; |
| 65 | 65 | this.oldValue = get(this.row, this.item.agentKey || this.item.fullKey); |
| 66 | + this.value = get(this.row, this.item.agentKey || this.item.fullKey); | |
| 66 | 67 | } else { |
| 67 | 68 | if (!this.confirm) { |
| 68 | 69 | this.$emit('cancel', this.emitData); |
| ... | ... | @@ -78,7 +79,7 @@ export default { |
| 78 | 79 | }, |
| 79 | 80 | methods: { |
| 80 | 81 | $_get: get, |
| 81 | - // 组件出发input事件 | |
| 82 | + // 组件触发input事件 | |
| 82 | 83 | onInput(value) { |
| 83 | 84 | this.value = value; |
| 84 | 85 | this.$emit('update', this.emitData) | ... | ... |
| ... | ... | @@ -0,0 +1,293 @@ |
| 1 | +<style> | |
| 2 | +.eagle-table { | |
| 3 | + width: 100%; | |
| 4 | +} | |
| 5 | +</style> | |
| 6 | + | |
| 7 | +<template> | |
| 8 | + <div @keyup.enter="tableEditCell = {}"> | |
| 9 | + <div style="padding-bottom: 10px;"> | |
| 10 | + <el-button @click="handleNew" size="mini" v-if="!rowEdit">新增</el-button> | |
| 11 | + <el-button @click="handleEdit" size="mini" v-if="!rowEditable && tableSelection.length > 0">编辑</el-button> | |
| 12 | + <el-button @click="handleSave" size="mini" type="primary" v-if="rowEditable">完成</el-button> | |
| 13 | + <el-button @click="handleCancel" size="mini" type="plain" v-if="rowNew && !rowEdit">取消</el-button> | |
| 14 | + <el-button @click="handleDelete" size="mini" type="danger" v-if="tableSelection.length > 0">删除</el-button> | |
| 15 | + </div> | |
| 16 | + <el-table class="eagle-table" ref="table" :data="tableData" v-bind="{ size: 'small', ...tableProps }" | |
| 17 | + v-on="tableEvents" @cell-dblclick="onCellDblclick" @selection-change="onSelectionChange" | |
| 18 | + > | |
| 19 | + <el-table-column type="selection" :selectable="r => rowNew ? r.$new : true"></el-table-column> | |
| 20 | + <!-- 默认表格插槽 --> | |
| 21 | + <slot name="default"></slot> | |
| 22 | + <!-- 根据配置列表生成表格列 --> | |
| 23 | + <template v-if="tableList && tableList.length > 0"> | |
| 24 | + <template v-for="(item, index) in tableList"> | |
| 25 | + <template v-if="bindItemVisible(item.visible)"> | |
| 26 | + <!-- 如果有表格列具名插槽 --> | |
| 27 | + <slot v-if="$scopedSlots[item.keyPath.join('-')]" :name="item.keyPath.join('-')" v-bind="item"></slot> | |
| 28 | + <!-- 默认表格列渲染 --> | |
| 29 | + <el-table-column v-else v-bind="item" :prop="item.fullKey || item.key" :key="index" :min-width="minWidth || item.minWidth || item['min-width'] || (editable ? 140 : undefined)"> | |
| 30 | + <template #default="{ row, column, $index }"> | |
| 31 | + <cell-editable | |
| 32 | + :editable="row.$editable || (editable && (tableEditCell.index === row.$index && tableEditCell.key === (item.agentKey || item.fullKey || item.key)))" | |
| 33 | + :row="row" :item="item" @update="onCellUpdate" @done="onCellUpdateDone" @cancel="onCellUpdateCancel" :btn-visible="!row.$editable" | |
| 34 | + > | |
| 35 | + <!-- 如果有表格列值渲染具名插槽 --> | |
| 36 | + <slot v-if="$scopedSlots[`value-${item.keyPath.join('-')}`]" :name="`value-${item.keyPath.join('-')}`" v-bind="item" | |
| 37 | + :row="row" :value="$_get(row, item.fullKey)" :column="column" :index="$index" | |
| 38 | + ></slot> | |
| 39 | + <!-- 如果表格列配置了值渲染参数 --> | |
| 40 | + <component v-else-if="item.render" :is="item.render.type" v-bind="item.render.props" :style="item.render.style"> | |
| 41 | + <template v-if="item.render.children">{{ bindItemRenderChildren(item, { row, column, $index }) }}</template> | |
| 42 | + <template v-else>{{ $_get(row, item.fullKey) }}</template> | |
| 43 | + </component> | |
| 44 | + </cell-editable> | |
| 45 | + </template> | |
| 46 | + </el-table-column> | |
| 47 | + </template> | |
| 48 | + </template> | |
| 49 | + </template> | |
| 50 | + <!-- 已生成列表后的追加列插槽 --> | |
| 51 | + <slot name="column-append"></slot> | |
| 52 | + <!-- 末尾列插槽 --> | |
| 53 | + <slot name="column-end"></slot> | |
| 54 | + </el-table> | |
| 55 | + </div> | |
| 56 | +</template> | |
| 57 | + | |
| 58 | +<script> | |
| 59 | +import { cloneDeep, get, set } from '../form-new/util'; | |
| 60 | +import CellEditable from './cell-editable'; | |
| 61 | + | |
| 62 | +const listHasKey = (list, name) => { | |
| 63 | + let result = false; | |
| 64 | + for (const row of list) { | |
| 65 | + if (row[name]) { | |
| 66 | + result = true; | |
| 67 | + break; | |
| 68 | + } | |
| 69 | + } | |
| 70 | + return result; | |
| 71 | +} | |
| 72 | + | |
| 73 | +export default { | |
| 74 | + name: 'TableNew', | |
| 75 | + components: { CellEditable }, | |
| 76 | + props: { | |
| 77 | + // 用于实例化本组件绑定v-model的值 | |
| 78 | + value: Array, | |
| 79 | + // 配置列表 | |
| 80 | + list: { | |
| 81 | + type: Array, | |
| 82 | + required: true | |
| 83 | + }, | |
| 84 | + // 表格参数 | |
| 85 | + tableProps: { | |
| 86 | + type: Object, | |
| 87 | + default() { return {} } | |
| 88 | + }, | |
| 89 | + // 表格事件 | |
| 90 | + tableEvents: Object, | |
| 91 | + // 是否可编辑 | |
| 92 | + editable: Boolean, | |
| 93 | + // 列宽 | |
| 94 | + minWidth: Number, | |
| 95 | + }, | |
| 96 | + data() { | |
| 97 | + return { | |
| 98 | + tableList: [], // 表格配置列表 | |
| 99 | + tableData: [], // 表格数据 | |
| 100 | + tableRowTemplate: { $editable: true }, // 行数据模板 | |
| 101 | + tableEditCell: {}, // 正在编辑的单元格 | |
| 102 | + tableSelection: [], // 表格已选中 | |
| 103 | + }; | |
| 104 | + }, | |
| 105 | + computed: { | |
| 106 | + // 表格实体 | |
| 107 | + instance: { | |
| 108 | + get() { return this.$refs.table; } | |
| 109 | + }, | |
| 110 | + // 行编辑状态 | |
| 111 | + rowEditable() { | |
| 112 | + return listHasKey(this.tableData, '$editable'); | |
| 113 | + }, | |
| 114 | + // 存在新行 | |
| 115 | + rowNew() { | |
| 116 | + return listHasKey(this.tableData, '$new'); | |
| 117 | + }, | |
| 118 | + // 存在编辑行 | |
| 119 | + rowEdit() { | |
| 120 | + return listHasKey(this.tableData, '$edit'); | |
| 121 | + } | |
| 122 | + }, | |
| 123 | + watch: { | |
| 124 | + value: { | |
| 125 | + handler(val = []) { | |
| 126 | + this.tableData = val.map((o, i) => { | |
| 127 | + return { ...o, $index: i, $editable: undefined, $new: undefined }; | |
| 128 | + }); | |
| 129 | + }, | |
| 130 | + immediate: true | |
| 131 | + }, | |
| 132 | + list: { | |
| 133 | + handler(val) { | |
| 134 | + // 深度克隆传入的列表,避免原始值被修改 | |
| 135 | + const newList = cloneDeep(this.list); | |
| 136 | + // 生成列表值的全路径key,即列表项为对象时,对象内的key与上一级的key合并作为全路径key | |
| 137 | + const generateFullKey = (list, parentKey) => { | |
| 138 | + list.forEach(item => { | |
| 139 | + if (item.group && item.list) { | |
| 140 | + if (item.group.key) { | |
| 141 | + item.fullKey = `${parentKey ? `${parentKey}.${item.group.key}` : item.group.key}`; | |
| 142 | + } else { | |
| 143 | + item.fullKey = parentKey || item.key; | |
| 144 | + } | |
| 145 | + generateFullKey(item.list, item.fullKey); | |
| 146 | + } else { | |
| 147 | + item.fullKey = `${parentKey ? `${parentKey}.${item.key}` : item.key}`; | |
| 148 | + } | |
| 149 | + }); | |
| 150 | + }; | |
| 151 | + // 生成fullKey | |
| 152 | + generateFullKey(newList); | |
| 153 | + // 创建输出列表 | |
| 154 | + const result = []; | |
| 155 | + const tableRowTemplate = {}; | |
| 156 | + // 生成列表值的全路径key,即列表项为对象时,对象内的key与上一级的key合并作为全路径key | |
| 157 | + const generateFlatList = (list) => { | |
| 158 | + list.forEach(item => { | |
| 159 | + if (item.group && item.list) { | |
| 160 | + generateFlatList(item.list); | |
| 161 | + } else if (!item.group && !item.list) { | |
| 162 | + result.push({ ...item, keyPath: item.fullKey.split('.') }); | |
| 163 | + set(tableRowTemplate, item.fullKey, undefined); | |
| 164 | + tableRowTemplate.$editable = true; | |
| 165 | + } | |
| 166 | + }); | |
| 167 | + }; | |
| 168 | + generateFlatList(newList); | |
| 169 | + this.tableList = result; | |
| 170 | + this.tableRowTemplate = tableRowTemplate; | |
| 171 | + }, | |
| 172 | + immediate: true | |
| 173 | + } | |
| 174 | + }, | |
| 175 | + methods: { | |
| 176 | + $_get: get, | |
| 177 | + // 处理新增逻辑 | |
| 178 | + handleNew() { | |
| 179 | + const tableData = cloneDeep(this.tableData); | |
| 180 | + tableData.push({ ...this.tableRowTemplate, $new: true }); | |
| 181 | + this.tableEditCell = {}; | |
| 182 | + this.tableData = tableData.map((o, i) => ({ ...o, $index: i })); | |
| 183 | + }, | |
| 184 | + // 处理编辑逻辑 | |
| 185 | + handleEdit() { | |
| 186 | + const tableData = cloneDeep(this.tableData); | |
| 187 | + const selectionIndexArr = this.tableSelection.map(i => i.$index); | |
| 188 | + tableData.forEach((r, i) => { | |
| 189 | + if (selectionIndexArr.includes(r.$index)) { | |
| 190 | + tableData[i].$editable = true; | |
| 191 | + tableData[i].$edit = true; | |
| 192 | + tableData[i].$new = true; | |
| 193 | + } | |
| 194 | + }); | |
| 195 | + this.tableEditCell = {}; | |
| 196 | + this.tableData = tableData.map((o, i) => ({ ...o, $index: i })); | |
| 197 | + }, | |
| 198 | + // 处理保存逻辑 | |
| 199 | + handleSave() { | |
| 200 | + const tableData = cloneDeep(this.tableData); | |
| 201 | + tableData.forEach((r, i) => { | |
| 202 | + delete tableData[i].$editable; | |
| 203 | + }); | |
| 204 | + this.tableEditCell = {}; | |
| 205 | + this.tableData = tableData.map((o, i) => ({ ...o, $index: i })); | |
| 206 | + this.$nextTick(() => { | |
| 207 | + this.emitTableData(this.tableData); | |
| 208 | + this.$emit(this.rowEdit ? 'row-edit' : 'row-new', this.tableData.filter(d => d.$new).map(d => { | |
| 209 | + delete d.$new; | |
| 210 | + return d; | |
| 211 | + })); | |
| 212 | + }); | |
| 213 | + }, | |
| 214 | + // 处理取消逻辑 | |
| 215 | + handleCancel() { | |
| 216 | + let tableData = cloneDeep(this.tableData); | |
| 217 | + tableData = tableData.filter(row => !row.$new); | |
| 218 | + this.emitTableData(tableData); | |
| 219 | + }, | |
| 220 | + // 处理删除逻辑 | |
| 221 | + handleDelete() { | |
| 222 | + const tableData = cloneDeep(this.tableData); | |
| 223 | + const selectionIndexArr = this.tableSelection.map(i => i.$index); | |
| 224 | + if (!this.rowNew && !this.rowEdit) { | |
| 225 | + this.$emit('row-delete', this.tableSelection); | |
| 226 | + } | |
| 227 | + this.tableEditCell = {}; | |
| 228 | + this.tableData = tableData.filter((d, i) => !selectionIndexArr.includes(i)).map((o, i) => ({ ...o, $index: i })); | |
| 229 | + }, | |
| 230 | + // 更新表格数据 | |
| 231 | + emitTableData(tableData) { | |
| 232 | + if (this.$listeners['input']) { | |
| 233 | + this.$emit('input', tableData.map((o, i) => { | |
| 234 | + return { ...o, $index: i, $editable: undefined, $new: undefined, $edit: undefined }; | |
| 235 | + })); | |
| 236 | + } else { | |
| 237 | + this.tableData = tableData; | |
| 238 | + } | |
| 239 | + }, | |
| 240 | + // 绑定表格列显示隐藏状态 | |
| 241 | + bindItemVisible(visible = true) { | |
| 242 | + let result = visible; | |
| 243 | + if (typeof visible === 'function') { | |
| 244 | + result = visible(this.tableData); | |
| 245 | + } | |
| 246 | + return result; | |
| 247 | + }, | |
| 248 | + // 处理表格项渲染时的子值 | |
| 249 | + bindItemRenderChildren(item, scope) { | |
| 250 | + return item.render.children instanceof Function ? item.render.children(scope) : this.$_get(scope.row, item.fullKey) | |
| 251 | + }, | |
| 252 | + // 双击单元格 | |
| 253 | + onCellDblclick(row, column, cell, event) { | |
| 254 | + if (this.editable && !this.rowNew) { | |
| 255 | + this.tableEditCell = { index: row.$index, key: column.property }; | |
| 256 | + } | |
| 257 | + }, | |
| 258 | + // 编辑表格更新值 | |
| 259 | + onCellUpdate({ oldValue, value, row, key, fullKey }) { | |
| 260 | + this.setCellValue({ value, row, key, fullKey }); | |
| 261 | + }, | |
| 262 | + // 编辑表格确认 | |
| 263 | + onCellUpdateDone({ oldValue, value, row, key, fullKey }) { | |
| 264 | + this.tableEditCell = {}; | |
| 265 | + if (this.$listeners['cell-edit']) { | |
| 266 | + const { tableData } = this.setCellValue({ value, row, key, fullKey }); | |
| 267 | + this.emitTableData(tableData); | |
| 268 | + this.$emit('cell-edit', { row, key, fullKey, value }); | |
| 269 | + } | |
| 270 | + }, | |
| 271 | + // 表格取消编辑 | |
| 272 | + onCellUpdateCancel({ oldValue, value, row, key, fullKey }) { | |
| 273 | + if (row.$new !== true) { | |
| 274 | + this.setCellValue({ value: oldValue, row, key, fullKey }); | |
| 275 | + } | |
| 276 | + }, | |
| 277 | + // 设置表格值 | |
| 278 | + setCellValue({ value, row, key, fullKey }) { | |
| 279 | + const tableData = cloneDeep(this.tableData); | |
| 280 | + const tableRow = tableData[row.$index]; | |
| 281 | + set(tableRow, fullKey, value); | |
| 282 | + tableData[row.$index] = tableRow; | |
| 283 | + this.$set(this.tableData, row.$index, tableRow); | |
| 284 | + return { tableData, tableRow }; | |
| 285 | + }, | |
| 286 | + // 表格选中 | |
| 287 | + onSelectionChange(selection) { | |
| 288 | + this.tableSelection = selection; | |
| 289 | + this.$emit('selection', selection); | |
| 290 | + } | |
| 291 | + } | |
| 292 | +}; | |
| 293 | +</script> | |
| 0 | 294 | \ No newline at end of file | ... | ... |
examples/views/page/table-new/index.vue
| ... | ... | @@ -5,74 +5,60 @@ |
| 5 | 5 | </style> |
| 6 | 6 | |
| 7 | 7 | <template> |
| 8 | - <div @keyup.enter="tableEditCell = {}"> | |
| 9 | - <div style="padding-bottom: 10px;"> | |
| 10 | - <el-button @click="handleNew" size="mini" v-if="!rowEdit">新增</el-button> | |
| 11 | - <el-button @click="handleEdit" size="mini" v-if="!rowEditable && tableSelection.length > 0">编辑</el-button> | |
| 12 | - <el-button @click="handleSave" size="mini" type="primary" v-if="rowEditable">完成</el-button> | |
| 13 | - <el-button @click="handleCancel" size="mini" type="plain" v-if="rowNew && !rowEdit">取消</el-button> | |
| 14 | - <el-button @click="handleDelete" size="mini" type="danger" v-if="tableSelection.length > 0">删除</el-button> | |
| 15 | - </div> | |
| 16 | - <el-table class="eagle-table" ref="table" :data="tableData" v-bind="{ size: 'small', ...tableProps }" | |
| 17 | - v-on="tableEvents" @cell-dblclick="onCellDblclick" @selection-change="onSelectionChange" | |
| 18 | - > | |
| 19 | - <el-table-column type="selection" :selectable="r => rowNew ? r.$new : true"></el-table-column> | |
| 20 | - <!-- 默认表格插槽 --> | |
| 21 | - <slot name="default"></slot> | |
| 22 | - <!-- 根据配置列表生成表格列 --> | |
| 23 | - <template v-if="tableList && tableList.length > 0"> | |
| 24 | - <template v-for="(item, index) in tableList"> | |
| 25 | - <template v-if="bindItemVisible(item.visible)"> | |
| 26 | - <!-- 如果有表格列具名插槽 --> | |
| 27 | - <slot v-if="$scopedSlots[item.keyPath.join('-')]" :name="item.keyPath.join('-')" v-bind="item"></slot> | |
| 28 | - <!-- 默认表格列渲染 --> | |
| 29 | - <el-table-column v-else v-bind="item" :prop="item.fullKey || item.key" :key="index" :min-width="minWidth || item.minWidth || item['min-width'] || (editable ? 140 : undefined)"> | |
| 30 | - <template #default="{ row, column, $index }"> | |
| 31 | - <cell-editable | |
| 32 | - :editable="row.$editable || (editable && (tableEditCell.index === row.$index && tableEditCell.key === (item.agentKey || item.fullKey || item.key)))" | |
| 33 | - :row="row" :item="item" @update="onCellUpdate" @done="onCellUpdateDone" @cancel="onCellUpdateCancel" :btn-visible="!row.$editable" | |
| 34 | - > | |
| 35 | - <!-- 如果有表格列值渲染具名插槽 --> | |
| 36 | - <slot v-if="$scopedSlots[`value-${item.keyPath.join('-')}`]" :name="`value-${item.keyPath.join('-')}`" v-bind="item" | |
| 37 | - :row="row" :value="$_get(row, item.fullKey)" :column="column" :index="$index" | |
| 38 | - ></slot> | |
| 39 | - <!-- 如果表格列配置了值渲染参数 --> | |
| 40 | - <component v-else-if="item.render" :is="item.render.type" v-bind="item.render.props" :style="item.render.style"> | |
| 41 | - <template v-if="item.render.children">{{ bindItemRenderChildren(item, { row, column, $index }) }}</template> | |
| 42 | - <template v-else>{{ $_get(row, item.fullKey) }}</template> | |
| 43 | - </component> | |
| 44 | - </cell-editable> | |
| 45 | - </template> | |
| 46 | - </el-table-column> | |
| 47 | - </template> | |
| 8 | + <el-table class="eagle-table" ref="table" :data="tableData" v-bind="{ size: 'small', ...tableProps }" | |
| 9 | + v-on="tableEvents" @selection-change="onSelectionChange" | |
| 10 | + > | |
| 11 | + <!-- 默认表格插槽 --> | |
| 12 | + <slot name="default"></slot> | |
| 13 | + <!-- 根据配置列表生成表格列 --> | |
| 14 | + <template v-if="tableList && tableList.length > 0"> | |
| 15 | + <template v-for="(item, index) in tableList"> | |
| 16 | + <template v-if="bindItemVisible(item.visible)"> | |
| 17 | + <!-- 如果有表格列具名插槽 --> | |
| 18 | + <slot v-if="$scopedSlots[item.keyPath.join('-')]" :name="item.keyPath.join('-')" v-bind="item"></slot> | |
| 19 | + <!-- 默认表格列渲染 --> | |
| 20 | + <el-table-column v-else v-bind="item" :prop="item.fullKey || item.key" :key="index" :min-width="minWidth || item.minWidth || item['min-width']"> | |
| 21 | + <template #default="{ row, column, $index }"> | |
| 22 | + <cell-render :row="row" :item="item"> | |
| 23 | + <!-- 如果有表格列值渲染具名插槽 --> | |
| 24 | + <slot v-if="$scopedSlots[`value-${item.keyPath.join('-')}`]" :name="`value-${item.keyPath.join('-')}`" v-bind="item" | |
| 25 | + :row="row" :value="$_get(row, item.fullKey)" :column="column" :index="$index" | |
| 26 | + ></slot> | |
| 27 | + <!-- 如果表格列配置了值渲染参数 --> | |
| 28 | + <component v-else-if="item.render" :is="item.render.type" v-bind="item.render.props" :style="item.render.style"> | |
| 29 | + <template v-if="item.render.children">{{ bindItemRenderChildren(item, { row, column, $index }) }}</template> | |
| 30 | + <template v-else>{{ $_get(row, item.fullKey) }}</template> | |
| 31 | + </component> | |
| 32 | + </cell-render> | |
| 33 | + </template> | |
| 34 | + </el-table-column> | |
| 48 | 35 | </template> |
| 49 | 36 | </template> |
| 50 | - <!-- 已生成列表后的追加列插槽 --> | |
| 51 | - <slot name="column-append"></slot> | |
| 52 | - <!-- 末尾列插槽 --> | |
| 53 | - <slot name="column-end"></slot> | |
| 54 | - </el-table> | |
| 55 | - </div> | |
| 37 | + </template> | |
| 38 | + <!-- 已生成列表后的追加列插槽 --> | |
| 39 | + <slot name="column-append"></slot> | |
| 40 | + <!-- 末尾列插槽 --> | |
| 41 | + <slot name="column-end"></slot> | |
| 42 | + </el-table> | |
| 56 | 43 | </template> |
| 57 | 44 | |
| 58 | 45 | <script> |
| 59 | 46 | import { cloneDeep, get, set } from '../form-new/util'; |
| 60 | -import CellEditable from './cell-editable'; | |
| 61 | - | |
| 62 | -const listHasKey = (list, name) => { | |
| 63 | - let result = false; | |
| 64 | - for (const row of list) { | |
| 65 | - if (row[name]) { | |
| 66 | - result = true; | |
| 67 | - break; | |
| 68 | - } | |
| 69 | - } | |
| 70 | - return result; | |
| 71 | -} | |
| 72 | 47 | |
| 73 | 48 | export default { |
| 74 | 49 | name: 'TableNew', |
| 75 | - components: { CellEditable }, | |
| 50 | + components: { | |
| 51 | + CellRender: { | |
| 52 | + props: { row: Object, item: Object }, | |
| 53 | + render(h) { | |
| 54 | + if (this.$scopedSlots.default) { | |
| 55 | + return h('span', this.$scopedSlots.default()); | |
| 56 | + } else { | |
| 57 | + return h('span', get(this.row, this.item.agentKey || this.item.fullKey)); | |
| 58 | + } | |
| 59 | + }, | |
| 60 | + } | |
| 61 | + }, | |
| 76 | 62 | props: { |
| 77 | 63 | // 用于实例化本组件绑定v-model的值 |
| 78 | 64 | value: Array, |
| ... | ... | @@ -88,8 +74,6 @@ export default { |
| 88 | 74 | }, |
| 89 | 75 | // 表格事件 |
| 90 | 76 | tableEvents: Object, |
| 91 | - // 是否可编辑 | |
| 92 | - editable: Boolean, | |
| 93 | 77 | // 列宽 |
| 94 | 78 | minWidth: Number, |
| 95 | 79 | }, |
| ... | ... | @@ -97,9 +81,6 @@ export default { |
| 97 | 81 | return { |
| 98 | 82 | tableList: [], // 表格配置列表 |
| 99 | 83 | tableData: [], // 表格数据 |
| 100 | - tableRowTemplate: { $editable: true }, // 行数据模板 | |
| 101 | - tableEditCell: {}, // 正在编辑的单元格 | |
| 102 | - tableSelection: [], // 表格已选中 | |
| 103 | 84 | }; |
| 104 | 85 | }, |
| 105 | 86 | computed: { |
| ... | ... | @@ -107,25 +88,11 @@ export default { |
| 107 | 88 | instance: { |
| 108 | 89 | get() { return this.$refs.table; } |
| 109 | 90 | }, |
| 110 | - // 行编辑状态 | |
| 111 | - rowEditable() { | |
| 112 | - return listHasKey(this.tableData, '$editable'); | |
| 113 | - }, | |
| 114 | - // 存在新行 | |
| 115 | - rowNew() { | |
| 116 | - return listHasKey(this.tableData, '$new'); | |
| 117 | - }, | |
| 118 | - // 存在编辑行 | |
| 119 | - rowEdit() { | |
| 120 | - return listHasKey(this.tableData, '$edit'); | |
| 121 | - } | |
| 122 | 91 | }, |
| 123 | 92 | watch: { |
| 124 | 93 | value: { |
| 125 | 94 | handler(val = []) { |
| 126 | - this.tableData = val.map((o, i) => { | |
| 127 | - return { ...o, $index: i, $editable: undefined, $new: undefined }; | |
| 128 | - }); | |
| 95 | + this.tableData = val; | |
| 129 | 96 | }, |
| 130 | 97 | immediate: true |
| 131 | 98 | }, |
| ... | ... | @@ -152,7 +119,6 @@ export default { |
| 152 | 119 | generateFullKey(newList); |
| 153 | 120 | // 创建输出列表 |
| 154 | 121 | const result = []; |
| 155 | - const tableRowTemplate = {}; | |
| 156 | 122 | // 生成列表值的全路径key,即列表项为对象时,对象内的key与上一级的key合并作为全路径key |
| 157 | 123 | const generateFlatList = (list) => { |
| 158 | 124 | list.forEach(item => { |
| ... | ... | @@ -160,83 +126,17 @@ export default { |
| 160 | 126 | generateFlatList(item.list); |
| 161 | 127 | } else if (!item.group && !item.list) { |
| 162 | 128 | result.push({ ...item, keyPath: item.fullKey.split('.') }); |
| 163 | - set(tableRowTemplate, item.fullKey, undefined); | |
| 164 | - tableRowTemplate.$editable = true; | |
| 165 | 129 | } |
| 166 | 130 | }); |
| 167 | 131 | }; |
| 168 | 132 | generateFlatList(newList); |
| 169 | 133 | this.tableList = result; |
| 170 | - this.tableRowTemplate = tableRowTemplate; | |
| 171 | 134 | }, |
| 172 | 135 | immediate: true |
| 173 | 136 | } |
| 174 | 137 | }, |
| 175 | 138 | methods: { |
| 176 | 139 | $_get: get, |
| 177 | - // 处理新增逻辑 | |
| 178 | - handleNew() { | |
| 179 | - const tableData = cloneDeep(this.tableData); | |
| 180 | - tableData.push({ ...this.tableRowTemplate, $new: true }); | |
| 181 | - this.tableEditCell = {}; | |
| 182 | - this.tableData = tableData.map((o, i) => ({ ...o, $index: i })); | |
| 183 | - }, | |
| 184 | - // 处理编辑逻辑 | |
| 185 | - handleEdit() { | |
| 186 | - const tableData = cloneDeep(this.tableData); | |
| 187 | - const selectionIndexArr = this.tableSelection.map(i => i.$index); | |
| 188 | - tableData.forEach((r, i) => { | |
| 189 | - if (selectionIndexArr.includes(r.$index)) { | |
| 190 | - tableData[i].$editable = true; | |
| 191 | - tableData[i].$edit = true; | |
| 192 | - tableData[i].$new = true; | |
| 193 | - } | |
| 194 | - }); | |
| 195 | - this.tableEditCell = {}; | |
| 196 | - this.tableData = tableData.map((o, i) => ({ ...o, $index: i })); | |
| 197 | - }, | |
| 198 | - // 处理保存逻辑 | |
| 199 | - handleSave() { | |
| 200 | - const tableData = cloneDeep(this.tableData); | |
| 201 | - tableData.forEach((r, i) => { | |
| 202 | - delete tableData[i].$editable; | |
| 203 | - }); | |
| 204 | - this.tableEditCell = {}; | |
| 205 | - this.tableData = tableData.map((o, i) => ({ ...o, $index: i })); | |
| 206 | - this.$nextTick(() => { | |
| 207 | - this.emitTableData(this.tableData); | |
| 208 | - this.$emit(this.rowEdit ? 'row-edit' : 'row-new', this.tableData.filter(d => d.$new).map(d => { | |
| 209 | - delete d.$new; | |
| 210 | - return d; | |
| 211 | - })); | |
| 212 | - }); | |
| 213 | - }, | |
| 214 | - // 处理取消逻辑 | |
| 215 | - handleCancel() { | |
| 216 | - let tableData = cloneDeep(this.tableData); | |
| 217 | - tableData = tableData.filter(row => !row.$new); | |
| 218 | - this.emitTableData(tableData); | |
| 219 | - }, | |
| 220 | - // 处理删除逻辑 | |
| 221 | - handleDelete() { | |
| 222 | - const tableData = cloneDeep(this.tableData); | |
| 223 | - const selectionIndexArr = this.tableSelection.map(i => i.$index); | |
| 224 | - if (!this.rowNew && !this.rowEdit) { | |
| 225 | - this.$emit('row-delete', this.tableSelection); | |
| 226 | - } | |
| 227 | - this.tableEditCell = {}; | |
| 228 | - this.tableData = tableData.filter((d, i) => !selectionIndexArr.includes(i)).map((o, i) => ({ ...o, $index: i })); | |
| 229 | - }, | |
| 230 | - // 更新表格数据 | |
| 231 | - emitTableData(tableData) { | |
| 232 | - if (this.$listeners['input']) { | |
| 233 | - this.$emit('input', tableData.map((o, i) => { | |
| 234 | - return { ...o, $index: i, $editable: undefined, $new: undefined, $edit: undefined }; | |
| 235 | - })); | |
| 236 | - } else { | |
| 237 | - this.tableData = tableData; | |
| 238 | - } | |
| 239 | - }, | |
| 240 | 140 | // 绑定表格列显示隐藏状态 |
| 241 | 141 | bindItemVisible(visible = true) { |
| 242 | 142 | let result = visible; |
| ... | ... | @@ -249,43 +149,8 @@ export default { |
| 249 | 149 | bindItemRenderChildren(item, scope) { |
| 250 | 150 | return item.render.children instanceof Function ? item.render.children(scope) : this.$_get(scope.row, item.fullKey) |
| 251 | 151 | }, |
| 252 | - // 双击单元格 | |
| 253 | - onCellDblclick(row, column, cell, event) { | |
| 254 | - if (this.editable && !this.rowNew) { | |
| 255 | - this.tableEditCell = { index: row.$index, key: column.property }; | |
| 256 | - } | |
| 257 | - }, | |
| 258 | - // 编辑表格更新值 | |
| 259 | - onCellUpdate({ oldValue, value, row, key, fullKey }) { | |
| 260 | - this.setCellValue({ value, row, key, fullKey }); | |
| 261 | - }, | |
| 262 | - // 编辑表格确认 | |
| 263 | - onCellUpdateDone({ oldValue, value, row, key, fullKey }) { | |
| 264 | - this.tableEditCell = {}; | |
| 265 | - if (this.$listeners['cell-edit']) { | |
| 266 | - const { tableData } = this.setCellValue({ value, row, key, fullKey }); | |
| 267 | - this.emitTableData(tableData); | |
| 268 | - this.$emit('cell-edit', { row, key, fullKey, value }); | |
| 269 | - } | |
| 270 | - }, | |
| 271 | - // 表格取消编辑 | |
| 272 | - onCellUpdateCancel({ oldValue, value, row, key, fullKey }) { | |
| 273 | - if (row.$new !== true) { | |
| 274 | - this.setCellValue({ value: oldValue, row, key, fullKey }); | |
| 275 | - } | |
| 276 | - }, | |
| 277 | - // 设置表格值 | |
| 278 | - setCellValue({ value, row, key, fullKey }) { | |
| 279 | - const tableData = cloneDeep(this.tableData); | |
| 280 | - const tableRow = tableData[row.$index]; | |
| 281 | - set(tableRow, fullKey, value); | |
| 282 | - tableData[row.$index] = tableRow; | |
| 283 | - this.$set(this.tableData, row.$index, tableRow); | |
| 284 | - return { tableData, tableRow }; | |
| 285 | - }, | |
| 286 | 152 | // 表格选中 |
| 287 | 153 | onSelectionChange(selection) { |
| 288 | - this.tableSelection = selection; | |
| 289 | 154 | this.$emit('selection', selection); |
| 290 | 155 | } |
| 291 | 156 | } | ... | ... |