<template>
  <div class="widget-panel">
    <div v-if="data.list.length == 0" class="form-empty">
      从左侧拖拽布局和字段来设计表单
    </div>
    <div
      class="outer-container"
      ref="outerContainer"
      :class="{'scrollbar-container': formType !== 'mobile'}"
    >
      <div
        class="inner-container"
        :class="{'scrollbar-container': formType === 'mobile'}"
        style="padding: 20px 0"
      >
        <el-scrollbar
          class="scrollbar-fullheight"
          :class="{'mobile-scrollbar': formType === 'mobile'}"
        >
          <div v-if="formType === 'mobile'" class="mobile-model__container">
            <div class="mobile-model__header"></div>
            <div class="mobile-model__body"></div>
            <div class="mobile-model__bottom"></div>
          </div>
          <div v-if="formType !== 'mobile'" class="widget-panel_width">
            <label>占屏比例：</label>
            <ht-radio
              v-model="widthSetting.widthType"
              :options="widthOption"
              :props="{key: 'key', value: 'text'}"
              class="widget-panel_width_radio"
              @change="widthTypeChange"
            ></ht-radio>
            <ht-input
              v-model="widthSetting.widthValue"
              type="number"
              class="widget-panel_width_number"
              controls-position="left"
              size="mini"
              company="%"
              :min="0"
              :max="100"
              @change="widthValueChange"
            ></ht-input>
          </div>
          <el-form
            class="widget-panel_form"
            :size="data.config.size"
            :label-position="data.config.labelPosition"
            :label-width="data.config.labelWidth + 'px'"
            :style="{
              width:
                widthSetting.widthType === 'normal'
                  ? '60%'
                  : widthSetting.widthType === 'personal'
                  ? widthSetting.widthValue + '%'
                  : '100%',
            }"
          >
            <draggable
              v-model="data.list"
              v-bind="{
                group: 'form',
                ghostClass: 'ghost',
                animation: 200,
                handle: '.drag-widget',
              }"
              @start="handleMoveStart"
              @add="handleWidgetAdd"
              @input="handleChange($event)"
            >
              <transition-group
                name="fade"
                tag="div"
                class="widget-form-list"
                :class="{'widget-form__bg': formType === 'mobile'}"
              >
                <template
                  v-for="(element, index) in data.list.filter((d) => d.key)"
                >
                  <template v-if="element.ctrlType == 'grid'">
                    <widget-grid-layout
                      :key="element.key + tempKey"
                      :data.sync="data"
                      :selectWidgetList.sync="selectWidgetList"
                      :index="index"
                      :select="selectWidget"
                      :element="element"
                      :top-data="data"
                    />
                  </template>
                  <template v-else-if="element.ctrlType == 'tab'">
                    <widget-table-layout
                      :key="element.key + tempKey"
                      :data.sync="data"
                      :selectWidgetList.sync="selectWidgetList"
                      :index="index"
                      :select="selectWidget"
                      :element="element"
                      :top-data="data"
                      @click-tab="handleClickTab"
                    />
                  </template>
                  <template v-else-if="element.ctrlType == 'page'">
                    <widget-pagination-layout
                      :key="element.key + tempKey"
                      :data.sync="data"
                      :index="index"
                      :select="selectWidget"
                      :selectWidgetList.sync="selectWidgetList"
                      :element="element"
                      :top-data="data"
                    />
                  </template>
                  <template v-else-if="element.ctrlType == 'pageSteps'">
                    <widget-page-steps-layout
                      :key="element.key + tempKey"
                      :data.sync="data"
                      :selectWidgetList.sync="selectWidgetList"
                      :index="index"
                      :select="selectWidget"
                      :element="element"
                      :top-data="data"
                    />
                  </template>
                  <template v-else-if="element.ctrlType == 'pageButton'">
                    <widget-page-button-layout
                      :key="element.key + tempKey"
                      :data.sync="data"
                      :selectWidgetList.sync="selectWidgetList"
                      :index="index"
                      :select="selectWidget"
                      :element="element"
                      :top-data="data"
                    />
                  </template>
                  <template v-else-if="element.ctrlType == 'accordion'">
                    <widget-collapse-layout
                      :key="element.key + tempKey"
                      :data.sync="data"
                      :selectWidgetList.sync="selectWidgetList"
                      :index="index"
                      :select="selectWidget"
                      :element="element"
                      :top-data="data"
                      @get-collapse-active-name="getCollapseActiveName"
                    />
                  </template>
                  <template v-else-if="element.ctrlType == 'subtable'">
                    <widget-subtable-layout
                      :key="element.key + tempKey"
                      :data.sync="data"
                      :selectWidgetList.sync="selectWidgetList"
                      :index="index"
                      :select="selectWidget"
                      :element.sync="element"
                      :top-data="data"
                    />
                  </template>
                  <template v-else-if="element.ctrlType == 'subDiv'">
                    <widget-subdiv-layout
                      :key="element.key + tempKey"
                      :data.sync="data"
                      :selectWidgetList.sync="selectWidgetList"
                      :index="index"
                      :select="selectWidget"
                      :element.sync="element"
                      :top-data="data"
                    />
                  </template>
                  <template v-else-if="element.ctrlType == 'dataView'">
                    <widget-data-view-layout
                      :key="element.key + tempKey"
                      :data.sync="data"
                      :selectWidgetList.sync="selectWidgetList"
                      :index="index"
                      :select="selectWidget"
                      :element="element"
                      :top-data="data"
                    />
                  </template>
                  <template v-else-if="element.ctrlType == 'hottable'">
                    <widget-hottable-layout
                      :key="element.key + tempKey"
                      :data.sync="data"
                      :selectWidgetList.sync="selectWidgetList"
                      :index="index"
                      :select="selectWidget"
                      :element.sync="element"
                      :top-data="data"
                    />
                  </template>
                  <template v-else-if="element.ctrlType == 'table'">
                    <widget-main-table-layout
                      :key="element.key + tempKey"
                      :data.sync="data"
                      :select="selectWidget"
                      :selectWidgetList.sync="selectWidgetList"
                      :index="index"
                      :element="element"
                      :top-data="data"
                    />
                  </template>
                  <template v-else>
                    <widget-form-item
                      :key="element.key + tempKey"
                      :element="element"
                      :select="selectWidget"
                      :selectWidgetList.sync="selectWidgetList"
                      :index="index"
                      :data.sync="data"
                      :top-data="data"
                    ></widget-form-item>
                  </template>
                </template>
              </transition-group>
            </draggable>
          </el-form>
        </el-scrollbar>
      </div>
    </div>
  </div>
