Commit 5b19b5f55f0b1022c3bf5e7b7060534b2d9e3676

Authored by 梁灏
1 parent 191068ac

support Transfer

support Transfer
@@ -46,6 +46,7 @@ li + li { border-left: solid 1px #bbb; padding-left: 10px; margin-left: 10px; } @@ -46,6 +46,7 @@ li + li { border-left: solid 1px #bbb; padding-left: 10px; margin-left: 10px; }
46 <li><router-link to="/select">Select</router-link></li> 46 <li><router-link to="/select">Select</router-link></li>
47 <li><router-link to="/backtop">Backtop</router-link></li> 47 <li><router-link to="/backtop">Backtop</router-link></li>
48 <li><router-link to="/page">Page</router-link></li> 48 <li><router-link to="/page">Page</router-link></li>
  49 + <li><router-link to="/transfer">Transfer</router-link></li>
49 </ul> 50 </ul>
50 </nav> 51 </nav>
51 <router-view></router-view> 52 <router-view></router-view>
@@ -148,6 +148,10 @@ const router = new VueRouter({ @@ -148,6 +148,10 @@ const router = new VueRouter({
148 { 148 {
149 path: '/page', 149 path: '/page',
150 component: require('./routers/page.vue') 150 component: require('./routers/page.vue')
  151 + },
  152 + {
  153 + path: '/transfer',
  154 + component: require('./routers/transfer.vue')
151 } 155 }
152 ] 156 ]
153 }); 157 });
examples/routers/transfer.vue
  1 +<!--<template>-->
  2 + <!--<div>-->
  3 + <!--<Transfer-->
  4 + <!--:data="data1"-->
  5 + <!--filterable-->
  6 + <!--:target-keys="targetKeys1"-->
  7 + <!--:render-format="render1"-->
  8 + <!--@on-change="handleChange1"></Transfer>-->
  9 + <!--</div>-->
  10 +<!--</template>-->
  11 +<!--<script>-->
  12 + <!--export default {-->
  13 + <!--data () {-->
  14 + <!--return {-->
  15 + <!--data1: this.getMockData(),-->
  16 + <!--targetKeys1: this.getTargetKeys()-->
  17 + <!--}-->
  18 + <!--},-->
  19 + <!--methods: {-->
  20 + <!--getMockData () {-->
  21 + <!--let mockData = [];-->
  22 + <!--for (let i = 1; i <= 20; i++) {-->
  23 + <!--mockData.push({-->
  24 + <!--key: i.toString(),-->
  25 + <!--label: '内容' + i,-->
  26 + <!--description: '内容' + i + '的描述信息',-->
  27 + <!--disabled: Math.random() * 3 < 1-->
  28 + <!--});-->
  29 + <!--}-->
  30 + <!--return mockData;-->
  31 + <!--},-->
  32 + <!--getTargetKeys () {-->
  33 + <!--return this.getMockData()-->
  34 + <!--.filter(() => Math.random() * 2 > 1)-->
  35 + <!--.map(item => item.key);-->
  36 + <!--},-->
  37 + <!--render1 (item) {-->
  38 + <!--return item.label;-->
  39 + <!--},-->
  40 + <!--handleChange1 (newTargetKeys, direction, moveKeys) {-->
  41 + <!--console.log(newTargetKeys);-->
  42 + <!--console.log(direction);-->
  43 + <!--console.log(moveKeys);-->
  44 + <!--this.targetKeys1 = newTargetKeys;-->
  45 + <!--}-->
  46 + <!--}-->
  47 + <!--}-->
  48 +<!--</script>-->
  49 +
  50 +
1 <template> 51 <template>
2 <Transfer 52 <Transfer
3 - :data="data2"  
4 - :target-keys="targetKeys2" 53 + :data="data3"
  54 + :target-keys="targetKeys3"
  55 + :list-style="listStyle"
  56 + :render-format="render3"
  57 + :operations="['向左移动','向右移动']"
5 filterable 58 filterable
6 - :render-format="rf"  
7 - :filter-method="filterMethod"  
8 - @on-change="handleChange2"></Transfer> 59 + @on-change="handleChange3">
  60 + <div :style="{float: 'right', margin: '5px'}">
  61 + <Button type="ghost" size="small" @click.native="reloadMockData">刷新</Button>
  62 + </div>
  63 + </Transfer>
