<!-- @desc:modal弹窗  @auth:周兴  @time:2022/7/23 15:40 -->
<template>
  <div ref="modal_div" v-if="displayFlag" >
    <Modal
      ref="modal"
      :width="width"
      :ok-text="okText"
      :cancel-text="cancelText"
      :footer-hide="!footerFlag"
      :transfer="transfer"
      :scrollable="scrollable"
      :fullscreen="fullscreen"
      :draggable="draggable"
      :sticky="sticky"
      :reset-drag-position="resetDragPosition"
      :sticky-distance="stickyDistance"
      :closable="closable"
      :lock-scroll="lockScroll"
      v-model="showModal"
      :class-name="className"
      :styles="styles"
      @on-ok="handleOk"
      @on-cancel="handleCancel"
      @on-visible-change="onVisibleChange"
      :z-index="1000"
      :title="title"
      :mask-closable="maskClosable"
      :mask="mask">
      <div slot="header" class="header-class">
        <span>{{ title }}</span>
        <Poptip trigger="hover" transfer v-if="showHeaderIcon">
          <Icon style="cursor: pointer" size="16" type="iconfont iconfont icon-question"/>
          <div slot="content">
            <slot name="headerTip"></slot>
          </div>
        </Poptip>
      </div>
      <slot></slot>
      <!--加载中-->
      <loading :loading="loading" ></loading>
      <div v-if="footerFlag" slot="footer" style="display: flex;float: right;margin-bottom: 10px">
        <slot name="footer"></slot>
        <!--      <DkButton :loading="loading" v-if="okVisibleFlag" type="primary" @click="modalOk" name="confirm" :ref="saveFlag?'save':'confirm'">{{ saveFlag?$t('save') :$t('confirm') }}</DkButton>-->
        <!--      <DkButton v-if="cancelVisibleFlag" @click="modalCancel" name="close" ref="close">{{ $t('close') }}</DkButton>-->
        <DkButton :loading="loading" v-if="okVisibleFlag" type="primary" @click="modalOk" name="confirm"
                  :ref="saveFlag?'save':'confirm'">{{ saveFlag ? '保存(S)' : '确定(O)' }}
        </DkButton>
        <DkButton v-if="cancelVisibleFlag" @click="modalCancel" name="close" :ref="saveFlag?'close':'cancel'">{{ saveFlag ? '关闭(X)' : '取消(Y)' }}</DkButton>
      </div>
    </Modal>
  </div>
</template>

<script>
import {button as buttonList} from "@/locale/lang/zh-CN";
import {localRead, localSave} from "@/libs/base/util";