</template>

<script>
import Draggable from 'vuedraggable'
import WidgetFormItem from '@/components/form/WidgetFormItem.vue'
import WidgetGridLayout from '@/components/form/WidgetGridLayout.vue'
import WidgetTableLayout from '@/components/form/WidgetTableLayout.vue'
import WidgetPaginationLayout from '@/components/form/WidgetPaginationLayout.vue'
import WidgetCollapseLayout from '@/components/form/WidgetCollapseLayout.vue'
import WidgetSubtableLayout from '@/components/form/WidgetSubtableLayout.vue'
import WidgetSubdivLayout from '@/components/form/WidgetSubDivLayout.vue'
import WidgetPageStepsLayout from '@/components/form/WidgetPageStepsLayout.vue'
import WidgetPageButtonLayout from '@/components/form/WidgetPageButtonLayout.vue'
import WidgetDataViewLayout from '@/components/form/WidgetDataViewLayout.vue'
import WidgetHottableLayout from '@/components/form/WidgetHottableLayout.vue'
import WidgetMainTableLayout from '@/components/form/WidgetMainTableLayout.vue'
import deepmerge from 'deepmerge'
import {mapState, mapMutations} from 'vuex'
import updateSelectControl from '@/mixins/updateSelectControl.js'
export default {
  name: 'widget-panel',
  components: {
    Draggable,
    WidgetGridLayout,
    WidgetTableLayout,
    WidgetPaginationLayout,
    WidgetCollapseLayout,
    WidgetSubtableLayout,
    WidgetSubdivLayout,
    WidgetFormItem,
    WidgetPageStepsLayout,
    WidgetPageButtonLayout,
    WidgetDataViewLayout,
    WidgetHottableLayout,
    WidgetMainTableLayout
  },
  props: ['data', 'select', 'selectWidgetList', 'formType', 'formData'],
  mixins: [updateSelectControl],
  data() {
    return {
      tempKey: '',
      widthSetting: {
        // 宽度配置
        widthType: 'fullscreen',
        widthValue: 60
      },
      // selectWidget: this.select,
      widthOption: [
        {text: '正常(0.6)', key: 'normal'},
        {text: '全屏', key: 'fullscreen'},
        {text: '自定义', key: 'personal'}
      ]
    }
  },
  computed: {
    ...mapState('form', ['selectWidget'])
  },
  created() {
    this.initWidthSetting()
  },
  mounted() {
    document.body.ondrop = function(event) {
      let isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1
      if (isFirefox) {
        event.preventDefault()
        event.stopPropagation()
      }
    }
    this.$refs.outerContainer.addEventListener('dragover', this.handleDragOver)
  },
  methods: {
    ...mapMutations({
      setSelectWidget: 'form/setSelectWidget', // 设置当前选中控件
    }),
    handleDragOver(event) {
      // 获取鼠标相对于外层容器的位置
      const mouseY =
        event.clientY - this.$refs.outerContainer.getBoundingClientRect().top
      // 外层容器的高度
      const containerHeight = this.$refs.outerContainer.clientHeight

      // 如果鼠标接近容器的上边界，向上滚动
      if (mouseY < 150) {
        this.$refs.outerContainer.scrollTop -= 5 // 调整滚动速度
      }
      // 如果鼠标接近容器的下边界，向下滚动
      else if (mouseY > containerHeight - 200) {
        this.$refs.outerContainer.scrollTop += 20 // 调整滚动速度
      }
    },
    handleClickTab(index) {
      this.$emit('click-tab', index)
    },
    getCollapseActiveName(activeNames) {
      this.$emit('get-collapse-active-name', activeNames)
    },
    initWidthSetting() {
      if (!this.formData.formSetting) {
        this.formData.formSetting = JSON.stringify({...this.widthSetting,formWidthStr:`${this.widthSetting.widthValue}%`})
      } else if (
        this.formData.formSetting &&
        !JSON.parse(this.formData.formSetting).widthType
      ) {
        let obj = JSON.parse(this.formData.formSetting)
        obj.widthType = this.widthSetting.widthType
        obj.widthValue = this.widthSetting.widthValue
        obj.formWidthStr = `${this.widthSetting.widthValue}%`
        this.formData.formSetting = JSON.stringify(obj)
       }else if(this.formData.formSetting && !JSON.parse(this.formData.formSetting).formWidthStr){
        let formSettings = JSON.parse(this.formData.formSetting)
        formSettings.formWidthStr = `${formSettings.widthValue}%`
        this.formData.formSetting = JSON.stringify(formSettings)
      } else {
        this.widthSetting.widthType =
          JSON.parse(this.formData.formSetting).widthType || 'fullscreen'
        this.widthSetting.widthValue =
          JSON.parse(this.formData.formSetting).widthValue || 60
      }
    },
    widthValueChange(value) {
      let obj = JSON.parse(this.formData.formSetting)
      obj.widthValue = value
      obj.formWidthStr = `${this.widthSetting.widthValue}%`
      obj.widthValue = Number(value)
      this.formData.formSetting = JSON.stringify(obj)
    },
    // 宽度配置变化
    widthTypeChange(value) {
      let obj = JSON.parse(this.formData.formSetting)
      obj.widthType = value
      if (value === 'personal') {
        obj.widthValue = this.widthSetting.widthValue
        obj.formWidthStr = `${this.widthSetting.widthValue}%`
      }
      this.formData.formSetting = JSON.stringify(obj)
    },
    handleMoveStart: function(evt) {
      window.panelList = this.data.list
      // 新增控件时  将控件属性切断联系
      evt.item._underlying_vm_ = deepmerge({}, evt.item._underlying_vm_, {
        clone: true
      })
      const key =
        Date.parse(new Date()) + '_' + Math.ceil(Math.random() * 99999)
      evt.item._underlying_vm_.key = key

      evt.item._data_vm_ = deepmerge({}, this.data.list, {
        clone: true
      })
      evt.item._p_vm_ = this.data
    },
    handleSelectWidget(index) {
      this.setSelectWidget(this.data.list[index])
    },
    handleAddBack($event, newIndex) {
      this.data.list.splice(newIndex, 1)
      if ($event.item._p_vm_) {
        $event.item._p_vm_.list = $event.item._data_vm_
      }
    },
    handleWidgetAdd(evt) {
      const newIndex = evt.newIndex
      const item = evt.item
      const itemVm = item._underlying_vm_
      if (
        itemVm.isLayout &&
        item.__vue__ &&
        item.__vue__.element &&
        item.__vue__.element.parentNodeType === 'sub' &&
        item.__vue__.element.columns.some(it => it.list.length)
      ) {
        this.$message.warning('子表中的有控件的栅格布局控件不允许拖出')
        this.handleAddBack(evt, newIndex)
        return false
      }
      const isSunTable =
        item.__vue__ &&
        item.__vue__.element &&
        item.__vue__.element.ctrlType === 'sunDiv'
      if (
        item.innerText == '孙表' ||
        isSunTable ||
        itemVm.ctrlType === 'sunDiv'
      ) {
        this.$message.error('孙表只能存在子表中')
        this.handleAddBack(evt, newIndex)
        return false
      }
      //拖拽的控件是高德地图控件时，判断是否已经存在高德地图控件
      const vueInst = this
      //拖字段属性时防止子表和孙表字段拖入非对应布局中
      if (
        vueInst.data.list[newIndex] &&
        vueInst.data.list[newIndex].fieldPath
      ) {
        if (
          vueInst.data.list[newIndex].fieldPath.indexOf('item.') == 0 &&
          !itemVm.options.noBindModel
        ) {
          this.$message.error('子表字段只能存在子表中')
          this.handleAddBack(evt, newIndex)
          return false
        } else if (
          vueInst.data.list[newIndex].fieldPath.split('.').length == 4 &&
          !itemVm.options.noBindModel
        ) {
          this.$message.error('孙表字段只能存在子表中')
          this.handleAddBack(evt, newIndex)
          return false
        }
      }
      let amapNum = 0
      for (let i = vueInst.data.list.length - 1; i >= 0; i--) {
        if (['amap','tianditu'].includes(vueInst.data.list[i].ctrlType)) {
          amapNum = amapNum + 1
        }
      }
      //amapNum为1代表只存在一个高德地图控件，大于1则拖拽的控件也是高德地图控件
      if (amapNum > 1) {
        for (let j = vueInst.data.list.length - 1; j >= 0; j--) {
          if (
            ['amap','tianditu'].includes(vueInst.data.list[i].ctrlType) &&
            !vueInst.data.list[j].options.addressName
          ) {
            this.$message.error('已存在地图控件')
            vueInst.data.list.splice(j, 1)
            return
          }
        }
      }
      const to = evt.to
      this.setSelectWidget(this.data.list[newIndex])
      //如果启用了分页布局,就不能在开头与结尾添加东西了
      if (this.data.pageSize && this.data.pageSize >= 2) {
        if (evt.newIndex == 0) {
          let dataEn = this.data.list[0]
          this.data.list.splice(0, 1)
          this.data.list.splice(1, 0, dataEn)
        } else if (evt.newIndex == this.data.list.length - 1) {
          let dataEn = this.data.list[evt.newIndex]
          this.data.list.splice(evt.newIndex, 1)
          this.data.list.splice(this.data.list.length - 1, 0, dataEn)
        }
      }
      //如果是分页布局.第一次拖入,会额外添加一个步骤条的头,与一个页尾
      if (this.selectWidget.ctrlType == 'page') {
        if (
          this.data.pageSize &&
          (this.data.pageSize == 2 || this.data.pageSize > 2)
        ) {
          this.data.pageSize += 1
          this.data.list[0].pageSize = this.data.pageSize
          this.data.list[0].pageStepsArr.push({
            name: '分页' + (this.data.list[0].pageStepsArr.length + 1)
          })
        } else {
          this.data.pageSize = 2
          let pageSteps = {
            ctrlType: 'pageSteps',
            desc: '分页步骤条',
            key: '1581473408000_37810',
            isShow: true,
            isLayout: true,
            columns: [
              {
                list: []
              }
            ],
            pageSize: 2,
            pageStepsArr: [{name: '分页1'}, {name: '分页2'}]
          }

          this.data.list.splice(0, 0, pageSteps)
          let pageButton = {
            ctrlType: 'pageButton',
            desc: '分页步骤按钮',
            key: '1581473408000_37811',
            isLayout: true,
            columns: [
              {
                list: []
              }
            ],
            nextButton: {
              name: '下一步',
              icon: '',
              color: '#409eff',
              preScript: '',
              rearScript: ''
            },
            backButton: {
              name: '上一步',
              icon: '',
              color: '#67C23A',
              preScript: '',
              rearScript: ''
            }
          }
          this.data.list.push(pageButton)
        }
      }

      // 直接拖拽的子表属性
      if (itemVm.ctrlType === 'subtable') {
        // 将子表的 name 绑定给所有子元素 boSubEntity
        itemVm.list.forEach(i => {
          i.boSubEntity = itemVm.name
        })
      }
    },
    handleChange(arr) {
      this.data.list.remove(this.data.list.length - 1)
    }
  },
  watch: {
    formData(newValue, oldValue) {
      if (newValue && newValue.formSetting) {
        this.initWidthSetting()
      }
      this.tempKey = new Date();
    }
  }
}
</script>
<style lang="scss" scoped>
@import '@/assets/css/element-variables.scss';

