Commit 303ef68882af7d8e6b235acc89b0447735476d57
1 parent
bffb3d99
Exists in
master
and in
2 other branches
feat: 优化SchemaTransfer
Showing
3 changed files
with
144 additions
and
27 deletions
Show diff stats
examples/views/docs/component/schema-transfer.md
| ... | ... | @@ -100,11 +100,86 @@ export default { |
| 100 | 100 | |
| 101 | 101 | 可以单独配置已选中的表格 |
| 102 | 102 | |
| 103 | -::: snippet `schema`中设置`selected`,格式与`z-schema-table`相同。 | |
| 103 | +::: snippet `schema`中设置`selected`,配置与`SchemaTable`相同。其中已选中项的表格字段可以与数据源不同,设置`choose-formatter`改变选择的数据格式。 | |
| 104 | 104 | |
| 105 | 105 | ```html |
| 106 | 106 | <template> |
| 107 | - <z-schema-transfer v-model="model" :schema="schema" :source="source" value-key="id" size="small"></z-schema-transfer> | |
| 107 | + <z-schema-transfer v-model="model" :schema="schema" :source="source" value-key="id" size="small" :choose-formatter="chooseFormatter"></z-schema-transfer> | |
| 108 | +</template> | |
| 109 | + | |
| 110 | +<script> | |
| 111 | +export default { | |
| 112 | + data() { | |
| 113 | + return { | |
| 114 | + model: [], | |
| 115 | + source: [ | |
| 116 | + { id: '0', name: '姓名0', age: 17 }, | |
| 117 | + { id: '1', name: '姓名1', age: 26 }, | |
| 118 | + ], | |
| 119 | + schema: { | |
| 120 | + table: { | |
| 121 | + items: [ | |
| 122 | + { label: '姓名', prop: 'name', minWidth: 120 }, | |
| 123 | + { label: '年龄', prop: 'age', minWidth: 120 }, | |
| 124 | + { label: '地址', prop: 'address', minWidth: 120 }, | |
| 125 | + ] | |
| 126 | + }, | |
| 127 | + selected: { | |
| 128 | + props: { border: true, editable: true }, | |
| 129 | + items: [ | |
| 130 | + { label: '姓名', prop: 'name', minWidth: 120, editable: false }, | |
| 131 | + { label: '性别', prop: 'gender', minWidth: 120, editable: false }, | |
| 132 | + { label: '民族', prop: 'ethnicity', minWidth: 120, editalways: true }, | |
| 133 | + ] | |
| 134 | + } | |
| 135 | + }, | |
| 136 | + } | |
| 137 | + }, | |
| 138 | + methods: { | |
| 139 | + chooseFormatter(row) { | |
| 140 | + return { id: row.id, name: row.name, gender: '男', ethnicity: '汉' }; | |
| 141 | + } | |
| 142 | + } | |
| 143 | +} | |
| 144 | +</script> | |
| 145 | +``` | |
| 146 | + | |
| 147 | +::: | |
| 148 | + | |
| 149 | +## 自定义插槽 | |
| 150 | + | |
| 151 | +同其他组件一样,可以对部分内容设置插槽 | |
| 152 | + | |
| 153 | +::: snippet 左侧插槽格式默认与`SchemaPage`组件相同,已选中表格的插槽以`selected-`开头 | |
| 154 | + | |
| 155 | +```html | |
| 156 | +<template> | |
| 157 | + <z-schema-transfer v-model="model" :schema="schema" :source="source" value-key="id" size="small"> | |
| 158 | + <template #table-cell-name="{ value, size }"> | |
| 159 | + <el-tag :size="size">{{ value }}</el-tag> | |
| 160 | + </template> | |
| 161 | + <template #operation="{ choose }"> | |
| 162 | + <el-table-column label="新操作" width="80" align="center" fixed="right"> | |
| 163 | + <template #default="{ row, $index }"> | |
| 164 | + <div class="z-schema-page__table-operation"> | |
| 165 | + <el-button size="mini" @click="choose(row)">选中</el-button> | |
| 166 | + </div> | |
| 167 | + </template> | |
| 168 | + </el-table-column> | |
| 169 | + </template> | |
| 170 | + <template #selected-cell-name="{ value, size }"> | |
| 171 | + <el-tag :size="size" type="success">{{ value }}</el-tag> | |
| 172 | + </template> | |
| 173 | + <template #selected-operation="{ remove }"> | |
| 174 | + <el-table-column label="新操作" width="80" align="center" fixed="right"> | |
| 175 | + <template #default="{ row, $index }"> | |
| 176 | + <div class="z-schema-page__table-operation"> | |
| 177 | + <el-button size="mini" @click="remove(row)">移除</el-button> | |
| 178 | + </div> | |
| 179 | + </template> | |
| 180 | + </el-table-column> | |
| 181 | + </template> | |
| 182 | + </z-schema-transfer> | |
| 108 | 183 | </template> |
| 109 | 184 | |
| 110 | 185 | <script> |
| ... | ... | @@ -151,15 +226,15 @@ export default { |
| 151 | 226 | <template> |
| 152 | 227 | <z-schema-transfer v-model="model" :schema="schema" :source="source" value-key="id" size="small"> |
| 153 | 228 | <template #title-left>未选择 <i class="el-icon-minus"></i></template> |
| 154 | - <template #default="{ onChoose, valueFormatter }"> | |
| 229 | + <template #default="{ choose, deselect }"> | |
| 155 | 230 | <div> |
| 156 | - <el-button size="mini" v-for="item in valueFormatter(source)" @click="onChoose(item)">{{ item.name }}</el-button> | |
| 231 | + <el-button size="mini" v-for="item in deselect(source)" @click="choose(item)">{{ item.name }}</el-button> | |
| 157 | 232 | </div> |
| 158 | 233 | </template> |
| 159 | 234 | <template #title-right>已选择 <i class="el-icon-check"></i></template> |
| 160 | - <template #selected="{ onRemove }"> | |
| 235 | + <template #selected="{ remove }"> | |
| 161 | 236 | <div> |
| 162 | - <el-button size="mini" v-for="item in model" @click="onRemove(item)">{{ item.name }}</el-button> | |
| 237 | + <el-button size="mini" v-for="item in model" @click="remove(item)">{{ item.name }}</el-button> | |
| 163 | 238 | </div> |
| 164 | 239 | </template> |
| 165 | 240 | </z-schema-transfer> | ... | ... |
packages/schema-transfer/index.vue
| ... | ... | @@ -29,11 +29,11 @@ |
| 29 | 29 | <div class="z-schema-transfer__left"> |
| 30 | 30 | <div class="z-schema-transfer__header"> |
| 31 | 31 | <div class="z-schema-transfer__title"> |
| 32 | - <slot name="title-left">{{ titles[0] }}</slot> | |
| 32 | + <slot name="title-left" v-bind="_slotScope">{{ titles[0] }}</slot> | |
| 33 | 33 | </div> |
| 34 | 34 | </div> |
| 35 | 35 | <div class="z-schema-transfer__content"> |
| 36 | - <slot :onChoose="onChoose" :valueFormatter="valueFormatter"> | |
| 36 | + <slot v-bind="_slotScope"> | |
| 37 | 37 | <z-schema-page |
| 38 | 38 | :size="transferSize" |
| 39 | 39 | :value-filter="valueFilter" |
| ... | ... | @@ -43,14 +43,19 @@ |
| 43 | 43 | @update:value-filter="e => $emit('update:value-filter', e)" |
| 44 | 44 | :auto="auto" |
| 45 | 45 | > |
| 46 | + <template v-for="item in getSlotKeys('table-')" #[item.name]="slotScope"> | |
| 47 | + <slot :name="item.slot" v-bind="{ ..._slotScope, ...slotScope }"></slot> | |
| 48 | + </template> | |
| 46 | 49 | <template #operation> |
| 47 | - <el-table-column label="操作" width="80" align="center" fixed="right"> | |
| 48 | - <template #default="{ row, $index }"> | |
| 49 | - <div class="z-schema-page__table-operation"> | |
| 50 | - <el-button type="text" :disabled="_rowDisabled(row, $index)" @click="onChoose(row)">选择</el-button> | |
| 51 | - </div> | |
| 52 | - </template> | |
| 53 | - </el-table-column> | |
| 50 | + <slot name="operation" v-bind="_slotScope"> | |
| 51 | + <el-table-column label="操作" width="80" align="center" fixed="right"> | |
| 52 | + <template #default="{ row, $index }"> | |
| 53 | + <div class="z-schema-page__table-operation"> | |
| 54 | + <el-button type="text" :disabled="_rowDisabled(row, $index)" @click="onChoose(row)">选择</el-button> | |
| 55 | + </div> | |
| 56 | + </template> | |
| 57 | + </el-table-column> | |
| 58 | + </slot> | |
| 54 | 59 | </template> |
| 55 | 60 | </z-schema-page> |
| 56 | 61 | </slot> |
| ... | ... | @@ -63,15 +68,20 @@ |
| 63 | 68 | </div> |
| 64 | 69 | </div> |
| 65 | 70 | <div class="z-schema-transfer__content"> |
| 66 | - <slot name="selected" :onRemove="onRemove"> | |
| 71 | + <slot name="selected" v-bind="_slotScope"> | |
| 67 | 72 | <z-schema-table :size="transferSize" :value="value" :schema="schemaRight" @input="onInput"> |
| 68 | - <el-table-column label="操作" width="80" align="center" fixed="right"> | |
| 69 | - <template #default="{ row, $index }"> | |
| 70 | - <div class="z-schema-page__table-operation"> | |
| 71 | - <el-button type="text" :disabled="_rowDisabled(row, $index)" @click="onRemove(row, $index)">移除</el-button> | |
| 72 | - </div> | |
| 73 | - </template> | |
| 74 | - </el-table-column> | |
| 73 | + <template v-for="item in getSlotKeys('selected-', true)" #[item.name]="slotScope"> | |
| 74 | + <slot :name="item.slot" v-bind="{ ..._slotScope, ...slotScope }"></slot> | |
| 75 | + </template> | |
| 76 | + <slot name="selected-operation" v-bind="_slotScope"> | |
| 77 | + <el-table-column label="操作" width="80" align="center" fixed="right"> | |
| 78 | + <template #default="{ row, $index }"> | |
| 79 | + <div class="z-schema-page__table-operation"> | |
| 80 | + <el-button type="text" :disabled="_rowDisabled(row, $index)" @click="onRemove(row, $index)">移除</el-button> | |
| 81 | + </div> | |
| 82 | + </template> | |
| 83 | + </el-table-column> | |
| 84 | + </slot> | |
| 75 | 85 | </z-schema-table> |
| 76 | 86 | </slot> |
| 77 | 87 | </div> |
| ... | ... | @@ -114,6 +124,7 @@ export default { |
| 114 | 124 | auto: Boolean, |
| 115 | 125 | rowDisabled: Function, |
| 116 | 126 | apiSearch: Function, |
| 127 | + chooseFormatter: Function, | |
| 117 | 128 | valueFilter: { |
| 118 | 129 | type: Object, |
| 119 | 130 | default() { |
| ... | ... | @@ -186,10 +197,37 @@ export default { |
| 186 | 197 | return this.value.map(item => item[this.valueKey]); |
| 187 | 198 | }, |
| 188 | 199 | valueTable() { |
| 189 | - return this.valueFormatter(this.dataSource || []); | |
| 200 | + return this.deselect(this.dataSource || []); | |
| 201 | + }, | |
| 202 | + slotKeys() { | |
| 203 | + return Object.keys(this.$scopedSlots); | |
| 204 | + }, | |
| 205 | + _slotScope() { | |
| 206 | + const methods = ['deselect']; | |
| 207 | + const defaultScope = { | |
| 208 | + size: this.transferSize, | |
| 209 | + disabled: this.transferDisabled, | |
| 210 | + choose: this.onChoose, | |
| 211 | + remove: this.onRemove, | |
| 212 | + }; | |
| 213 | + return [...methods].reduce((result, current) => { | |
| 214 | + result[current] = this[current]; | |
| 215 | + return result; | |
| 216 | + }, defaultScope); | |
| 190 | 217 | }, |
| 191 | 218 | }, |
| 192 | 219 | methods: { |
| 220 | + getSlotKeys(prefix, fixed) { | |
| 221 | + return this.slotKeys.reduce((result, current) => { | |
| 222 | + if (current.indexOf(prefix) === 0) { | |
| 223 | + result.push({ | |
| 224 | + slot: current, | |
| 225 | + name: fixed ? current.substring(prefix.length) : current, | |
| 226 | + }); | |
| 227 | + } | |
| 228 | + return result; | |
| 229 | + }, []); | |
| 230 | + }, | |
| 193 | 231 | _rowDisabled(row, index) { |
| 194 | 232 | if (this.transferDisabled) { |
| 195 | 233 | return true; |
| ... | ... | @@ -199,11 +237,15 @@ export default { |
| 199 | 237 | } |
| 200 | 238 | return false; |
| 201 | 239 | }, |
| 202 | - valueFormatter(value) { | |
| 240 | + deselect(value) { | |
| 203 | 241 | return value.filter(item => !this.valueKeys.includes(item[this.valueKey])); |
| 204 | 242 | }, |
| 205 | 243 | onChoose(row) { |
| 206 | - this.$emit('input', [...this.value, row]); | |
| 244 | + let newRow = cloneDeep(row); | |
| 245 | + if (this.chooseFormatter) { | |
| 246 | + newRow = this.chooseFormatter(newRow); | |
| 247 | + } | |
| 248 | + this.$emit('input', [...this.value, newRow]); | |
| 207 | 249 | }, |
| 208 | 250 | onRemove(row, index) { |
| 209 | 251 | const newValue = cloneDeep(this.value || []); | ... | ... |