9 </template> 64 </template>
10 <script> 65 <script>
11 export default { 66 export default {
12 data () { 67 data () {
13 return { 68 return {
14 - data2: this.getMockData(),  
15 - targetKeys2: this.getTargetKeys() 69 + data3: this.getMockData(),
  70 + targetKeys3: this.getTargetKeys(),
  71 + listStyle: {
  72 + width: '250px',
  73 + height: '300px'
  74 + }
16 } 75 }
17 }, 76 },
18 methods: { 77 methods: {
@@ -30,18 +89,62 @@ @@ -30,18 +89,62 @@
30 }, 89 },
31 getTargetKeys () { 90 getTargetKeys () {
32 return this.getMockData() 91 return this.getMockData()
33 - .filter(() => Math.random() * 2 > 1)  
34 - .map(item => item.key); 92 + .filter(() => Math.random() * 2 > 1)
  93 + .map(item => item.key);
35 }, 94 },
36 - handleChange2 (newTargetKeys) {  
37 - this.targetKeys2 = newTargetKeys; 95 + handleChange3 (newTargetKeys) {
  96 + this.targetKeys3 = newTargetKeys;
38 }, 97 },
39 - filterMethod (data, query) {  
40 - return data.label.indexOf(query) > -1; 98 + render3 (item) {
  99 + return item.label + ' - ' + item.description;
41 }, 100 },
42 - rf (data) {  
43 - return '<i class="ivu-icon ivu-icon-alert"></i>' + data.label; 101 + reloadMockData () {
  102 + this.data3 = this.getMockData();
  103 + this.targetKeys3 = this.getTargetKeys();
44 } 104 }
45 } 105 }
46 } 106 }
47 </script> 107 </script>
  108 +
  109 +<!--<template>-->
  110 + <!--<Transfer-->
  111 + <!--:data="data4"-->
  112 + <!--:target-keys="targetKeys4"-->
  113 + <!--:render-format="render4"-->
  114 + <!--@on-change="handleChange4"></Transfer>-->
  115 +<!--</template>-->
  116 +<!--<script>-->
  117 + <!--export default {-->
  118 + <!--data () {-->
  119 + <!--return {-->
  120 + <!--data4: this.getMockData(),-->
  121 + <!--targetKeys4: this.getTargetKeys()-->
  122 + <!--}-->
  123 + <!--},-->
  124 + <!--methods: {-->
  125 + <!--getMockData () {-->
  126 + <!--let mockData = [];-->
  127 + <!--for (let i = 1; i <= 20; i++) {-->
  128 + <!--mockData.push({-->
  129 + <!--key: i.toString(),-->
  130 + <!--label: '内容' + i,-->
  131 + <!--description: '内容' + i + '的描述信息',-->
  132 + <!--disabled: Math.random() * 3 < 1-->
  133 + <!--});-->
  134 + <!--}-->
  135 + <!--return mockData;-->
  136 + <!--},-->
  137 + <!--getTargetKeys () {-->
  138 + <!--return this.getMockData()-->
  139 + <!--.filter(() => Math.random() * 2 > 1)-->
  140 + <!--.map(item => item.key);-->
  141 + <!--},-->
  142 + <!--handleChange4 (newTargetKeys) {-->
  143 + <!--this.targetKeys4 = newTargetKeys;-->
  144 + <!--},-->
  145 + <!--render4 (item) {-->
  146 + <!--return item.label + ' - ' + item.description;-->
  147 + <!--}-->
  148 + <!--}-->
  149 + <!--}-->
  150 +<!--</script>-->
src/components/transfer/list.vue
1 <template> 1 <template>
2 <div :class="classes" :style="style"> 2 <div :class="classes" :style="style">
3 <div :class="prefixCls + '-header'"> 3 <div :class="prefixCls + '-header'">
4 - <Checkbox :checked.sync="checkedAll" :disabled="checkedAllDisabled" @on-change="toggleSelectAll"></Checkbox> 4 + <Checkbox :value="checkedAll" :disabled="checkedAllDisabled" @on-change="toggleSelectAll"></Checkbox>
5 <span>{{ title }}</span> 5 <span>{{ title }}</span>
6 <span :class="prefixCls + '-header-count'">{{ count }}</span> 6 <span :class="prefixCls + '-header-count'">{{ count }}</span>
7 </div> 7 </div>
@@ -9,21 +9,23 @@ @@ -9,21 +9,23 @@
9 <div :class="prefixCls + '-body-search-wrapper'" v-if="filterable"> 9 <div :class="prefixCls + '-body-search-wrapper'" v-if="filterable">
10 <Search 10 <Search
11 :prefix-cls="prefixCls + '-search'" 11 :prefix-cls="prefixCls + '-search'"
12 - :query.sync="query" 12 + :query="query"
  13 + @on-query-clear="handleQueryClear"
  14 + @on-query-change="handleQueryChange"
