基於iview-封裝定製化的穿梭框組件

基於iview-封裝定製化的穿梭框組件

PM那邊需求如下:
在這裏插入圖片描述
在這裏插入圖片描述
** 效果圖如下:**
在這裏插入圖片描述

代碼如下:

<template>
    <!-- 穿梭組件 -->
    <div class="transferTpl">
        <div class="left">
            <div class="title">
                <span>{{ leftTitle }}</span>
                <span>({{ checked }}{{ checked != 0 ? '/' + total : '' }})</span>
            </div>
            <div class="content">
                <Tabs size="small">
                    <TabPane v-for="(item, index) in chooseList"
                             :key="item.title"
                             :label="item.title"
                             class="repair-cpu">
                        <Checkbox
                                :indeterminate="item.indeterminate"
                                :value="item.checkAll"
                                :disabled="item.checkAllDisabled"
                                @click.prevent.native="handleCheckAll(index)">全選</Checkbox>
                        <CheckboxGroup v-model="item.checkAllGroup" @on-change="checkAllGroupChange(index)">
                            <Checkbox v-for="(i, j) in item.dataList"
                                      :key="j"
                                      :disabled="i.disabled"
                                      :label="i.name"></Checkbox>
                        </CheckboxGroup>
                    </TabPane>
                </Tabs>
            </div>
            <div class="footer" v-if="isShowDesc">
                <span>{{ descTitle }}</span>
                <Input v-model="desc" :placeholder="descPlace" :disabled="descDisabled" class="desc" />
            </div>
        </div>
        <div class="middle">
            <Button class="move"
                    size="small"
                    :disabled="disabled"
                    @click="handleTransfer"
                    icon="ios-arrow-forward"></Button>
        </div>
        <div class="right">
            <div class="title">
                <span>{{ rightTitle }} ({{ alreadyChoose }})</span>
                <Button v-if="alreadyChoose !== 0" type="text" @click="delAll" style="float: right; background: #f5f5f5;">清空</Button>
            </div>
            <div class="content">
                <div class="header">
                    <span>{{ rightName }}</span>
                    <span>{{ rightDescName }}</span>
                </div>
                <div class="collapse">
                    <Collapse simple accordion value="cpu">
                        <Panel v-for="(item, index) in selectedList" :key="index" :name="item.title">
                            {{ item.title }}{{ item.dataList.length }}<Icon type="md-close" @click.stop="delItem(item)" class="item-total-icon" style="line-height: 36px; margin-right: 10px"></Icon>
                            <div slot="content">
                                <div class="over-blur" v-for="(i, j) in item.dataList">
                                    <span>{{ i.name }}</span>
                                    <span>{{ i.desc }}</span>
                                    <Icon @click="delnum(i)" type="md-close" class="over-blur-icon"></Icon>
                                </div>
                            </div>
                        </Panel>
                    </Collapse>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
    var _lodash = require('lodash');
    export default {
        name: "transferTpl",
        props: [
            'chooseDdataList',  // 待選項  Array
            'leftTitle', // 左側標題
            'isShowDesc',  // 是否顯示描述
            'descTitle', // 描述標題
            'rightTitle', // 右側標題
            'rightName', // 右側 item name
            'rightDescName' // 右側 item-desc name
        ],
        data() {
            return {
                chooseList: this.chooseDdataList,
                disabled: true,  // 按鈕禁用狀態
                desc: '',  // 描述
                descPlace: '',  // 描述placehoder
                descDisabled: true, // 描述禁用狀態
                selectedList: [], // 已選維修部件  已選項
                // selectedList模板
                // selectedList: [
                //     {
                //         title: 'CPU',
                //         dataList: [
                //             {
                //                 name: '',
                //                 desc: ''
                //             }
                //         ]
                //     }
                // ]
            }
        },
        watch: {
            // 監聽已選項
            'chooseList': {
                handler(val) {
                    let arr = [];
                    val.forEach(item => {
                        // 判斷是否只包含禁用
                        if (item.checkAllGroup.length) {
                            item.dataList.forEach(i => {
                                item.checkAllGroup.forEach(j => {
                                    // 只有當按鈕狀態爲可選時纔可輸入描述
                                    if (j === i.name && !i.disabled) {
                                        arr.push(true);
                                    }
                                })
                            })
                        } else {
                            arr.push(false);
                            item.indeterminate = false;
                            item.checkAll = false;
                        }

                        // 修改全選禁用狀態
                        let disabledList = [];
                        item.dataList.forEach(item => {
                            disabledList.push(item.disabled);
                        })
                        if (disabledList.includes(true) && new Set(disabledList).size === 1) {
                            item.checkAllDisabled = true;
                        } else {
                            item.checkAllDisabled = false;
                        }
                    })
                    // 修改描述input禁用狀態
                    if (arr.includes(true)) {
                        this.descDisabled = false;
                    } else {
                        this.descDisabled = true;
                    }
                },
                deep: true
            },
            // 監聽描述信息 - 修改穿梭框按鈕禁用狀態
            'desc': {
                handler(val) {
                    if (val !== '') {
                        this.disabled = false;
                    } else {
                        this.disabled = true;
                    }
                }
            }
        },
        computed: {
            // 已選項
            checked() {
                return (this.handleNum(this.chooseList, 'checkAllGroup') || []).length;
            },
            // 待選項總數
            total() {
                return (this.handleNum(this.chooseList, 'dataList') || []).length;
            },
            // 右側已選
            alreadyChoose() {
                return (this.handleNum(this.selectedList, 'dataList') || []).length;
            }
        },
        create() {
        },
        methods: {
            // 穿梭按鈕事件,渲染右側列表
            handleTransfer() {
                // 處理已選項  先遍歷已選擇數據
                this.chooseList.forEach(obj => {
                    // 如果存在已勾選的item
                    (obj.checkAllGroup || []).forEach(item => {
                        // 判斷右側是否已存在當前類型
                        if (this.selectedList.length) {
                            let titleList = [];
                            this.selectedList.map(num => {
                                // 若存在
                                if (num.title === obj.title) {
                                    let list = [];
                                    num.dataList.forEach(n => {
                                        list.push(n.name);
                                    })
                                    if (!list.includes(item)) {
                                        let objTpl = {
                                            name: item,
                                            desc: this.desc
                                        }
                                        num.dataList.push(objTpl);
                                        // 複選框禁用
                                        obj.dataList.forEach(m => {
                                            if (m.name === item) {
                                                m.disabled = true;
                                            }
                                        })
                                    }
                                }
                                titleList.push(num.title);
                            })
                            // 若右側沒有當前項
                            if (!titleList.includes(obj.title)) {
                                let objTpl = {
                                    title: obj.title,
                                    dataList: []
                                }

                                let snapObj = {
                                    name: item,
                                    desc: this.desc
                                }
                                objTpl.dataList.push(snapObj)
                                this.selectedList.push(objTpl);
                                obj.dataList.forEach(m => {
                                    if (m.name === item) {
                                        m.disabled = true;
                                    }
                                })
                            }
                        } else {
                            //若不存在
                            let objTpl = {
                                title: obj.title,
                                dataList: [
                                    {
                                        name: item,
                                        desc: this.desc
                                    }
                                ]
                            }
                            this.selectedList.push(objTpl);
                            obj.dataList.forEach(m => {
                                if (m.name === item) {
                                    m.disabled = true;
                                }
                            })
                        }
                    })
                });
                this.desc = '';
                this.descDisabled = true;
            },
            // 全選check
            handleCheckAll (key) {
                if (this.chooseList[key].indeterminate) {
                    this.chooseList[key].checkAll = false;
                } else {
                    this.chooseList[key].checkAll = !this.chooseList[key].checkAll;
                }
                this.chooseList[key].indeterminate = false;

                if (this.chooseList[key].checkAll) {
                    let list = [];
                    this.chooseList[key].dataList.forEach(item => {
                        list.push(item.name);
                    })
                    this.chooseList[key].checkAllGroup = list;
                } else {
                    this.chooseList[key].checkAllGroup = [];
                }
            },
            // check某一項
            checkAllGroupChange (key) {
                let data = this.chooseList[key].checkAllGroup;
                if (data.length === this.chooseList[key].dataList.length) {
                    this.chooseList[key].indeterminate = false;
                    this.chooseList[key].checkAll = true;
                } else if (data.length > 0) {
                    this.chooseList[key].indeterminate = true;
                    this.chooseList[key].checkAll = false;
                } else {
                    this.chooseList[key].indeterminate = false;
                    this.chooseList[key].checkAll = false;
                }
            },
            // 刪除全部
            delAll() {
                this.selectedList = [];
                this.chooseList.forEach(item => {
                    item.dataList.forEach(obj => {
                        obj.disabled = false;
                    })
                    item.checkAllGroup = [];
                    item.indeterminate = false;
                })
            },
            // 刪除某一項
            delItem(item) {
                this.selectedList.forEach((obj, index) => {
                    if (item.title === obj.title) {
                        this.selectedList.splice(index, 1);
                    }
                    this.chooseList.forEach(n => {
                        if (n.title === item.title) {
                            n.dataList.forEach(m => {
                                m.disabled = false;
                            })
                            n.checkAllGroup = [];
                            n.indeterminate = false;
                        }

                    })
                })

            },
            // 刪除某一個
            delnum(val) {
                // 刪除已選項
                this.selectedList.forEach((item, k) => {
                    item.dataList.forEach((obj, index) => {
                        if (obj.name === val.name) {
                            item.dataList.splice(index, 1);
                            if (item.dataList.length === 0) {
                                this.selectedList.splice(k, 1);
                            }
                        }
                    })
                })

                // 重置待選項
                this.chooseList.forEach(item => {
                    item.dataList.forEach((obj, index) => {
                        if (obj.name === val.name) {
                            obj.disabled = false;
                        }
                    })
                    item.checkAllGroup.forEach((obj, index) => {
                        if (obj === val.name) {
                            item.checkAllGroup.splice(index, 1); // 取消選中
                            item.checkAll = false; // 取消全選狀態
                            item.indeterminate = true;
                        }
                    })
                })
            },
            // 處理 已選,待選,總數
            handleNum(data, key) {
                let list = [];
                data.forEach(item => {
                    item[key].forEach(obj => {
                        list.push(obj);
                    })
                })
                return list;
            }
        }
    }
