TransferTree.vue 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. <template>
  2. <div class="transfer" :style="{width,height}">
  3. <!-- 左侧穿梭框 原料框 -->
  4. <div class="transfer-left">
  5. <h3 class="transfer-title">
  6. <!--全选按钮-->
  7. <el-checkbox v-model="is_from_selected_all" @change="onChangeFromAll">全选</el-checkbox>
  8. <!--源列表标题-->
  9. <span class="u-right list-title">{{ fromTitle }}</span>
  10. </h3>
  11. <!-- 内容区 -->
  12. <div class="transfer-main">
  13. <en-tree-list
  14. :treeData="from_data"
  15. :key="1"
  16. :isCompleted="is_from_completed"
  17. :selectedAllData="selected_all_from_data"
  18. @getChooseData="updateSelectedFromData"
  19. @scorll_load_more="scorllLoadFromData"
  20. @listenCompleted="listenFromCompleted"
  21. class="trees"></en-tree-list>
  22. </div>
  23. </div>
  24. <!--穿梭区 按钮框-->
  25. <div class="transfer-center">
  26. <template v-if='button_text'>
  27. <p class="transfer-center-item">
  28. <el-button type="primary" @click="addTo" :disabled="from_disabled">
  29. {{ fromButton || '添加'}}
  30. <i class="el-icon-arrow-right"></i>
  31. </el-button>
  32. </p>
  33. <p class="transfer-center-item">
  34. <el-button type="primary" @click='removeTo' :disabled="to_disabled" icon="el-icon-arrow-left">{{ toButton || '移除'}}</el-button>
  35. </p>
  36. </template>
  37. <template v-else>
  38. <p class="transfer-center-item">
  39. <el-button type="primary" @click="addToAims" icon="el-icon-arrow-right" circle :disabled="from_disabled"></el-button>
  40. </p>
  41. <p class="transfer-center-item">
  42. <el-button type="primary" @click='removeToSource' :disabled="to_disabled" icon="el-icon-arrow-left" circle></el-button>
  43. </p>
  44. </template>
  45. </div>
  46. <!--右侧穿梭框 目标框-->
  47. <div class="transfer-right">
  48. <h3 class="transfer-title">
  49. <!--全选按钮-->
  50. <el-checkbox v-model="is_to_selected_all" @change="onChangeToAll">全选</el-checkbox>
  51. <!--目标列表标题-->
  52. <span class="u-right list-title">{{ toTitle }}</span>
  53. </h3>
  54. <!-- 内容区 -->
  55. <div class="transfer-main">
  56. <en-tree-list
  57. :treeData="to_data"
  58. :isCompleted="is_to_completed"
  59. :selectedAllData="selected_all_to_data"
  60. :key="2"
  61. @getChooseData="updateSelectedToData"
  62. @listenCompleted="listenToCompleted"
  63. class="trees"></en-tree-list>
  64. </div>
  65. </div>
  66. </div>
  67. </template>
  68. <script>
  69. import TreeList from './TreeList'
  70. export default {
  71. name: 'EnTransferTree',
  72. data() {
  73. return {
  74. /** 添加是否禁用 */
  75. from_disabled: false,
  76. /** 移除是否禁用 */
  77. to_disabled: false,
  78. /** 源数据是否全选 */
  79. is_from_selected_all: false,
  80. /** 目标数据是否全选 */
  81. is_to_selected_all: false,
  82. /** 源数据选中项 */
  83. selected_from_data: '',
  84. /** 目标数据选中项 */
  85. selected_to_data: '',
  86. /** 是否完成左侧移动 */
  87. is_from_completed: false,
  88. /** 是否完成右侧移动 */
  89. is_to_completed: false,
  90. /** 全选时的源数据选中数据 */
  91. selected_all_from_data: {},
  92. /** 全选时的目标数据选中数据 */
  93. selected_all_to_data: {}
  94. }
  95. },
  96. components: { [TreeList.name]: TreeList },
  97. props: {
  98. // 宽度
  99. width: {
  100. type: String,
  101. default: '100%'
  102. },
  103. // 高度
  104. height: {
  105. type: String,
  106. default: '320px'
  107. },
  108. // 标题
  109. title: {
  110. type: Array,
  111. default: () => ['源列表', '目标列表']
  112. },
  113. // 穿梭按钮名字
  114. button_text: Array,
  115. // 源数据
  116. from_data: {
  117. type: Object,
  118. default: () => ({})
  119. },
  120. // 目标数据
  121. to_data: {
  122. type: Object,
  123. default: () => ({})
  124. }
  125. },
  126. methods: {
  127. // 源数据更新
  128. updateSelectedFromData(data) {
  129. this.selected_from_data = data
  130. this.is_from_selected_all = Object.keys(this.from_data).length === Object.keys(this.selected_from_data).length
  131. },
  132. // 更新目标数据
  133. updateSelectedToData(data) {
  134. this.selected_to_data = data
  135. this.is_to_selected_all = Object.keys(this.to_data).length === Object.keys(this.selected_to_data).length
  136. },
  137. // 添加按钮 执行添加操作 1.源数据更新 把源数据选中项删除/添加 2.目标数据更新 把源数据选中项整合进目标数据 释放当前源数据 目标数据
  138. addToAims() {
  139. // 源数据更新 第二个参数代表数据更新类型(0移除 1添加)
  140. this.$emit('from_data_change', this.selected_from_data, 0)
  141. // 目标数据更新
  142. this.$emit('to_data_change', this.selected_from_data, 1)
  143. // 释放当前选中数据
  144. this.selected_from_data = {}
  145. this.is_from_completed = true
  146. },
  147. // 移除按钮 执行移除操作 1.目标数据更新 把目标数据选中项删除 2.源数据更新 把目标数据选中项整合进源数据 释放当前源数据 目标数据
  148. removeToSource() {
  149. // 源数据更新 第二个参数代表数据更新类型(0移除 1添加)\
  150. this.$emit('from_data_change', this.selected_to_data, 1)
  151. // 目标数据更新
  152. this.$emit('to_data_change', this.selected_to_data, 0)
  153. // 释放当前选中数据
  154. this.selected_to_data = {}
  155. this.is_to_completed = true
  156. },
  157. /** 滚动监听触发 加载更多源数据 */
  158. scorllLoadFromData() {
  159. // this.$emit('')
  160. },
  161. /** 监听左侧穿梭完成 */
  162. listenFromCompleted(target) {
  163. this.is_from_completed = false
  164. },
  165. /** 监听右侧穿梭完成 */
  166. listenToCompleted(target) {
  167. this.is_to_completed = false
  168. },
  169. /** 源数据是否全选 */
  170. onChangeFromAll(val) {
  171. this.$emit('from_selected_all', val)
  172. this.selected_from_data = this.selected_all_from_data = val ? JSON.parse(JSON.stringify(this.from_data)) : {}
  173. },
  174. /** 目标数据是否全选 */
  175. onChangeToAll(val) {
  176. this.$emit('to_selected_all', val)
  177. this.selected_to_data = this.selected_all_to_data = val ? JSON.parse(JSON.stringify(this.to_data)) : {}
  178. }
  179. },
  180. computed: {
  181. // 左侧菜单名
  182. fromTitle() {
  183. let [text] = this.title
  184. return text
  185. },
  186. // 右侧菜单名
  187. toTitle() {
  188. let [, text] = this.title
  189. return text
  190. },
  191. // 上部按钮名
  192. fromButton() {
  193. if (this.button_text === undefined) {
  194. return
  195. }
  196. let [text] = this.button_text
  197. return text
  198. },
  199. // 下部按钮名
  200. toButton() {
  201. if (this.button_text === undefined) {
  202. return
  203. }
  204. let [, text] = this.button_text
  205. return text
  206. }
  207. },
  208. watch: {
  209. // 左侧 状态监测
  210. from_data(val) {
  211. this.from_disabled = !Object.keys(val).length
  212. if (this.from_disabled) {
  213. this.is_from_selected_all = false
  214. }
  215. },
  216. // 右侧 状态监测
  217. to_data(val) {
  218. this.to_disabled = !Object.keys(val).length
  219. if (this.to_disabled) {
  220. this.is_to_selected_all = false
  221. }
  222. }
  223. }
  224. }
  225. </script>
  226. <style type="text/scss" lang="scss" scoped>
  227. .el-tree {
  228. min-width: 100%;
  229. display: inline-block !important;
  230. }
  231. .transfer {
  232. position: relative;
  233. overflow: hidden;
  234. }
  235. .transfer-left {
  236. position: absolute;
  237. top: 0;
  238. left: 0;
  239. }
  240. .transfer-right {
  241. position: absolute;
  242. top: 0;
  243. right: 0;
  244. }
  245. .transfer-main {
  246. padding: 10px;
  247. height: calc(100% - 41px);
  248. box-sizing: border-box;
  249. overflow: auto;
  250. }
  251. .transfer-left,.transfer-right {
  252. border: 1px solid #ebeef5;
  253. width: 40%;
  254. height: 100%;
  255. box-sizing: border-box;
  256. border-radius: 5px;
  257. vertical-align: middle;
  258. }
  259. .transfer-center {
  260. position: absolute;
  261. top: 50%;
  262. left: 40%;
  263. width: 20%;
  264. transform: translateY(-50%);
  265. text-align: center;
  266. }
  267. .transfer-center-item {
  268. padding: 10px;
  269. overflow: hidden;
  270. }
  271. .transfer-title {
  272. border-bottom: 1px solid #ebeef5;
  273. padding: 0 15px;
  274. height: 40px;
  275. line-height: 40px;
  276. color: #333;
  277. font-size: 16px;
  278. text-align: center;
  279. background-color: #f5f7fa;
  280. }
  281. .list-title {
  282. font-size: 14px;
  283. }
  284. .transfer-title .el-checkbox {
  285. margin-right: 10px;
  286. }
  287. </style>