<template>
  <a-tabs
    v-model="actionId"
    :class="{
      [$style['one-tab']]: taskCandidateInfos.length === 1,
      [$style['single-click-mode']]: !dblClickTransfer,
    }"
  >
    <a-tab-pane
      v-for="taskCandidateInfo in taskCandidateInfos"
      :key="taskCandidateInfo.actionId"
      :tab="taskCandidateInfo.actionName"
    >
      <a-tabs
        tab-position="left"
        :class="{ [$style['tab-left']]: true, [$style['one-tab']]: isOneTab(taskCandidateInfo) }"
      >
        <!-- 按部门选 -->
        <a-tab-pane v-if="taskCandidateInfo.group.rootCandidateInfo.length > 0" key="group">
          <span slot="tab"> <a-icon type="apartment" /><br />选部门</span>
          <a-input-search
            v-model="searchValue"
            size="large"
            placeholder="请输入关键字搜索"
            :class="$style.search"
            allow-clear
            @search="onSearch(taskCandidateInfo)"
          />
          <a-transfer
            :selected-keys="taskCandidateInfo.selectedCodes"
            :show-select-all="taskCandidateInfo.multi"
            :data-source="groupCompute"
            :lazy="false"
            :class="{
              [$style.grouptransfer]: true,
              [$style.single]: false,
              [$style.nodep]: !groupCheckable,
            }"
            :target-keys="taskCandidateInfo.targetKeys"
            :render="(item) => renderItem(item, taskCandidateInfo.targetKeys, taskCandidateInfo)"
            @change="
              (nextKeys, direction, moveKeys) => {
                handleChange(
                  nextKeys,
                  direction,
                  moveKeys,
                  taskCandidateInfo.targetKeys,
                  taskCandidateInfo
                ),
                  handleTreeData(
                    taskCandidateInfo.group.rootCandidateInfo,
                    taskCandidateInfo.targetKeys
                  )
              }
            "
            @selectChange="
              (sourceSelectedKeys, targetSelectedKeys) =>
                handleSelectChange(sourceSelectedKeys, targetSelectedKeys, taskCandidateInfo)
            "
          >
            <a-button
              v-if="props.direction === 'right'"
              slot="footer"
              slot-scope="props"
              size="small"
              icon="sd-trash2"
              type="link"
              @click="
                handleChange(
                  null,
                  null,
                  [...taskCandidateInfo.targetKeys],
                  taskCandidateInfo.targetKeys,
                  taskCandidateInfo
                )
              "
            >
            </a-button>
            <template v-slot:children="{ props: { direction, selectedKeys }, on: { itemSelect } }">
              <div
                v-if="direction === 'left'"
                :class="{ [$style.source]: true, [$style['user-check-able']]: !userCheckable }"
              >
                <a-card size="small" bordered>
                  <div slot="extra">
                    <a-checkbox
                      v-if="taskCandidateInfo.multi && groupCheckable"
                      :checked="taskCandidateInfo.groupCheckAll"
                      :indeterminate="taskCandidateInfo.groupIndeterminate"
                      @change="(e) => onCheckAllChange(e, taskCandidateInfo, 'group')"
                    /><span>
                      {{
                        taskCandidateInfo.groupCheckedNum
                          ? taskCandidateInfo.groupCheckedNum + '/'
                          : ''
                      }}{{ taskCandidateInfo.groupCheckedNumAll }} 项
                    </span>
                    <a-button
                      v-if="!dblClickTransfer && groupCheckable && taskCandidateInfo.multi"
                      type="link"
                      icon="double-right"
                      :class="$style.allbtn"
                      @click="
                        handleChange(
                          null,
                          null,
                          groupUpKeys,
                          taskCandidateInfo.targetKeys,
                          taskCandidateInfo
                        )
                      "
                    />
                  </div>
                  <a-tree
                    v-if="direction === 'left'"
                    :class="{
                      [$style.allrootisleaf]:
                        taskCandidateInfo.group.rootCandidateInfo.findIndex(
                          (item) => !item.isLeaf
                        ) === -1,
                    }"
                    :checkable="groupCheckable"
                    show-icon
                    selectable
                    :check-strictly="true"
                    :tree-data="groupUp"
                    :expanded-keys.sync="taskCandidateInfo.expandedKeys"
                    :checked-keys="[...selectedKeys, ...taskCandidateInfo.targetKeys]"
                    :load-data="
                      (treeNode) =>
                        onLoadData(
                          treeNode,
                          taskCandidateInfo,
                          taskCandidateInfo.group.rootCandidateInfo,
                          taskCandidateInfo.group.transferDataSource
                        )
                    "
                    :selected-keys="taskCandidateInfo.selectedNodeInfo.selectedKeys"
                    @check="(kyes, info) => onCheckUser(kyes, info, taskCandidateInfo, itemSelect)"
                    @dblclick="
                      (e, treeNode) => {
                        if (groupCheckable && treeNode.dataRef.checkable !== false) {
                          handleChange(
                            null,
                            'right',
                            [treeNode.dataRef.key],
                            taskCandidateInfo.targetKeys,
                            taskCandidateInfo
                          )
                        }
                      }
                    "
                    @select="
                      (selectedKeys, treeNode) => {
                        if (
                          treeNode.node.dataRef.checkable &&
                          !userCheckable &&
                          !dblClickTransfer
                        ) {
                          itemSelect(selectedKeys[0], true)
                          return
                        }
                        onSelect(selectedKeys, treeNode.node.dataRef, taskCandidateInfo)
                      }
                    "
                  >
                    <a-icon slot="G" type="apartment" :class="$style.theme" />
                    <a-icon slot="U" type="user" :class="$style.theme" />
                  </a-tree>
                </a-card>
                <a-card v-show="userCheckable" size="small" bordered>
                  <div slot="extra">
                    <a-checkbox
                      v-if="taskCandidateInfo.multi"
                      :checked="taskCandidateInfo.userCheckAll"
                      :indeterminate="taskCandidateInfo.userIndeterminate"
                      @change="(e) => onCheckAllChange(e, taskCandidateInfo, 'user')"
                    /><span>
                      {{
                        taskCandidateInfo.userCheckedNum
                          ? taskCandidateInfo.userCheckedNum + '/'
                          : ''
                      }}{{ taskCandidateInfo.userCheckedNumAll || 0 }} 项
                    </span>
                    <a-button
                      v-if="!dblClickTransfer && taskCandidateInfo.multi"
                      type="link"
                      icon="double-right"
                      :class="$style.allbtn"
                      @click="
                        handleChange(
                          null,
                          null,
                          groupDown.map((item) => item.key),
                          taskCandidateInfo.targetKeys,
                          taskCandidateInfo
                        )
                      "
                    />
                  </div>

                  <sd-picker-source-list
                    :key="sdGet(taskCandidateInfo, 'selectedNodeInfo?.selectedKeys?.[0]')"
                    option-value="key"
                    :load-list-data="
                      () => loadList(taskCandidateInfo.selectedNodeInfo, taskCandidateInfo)
                    "
                    :data-source="groupDown || []"
                    :target-keys="taskCandidateInfo.targetKeys"
                    :update-data-source="() => []"
                    :update-show-search="() => []"
                    :selected-keys="selectedKeys"
                    :item-select="itemSelect"
                    :render="renderList"
                    :item-dbl-click="
                      (e, key) =>
                        handleChange(
                          null,
                          'right',
                          [key],
                          taskCandidateInfo.targetKeys,
                          taskCandidateInfo
                        )
                    "
                  ></sd-picker-source-list>
                </a-card>
              </div>
              <pickerListRight
                v-if="direction === 'right'"
                option-value="key"
                :data-source="taskCandidateInfo.targetNodes"
                :target-keys="taskCandidateInfo.targetKeys"
                :selected-keys="selectedKeys"
                :item-select="itemSelect"
                :render="renderList"
                :item-dbl-click="
                  (e, key) =>
                    handleChange(
                      null,
                      'left',
                      [key],
                      taskCandidateInfo.targetKeys,
                      taskCandidateInfo
                    )
                "
                @updateTargetKeys="
                  (targetKeys) => {
                    updateTargetKeys(targetKeys, taskCandidateInfo)
                  }
                "
              />
            </template>
          </a-transfer>
        </a-tab-pane>
        <!-- 只选人员 -->
        <a-tab-pane v-if="taskCandidateInfo.user.rootCandidateInfo.length > 0" key="user">
          <span slot="tab"> <a-icon type="user" /><br />人员列表</span>
          <a-transfer
            :show-search="true"
            :filter-option="filterOption"
            :show-select-all="taskCandidateInfo.multi"
            :selected-keys="taskCandidateInfo.selectedCodes"
            :class="{ [$style.usertransfer]: true, [$style.single]: false }"
            :data-source="userCompute"
            :target-keys="taskCandidateInfo.targetKeys"
            :render="(item) => renderItem(item, taskCandidateInfo.targetKeys, taskCandidateInfo)"
            @change="
              (nextKeys, direction, moveKeys) =>
                handleChange(
                  nextKeys,
                  direction,
                  moveKeys,
                  taskCandidateInfo.targetKeys,
                  taskCandidateInfo
                )
            "
            @selectChange="
              (sourceSelectedKeys, targetSelectedKeys) =>
                handleSelectChange(sourceSelectedKeys, targetSelectedKeys, taskCandidateInfo)
            "
          >
            <a-button
              v-if="!dblClickTransfer && taskCandidateInfo.multi"
              slot="footer"
              slot-scope="props"
              :icon="props.direction === 'right' ? 'sd-trash2' : 'double-right'"
              type="link"
              @click="
                () => {
                  if (props.direction === 'right') {
                    handleChange(
                      null,
                      null,
                      [...taskCandidateInfo.targetKeys],
                      taskCandidateInfo.targetKeys,
                      taskCandidateInfo
                    )
                  } else {
                    handleChange(
                      null,
                      null,
                      userCompute
                        .filter(
                          (item) => !taskCandidateInfo.targetKeys.some((key) => item.key === key)
                        )
                        .map((item) => item.key),
                      taskCandidateInfo.targetKeys,
                      taskCandidateInfo
                    )
                  }
                }
              "
            />
            <template v-slot:children="{ props: { direction, selectedKeys }, on: { itemSelect } }">
              <pickerListRight
                v-if="direction === 'right'"
                option-value="key"
                :data-source="taskCandidateInfo.targetNodes"
                :target-keys="taskCandidateInfo.targetKeys"
                :selected-keys="selectedKeys"
                :item-select="itemSelect"
                :render="renderList"
                :item-dbl-click="
                  (e, key) =>
                    handleChange(
                      null,
                      'left',
                      [key],
                      taskCandidateInfo.targetKeys,
                      taskCandidateInfo
                    )
                "
                @updateTargetKeys="
                  (targetKeys) => {
                    updateTargetKeys(targetKeys, taskCandidateInfo)
                  }
                "
              />
            </template>
          </a-transfer>
        </a-tab-pane>
      </a-tabs>
    </a-tab-pane>
  </a-tabs>