13 :placeholder="filterPlaceholder"></Search> 15 :placeholder="filterPlaceholder"></Search>
14 </div> 16 </div>
15 <ul :class="prefixCls + '-content'"> 17 <ul :class="prefixCls + '-content'">
16 <li 18 <li
17 - v-for="item in showItems | filterBy filterData" 19 + v-for="item in filterData"
18 :class="itemClasses(item)" 20 :class="itemClasses(item)"
19 @click.prevent="select(item)"> 21 @click.prevent="select(item)">
20 - <Checkbox :checked="isCheck(item)" :disabled="item.disabled"></Checkbox>  
21 - <span>{{{ showLabel(item) }}}</span> 22 + <Checkbox :value="isCheck(item)" :disabled="item.disabled"></Checkbox>
  23 + <span v-html="showLabel(item)"></span>
22 </li> 24 </li>
23 <li :class="prefixCls + '-content-not-found'">{{ notFoundText }}</li> 25 <li :class="prefixCls + '-content-not-found'">{{ notFoundText }}</li>
24 </ul> 26 </ul>
25 </div> 27 </div>
26 - <div :class="prefixCls + '-footer'" v-if="showFooter" v-el:footer><slot></slot></div> 28 + <div :class="prefixCls + '-footer'" v-if="showFooter"><slot></slot></div>
27 </div> 29 </div>
28 </template> 30 </template>
29 <script> 31 <script>
@@ -31,6 +33,7 @@ @@ -31,6 +33,7 @@
31 import Checkbox from '../checkbox/checkbox.vue'; 33 import Checkbox from '../checkbox/checkbox.vue';
32 34
33 export default { 35 export default {
  36 + name: 'TransferList',
34 components: { Search, Checkbox }, 37 components: { Search, Checkbox },
35 props: { 38 props: {
36 prefixCls: String, 39 prefixCls: String,
@@ -52,6 +55,11 @@ @@ -52,6 +55,11 @@
52 showFooter: true 55 showFooter: true
53 }; 56 };
54 }, 57 },
  58 + watch: {
  59 + data () {
  60 + this.updateFilteredData();
  61 + }
  62 + },
