<template>
  <section class="selectArea">
    <div class="areaSelector">
      <div class="fixedTop">
        <em>选择区域</em>
        <div class="selectedArea">
          <p v-if="hasSelected" v-text="fullArea.map(e=>e.name).join('')"/>
          <p v-else>请选择</p>
        </div>
        <div/>
        <span v-if="urlParams.all" v-text="`省`" @click="selectNode({}, -1)"/>
        <span v-for="(area,i) in typeLabels" :key="area.id"
              v-text="area.levelLabel" @click="selectNode(area, i)"/>
      </div>
    </div>
    <scroll-view class="fill pendingList" scroll-y>
      <div class="pendingItem flexRow" flex v-for="op in pending" :key="op.id" @tap.stop="getChild(op)">
        <div class="fill" :class="{ self: index == op.id }" v-html="op.name"/>
        <u-icon v-if="index == op.id" name="checkbox-mark" color="#4181FF"/>
      </div>
      <AiEmpty v-if="pending.length==0" description="无下级地区数据"/>
    </scroll-view>
    <div class="bottomBtns">
      <div @click.stop="back">取消</div>
      <div class="primary fill" @click.stop="handleSelect">确定</div>
    </div>
  </section>
</template>

<script>

export default {
  name: "selectArea",
  appName: "选择地区",
  computed: {
    dataRange() {
      return this.urlParams.all || this.urlParams.disabled ? 0 : this.getAreaType(this.root)
    },
    root() {
      return this.urlParams.areaId || this.$areaId
    },
    pending() {
      return this.list?.map(e => ({...e, levelLabel: this.levelLabels[e.type]})) || []
    },
    hasSelected() {
      return this.fullArea?.length > 0
    },
    hasLastLevelValue() {
      return this.fullArea.some(e => e.type >= this.urlParams.valueLevel)
    },
    typeLabels() {
      return this.fullArea.filter(e => e.type < this.urlParams.valueLevel)
    }
  },
  data() {
    return {
      fullArea: [],
      index: '',
      list: [],
      levelLabels: ["省", "市", "县/区", "镇/街道", "村/社区"],
      selected: {},
      urlParams: {}
    }
  },
  watch: {
    root(v) {
      v && (this.getFullArea(v))
    }
  },
  methods: {
    getInfo(areaId) {
      return areaId && this.$instance.post('/admin/area/getAllParentAreaId', null, {
        withoutToken: true,
        params: {areaId},
      }).then(res => {
        if (res?.data) {
          res.data.forEach((e) => {
            e && (e.levelLabel = this.levelLabels[e.type])
          })
          return res.data.reverse()
        }
      })
    },
    getFullArea(areaId) {
      return this.fullArea?.length > 0 ? Promise.resolve(this.fullArea) : this.getInfo(areaId).then(meta => {
        if (meta.length > 1) {
          this.fullArea = meta.slice(this.dataRange)
        } else {
          this.fullArea = meta
        }
        return this.fullArea
      })
    },
    getChildAreas(id) {
      id && this.$instance.post('/admin/area/queryAreaByParentId', null, {
        withoutToken: true,
        params: {id},
      }).then((res) => {
        if (res?.data) {
          this.list = res.data
          if (this.urlParams.selectRoot) {
            if (this.hasLastLevelValue) {
              let parent = JSON.parse(JSON.stringify(this.fullArea?.slice(-2)?.[0]))
              this.list.unshift(parent)
            } else {
              let parent = JSON.parse(JSON.stringify(this.fullArea?.slice(-1)?.[0]))
              this.list.unshift(parent)
            }
          }
        }
      })
    },
    getProvinces() {
      this.$instance.post('/admin/area/queryProvinceList', null, {withoutToken: true}).then((res) => {
        if (res?.data) {
          this.list = res.data
        }
      })
    },
    handleSelect() {
      let {selected, fullArea} = this
      uni.$emit("selectArea", {...selected, fullArea})
      this.back()
    },
    getChild(op) {
      if (op.id != this.index) {
        this.selected = op
        this.index = op.id
        let {length} = this.fullArea
        if (op.type == this.urlParams.valueLevel) {
          if (this.hasLastLevelValue) {
            this.fullArea.splice(length - 1, 1, op)
          } else this.fullArea.push(op)
        } else if (op.type < this.urlParams.valueLevel) {
          if (this.hasLastLevelValue) {
            this.fullArea.splice(length - 1, 1)
          } else {
            this.fullArea.push(op)
            this.getChildAreas(op.id)
          }
        }
      }
    },
    selectNode(area, i) {
      let deleteCount = this.fullArea.length - i
      if (deleteCount > 0) {
        this.fullArea.splice(i + 1, deleteCount)
      }
      if (this.urlParams.all && !area.id) {
        this.index = ''
        this.getProvinces()
      } else {
        this.index = area.id
        this.getChildAreas(area.id)
      }
    },
    handleInit() {
      //初始化
      this.index = this.urlParams.value || this.root
      if (!this.urlParams.disabled) {
        if (this.urlParams.value) {
          this.getFullArea(this.urlParams.value).then(() => {
            let area = this.fullArea.find(e => e.id == this.urlParams.value) || {}
            //当前选择列表必须是可选范围内的值
            let top = area.type == this.urlParams.valueLevel ? area.parentId : area.id
            if (this.getAreaType(top) >= this.dataRange) {
              this.getChildAreas(top)
            }
          })
        } else if (this.urlParams.all) {
          this.getProvinces()
        } else {
          this.getFullArea(this.root).then(() => {
            this.getChildAreas(this.root)
          })
        }
      }
    },
    back() {
      uni.navigateBack({})
    },
    getAreaType(area) {
      let rules = [10, 8, 6, 3, 0], level = 0
      if (area) {
        rules.some((e, i) => {
          let reg = new RegExp(`0{${e}}`, 'g')
          if (reg.test(area)) {
            return (level = i)
          }
        })
      }
      return level
    }
  },
  onLoad(params) {
    Object.keys(params).map(k => {
      this.$set(this.urlParams, k,
          params[k] == "false" ? false :
              params[k] == "undefined" ? null : params[k]
      )
    })
    this.$nextTick(() => this.handleInit())
  }
}
</script>

