<template>
  <WorkspaceCard class="work-common" title="常用功能">
    <span slot="header-right" class="header-right-set" @click="setCommonFun"><i class="icon-set-img"></i> 设置</span>
    <div class="common-lists">
      <div class="list-item" v-for="item in commonList" :key="item.id" @click="openLink(item)">
        <div class="icon-box-container" v-if="item.icon && item.icon.indexOf('icon-') === 0">
          <JyIcon :name="item.icon" classPrefix=""></JyIcon>
        </div>
        <div v-else class="icon-box-container">
          <el-image :src="item.icon" alt="常用功能">
            <img slot="error" src="https://www.jianyu360.cn/common-module/public/image/auto.png" />
          </el-image>
        </div>
        <span v-html="item.name.replace('/', '/<br>')" class="item-name"></span>
      </div>
      <div v-if="commonList && commonList.length < maxCount" class="list-add" @click="setCommonFun">
        <span class="icon-add-img"></span>
        <span class="add-text">添加常用功能</span>
      </div>
    </div>
    <!-- 设置常用功能dialog -->
    <el-dialog
      custom-class="fn-dialog"
      :visible.sync="dialogShow"
      :close-on-click-modal="false"
      :show-close="false"
      v-if="dialogShow"
      center
      width="696px">
      <SelectorCard @onCancel="changeDialogState(false)" @onConfirm="confirmSaveFn" confirmText="确定">
        <div slot="header">常用功能设置</div>
        <div class="transfer-content">
          <Transfer :maxCount="maxCount" submitKey="id" :left="allFunctions" :right="transferCommonList" @onSave="onTransferSave"></Transfer>
        </div>
      </SelectorCard>
    </el-dialog>
    <!-- 改为抽屉式 -->
    <DrawerCard customClass="drawer-class" title="常用功能设置" percent="600px" :with-header="false" v-model="drawerShow" @close="onCloseDrawer" @saveData="onSaveDrawer">
      <div class="function-drawer-content" ref="drawerScroll" @scroll="handleScroll($event)">
        <div class="added-function">
          <h3 class="added-title">已添加（{{addedList.length}}）</h3>
          <transition-group class="added-container" name="drag" tag="ul" v-if="addedList && addedList.length > 0">
            <li class="added-item" draggable v-for="(item, i) in addedList" :key="item.id" @dragover.prevent @dragstart="onDragstart($event, i)" @dragenter="onDragenter($event, i)" @dragend="onDragend($event, i)">
              <div class="icon-box-container">
                <el-image :src="item.icon" :alt="item.name">
                  <img slot="error" src="https://www.jianyu360.cn/common-module/public/image/auto.png" />
                </el-image>
              </div>
              <span v-html="item.name.replace('/', '/<br>')" class="item-name"></span>
              <span class="remove-tag" @click.stop="onAddedRemove(item)">-</span>
            </li>
          </transition-group>
          <div v-else class="no-added">暂未设置常用功能</div>
        </div>
        <div class="classify-function" ref="refContent">
          <div class="classify-tab" :class="{'tab-fixed': tabFixed}" ref="tabBox">
            <span class="tab-item" :class="{'active': tabActive === index}" v-for="(item, index) in tabNames" :key="item.id" @click="goAnchor(item, index)">{{item.name}}</span>
          </div>
          <div class="classify-content">
            <ul class="outer-container">
              <li class="outer-item"  :id="level.name" v-for="level in mainFunList" :key="level.id">
                <h3 class="outer-item-name">{{ level.name }}</h3>
                <ul class="insert-container">
                  <li class="insert-item" v-for="next in level.children" :key="next.id">
                    <div class="insert-item-left">
                      <el-image :src="next.icon" :alt="next.name">
                        <img slot="error" src="https://www.jianyu360.cn/common-module/public/image/auto.png" />
                      </el-image>
                      <span v-html="next.name.replace('<br>', '')"></span>
                    </div>
                    <transition name="el-zoom-in-center">
                      <span v-if="next.status" class="handle-btn remove-btn" @click.stop="onRemoveFun(next)">移除</span>
                      <span v-else class="handle-btn add-btn" @click.stop="onAddFun(next)">添加</span>
                    </transition>
                  </li>
                </ul>
              </li>
            </ul>
          </div>
        </div>
      </div>
    </DrawerCard>
  </WorkspaceCard>
