<!-- 选择学生框 -->
<template>
  <cs-field
    ref="csField"
    class="cs-student"
    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>

      <van-tree-select
        class="tree-select-card"
        :items="currentItems"
        :main-active-index="mainActiveIndex"
        @click-nav="clickNav"
      >
        <template #content>
          <!-- 操作区 -->
          <div class="option-bar" v-if="multiple">
            <van-tag type="success" plain size="large" @click="clickAll(true)">
              <van-icon name="success" />
              <span>全选</span>
            </van-tag>
            <van-tag type="warning" plain size="large" @click="clickAll(false)">
              <van-icon name="cross" />
              <span>全不选</span>
            </van-tag>
          </div>

          <!-- 学生列表 -->
          <div class="student-list" :class="multiple ? 'multiple' : ''">
            <van-cell v-for="student in classStudents" :key="student.Id" @click="selectStudent(student)">
              <template #title>
                <div class="student-item">
                  <van-image round width="32px" height="32px" :src="student.PhotoImageUrl" />
                  <span class="name" :class="student.Selected ? 'selected' : ''">
                    {{ student.Name }}
                  </span>
                </div>
              </template>
              <template #right-icon>
                <van-icon class="selected" name="passed" size="20" v-if="student.Selected" />
              </template>
            </van-cell>
          </div>
        </template>
      </van-tree-select>

      <!-- 选中学生数 -->
      <div class="bottom-tool">
        <div>
          已选中
          <span style="color: #f00">{{ selectStudentIds.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: 'CsFieldStudent',
  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: '',

      studentInfos: [], // 所有学生
      classInfos: [], // 所有班级
      studentDict: {}, // 学生字典 [ classId: students ]
      studentNameDict: {}, // 学生姓名字典 [ studentId: studentName ]

      currentItems: [], // tree结构
      mainActiveIndex: 0,
      classStudents: [], // 选中班级的学生列表
      selectStudentIds: [] // 选中学生编号集合
    }
  },
  //监听属性 类似于data概念
  computed: {
    currentPlaceholder() {
      if (this.placeholder) {
        return this.placeholder
      } else {
        return this.i18nLang.$t('common.placeholderStudent')
      }
    }
  },
  //监控data中的数据变化
  watch: {
    value: {
      handler(val, oldVal) {
        this.setData()
      },
      immediate: true, // 首次绑定是否执行
      deep: true // 对象内部的属性监听，也叫深度监听
    }
  },
  //方法集合
  methods: {
    change() {
      this.$forceUpdate()
    },

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

      // 循环学生集合，设置选中的学生
      this.studentInfos.forEach(studentInfo => {
        if (studentInfo.ClassId > 0) {
          if (this.selectStudentIds.indexOf(studentInfo.Id) > -1) {
            studentInfo.Selected = true
          } else {
            studentInfo.Selected = false
          }
        }
      })

      let currentItems = []
      // 循环班级，构造班级数据
      this.classInfos.forEach(classInfo => {
        if (this.studentDict[classInfo.Id]) {
          let classSelect = true
          let badge = 0
          this.studentDict[classInfo.Id].forEach(student => {
            if (student.Selected) {
              badge++
            } else {
              classSelect = false
            }
          })
          currentItems.push({
            id: classInfo.Id,
            text: classInfo.Name,
            badge: badge ? badge : null,
            children: this.studentDict[classInfo.Id],
            Selected: classSelect
          })
        }
      })
      this.currentItems = currentItems
      this.$refs.csField.showPopup = true
      this.clickNav(this.mainActiveIndex)
      loading.clear()
    },

    /** 选中左侧班级 */
    clickNav(index) {
      const item = this.currentItems[index]
      this.classStudents = item.children
      if (this.mainActiveIndex != index) {
        this.mainActiveIndex = index
      }
      this.change()
    },

    /** 全选/全不选 */
    clickAll(isSelected) {
      const item = this.currentItems[this.mainActiveIndex]

      // 设置选中项，选中学生编号集合
      item.children.forEach(student => {
        student.Selected = isSelected
        if (isSelected) {
          if (this.selectStudentIds.indexOf(student.Id) == -1) {
            this.selectStudentIds.push(student.Id)
          }
        } else {
          if (this.selectStudentIds.indexOf(student.Id) > -1) {
            this.selectStudentIds.splice(this.selectStudentIds.indexOf(student.Id), 1)
          }
        }
      })
      // 设置选中数
      if (isSelected) {
        item.badge = item.children.length
      } else {
        item.badge = null
      }
      // 设置是否选中班级
      item.Selected = isSelected
      this.change()
    },

    /** 选中右侧学生 */
    selectStudent(student) {
      student.Selected = !student.Selected
      // 多选
      if (this.multiple) {
        if (student.Selected) {
          this.selectStudentIds.push(student.Id)
        } else {
          this.selectStudentIds.splice(this.selectStudentIds.indexOf(student.Id), 1)
        }

        // 设置选中数，是否选中班级
        const item = this.currentItems[this.mainActiveIndex]
        if (student.Selected) {
          item.badge = item.badge ? item.badge + 1 : 1
        } else {
          item.badge = item.badge > 1 ? item.badge - 1 : null
        }
        let classSelect = true
        for (let i = 0; i < item.children.length; i++) {
          const studentItem = item.children[i]
          if (!studentItem.Selected) {
            classSelect = false
            break
          }
        }
        item.Selected = classSelect
      }
      // 单选
      else {
        this.selectStudentIds.splice(0, this.selectStudentIds.length)
        this.currentItems.forEach(classInfo => {
          classInfo.Selected = false
          classInfo.badge = null
          classInfo.children.forEach(studentInfo => {
            if (student.Id == studentInfo.Id) {
              if (student.Selected) {
                classInfo.badge = 1
                this.selectStudentIds.push(student.Id)
              }
            } else {
              studentInfo.Selected = false
            }
          })
        })
      }
      this.change()
    },

    /** 确认提交 */
    submit() {
      let items = []
      this.currentItems.forEach(classInfo => {
        // 选中班级，生成对象数组
        if (this.mixed && classInfo.Selected) {
          items.push({ Id: classInfo.id, Label: classInfo.text, Type: 'class' })
        }
        // 选中班级内学生，查找学生
        else {
          classInfo.children.forEach(studentInfo => {
            // 构造选中学生对象数组
            if (this.mixed && studentInfo.Selected) {
              items.push({ Id: studentInfo.Id, Label: studentInfo.Name, Type: 'student' })
            }
          })
        }
      })

      // 混合选择，返回对象数组
      if (this.mixed) {
        if (items.length == 0) {
          // 多选
          if (this.multiple) {
            this.$emit('input', [])
          }
          // 单选
          else {
            this.$emit('input', {})
          }
          this.$refs.csField.showPopup = false
          return
        }

        items.sort((a, b) => {
          return this.$util.sort(a.Type, b.Type)
        })
        // 多选
        if (this.multiple) {
          this.$emit('input', items)
        }
        // 单选
        else {
          this.$emit('input', items[0])
        }
      }
      // 返回学生编号集合
      else {
        if (this.selectStudentIds.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.selectStudentIds)
        }
        // 单选
        else {
          this.$emit('input', this.selectStudentIds[0])
        }
      }
      this.setShowValue(items)
      this.$nextTick(() => {
        this.$refs.csField.showPopup = false
      })
    },

    /** 绑定数据 */
    async setData() {
      if (!this.classInfos || this.classInfos.length == 0) {
        await this.getClasses()
      }
      if (!this.studentInfos || this.studentInfos.length == 0) {
        await this.getStudents()
      }

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

      let items = []
      // 混合选择，返回对象数组
      if (this.mixed) {
        let studentIdsDict = {}
        this.studentInfos.forEach(studentInfo => {
          if (!studentIdsDict[studentInfo.ClassId]) {
            studentIdsDict[studentInfo.ClassId] = []
          }
          studentIdsDict[studentInfo.ClassId].push(studentInfo.Id)
        })

        // 多选
        if (this.multiple) {
          if (this.value.length) {
            this.value.forEach(item => {
              if (item.Type == 'class') {
                studentIdsDict[item.Id].forEach(studentId => {
                  this.selectStudentIds.push(studentId)
                })
              } else if (item.Type == 'student') {
                this.selectStudentIds.push(item.Id)
              }
            })
            items = this.$util.copy(this.value)
          }
        }
        // 单选
        else {
          let item = {}
          if (this.value.length) {
            item = this.value[0]
            items = this.$util.copy(this.value)
          } else if (this.value.Type) {
            item = this.value
            items = [this.$util.copy(this.value)]
          }
          if (item.Type == 'class') {
            studentIdsDict[item.Id].forEach(studentId => {
              this.selectStudentIds.push(studentId)
            })
          } else if (item.Type == 'student') {
            this.selectStudentIds.push(item.Id)
          }
        }
      }
      // 返回学生编号集合
      else {
        // 多选
        if (this.multiple) {
          if (this.value.length) {
            this.selectStudentIds = this.$util.copy(this.value)
          }
        }
        // 单选
        else {
          if (this.value.length && Number(this.value[0])) {
            this.selectStudentIds = [Number(this.value[0])]
          } else if (Number(this.value)) {
            this.selectStudentIds = [Number(this.value)]
          }
        }
      }
      this.setShowValue(items)
    },

    /** 设置显示内容 */
    setShowValue(items) {
      // 混合选择，返回对象数组
      if (this.mixed) {
        let classNames = []
        let studentNames = []
        for (let i = 0; i < items.length; i++) {
          const item = items[i]
          if (item.Type == 'class') {
            classNames.push(item.Label)
          } else if (item.Type == 'student') {
            studentNames.push(item.Label)
          }
        }
        let currentValue = ''
        if (classNames.length > 0) {
          if (classNames.length < 3) {
            currentValue = classNames.join('、')
          } else {
            currentValue = `${classNames.splice(0, 2).join('、')}等${classNames.length + 2}个班级`
          }
        }
        if (studentNames.length > 0) {
          if (currentValue.length > 0) {
            currentValue += '。'
          }
          if (studentNames.length < 3) {
            currentValue += studentNames.join('、')
          } else {
            currentValue += `${studentNames.splice(0, 2).join('、')}等${studentNames.length + 2}名学生`
          }
        }
        this.currentValue = currentValue
      }
      // 返回学生编号集合
      else {
        let studentNames = []
        for (let i = 0; i < this.selectStudentIds.length; i++) {
          const studentId = this.selectStudentIds[i]

          studentNames.push(this.studentNameDict[studentId])
          if (this.selectStudentIds.length > 3 && i == 2) {
            break
          }
        }
        let currentValue = studentNames.join('、')
        if (this.selectStudentIds.length > 3) {
          currentValue += `等${this.selectStudentIds.length}名学生`
        }
        this.currentValue = currentValue
      }
      this.change()
    },

    /** 查询学生列表 */
    async getStudents() {
      await this.getAxios(
        '//api/v2/K12Base/Student',
        { action: 'GetListByYearId', tenantId: this.tenantId },
        {},
        {},
        { disableLoading: true }
      ).then(res => {
        this.studentInfos = res
        this.studentDict = {}
        this.studentNameDict = {}
        this.studentInfos.forEach(item => {
          if (!this.studentDict[item.ClassId]) {
            this.studentDict[item.ClassId] = []
          }
          this.studentDict[item.ClassId].push(item)
          this.studentNameDict[item.Id] = item.Name
        })
      })
    },

    /** 查询班级列表 */
    async getClasses() {
      await this.getAxios(
        '//api/v2/K12Base/Class',
        { action: 'GetList', tenantId: this.tenantId },
        {},
        {},
        { disableLoading: true }
      ).then(res => {
        this.classInfos = res
      })
    }
  },
  //生命周期 - 创建完成（可以访问当前this实例）
  created() {},
  //生命周期 - 挂载完成（可以访问DOM元素）
  mounted() {},
  beforeCreate() {}, //生命周期 - 创建之前
  beforeMount() {}, //生命周期 - 挂载之前
  beforeUpdate() {}, //生命周期 - 更新之前
  updated() {}, //生命周期 - 更新之后
  beforeDestroy() {}, //生命周期 - 销毁之前
  destroyed() {}, //生命周期 - 销毁完成
  activated() {} //如果页面有keep-alive缓存功能，这个函数会触发
}
</script>
<style lang="scss" scoped>
.cs-student {
  // 标题
  .title {
    position: fixed;
    top: 0;
    left: 0;
    z-index: 999;
    width: 100%;
    height: 50px;
    line-height: 50px;
    font-size: 16px;
    text-align: center;
  }

  // 选择树卡片
  .tree-select-card {
    margin: 50px 0;
    height: calc(100vh - 100px) !important;

    // 右侧操作栏
    .option-bar {
      width: 58%;
      display: block;
      padding: 7px 16px;
      background: white;
      position: fixed;
      top: 50px;
      z-index: 999;

      .van-tag + .van-tag {
        margin-left: 10px;
      }

      .van-tag {
        i {
          margin-right: 5px;
        }
      }
    }

    // 学生列表
    .student-list {
      // 单个学生
      .student-item {
        display: flex;
        align-items: center;

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

      // 选中
      .selected {
        color: #1989fa;
      }
    }
    .student-list.multiple {
      margin-top: 44px;
    }
  }

  // 底部操作栏
  .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-student {
  .van-popup__close-icon {
    z-index: 1000;
  }
}
</style>