</template>

<script>
// 树的穿梭框
import cloneDeep from 'lodash.clonedeep'
import FlowService from '@/webflow/flow-service'
import sdPickerSourceList from '@/common/components/sd-picker-source-list'
import sdUserinfoCard from '@/common/components/sd-user-item/sd-userinfo-card'
import config from '@/config'
import pickerListRight from '@/common/components/sd-picker/sd-picker-list-right.vue'
import components from './_import-components/sd-next-node-user-import'
const flatten = function(list = [], transferSource) {
  if (!transferSource) return
  list.forEach((item) => {
    const { attrs, code, name, type, title, key, checkable } = item
    transferSource.push({ attrs, code, name, type, title, key, checkable })
    flatten(item.children || [], transferSource)
  })
}
export default {
  name: 'SdNextNodeCandidate',
  components: {
    ...components,
    sdPickerSourceList,
    pickerListRight,
  },
  props: {
    value: {
      type: Array,
      default: () => {},
    },
    flowData: {
      type: Object,
      default: () => ({}),
    },
    /**
     * @ignore
     */
    dblClickTransfer: {
      type: Boolean,
      default: () => config.common.picker.dblClickTransfer,
    },
  },
  data() {
    return {
      activeTab: undefined,
      taskCandidateInfos: [],
      selectedNodeInfo: {},
      actionId: this.value[0].actionId,
      searchValue: '',
      searchResult: undefined, // 本次查询的结果
    }
  },

  computed: {
    userCompute() {
      // 这个是相对于不同页签的选人，不是上下栏里的选人
      const taskCandidateInfo = this.taskCandidateInfos.find(
        (item) => item.actionId === this.actionId
      )
      const grouptabnodes = taskCandidateInfo.targetNodes.filter((node) => {
        return !taskCandidateInfo.user.rootCandidateInfo.some((item) => item.key === node.key)
      })
      return [...grouptabnodes, ...taskCandidateInfo.user.rootCandidateInfo]
    },
    groupCompute() {
      // 这个是相对于不同页签的选组或人数据源，包含上面的组织下面的人
      const taskCandidateInfo = this.taskCandidateInfos.find(
        (item) => item.actionId === this.actionId
      )
      if (this.searchResult) {
        // 从搜索结果取数据源
        return [
          ...taskCandidateInfo.targetNodes.filter((node) => {
            return !this.searchResult.some((item) => item.key === node.key)
          }),
          ...this.searchResult,
        ]
      } else {
        return [
          ...taskCandidateInfo.targetNodes.filter((node) => {
            return !taskCandidateInfo.group.transferDataSource.some((item) => item.key === node.key)
          }),
          ...taskCandidateInfo.group.transferDataSource.filter((item) => item.checkable !== false),
        ]
      }
    },
    groupUp() {
      const taskCandidateInfo = this.taskCandidateInfos.find(
        (item) => item.actionId === this.actionId
      )
      if (this.searchResult) {
        return JSON.parse(JSON.stringify(this.searchResult))
          .filter((item) => item.type !== 'User')
          .map((item) => {
            item.disabled = taskCandidateInfo.targetKeys.includes(item.key)
            return item
          })
      } else {
        return taskCandidateInfo.group.rootCandidateInfo
      }
    },
    groupUpKeys() {
      // 没有选中的树的key
      const taskCandidateInfo = this.taskCandidateInfos.find(
        (item) => item.actionId === this.actionId
      )
      return this.groupCompute
        .filter((item) => !this.groupDown?.find((user) => user.key === item.key))
        .filter((item) => !taskCandidateInfo.targetKeys.includes(item.key))
        .map((item) => item.key)
    },
    groupDown() {
      const taskCandidateInfo = this.taskCandidateInfos.find(
        (item) => item.actionId === this.actionId
      )
      if (this.searchResult) {
        return this.searchResult.filter(
          (item) => item.type === 'User' && !taskCandidateInfo.targetKeys.includes(item.key)
        )
      } else {
        return taskCandidateInfo.group.candidates.filter(
          (item) => !taskCandidateInfo.targetKeys.includes(item.key)
        )
      }
    },
    groupCheckable() {
      const taskCandidateInfo = this.taskCandidateInfos.find(
        (item) => item.actionId === this.actionId
      )
      return taskCandidateInfo?.props?.deptSelectEnable === true
    },
    userCheckable() {
      const taskCandidateInfo = this.taskCandidateInfos.find(
        (item) => item.actionId === this.actionId
      )
      return taskCandidateInfo?.props?.userSelectDisable !== true
    },
  },
  created() {
    // 变量后面改成驼峰的
    this.value.forEach((candidateInfo) => {
      const rootnodes = candidateInfo.rootCandidateInfo
      // 子环节获取下一环节时需要根节点信息,作为属性一代代传下去
      rootnodes.forEach((item) => (item.rootkey = item.key))
      candidateInfo.expandedKeys = [rootnodes[0].key] // 展开第一个根节点
      // 指定范围的人员
      candidateInfo.user = {}
      candidateInfo.user.rootCandidateInfo = rootnodes.filter((item) => item.type === 'User')
      // 直接选部门用
      candidateInfo.group = {}
      candidateInfo.group.rootCandidateInfo = rootnodes.filter((item) => item.type !== 'User')
      candidateInfo.group.transferDataSource = JSON.parse(
        // 初始化穿梭框
        JSON.stringify(rootnodes)
      )
      candidateInfo.group.candidates = []
      candidateInfo.targetKeys =
        candidateInfo.candidates?.map((candidates) => {
          candidates.title = candidates.name // 穿梭框必须key,title
          candidates.key = candidates.code
          return candidates.code
        }) || []
      candidateInfo.targetNodes = candidateInfo.candidates || []
      candidateInfo.selectedCodes = [] // 两个选中的值
      candidateInfo.selectedNodeInfo = { selectedKeys: [] }
      if (
        candidateInfo.group.rootCandidateInfo[0] &&
        candidateInfo?.props?.userSelectDisable !== true
      ) {
        candidateInfo.selectedNodeInfo = {
          selectedKeys: [candidateInfo.group.rootCandidateInfo[0].key],
          dataRef: candidateInfo.group.rootCandidateInfo[0],
        }
      }
    })
    this.taskCandidateInfos = JSON.parse(JSON.stringify(this.value))
    this.$watch(
      () => {
        return this.taskCandidateInfos.find((item) => item.actionId === this.actionId).targetKeys
      },
      () => {
        // 记录选中的节点
        const taskCandidateInfo = this.taskCandidateInfos.find(
          (item) => item.actionId === this.actionId
        )
        if (!taskCandidateInfo?.targetKeys?.length) {
          taskCandidateInfo.targetNodes = []
        } else {
          taskCandidateInfo.targetNodes = taskCandidateInfo.targetKeys.map((code) => {
            return [
              ...this.userCompute,
              ...this.groupCompute,
              ...(taskCandidateInfo.targetNodes || []),
            ].find((item) => item.key === code)
          })
        }
      }
    )
    this.setAllCheckState(this.taskCandidateInfos[0])
  },
  inject: {
    webflow: { default: () => ({}) },
  },
  methods: {
    onSearch(taskCandidateInfo) {
      if (this.searchValue) {
        this.flowData.inputs = this.webflow.getBackendValues()
        FlowService.searchCandidates(
          this.searchValue,
          this.flowData,
          taskCandidateInfo.actionId,
          taskCandidateInfo.rootCandidateInfo[0] // 查询随便传个跟节，为了获取节点的attr属性
        ).then((data) => {
          this.searchResult = data
          this.setAllCheckState(taskCandidateInfo)
        })
      } else {
        this.searchResult = undefined
        this.setAllCheckState(taskCandidateInfo)
      }
    },
    onCheckAllChange(e, taskCandidateInfo, type) {
      let nodes = this.groupDown
      if (type === 'group') {
        // 过滤出非人员节点
        nodes = this.groupCompute.filter(
          (item) => !this.groupDown?.find((user) => user.key === item.key)
        )
      }
      const keys = nodes // 过滤出未选中的
        .filter((item) => !taskCandidateInfo.targetKeys.includes(item.key))
        .map((item) => item.key)
      if (e.target.checked) {
        // 全选加到selectedCodes里面去
        taskCandidateInfo.selectedCodes = [...new Set(taskCandidateInfo.selectedCodes.concat(keys))]
      } else {
        taskCandidateInfo.selectedCodes = taskCandidateInfo.selectedCodes.filter(
          (key) => !keys.includes(key)
        )
      }
      this.setAllCheckState(taskCandidateInfo)
    },
    isOneTab(candidateInfo) {
      // 是不是只有一个taba
      return (
        ['group', 'user'].filter((item) => {
          return candidateInfo[item].rootCandidateInfo.length
        }).length === 1
      )
    },
    handleSelectChange(sourceSelectedKeys, targetSelectedKeys, taskCandidateInfo) {
      if (!this.dblClickTransfer) {
        this.handleChange(
          null,
          null,
          [...sourceSelectedKeys, ...targetSelectedKeys],
          taskCandidateInfo.targetKeys,
          taskCandidateInfo
        )
        return
      }
      if (!taskCandidateInfo.multi) {
        if (sourceSelectedKeys.length > 1) {
          sourceSelectedKeys.splice(0, 1)
        }
      }
      taskCandidateInfo.selectedCodes = [...sourceSelectedKeys, ...targetSelectedKeys]
      // 设置全选状态
      this.setAllCheckState(taskCandidateInfo)
      this.$nextTick(() => {
        this.$emit('input', this.taskCandidateInfos)
      })
    },
    setAllCheckState(taskCandidateInfo) {
      // 过滤出非人员节点和未选中到右边的待选部门节点,控制全选状态
      const keys = this.groupUpKeys
      // 找到keys在selectedCodes个数
      const num = keys.filter((key) => taskCandidateInfo.selectedCodes?.includes(key)).length
      taskCandidateInfo.groupCheckAll = !!(num && num === keys.length) // 拆开的部门列表全选状态
      taskCandidateInfo.groupIndeterminate = !!(num && num < keys.length)
      taskCandidateInfo.groupCheckedNum = num
      taskCandidateInfo.groupCheckedNumAll = keys.length
      // 过滤出为选人员节点，控制全选状态
      const keys2 = this.groupDown
        ?.filter((item) => !taskCandidateInfo.targetKeys.includes(item.key))
        .map((item) => item.key)
      // 找到keys在selectedCodes个数
      if (!keys2) return
      const num2 = keys2?.filter((key) => taskCandidateInfo.selectedCodes?.includes(key)).length
      taskCandidateInfo.userCheckAll = num2 === keys2.length && num2 !== 0 // 拆开的部门列表全选状态
      taskCandidateInfo.userIndeterminate = !!(num2 && num2 < keys2.length)
      taskCandidateInfo.userCheckedNum = num2
      taskCandidateInfo.userCheckedNumAll = keys2.length
      // 不再数据源里的选中的key都去掉，否则选中状态不对
      taskCandidateInfo.selectedCodes = taskCandidateInfo.selectedCodes.filter((key) =>
        [...this.userCompute, ...this.groupCompute].map((item) => item.key).includes(key)
      )
    },
    renderItem(item, targetkeys, candidateInfo) {
      const customLabel = (
        <span>
          <span
            class='custom-item'
            vOn:dblclick={() =>
              this.handleChange(null, null, [item.key], targetkeys, candidateInfo)
            }
          >
            {item.title}
          </span>
          {item.type === 'User' ? <sdUserinfoCard account={item.code} /> : ''}
        </span>
      )
      return {
        label: customLabel, // for displayed item
        value: item.title, // for title and filter matching
      }
    },
    renderList(item) {
      return (
        <span>
          <span class='custom-item'>{item.title}</span>
          {item.type === 'User' ? <sdUserinfoCard account={item.code} /> : ''}
        </span>
      )
    },
    onCheckUser(checkedKeys, info, candidateInfo, itemSelect) {
      // 树的选人
      // 组件的逻辑是，通过树的选中状态-》控制穿梭框source的选中状态-》又控制树的选择状态
      // checkedKeys是树的选中状态，用它修改穿梭框的选中状态，反过来又自动更改了树的选中状态
      const { eventKey } = info.node
      itemSelect(eventKey, checkedKeys.checked.indexOf(eventKey) !== -1)
    },
    onLoadData(treeNode, taskCandidateInfo, treeData, transferSource) {
      if (treeNode.dataRef.children) {
        return Promise.resolve()
      }
      const rootkey = treeNode.dataRef.rootkey
      // 找到根节点
      const operator = taskCandidateInfo.rootCandidateInfo.find((item) => item.key === rootkey)
      return FlowService.childNodes(
        treeNode.dataRef,
        operator,
        this.flowData,
        taskCandidateInfo.actionId,
        'Group'
      ).then((data) => {
        const getExpanedKey = function(data) {
          data.forEach((item) => {
            if (item.attrs.we_selected === 'true') {
              // 设置默认选中
              taskCandidateInfo.selectedNodeInfo = {
                selectedKeys: [item.key],
                dataRef: item,
              }
            }
            if (item.attrs.we_expanded === 'true') {
              taskCandidateInfo.expandedKeys.push(item.key)
            }
            getExpanedKey(item.children || [])
          })
        }
        getExpanedKey(data)
        treeNode.dataRef.children = data
        const temp = cloneDeep(treeData)
        treeData.splice(0, treeData.length) // 刷新树对象原对象，不要修改指向
        temp.forEach((key) => treeData.push(key))
        if (transferSource) {
          transferSource.splice(0, transferSource.length)
        }
        // 树更新后需要加上人的
        taskCandidateInfo.group.candidates?.forEach((item) => {
          transferSource.push(item)
        })
        flatten([...treeData], transferSource)
        this.setAllCheckState(taskCandidateInfo)
      })
    },
    handleTreeData(treeSource, targetKeys) {
      // 被选中的禁用掉，不要重复选
      treeSource.forEach((item) => {
        item.disabled = targetKeys.includes(item.key)
        if (item.children) this.handleTreeData(item.children, targetKeys)
      })
      return treeSource
    },
    onSelect(selectedKeys, dataRef, taskCandidateInfo) {
      if (selectedKeys.length === 0) return // 兼容再次点击已选中的selectedKeys为空
      taskCandidateInfo.selectedNodeInfo = {
        selectedKeys,
        dataRef,
      }
    },
    loadList({ selectedKeys, dataRef } = {}, taskCandidateInfo) {
      if (!selectedKeys || selectedKeys?.length === 0) return // 兼容再次点击已选中的selectedKeys为空
      taskCandidateInfo.group.selectedkeys = selectedKeys
      const rootkey = dataRef.rootkey
      // 找到根节点
      let operator = taskCandidateInfo.rootCandidateInfo.find((item) => item.key === rootkey)
      if (!operator) {
        // 如果没有找到根节点，就取第一个根节点，例如搜索的时候
        operator = taskCandidateInfo.rootCandidateInfo[0]
      }
      return FlowService.childNodes(
        dataRef,
        operator,
        this.flowData,
        taskCandidateInfo.actionId
      ).then((data) => {
        // 过滤出人
        data = data.filter((item) => item.type === 'User')
        taskCandidateInfo.group.candidates = data
        // 把部门和人合并到一个数据源
        taskCandidateInfo.group.transferDataSource.splice(0, 9999)
        flatten(
          [...taskCandidateInfo.group.rootCandidateInfo, ...taskCandidateInfo.group.candidates],
          taskCandidateInfo.group.transferDataSource
        )
        if (this.searchResult) {
          // 当搜出部门后，点击部门时列出部门的人，所以索性直接修改查询后的结果触发下compute
          this.searchResult = [...this.groupUp, ...data]
        }
        this.setAllCheckState(taskCandidateInfo)
      })
    },
    handleChange(nextTargetKeys, direction, moveKeys, targetkeys, candidateInfo) {
      if (!direction) {
        direction = 'right' // 如果没有设置方向，自己判断
        if (targetkeys.includes(moveKeys[0])) {
          // 如果包含则是向左
          direction = 'left'
        }
      }
      // targetkeys必须是原对象修改，不能指向其他对象
      if (direction === 'right') {
        if (!candidateInfo.multi) {
          // 如果是单选其他类型已选的都清掉，先这么搞
          targetkeys.splice(0, targetkeys.length)
        }
        moveKeys.forEach((key) => targetkeys.push(key)) // 从左到右加
      } else {
        if (nextTargetKeys) {
          targetkeys.splice(0, targetkeys.length) // 从右到左，直接把nextTargetKeys给targetkeys
          nextTargetKeys.forEach((key) => targetkeys.push(key))
        } else {
          const keys = [...targetkeys]
          targetkeys.splice(0, targetkeys.length)
          keys.filter((key) => !moveKeys.includes(key)).forEach((key) => targetkeys.push(key))
        }
      }
      // 不管是从哪选了，是单选就把部门树的状态更新下
      this.handleTreeData(candidateInfo.group.rootCandidateInfo, candidateInfo.targetKeys)
      this.$nextTick(() => {
        this.$emit('input', this.taskCandidateInfos)
        this.setAllCheckState(this.taskCandidateInfos[0])
      })
    },
    filterOption(inputValue, option) {
      return (
        inputValue === undefined ||
        option.code?.indexOf(inputValue) > -1 ||
        option.name?.indexOf(inputValue) > -1 ||
        option.attrs?.pinyin?.indexOf(inputValue) > -1
      )
    },
    updateTargetKeys(targetKeys, taskCandidateInfo) {
      taskCandidateInfo.targetKeys = targetKeys
      this.$nextTick(() => {
        this.$emit('input', this.taskCandidateInfos)
      })
    },
  },
}
</script>