.widget-panel {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  .widget-panel_width {
    display: flex;
    align-items: center;
    justify-content: center;
    padding-top: 22px;
    padding-bottom: 10px;
    label {
      color: #333;
      font-size: 16px;
    }
    .widget-panel_width_radio {
      width: auto;
      ::v-deep .el-radio-group {
        vertical-align: sub;
      }
    }
    .widget-panel_width_number {
      width: 128px;
      align-items: center;
    }
  }
  .widget-panel_form {
    margin: 0 auto;
  }
}
::v-deep .has-company-box .el-input-number {
  width: auto !important;
}
.scrollbar-fullheight {
  height: 100%;
}

.widget-form-list {
  padding: 10px 15px;
  background: #fff;
  border: 1px solid #dfdfdf;
  min-height: 600px;
  margin: 10px;
}
.widget-form__bg {
  width: 375px;
  margin: 10px auto;
  border-radius: 36px;
}
.form-empty {
  position: absolute;
  text-align: center;
  width: 300px;
  font-size: 20px;
  top: 200px;
  left: 50%;
  margin-left: -150px;
  color: #ccc;
}
.mobile-scrollbar {
  position: relative;
  /* text-align: center; */
  display: flex;
  align-items: center;
  justify-content: center;
  ::v-deep .el-scrollbar__wrap {
    background: url('../../assets/img/mobile-android.png') no-repeat center
      center;
    background-size: calc(100% + 36px) calc(100% + 60px);
    width: 400px;
    height: 800px;
    position: absolute;
    top: 50%;
    // left: 50%;
    margin-left: -200px;
    margin-top: -450px;
    border: 20px solid transparent;
    border-width: 30px 20px 36px 20px;

    scrollbar-width: 0;
    -ms-overflow-style: none;
    &::-webkit-scrollbar {
      width: 0;
    }
    //////
    height: calc(100% - 152px) !important;
    margin: 20px 0;
    /* margin-top: 48px; */
    position: absolute;
    top: 28px;
    text-align: center;
  }
  .widget-form-list {
    background: none;
    border: none;
  }
}

.scrollbar-container {
  overflow: auto;
  height: calc(100vh - 60px);
}
</style>