</script>

<style lang="less">
    .transferTpl {
        width: 100%;
        display: flex;
        .left,.right {
            width: 418px;
            border: 1px solid #eaeaea;
            .title {
                width: 100%;
                height: 30px;
                line-height: 30px;
                padding-left: 5px;
                background: #f5f5f5;
                span:nth-child(1) {
                    font-weight: 700;
                }
            }
            .content {
                padding: 5px;
                height: 300px;
                /* 選擇維修部件 */
                .repair-cpu {
                    height: 234px;
                    overflow-y: auto;
                    padding: 5px 5px 0 5px;
                    .ivu-checkbox-wrapper {
                        width: 45%;
                        span:nth-child(2) {
                            display: inline-block;
                            width: 85%;
                            white-space: nowrap;
                            text-overflow: ellipsis;
                            overflow: hidden;
                            vertical-align: middle;
                        }
                    }
                }
                /* 已選維修部件 */
                .header {
                    height: 30px;
                    line-height: 30px;
                    border-bottom: 1px solid #eee;
                    span {
                        font-size: 12px;
                        display: inline-block;
                    }
                    span:first-child {
                        width: 100px;
                        margin-left: 36px;
                        display: inline-block;
                        white-space: nowrap;
                        text-overflow: ellipsis;
                        overflow: hidden;
                    }
                    span:last-child {
                        width: 200px;
                        margin-left: 20px;
                        display: inline-block;
                        white-space: nowrap;
                        text-overflow: ellipsis;
                        overflow: hidden;
                    }
                }
                .collapse {
                    height: 260px;
                    overflow-y: auto;
                    overflow-x: hidden;
                    .over-blur {
                        line-height: 24px;
                        span {
                            font-size: 12px;
                            display: inline-block;
                        }
                        span:first-child {
                            width: 100px;
                            margin-left: 10px;
                            display: inline-block;
                            white-space: nowrap;
                            text-overflow: ellipsis;
                            overflow: hidden;
                        }
                        span:nth-child(2) {
                            width: 180px;
                            margin-left: 20px;
                            display: inline-block;
                            white-space: nowrap;
                            text-overflow: ellipsis;
                            overflow: hidden;
                        }
                        .over-blur-icon {
                            float: right;
                            display: inline-block;
                            cursor: pointer;
                            font-size: 14px;
                        }
                    }
                }
                .item-total-icon {
                    color: #999;
                    font-size: 18px;
                    cursor: pointer;
                    float: right;
                    line-height: 38px;
                }
                .ivu-collapse-simple {
                    border: none;
                }
                .ivu-collapse > .ivu-collapse-item {
                    border: none;
                }
                .ivu-collapse > .ivu-collapse-item > .ivu-collapse-header {
                    padding-left: 10px;
                    i {
                        margin-right: 0;
                        line-height: 21px;
                    }
                }
            }
            .footer {
                width: 100%;
                height: 30px;
                line-height: 30px;
                padding-left: 5px;
                background: #f5f5f5;
                .desc {
                    width: 280px;
                    .ivu-input-inner-container input {
                        height: 24px;
                    }
                }
            }
        }
        .middle {
            width: 100px;
            display: flex;
            align-items:center;
            justify-content: center;
            .move {
                border: 1px solid #2b85e4;
                background: #fff;
                width: 60px;
                height: 30px;
            }
            .move:hover {
                background: #e7edf3;
            }
            .move:active {
                background: #c6d8ea;
            }
            .move[disabled] {
                background-color: #cccccc;
                border: 1px solid #cccccc;
            }
        }
        .right {
            width: 418px;
            border: 1px solid #eaeaea;
        }
    }
</style>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章