<template>
  <el-drawer
    :title="title"
    :visible.sync="drawerVisible"
    direction="rtl"
    size="500px"
    :before-close="handleClose"
    v-bind="$attrs"
    v-on="$listeners"
  >
    <el-row>
      <el-col v-for="(item, index) in detailFormat" :key="index" class="detail-block" :span="24">
        <el-col v-if="item.header" class="detail-block--header" :span="24">
          {{ item.header }}
        </el-col>
        <el-col
          v-for="(col, colIndex) in item.content"
          :key="colIndex"
          :span="24"
          class="detail-block--item"
        >
          <el-col class="detail-block--item-title" :required="col.required">
            {{ col.title }}
          </el-col>
          <el-col class="detail-block--item-content">
            <div v-if="col.render==='image'">
              <template>
                <div style="display: flex;gap: 10px;">
                  <el-image
                    v-for="url in imageUrl(detailData[col.prop])"
                    :key="url"
                    style="width: 80px; height: 80px"
                    :lazy="true"
                    :src="url"
                    :preview-src-list="imageUrl(detailData[col.prop])"
                  />
                </div>
              </template>
            </div>
            <div v-else-if="col.render==='pre'">
              <pre v-if="isJSON(col.method ? col.method(detailData[col.prop]) : detailData[col.prop])" v-html="formatJson(col.method ? col.method(detailData[col.prop]) : detailData[col.prop])" />
              <div v-else>{{ col.method ? col.method(detailData[col.prop]) : detailData[col.prop] }}</div>
            </div>
            <div v-else-if="col.render==='html'" v-html="detailData[col.prop]" />
            <div v-else class="common-content">
              {{ col.method ? col.method(detailData[col.prop]) : detailData[col.prop] }}
            </div>

          </el-col>
        </el-col>
      </el-col>
    </el-row>
    <template
      v-for="(index, name) in $slots"
      :slot="name"
    >
      <slot :name="name" />
    </template>

  </el-drawer>
</template>

