<template>
  <div
    class="navbar-default box-shadow flex"
    :style="{
      justifyContent: handleType == 'simple' ? 'flex-end' : 'space-between'
    }"
  >
    <el-page-header @back="formBack" v-if="handleType != 'simple'">
      <template v-slot:content
        ><el-tooltip
          effect="dark"
          :content="`${title}(${formData.name})`"
          placement="top-start"
        >
          <div>{{ title }}({{ formData.name }})</div>
        </el-tooltip>
      </template>
    </el-page-header>
    <span>
      <el-button
        v-if="
          handleType == 'simple' && formId && curFormRight.indexOf('3') > -1
        "
        @click="switchForm"
      >
        切换{{ formData.formType == 'pc' ? '移动表单' : 'pc表单' }}
      </el-button>
      <el-button
        icon="icon-technology"
        v-if="formId && curFormRight.indexOf('3') > -1"
        @click="includdingFile('')"
        >引入脚本</el-button
      >
      <el-button icon="icon-list" v-if="formId" @click="historyRecord"
        >表单历史记录</el-button
      >
      <el-button
        v-if="handleType != 'simple' || formId"
        icon="icon-save"
        type="primary"
        :disabled="disabledButton"
        @click="save('notPublish')"
        >保存</el-button
      >
      <el-button
        icon="icon-release"
        @click="publish(1)"
        :disabled="disabledButton"
        v-if="
          (!formId ||
            (formId &&
              formData.status == 'draft' &&
              formData.isPrint != 'Y')) &&
            curFormRight.indexOf('3') > -1
        "
        >发布</el-button
      >
      <el-button
        icon="icon-release"
        @click="newVersion"
        :disabled="disabledButton"
        v-else-if="
          formId && formData.isPrint != 'Y' && curFormRight.indexOf('3') > -1
        "
        >发布新版</el-button
      >
      <el-button @click="previewForm()">预览</el-button>
      <el-button icon="el-icon-folder" @click="$emit('local-save')"
        >导出本地</el-button
      >

      <el-upload
        class="upload-demo"
        style="display: inline-block"
        ref="upload"
        action="https://jsonplaceholder.typicode.com/posts/"
        :show-file-list="false"
        :on-change="fileOnChange"
        :auto-upload="false"
        v-if="curFormRight.indexOf('3') > -1"
        accept="json"
      >
        <el-button icon="el-icon-folder-opened" slot="trigger" size="small"
          >本地导入</el-button
        >
      </el-upload>
    </span>
    <el-dialog
      title="表单数据"
      :visible.sync="dialogFormVisible"
      append-to-body
      class="urgent-text"
      :close-on-click-modal="false"
      width="1024"
      top="8vh"
    >
      <el-row style="height: 500px">
        <el-col :span="24" style="padding: 5px; height: 500px">
          <codemirror
            ref="mycode"
            v-model="formHtml"
            :options="cmOptions"
            class="mycode"
            style="width: 99%; height: 500px"
          ></codemirror>
        </el-col>
      </el-row>
    </el-dialog>
    <el-dialog
      title="提示"
      :visible.sync="dialogincluddingFileVisible"
      append-to-body
      class="urgent-text includding-form js-dialog"
      :close-on-click-modal="false"
      width="100%"
      :show-close="false"
      top="0vh"
    >
      <div slot="title" class="dialog-header">
        <el-page-header @back="goBack" content="引入脚本"> </el-page-header>
        <div class="right-btn__wrap">
          <el-button size="small" type="primary" @click="includeFilesOk"
            >确 定</el-button
          >
          <el-button size="small" @click="goBack">取 消</el-button>
        </div>
      </div>
      <el-row class="js-content_row">
        <el-col
          :span="8"
          class="js-content_col js-content__left"
          :class="{
            'collapse-left': !asideShowLeft,
            'current-width':
              asideShowLeft && !asideShowRight && !asideShowContent,
            'currentTwo-width':
              (asideShowLeft && !asideShowContent && asideShowRight) ||
              (asideShowLeft && asideShowContent && !asideShowRight)
          }"
        >
          <div class="col-header col-left__header">
            <div class="left-header__left">
              <i class="icon-html"></i>
              <span class="sub-title" v-show="asideShowLeft">HTML</span>
              <el-tooltip
                class="item"
                effect="dark"
                placement="bottom"
                popper-class="js-var-tip"
                v-if="asideShowLeft"
              >
                <div slot="content">
                  请输入符合HTML 标签的语法格式编写 <br />
                  示例：{{ Html }}
                </div>
                <i class="icon-notes tip-icon"></i>
              </el-tooltip>
            </div>
            <div
              class="left-header__right"
              @click="asideShowLeft = !asideShowLeft"
            >
              <i
                :class="[
                  asideShowLeft ? 'el-icon-arrow-left' : 'el-icon-arrow-right'
                ]"
              ></i>
            </div>
          </div>
          <div class="col-left__content">
            <codemirror
              ref="mycode"
              v-model="formHtml"
              :options="cmOptions"
              class="code"
            ></codemirror>
          </div>
        </el-col>
        <el-col
          :span="8"
          class="js-content_col js-content__content"
          :class="{
            'collapse-content': !asideShowContent,
            'current-width':
              !asideShowLeft && !asideShowRight && asideShowContent,
            'currentTwo-width':
              (!asideShowLeft && asideShowContent && asideShowRight) ||
              (asideShowLeft && asideShowContent && !asideShowRight)
          }"
        >
          <div class="col-header col-left__header">
            <div class="left-header__left">
              <i class="icon-css"></i>
              <span class="sub-title" v-show="asideShowContent">CSS</span>
              <el-tooltip
                class="item"
                effect="dark"
                placement="bottom"
                popper-class="js-var-tip"
                v-if="asideShowContent"
              >
                <div slot="content">
                  通过内部样式表引入的原生CSS <br />
                  示例：.Hotent{ color: skyblue; }
                </div>
                <i class="icon-notes tip-icon"></i>
              </el-tooltip>
            </div>

            <div
              class="left-header__right"
              @click="asideShowContent = !asideShowContent"
            >
              <i
                :class="[
                  asideShowContent
                    ? 'el-icon-arrow-left'
                    : 'el-icon-arrow-right'
                ]"
              ></i>
            </div>
          </div>
          <div class="col-left__content">
            <HtMonacoEditor
              ref="mycodeCss"
              v-model="includeFiles.formCss"
              language="css"
              :showAll="false"
              :contextmenu="false"
            />
          </div>
        </el-col>
        <el-col
          :span="8"
          class="js-content_col js-content__right"
          :class="{
            'collapse-right': !asideShowRight,
            'current-width':
              !asideShowLeft && !asideShowContent && asideShowRight,
            'currentTwo-width':
              (!asideShowLeft && asideShowContent && asideShowRight) ||
              (asideShowLeft && !asideShowContent && asideShowRight)
          }"
        >
          <div class="col-header col-right__header">
            <div class="left-header__left right-header__left">
              <i class="icon-JS"></i>
              <div class="js-top_wrap" v-show="asideShowRight">
                <span class="sub-title">JS</span>
                <span class="desc">自定义JS脚本</span>
                <el-dropdown
                  @command="variablesClick"
                  size="mini"
                  class="common-var"
                >
                  <el-button>
                    常用变量
                    <i class="el-icon-caret-bottom"></i>
                  </el-button>
                  <el-dropdown-menu slot="dropdown">
                    <el-dropdown-item :command="{value: 'currentUser.account'}"
                      >当前用户账号</el-dropdown-item
                    >
                    <el-dropdown-item :command="{value: 'currentUser.username'}"
                      >当前用户名称</el-dropdown-item
                    >
                  </el-dropdown-menu>
                </el-dropdown>
                <el-tooltip
                  class="item"
                  effect="dark"
                  placement="bottom"
                  popper-class="js-var-tip"
                >
                  <div slot="content">
                    使用到表单BO数据例：data.实体表名.实体表字段；<br />使用表单实例可直接使用：this或_this
                  </div>
                  <i class="icon-notes tip-icon"></i>
                </el-tooltip>
              </div>
            </div>
            <div
              class="left-header__right"
              @click="asideShowRight = !asideShowRight"
            >
              <i
                :class="[
                  asideShowRight ? 'el-icon-arrow-left' : 'el-icon-arrow-right'
                ]"
              ></i>
            </div>
          </div>
          <div class="col-right__content">
            <HtMonacoEditor
              ref="mycode2"
              v-model="includeFiles.diyJs"
              language="javascript"
            />
          </div>
        </el-col>
      </el-row>
    </el-dialog>
    <ht-load-data
      :url.sync="formHtmlUrl"
      context="form"
      @after-load-data="afterformHtml"
    ></ht-load-data>
    <el-dialog
      title="表单历史记录"
      :visible.sync="historyRecordVisible"
      append-to-body
      class="urgent-text"
      :close-on-click-modal="false"
      width="64%"
      top="8vh"
    >
      <ht-table
        @load="loadData"
        :data="tableData"
        :pageResult="pageResult"
        :selectable="false"
        :show-export="false"
        ref="htTable"
        :show-custom-column="false"
      >
        <template>
          <ht-table-column
            type="index"
            width="50"
            align="center"
            label="序号"
          />
          <ht-table-column prop="formId" width="180" label="表单ID" />
          <ht-table-column
            prop="createTime"
            width="160"
            label="修改时间"
            :sortable="true"
          />
          <ht-table-column
            prop="version"
            width="100"
            label="表单版本"
            :sortable="true"
          />
          <ht-table-column label="操作">
            <template v-slot="{row}">
              <el-button type="primary" @click="getFormHistoryRecord(row)"
                >查看表单数据</el-button
              >
              <el-button
                type="success"
                v-if="curFormRight.indexOf('3') > -1"
                @click="updateFormHistoryRecord(row)"
                >恢复</el-button
              >
              <el-button
                type="danger"
                v-if="curFormRight.indexOf('4') > -1"
                @click="delFormHistoryRecord(row)"
                >删除</el-button
              >
            </template>
          </ht-table-column>
        </template>
      </ht-table>
    </el-dialog>
    <mobile-preview-form-dialog
      :formId="cacheId"
      ref="mobilePreviewForm"
    ></mobile-preview-form-dialog>
  </div>
