<template>
  <div class="panel">
    <el-tabs
      class="panel__tabs"
      v-model="activeName"
      @tab-click="handleClick"
      :stretch="true"
    >
      <el-tab-pane label="控件" name="controlLayout" class="control-layout">
        <div class="search-Box">
          <el-autocomplete
            class="inline-input"
            v-model="controlSearch"
            :fetch-suggestions="querySearch"
            placeholder="请输入关键字"
            suffix-icon="el-icon-search"
            :trigger-on-focus="false"
            style="margin-left: 14px; width: 226px"
            @select="handleSelect"
            @keyup.enter.native="search"
            clearable
          ></el-autocomplete>
        </div>
        <el-scrollbar class="scrollbar-fullheight">
          <div class="control-list">
            <el-collapse v-model="activeNames">
              <el-collapse-item
                v-for="(item, index) in allComponentList"
                :key="index"
                :name="item.id"
              >
                <template slot="title">
                  <i
                    class="iconcolor"
                    :class="
                      activeNames.includes(item.id)
                        ? 'el-icon-caret-bottom'
                        : 'el-icon-caret-top'
                    "
                  ></i>
                  <div class="widget-cate">{{ item.name }}</div>
                </template>
                <template>
                  <draggable
                    tag="ul"
                    class="flex-container"
                    :list="item.children"
                    v-bind="{
                      group: {name: 'form', pull: 'clone', put: false},
                      sort: false,
                      ghostClass: 'ghost',
                    }"
                    @end="handleMoveEnd"
                    @start="handleMoveStart"
                    :move="handleMove"
                  >
                    <li
                      class="flex-item dash-border"
                      :class="{
                        'no-put': item.type == 'divider',
                        'is-switch': item2.ctrlType == 'switch',
                      }"
                      v-for="(item2, index2) in item.children"
                      v-show="
                        (formType === 'pc' && item2.ctrlType != 'hottable') ||
                        (formType === 'mobile' &&
                          (item.id == '1'
                            ? mobileShowLayout.includes(item2.ctrlType)
                            : !invisibleMobileAdvance.includes(
                                item2.ctrlType
                              ))) ||
                        (!formType && item2.ctrlType != 'hottable')
                      "
                      :key="index2"
                      :id="item2.desc"
                    >
                      <a :class="item2.desc == controlSearch ? 'active' : ''">
                        <i :class="item2.icon"></i>
                        <span>{{ item2.desc }}</span>
                      </a>
                    </li>
                  </draggable>
                </template>
              </el-collapse-item>
            </el-collapse>
          </div>
        </el-scrollbar>
      </el-tab-pane>
      <el-tab-pane label="属性" name="attributeField">
        <el-scrollbar class="scrollbar-fullheight attribute-scrollbar">
          <div class="control-list">
            <template v-if="layoutComponents.length">
              <div class="widget-cate">布局</div>
              <draggable
                tag="ul"
                class="flex-container"
                :list="layoutComponents"
                v-bind="{
                  group: {name: 'form', pull: 'clone', put: false},
                  sort: false,
                  ghostClass: 'ghost',
                }"
                @end="handleMoveEnd"
                @start="handleMoveStart"
                :move="handleMove"
              >
                <li
                  class="flex-item dash-border"
                  :class="{'no-put': item.type == 'divider'}"
                  v-for="(item, index) in layoutComponents"
                  v-show="
                    (formType === 'pc' && item.ctrlType != 'hottable') ||
                    (formType === 'mobile' &&
                      mobileShowLayout.includes(item.ctrlType)) ||
                    (!formType && item.ctrlType != 'hottable')
                  "
                  :key="index"
                >
                  <a>
                    <i :class="item.icon"></i>
                    <span>{{ item.desc }}</span>
                  </a>
                </li>
              </draggable>
            </template>
          </div>
          <div class="attributeField">
            <el-menu
              :default-active="activeBoTreeMenu"
              class="el-menu-vertical-demo"
            >
              <el-submenu
                v-for="(boDef, index) in boTreeData"
                :key="'def' + index"
                :index="index + ''"
              >
                <template slot="title">
                  <span>{{ boDef.description }}</span>
                </template>

                <draggable
                  class="flex-container"
                  tag="ul"
                  :list="boDef.children[0].attributeList"
                  v-bind="{
                    group: {name: 'form', pull: 'clone', put: false},
                    sort: false,
                    ghostClass: 'ghost',
                  }"
                  @end="handleMoveEnd"
                  @start="handleFiledMoveStart"
                  :move="handleMove"
                >
                  <el-menu-item
                    v-for="(mAttr, mAttrIndex) in boDef.children[0]
                      .attributeList"
                    :key="boDef.children[0].name + mAttrIndex"
                  >
                    <i
                      :class="
                        mAttr.dataType == 'date'
                          ? 'icon-date'
                          : mAttr.dataType == 'number'
                          ? 'icon-number'
                          : mAttr.dataType == 'clob'
                          ? 'icon-text'
                          : 'icon-single2'
                      "
                    ></i>
                    <span
                      slot="title"
                      :style="getTitleStyle(boDef.children[0].name, mAttr.name)"
                      >{{ mAttr.desc }}</span
                    >
                  </el-menu-item>
                </draggable>

                <el-submenu
                  v-show="
                    boDef.children[0].children &&
                    boDef.children[0].children.length > 0
                  "
                  v-for="(subEnt, subIndex) in boDef.children[0].children"
                  :key="'sub' + subEnt.name + subIndex"
                  :index="index + '-' + subIndex"
                >
                  <template slot="title">
                    <draggable
                      tag="ul"
                      :list="!!subEnt ? [subEnt] : []"
                      v-bind="{
                        group: {name: 'form', pull: 'clone', put: false},
                        sort: false,
                        ghostClass: 'ghost',
                      }"
                      @end="handleMoveEnd"
                      @start="handleTableMoveStart"
                      :move="handleMove"
                      ><div :style="getTitleStyle('subtable', subEnt.name)">
                        {{ subEnt.desc }}
                      </div></draggable
                    >
                  </template>
                  <draggable
                    class="flex-container"
                    tag="ul"
                    :list="subEnt.attributeList"
                    v-bind="{
                      group: {name: 'form', pull: 'clone', put: false},
                      sort: false,
                      ghostClass: 'ghost',
                    }"
                    @end="handleMoveEnd"
                    @start="handleFiledMoveStart"
                    :move="handleMove"
                  >
                    <el-menu-item
                      v-for="(subAttr, subAttrIndex) in subEnt.attributeList"
                      :key="'subAttr' + subEnt.name + subAttrIndex"
                    >
                      <i
                        :class="
                          subAttr.dataType == 'date'
                            ? 'icon-date'
                            : subAttr.dataType == 'number'
                            ? 'icon-number'
                            : subAttr.dataType == 'clob'
                            ? 'icon-text'
                            : 'icon-single2'
                        "
                      ></i>
                      <span
                        slot="title"
                        :style="getTitleStyle(subEnt.name, subAttr.name)"
                        >{{ subAttr.desc }}</span
                      >
                    </el-menu-item>
                  </draggable>

                  <el-submenu
                    v-show="subEnt.children && subEnt.children.length > 0"
                    v-for="(sunEnt, sunIndex) in subEnt.children"
                    :key="'sun' + sunEnt.name + sunIndex"
                    :index="index + '-' + subIndex + '-' + sunIndex"
                  >
                    <template slot="title">{{ sunEnt.desc }}</template>
                    <draggable
                      class="flex-container"
                      tag="ul"
                      :list="sunEnt.attributeList"
                      v-bind="{
                        group: {name: 'form', pull: 'clone', put: false},
                        sort: false,
                        ghostClass: 'ghost',
                      }"
                      @end="handleMoveEnd"
                      @start="handleFiledMoveStart"
                      :move="handleMove"
                    >
                      <el-menu-item
                        v-for="(sunAttr, sunAttrIndex) in sunEnt.attributeList"
                        :key="'sunAttr' + sunEnt.name + sunAttrIndex"
                        :index="'sunAttr' + sunEnt.name + sunAttrIndex"
                      >
                        <i
                          :class="
                            sunAttr.dataType == 'date'
                              ? 'icon-date'
                              : sunAttr.dataType == 'number'
                              ? 'icon-number'
                              : sunAttr.dataType == 'clob'
                              ? 'icon-text'
                              : 'icon-single2'
                          "
                        ></i>
                        <span
                          slot="title"
                          :style="getTitleStyle(sunEnt.name, sunAttr.name)"
                          >{{ sunAttr.desc }}</span
                        >
                      </el-menu-item>
                    </draggable>
                  </el-submenu>
                </el-submenu>
              </el-submenu>
            </el-menu>
          </div>
        </el-scrollbar>
      </el-tab-pane>
      <el-tab-pane label="复用字段" name="copyFast">
        <el-scrollbar class="scrollbar-fullheight">
          <div class="control-list">
            <template v-if="layoutComponents.length">
              <div class="widget-cate">布局</div>
              <draggable
                tag="ul"
                class="flex-container"
                :list="layoutComponents"
                v-bind="{
                  group: {name: 'form', pull: 'clone', put: false},
                  sort: false,
                  ghostClass: 'ghost',
                }"
                @end="handleMoveEnd"
                @start="handleMoveStart"
                :move="handleMove"
              >
                <li
                  class="flex-item dash-border"
                  :class="{'no-put': item.type == 'divider'}"
                  v-for="(item, index) in layoutComponents"
                  v-show="
                    (formType === 'pc' && item.ctrlType != 'hottable') ||
                    (formType === 'mobile' &&
                      mobileShowLayout.includes(item.ctrlType)) ||
                    (!formType && item.ctrlType != 'hottable')
                  "
                  :key="index"
                >
                  <a>
                    <i :class="item.icon"></i>
                    <span>{{ item.desc }}</span>
                  </a>
                </li>
              </draggable>
            </template>
          </div>
          <div class="panel__copy--btndiv">
            <el-button
              type="primary"
              icon="el-icon-plus"
              @click="addCopyForms()"
              >添加复用字段</el-button
            >
          </div>
          <el-collapse
            class="copyCollapse"
            v-model="activeCopyFormNames"
            v-for="(form, findex) in copyFormBoTreeData"
            :key="'form' + findex"
            :index="findex + ''"
          >
            <el-collapse-item :title="form.name" :name="'form' + findex">
              <div class="attributeField">
                <el-menu
                  :default-active="form.key + 0"
                  class="el-menu-vertical-demo"
                >
                  <el-submenu
                    v-for="(boDef, index) in form.boTreeData"
                    :key="form.key + 'def' + index"
                    :index="form.key + index + ''"
                  >
                    <template slot="title">
                      <span>{{ boDef.description }}</span>
                    </template>

                    <draggable
                      class="flex-container"
                      tag="ul"
                      :list="boDef.children[0].attributeList"
                      v-bind="{
                        group: {name: 'form', pull: 'clone', put: false},
                        sort: false,
                        ghostClass: 'ghost',
                      }"
                      @end="handleMoveEnd"
                      @start="handleCopyFiledMoveStart(form.key, $event)"
                      :move="handleMove"
                    >
                      <el-menu-item
                        v-for="(mAttr, mAttrIndex) in boDef.children[0]
                          .attributeList"
                        v-show="isShow(mAttr)"
                        :key="form.key + boDef.children[0].name + mAttrIndex"
                      >
                        <i
                          :class="
                            mAttr.dataType == 'date'
                              ? 'icon-date'
                              : mAttr.dataType == 'number'
                              ? 'icon-number'
                              : mAttr.dataType == 'clob'
                              ? 'icon-text'
                              : 'icon-single2'
                          "
                        ></i>
                        <span
                          slot="title"
                          :style="
                            getTitleStyle(boDef.children[0].name, mAttr.name)
                          "
                          >{{ mAttr.desc }}</span
                        >
                      </el-menu-item>
                    </draggable>
                    <el-submenu
                      v-show="
                        boDef.children[0].children &&
                        boDef.children[0].children.length > 0
                      "
                      v-for="(subEnt, subIndex) in boDef.children[0].children"
                      :key="form.key + 'sub' + subEnt.name + subIndex"
                      :index="form.key + index + '-' + subIndex"
                    >
                      <template slot="title">{{ subEnt.desc }}</template>
                      <draggable
                        class="flex-container"
                        tag="ul"
                        :list="subEnt.attributeList"
                        v-bind="{
                          group: {name: 'form', pull: 'clone', put: false},
                          sort: false,
                          ghostClass: 'ghost',
                        }"
                        @end="handleMoveEnd"
                        @start="handleCopyFiledMoveStart(form.key, $event)"
                        :move="handleMove"
                      >
                        <el-menu-item
                          v-for="(
                            subAttr, subAttrIndex
                          ) in subEnt.attributeList"
                          :key="
                            form.key + 'subAttr' + subEnt.name + subAttrIndex
                          "
                          v-show="isShow(subAttr)"
                        >
                          <i
                            :class="
                              subAttr.dataType == 'date'
                                ? 'icon-date'
                                : subAttr.dataType == 'number'
                                ? 'icon-number'
                                : subAttr.dataType == 'clob'
                                ? 'icon-text'
                                : 'icon-single2'
                            "
                          ></i>
                          <span
                            slot="title"
                            :style="getTitleStyle(subEnt.name, subAttr.name)"
                            >{{ subAttr.desc }}</span
                          >
                        </el-menu-item>
                      </draggable>
                      <el-submenu
                        v-show="subEnt.children && subEnt.children.length > 0"
                        v-for="(sunEnt, sunIndex) in subEnt.children"
                        :key="form.key + 'sun' + sunEnt.name + sunIndex"
                        :index="
                          form.key + index + '-' + subIndex + '-' + sunIndex
                        "
                      >
                        <template slot="title">{{ sunEnt.desc }}</template>
                        <draggable
                          class="flex-container"
                          tag="ul"
                          :list="sunEnt.attributeList"
                          v-bind="{
                            group: {name: 'form', pull: 'clone', put: false},
                            sort: false,
                            ghostClass: 'ghost',
                          }"
                          @end="handleMoveEnd"
                          @start="handleCopyFiledMoveStart(form.key, $event)"
                          :move="handleMove"
                        >
                          <el-menu-item
                            v-show="isShow(sunAttr)"
                            v-for="(
                              sunAttr, sunAttrIndex
                            ) in sunEnt.attributeList"
                            :key="
                              form.key + 'sunAttr' + sunEnt.name + sunAttrIndex
                            "
                            :index="
                              form.key + 'sunAttr' + sunEnt.name + sunAttrIndex
                            "
                          >
                            <i
                              :class="
                                sunAttr.dataType == 'date'
                                  ? 'icon-date'
                                  : sunAttr.dataType == 'number'
                                  ? 'icon-number'
                                  : sunAttr.dataType == 'clob'
                                  ? 'icon-text'
                                  : 'icon-single2'
                              "
                            ></i>
                            <span
                              slot="title"
                              :style="getTitleStyle(sunEnt.name, sunAttr.name)"
                              >{{ sunAttr.desc }}</span
                            >
                          </el-menu-item>
                        </draggable>
                      </el-submenu>
                    </el-submenu>
                  </el-submenu>
                </el-menu>
              </div>
            </el-collapse-item>
          </el-collapse>
        </el-scrollbar>
      </el-tab-pane>
    </el-tabs>
    <eip-copy-form-dialog
      ref="eipCopyFormDialog"
      :single="false"
      @onConfirm="formDialogConfirm"
      :formType="formType"
      :boDefIds="boDefIds"
      :formId="formId"
      appendToBody
    />
  </div>