<script>
export default {
  name: 'YMTableDetail',
  model: {
    prop: 'drawerVisible',
    event: 'change'
  },
  props: {
    drawerVisible: {
      type: Boolean,
      default: false
    },
    title: {
      type: String,
      default: '详情'
    },
    detailFormat: {
      type: Array,
      default: () => ([])
    },
    // 表格选择的数据内容
    detailData: {
      type: Object,
      default: () => ({})
    }
  },
  data() {
    return {
    }
  },
  created() {
  },
  methods: {
    isJSON(str) {
      if (typeof str === 'string') {
        try {
          var obj = JSON.parse(str)
          if (typeof obj === 'object' && obj) {
            return true
          } else {
            return false
          }
        } catch (e) {
          return false
        }
      } else {
        if (typeof str === 'object') {
          return true
        } else {
          return false
        }
      }
    },
    transitionJsonToString(jsonObj, callback) {
      // 转换后的jsonObj受体对象
      var _jsonObj = null
      // 判断传入的jsonObj对象是不是字符串，如果是字符串需要先转换为对象，再转换为字符串，这样做是为了保证转换后的字符串为双引号
      if (Object.prototype.toString.call(jsonObj) !== '[object String]') {
        try {
          _jsonObj = JSON.stringify(jsonObj)
        } catch (error) {
          // 转换失败错误信息
          console.error('您传递的json数据格式有误，请核对...')
          console.error(error)
          callback(error)
        }
      } else {
        try {
          jsonObj = jsonObj.replace(/(\')/g, '"')
          _jsonObj = JSON.stringify(JSON.parse(jsonObj))
        } catch (error) {
          // 转换失败错误信息
          console.error('您传递的json数据格式有误，请核对...')
          console.error(error)
          callback(error)
        }
      }
      console.table('🚀  transitionJsonToString  _jsonObj:', _jsonObj)
      return _jsonObj
    },
    formatJson(jsonObj, callback) {
      // 正则表达式匹配规则变量
      // var reg = null
      // 转换后的字符串变量
      var formatted = ''
      // 换行缩进位数
      var pad = 0
      // 一个tab对应空格位数
      var PADDING = '&nbsp;&nbsp;&nbsp;&nbsp;'
      // json对象转换为字符串变量
      var jsonString = this.transitionJsonToString(jsonObj, callback)
      if (!jsonString) {
        return jsonString
      }
      // 存储需要特殊处理的字符串段
      var _index = []
      // 存储需要特殊处理的“再数组中的开始位置变量索引
      var _indexStart = null
      // 存储需要特殊处理的“再数组中的结束位置变量索引
      var _indexEnd = null
      // 将jsonString字符串内容通过\r\n符分割成数组
      var jsonArray = []
      // 正则匹配到{,}符号则在两边添加回车换行
      jsonString = jsonString.replace(/([\{\}])/g, '\r\n$1\r\n')
      // 正则匹配到[,]符号则在两边添加回车换行
      jsonString = jsonString.replace(/([\[\]])/g, '\r\n$1\r\n')
      // 正则匹配到,符号则在两边添加回车换行
      jsonString = jsonString.replace(/(\,)/g, '$1\r\n')
      // 正则匹配到要超过一行的换行需要改为一行
      jsonString = jsonString.replace(/(\r\n\r\n)/g, '\r\n')
      // 正则匹配到单独处于一行的,符号时需要去掉换行，将,置于同行
      jsonString = jsonString.replace(/\r\n\,/g, ',')
      // 特殊处理双引号中的内容
      jsonArray = jsonString.split('\r\n')
      jsonArray.forEach(function(node, index) {
        // 获取当前字符串段中"的数量
        var num = node.match(/\"/g) ? node.match(/\"/g).length : 0
        // 判断num是否为奇数来确定是否需要特殊处理
        if (num % 2 && !_indexStart) {
          _indexStart = index
        }
        if (num % 2 && _indexStart && _indexStart !== index) {
          _indexEnd = index
        }
        // 将需要特殊处理的字符串段的其实位置和结束位置信息存入，并对应重置开始时和结束变量
        if (_indexStart && _indexEnd) {
          _index.push({
            start: _indexStart,
            end: _indexEnd
          })
          _indexStart = null
          _indexEnd = null
        }
      })
      // 开始处理双引号中的内容，将多余的"去除
      _index.reverse().forEach(function(item, index) {
        var newArray = jsonArray.slice(item.start, item.end + 1)
        jsonArray.splice(
          item.start,
          item.end + 1 - item.start,
          newArray.join('')
        )
      })
      // 奖处理后的数组通过\r\n连接符重组为字符串
      jsonString = jsonArray.join('\r\n')
      // 将匹配到:后为回车换行加大括号替换为冒号加大括号
      jsonString = jsonString.replace(/\:\r\n\{/g, ':{')
      // 将匹配到:后为回车换行加中括号替换为冒号加中括号
      jsonString = jsonString.replace(/\:\r\n\[/g, ':[')
      // 将上述转换后的字符串再次以\r\n分割成数组
      jsonArray = jsonString.split('\r\n')
      // 将转换完成的字符串根据PADDING值来组合成最终的形态
      jsonArray.forEach(function(item, index) {
        // console.log(item);
        var i = 0
        // 表示缩进的位数，以tab作为计数单位
        var indent = 0
        // 表示缩进的位数，以空格作为计数单位
        var padding = ''
        if (item.match(/\{$/) || item.match(/\[$/)) {
          // 匹配到以{和[结尾的时候indent加1
          indent += 1
        } else if (
          item.match(/\}$/) ||
          item.match(/\]$/) ||
          item.match(/\},$/) ||
          item.match(/\],$/)
        ) {
          // 匹配到以}和]结尾的时候indent减1
          if (pad !== 0) {
            pad -= 1
          }
        } else {
          indent = 0
        }
        for (i = 0; i < pad; i++) {
          padding += PADDING
        }
        formatted += padding + item + '<br />'
        pad += indent
      })
      // 返回的数据需要去除两边的空格
      return formatted.trim()
    },
    formatUrl(url) {
      return url.map(item => {
        return String(item || '').indexOf('http') > -1 ? item : `${process.env.VUE_APP_BASE_IMG}${item}`
      })
    },
    imageUrl(url) {
      if (Array.isArray(url)) {
        return this.formatUrl(url)
      } else {
        const arr = String(url).split(',')
        return this.formatUrl(arr)
      }
    },
    handleClose(done) {
      this.$emit('change', false)
    }
  }
}
</script>

<style lang="scss" scoped>

</style>
<style lang="scss">
.el-drawer__header{
  margin-bottom: 0;
  padding: 16px 24px;

  color: rgba(48, 49, 51, 1);
  box-shadow: inset 0px -1px 0px 0px #F0F0F0;

  font-size: 16px;
}
.el-drawer__body{
  overflow-y: auto;

  padding: 20px;
}
.detail-block{
  margin-bottom: 16px;
}
.detail-block--header{
  position: relative;

  height: 42px;
  padding-left: 15px;

  color: #333;

  font-size: 16px;
  line-height: 42px;
  &::after{
    position: absolute;
    top: 14px;
    left: 0;

    width: 3px;
    height: 14px;

    content: '';

    background-color: rgba(64, 158, 255, 1);
  }
}
.detail-block--item{
  display: flex;

  margin: 8px 0;
  padding: 5px 0;
  .el-col{
    font-size: 14px;
    line-height: 22px;
  }
  &-title{
    position: relative;

    flex-shrink: 0;

    width: 96px;

    color: rgba(96, 98, 102, 1);
    &[required]{
      padding-left: 10px;
      &::after{
        position: absolute;
        top: 5px;
        left: 0;

        content: '*';

        color: #F56C6C;

        font-size: 20px;
      }
    }
  }

  &-content{
    flex: 1;

    width: calc(100% - 96px);

    color: rgba(48, 49, 51, 1);
    pre{
      overflow-y: auto;

      margin-top: 0;
      padding: 10px;

      border-radius: 10px;
      background-color: aliceblue;
    }
  }
}
.common-content{
  display: inline-block;

  width: 100%;

  white-space: wrap;
}
</style>
