Blame view

src/components/transfer/transfer.vue 6.09 KB
77f7bb95   梁灏   add Transfer comp...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
  <template>
      <div :class="classes">
          <List
              v-ref:left
              :prefix-cls="prefixCls + '-list'"
              :data="leftData"
              :render-format="renderFormat"
              :checked-keys.sync="leftCheckedKeys"
              :valid-keys-count.sync="leftValidKeysCount"
              :style="listStyle"
              :title="titles[0]"
              :filterable="filterable"
              :filter-placeholder="filterPlaceholder"
              :filter-method="filterMethod"
              :not-found-text="notFoundText">
              <slot></slot>
          </List><Operation
              :prefix-cls="prefixCls"
              :operations="operations"
              :left-active="leftValidKeysCount > 0"
              :right-active="rightValidKeysCount > 0"></Operation><List
              v-ref:right
              :prefix-cls="prefixCls + '-list'"
              :data="rightData"
              :render-format="renderFormat"
              :checked-keys.sync="rightCheckedKeys"
              :valid-keys-count.sync="rightValidKeysCount"
              :style="listStyle"
              :title="titles[1]"
              :filterable="filterable"
              :filter-placeholder="filterPlaceholder"
              :filter-method="filterMethod"
              :not-found-text="notFoundText">
              <slot></slot>
          </List>
      </div>
  </template>
  <script>
      import List from './list.vue';
      import Operation from './operation.vue';
  
      const prefixCls = 'ivu-transfer';
  
      export default {
          components: { List, Operation },
          props: {
              data: {
                  type: Array,
                  default () {
                      return []
                  }
              },
              renderFormat: {
                  type: Function,
                  default (item) {
                      return item.label || item.key;
                  }
              },
              targetKeys: {
                  type: Array,
                  default () {
                      return []
                  }
              },
              selectedKeys: {
                  type: Array,
                  default () {
                      return []
                  }
              },
              listStyle: {
                  type: Object,
                  default () {
                      return {}
                  }
              },
              titles: {
                  type: Array,
                  default () {
                      return ['源列表', '目的列表']
                  }
              },
              operations: {
                  type: Array,
                  default () {
                      return []
                  }
              },
              filterable: {
                  type: Boolean,
                  default: false
              },
              filterPlaceholder: {
                  type: String,
                  default: '请输入搜索内容'
              },
              filterMethod: {
                  type: Function,
                  default (data, query) {
                      const type = ('label' in data) ? 'label' : 'key';
                      return data[type].indexOf(query) > -1;
                  }
              },
              notFoundText: {
                  type: String,
                  default: '列表为空'
              }
          },
          data () {
              return {
                  prefixCls: prefixCls,
                  leftData: [],
                  rightData: [],
                  leftCheckedKeys: [],
                  rightCheckedKeys: []
              }
          },
          computed: {
              classes () {
                  return [
                      `${prefixCls}`
                  ]
              },
              leftValidKeysCount () {
                  return this.getValidKeys('left').length;
              },
              rightValidKeysCount () {
                  return this.getValidKeys('right').length;
              }
          },
          methods: {
              getValidKeys (direction) {
                  return this[`${direction}Data`].filter(data => !data.disabled && this[`${direction}CheckedKeys`].indexOf(data.key) > -1).map(data => data.key);
              },
              splitData (init = false) {
                  this.leftData = [...this.data];
                  this.rightData = [];
                  if (this.targetKeys.length > 0) {
                      this.targetKeys.forEach((targetKey) => {
                          this.rightData.push(
                                  this.leftData.filter((data, index) => {
                                      if (data.key === targetKey) {
                                          this.leftData.splice(index, 1);
                                          return true;
                                      }
                                      return false;
                                  })[0]);
                      });
                  }
                  if (init) {
                      this.splitSelectedKey();
                  }
              },
              splitSelectedKey () {
                  const selectedKeys = this.selectedKeys;
                  if (selectedKeys.length > 0) {
                      this.leftCheckedKeys = this.leftData
                              .filter(data => selectedKeys.indexOf(data.key) > -1)
                              .map(data => data.key);
                      this.rightCheckedKeys = this.rightData
                              .filter(data => selectedKeys.indexOf(data.key) > -1)
                              .map(data => data.key);
                  }
              },
              moveTo (direction) {
                  const targetKeys = this.targetKeys;
                  const opposite = direction === 'left' ? 'right' : 'left';
                  const moveKeys = this.getValidKeys(opposite);
                  const newTargetKeys = direction === 'right' ?
                          moveKeys.concat(targetKeys) :
                          targetKeys.filter(targetKey => !moveKeys.some(checkedKey => targetKey === checkedKey));
  
                  this.$refs[opposite].toggleSelectAll(false);
                  this.$emit('on-change', newTargetKeys, direction, moveKeys);
              }
          },
          watch: {
              targetKeys () {
                  this.splitData(false);
              }
          },
          created () {
              this.splitData(true);
          }
      }
  </script>