55 computed: { 63 computed: {
56 classes () { 64 classes () {
57 return [ 65 return [
@@ -79,6 +87,9 @@ @@ -79,6 +87,9 @@
79 }, 87 },
80 checkedAllDisabled () { 88 checkedAllDisabled () {
81 return this.data.filter(data => !data.disabled).length <= 0; 89 return this.data.filter(data => !data.disabled).length <= 0;
  90 + },
  91 + filterData () {
  92 + return this.showItems.filter(item => this.filterMethod(item, this.query));
82 } 93 }
83 }, 94 },
84 methods: { 95 methods: {
@@ -105,25 +116,23 @@ @@ -105,25 +116,23 @@
105 this.showItems = this.data; 116 this.showItems = this.data;
106 }, 117 },
107 toggleSelectAll (status) { 118 toggleSelectAll (status) {
108 - this.checkedKeys = status ? 119 + const keys = status ?
109 this.data.filter(data => !data.disabled || this.checkedKeys.indexOf(data.key) > -1).map(data => data.key) : 120 this.data.filter(data => !data.disabled || this.checkedKeys.indexOf(data.key) > -1).map(data => data.key) :
110 this.data.filter(data => data.disabled && this.checkedKeys.indexOf(data.key) > -1).map(data => data.key); 121 this.data.filter(data => data.disabled && this.checkedKeys.indexOf(data.key) > -1).map(data => data.key);
  122 + this.$emit('on-checked-keys-change', keys);
  123 + },
  124 + handleQueryClear () {
  125 + this.query = '';
111 }, 126 },
112 - filterData (value) {  
113 - return this.filterMethod(value, this.query); 127 + handleQueryChange (val) {
  128 + this.query = val;
114 } 129 }
115 }, 130 },
116 created () { 131 created () {
117 this.updateFilteredData(); 132 this.updateFilteredData();
118 -  
119 - },  
120 - compiled () {  
121 - this.showFooter = this.$els.footer.innerHTML !== '';  
122 }, 133 },
123 - watch: {  
124 - data () {  
125 - this.updateFilteredData();  
126 - } 134 + mounted () {
  135 + this.showFooter = this.$slots.default !== undefined;
127 } 136 }
128 }; 137 };
129 </script> 138 </script>
src/components/transfer/operation.vue
1 <template> 1 <template>
2 <div :class="prefixCls + '-operation'"> 2 <div :class="prefixCls + '-operation'">
3 - <i-button type="primary" size="small" :disabled="!rightActive" @click="moveToLeft"> 3 + <i-button type="primary" size="small" :disabled="!rightActive" @click.native="moveToLeft">
4 <Icon type="ios-arrow-left"></Icon> {{ operations[0] }} 4 <Icon type="ios-arrow-left"></Icon> {{ operations[0] }}
5 </i-button> 5 </i-button>
6 - <i-button type="primary" size="small" :disabled="!leftActive" @click="moveToRight"> 6 + <i-button type="primary" size="small" :disabled="!leftActive" @click.native="moveToRight">
7 {{ operations[1] }} <Icon type="ios-arrow-right"></Icon> 7 {{ operations[1] }} <Icon type="ios-arrow-right"></Icon>
8 </i-button> 8 </i-button>
9 </div> 9 </div>
@@ -13,6 +13,7 @@ @@ -13,6 +13,7 @@
13 import Icon from '../icon/icon.vue'; 13 import Icon from '../icon/icon.vue';
14 14
15 export default { 15 export default {
  16 + name: 'Operation',
16 components: { iButton, Icon }, 17 components: { iButton, Icon },
17 props: { 18 props: {
18 prefixCls: String, 19 prefixCls: String,
src/components/transfer/search.vue
1 <template> 1 <template>
2 <div :class="prefixCls"> 2 <div :class="prefixCls">
3 <i-input 3 <i-input
4 - :value.sync="query" 4 + v-model="currentQuery"
5 size="small" 5 size="small"
6 :icon="icon" 6 :icon="icon"
7 :placeholder="placeholder" 7 :placeholder="placeholder"
@@ -12,12 +12,26 @@ @@ -12,12 +12,26 @@
12 import iInput from '../input/input.vue'; 12 import iInput from '../input/input.vue';
13 13
14 export default { 14 export default {
  15 + name: 'Search',
15 components: { iInput }, 16 components: { iInput },
16 props: { 17 props: {
17 prefixCls: String, 18 prefixCls: String,
18 placeholder: String, 19 placeholder: String,
19 query: String 20 query: String
20 }, 21 },
  22 + data () {
  23 + return {
  24 + currentQuery: this.query
  25 + };
  26 + },
  27 + watch: {
  28 + query (val) {
  29 + this.currentQuery = val;
  30 + },
  31 + currentQuery (val) {
  32 + this.$emit('on-query-change', val);
  33 + }
  34 + },
21 computed: { 35 computed: {
22 icon () { 36 icon () {
23 return this.query === '' ? 'ios-search' : 'ios-close'; 37 return this.query === '' ? 'ios-search' : 'ios-close';
@@ -25,17 +39,19 @@ @@ -25,17 +39,19 @@
25 }, 39 },
26 methods: { 40 methods: {
27 handleClick () { 41 handleClick () {
28 - if (this.query === '') return;  
29 - this.query = '';  
30 - }  
31 - },  
32 - events: {  
33 - 'on-form-blur' () {  
34 - return false;  
35 - },  
36 - 'on-form-change' () {  
37 - return false; 42 + if (this.currentQuery === '') return;
  43 + this.currentQuery = '';
  44 + this.$emit('on-query-clear');
38 } 45 }
39 } 46 }
  47 + // todo 事件
  48 +// events: {
  49 +// 'on-form-blur' () {
  50 +// return false;
  51 +// },
  52 +// 'on-form-change' () {
  53 +// return false;
  54 +// }
  55 +// }
40 }; 56 };
41 </script> 57 </script>
src/components/transfer/transfer.vue
1 <template> 1 <template>
2 <div :class="classes"> 2 <div :class="classes">
3 <List 3 <List
4 - v-ref:left 4 + ref="left"
5 :prefix-cls="prefixCls + '-list'" 5 :prefix-cls="prefixCls + '-list'"
6 :data="leftData" 6 :data="leftData"
7 :render-format="renderFormat" 7 :render-format="renderFormat"
8 - :checked-keys.sync="leftCheckedKeys"  
9 - :valid-keys-count.sync="leftValidKeysCount" 8 + :checked-keys="leftCheckedKeys"
  9 + @on-checked-keys-change="handleLeftCheckedKeysChange"
  10 + :valid-keys-count="leftValidKeysCount"
10 :style="listStyle" 11 :style="listStyle"
11 :title="titles[0]" 12 :title="titles[0]"
12 :filterable="filterable" 13 :filterable="filterable"
@@ -19,19 +20,20 @@ @@ -19,19 +20,20 @@
19 :operations="operations" 20 :operations="operations"
20 :left-active="leftValidKeysCount > 0" 21 :left-active="leftValidKeysCount > 0"
21 :right-active="rightValidKeysCount > 0"></Operation><List 22 :right-active="rightValidKeysCount > 0"></Operation><List
22 - v-ref:right 23 + ref="right"
23 :prefix-cls="prefixCls + '-list'" 24 :prefix-cls="prefixCls + '-list'"
24 :data="rightData" 25 :data="rightData"
25 :render-format="renderFormat" 26 :render-format="renderFormat"
26 - :checked-keys.sync="rightCheckedKeys"  
27 - :valid-keys-count.sync="rightValidKeysCount" 27 + :checked-keys="rightCheckedKeys"
  28 + @on-checked-keys-change="handleRightCheckedKeysChange"
  29 + :valid-keys-count="rightValidKeysCount"
28 :style="listStyle" 30 :style="listStyle"
29 :title="titles[1]" 31 :title="titles[1]"
30 :filterable="filterable" 32 :filterable="filterable"
31 :filter-placeholder="filterPlaceholder" 33 :filter-placeholder="filterPlaceholder"
32 :filter-method="filterMethod" 34 :filter-method="filterMethod"
33 :not-found-text="notFoundText"> 35 :not-found-text="notFoundText">
34 - <slot></slot> 36 + <slot name="right"></slot>
35 </List> 37 </List>
36 </div> 38 </div>
37 </template> 39 </template>
@@ -177,7 +179,14 @@ @@ -177,7 +179,14 @@
177 179
178 this.$refs[opposite].toggleSelectAll(false); 180 this.$refs[opposite].toggleSelectAll(false);
179 this.$emit('on-change', newTargetKeys, direction, moveKeys); 181 this.$emit('on-change', newTargetKeys, direction, moveKeys);
180 - this.$dispatch('on-form-change', newTargetKeys, direction, moveKeys); 182 + // todo 事件
  183 +// this.$dispatch('on-form-change', newTargetKeys, direction, moveKeys);
  184 + },
  185 + handleLeftCheckedKeysChange (keys) {
  186 + this.leftCheckedKeys = keys;
  187 + },
  188 + handleRightCheckedKeysChange (keys) {
  189 + this.rightCheckedKeys = keys;
181 } 190 }
182 }, 191 },
183 watch: { 192 watch: {
@@ -39,7 +39,7 @@ import Tag from &#39;./components/tag&#39;; @@ -39,7 +39,7 @@ import Tag from &#39;./components/tag&#39;;
39 import Timeline from './components/timeline'; 39 import Timeline from './components/timeline';
40 // import TimePicker from './components/time-picker'; 40 // import TimePicker from './components/time-picker';
41 import Tooltip from './components/tooltip'; 41 import Tooltip from './components/tooltip';
42 -// import Transfer from './components/transfer'; 42 +import Transfer from './components/transfer';
43 import Tree from './components/tree'; 43 import Tree from './components/tree';
44 import Upload from './components/upload'; 44 import Upload from './components/upload';
45 import { Row, Col } from './components/grid'; 45 import { Row, Col } from './components/grid';
@@ -107,7 +107,7 @@ const iview = { @@ -107,7 +107,7 @@ const iview = {
107 TimelineItem: Timeline.Item, 107 TimelineItem: Timeline.Item,
108 // TimePicker, 108 // TimePicker,
109 Tooltip, 109 Tooltip,
110 - // Transfer, 110 + Transfer,
111 Tree, 111 Tree,
112 Upload 112 Upload
113 }; 113 };