</template>

<script>
import { JyIcon } from '@jianyu/icon'
import { mapState, mapMutations, mapActions } from 'vuex'
import { Dialog, Image } from 'element-ui'
import WorkspaceCard from '../ui/WorkspaceCard'
import SelectorCard from '@/components/selector/SelectorCard'
import Transfer from '@/components/work-desktop/Transfer'
import { mixinNoPowerMessageTip } from '@/utils/mixins/no-power-message-box'
import { tryCallHooks } from '@jianyu/easy-inject-qiankun'
import { debounce } from '@/utils/globalFunctions'
import DrawerCard from '@/components/drawer/Drawer.vue'

export default {
  name: 'CommonUse',
  mixins: [mixinNoPowerMessageTip],
  components: {
    [Dialog.name]: Dialog,
    [Image.name]: Image,
    WorkspaceCard,
    SelectorCard,
    JyIcon,
    Transfer,
    DrawerCard
  },
  data () {
    return {
      addedList: [],
      mainFunList: [],
      dragIndex: '',
      enterIndex: '',
      tabActive: 0,
      tabFixed: false,
      isScrollAnchor: true
    }
  },
  computed: {
    ...mapState({
      maxCount: state => state.workspace.commonUse.maxCount,
      dialogShow: state => state.workspace.commonUse.dialogShow,
      allFunctions: state => state.workspace.commonUse.allFunctions, // 所有功能
      transferCommonList: state => state.workspace.commonUse.transferCommonList,
      commonList: state => state.workspace.commonUse.commonList, // 常用功能
      mainFunctions: state => state.workspace.commonUse.mainFunctions,
      drawerShow: state => state.workspace.commonUse.drawerShow
    }),
    tabNames () {
      return this.mainFunctions.filter(item => item.level === 1)
    }
  },
  watch: {
    commonList (val) {
      if (val) {
        this.addedList = JSON.parse(JSON.stringify(val))
        this.formatMainFunList(this.addedList)
      }
    },
    mainFunctions (val) {
      if (val) {
        this.mainFunList = JSON.parse(JSON.stringify(val))
        this.formatMainFunList(this.addedList)
      }
    },
    drawerShow (val) {
      if (!val) {
        this.tabFixed = false
        this.tabActive = 0
      }
    }
  },
  async created () {
    await this.getCanUseFunctions()
    await this.getAllFunctions({ vm: this })
  },
  beforeDestroy () {
    window.removeEventListener('scroll', this.handleScroll)
  },
  methods: {
    ...mapMutations('workspace/commonUse', [
      'changeDialogState',
      'transferSave',
      'changeDrawerState'
    ]),
    ...mapActions('workspace/commonUse', [
      'getAllFunctions',
      'getCanUseFunctions',
      'confirmSave'
    ]),
    // 穿梭框子组件传来的组件
    onTransferSave (data) {
      this.transferSave(data)
    },
    openLink (item) {
      const { url } = item
      if (item.usable) {
        tryCallHooks({
          fn: () => {
            this.$BRACE.methods.open({
              route: {
                ...item,
                link: url
              }
            })
          },
          spareFn: () => {
            window.open(url)
          }
        })
      } else {
        // 判断是否需要自定义弹窗文案
        const hasTipInfo = Object.keys(item?.tipInfo || {}).length > 0
        if (hasTipInfo) {
          // 自定义弹窗文案
          const menu = item
          // 格式化弹窗配置信息
          const dialogParams = {
            type: 'tip',
            title: menu.tipInfo?.title,
            message: menu.tipInfo?.content,
            options: Object.assign({
              dangerouslyUseHTMLString: true,
              customClass: 'custom-message-box',
              confirmButtonText: '我知道了',
              confirmButtonClass: 'custom-confirm-btn',
              showClose: false,
              showCancelButton: false,
              closeOnClickModal: false,
              center: true
            }, {
              showCancelButton: !!menu.tipInfo?.isShowCancel,
              confirmButtonText: menu.tipInfo?.confirmText
            }, menu.tipInfo?.options || {})
          }
          this.$confirm(dialogParams.message, dialogParams.title, dialogParams.options).then(() => {
            // 确认按钮自定义跳转
            if (menu.tipInfo?.confirmUrl) {
              // 调用工作桌面函数跳转
              tryCallHooks({
                fn: () => {
                  this.$BRACE.methods.open({
                    route: {
                      link: menu.tipInfo?.confirmUrl,
                      appType: menu.tipInfo?.appType,
                      openType: menu.tipInfo?.openType
                    }
                  })
                },
                spareFn: () => {
                  window.open(menu.tipInfo?.confirmUrl)
                }
              })
            }
          }).catch(e => e)
        } else {
          // 默认文案
          this.showNoPowerMessageTip()
        }
      }
    },
    confirmSaveFn () {
      try {
        this.confirmSave()
      } catch (error) {
        this.$toast(error)
      }
    },
    onDragstart (e, index) {
      this.dragIndex = index
      const element = e.target
      element.classList.add('drag-move-item')
    },
    onDragenter: debounce(function (e, index) {
      e.preventDefault()
      if (this.dragIndex !== index) {
        const source = this.addedList[this.dragIndex]
        this.addedList.splice(this.dragIndex, 1)
        this.addedList.splice(index, 0, source)
        this.dragIndex = index
        const ids = this.addedList.map(v => {
          return v.id
        })
        this.transferSave(ids)
      }
    }, 200),
    onDragend (e, index) {
      e.preventDefault()
      const element = e.srcElement
      element.classList.remove('drag-move-item')
      this.$forceUpdate()
    },
    formatMainFunList (addedList = []) {
      this.mainFunList.forEach(v => {
        v.children.forEach(t => {
          t.status = false
          addedList.forEach(s => {
            if (s.id === t.id || s.name === t.name) {
              t.status = true
            }
          })
        })
      })
    },
    onCloseDrawer () {
      // this.tabFixed = false
      // this.tabActive = 0
      this.formatMainFunList(this.commonList)
      this.changeDrawerState(false)
    },
    onSaveDrawer () {
      this.confirmSaveFn()
    },
    setCommonFun () {
      this.changeDrawerState(true)
      this.addedList = JSON.parse(JSON.stringify(this.commonList))
      this.formatMainFunList(this.addedList)
    },
    onRemoveFun (item) {
      item.status = false
      this.addedList.splice(this.addedList.findIndex(add => add.id === item.id || add.name === item.name), 1)
      this.updateMainFunStatus(item)
    },
    onAddFun (item) {
      item.status = true
      this.addedList.unshift(item)
      this.updateMainFunStatus(item)
    },
    onAddedRemove (item) {
      this.addedList.splice(this.addedList.findIndex(add => add.id === item.id), 1)
      this.mainFunList.forEach(v => {
        if (v.children) {
          v.children.forEach(s => {
            if (item.id === s.id || item.name === s.name) {
              s.status = false
              this.$forceUpdate()
            }
          })
        }
      })
      const ids = this.addedList.map(v => {
        return v.id
      })
      this.transferSave(ids)
    },
    goAnchor (item, index) {
      this.isScrollAnchor = false
      const dom = this.$root.$el.querySelector('#' + item.name)
      const offsetTop = this.getOffsetTop(dom)
      // qiankun 子应用选择器获取不到document  改为this.$root.$el
      const scrollDom = this.$root.$el.querySelector('.function-drawer-content')
      // const addTop = this.$root.$el.querySelector('.added-function').offsetHeight
      const scrollTop = offsetTop - 70 - 48
      scrollDom.scrollTo({
        /**
         * 抽屉header高度70px, tabs导航栏高度48px, 滚动子元素h3标题高度60px
         */
        top: scrollTop,
        behavior: 'smooth'
      })
      this.tabActive = index
      setTimeout(() => {
        this.isScrollAnchor = true
      }, 800)
    },
    handleScroll (e) {
      const tabOffsetTop = this.$refs.refContent.getBoundingClientRect().top
      this.tabFixed = tabOffsetTop <= 70
      if (!this.isScrollAnchor) return
      const scrollItems = this.$root.$el.querySelectorAll('.outer-item')
      for (let i = scrollItems.length - 1; i >= 0; i--) {
        // console.log(e.target.scrollTop, this.getOffsetTop(scrollItems[i]), this.getOffsetTop(scrollItems[0]), 'judge')
        const scrollItemTop = this.getOffsetTop(scrollItems[i])
        // 判断滚动条滚动距离是否大于当前滚动项可滚动距离
        const judge =
          e.target.scrollTop >= scrollItemTop - 70 - 48 - 60
        if (judge) {
          this.tabActive = i
          break
        }
      }
    },
    // 获取当前元素的offsetTop
    getOffsetTop (obj) {
      let offsetTop = 0
      while (obj !== window.document.body && obj != null) {
        offsetTop += obj.offsetTop
        obj = obj.offsetParent
      }
      return offsetTop
    },
    updateMainFunStatus (item) {
      this.mainFunList.forEach(v => {
        if (v.children) {
          v.children.forEach(s => {
            if (item.id === s.id || item.name === s.name) {
              s.status = item.status
              this.$forceUpdate()
            }
          })
        }
      })
      this.formatMainFunList(this.addedList)
      const ids = this.addedList.map(v => {
        return v.id
      })
      this.transferSave(ids)
      this.$forceUpdate()
    }
  }
}
</script>

