<!-- 选择用户框 -->
<template>
  <cs-field
    ref="csField"
    class="cs-user"
    v-model="currentValue"
    :label="label"
    :rules="rules"
    :rules-key="rulesKey"
    :disabled="disabled"
    :colon="colon"
    :required="required"
    :error-message-align="errorMessageAlign"
    :label-class="labelClass"
    :label-width="labelWidth"
    :label-align="labelAlign"
    :input-align="inputAlign"
    :popupCloseable="true"
    right-icon="arrow"
    @click="showPicker"
  >
    <div :class="disabled ? 'disabled' : ''">
      <span v-if="currentValue">{{ currentValue }}</span>
      <span class="placeholder" v-else>{{ currentPlaceholder }}</span>
    </div>

    <template #popup>
      <!-- 标题 -->
      <div class="title">{{ title }}</div>
      <div class="search">
        <van-search v-model="keyword" placeholder="请输入关键字" />
      </div>

      <div class="bar-list">
        <!-- 用户索引列表 -->
        <van-index-bar :index-list="indexList" v-if="!keyword">
          <div v-for="item in currentItems" :key="item.Key">
            <van-index-anchor :index="item.Key" />

            <div class="user-list">
              <van-cell v-for="member in item.MemberInfos" :key="member.Id" @click="selectMember(member)">
                <template #title>
                  <div :class="member.Selected ? 'selected' : ''">
                    <div class="user-item">
                      <van-image round width="32px" height="32px" :src="member.PhotoImageUrl" />
                      <div class="name">
                        <span>{{ member.DisplayName }}</span>
                        <van-tag style="margin-left: 7px" type="warning" size="medium" v-if="member.JobTitle">
                          {{ member.JobTitle }}
                        </van-tag>
                        <span v-if="member.OrgName"> （{{ member.OrgName }}） </span>
                      </div>
                    </div>
                    <div class="notes">
                      <span v-if="member.Mobile">{{ member.Mobile }}</span>
                    </div>
                  </div>
                </template>
                <template #right-icon>
                  <van-icon class="selected" name="passed" size="20" v-if="member.Selected" />
                </template>
              </van-cell>
            </div>
          </div>
        </van-index-bar>

        <!-- 用户搜索列表 -->
        <div class="user-list" v-if="keyword">
          <van-cell v-for="member in searchItems" :key="member.Id" @click="selectMember(member)">
            <template #title>
              <div :class="member.Selected ? 'selected' : ''">
                <div class="user-item">
                  <van-image round width="32px" height="32px" :src="member.PhotoImageUrl" />
                  <div class="name">
                    <span>{{ member.DisplayName }}</span>
                    <van-tag style="margin-left: 7px" type="warning" size="medium" v-if="member.JobTitle">
                      {{ member.JobTitle }}
                    </van-tag>
                    <span v-if="member.OrgName"> （{{ member.OrgName }}） </span>
                  </div>
                </div>
                <div class="notes">
                  <span v-if="member.Mobile">{{ member.Mobile }}</span>
                </div>
              </div>
            </template>
            <template #right-icon>
              <van-icon class="selected" name="passed" size="20" v-if="member.Selected" />
            </template>
          </van-cell>
        </div>
      </div>

      <!-- 选中用户数 -->
      <div class="bottom-tool">
        <div>
          已选中
          <span style="color: #f00">{{ selectMemberIds.length }}</span>
          人
        </div>
        <van-tag type="primary" round size="large" @click="submit"> 确认 </van-tag>
      </div>
    </template>
  </cs-field>
</template>
<script>
import CsField from '../Base'
import mixin from '../mixin'
import { i18n } from '../../../..//lib/locale/lang/index'