</template>
<script>
import Draggable from 'vuedraggable'
import deepmerge from 'deepmerge'
import {
  advanceComponents,
  basicComponents,
  flowComponents,
  layoutComponents,
} from '@/api/controlsConfig.js'
import req from '@/request.js'

const EipCopyFormDialog = () =>
  import('@/components/dialog/EipCopyFormDialog.vue')

export default {
  name: 'field-panel',
  components: {Draggable, EipCopyFormDialog},
  props: ['boDefIds', 'widgetForm', 'formType', 'formId', 'copyFormList'],
  data() {
    return {
      mobileShowLayout: ['accordion', 'tab', 'subDiv', 'sunDiv', 'divider'], // 移动端展示的布局
      invisibleMobileAdvance: ['dataView',  'processForecast'],
      showFiledList: [],
      basicComponents,
      layoutComponents,
      advanceComponents,
      flowComponents,
      activeName: 'controlLayout',
      boTreeData: [],
      activeBoTreeMenu: '0',
      activeCopyFormNames: ['form0'],
      selectedMap: {},
      boDefIdMap: {},
      copyFiledMap: {},
      copyFormBoTreeData: [],
      newMap: {},
      controlSearch: '', //搜索关键字
      activeNames: ['1', '2', '3', '4'],
      controlSearchList: [],
      allComponents: [
        ...basicComponents,
        ...layoutComponents,
        ...advanceComponents,
        ...flowComponents,
      ],
      allComponentList: [
        {id: '1', name: '布局', children: layoutComponents},
        {id: '2', name: '基础控件', children: basicComponents},
        {id: '3', name: '流程控件', children: flowComponents},
        {id: '4', name: '高级控件', children: advanceComponents},
      ],
    }
  },
  created() {
    if (this.copyFormList && this.copyFormList.length > 0) {
      this.initGenerateBoTreeData(this.boDefIds, true)
    }
    this.allComponents.forEach((item) => {
      this.controlSearchList.push({
        id: item.ctrlType,
        value: item.desc,
      })
    })
  },
  watch: {
    boDefIds: {
      handler: function (newVal) {
        this.copyFiledMap = {}
        this.initGenerateBoTreeData(newVal)
      },
    },
    widgetForm: {
      handler: function (val, oldVal) {
        if (val && val.list && val.list.length > 0) {
          this.initSelectedMap(val.list)
        } else {
          this.selectedMap = {}
        }
      },
      deep: true,
    },
  },
  methods: {
    handleMoveEnd: function (evt) {},
    handleMoveStart: function (evt) {
      // 新增控件时  将控件属性切断联系
      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
    },
    handleFiledMoveStart: function (evt) {
      // 新增控件时  将控件属性切断联系
      const fieldControl = this.getFieldControl(evt.item._underlying_vm_)
      if (this.selectedMap[fieldControl.tableName + '_' + fieldControl.name]) {
        this.$message({
          message:
            '字段【' + fieldControl.desc + '】已绑定控件，不能多次绑定。',
          type: 'warning',
        })
        delete evt.item._underlying_vm_
        return
      }
      //添加拖拽方式属性
      fieldControl.dragType = 'field'
      //属性控件拖拽默认绑定属性，把不绑定属性设为false
      fieldControl.options.noBindModel = false
      evt.item._underlying_vm_ = deepmerge({}, fieldControl, {
        clone: true,
      })
      const key =
        Date.parse(new Date()) + '_' + Math.ceil(Math.random() * 99999)
      evt.item._underlying_vm_.key = key
    },
    handleTableMoveStart(evt) {
      if (this.selectedMap['subtable_' + evt.item._underlying_vm_.name]) {
        this.$message({
          message:
            '子表【' +
            evt.item._underlying_vm_.desc +
            '】已绑定控件，不能多次绑定。',
          type: 'warning',
        })
        delete evt.item._underlying_vm_
        return
      }
      if (this.formType === 'mobile') {
        evt.item._underlying_vm_ = this.getLayoutControl(
          evt.item._underlying_vm_,
          'subDiv'
        )
      } else {
        evt.item._underlying_vm_ = this.getLayoutControl(
          evt.item._underlying_vm_,
          'subtable'
        )
      }

      evt.item._underlying_vm_.key =
        Date.parse(new Date()) + '_' + Math.ceil(Math.random() * 99999)
    },
    getLayoutControl(item, type) {
      let layoutConfig = deepmerge(
        {},
        this.layoutComponents.find((item) => item.ctrlType === type),
        {clone: true}
      )
      layoutConfig.name = item.name
      layoutConfig.desc = item.desc
      layoutConfig.options.boSubEntity = item.name
      layoutConfig.options.relation = item.relation
      layoutConfig.options.subTablePath =
        this.boTreeData[0].alias + '.sub_' + item.name
      if (item.show === '子实体') {
        layoutConfig.options.subDivTablePath = layoutConfig.options.subTablePath
      }
      layoutConfig.list = item.attributeList.map((subField) => {
        return this.getFieldControl(subField, 'sub')
      })
      return layoutConfig
    },
    handleCopyFiledMoveStart: function (formKey, evt) {
      // 新增控件时  将控件属性切断联系
      let fieldControl = this.getCopyFieldControl(
        formKey,
        evt.item._underlying_vm_
      )
      if (!fieldControl || typeof fieldControl == 'undefined') {
        this.$message({message: '未找到该复用字段的控件。', type: 'warning'})
        fieldControl = this.getFieldControl(evt.item._underlying_vm_)
      }
      if (this.selectedMap[fieldControl.tableName + '_' + fieldControl.name]) {
        this.$message({
          message:
            '字段【' + fieldControl.desc + '】已绑定控件，不能多次绑定。',
          type: 'warning',
        })
        delete evt.item._underlying_vm_
        return
      }
      //添加拖拽方式属性
      fieldControl.dragType = 'copy'
      evt.item._underlying_vm_ = deepmerge({}, fieldControl, {
        clone: true,
      })
      const key =
        Date.parse(new Date()) + '_' + Math.ceil(Math.random() * 99999)
      evt.item._underlying_vm_.key = key
      //检测有没有绑定指定属性或事件，如果有提示注意检查是否涉及到其他BO导致绑定属性或事件失效
      setTimeout(() => this.validateFieldProperty(fieldControl), 1500)
    },
    handleMove: function (evt) {},
    handleClick(tab, event) {
      if (
        tab.name == 'attributeField' &&
        this.boDefIds &&
        (!this.boTreeData || this.boTreeData.length == 0)
      ) {
        this.initGenerateBoTreeData(this.boDefIds)
      }
    },
    validateFieldProperty(filed) {
      if (filed && filed.options) {
        let propertyList = []
        //判断计算公式
        if (filed.options.formulasDiyJs) {
          propertyList.push('【计算公式】')
        }
        //判断联动设置
        if (filed.options.linkage) {
          propertyList.push('【联动设置】')
        }
        //判断统计函数
        if (filed.options.mathExp) {
          propertyList.push('【字段校验】')
        }
        //判断文本内容的变量
        if (filed.options.textValue) {
          propertyList.push('【文本内容变量】')
        }
        //判断字段校验
        if (
          filed.options.validateList &&
          filed.options.validateList.length > 0
        ) {
          propertyList.push('【字段校验】')
        }
        if (propertyList.length > 0) {
          let msg =
            '复用字段“' +
            filed.desc +
            '”中设置了' +
            propertyList.join('，') +
            '，请检查是否存在绑定非当前BO字段，如果存在需自行修改，否则可能会影响相关功能效果。'
          this.$message({message: msg, type: 'warning', duration: 5500})
        }
      }
    },
    getTitleStyle(entName, fieldName) {
      if (this.selectedMap[entName + '_' + fieldName]) {
        return 'color:#bdbfc2;'
      }
      return 'color:#212121;'
    },
    initGenerateBoTreeData(boDefIds, initCopyForm) {
      if (boDefIds) {
        let _this = this
        const ids = boDefIds.split(',')
        ids.forEach((defId) => {
          _this.boDefIdMap[defId] = true
        })
        req
          .get('${form}/form/form/v1/generateBoTreeData?boDefIds=' + boDefIds)
          .then((data) => {
            let response = data.data
            if (response.state) {
              _this.boTreeData = JSON.parse(response.value)
            }
            if (initCopyForm) {
              _this.formDialogConfirm(_this.copyFormList, true)
              _this.initSelectedMap(_this.widgetForm.list)
            }
          })
      } else {
        this.boTreeData = []
        this.boDefIdMap = {}
      }
    },
    getFieldControl(field, parentNodeType) {
      let baseObj = {
        name: field.name,
        target: field.name,
        desc: field.comment,
        title: field.comment,
        boAttrId: field.boAttrId,
        fieldPath: field.fieldPath,
        entId: field.entId,
        boDefAlias: field.boDefAlias,
        tableName: field.tableName,
        columnType: field.dataType,
        parentNodeType: parentNodeType || null,
      }
      if (field.fieldPath.split('.').length > 2) {
        baseObj.parentNodeType = 'sun'
        baseObj.boSubEntity = field.tableName
      }
      const key =
        Date.parse(new Date()) + '_' + Math.ceil(Math.random() * 99999)
      let resultField = null
      if (field.dataType == 'number') {
        let option = {
          icon: 'icon-single',
          ctrlType: 'number',
          key: key,
          columnType: 'number',
          options: {
            width: '100%',
            isWidth: true,
            defaultValue: 0,
            min: -Number(''.padStart(field.attrLength, '9')),
            max: Number(''.padStart(field.attrLength, '9')),
            numberMin: -Number(''.padStart(field.attrLength, '9')),
            numberMax: Number(''.padStart(field.attrLength, '9')),
            step: 1,
            decimalDigits: field.decimalLen,
            maxDecimalDigits: field.decimalLen,
            filtercurrency: '',
            filterthousandBit: '',
            advancedProperty: 'inputType|bindPreAndSufFix|disabled',
            basicsProperty: 'number|currency|placeholder|dateCount',
            controlsPosition: '',
            company: '',
            validateType:
              'min_value|max_value|confirmed|numeric|between|digits|required|row_unique|frontJSValidate|mobile',
            dataType: 'number',
            validateList: [],
            disabled: false,
            formulasDiyJs: '',
            customInput: '',
            lableColor: '',
            mathExp: '',
            controls: true,
            validate:
              "'decimal|max_number:999999999|min_number:-999999999|decimalDigits_Num:0'",
            bindPreAndSufFixjson: {
              preFix: '',
              sufSix: '',
            },
          },
        }
        resultField = {...baseObj, ...option}
      } else if (field.dataType == 'date') {
        let option = {
          icon: 'icon-date',
          ctrlType: 'date',
          key: key,
          columnType: 'date',
          options: {
            width: '100%',
            isWidth: true,
            defaultValue: '',
            dataType: 'date',
            validateType:
              'isAfter|isBefore|isStart|isEnd|required|row_unique|frontJSValidate',
            advancedProperty: 'isEditor|isInputEdit',
            placeholder: '',
            basicsProperty: 'date|placeholder',
            validate: '',
            readonly: false,
            editable: true,
            clearable: true,
            timestamp: false,
            required: false,
            type: 'date',
            validateList: [],
            disabled: false,
            formulasDiyJs: '',
            lableColor: '',
            mathExp: '',
            bindPreAndSufFixjson: {
              preFix: '',
              sufSix: '',
            },
            format: field.format,
            inputFormat: field.format,
            customInput: '',
          },
        }
        resultField = {...baseObj, ...option}
      } else if (field.dataType == 'clob') {
        let option = {
          icon: 'icon-single',
          ctrlType: 'textarea',
          key: key,
          columnType: 'clob',
          options: {
            width: '100%',
            isWidth: true,
            defaultValue: '',
            dataType: 'clob',
            validateType:
              'regex|min|max|required|row_unique|frontJSValidate|backendValidate',
            advancedProperty: 'isEditor|isInputEdit',
            placeholder: '',
            basicsProperty: 'placeholder',
            validateList: [],
            disabled: false,
            formulasDiyJs: '',
            customInput: '',
            lableColor: '',
          },
        }
        resultField = {...baseObj, ...option}
      } else {
        let option = {
          icon: 'icon-single',
          ctrlType: 'input',
          key: key,
          options: {
            width: '100%',
            isWidth: true,
            defaultValue: '',
            isCountDate: false,
            mathExp: '',
            isStartDate: '',
            isEndDate: '',
            countFormat: 'day',
            dataType: 'string|number',
            validateList: [],
            validate: '',
            validateType:
              'confirmed|email|regex|id_card|min|max|min_value|max_value|isAfter|isBefore|isStart|isEnd|numeric|between|is|digits|mobile|required|row_unique|alpha_spaces|alpha_dash|alpha_num|alpha|frontJSValidate|backendValidate',
            advancedProperty:
              'isInputEdit|isBindIdentity|inputType|bindPreAndSufFix',
            placeholder: '',
            disabled: false,
            basicsProperty: 'input|dateCount|placeholder',
            bindIdentityjson: {},
            isBindPreAndSufFix: false,
            bindPreAndSufFixjson: {
              preFix: '',
              sufSix: '',
            },
            formulasDiyJs: '',
            customInput: '',
            lableColor: '',
            showCondition: {target: '', fieldPath: '', value: ''},
          },
        }
        resultField = {...baseObj, ...option}
      }
      // bo属性中设置了必填 且 当前控件的校验规则为空
      if (
        field.isRequired == '1' &&
        (!resultField.options.validateList ||
          resultField.options.validateList.length == 0)
      ) {
        resultField.options.validate = "'required'"
        resultField.options.validateList = [
          {
            key: 'required',
            name: '*必填',
          },
        ]
      }
      return resultField
    },
    getCopyFieldControl(formKey, field) {
      if (
        this.copyFiledMap[formKey] &&
        this.copyFiledMap[formKey][
          formKey + '_' + field.tableName + '_' + field.name
        ]
      ) {
        return this.copyFiledMap[formKey][
          formKey + '_' + field.tableName + '_' + field.name
        ]
      } else {
        return null
      }
    },
    initSelectedMap(rootList, formKey) {
      const this_ = this
      let newMap = {}
      this.newMap = newMap
      let getFieldMap = function (newMap, obj, type) {
        switch (type) {
          case 'grid':
            if (obj.columns && obj.columns.length > 0) {
              obj.columns.forEach((citem) => {
                if (citem.list && citem.list.length > 0) {
                  citem.list.forEach((gitem) => {
                    if (gitem.fieldPath) {
                      if (formKey) {
                        newMap[
                          formKey + '_' + gitem.tableName + '_' + gitem.name
                        ] = {...gitem}
                      } else {
                        newMap[gitem.tableName + '_' + gitem.name] = true
                      }
                    }
                  })
                }
              })
            }
            break
          case 'table':
            if (obj.rows && obj.rows.length > 0) {
              obj.rows.forEach((ritem) => {
                if (ritem.cols && ritem.cols.length > 0) {
                  ritem.cols.forEach((citem) => {
                    citem.list.forEach((item) => {
                      if (item.fieldPath) {
                        if (formKey) {
                          newMap[
                            formKey + '_' + item.tableName + '_' + item.name
                          ] = {...item}
                        } else {
                          newMap[item.tableName + '_' + item.name] = true
                        }
                      }
                    })
                  })
                }
              })
            }
            break
          default:
            break
        }
      }
      let getLayoutMap = function (list, newMap) {
        list.forEach((listItem) => {
          if (listItem.fieldPath) {
            if (formKey) {
              newMap[formKey + '_' + listItem.tableName + '_' + listItem.name] =
                {...listItem}
            } else {
              newMap[listItem.tableName + '_' + listItem.name] = true
            }
          } else if (listItem.ctrlType) {
            switch (listItem.ctrlType) {
              case 'tab':
              case 'accordion':
                if (listItem.columns && listItem.columns.length > 0) {
                  listItem.columns.forEach((aitem) => {
                    if (aitem.list && aitem.list.length > 0) {
                      getLayoutMap(aitem.list, newMap)
                    }
                  })
                }
                break
              case 'grid':
                getFieldMap(newMap, listItem, 'grid')
                break
              case 'table':
                getFieldMap(newMap, listItem, 'table')
                break
              case 'subtable':
                newMap['subtable_' + listItem.name] = {
                  ...listItem,
                }

                if (listItem.list && listItem.list.length > 0) {
                  listItem.list.forEach((item) => {
                    if (item.fieldPath) {
                      if (formKey) {
                        newMap[
                          formKey + '_' + item.tableName + '_' + item.name
                        ] = {...item}
                      } else {
                        newMap[item.tableName + '_' + item.name] = true
                      }
                    } else if (
                      item.ctrlType == 'sunDiv' ||
                      item.ctrlType == 'suntable'
                    ) {
                      if (item.list && item.list.length > 0) {
                        item.list.forEach((sunitem) => {
                          if (sunitem.fieldPath) {
                            if (formKey) {
                              newMap[
                                formKey +
                                  '_' +
                                  sunitem.tableName +
                                  '_' +
                                  sunitem.name
                              ] = {...sunitem}
                            } else {
                              newMap[
                                sunitem.tableName + '_' + sunitem.name
                              ] = true
                            }
                          } else if (sunitem.ctrlType == 'grid') {
                            getFieldMap(newMap, sunitem, 'grid')
                          }
                        })
                      }
                    }
                  })
                }
                break
              case 'subDiv':
                if (listItem.list && listItem.list.length > 0) {
                  listItem.list.forEach((item) => {
                    if (item.fieldPath) {
                      newMap[item.tableName + '_' + item.name] = true
                    } else if (item.ctrlType == 'grid') {
                      getFieldMap(newMap, item, 'grid')
                    } else if (
                      item.ctrlType == 'sunDiv' ||
                      item.ctrlType == 'suntable'
                    ) {
                      if (item.list && item.list.length > 0) {
                        item.list.forEach((sunitem) => {
                          if (sunitem.fieldPath) {
                            if (formKey) {
                              newMap[
                                formKey +
                                  '_' +
                                  sunitem.tableName +
                                  '_' +
                                  sunitem.name
                              ] = {...sunitem}
                            } else {
                              newMap[
                                sunitem.tableName + '_' + sunitem.name
                              ] = true
                            }
                          } else if (sunitem.ctrlType == 'grid') {
                            getFieldMap(newMap, sunitem, 'grid')
                          }
                        })
                      }
                    }
                  })
                }
                break
              default:
                break
            }
          } else {
          }
        })
        if (newMap) {
          //获取可以复用的字段集合
          for (let key in newMap) {
            this_.showFiledList.push(newMap[key])
          }
        }
      }
      getLayoutMap(rootList, newMap)
      if (formKey) {
        this.copyFiledMap[formKey] = newMap
      } else {
        this.selectedMap = newMap
      }
    },
    addCopyForms() {
      if (this.boDefIdMap.length == undefined || this.boDefIdMap.length == 0) {
        this.initGenerateBoTreeData(this.boDefIds, true)
      }
      this.$refs.eipCopyFormDialog.showDialog()
    },
    addCopyForm(form) {
      let formObj = {key: form.formKey, name: form.name, boTreeData: []}
      let _this = this
      let copyBoTree = function (defId) {
        let copyTreeData = {}
        _this.boTreeData.forEach((treeData) => {
          if (treeData.id == defId) {
            copyTreeData = {...treeData}
          }
        })
        return copyTreeData
      }
      form.boDefList.forEach((defId) => {
        if (_this.boDefIdMap[defId]) {
          let copyTree = copyBoTree(defId)
          if (JSON.stringify(copyTree) != '{}') {
            formObj.boTreeData.push(copyTree)
          }
        }
      })
      if (formObj.boTreeData.length > 0) {
        const expand = JSON.parse(form.expand)
        this.initSelectedMap(expand.list, form.formKey)
        this.copyFormBoTreeData.push(formObj)
      } else {
        this.$message({
          message: '表单【' + form.name + '】不能被复用。',
          type: 'warning',
        })
      }
    },
    formDialogConfirm(data, init) {
      if (data && data.length > 0) {
        let _this = this
        data.forEach((form) => {
          if (form.expand && form.boDefList && form.boDefList.length > 0) {
            _this.addCopyForm(form)
            if (!init) {
              _this.$emit('addTocopyFormList', form)
            }
          }
        })
      }
    },
    //判断哪些字段可以复用
    isShow(attr) {
      if (this.showFiledList.length > 0) {
        let isShow = this.showFiledList.find(
          (obj) => obj.fieldPath == attr.fieldPath
        )
        if (isShow) {
          return true
        } else {
          if (
            attr.tableName &&
            attr.name &&
            this.newMap[`${attr.tableName}_${attr.name}`] == true
          ) {
            return true
          }
          return false
        }
      } else {
        return false
      }
    },
    toTarget(selector) {
      this.$el
        .querySelector(selector)
        .scrollIntoView({behavior: 'instant', block: 'end', inline: 'nearest'})
    },
    // fetch-suggestions 是一个返回输入建议的方法属性，在该方法中你可以在输入建议数据准备好时通过 cb(data) 返回到 autocomplete 组件中.
    querySearch(queryString, cb) {
      const controlSearchList = this.controlSearchList
      const results = queryString
        ? controlSearchList.filter(this.createFilter(queryString))
        : controlSearchList
      // 调用 callback 返回建议列表的数据
      cb(results)
    },
    createFilter(queryString) {
      return (controlSearch) => {
        return (
          controlSearch.value
            .toLowerCase()
            .indexOf(queryString.toLowerCase()) !== -1 // 改为===0 就是筛选的数据只是首字匹配的列表项，需要包含输入字的所有列表项改为！==-1
        )
      }
    },
    /* 跳转并传值 */
    handleSelect(data) {
      this.allComponentList.forEach((item) => {
        item.children.some((child) => {
          if (child.desc == this.controlSearch) {
            if (!this.activeNames.includes(item.id)) {
              this.activeNames.push(item.id)
            }
          }
        })
      })
      setTimeout(() => {
        this.toTarget('#' + data.value)
      }, 500)
    },
    search() {
      if (!this.controlSearch) {
        this.$message.warning('请输入关键字')
        return
      }
      let controlSearchMess = []
      this.allComponentList.forEach((item) => {
        item.children.some((child) => {
          if (child.desc == this.controlSearch) {
            controlSearchMess.push(child.desc)
            if (!this.activeNames.includes(item.id)) {
              this.activeNames.push(item.id)
            }
          }
        })
      })
      // 判断一下，如果该长度为0的话，那就证明输入的内容和列表的内容不一样。
      if (controlSearchMess.length === 0) {
        this.$message.warning('不存在“' + this.controlSearch + '”组件')
        return
      }
      setTimeout(() => {
        this.toTarget('#' + this.controlSearch)
      }, 500)
    },
  },
}
</script>
<style lang="scss" scoped>
@import '@/assets/css/form-editor.scss';