</template>
<script>
import request from '@/request.js'
import form from '@/api/form.js'
import {mapState} from 'vuex'
import {Base64} from 'js-base64'
import controlsApi from '@/api/controlsConfig.js'
import {Message} from 'element-ui'
const MobilePreviewFormDialog = () =>
  import('@/components/form/MobilePreviewFormDialog.vue')
import _ from 'lodash'
export default {
  props: ['widgetForm', 'formData', 'formId', 'handleType', 'curFormRight'],
  components: {
    MobilePreviewFormDialog
  },
  data() {
    return {
      leftSpan: 13, //引入脚本左侧宽度
      rightSpan: 9, //引入脚本右侧宽度
      asideShowLeft: true, //引入脚本左侧默认显示
      asideShowRight: true, //引入脚本右侧默认显示
      asideShowContent: true, //引入脚本中间默认显示
      params: null,
      dialogFormVisible: false, //查看表单数据dialog
      dialogincluddingFileVisible: false, //引入脚本dialog
      historyRecordVisible: false, //表单历史记录dialog
      newVersionConfig: false,
      formHtmlUrl: '', //获取表单HTML url
      formHtml: '', //获取表单HTML
      formCss: '', //获取表单Css
      formExpand: '', //表单json数据
      tableData: [], //表单历史记录列表数据
      pageResult: {
        page: 1,
        pageSize: 10,
        total: 0,
        showTotal: true
      },
      Html: '<div class="Hotent">HelloWorld!</div>',
      includeFiles: {diyFile: '', diyCss: '', diyJs: '', formCss: ''}, //引入脚本和样式对象
      cmOptions: {
        value: '',
        mode: 'vue',
        readOnly: false,
        smartIndent: true,
        tabSize: 2,
        theme: 'base16-light',
        lineNumbers: true,
        line: true
      },
      cmOptions2: {
        value: '',
        mode: 'javascript',
        readOnly: false,
        smartIndent: true,
        tabSize: 2,
        theme: 'base16-light',
        lineNumbers: true,
        line: true
      },
      clickCount: 0,
      publishTimer: null,
      iedntityConfig: [],
      cacheId: '',
      disabledButton: false
    }
  },

  computed: {
    ...mapState({
      currentUser: state => state.login.currentUser
    }),
    title: function() {
      return this.formData.formType == 'pc' ? 'PC表单设计' : '手机表单设计'
    }
  },
  watch: {
    asideShowLeft: function(newVal, oldVal) {
      if (newVal != oldVal) {
        let myEvent = new Event('resize') // resize是指resize事件
        window.dispatchEvent(myEvent) // 触发window的resize事件
        this.asideshowHandler()
      }
    },
    asideShowRight: function(newVal, oldVal) {
      if (newVal != oldVal) {
        let myEvent = new Event('resize') // resize是指resize事件
        window.dispatchEvent(myEvent) // 触发window的resize事件
        this.asideshowHandler()
      }
    },
    asideShowContent: function(newVal, oldVal) {
      if (newVal != oldVal) {
        let myEvent = new Event('resize') // resize是指resize事件
        window.dispatchEvent(myEvent) // 触发window的resize事件
        this.asideshowHandler()
      }
    }
  },
  methods: {
    switchForm() {
      this.$emit('switchForm')
    },
    asideshowHandler() {
      if (this.asideShowLeft && !this.asideShowRight) {
        this.leftSpan = 22
        this.rightSpan = 0
      }
      if (!this.asideShowLeft && this.asideShowRight) {
        this.leftSpan = 0
        this.rightSpan = 22
      }
      if (!this.asideShowLeft && !this.asideShowRight) {
        this.leftSpan = 0
        this.rightSpan = 0
      }
      if (this.asideShowLeft && this.asideShowRight) {
        this.leftSpan = 13
        this.rightSpan = 9
      }
    },
    fileOnChange(file, fileList) {
      if (file.name.indexOf('.json') == -1) {
        this.$message.warning('只支持该页面导出本地的json文件')
        return
      }
      this.$confirm(
        '导入后会覆盖掉之前选择的数据建模,以导入文件的绑定信息为准, 是否继续?',
        '提示',
        {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }
      )
        .then(() => {
          var reader = new FileReader()
          reader.readAsText(file.raw)
          let _this = this
          reader.onload = function() {
            try {
              let json = JSON.parse(this.result)
              _this.$emit('load-local', json)
            } catch (err) {
              _this.$message.error('只支持该页面导出本地的json文件')
            }
          }
        })
        .catch(() => {})
    },
    //表单返回
    formBack() {
      this.$confirm('您确认离开当前编辑页面？', '现在离开，内容不会自动保存', {
        cancelButtonText: '取消',
        confirmButtonText: '确定',
        type: 'warning',
        closeOnClickModal: false
      }).then(() => {
        this.$emit('close-dialog')
      })
    },
    //查看表单数据
    getFormHistoryRecord(row) {
      const this_ = this
      this_.dialogFormVisible = true
      request
        .get('${form}/form/form/v1/getFormHistoryRecord?id=' + row.id)
        .then(function(rep) {
          if (rep) {
            var pretty = require('pretty')
            this_.formHtml = pretty(row.formHtml)
          }
        })
    },
    //恢复表单数据
    updateFormHistoryRecord(row) {
      const this_ = this
      this.$confirm('是否确定切换版本？', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        request
          .get('${form}/form/form/v1/updateFormHistoryRecord?id=' + row.id)
          .then(function(rep) {
            if (rep.data.state) {
              Message.success(rep.data.message)
              this_.$emit('close-dialog')
            }
          })
      })
    },
    //删除表单数据
    delFormHistoryRecord(row) {
      const this_ = this
      this.$confirm('是否确定删除？', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        request
          .remove('${form}/form/form/v1/delFormHistoryRecord?id=' + row.id)
          .then(function(rep) {
            if (rep.data.state) {
              Message.success('删除成功')
              let param = {
                pageBean: {page: 1, pageSize: 20, showTotal: true},
                querys: [
                  {
                    property: 'formId',
                    value: row.formId,
                    operation: 'EQUAL',
                    relation: 'AND'
                  }
                ]
              }
              this_.loadData(param)
            }
          })
      })
    },
    variablesClick(data) {
      this.$refs.mycode2.insertValue(data.value)
    },
    //加载表单历史记录列表数据
    loadData(param, cb) {
      const this_ = this
      let queryUrl = '${form}/form/form/v1/formHistoryRecordlistJson'
      let pageBean = {
        pageBean: param.pageBean,
        querys: [
          {
            property: 'formId',
            value: this_.formData.id, // 兼容旧数据
            operation: 'EQUAL',
            relation: 'OR'
          },
          {
            property: 'formKey',
            value: this_.formData.formKey,
            operation: 'EQUAL',
            relation: 'OR'
          }
        ]
      }
      request
        .post(queryUrl, pageBean)
        .then(response => {
          this_.tableData = response.data.rows
          this_.pageResult = {
            page: response.data.page,
            pageSize: response.data.pageSize,
            total: response.data.total
          }
        })
        .finally(() => cb && cb())
    },
    //打开引入表单历史记录列表对话框
    historyRecord() {
      const this_ = this
      this_.historyRecordVisible = true
      let param = {
        pageBean: {page: 1, pageSize: 10, showTotal: true},
        querys: [
          {
            property: 'formId',
            value: this_.formData.id,
            operation: 'EQUAL',
            relation: 'AND'
          }
        ]
      }
      this_.loadData(param)
    },
    afterformHtml(data) {
      if (data && data.bpmForm) {
        var pretty = require('pretty')
        this.formHtml = pretty(data.bpmForm.formHtml)
        this.formExpand = data.bpmForm.expand
        this.includeFiles.diyJs = data.bpmForm.diyJs || ''
        this.includeFiles.formCss = data.bpmForm.formCss || ''
      }
    },
    //打开引入脚本对话框
    includdingFile(formId) {
      if (!formId) {
        formId = this.formData.id
      }
      this.dialogincluddingFileVisible = true
      this.formHtmlUrl = '/form/form/v1/previewDesignVue?formId=' + formId
      this.includeFiles = this.formData.includeFiles
        ? Base64.decode(this.formData.includeFiles, 'utf-8')
        : {diyFile: ' ', diyCss: ' ', diyJs: ' ', formCss: ' '}
    },
    //引入脚本和样式对象保存
    includeFilesOk() {
      if (!this.formHtml) {
        this.$message.warning('模板HTML不能为空！')
        return
      }
      this.dialogincluddingFileVisible = false
      form
        .saveFormJs({
          formId: this.formData.id,
          diyJs: this.includeFiles.diyJs,
          formCss: this.includeFiles.formCss,
          formHtml: Base64.encode(this.formHtml, 'utf-8'),
          formExpand: Base64.encode(this.formExpand, 'utf-8')
        })
        .then(resp => {
          if (resp.state) {
            this.$message.success(resp.message)
          }
        })
      //将脚本赋值给formData,用于从缓存进入预览表单时使用
      this.formData.diyJs = this.includeFiles.diyJs || ''
      this.formData.formCss = this.includeFiles.formCss || ''
    },
    //布局字段中嵌入了布局字段的情况
    isSave(list) {
      let flag = false
      //不需要绑定表单属性的控件
      let ctrlTypeList = [
        'grid',
        'text',
        'accordion',
        'tab',
        'immediate-single',
        'immediate-textarea',
        'image',
        'iframe',
        'amap',
        'dataView',
        'formTable',
        'table',
        'title',
        'simple-text'
      ]
      for (let i = 0; i < list.length; i++) {
        if (
          list[i].ctrlType == 'grid' ||
          list[i].ctrlType == 'accordion' ||
          list[i].ctrlType == 'tab'
        ) {
          for (let j = 0; j < list[i].columns.length; j++) {
            if (list[i].columns[j].list.length > 0) {
              for (let k = 0; k < list[i].columns[j].list.length; k++) {
                if (
                  list[i].columns[j].list[k].name == '' &&
                  ctrlTypeList.indexOf(list[i].columns[j].list[k].ctrlType) ==
                    -1 &&
                  !list[i].columns[j].list[k].options.noBindModel
                ) {
                  this.$message.error(
                    '【' +
                      list[i].desc +
                      '中的' +
                      list[i].columns[j].list[k].desc +
                      '】未绑定属性值'
                  )
                  flag = true
                  return flag
                }
              }
            }
          }
        }
      }
      return flag
    },

    verifyLoop(list, cb) {

      //栅格
      if (list.columns && list.columns.length > 0) {
        for (let j = 0; j < list.columns.length; j++) {
          if (list.columns[j].list.length > 0) {
            for (let k = 0; k < list.columns[j].list.length; k++) {
              if (['table', 'grid'].includes(list.ctrlType)) {
                if (['subtable'].includes(list.columns[j].list[k].ctrlType)) {
                  cb()
                }
              }
              this.verifyLoop(list.columns[j].list[k], cb)
            }
          }
          if (list.columns[j].rows && list.columns[j].rows.length > 0) {
            this.verifyLoop(list.columns[j].rows, cb)
          }
        }
      }
     //表格
      if (list.rows && list.rows.length > 0) {
        for (let j = 0; j < list.rows.length; j++) {
          if (list.rows[j].cols.length > 0) {
            for (let k = 0; k < list.rows[j].cols.length; k++) {
              if (list.rows[j].cols[k].list.length > 0) {
                for (let l = 0; l < list.rows[j].cols[k].list.length; l++) {
                  if (['table', 'grid'].includes(list.ctrlType)) {
                    if (
                      ['subtable'].includes(
                        list.rows[j].cols[k].list[l].ctrlType
                      )
                    ) {
                      cb()
                    }
                  }
                  this.verifyLoop(list.rows[j].cols[k], cb)
                }
              }
            }
          }
        }
      }
    },

    getPostData() {
      let type = false
      for (let i = 0; i < this.widgetForm.list.length; i++) {
        this.verifyLoop(this.widgetForm.list[i], () => {
          type = true

          return
        })
      }
      if (type) {
        this.$message({
          message: '子表不允许拖入栅格/表格布局',
          type: 'error'
        })
        return
      }
      if (this.widgetForm.list.length == 0) {
        this.$message.error('请拖拽表单控件')
        return
      }
      //不需要绑定表单属性的控件
      let ctrlTypeList = [
        'grid',
        'text',
        'accordion',
        'tab',
        'immediate-single',
        'immediate-textarea',
        'image',
        'iframe',
        'amap',
        'dataView',
        'formTable',
        'table',
        'title',
        'simple-text'
      ]
      let amap = 0
      for (let i = 0; i < this.widgetForm.list.length; i++) {
        if (this.widgetForm.list[i].ctrlType == 'amap') {
          amap++
          if (amap > 1) {
            this.$message({
              type: 'error',
              message: '表单中只能存在一个地图控件!'
            })
            return
          }
        }
        if (
          this.widgetForm.list[i].ctrlType == 'grid' ||
          this.widgetForm.list[i].ctrlType == 'accordion' ||
          this.widgetForm.list[i].ctrlType == 'tab'
        ) {
          for (let j = 0; j < this.widgetForm.list[i].columns.length; j++) {
            if (this.widgetForm.list[i].columns[j].span.length > 20) {
              this.$message({
                message:
                  'tab布局控件第' + (j + 1) + '个标签配置项字符长度超出20！',
                type: 'error'
              })
              return
            }
            if (this.widgetForm.list[i].columns[j].list.length > 0) {
              for (
                let k = 0;
                k < this.widgetForm.list[i].columns[j].list.length;
                k++
              ) {
                if (
                  this.widgetForm.list[i].columns[j].list[k].ctrlType == 'amap'
                ) {
                  amap++
                  if (amap > 1) {
                    this.widgetForm.list[i].columns[j].list.splice(k, 1)
                    this.$message({
                      type: 'error',
                      message: '已存在高德地图控件!'
                    })
                    return
                  }
                }
                //判断布局字段中是否嵌入了布局字段
                if (
                  this.widgetForm.list[i].columns[j].list[k].name == '' &&
                  (this.widgetForm.list[i].columns[j].list[k].ctrlType ==
                    'grid' ||
                    this.widgetForm.list[i].columns[j].list[k].ctrlType ==
                      'accordion' ||
                    this.widgetForm.list[i].columns[j].list[k].ctrlType ==
                      'tab')
                ) {
                  let flag = this.isSave(
                    this.widgetForm.list[i].columns[j].list
                  ) //布局字段中嵌入了布局字段
                  if (flag) {
                    return
                  }
                } else if (
                  this.widgetForm.list[i].columns[j].list[k].name == '' &&
                  ctrlTypeList.indexOf(
                    this.widgetForm.list[i].columns[j].list[k].ctrlType
                  ) == -1 &&
                  !this.widgetForm.list[i].columns[j].list[k].options
                    .noBindModel
                ) {
                  this.$message.error(
                    '【' +
                      this.widgetForm.list[i].desc +
                      '中的' +
                      this.widgetForm.list[i].columns[j].list[k].desc +
                      '】未绑定属性值'
                  )
                  return
                }
              }
            }
          }
        }
      }
      var resp = this.judgeWidgetFormList(this.widgetForm.list)
      if (resp) {
        const formDef = {
          expand: JSON.stringify(this.widgetForm),
          rev: this.formData.rev,
          identityConfig: this.getIdentityConfig()
        }
        formDef.name = this.formData.name
        formDef.key = this.formData.formKey
        formDef.type = this.formData.typeName
        formDef.typeId = this.formData.typeId
        //formDef.diyJs = this.formData.diyJs || ''
        //formDef.formCss = this.formData.formCss || ''
        if (this.formData.defId) {
          formDef.id = this.formData.defId
        }
        let {
          id,
          defId,
          formKey,
          name,
          desc,
          formHtml,
          status,
          isMain,
          version,
          typeId,
          typeName,
          formTabTitle,
          formType,
          diyJs,
          formCss,
          versionCount,
          busDataTemplateCount,
          expand,
          isPrint,
          formSetting
        } = this.formData
        let bpmFormParams = {
          id,
          defId,
          formKey,
          name,
          desc,
          formHtml,
          status,
          isMain,
          version,
          typeId,
          typeName,
          formTabTitle,
          formType,
          diyJs,
          formCss,
          versionCount,
          busDataTemplateCount,
          expand,
          isPrint,
          formSetting
        }
        let bpmFormVo = {
          bpmFormDef: formDef,
          bpmForm: bpmFormParams
        }
        if (this.newVersionConfig) {
          bpmFormVo.newForm = 'newForm'
        }
        return bpmFormVo
      }
    },
    publish(i) {
      if (i == 1) {
        this.save()
      }
      i++
      if (this.isPublish) {
        this.$http
          .post('${form}/form/form/v1/publish', {}, {formId: this.formId})
          .then(response => {
            if (response.data.state) {
              this.$message({
                type: 'success',
                message: response.data.message
              })
              this.formData.status = 'deploy'
              //清除定时器
              if (this.publishTimer) {
                clearTimeout(this.publishTimer)
                this.publishTimer = null
              }
              this.$emit('close-dialog')
            }
          })
      } else {
        this.publishTimer = setTimeout(() => this.publish(i), 500)
      }
    },
    newVersion: _.debounce(
      function() {
        this.newVersionConfig = true
        this.save()
      },
      2000,
      {leading: true}
    ),
    save(param) {
      this.notPublish = true
      if (param) {
        this.notPublish = false
      }
      //先校验表单的基本属性
      this.$emit('saveValidate')
    },
    saveEnd() {
      let params = this.getPostData()
      this.newVersionConfig = false
      if (params) {
        const this_ = this
        //保存表单是先判断是否有表单模板，没有表单模板先初始化表单模板
        form.isTemplateByAlias('fieldControl').then(resp => {
          if (resp.data.value != undefined) {
            //保存表单
            this_.saveForm(params, this_)
          } else {
            //初始化表单模板
            form.initTemplate().then(response => {
              if (response.data.state) {
                //保存表单
                this_.saveForm(params, this_)
              }
            })
          }
        })
      }
    },
    //保存表单
    saveForm(params, this_) {
      this.disabledButton = true
      request.post('${form}/form/form/v1/saveForm', params).then(
        response => {
          this_.$message.success(response.data.message)
          this_.$emit('close-dialog', response.data.value)
          if (this.notPublish) {
            this.isPublish = true
          }
          this.disabledButton = false
        },
        error => {
          this.$message.error(
            error.response.data.message ||
              '表单保存失败！请检查表单模板是否正确'
          )
          this.isPublish = false
          this.disabledButton = false
        }
      )
    },
    previewForm() {
      //表单设计页面的预览不通过数据库的formId来预览，而是通过把当前表单设计页面的数据暂存到浏览器缓存，在front端获取解析来预览
      let params = this.getPostData()
      this.newVersionConfig = false
      if (!params) return
      if (this.currentUser && this.currentUser.account) {
        //预览表单时先判断是否有表单模板，没有表单模板先初始化表单模板
        form.isTemplateByAlias('fieldControl').then(resp => {
          if (resp.data.value != undefined) {
            this.toPreview(params)
          } else {
            //初始化表单模板
            form.initTemplate().then(response => {
              if (response.data.state) {
                this.toPreview(params)
              }
            })
          }
        })
        //window.open(url, '_blank')
      }
    },
    toPreview(params) {
      request
        .post('${form}/form/form/v1/saveFormOnCache', params)
        .then(response => {
          if (response.data.state) {
            this.cacheId = response.data.value
            let url = ''
            if (this.formData.formType == 'pc') {
              url = `/formPreview/${this.cacheId}`
              window.open(window.context.manage + url, '_blank')
            } else {
              // url = `/formPreview/${cacheId}?mobile=true`
              window.open(
                window.context.manage +
                  `/formPreview/${this.cacheId}?mobile=true`,
                '_blank'
              )
            }
          } else {
            this.$message.error(response.data.message)
          }
        })
    },
    genHtml() {
      request
        .post('${form}/form/form/v1/generateFrom', this.getPostData())
        .then(response => {
          this.$message.success(response.data.message)
          this.$emit('close-dialog')
        })
    },
    editHtml() {},
    isUpload() {},
    addStyle(listValue) {
      if (listValue.columns.length > 2) {
        listValue.columns.forEach((v, i) => {
          if (v.style && v.style.includes('border')) {
            if (
              i < listValue.columns.length - 1 &&
              !v.style.includes('border-right: none')
            ) {
              v.style += ' border-right: none; '
            }
          }
        })
      }
    },
    //兼容旧数据，删除readonly、width属性
    compatibleWithOldData(ctrlValue) {
      if (ctrlValue.options) {
        if (ctrlValue.options.isReadonly) {
          delete ctrlValue.options.isReadonly
          ctrlValue.options.isInputEdit = true
        }
        if (this.formData.formType != 'pc' && ctrlValue.options.width) {
          delete ctrlValue.options.width
        }
        if (
          ctrlValue.ctrlType == 'number' &&
          ctrlValue.options.advancedProperty &&
          !ctrlValue.options.advancedProperty.includes('|disabled')
        ) {
          ctrlValue.options.advancedProperty =
            ctrlValue.options.advancedProperty + '|disabled'
        }
      }
    },
    judgeWidgetFormList(widgetFormList) {
      // 判断表单当中，有必须绑定属性的控件没有绑定属性
      let resultVal = true
      let fieldList = []
      for (var i = 0; i < widgetFormList.length; i++) {
        var listValue = this.widgetForm.list[i]
        this.compatibleWithOldData(listValue)
        if (listValue.columns) {
          this.addStyle(listValue)
          // 栅格布局的字段保存  tab 折叠
          for (var j = 0; j < listValue.columns.length; j++) {
            var listValue1 = []
            //非布局字段
            var fieldListValue1 = listValue.columns[j].list.filter(c => {
              this.compatibleWithOldData(c)
              !controlsApi.isLayoutComponents(c.ctrlType) &&
                !c.options.noBindModel &&
                c.options.noBindModel != undefined
            })
            listValue1 = listValue1.concat(fieldListValue1)
            //栅格-折叠-tab布局/表格布局
            var gridListValue1 = listValue.columns[j].list.filter(
              c =>
                c.ctrlType == 'grid' ||
                c.ctrlType == 'table' ||
                c.ctrlType == 'tab' ||
                c.ctrlType == 'accordion'
            )
            for (let k = 0; k < gridListValue1.length; k++) {
              //栅格-折叠-tab布局
              var columnsObj = gridListValue1[k].columns
              if (columnsObj) {
                for (let l = 0; l < columnsObj.length; l++) {
                  var list = columnsObj[l].list
                  list = list.filter(c => {
                    if (c.ctrlType == 'table') {
                      c.rows.forEach(item => {
                        item.cols.forEach(obj => {
                          listValue1 = listValue1.concat(obj.list)
                        })
                      })
                    } else {
                      var obj = c.columns
                      if (obj) {
                        for (let l = 0; l < obj.length; l++) {
                          var list = obj[l].list
                          list = list.filter(n => {
                            return !n.options.noBindModel
                          })
                          listValue1 = listValue1.concat(list)
                        }
                      }
                    }
                  })
                  listValue1 = listValue1.concat(list)
                }
              }
              //表格布局
              if (!columnsObj) {
                columnsObj = gridListValue1[k].rows
                columnsObj.forEach(item => {
                  item.cols.forEach(obj => {
                    listValue1 = listValue1.concat(obj.list)
                  })
                })
              }
            }
            fieldList = fieldList.concat(listValue1)
            //子表布局
            var subtableListValue1 = listValue.columns[j].list.filter(
              c => c.ctrlType == 'subtable' || c.ctrlType == 'subDiv'
            )

            for (let k = 0; k < subtableListValue1.length; k++) {
              var subObj = subtableListValue1[k]
              if (subObj.list) {
                if (!this.subUnique(subObj)) {
                  return false
                }
              }
            }
            // resultVal = this.validateFields(listValue1)
            // if (!resultVal) {
            //   return false
            // }

            //数据视图
            var dataViewListValue1 = listValue.columns[j].list.filter(
              c => c.ctrlType == 'dataView'
            )

            for (let h = 0; h < dataViewListValue1.length; h++) {
              var dataView = dataViewListValue1[h]
              if (dataView.templateKey == '') {
                this.$message.error('请绑定表单列表')
                return false
              }
            }

            // for (let f = 0; f < fieldList.length; f++) {
            //   for (let v = 0; v < listValue.columns[j].list.length; v++) {
            //     if (
            //       listValue.columns[j].list[v].fieldPath ==
            //         fieldList[f].fieldPath &&
            //       fieldList[f].target
            //     ) {
            //       this.$message.error(
            //         '字段属性【' + fieldList[f].title + '】,绑定了多个布局控件'
            //       )
            //       return false
            //     }
            //   }
            // }
            // if (listValue.ctrlType == "grid") {
            fieldList = fieldList.concat(listValue.columns[j].list)
            // }
            resultVal = this.validateFields(fieldList)
            if (!resultVal) {
              return false
            }
          }
        } else if (listValue.list) {
          let _this = this
          let fieldNum = 0
          try {
            listValue.list.forEach((v, index) => {
              this.compatibleWithOldData(v)
              if (
                (listValue.ctrlType == 'subtable' ||
                  listValue.ctrlType == 'subDiv') &&
                fieldNum == 0
              ) {
                if (v.ctrlType != 'sunDiv' && v.ctrlType != 'suntable') {
                  fieldNum++
                } else if (
                  listValue.list.length - 1 == index &&
                  fieldNum == 0
                ) {
                  throw new Error('请给子表添加字段!')
                }
              }
              if (v.ctrlType == 'grid') {
                _this.addStyle(v)
              }
            })
          } catch (e) {
            this.$message({type: 'error', message: e.message})
            return false
          }
          var res = this.subUnique(listValue)
          if (!res) {
            return false
          }
        } else if (
          (!listValue.options || !listValue.options.noBindModel) &&
          !listValue.rows
        ) {
          fieldList.push(listValue)
          // 不使用布局
          resultVal = this.validateField(listValue)
          if (!resultVal) {
            break
          }
        } else if (listValue.rows && listValue.rows.length > 0) {
          listValue.rows.forEach(item => {
            item.cols.forEach(obj => {
              if (obj.list) {
                obj.list.forEach((v, index) => {
                  this.compatibleWithOldData(v)
                })
              }
              fieldList = fieldList.concat(obj.list)
            })
          })
          // 表格布局
          resultVal = this.validateRowFields(listValue)
          if (!resultVal) {
            break
          }
        } else if (listValue.templateKey) {
          if (listValue.templateKey == '') {
            //数据视图
            this.$message.error('请绑定表单列表')
            return false
          }
        }
      }
      return resultVal
    },
    subUnique(listValue) {
      let res = true
      if (!listValue.options.boSubEntity) {
        this.$message.error(listValue.desc + '请绑定实体')
        return false
      }
      if (listValue.list.length == 0) {
        this.$message.error(listValue.desc + '请至少绑定一个子表字段')
        return false
      }
      //获取孙表字段
      let sunList = listValue.list.filter(
        c => c.ctrlType == 'suntable' || c.ctrlType == 'sunDiv'
      )
      for (let k = 0; k < sunList.length; k++) {
        if (!sunList[k].options.boSubEntity) {
          this.$message.error(sunList[k].desc + '请绑定实体')
          return false
        }
        if (sunList[k].list.length == 0) {
          this.$message.error(sunList[k].desc + '请至少绑定一个孙表字段')
          return false
        }
        let sunFieldList = this.getField(sunList[k])
        if (!this.validateFields(sunFieldList)) {
          return false
        }
      }
      let subFieldList = this.getField(listValue)
      if (!this.validateFields(subFieldList)) {
        return false
      }
      return res
    },
    getField(listValue) {
      //获取布局中栅格布局
      let gridListValue1 = listValue.list.filter(c => c.ctrlType == 'grid')
      //获取布局中基础字段
      let subFieldList = listValue.list.filter(
        c =>
          c.ctrlType != 'grid' &&
          (c.ctrlType != 'suntable' || c.ctrlType != 'sunDiv')
      )
      for (let k = 0; k < gridListValue1.length; k++) {
        let columnsObj = gridListValue1[k].columns
        for (let l = 0; l < columnsObj.length; l++) {
          let list = columnsObj[l].list
          subFieldList = subFieldList.concat(list)
        }
      }
      return subFieldList
    },
    unique(arr) {
      let hash = {}
      for (let i = 0; i < arr.length; i++) {
        if (arr[i].fieldPath && hash[arr[i].fieldPath]) {
          return arr[i]
        }
        hash[arr[i].fieldPath] = true
      }
      return false
    },
    validateRowFields(field) {
      let resultVal = true
      for (var k = 0; k < field.rows.length; k++) {
        let cols = field.rows[k].cols
        for (var c = 0; c < cols.length; c++) {
          for (let l = 0; l < cols[c].list.length; l++) {
            resultVal = this.validateField(cols[c].list[l])
            if (!resultVal) {
              return false
            }
          }
        }
      }
      return true
    },
    validateFields(fields) {
      let resultVal = true
      for (var k = 0; k < fields.length; k++) {
        resultVal = this.validateField(fields[k])
        if (!resultVal) {
          return false
        }
      }
      return true
    },
    validateField(field) {
      if (
        !field.isLayout &&
        (!field.options || !field.options.noBindModel) &&
        (field.name == '' || !field.target) &&
        field.ctrlType != 'title' &&
        field.ctrlType != 'simple-text'
      ) {
        this.$message.error('请绑定属性值')
        return false
      }
      if (field.ctrlType == 'selector' && !field.options.selector.type.alias) {
        this.$message.error('选择器控件请绑定选择器')
        return false
      }
      if (field.ctrlType == 'identity' && !field.options.alias) {
        this.$message.error('请绑定流水号')
        return false
      }
      return true
    },
    getIdentityConfig() {
      let identityConfig = []
      function gatherIdentityConfig(list) {
        if (!list || list.length == 0) {
          return
        }
        list.forEach(item => {
          if (item.ctrlType == 'identity' && item.options.init === 'false') {
            identityConfig.push({
              parentType: item.parentNodeType || 'main',
              path: item.fieldPath,
              alias: item.options.alias,
              tableName: item.tableName,
              boSubEntity: item.boSubEntity
            })
          } else if (item.isLayout) {
            if (item.list) {
              gatherIdentityConfig(item.list)
            }
            if (item.columns) {
              item.columns.forEach(column => {
                gatherIdentityConfig(column.list)
              })
            }
          }
        })
      }
      gatherIdentityConfig(this.widgetForm.list)
      return JSON.stringify(identityConfig)
    },
    goBack() {
      this.dialogincluddingFileVisible = false
      this.includeFiles.diyJs = ''
      this.includeFiles.formCss = ''
    },
    handleCollapse() {
      this.asideShowLeft = !this.asideShowLeft
    }
  }
}
</script>
<style lang="scss" scoped>
.js-dialog {
  height: 100%;
  overflow: hidden;
  ::v-deep {
    .el-dialog {
      height: 100%;
      margin: 0;
      .el-dialog__header {
        padding: 0 24px;
        border-bottom: 1px solid #eee;
      }
      .dialog-header {
        height: 48px;
        display: flex;
        align-items: center;
        justify-content: space-between;
        .el-page-header__left {
          color: #409eff;
        }
        .el-page-header__content {
          font-size: 18px;
          color: #222;
          font-weight: bold;
        }
        .right-btn__wrap {
          .el-button {
            padding: 8px 15px;
          }
        }
      }
      .el-dialog__body {
        padding: 24px;
        height: calc(100% - 48px - 48px);
        .js-content_row {
          height: 100%;
        }
        .js-content_col {
          border: 1px solid #e6e6e6;
          width: calc(33.33% - 16px);
          height: 100%;
          .col-header {
            height: 48px;
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding-left: 20px;
            border-bottom: 1px solid #e6e6e6;
          }
          .col-left__content,
          .col-right__content {
            padding: 20px;
            height: calc(100% - 48px - 40px);
            .code {
              height: 100%;
              overflow: auto;
            }
          }
          .left-header__left {
            font-size: 16px;
            color: #333;
            font-weight: bold;
            .icon-html,
            .icon-JS,
            .icon-css {
              font-size: 20px;
            }
            .sub-title {
              padding-left: 8px;
              padding-right: 5px;
            }
            .js-top_wrap {
              display: flex;
              align-items: center;
              .desc {
                color: #888;
                padding-left: 24px;
                font-size: 14px;
                font-weight: 400;
              }
              .common-var {
                margin-left: 8px;
                .el-button {
                  background: #f6f6f6;
                  border-color: #f6f6f6;
                }
              }
              .tip-icon {
                padding-left: 6px;
                font-size: 16px;
                color: #999999;
              }
            }
          }
          .right-header__left {
            display: flex;
            height: 48px;
            align-items: center;
          }
          .left-header__right {
            width: 18px;
            height: 48px;
            line-height: 48px;
            text-align: center;
            color: #333;
            border-left: 1px solid #e6e6e6;
            background: #e9e9e9;
            &:hover {
              cursor: pointer;
            }
          }
        }
        .js-content__left {
          margin-right: 16px;
        }
        .js-content__content {
          margin: 0px;
          width: 33.33%;
        }
        .js-content__right {
          margin-left: 16px;
        }
        .collapse-left,
        .collapse-content,
        .collapse-right {
          width: 72px;
          .col-left__content {
            padding: 20px 16px;
          }
        }
        .current-width {
          width: calc(100% - 144px - 32px);
        }
        .currentTwo-width {
          width: calc((100% - 72px - 32px) / 2);
        }
      }
    }
  }
}
.navbar-default {
  height: 100%;
  background-image: none;
  background: #fff;
  border-radius: 0px;
  box-shadow: 0px 2px 5px rgba(86, 96, 117, 0.15);
  border-bottom: 1px solid #ededed;
  justify-content: space-between;
  padding: 0 10px;
  ::v-deep .el-page-header__content {
    width: calc(100% - 100px);
    .el-tooltip {
      width: 100%;
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
    }
  }
  ::v-deep .el-page-header {
    width: 34%;
  }
}

.navbar-default span {
  color: #666;
  font-size: 14px;
  line-height: 48px;
  font-weight: bold;
  margin-left: 20px;
}

.navbar-default button {
  margin-right: 10px;
}
/deep/ .CodeMirror {
  font-family: monospace;
  height: 100% !important;
  color: black;
  direction: ltr;
  .CodeMirror-scroll {
    height: 100%;
  }
}
.includding-form .el-dialog .el-dialog__body {
  padding: 10px 5px;
}
@media (max-width: 1024px) {
  .urgent-text {
    /deep/ .el-dialog {
      width: 78% !important;
    }
  }
}
</style>
