<script>
import './commonList.scss'
import { registerComponents, initComponents } from './config' // 动态添加组件的实现导入
import TextTransformInput from '../../textTransformInput/src/text-transform-input'

import { warn, getValueByPath } from './shared'

export default {
  name: 'CommonList',
  components: {
    TextTransformInput // 实现内容输入的自由切换
  },
  props: {
    disable: {
      type: Boolean,
      default: true
    },
    listApi: {
      type: [Function, undefined],
      default: undefined
    },
    customParams: {
      type: [Object, undefined],
      default: undefined
    },
    getListKey: {
      type: String,
      default: ''
    },
    getTotalKey: {
      type: String,
      default: ''
    }
  },
  data() {
    return {
      componentMap: {},
      list: [], // 列表数据
      total: 0, // 列表数据总数
      loading: false, // 是否在加载中
      params: {
        pageNo: 1,
        pageSize: 10,
        current: 1,
        paras: ''
      }
    }
  },
  // watch: {
  //   list: {
  //     deep: true,
  //     handler: function (o) {
  //       this.$emit('change', o)
  //     }
  //   }
  // },
  beforeCreate() {
    const { id } = this.$attrs
    if (!id) warn('组件缺少参数 id')
    if (id) registerComponents(this, id)
  },
  created() {
    const { id } = this.$attrs
    if (!id) warn('组件缺少参数 id')
    if (id) initComponents(this, id)
  },
  beforeMount() { },
  mounted() {
    this.getList()
  },
  methods: {
    renderTableColumn(h, item) {
      const _that = this
      if (typeof item === 'string') {
        item = {
          name: 'selection',
          label: '',
          uniquekey: 'selection',
          width: '55',
          align: 'center'
        }
      }
      const { componentMap, disable, transformUrlAddress, to, flexColumnWidth } = this
      const {
        showOverflowTooltip = true,
        name,
        width,
        minWidth,
        uniquekey,
        align,
        render,
        fixed,
        label,
        header,
        urlAddress,
        link,
        fit
      } = item

      const v = ['index', 'selection'].find((item) => uniquekey === item)

      if (v) return <el-table-column fixed='left' label={name} align='center' type={v} width='55' />
      const widthMath = flexColumnWidth(name || label, minWidth)
      return (
        <el-table-column
          label={name || label}
          // width={widthMath}
          show-overflow-tooltip={showOverflowTooltip}
          min-width={widthMath}
          align={align}
          fit={fit}
          fixed={fixed}
          scopedSlots={{
            default(props) {
              // Desc: @description: 表单初始化
              // Desc: @param {$index} 索引
              // Desc: @param {column} 列数据
              // Desc: @param {row} 行数据
              // Desc: 关于 _Name
              const privateKey = Object.prototype.hasOwnProperty.call(props.row, uniquekey + '_Name') ? uniquekey + '_Name' : uniquekey
              // Desc: 一级自定义配置 处理具有特殊样式 czj 烟熏三文鱼
              if (componentMap[privateKey]) {
                return h(componentMap[privateKey], {
                  props: {
                    row: props.row,
                    index: props.$index,
                    col: props.column
                  }
                })
              }
              // Desc: 二级自定义配置 如果字段中含有 render 则进行 render 方法渲染，常用于前端自定义配置
              if (render) return <span class='text-1'>{render(props.row, props.$index)}</span>
              // Desc: 三级配置 urlAddress 具有跳转功能
              if (urlAddress) {
                return (
                  <span class='text-1 theme-color cp'>
                    <router-link to={transformUrlAddress({ col: item, row: props.row })}>{props.row[privateKey]}</router-link>
                  </span>
                )
              }
              // Desc: 四级配置 link 具有跳转功能
              if (link) {
                return (
                  <el-link
                    underline={false}
                    type='text'
                    onClick={() => to(link(props.row))}>
                    {render ? render(props.row, props.$index) : props.row[privateKey]}
                  </el-link>
                )
              }

              // Desc: 默认样式
              return (
                <span class='text-1 cp'>
                  <text-transform-input disable={disable} setData={(value) => {
                    _that.$set(props.row, privateKey, value)
                  }} newValue={props.row[privateKey]} />
                </span>)
            }
          }}>
          {header ? <template slot='header'>
            <div style={{ whiteSpace: 'nowrap' }}>{header()}</div>
          </template> : ''}
        </el-table-column>
      )
    },
    flexColumnWidth(str, width) {
      let flexWidth = 0
      for (const char of str) {
        if (char >= 'A' && char <= 'Z') {
          // 如果是英文字符，为字符分配8个单位宽度
          flexWidth += 12
        } else if (char >= 'a' && char <= 'z') {
          // 如果是中文字符，为字符分配20个单位宽度
          flexWidth += 7
        } else if (char >= '\u4e00' && char <= '\u9fa5') {
          // 如果是中文字符，为字符分配20个单位宽度
          flexWidth += 20
        } else {
          // 其他种类字符，为字符分配5个单位宽度
          flexWidth += 15
        }
      }
      flexWidth = flexWidth + 20
      if (width && flexWidth < parseInt(width)) {
        flexWidth = parseInt(width)
      }
      return flexWidth + 'px'
    },
    to(path) {
      this.$router.push({ path })
    },
    // Desc: 代码 4 次重构简化 20201125 烟熏三文鱼
    // Desc: 代码 5 次简化 20200120 烟熏三文鱼 -- 添加外部可控接口数据
    getList() {
      const { paras, data, id } = this.$attrs
      const { listApi, customParams, getListKey, getTotalKey } = this

      const COMMON_GET_PATH_VALUE_LIST = 'data.data'
      const COMMON_GET_PATH_VALUE_COUNT = 'count'

      if (customParams) {
        Object.assign(this.params, customParams)
      } else {
        this.params.statId = id
        this.params.paras = paras || ''
        this.params.orderField = ''
        this.params.orderType = ''
      }

      if (!listApi) {
        this.list = data
        return new Promise((resolve) => resolve())
      } else {
        this.loading = true
        return listApi(this.params).then((res) => {
          if (res.data) {
            this.list = getValueByPath(res, getListKey || COMMON_GET_PATH_VALUE_LIST) || []
            this.total = getValueByPath(res, getTotalKey || COMMON_GET_PATH_VALUE_COUNT) || 0
            this.$emit('result', res)
          } else {
            console.warn('[yxswy] 获取的数据结构异常 需要看一下数据 commlist')
          }
        })
          .finally(() => {
            this.$nextTick(() => {
              this.loading = false
            })
          })
      }
    },
    handleSizeChange(pageSize) {
      this.params.pageSize = pageSize
      this.getList()
    },
    handleCurrentChange(pageNo) {
      this.params.pageNo = pageNo
      this.params.current = pageNo
      this.getList()
    },
    transformUrlAddress({ col, row }) {
      return col.urlAddress.replace(/{{([\w.]+)}}/g, function ($1, $2) {
        return $2.split('.').reduce((d, key) => d[key], { col, row })
      })
    },
    handleSelectionChange(rows) {
      this.$emit('update:multiple-selection', rows) // 修改多选数据
      this.$emit('multipleSelectionFunction', rows) // 触发多选方法
    },
    getData() {
      return this.list
    }
  },
  render(h) {
    // warn('niu')
    const { col = [], footer = true } = this.$attrs
    const attrs = {
      border: false
    }
    return (
      <div class='common-table-index'>
        {this.$slots.default}
        {this.$slots.top}
        {this.$slots.header}
        <el-table
          data={this.list}
          {...{ attrs }}
          on-selection-change={this.handleSelectionChange}
          v-loading={this.loading}
          header-cell-style={{
            background: '#fafafa',
            color: '#000'
          }}>
          {col.map((item) => this.renderTableColumn(h, item))}
        </el-table>
        {this.$slots.footer}
        {footer ? <div class='table-footer'>
          <el-pagination
            on-size-change={this.handleSizeChange}
            on-current-change={this.handleCurrentChange}
            current-page={this.params.pageNo}
            page-sizes={[10, 20, 50, 100]}
            page-size={this.params.pageSize}
            layout='total, prev, pager, next, sizes, jumper'
            total={this.total} />
        </div> : ''}
      </div>
    )
  }
}
</script>