.panel {
  height: 100%;
  /deep/ .el-tabs__content {
    height: calc(100% - 100px);
  }
  /deep/ .el-tab-pane {
    height: 100%;
  }
  // /deep/ .el-tabs__nav {
  //   margin-left: 10px;
  // }
  /deep/.el-tabs__item {
    padding: 0;
  }
  /deep/ .el-tabs__item {
    font-size: 13px;
  }
  /deep/ .el-collapse-item__header {
    text-indent: 10px;
  }
  .panel__tabs {
    height: 100%;
  }
  .scrollbar-fullheight {
    height: 100%;
    padding-bottom: 20px;
  }
  .attribute-scrollbar{
    height: calc(100% - 20px);
  }
  .panel__copy--btndiv {
    text-align: center;
  }
}

.widget-cate {
  padding: 10px 0 0 10px;
  font-weight: bold;
  color: #333;
  font-size: 16px;
  font-family: Source Han Sans SC;
}

ul.flex-container {
  margin: 0;
  list-style: none;
  padding: 10px 5px;
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
}

ul.flex-container > li.flex-item {
  height: 32px;
  line-height: 32px;
  // border: 1px solid #ccc;
  margin: 6px;
  width: 94px;
  padding-left: 14px;
  border-radius: 2px;
  cursor: pointer;
  color: #333;
  background: rgb(246, 246, 246);
  // &.dash-border {
  //   border: 1px dashed #d5d5d5;
  // }
  .icon-switch {
    font-size: 24px;
  }
}

