Commit 984d820ea9f54e084efcac66c20261827cf41edd

Authored by Aaron
1 parent d22cb190
Exists in master and in 1 other branch legacy

新式表格支持行内编辑

examples/views/page/other.vue
... ... @@ -76,7 +76,7 @@ export default {
76 76 // { type: 'el-input', label: '市', key: 'city', render: { type: 'el-tag', props: { type: 'danger', size: 'mini' } } },
77 77 { type: 'el-input', label: '市', key: 'city',
78 78 render: {
79   - type: 'span', props: { href: 'https:///www.baidu.com/' }, style: { color: 'red' },
  79 + type: 'a', props: { href: 'https:///www.baidu.com/', target: '_blank' }, style: { color: 'red' },
80 80 children({ row }) {
81 81 const { location: { district: { city } = {} } = {} } = row;
82 82 return city ? `${city}[城市]` : '';
... ...
examples/views/page/table-new/index.vue
... ... @@ -2,49 +2,93 @@
2 2 .eagle-table {
3 3 width: 100%;
4 4 }
  5 +.eagle-table-cell-edit {
  6 + display: flex;
  7 + align-items: center;
  8 +}
5 9 </style>
6 10  
7 11 <template>
8   - <div>
  12 + <div @keyup.enter="editCell = {}">
9 13 <pre>{{ tableList }}</pre>
10   - <el-table class="eagle-table" ref="table" :data="tableData" v-bind="{ size: 'small', ...tableProps }" v-on="tableEvents">
  14 + <el-table class="eagle-table" ref="table" :data="tableData" v-bind="{ size: 'small', ...tableProps }" v-on="tableEvents" @cell-dblclick="onCellDblclick">
  15 + <!-- 默认表格插槽 -->
11 16 <slot name="default"></slot>
  17 + <!-- 根据配置列表生成表格列 -->
12 18 <template v-if="tableList && tableList.length > 0">
13 19 <template v-for="(item, index) in tableList">
14 20 <template v-if="bindItemVisible(item.visible)">
  21 + <!-- 如果有表格列具名插槽 -->
15 22 <slot v-if="$scopedSlots[item.keyPath.join('-')] || $slots[item.keyPath.join('-')]" :name="item.keyPath.join('-')" v-bind="item"></slot>
  23 + <!-- 如果有表格列值渲染具名插槽 -->
16 24 <el-table-column v-else-if="$scopedSlots[`value-${item.keyPath.join('-')}`] || $slots[`value-${item.keyPath.join('-')}`]"
17 25 v-bind="item" :prop="item.agentKey || item.fullKey || item.key" :key="index"
18 26 :min-width="item.minWidth || item['min-width']"
19 27 >
20   - <slot slot-scope="{ row, column, $index }" :name="`value-${item.keyPath.join('-')}`" v-bind="item"
21   - :row="row" :value="$_get(row, item.fullKey)" :column="column" :index="$index"
22   - ></slot>
  28 + <template slot-scope="{ row, column, $index }">
  29 + <div v-if="editCell.index === row.$index && editCell.key === (item.agentKey || item.fullKey || item.key)" class="eagle-table-cell-edit">
  30 + <component
  31 + :value="$_get(row, item.fullKey)"
  32 + :is="item.type" v-bind="item.props" :style="item.style" size="mini"
  33 + @input="v => onCellUpdate({ value: v, row, key: item.fullKey })"
  34 + ></component>
  35 + <el-button type="text" icon="el-icon-check" @click="editCell = {}"></el-button>
  36 + </div>
  37 + <slot v-else :name="`value-${item.keyPath.join('-')}`" v-bind="item"
  38 + :row="row" :value="$_get(row, item.fullKey)" :column="column" :index="$index"
  39 + ></slot>
  40 + </template>
23 41 </el-table-column>
  42 + <!-- 如果表格列配置了值渲染参数 -->
24 43 <el-table-column v-else-if="item.render" v-bind="item" :prop="item.agentKey || item.fullKey || item.key"
25 44 :key="index" :min-width="item.minWidth || item['min-width']"
26 45 >
27   - <template slot-scope="slotScope">
28   - <component :is="item.render.type" v-bind="item.render.props" :style="item.render.style">
29   - <template v-if="item.render.children">{{ bindItemRenderChildren(item, slotScope) }}</template>
30   - <template v-else>{{ $_get(row, item.fullKey) }}</template>
31   - </component>
  46 + <template slot-scope="{ row, column, $index }">
  47 + <div v-if="editCell.index === row.$index && editCell.key === (item.agentKey || item.fullKey || item.key)" class="eagle-table-cell-edit">
  48 + <component
  49 + :value="$_get(row, item.fullKey)"
  50 + :is="item.type" v-bind="item.props" :style="item.style" size="mini"
  51 + @input="v => onCellUpdate({ value: v, row, key: item.fullKey })"
  52 + ></component>
  53 + <el-button type="text" icon="el-icon-check" @click="editCell = {}"></el-button>
  54 + </div>
  55 + <template v-else>
  56 + <component :is="item.render.type" v-bind="item.render.props" :style="item.render.style">
  57 + <template v-if="item.render.children">{{ bindItemRenderChildren(item, { row, column, $index }) }}</template>
  58 + <template v-else>{{ $_get(row, item.fullKey) }}</template>
  59 + </component>
  60 + </template>
32 61 </template>
33 62 </el-table-column>
  63 + <!-- 默认表格列渲染 -->
34 64 <el-table-column v-else v-bind="item" :prop="item.agentKey || item.fullKey || item.key"
35   - :key="index" :min-width="item.minWidth || item['min-width']"
36   - ></el-table-column>
  65 + :key="index" :min-width="item.minWidth || item['min-width'] || 120"
  66 + >
  67 + <template slot-scope="{ row }">
  68 + <div v-if="editCell.index === row.$index && editCell.key === (item.agentKey || item.fullKey || item.key)" class="eagle-table-cell-edit">
  69 + <component
  70 + :value="$_get(row, item.fullKey)"
  71 + :is="item.type" v-bind="item.props" :style="item.style" size="mini"
  72 + @input="v => onCellUpdate({ value: v, row, key: item.fullKey })"
  73 + ></component>
  74 + <el-button type="text" icon="el-icon-check" @click="editCell = {}"></el-button>
  75 + </div>
  76 + <template v-else>{{ $_get(row, item.fullKey) }}</template>
  77 + </template>
  78 + </el-table-column>
37 79 </template>
38 80 </template>
39 81 </template>
  82 + <!-- 已生成列表后的追加列插槽 -->
40 83 <slot name="column-append"></slot>
  84 + <!-- 末尾列插槽 -->
41 85 <slot name="column-end"></slot>
42 86 </el-table>
43 87 </div>
44 88 </template>
45 89  
46 90 <script>
47   -import { cloneDeep, get } from '../form-new/util';
  91 +import { cloneDeep, get, set } from '../form-new/util';
48 92  
49 93 export default {
50 94 name: 'TableNew',
... ... @@ -68,6 +112,7 @@ export default {
68 112 return {
69 113 tableList: [],
70 114 tableData: [],
  115 + editCell: {},
71 116 };
72 117 },
73 118 computed: {
... ... @@ -81,7 +126,7 @@ export default {
81 126 watch: {
82 127 value: {
83 128 handler(val = []) {
84   - this.tableData = val;
  129 + this.tableData = val.map((o, i) => ({ ...o, $index: i }));
85 130 },
86 131 immediate: true
87 132 },
... ... @@ -137,6 +182,20 @@ export default {
137 182 // 处理表格项渲染时的子值
138 183 bindItemRenderChildren(item, scope) {
139 184 return item.render.children instanceof Function ? item.render.children(scope) : this.$_get(scope.row, item.fullKey)
  185 + },
  186 + // 双击单元格
  187 + onCellDblclick(row, column, cell, event) {
  188 + this.editCell = { index: row.$index, key: column.property };
  189 + },
  190 + // 编辑表格更新值
  191 + onCellUpdate({ value, row, key }) {
  192 + const tableData = cloneDeep(this.tableData);
  193 + const tableRow = tableData[row.$index];
  194 + set(tableRow, key, value);
  195 + tableData[row.$index] = tableRow;
  196 + this.$set(this.tableData, row.$index, tableRow);
  197 + // this.tableData = tableData;
  198 + // this.$emit('input', tableData);
140 199 }
141 200 }
142 201 };
... ...
packages/scheme/index.vue
... ... @@ -138,7 +138,7 @@
138 138 ...tableEvents,
139 139 }"
140 140 >
141   - <slot></slot>
  141 + <slot v-bind="slotMethod"></slot>
142 142 <!-- 表格具名插槽 -->
143 143 <template v-for="(item, index) in tableList || _tableList">
144 144 <slot v-if="$scopedSlots[`table-${item.key}`] || $slots[`table-${item.key}`]" :name="`table-${item.key}`" :slot="item.key" v-bind="slotMethod"></slot>
... ...