<style lang="scss" scoped>
$main: #2cb7ca;
.drag-move {
  transition: transform .3s;
}
::v-deep{
  .fn-dialog{
    .el-dialog__header,.el-dialog__body{
      padding: 0;
    }
  }
  .transfer-content{
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .selector-card-header{
    margin: 0 0 28px!important;
  }
  .selector-card.s-card{
    width: 100%;
  }
  .selector-card-content{
    display: block!important;
    padding: 0 30px;
  }
  .more-tips{
    margin-top: 20px;
    font-size: 14px;
    line-height: 22px;
    text-align: center;
    color: #686868;
  }
  .drawer-class{
    background: #F2F2F4;
    .el-header{
      padding: 26px 30px;
      font-size: 18px;
      background: #fff;
      box-shadow: 0px -1px 0px 0px rgba(0, 0, 0, 0.05) inset;
    }
    .el-main{
      overflow-y: hidden!important;
    }
    .function-drawer-content{
      height: 100%;
      overflow-y: scroll;
    }
    .added-function{
      padding: 16px 30px 24px;
      background: #fff;
      .added-title{
        line-height: 24px;
        font-size: 16px;
      }
      .no-added{
        padding: 40px;
        text-align: center;
        font-size: 16px;
        color: #686868;
      }
      .added-container{
        display: flex;
        flex-wrap: wrap;
      }
      .added-item{
        position: relative;
        display: flex;
        flex-direction: column;
        align-items: center;
        width: 104px;
        height: fit-content;
        margin: 16px 0 0 0;
        padding: 8px 0;
        text-align: center;
        flex-shrink: 0;
        border-radius: 8px;
        cursor: grabbing;
        .item-name{
          margin-top: 8px;
          line-height: 22px;
          font-size: 14px;
          color: #1D1D1D;
          pointer-events: none;
        }
        .remove-tag{
          position: absolute;
          top: 0;
          right: 8px;
          display: inline-block;
          width: 14px;
          height: 14px;
          line-height: 12px;
          border-radius: 50%;
          background: #FF3A20;
          color: #fff;
          font-weight: bold;
          cursor: pointer;
          font-size: 16px;
        }
      }
      .drag-move-item{
        // padding: 8px 0;
        border: 1px solid rgba(0, 0, 0, 0.05);
        box-shadow: 0px 2px 16px rgba(0, 0, 0, 0.08);
        // border-radius: 8px;
        .remove-tag{
          display: none;
        }
      }
      .drag-init-hide{
        transition: 0.01s;
        transform: translateX(-9999px);
      }
    }
    .classify-function{
      margin-top: 12px;
      .classify-tab{
        width: 100%;
        padding: 0 12px;
        background: #fff;
        white-space: nowrap;
        overflow-x: auto;
        border-bottom: 1px solid rgba(0, 0, 0, 0.05);
        &::-webkit-scrollbar{
          height: 4px;
        }
        &::-webkit-scrollbar-track {
          background-color: #f5f5f5;
        }
        &::-webkit-scrollbar-thumb {
          border-radius: 2px;
          background-color: #ECECEC;
          opacity: 0.15;
        }
      }
      .tab-fixed{
        position: fixed;
        top: 70px;
        width: 100%;
        background: #fff;
        z-index: 10;
        white-space: nowrap;
        overflow-x: auto;
      }
      .tab-item{
        display: inline-block;
        // height: 100%;
        height: 48px;
        line-height: 48px;
        padding: 0 20px;
        cursor: pointer;
        font-size: 16px;
      }
      .active{
        position: relative;
        color: $main;
        &::after{
          position: absolute;
          content: '';
          width: 32px;
          height: 2px;
          bottom: 0;
          left: 50%;
          margin-left: -16px;
          background: $main;
        }
      }
      .classify-content{
        .outer-container,
        .insert-container{
          display: flex;
          flex-direction: column;
        }
        .outer-item{
          padding-left: 30px;
          margin-bottom: 8px;
          background: #fff;
          &:last-child{
            min-height: 100%;
          }
        }
        .outer-item-name{
          padding: 24px 0 8px;
          font-size: 18px;
          line-height: 28px;
          font-weight: 700;
          color: #1D1D1D;
        }
        .insert-item{
          position: relative;
          display: flex;
          align-items: center;
          justify-content: space-between;
          padding: 18px 30px 18px 0;
          &::after{
            position: absolute;
            content: '';
            right: 0;
            left: 60px;
            bottom: 0;
            border-bottom: 1px solid rgba(0, 0, 0, 0.05);
          }
          .el-image{
            width: 44px;
            height: 44px;
            flex-shrink: 0;
          }
        }
        .insert-item-left{
          display: flex;
          align-items: center;
          span{
            margin-left: 16px;
            font-size: 16px;
            line-height: 24px;
          }
        }
        .handle-btn{
          width: 72px;
          height: 30px;
          line-height: 28px;
          text-align: center;
          background: transparent;
          cursor: pointer;
        }
        .add-btn{
          border: 1px solid #E0E0E0;
          color: #1D1D1D;
          border-radius: 4px;
        }
        .remove-btn{
          border: 0;
          font-size: 14px;
          color: #FF3A20;
        }
      }
    }
  }
}
.icon-box-container {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  pointer-events: none;
  ::before{
    content: ''
  }
  ::v-deep {
    .el-image {
      width: 100%;
      height: 100%;
      img {
        width: 100%;
        height: 100%;
      }
    }
  }
}

.icon-set-img{
  display: inline-block;
  width: 18px;
  height: 18px;
  margin-right: 6px;
  background: url('~@/assets/images/icon/icon-set.png') no-repeat center center;
  background-size: contain;
}
.icon-add-img{
  display: inline-block;
  width: 44px;
  height: 44px;
  background: url('~@/assets/images/icon/icon-add.png') no-repeat center center;
  background-size: contain;
}

.header-right-set {
  display: flex;
  align-items: center;
  color: $main;
  font-size: 14px;
  cursor: pointer;
}
.common-lists{
  padding: 0 20px;
  display: flex;
  flex-wrap: wrap;
  .list-item,
  .list-add{
    width: 120px;
    padding: 18px 0 24px;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    cursor: pointer;
  }
  .list-item{
    // flex: 1;
    &:hover{
      span{
        color: $main;
      }
    }
  }
  .item-name,.add-text{
    margin-top: 10px;
    font-size: 14px;
    line-height: 20px;
    color: #1D1D1D;
    @media only screen and (max-width: 1280px) {
      font-size: 12px;
    }
  }
  .item-img{
    width: 44px;
    height: 44px;
  }
  .add-text{
    white-space: nowrap;
    color: #686868;
  }
}
</style>
