14_穿梭框决定下拉列表

发布时间 2024-01-08 10:34:32作者: pleaseAnswer

实现效果

需求说明

客服分配设置-客服分组设置

  1. 接待客服:选择客服为穿梭框样式
    • 左侧为系统账号 | 渠道主号下的所有子账号
    • 右侧为被分配到该分组的客服
  2. 个别客服接待上限
    • 可多选客服,可选的范围为【接待客服】中右侧列表里的客服
    • 点击 “+ 添加” 添加一行数据
    • 选项互斥

代码实现

<Form :model="formData">
  <FormItem label="接待客服:" prop="ids">
    <Transfer
      :titles="['所有成员', '接待客服']"
      :data="kefuList"
      :target-keys="formData.ids"
      filterable
      @on-change="onKefuTransfer"
    ></Transfer>
  </FormItem>
  <FormItem label="个别客服接待上限:">
	<div v-for="(item, index) of formData.otherKefuList" :key="index">
	  <Select v-model="item.kf_id" placeholder="请选择客服" @on-change="getOtherKefuList">
		<Option
		  v-for="(optItem, optIndex) in item.options"
		  :value="optItem.kf_id"
		  :key="optIndex"
		>{{ optItem.admin_alias }}</Option>
	  </Select>
	  <InputNumber :min="1" v-model="item.num" class="mx-5" />
	  <Icon type="ios-close-circle" :size="22" style="cursor: pointer" color="#ed4014" @click="onRemoveOneOtherKefu(index)" />
    </div>
    <div style="color: #2c8cf0; cursor: pointer;" @click="onAddOtherKefu">
	  <Icon type="ios-add-circle" :size="20" />
	  <span class="px-5">添加</span>
    </div>
  </FormItem>
</Form>
props: {
  kefuList: Array
},
data() {
  return {
    formData: {
      // ...
      ids: [],
      kefuList: [], // 客服接待
      otherKefuList: [], // 个别客服接待 数据列表
      optsList: [] // 个别客服接待所有 options 组合的数组
    }
  }
}
// methods
// 初始化获取表单数据
async getEditInfo(id) {
  const { data } = await this.$axios(this.apis.edit, { id });
  const { customer_data, other_customer_data } = data;

  customer_data.length && (this.formData.ids = customer_data.map(item => item.kf_id));
  this.formData.kefuList = customer_data;
  this.formData.otherKefuList = other_customer_data;
  // 初始化 个别客服接待 列表
  this.getOtherKefuList();
}

// 穿梭框数据变化时触发
onKefuTransfer(keys, direction, moveKeys) {
  this.formData.ids = keys;
  const kefuListFilter = this.kefuList.filter(item => {
    return keys.includes(item.key);
  });
  const kefuList = kefuListFilter.map(item => ({
    kf_id: item.key,
    admin_alias: item.label
  }));
    
  this.formData.kefuList = kefuList; // 更新 kefuList
  this.formData.optsList = [kefuList]; // 初始化 optsList
    
  // 更新 个别客服接待 列表
  this.getOtherKefuList();
  
  // 处理下拉框列表
  if (direction === 'left') {
    const otherKefuList = this.formData.otherKefuList;
    const removeList = [];
    otherKefuList.map((item, index) => {
      if (moveKeys.includes(item.kf_id) || item.kf_id === null) {
        removeList.push(index);
      }
    });
    removeList.reverse().map(index => this.onRemoveOneOtherKefu(index));
  }
}

// 处理 个别客服接待 数据列表 otherKefuList & 所有 options 组合的数组 optsList
getOtherKefuList() {
  const { kefuList, otherKefuList } = this.formData;
  const list = [kefuList];
  
  // options 需要逐项递减,使用 optsList 存储所有的 options 列表
  otherKefuList.forEach((item, index) => {
    this.$set(item, 'options', list[index]);
    const options = deepClone(list[index]).filter(option => item.kf_id !== option.kf_id);
    list.push(options);
  })
  this.formData.optsList = list;
}

// 移除
onRemoveOneOtherKefu(index) {
  this.formData.otherKefuList.splice(index, 1);
  this.getOtherKefuList();
}
// 新增
onAddOtherKefu() {
  const { optsList, kefuList, otherKefuList } = this.formData;
  const len = kefuList.length;
  if(len === 0) {
    this.$Message.warning('请先选择接待客服');
    return;
  }
  if (kefuList.length === otherKefuList.length) {
    this.$Message.warning('接待客服上限设置数已达最大值');
    return;
  }
  const options = deepClone(optsList[optsList.length - 1]);
  this.formData.otherKefuList.push({
    options,
    kf_id: null,
    num: 1
  });
}

async onSave() {
  const data = this.dealParams();
  await this.$asyncFun(this.apis.save, { method: 'POST', data });
}

// 处理入参
dealParams() {
  const datas = {};
  const { num, kefuList, otherKefuList } = this.formData;
  // 组内客服接待上限 列表
  const list = kefuList.map(item => {
    return {
      id: item.kf_id,
      num
    };
  });
  // 个别客服接待上限 列表
  const otherList = otherKefuList.map(item => {
    return {
      id: item.kf_id,
      num: item.num
    };
  });
  // 去重,若重复保留个别客服设置项
  const map = new Map();
  const concatList = [...otherList, ...list].filter(item => {
    return !map.has(item.id) && map.set(item.id, 1);
  });
  const resArr = concatList
    .filter(item => item.id) // 过滤空白数据项
    .map(item => {
       return `${item.id}_${item.num}`;
     });
  return datas;
},