export default {
  name: "dk-modal",
  props: {
    value: {
      type: Boolean,
      default: false
    },
    // 标题
    title: {
      type: String,
      default: ''
    },
    // 距离上面的距离
    top: {
      type: [String, Number],
      default: 0
    },
    // 距离左侧的距离
    left: {
      type: [String, Number],
      default: 0
    },
    position: {
      type: String,
      default: 'relative'
    },
    // 宽度
    width: {
      type: [String, Number],
      default: '500px'
    },
    // 高度
    height: {
      type: [String, Number],
      default: null
    },
    // 是否显示底部区域
    footerFlag: {
      type: Boolean,
      default: true
    },
    // 按钮显示文本是保存还是确定，true为保存
    saveFlag: {
      type: Boolean,
      default: false
    },
    // 确定按钮是否可见
    okVisibleFlag: {
      type: Boolean,
      default: true
    },
    // 关闭按钮是否可见
    cancelVisibleFlag: {
      type: Boolean,
      default: true
    },
    // 为modal增加className
    className: {
      type: String,
      default: ''
    },
    okText: {
      type: String,
      default: ''
    },
    cancelText: {
      type: String,
      default: ''
    },
    // 是否将弹层放置于 body 内
    transfer: {
      type: Boolean,
      default: true
    },
    //是否可以滚动
    scrollable: {
      type: Boolean,
      default: false
    },
    //是否全屏显示
    fullscreen: {
      type: Boolean,
      default: false
    },
    // 是否可以拖拽
    draggable: {
      type: Boolean,
      default: true
    },
    // 拖拽时，是否吸附屏幕边缘
    sticky: {
      type: Boolean,
      default: true
    },
    // Modal 再次打开时，是否重置拖拽的位置
    resetDragPosition: {
      type: Boolean,
      default: false
    },
    // 拖拽时，自动吸附屏幕边缘的临界距离
    stickyDistance: {
      type: Number,
      default: 10
    },
    //是否显示右上角的关闭按钮，关闭后 Esc 按键也将关闭
    closable: {
      type: Boolean,
      default: true
    },
    // 是否禁止对页面滚动条的修改
    lockScroll: {
      type: Boolean,
      default: false
    },
    // 校验form的name名称
    validFormName: {
      type: String,
      default: 'dk-form'
    },
    loading: {
      type: Boolean,
      default: false
    },
    //点击遮罩层是否可以关闭model，默认可以
    maskClosable: {
      type: Boolean,
      default: true
    },
    //是否显示遮罩层阴影，默认显示
    mask: {
      type: Boolean,
      default: true
    },
    // 是否显示表头图标
    showHeaderIcon: {
      type: Boolean,
      default: false
    },
    // 关闭是否清空数据
    autoClearFlag: {
      type: Boolean,
      default: true
    },
    // 快捷键
    shortcutFlag:{
      type: Boolean,
      default: true
    },
    // 校验多个form的ref名称
    validFormRefList: {
      type: Array,
    }
  },
  watch: {
    value(n, o) {
      // console.log('u',n)
      this.showModal = n;
    },
    showModal(n, o) {
      this.$emit('input', n)
      if(n){
        this.displayFlag = true;
        this.onVisibleChange(true);
        if(this.shortcutFlag){
          this.addKeyBoardEvent();
        }
      }else{
        if(this.shortcutFlag) {
          //恢复快捷键
          document.onkeydown = this.documentKeyDownContent;
        }
      }
    }
  },
  data() {
    const vm = Window.vm;
    let self = this
    return {
      vm: vm ? vm : self,
      displayFlag:true,
      documentKeyDownContent: Object,
      showModal: false,
      openFlag:false,// 避免首次打开会调用两次
      styles: {
        minWidth: self.width,
        height: self.height,
        position: self.position
      }
    }
  },
  methods: {
    /**
     * @desc   : 监听全局键盘按钮按下的事件
     * @author : 周兴
     * @date   : 2022/3/4 16:57
     */
    addKeyBoardEvent() {
      let code = 0
      let self = this
      this.documentKeyDownContent = document.onkeydown
      document.onkeydown = function (e) {
        const evn = e || event
        const key = evn.keyCode || evn.which || evn.charCode
        // alt：code = 18
        if (key === 18) {
          code = 18
        }
        //只有modal弹出才能可见
        if (self.showModal) {
          // 查询子模块是否开着
          let currentModal = null
          let modalName = ''
          for (let it of Object.keys(self.$refs)) {
            // 如果没有放大镜的查询，那么就看这个界面的查询
            if (it.startsWith('modal_') && self.$refs[it] && it !== 'modal_div' ) {
              currentModal = self.$refs[it]
              modalName = it
              break
            }
          }
          // Q：code = 81 查询
          let btList = Object.values(self.$config.button);
          btList.forEach(forIt => {
            if (code === 18 && forIt.hotKey?.toLowerCase() === e.key.toLowerCase()) {
              e.returnValue = false
              // 如果模块开着，在前面加上模块的ref名
              if (currentModal != null) {
                if (self.$refs[modalName].$refs[forIt.name]) {
                  self.$refs[modalName].$refs[forIt.name].$el.click()
                }
              } else {
                if (self.$refs[forIt.name]) {
                  self.$refs[forIt.name].$el.click()
                }
              }
            }
          })
        }
      }
      // 监听全局键盘按钮松开的事件
      document.onkeyup = function (e) {
        const evn = e || event
        const key = evn.keyCode || evn.which || evn.charCode
        if (key === 18) {
          code = 0
        }
        // 一秒钟失效，避免因为按了alt+tab之后再回来，按其他什么英文字母都不好使了的问题
        setTimeout(() => {
          code = 0
        }, 1000)
      }
    },
    /**
     * @desc   : modal可见触发的事件
     * @author : 周兴
     * @date   : 2022/7/23 17:35
     */
    onVisibleChange(e) {
      if(!this.openFlag){
        this.openFlag = true;
        this.$emit('on-visible-change', e)
        // 1s后才会置为发false
        setTimeout(()=>{
          this.openFlag = false;
        },1000)
      }

      if (e) {
        // console.log('ttttt',this.$route,localRead(this.$route.name + '_temp'))
        // // if(data && !this.isEmpty(data)){
        // //   // 记录缓存
        // //   localSave(this.$route.name + '_temp', JSON.stringify(data));
        // // }
        // let tempData = localRead(this.$route.name + '_temp');
        // if(tempData){
        //   this.$refs.modal.$slots.default[0].componentInstance.$refs[this.validFormName].model = tempData
        // }
        this.$nextTick(() => {
          this.focus();   // 聚焦到第一个组件上
        })
      }else{
        this.$nextTick(()=>{
          this.displayFlag = false;
        })
      }
    },
    /**
     * @desc   : 记录缓存数据
     * @author : 周兴
     * @date   : 2024/4/9 9:44
     */
    handleTempData(data){
      // console.log('dd1d',data,this.$route)
      // if(data && !this.isEmpty(data)){
      //   // 记录缓存
      //   localSave(this.$route.name + '_temp', JSON.stringify(data));
      // }
    },
    /**
     * @desc   : 点击ok
     * @author : 周兴
     * @date   : 2022/7/23 17:35
     */
    handleOk(e) {
      this.$emit('on-ok', e)
    },
    /**
     * @desc   : 点击cancel
     * @author : 周兴
     * @date   : 2022/7/23 17:35
     */
    handleCancel(e) {
      // 清空form中的数据 resetFields(要求form表单中名称必须一致，有些值就清除不掉）
      if (this.$refs.modal && this.$refs.modal.$slots && this.$refs.modal.$slots.default
        && this.$refs.modal.$slots.default.length > 0
        && this.$refs.modal.$slots.default[0].componentInstance) {
        if(this.$refs.modal.$slots.default[0].componentInstance.$refs[this.validFormName]
          && this.$refs.modal.$slots.default[0].componentInstance.$refs[this.validFormName].resetFields){
          this.handleTempData(this.$refs.modal.$slots.default[0].componentInstance.$refs[this.validFormName].model);
          this.$refs.modal.$slots.default[0].componentInstance.$refs[this.validFormName].resetFields();
        }
        if(this.$refs.modal.$slots.default[0].componentInstance.resetFields){
          this.handleTempData(this.$refs.modal.$slots.default[0].componentInstance.model);
          this.$refs.modal.$slots.default[0].componentInstance.resetFields();
        }
      }
      this.showModal = false;
      this.$emit('on-cancel', e)
    },
    /**
     * @desc   : 点击ok
     * @author : 周兴
     * @date   : 2022/7/23 17:36
     */
    async modalOk() {
      if (this.$refs.modal && this.$refs.modal.$slots && this.$refs.modal.$slots.default
        && this.$refs.modal.$slots.default.length > 0
        && this.$refs.modal.$slots.default[0].componentInstance) {
        let componentInstance = this.$refs.modal.$slots.default[0].componentInstance;
        let tag = componentInstance.$vnode.tag;
        // 如果modal当中包括了collapse组件
        if(tag?.endsWith('collapse') && componentInstance.formList && componentInstance.formList.length > 0){
          // 多个form表单的校验
          let flag = true;
          await componentInstance.formList.forEach(it => {
            it.validate().then(valid => {
              if (!valid) {
                flag = false;
              }
            })
          })
          // 通过校验,进行保存操作
          if (flag) {
            this.$emit('modalOk');
          }
        }
        //如果校验开启，需要进行校验
        else if (this.validFormRefList && this.validFormRefList.length > 0) {
          // 多个form表单的校验
          let flag = true;
          await this.validFormRefList.forEach(it => {
            if (componentInstance.$refs[it]) {
              componentInstance.$refs[it].validate().then(valid => {
                if (!valid) {
                  flag = false;
                }
              })
            }
          })
          // 通过校验,进行保存操作
          if (flag) {
            this.$emit('modalOk');
          }
        } else if (componentInstance.$refs[this.validFormName]) {
          // 单个form校验
          componentInstance.$refs[this.validFormName].validate().then(valid => {
            if (!valid) {
              return;
            }
            this.$emit('modalOk');
          })
        } else {
          this.$emit('modalOk');
        }
      }else{
        this.$emit('modalOk');
      }
    },
    /**
     * @desc   : 点击关闭
     * @author : 周兴
     * @date   : 2022/7/24 10:52
     */
    modalCancel() {
      // 清空form中的数据 resetFields(要求form表单中名称必须一致，有些值就清除不掉）
      if (this.$refs.modal && this.$refs.modal.$slots && this.$refs.modal.$slots.default
        && this.$refs.modal.$slots.default.length > 0
        && this.$refs.modal.$slots.default[0].componentInstance) {
        if(this.$refs.modal.$slots.default[0].componentInstance.$refs[this.validFormName]
          && this.$refs.modal.$slots.default[0].componentInstance.$refs[this.validFormName].resetFields){
          this.handleTempData(this.$refs.modal.$slots.default[0].componentInstance.$refs[this.validFormName].model);
          this.$refs.modal.$slots.default[0].componentInstance.$refs[this.validFormName].resetFields();
        }
        if(this.$refs.modal.$slots.default[0].componentInstance.resetFields){
          this.handleTempData(this.$refs.modal.$slots.default[0].componentInstance.model);
          this.$refs.modal.$slots.default[0].componentInstance.resetFields();
        }
      }
      this.showModal = false;
      this.$emit('input', false)
      this.$emit('modalCancel')
    },
    /**
     * @desc   : 聚焦到第一个组件上
     * @author : 周兴
     * @date   : 2022/12/26 10:33
     */
    focus() {
      // 控制光标放到第一个元素上
      if (this.$refs['modal'] && this.$refs['modal'].$slots.default
        && this.$refs['modal'].$slots.default.length > 0
        && this.$refs['modal'].$slots.default[0].componentInstance) {
        let instance = this.$refs['modal'].$slots.default[0].componentInstance;
        if (instance && instance.focus) {
          instance.focus();
        }
      }
    },
    /**
     * @desc   : 控制弹起
     * @author : 周兴
     * @date   : 2023/4/13 14:55
     */
    handleKeyup(e) {
      if (e.key === 'Tab' && document.activeElement && document.activeElement.name === 'close') {
        // 如果是到关闭按钮，就把当前打回第一控件上
        this.focus();
      }
    },
  },
  created() {
    if (this.top) {
      Object.assign(this.styles, {top: this.top})
    }
    if (this.left) {
      Object.assign(this.styles, {left: this.left})
    }
  },
  beforeDestroy() {
    window.removeEventListener('keyup', this.handleKeyup)
    this.showModal = null;
  },
  mounted() {
    let self = this;
    //监听窗口变化
    window.addEventListener('keyup', self.handleKeyup)
  }
}
</script>

<style lang="scss" scoped>
.header-class {
  font-weight: bold;
}

/deep/ .ivu-modal-body {
  padding: 0 10px 2px 10px !important;
}

/deep/.search-data-class {
  .ivu-modal-body{
    height: 500px !important;
  }
  .ivu-modal-content{
    background: linear-gradient(356.41deg, #FFFFFF 79.81%, #DFE4F9 96.71%);
    box-shadow: 0px 3px 8px 0px rgba(146, 179, 186, 0.25);
  }
  .btn-div{
    background-color: transparent!important;
  }
}

/deep/.change-class {
  .ivu-modal-content{
    background: linear-gradient(356.41deg, #FFFFFF 79.81%, #DFE4F9 96.71%);
    box-shadow: 0px 3px 8px 0px rgba(146, 179, 186, 0.25);
  }
  .btn-div{
    background-color: transparent!important;
  }
}

/deep/ .ivu-modal-fullscreen {
  height: 100%;
}

/deep/ .ivu-modal-fullscreen .ivu-modal-body {
  overflow-x: hidden !important;
}

</style>