export default {
  name: 'CsFieldUser',
  components: { CsField },
  mixins: [mixin],
  props: {
    // 当前输入的值
    value: {
      default: null
    },
    // 租户编号
    title: {
      type: String,
      default: '选择用户'
    },
    // 混合选择
    mixed: {
      type: Boolean,
      default: true
    },
    // 是否多选
    multiple: {
      type: Boolean,
      default: true
    },
    // 租户编号
    tenantId: {
      default: null
    }
  },
  data() {
    return {
      i18nLang: new Vue({ i18n }),
      currentValue: '',

      keyword: '', // 搜索关键字
      memberInfos: [], // 所有用户
      memberDict: {}, // 所有用户字典
      orgInfos: [], // 校园组织
      orgDict: {}, // 校园组织字典
      memberOrgInfos: [], // 校园用户关联组织
      memberOrgIdDict: [], // 校园用户关联组织编号集合字典

      indexList: [], // 索引列表
      currentItems: [], // 当前显示数据
      searchItems: [], // 搜索显示数据
      selectMemberIds: [] // 选中用户编号集合
    }
  },
  //监听属性 类似于data概念
  computed: {
    currentPlaceholder() {
      if (this.placeholder) {
        return this.placeholder
      } else {
        return this.i18nLang.$t('common.placeholderMember')
      }
    }
  },
  //监控data中的数据变化
  watch: {
    value: {
      handler(val, oldVal) {
        this.setData()
      },
      immediate: true, // 首次绑定是否执行
      deep: true // 对象内部的属性监听，也叫深度监听
    },
    keyword: {
      handler(val, oldVal) {
        this.filterItemFunc()
      },
      immediate: true, // 首次绑定是否执行
      deep: true // 对象内部的属性监听，也叫深度监听
    }
  },
  //方法集合
  methods: {
    change() {
      this.$forceUpdate()
    },

    /** 关键字筛选 */
    filterItemFunc() {
      this.searchItems.splice(0, this.searchItems.length)
      if (!this.keyword) {
        return
      }
      for (let i = 0; i < this.memberInfos.length; i++) {
        const memberInfo = this.memberInfos[i]

        if (
          !this.$util.containsObjProperty(memberInfo, this.keyword, [
            'DisplayName',
            'Pinyin',
            'PinyinAbbr',
            'Mobile',
            'JobTitle',
            'OrgName'
          ])
        ) {
          continue
        }
        this.searchItems.push(memberInfo)
      }
    },

    /** 弹出选择框 */
    showPicker() {
      if (this.disabled) {
        return
      }
      let loading = vant.Toast.loading({
        message: '加载中...',
        forbidClick: true,
        loadingType: 'spinner'
      })

      this.memberInfos.forEach(memberInfo => {
        if (this.selectMemberIds.indexOf(memberInfo.Id) > -1) {
          memberInfo.Selected = true
        } else {
          memberInfo.Selected = false
        }
        if (memberInfo.Mobile === null) {
          memberInfo.Mobile = ''
        }
        if (memberInfo.JobTitle === null) {
          memberInfo.JobTitle = ''
        }
        memberInfo.OrgName = ''
        if (this.memberOrgIdDict[memberInfo.Id]) {
          let orgNames = []
          this.memberOrgIdDict[memberInfo.Id].forEach(orgId => {
            if (this.orgDict[orgId]) {
              orgNames.push(this.orgDict[orgId].Name)
            }
          })
          orgNames.sort((a, b) => {
            return this.$util.sort(a, b)
          })
          memberInfo.OrgName = orgNames.join('/')
        }
      })

      this.$refs.csField.showPopup = true
      loading.clear()
    },

    /** 选中用户 */
    selectMember(member) {
      member.Selected = !member.Selected
      // 多选
      if (this.multiple) {
        if (member.Selected) {
          this.selectMemberIds.push(member.Id)
        } else {
          this.selectMemberIds.splice(this.selectMemberIds.indexOf(member.Id), 1)
        }
      }
      // 单选
      else {
        if (!member.Selected) {
          this.selectMemberIds.splice(0, 1)
          this.change()
          return
        }

        if (this.selectMemberIds.length == 0) {
          this.selectMemberIds.push(member.Id)
        } else {
          this.selectMemberIds.splice(0, 1)
          this.memberInfos.forEach(memberInfo => {
            if (member.Id != memberInfo.Id) {
              memberInfo.Selected = false
            }
          })

          this.selectMemberIds.push(member.Id)
        }
      }
      this.change()
    },

    /** 确认提交 */
    submit() {
      // 混合选择，返回对象数组
      if (this.mixed) {
        let items = []
        this.selectMemberIds.forEach(memberId => {
          let memberInfo = this.memberDict[memberId]
          items.push({ Id: memberId, Label: memberInfo.DisplayName, Type: 'user' })
        })
        if (items.length == 0) {
          // 多选
          if (this.multiple) {
            this.$emit('input', [])
          }
          // 单选
          else {
            this.$emit('input', {})
          }
          this.$refs.csField.showPopup = false
          return
        }
        // 多选
        if (this.multiple) {
          this.$emit('input', items)
        }
        // 单选
        else {
          this.$emit('input', items[0])
        }
      }
      // 返回用户编号集合
      else {
        if (this.selectMemberIds.length == 0) {
          // 多选
          if (this.multiple) {
            this.$emit('input', [])
          }
          // 单选
          else {
            this.$emit('input', 0)
          }
          this.$refs.csField.showPopup = false
          return
        }

        // 多选
        if (this.multiple) {
          this.$emit('input', this.selectMemberIds)
        }
        // 单选
        else {
          this.$emit('input', this.selectMemberIds[0])
        }
      }
      this.setShowValue()
      this.$refs.csField.showPopup = false
    },

    /** 绑定数据 */
    async setData() {
      if (!this.memberInfos || this.memberInfos.length == 0) {
        await this.getMembers()
      }
      if (!this.orgInfos || this.orgInfos.length == 0) {
        await this.getTenantOrg()
      }
      if (!this.memberOrgInfos || this.memberOrgInfos.length == 0) {
        await this.getTenantMemberOrg()
      }

      this.selectMemberIds = []
      if (!this.value) {
        return
      }

      let pickerItemValues = []
      // 混合选择，返回对象数组
      if (this.mixed) {
        // 多选
        if (this.multiple) {
          pickerItemValues = this.$util.copy(this.value)
        }
        // 单选
        else {
          let item = {}
          if (this.value.length) {
            item = this.value[0]
          } else if (this.value.Type) {
            item = this.value
          }
          pickerItemValues = this.$util.copy([item])
        }
        let isGetMemberIds = false
        let selectMemberIds = []
        for (let i = 0; i < pickerItemValues.length; i++) {
          const pickerItemValue = pickerItemValues[i]
          if (pickerItemValue.Type != 'user') {
            isGetMemberIds = true
          } else {
            selectMemberIds.push(pickerItemValue.Id)
          }
        }
        if (isGetMemberIds) {
          this.selectMemberIds = await this.getMemberIdsByPicker(pickerItemValues)
        } else {
          this.selectMemberIds = selectMemberIds
        }
      }
      // 返回用户编号集合
      else {
        // 多选
        if (this.multiple) {
          if (this.value.length) {
            this.selectMemberIds = this.$util.copy(this.value)
          }
        }
        // 单选
        else {
          if (this.value.length && Number(this.value[0])) {
            this.selectMemberIds = [Number(this.value[0])]
          } else if (Number(this.value)) {
            this.selectMemberIds = [Number(this.value)]
          }
        }
      }
      this.setShowValue()
    },

    /** 设置显示内容 */
    setShowValue() {
      let memberNames = []
      for (let i = 0; i < this.selectMemberIds.length; i++) {
        let memberInfo = this.memberDict[this.selectMemberIds[i]]
        memberNames.push(memberInfo.DisplayName)

        if (memberNames.length >= 3) {
          break
        }
      }
      let currentValue = memberNames.join('、')
      if (this.selectMemberIds.length > 3) {
        currentValue += `等${this.selectMemberIds.length}名用户`
      }
      this.currentValue = currentValue
    },

    /** 根据选择用户组件数据 返回 用户编号集合 */
    async getMemberIdsByPicker(pickerItemValue) {
      return await this.postAxios(
        '//api/v2/Foundation/TenantMember',
        { action: 'GetMemberIdsByPicker', tenantId: this.tenantId },
        pickerItemValue,
        {},
        { disableLoading: true }
      ).then(res => {
        return res
      })
    },

    /** 查询校园组织列表 */
    async getTenantOrg() {
      await this.getAxios(
        '//api/v2/Foundation/TenantOrg',
        { tenantId: this.tenantId },
        {},
        {},
        { disableLoading: true }
      ).then(res => {
        this.orgInfos = res
        let orgDict = {}
        this.orgInfos.forEach(orgInfo => {
          orgDict[orgInfo.Id] = orgInfo
        })
        this.orgDict = orgDict
      })
    },

    /** 查询校园用户关联组织列表 */
    async getTenantMemberOrg() {
      await this.getAxios(
        '//api/v2/Foundation/TenantMemberOrg',
        { tenantId: this.tenantId },
        {},
        {},
        { disableLoading: true }
      ).then(res => {
        this.memberOrgInfos = res
        let memberOrgIdDict = {}
        this.memberOrgInfos.forEach(memberOrgInfo => {
          if (!memberOrgIdDict[memberOrgInfo.MemberId]) {
            memberOrgIdDict[memberOrgInfo.MemberId] = []
          }
          if (memberOrgIdDict[memberOrgInfo.MemberId].indexOf(memberOrgInfo.OrgId) == -1) {
            memberOrgIdDict[memberOrgInfo.MemberId].push(memberOrgInfo.OrgId)
          }
        })
        this.memberOrgIdDict = memberOrgIdDict
      })
    },

    /** 查询用户列表 */
    async getMembers() {
      await this.getAxios(
        '//api/v2/Foundation/TenantMember',
        { tenantId: this.tenantId },
        {},
        {},
        { disableLoading: true }
      ).then(res => {
        this.memberInfos = res
        let memberDict = {}

        let abbrs = []
        let otherAbbrs = []
        this.memberInfos.forEach(memberInfo => {
          memberDict[memberInfo.Id] = memberInfo
          let initials = '#'
          if (memberInfo.PinyinAbbr) {
            initials = memberInfo.PinyinAbbr.substring(0, 1)
            let number = initials.charCodeAt()
            if (number < 65 || number > 90) {
              initials = '#'
            }
          }
          if (initials == '#') {
            otherAbbrs.push(memberInfo)
          } else {
            if (!abbrs[initials]) {
              abbrs[initials] = []
            }
            abbrs[initials].push(memberInfo)
          }
        })
        this.memberDict = memberDict

        let indexList = []
        let items = []
        Object.keys(abbrs).forEach(key => {
          let item = {
            Key: key,
            MemberInfos: abbrs[key]
          }
          indexList.push(key)
          items.push(item)
        })
        indexList.sort((a, b) => {
          return this.$util.sort(a, b)
        })
        items.sort((a, b) => {
          return this.$util.sort(a.Key, b.Key)
        })

        if (otherAbbrs.length > 0) {
          indexList.push('#')
          items.push({ Key: '#', MemberInfos: otherAbbrs })
        }
        this.indexList = indexList
        this.currentItems = items
      })
    }
  },
  //生命周期 - 创建完成（可以访问当前this实例）
  created() {},
  //生命周期 - 挂载完成（可以访问DOM元素）
  mounted() {},
  beforeCreate() {}, //生命周期 - 创建之前
  beforeMount() {}, //生命周期 - 挂载之前
  beforeUpdate() {}, //生命周期 - 更新之前
  updated() {}, //生命周期 - 更新之后
  beforeDestroy() {}, //生命周期 - 销毁之前
  destroyed() {}, //生命周期 - 销毁完成
  activated() {} //如果页面有keep-alive缓存功能，这个函数会触发
}
</script>
<style lang="scss" scoped>
.cs-user {
  // 标题
  .title {
    position: fixed;
    top: 0;
    left: 0;
    z-index: 999;
    width: 100%;
    height: 50px;
    line-height: 50px;
    font-size: 16px;
    text-align: center;
  }

  // 搜索
  .search {
    position: fixed;
    top: 50px;
    left: 0;
    z-index: 999;
    width: 100%;
    height: 54px;
    line-height: 54px;
  }

  // 索引栏列表
  .bar-list {
    height: calc(100vh - 154px);
    margin: 104px 0 50px 0;
    overflow-y: auto;

    // 用户列表
    .user-list {
      padding-right: 25px;

      // 单个用户
      .user-item {
        display: flex;
        align-items: center;

        .name {
          margin-left: 8px;
        }
      }

      .notes {
        margin-left: 40px;
        font-size: 14px;
      }

      i {
        top: 5px;
      }

      // 选中
      .selected {
        color: #1989fa;
      }
    }
  }

  // 底部操作栏
  .bottom-tool {
    position: fixed;
    left: 0;
    bottom: 0;
    z-index: 999;
    background-color: white;
    width: calc(100% - 20px);
    height: 50px;
    padding: 0 10px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    border-top: 1px solid #d2d2d2;

    .van-tag {
      padding: 5px 12px;
    }
  }
}
</style>
<style lang="scss">
.cs-user {
  .van-popup__close-icon {
    z-index: 1000;
  }
}
</style>