<style lang="scss" scoped>
.selectArea {
  display: flex;
  flex-direction: column;
  height: 100vh;
  background: #fff;

  ::v-deep .areaSelector {
    display: flex;
    align-items: center;

    span {
      cursor: pointer;
      color: #333;
      font-weight: bold;
      line-height: 112px;
      margin-right: 72px;
      position: relative;

      &:last-of-type {
        margin-right: 0;

        &:after {
          content: " ";
          display: block;
          position: absolute;
          bottom: -26px;
          left: 50%;
          transform: translate(-50%, 100%);
          width: 40px;
          height: 8px;
          background: #4181FF;
          border-radius: 4px;
        }
      }
    }

    em {
      font-style: normal;
      font-size: 24px;
      font-weight: 400;
      color: #999999;
      line-height: 34px;
    }

    .selectedArea {
      display: flex;
      align-items: center;
      width: fit-content;
      max-width: calc(100vw - 128px);
      padding: 0 32px;
      height: 80px;
      background: #ECF2FF;
      border-radius: 40px;
      font-size: 32px;
      font-family: PingFangSC-Medium, PingFang SC;
      font-weight: 500;
      color: #4181FF !important;
      margin: 16px 0 32px;
      white-space: nowrap;

      & > p {
        overflow: hidden;
        text-overflow: ellipsis;
        direction: rtl;
      }
    }

    .fixedTop {
      width: 100vw;
      background: #fff;
      border-bottom: 4px solid #f5f5f5;
      text-align: start;
      padding: 32px 32px 0;
      box-sizing: border-box;
    }
  }

  ::v-deep .pendingList {
    padding: 0 32px;
    box-sizing: border-box;

    .emptyWrap {
      width: 100%;
    }

    .pendingItem {
      color: #333;
      height: 84px;
      text-align: start;

      .self {
        font-weight: bold;
      }
    }
  }

  ::v-deep.bottomBtns {
    width: 100vw;
    display: flex;
    align-items: center;
    text-align: center;
    height: 120px;
    font-size: 34px;
    font-family: PingFangSC-Medium, PingFang SC;
    font-weight: 500;
    color: #3671EE;
    background: #fff;
    padding: 0 32px;
    box-sizing: border-box;

    & > div {
      padding: 0 92px;
      line-height: 88px;
      height: 88px;
      border: 1px solid #A0C0FF;
      border-radius: 16px;

      &.primary {
        color: #fff;
        background: #4181FF;
        border-color: #4181FF;
      }

      & + div {
        margin-left: 32px;
      }
    }
  }
}
</style>