ul.flex-container > li.flex-item:hover {
  box-shadow: 0 2px 5px rgba(86, 96, 117, 0.15);
  background: rgb(255, 255, 255);
  border-color: $--color-primary;
  color: $--color-primary;
}

.active {
  color: $--color-primary;
}

li.flex-item > a > i {
  font-size: 16px;
}

li.flex-item > a > span {
  margin-left: 8px;
  font-size: 13px;
}
ul.flex-container > li.is-switch {
  a {
    align-items: center;
    display: flex;
  }
  line-height: unset;
  align-items: center;
  display: flex;
}
.attributeField >>> .el-submenu__title {
  height: 42px;
  line-height: 42px;
}
.attributeField >>> .el-submenu .el-menu-item {
  height: 38px;
  line-height: 38px;
}
.copyCollapse {
  margin-top: 10px;
}
.attributeField .el-menu-vertical-demo >>> .el-menu-item i {
  color: #409eff;
}
.control-list {
  >>> .el-icon-caret-bottom {
    margin-top: 10px;
    font-size: 16px;
  }
  >>> .el-icon-caret-top {
    margin-top: 10px;
    font-size: 16px;
  }
  >>> .el-collapse-item__header {
    border: 0px;
  }
  >>> .el-collapse-item__wrap {
    border: 0px;
  }
  >>> .el-collapse {
    border: 0px;
  }
  >>> .el-collapse-item__arrow {
    display: none;
  }
  >>> .el-collapse-itemitem__content {
    padding-bottom: 10px;
  }
  >>> .el-collapse-item__content {
    padding-bottom: 0px;
  }
}
.control-layout {
  .control-list {
    margin-top: 30px;
    .widget-cate {
      padding: 10px 0 0;
      text-indent: 7px;
    }
  }
}
.search-Box {
  position: fixed;
  z-index: 9999;
  height: 30px;
  width: 270px;
  background-color: #fff;
}
/deep/.el-tabs__item.is-top:nth-child(2) {
  padding-left: 0 !important;
}
</style>