<style module lang="scss">
@use '@/common/design' as *;
.tab-left {
  :global(.ant-tabs-left-bar .ant-tabs-tab) {
    padding: 8px 15px 8px 0;
    text-align: center;
    i {
      font-size: 1.6em;
    }
  }
  :global(.ant-tabs-nav .ant-tabs-tab .anticon) {
    margin-right: 0;
  }
  :global(.ant-transfer-list-footer) {
    top: 7px;
    right: 8px;
    bottom: auto;
    left: auto;
    width: auto;
    border-top: none;
  }
}
div.grouptransfer {
  &:not(.nodep) {
    :global(.ant-transfer-list):first-child {
      max-width: 408px;
    }
  }
  :global(.ant-transfer-list):first-child {
    padding: 0;
    :global(.ant-transfer-list-header) {
      display: none;
    }

    border: none;
  }

  :global(.ant-transfer-list:last-child) {
    width: 350px;
    height: 580px;
    :global(.ant-transfer-list-body) {
      overflow-y: auto;
      :global(.ant-transfer-list-body-customize-wrapper) {
        padding: 0;
      }
    }
  }
  :global(.custom-item) {
    display: inline-block;
    width: calc(100% - 50px);
    min-width: 120px;
    white-space: normal;
    vertical-align: top;
  }
  :global(.icon_sd-userinfo-card_common) {
    display: none;
  }
  :global(.ant-transfer-list-content-item:not(.ant-transfer-list-content-item-disabled):hover) {
    a {
      display: inline;
    }
  }
  :global(.ant-transfer-list-with-footer) {
    padding-bottom: 0;
  }
  :global(.ant-tree-treenode-disabled) {
    cursor: not-allowed;
    > span {
      pointer-events: none;
    }
  }
}
.grouptransfer.single,
.usertransfer.single {
  :global(.ant-transfer-operation),
  :global(.ant-transfer-list):last-child {
    display: none;
  }
  .source {
    display: flex;
    justify-content: space-evenly;
    :global(.ant-card-body) {
      height: 550px;
    }
  }
}
.usertransfer {
  display: flex;
  :global(.ant-transfer-list) {
    &:first-child {
      ul {
        height: calc(100% - 44px);
      }
    }

    flex: 1;
    height: 584px;
  }
  :global(.ant-transfer-operation) {
    flex: none;
    align-self: center;
  }
  :global(.custom-item) {
    display: inline-block;
    width: calc(100% - 50px);
    min-width: 120px;
    white-space: normal;
    vertical-align: top;
  }
  a {
    display: none;
  }
  :global(.ant-transfer-list-content-item:not(.ant-transfer-list-content-item-disabled):hover) {
    a {
      display: inline;
    }
  }

  > div:last-child {
    :global(.ant-transfer-list-body-search-wrapper) {
      display: none;
    }
  }
}
.role {
  // 角色也用树，只不过是一级的树，去掉角色前面的折叠图标占位
  :global(.ant-tree li span.ant-tree-switcher) {
    display: none;
  }
}

.allrootisleaf > li {
  :global(.ant-tree-switcher:empty) {
    display: none;
  }
  :global(span.ant-tree-checkbox) {
    padding-left: 10px;
  }
}
.one-tab {
  > [role='tablist'] {
    display: none;
  }
  :global(.ant-tabs .ant-tabs-left-content) {
    padding-left: 0;
    border-left: none;
  }
  .grouptransfer.nodep .source {
    width: 520px;
    > div {
      width: 250px;
    }
  }
}
.source {
  :global(.ant-card) {
    min-width: 340px;
    :global(.ant-card-head) {
      height: 39px;
    }
    :global(.ant-card-extra) {
      width: 100%;
      margin-left: inherit;
    }
    :global(.ant-card-body) {
      height: 250px;
      padding: 0;
      overflow: auto;
    }
  }
}
.source.user-check-able {
  :global(.ant-card) {
    :global(.ant-card-body) {
      height: 540px;
    }
  }
}
.grouptransfer.nodep {
  :global(.ant-card-body) {
    height: 360px;
  }
  :global(.ant-transfer-list:last-child) {
    width: 266px;
    height: 400px;
  }
  .source {
    display: flex;
    justify-content: space-between;
    width: 560px;
    height: 400px;
    > div {
      width: 265px;
      min-width: auto;
    }
  }
}
.search {
  width: 400px;
  margin-bottom: 10px;
}
.allbtn {
  position: absolute;
  right: 3px;
  height: 24px;
  line-height: 1em;
}
.single-click-mode {
  :global .ant-checkbox-wrapper {
    width: 0;
    margin-right: -8px;
    visibility: hidden;
  }
  .grouptransfer,
  .usertransfer {
    :global(.custom-item) {
      width: calc(100% - 26px);
    }
  }
}
</style>
